]> git.ipfire.org Git - thirdparty/cups.git/blob - ppdc/ppdmerge.cxx
Import changes from CUPS 1.5svn-r9085.
[thirdparty/cups.git] / ppdc / ppdmerge.cxx
1 //
2 // "$Id$"
3 //
4 // PPD file merge utility for the CUPS PPD Compiler.
5 //
6 // Copyright 2007-2010 by Apple Inc.
7 // Copyright 2002-2007 by Easy Software Products.
8 //
9 // These coded instructions, statements, and computer programs are the
10 // property of Apple Inc. and are protected by Federal copyright
11 // law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 // which should have been included with this file. If this file is
13 // file is missing or damaged, see the license at "http://www.cups.org/".
14 //
15 // Contents:
16 //
17 // main() - Main entry for the PPD merge utility.
18 // ppd_locale() - Return the locale associated with a PPD file.
19 // usage() - Show usage and exit.
20 //
21
22 //
23 // Include necessary headers...
24 //
25
26 #include <cups/cups-private.h>
27 #include <cups/ppd-private.h>
28 #include <cups/array.h>
29
30
31 //
32 // Local functions...
33 //
34
35 static const char *ppd_locale(ppd_file_t *ppd);
36 static void usage(void);
37
38
39 //
40 // 'main()' - Main entry for the PPD merge utility.
41 //
42
43 int // O - Exit status
44 main(int argc, // I - Number of command-line arguments
45 char *argv[]) // I - Command-line arguments
46 {
47 int i; // Looping var
48 char *opt; // Current option
49 ppd_file_t *ppd; // PPD file
50 cups_array_t *ppds; // Array of PPD files
51 const char *inname, // First input filename
52 *outname; // Output filename (if any)
53 cups_file_t *infile, // Input file
54 *outfile; // Output file
55 cups_array_t *languages; // Languages in file
56 const char *locale; // Current locale
57 char line[1024]; // Line from file
58
59
60 _cupsSetLocale(argv);
61
62 // Scan the command-line...
63 inname = NULL;
64 outname = NULL;
65 outfile = NULL;
66 languages = NULL;
67 ppds = cupsArrayNew(NULL, NULL);
68
69 for (i = 1; i < argc; i ++)
70 if (argv[i][0] == '-')
71 {
72 for (opt = argv[i] + 1; *opt; opt ++)
73 switch (*opt)
74 {
75 case 'o' : // Output file
76 if (outname)
77 usage();
78
79 i ++;
80 if (i >= argc)
81 usage();
82
83 outname = argv[i];
84 break;
85
86 default : // Unknown
87 usage();
88 break;
89 }
90 }
91 else
92 {
93 // Open and load the PPD file...
94 if ((infile = cupsFileOpen(argv[i], "r")) == NULL)
95 {
96 _cupsLangPrintf(stderr, _("%s: Unable to open %s: %s\n"), "ppdmerge",
97 argv[i], strerror(errno));
98 return (1);
99 }
100
101 // Open the PPD file...
102 if ((ppd = ppdOpen2(infile)) == NULL)
103 {
104 ppd_status_t status; // PPD open status
105 int linenum; // Line number
106
107
108 status = ppdLastError(&linenum);
109
110 _cupsLangPrintf(stderr, _("%s: Unable to open PPD file: %s on line %d.\n"),
111 "ppdmerge", ppdErrorString(status), linenum);
112
113 _cupsLangPrintf(stderr, "%d: ", linenum);
114 cupsFileRewind(infile);
115
116 line[0] = '\0';
117
118 while (cupsFileGets(infile, line, sizeof(line)))
119 {
120 linenum --;
121 if (!linenum)
122 break;
123 }
124
125 _cupsLangPrintf(stderr, "%s\n", line);
126
127 cupsFileClose(infile);
128 return (1);
129 }
130
131 // Figure out the locale...
132 if ((locale = ppd_locale(ppd)) == NULL)
133 {
134 _cupsLangPrintf(stderr,
135 _("ppdmerge: Bad LanguageVersion \"%s\" in %s\n"),
136 ppd->lang_version, argv[i]);
137 cupsFileClose(infile);
138 ppdClose(ppd);
139 return (1);
140 }
141
142 if (!strcmp(locale, "en") && !inname && !outfile)
143 {
144 // Set the English PPD's filename...
145 inname = argv[i];
146 languages = _ppdGetLanguages(ppd);
147
148 if (outname && !strcmp(inname, outname))
149 {
150 // Rename input filename so that we don't overwrite it...
151 char bckname[1024]; // Backup filename
152
153
154 snprintf(bckname, sizeof(bckname), "%s.bck", inname);
155
156 if (rename(inname, bckname))
157 {
158 _cupsLangPrintf(stderr,
159 _("ppdmerge: Unable to backup %s to %s- %s\n"),
160 inname, bckname, strerror(errno));
161 return (1);
162 }
163
164 inname = bckname;
165 }
166 }
167 else if (strcmp(locale, "en"))
168 {
169 // Save this PPD for later processing...
170 cupsArrayAdd(ppds, ppd);
171 }
172 else
173 {
174 // Don't need this PPD...
175 _cupsLangPrintf(stderr, _("ppdmerge: Ignoring PPD file %s...\n"),
176 argv[i]);
177 ppdClose(ppd);
178 }
179
180 // Close and move on...
181 cupsFileClose(infile);
182 }
183
184 // If no PPDs have been loaded, display the program usage message.
185 if (!inname)
186 usage();
187
188 // Loop through the PPD files we loaded to generate a new language list...
189 if (!languages)
190 languages = cupsArrayNew((cups_array_func_t)strcmp, NULL);
191
192 for (ppd = (ppd_file_t *)cupsArrayFirst(ppds);
193 ppd;
194 ppd = (ppd_file_t *)cupsArrayNext(ppds))
195 {
196 locale = ppd_locale(ppd);
197
198 if (cupsArrayFind(languages, (void *)locale))
199 {
200 // Already have this language, remove the PPD from the list.
201 ppdClose(ppd);
202 cupsArrayRemove(ppds, ppd);
203 }
204 else
205 cupsArrayAdd(languages, (void *)locale);
206 }
207
208 // Copy the English PPD starting with a cupsLanguages line...
209 infile = cupsFileOpen(inname, "r");
210
211 if (outname)
212 {
213 const char *ext = strrchr(outname, '.');
214 if (ext && !strcmp(ext, ".gz"))
215 outfile = cupsFileOpen(outname, "w9");
216 else
217 outfile = cupsFileOpen(outname, "w");
218 }
219 else
220 outfile = cupsFileStdout();
221
222 cupsFileGets(infile, line, sizeof(line));
223 cupsFilePrintf(outfile, "%s\n", line);
224 if ((locale = (char *)cupsArrayFirst(languages)) != NULL)
225 {
226 cupsFilePrintf(outfile, "*cupsLanguages: \"%s", locale);
227 while ((locale = (char *)cupsArrayNext(languages)) != NULL)
228 cupsFilePrintf(outfile, " %s", locale);
229 cupsFilePuts(outfile, "\"\n");
230 }
231
232 while (cupsFileGets(infile, line, sizeof(line)))
233 {
234 if (strncmp(line, "*cupsLanguages:", 15))
235 cupsFilePrintf(outfile, "%s\n", line);
236 }
237
238 // Loop through the other PPD files we loaded to provide the translations...
239 for (ppd = (ppd_file_t *)cupsArrayFirst(ppds);
240 ppd;
241 ppd = (ppd_file_t *)cupsArrayNext(ppds))
242 {
243 // Output all of the UI text for this language...
244 int j, k, l; // Looping vars
245 ppd_group_t *g; // Option group
246 ppd_option_t *o; // Option
247 ppd_choice_t *c; // Choice
248 ppd_coption_t *co; // Custom option
249 ppd_cparam_t *cp; // Custom parameter
250 ppd_attr_t *attr; // PPD attribute
251
252 locale = ppd_locale(ppd);
253
254 cupsFilePrintf(outfile, "*%% %s localization\n", ppd->lang_version);
255 cupsFilePrintf(outfile, "*%s.Translation ModelName/%s: \"\"\n", locale,
256 ppd->modelname);
257
258 for (j = ppd->num_groups, g = ppd->groups; j > 0; j --, g ++)
259 {
260 cupsFilePrintf(outfile, "*%s.Translation %s/%s: \"\"\n", locale,
261 g->name, g->text);
262
263 for (k = g->num_options, o = g->options; k > 0; k --, o ++)
264 {
265 cupsFilePrintf(outfile, "*%s.Translation %s/%s: \"\"\n", locale,
266 o->keyword, o->text);
267
268 for (l = o->num_choices, c = o->choices; l > 0; l --, c ++)
269 cupsFilePrintf(outfile, "*%s.%s %s/%s: \"\"\n", locale,
270 o->keyword, c->choice, c->text);
271
272 if ((co = ppdFindCustomOption(ppd, o->keyword)) != NULL)
273 {
274 snprintf(line, sizeof(line), "Custom%s", o->keyword);
275 attr = ppdFindAttr(ppd, line, "True");
276 cupsFilePrintf(outfile, "*%s.Custom%s True/%s: \"\"\n", locale,
277 o->keyword, attr->text);
278 for (cp = ppdFirstCustomParam(co); cp; cp = ppdNextCustomParam(co))
279 cupsFilePrintf(outfile, "*%s.ParamCustom%s %s/%s: \"\"\n", locale,
280 o->keyword, cp->name, cp->text);
281 }
282 }
283 }
284
285 ppdClose(ppd);
286 }
287
288 cupsArrayDelete(ppds);
289
290 cupsFileClose(outfile);
291
292 // Return with no errors.
293 return (0);
294 }
295
296
297 //
298 // 'ppd_locale()' - Return the locale associated with a PPD file.
299 //
300
301 static const char * // O - Locale string
302 ppd_locale(ppd_file_t *ppd) // I - PPD file
303 {
304 int i, // Looping var
305 vlen; // Length of LanguageVersion string
306 static char locale[255]; // Locale string
307 static struct // LanguageVersion translation table
308 {
309 const char *version, // LanguageVersion string */
310 *language; // Language code */
311 } languages[] =
312 {
313 { "chinese", "zh" },
314 { "czech", "cs" },
315 { "danish", "da" },
316 { "dutch", "nl" },
317 { "english", "en" },
318 { "finnish", "fi" },
319 { "french", "fr" },
320 { "german", "de" },
321 { "greek", "el" },
322 { "hungarian", "hu" },
323 { "italian", "it" },
324 { "japanese", "ja" },
325 { "korean", "ko" },
326 { "norwegian", "no" },
327 { "polish", "pl" },
328 { "portuguese", "pt" },
329 { "russian", "ru" },
330 { "simplified chinese", "zh_CN" },
331 { "slovak", "sk" },
332 { "spanish", "es" },
333 { "swedish", "sv" },
334 { "traditional chinese", "zh_TW" },
335 { "turkish", "tr" }
336 };
337
338
339 for (i = 0; i < (int)(sizeof(languages) / sizeof(languages[0])); i ++)
340 {
341 vlen = strlen(languages[i].version);
342
343 if (!strncasecmp(ppd->lang_version, languages[i].version, vlen))
344 {
345 if (ppd->lang_version[vlen] == '-' ||
346 ppd->lang_version[vlen] == '_')
347 snprintf(locale, sizeof(locale), "%s_%s", languages[i].language,
348 ppd->lang_version + vlen + 1);
349 else
350 strlcpy(locale, languages[i].language, sizeof(locale));
351
352 return (locale);
353 }
354 }
355
356 return (NULL);
357 }
358
359 //
360 // 'usage()' - Show usage and exit.
361 //
362
363 static void
364 usage(void)
365 {
366 _cupsLangPuts(stdout,
367 _("Usage: ppdmerge [options] filename.ppd "
368 "[ ... filenameN.ppd ]\n"
369 "Options:\n"
370 " -o filename.ppd[.gz]\n"));
371
372 exit(1);
373 }
374
375
376 //
377 // End of "$Id$".
378 //