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