]>
git.ipfire.org Git - thirdparty/cups.git/blob - cgi-bin/makedocset.c
2 * Xcode documentation set generator.
4 * Copyright 2007-2012 by Apple Inc.
5 * Copyright 1997-2007 by Easy Software Products.
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/".
15 * makedocset directory *.tokens
19 * Include necessary headers...
22 #include "cgi-private.h"
30 typedef struct _cups_html_s
/**** Help file ****/
32 char *path
; /* Path to help file */
33 char *title
; /* Title of help file */
36 typedef struct _cups_section_s
/**** Help section ****/
38 char *name
; /* Section name */
39 cups_array_t
*files
; /* Files in this section */
47 static int compare_html(_cups_html_t
*a
, _cups_html_t
*b
);
48 static int compare_sections(_cups_section_t
*a
, _cups_section_t
*b
);
49 static int compare_sections_files(_cups_section_t
*a
, _cups_section_t
*b
);
50 static void write_index(const char *path
, help_index_t
*hi
);
51 static void write_info(const char *path
, const char *revision
);
52 static void write_nodes(const char *path
, help_index_t
*hi
);
56 * 'main()' - Test the help index code.
59 int /* O - Exit status */
60 main(int argc
, /* I - Number of command-line args */
61 char *argv
[]) /* I - Command-line arguments */
63 int i
; /* Looping var */
64 char path
[1024], /* Path to documentation */
65 line
[1024]; /* Line from file */
66 help_index_t
*hi
; /* Help index */
67 cups_file_t
*tokens
, /* Tokens.xml file */
68 *fp
; /* Current file */
73 puts("Usage: makedocset directory revision *.tokens");
78 * Index the help documents...
81 snprintf(path
, sizeof(path
), "%s/Contents/Resources/Documentation", argv
[1]);
82 if ((hi
= helpLoadIndex(NULL
, path
)) == NULL
)
84 fputs("makedocset: Unable to index help files!\n", stderr
);
88 snprintf(path
, sizeof(path
), "%s/Contents/Resources/Documentation/index.html",
90 write_index(path
, hi
);
92 snprintf(path
, sizeof(path
), "%s/Contents/Resources/Nodes.xml", argv
[1]);
93 write_nodes(path
, hi
);
96 * Write the Info.plist file...
99 snprintf(path
, sizeof(path
), "%s/Contents/Info.plist", argv
[1]);
100 write_info(path
, argv
[2]);
103 * Merge the Tokens.xml files...
106 snprintf(path
, sizeof(path
), "%s/Contents/Resources/Tokens.xml", argv
[1]);
107 if ((tokens
= cupsFileOpen(path
, "w")) == NULL
)
109 fprintf(stderr
, "makedocset: Unable to create \"%s\": %s\n", path
,
114 cupsFilePuts(tokens
, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
115 cupsFilePuts(tokens
, "<Tokens version=\"1.0\">\n");
117 for (i
= 3; i
< argc
; i
++)
119 if ((fp
= cupsFileOpen(argv
[i
], "r")) == NULL
)
121 fprintf(stderr
, "makedocset: Unable to open \"%s\": %s\n", argv
[i
],
126 if (!cupsFileGets(fp
, line
, sizeof(line
)) || strncmp(line
, "<?xml ", 6) ||
127 !cupsFileGets(fp
, line
, sizeof(line
)) || strncmp(line
, "<Tokens ", 8))
129 fprintf(stderr
, "makedocset: Bad Tokens.xml file \"%s\"!\n", argv
[i
]);
133 while (cupsFileGets(fp
, line
, sizeof(line
)))
135 if (strcmp(line
, "</Tokens>"))
136 cupsFilePrintf(tokens
, "%s\n", line
);
142 cupsFilePuts(tokens
, "</Tokens>\n");
144 cupsFileClose(tokens
);
147 * Return with no errors...
155 * 'compare_html()' - Compare the titles of two HTML files.
158 static int /* O - Result of comparison */
159 compare_html(_cups_html_t
*a
, /* I - First file */
160 _cups_html_t
*b
) /* I - Second file */
162 return (_cups_strcasecmp(a
->title
, b
->title
));
167 * 'compare_sections()' - Compare the names of two help sections.
170 static int /* O - Result of comparison */
171 compare_sections(_cups_section_t
*a
, /* I - First section */
172 _cups_section_t
*b
) /* I - Second section */
174 return (_cups_strcasecmp(a
->name
, b
->name
));
179 * 'compare_sections_files()' - Compare the number of files and section names.
182 static int /* O - Result of comparison */
183 compare_sections_files(
184 _cups_section_t
*a
, /* I - First section */
185 _cups_section_t
*b
) /* I - Second section */
187 int ret
= cupsArrayCount(b
->files
) - cupsArrayCount(a
->files
);
192 return (_cups_strcasecmp(a
->name
, b
->name
));
197 * 'write_index()' - Write an index file for the CUPS help.
201 write_index(const char *path
, /* I - File to write */
202 help_index_t
*hi
) /* I - Index of files */
204 cups_file_t
*fp
; /* Output file */
205 help_node_t
*node
; /* Current help node */
206 _cups_section_t
*section
, /* Current section */
207 key
; /* Section search key */
208 _cups_html_t
*html
; /* Current HTML file */
209 cups_array_t
*sections
, /* Sections in index */
210 *sections_files
,/* Sections sorted by size */
211 *columns
[3]; /* Columns in final HTML file */
212 int column
, /* Current column */
213 lines
[3], /* Number of lines in each column */
214 min_column
, /* Smallest column */
215 min_lines
; /* Smallest number of lines */
219 * Build an array of sections and their files.
222 sections
= cupsArrayNew((cups_array_func_t
)compare_sections
, NULL
);
224 for (node
= (help_node_t
*)cupsArrayFirst(hi
->nodes
);
226 node
= (help_node_t
*)cupsArrayNext(hi
->nodes
))
231 key
.name
= node
->section
? node
->section
: "Miscellaneous";
232 if ((section
= (_cups_section_t
*)cupsArrayFind(sections
, &key
)) == NULL
)
234 section
= (_cups_section_t
*)calloc(1, sizeof(_cups_section_t
));
235 section
->name
= key
.name
;
236 section
->files
= cupsArrayNew((cups_array_func_t
)compare_html
, NULL
);
238 cupsArrayAdd(sections
, section
);
241 html
= (_cups_html_t
*)calloc(1, sizeof(_cups_html_t
));
242 html
->path
= node
->filename
;
243 html
->title
= node
->text
;
245 cupsArrayAdd(section
->files
, html
);
249 * Build a sorted list of sections based on the number of files in each section
250 * and the section name...
253 sections_files
= cupsArrayNew((cups_array_func_t
)compare_sections_files
,
255 for (section
= (_cups_section_t
*)cupsArrayFirst(sections
);
257 section
= (_cups_section_t
*)cupsArrayNext(sections
))
258 cupsArrayAdd(sections_files
, section
);
261 * Then build three columns to hold everything, trying to balance the number of
262 * lines in each column...
265 for (column
= 0; column
< 3; column
++)
267 columns
[column
] = cupsArrayNew((cups_array_func_t
)compare_sections
, NULL
);
271 for (section
= (_cups_section_t
*)cupsArrayFirst(sections_files
);
273 section
= (_cups_section_t
*)cupsArrayNext(sections_files
))
275 for (min_column
= 0, min_lines
= lines
[0], column
= 1;
279 if (lines
[column
] < min_lines
)
282 min_lines
= lines
[column
];
286 cupsArrayAdd(columns
[min_column
], section
);
287 lines
[min_column
] += cupsArrayCount(section
->files
) + 2;
291 * Write the HTML file...
294 if ((fp
= cupsFileOpen(path
, "w")) == NULL
)
296 fprintf(stderr
, "makedocset: Unable to create %s: %s\n", path
,
301 cupsFilePuts(fp
, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 "
302 "Transitional//EN\" "
303 "\"http://www.w3.org/TR/html4/loose.dtd\">\n"
306 "<title>CUPS Documentation</title>\n"
307 "<link rel='stylesheet' type='text/css' "
308 "href='cups-printable.css'>\n"
311 "<h1 class='title'>CUPS Documentation</h1>\n"
312 "<table width='100%' summary=''>\n"
315 for (column
= 0; column
< 3; column
++)
318 cupsFilePuts(fp
, "<td> </td>\n");
320 cupsFilePuts(fp
, "<td valign='top' width='33%'>");
321 for (section
= (_cups_section_t
*)cupsArrayFirst(columns
[column
]);
323 section
= (_cups_section_t
*)cupsArrayNext(columns
[column
]))
325 cupsFilePrintf(fp
, "<h2 class='title'>%s</h2>\n", section
->name
);
326 for (html
= (_cups_html_t
*)cupsArrayFirst(section
->files
);
328 html
= (_cups_html_t
*)cupsArrayNext(section
->files
))
329 cupsFilePrintf(fp
, "<p class='compact'><a href='%s'>%s</a></p>\n",
330 html
->path
, html
->title
);
332 cupsFilePuts(fp
, "</td>\n");
334 cupsFilePuts(fp
, "</tr>\n"
343 * 'write_info()' - Write the Info.plist file.
347 write_info(const char *path
, /* I - File to write */
348 const char *revision
) /* I - Subversion revision number */
350 cups_file_t
*fp
; /* File */
353 if ((fp
= cupsFileOpen(path
, "w")) == NULL
)
355 fprintf(stderr
, "makedocset: Unable to create %s: %s\n", path
,
360 cupsFilePrintf(fp
, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
361 "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" "
362 "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
363 "<plist version=\"1.0\">\n"
365 "\t<key>CFBundleIdentifier</key>\n"
366 "\t<string>org.cups.docset</string>\n"
367 "\t<key>CFBundleName</key>\n"
368 "\t<string>CUPS Documentation</string>\n"
369 "\t<key>CFBundleVersion</key>\n"
370 "\t<string>%d.%d.%s</string>\n"
371 "\t<key>CFBundleShortVersionString</key>\n"
372 "\t<string>%d.%d.%d</string>\n"
373 "\t<key>DocSetFeedName</key>\n"
374 "\t<string>cups.org</string>\n"
375 "\t<key>DocSetFeedURL</key>\n"
376 "\t<string>http://www.cups.org/org.cups.docset.atom"
378 "\t<key>DocSetPublisherIdentifier</key>\n"
379 "\t<string>org.cups</string>\n"
380 "\t<key>DocSetPublisherName</key>\n"
381 "\t<string>CUPS</string>\n"
384 CUPS_VERSION_MAJOR
, CUPS_VERSION_MINOR
, revision
,
385 CUPS_VERSION_MAJOR
, CUPS_VERSION_MINOR
, CUPS_VERSION_PATCH
);
392 * 'write_nodes()' - Write the Nodes.xml file.
396 write_nodes(const char *path
, /* I - File to write */
397 help_index_t
*hi
) /* I - Index of files */
399 cups_file_t
*fp
; /* Output file */
400 int id
; /* Current node ID */
401 help_node_t
*node
; /* Current help node */
402 int subnodes
; /* Currently in Subnodes for file? */
403 int needclose
; /* Need to close the current node? */
406 if ((fp
= cupsFileOpen(path
, "w")) == NULL
)
408 fprintf(stderr
, "makedocset: Unable to create %s: %s\n", path
,
413 cupsFilePuts(fp
, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
414 "<DocSetNodes version=\"1.0\">\n"
417 "<Name>CUPS Documentation</Name>\n"
418 "<Path>Documentation/index.html</Path>\n"
421 for (node
= (help_node_t
*)cupsArrayFirst(hi
->nodes
), id
= 1, subnodes
= 0,
424 node
= (help_node_t
*)cupsArrayNext(hi
->nodes
), id
++)
430 cupsFilePuts(fp
, "<Subnodes>\n");
434 cupsFilePrintf(fp
, "<Node id=\"%d\">\n"
435 "<Path>Documentation/%s</Path>\n"
436 "<Anchor>%s</Anchor>\n"
438 "</Node>\n", id
, node
->filename
, node
->anchor
,
445 cupsFilePuts(fp
, "</Subnodes>\n");
450 cupsFilePuts(fp
, "</Node>\n");
452 cupsFilePrintf(fp
, "<Node id=\"%d\">\n"
453 "<Path>Documentation/%s</Path>\n"
454 "<Name>%s</Name>\n", id
, node
->filename
, node
->text
);
460 cupsFilePuts(fp
, "</Subnodes>\n");
463 cupsFilePuts(fp
, "</Node>\n");
465 cupsFilePuts(fp
, "</TOC>\n"