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