]>
git.ipfire.org Git - thirdparty/cups.git/blob - cgi-bin/makedocset.c
4 * Xcode documentation set generator.
6 * Copyright 2007-2012 by Apple Inc.
7 * Copyright 1997-2007 by Easy Software Products.
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/".
17 * makedocset directory *.tokens
21 * main() - Test the help index code.
22 * compare_html() - Compare the titles of two HTML files.
23 * compare_sections() - Compare the names of two help sections.
24 * compare_sections_files() - Compare the number of files and section names.
25 * write_index() - Write an index file for the CUPS help.
26 * write_info() - Write the Info.plist file.
27 * write_nodes() - Write the Nodes.xml file.
31 * Include necessary headers...
34 #include "cgi-private.h"
42 typedef struct _cups_html_s
/**** Help file ****/
44 char *path
; /* Path to help file */
45 char *title
; /* Title of help file */
48 typedef struct _cups_section_s
/**** Help section ****/
50 char *name
; /* Section name */
51 cups_array_t
*files
; /* Files in this section */
59 static int compare_html(_cups_html_t
*a
, _cups_html_t
*b
);
60 static int compare_sections(_cups_section_t
*a
, _cups_section_t
*b
);
61 static int compare_sections_files(_cups_section_t
*a
, _cups_section_t
*b
);
62 static void write_index(const char *path
, help_index_t
*hi
);
63 static void write_info(const char *path
, const char *revision
);
64 static void write_nodes(const char *path
, help_index_t
*hi
);
68 * 'main()' - Test the help index code.
71 int /* O - Exit status */
72 main(int argc
, /* I - Number of command-line args */
73 char *argv
[]) /* I - Command-line arguments */
75 int i
; /* Looping var */
76 char path
[1024], /* Path to documentation */
77 line
[1024]; /* Line from file */
78 help_index_t
*hi
; /* Help index */
79 cups_file_t
*tokens
, /* Tokens.xml file */
80 *fp
; /* Current file */
85 puts("Usage: makedocset directory revision *.tokens");
90 * Index the help documents...
93 snprintf(path
, sizeof(path
), "%s/Contents/Resources/Documentation", argv
[1]);
94 if ((hi
= helpLoadIndex(NULL
, path
)) == NULL
)
96 fputs("makedocset: Unable to index help files!\n", stderr
);
100 snprintf(path
, sizeof(path
), "%s/Contents/Resources/Documentation/index.html",
102 write_index(path
, hi
);
104 snprintf(path
, sizeof(path
), "%s/Contents/Resources/Nodes.xml", argv
[1]);
105 write_nodes(path
, hi
);
108 * Write the Info.plist file...
111 snprintf(path
, sizeof(path
), "%s/Contents/Info.plist", argv
[1]);
112 write_info(path
, argv
[2]);
115 * Merge the Tokens.xml files...
118 snprintf(path
, sizeof(path
), "%s/Contents/Resources/Tokens.xml", argv
[1]);
119 if ((tokens
= cupsFileOpen(path
, "w")) == NULL
)
121 fprintf(stderr
, "makedocset: Unable to create \"%s\": %s\n", path
,
126 cupsFilePuts(tokens
, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
127 cupsFilePuts(tokens
, "<Tokens version=\"1.0\">\n");
129 for (i
= 3; i
< argc
; i
++)
131 if ((fp
= cupsFileOpen(argv
[i
], "r")) == NULL
)
133 fprintf(stderr
, "makedocset: Unable to open \"%s\": %s\n", argv
[i
],
138 if (!cupsFileGets(fp
, line
, sizeof(line
)) || strncmp(line
, "<?xml ", 6) ||
139 !cupsFileGets(fp
, line
, sizeof(line
)) || strncmp(line
, "<Tokens ", 8))
141 fprintf(stderr
, "makedocset: Bad Tokens.xml file \"%s\"!\n", argv
[i
]);
145 while (cupsFileGets(fp
, line
, sizeof(line
)))
147 if (strcmp(line
, "</Tokens>"))
148 cupsFilePrintf(tokens
, "%s\n", line
);
154 cupsFilePuts(tokens
, "</Tokens>\n");
156 cupsFileClose(tokens
);
159 * Return with no errors...
167 * 'compare_html()' - Compare the titles of two HTML files.
170 static int /* O - Result of comparison */
171 compare_html(_cups_html_t
*a
, /* I - First file */
172 _cups_html_t
*b
) /* I - Second file */
174 return (_cups_strcasecmp(a
->title
, b
->title
));
179 * 'compare_sections()' - Compare the names of two help sections.
182 static int /* O - Result of comparison */
183 compare_sections(_cups_section_t
*a
, /* I - First section */
184 _cups_section_t
*b
) /* I - Second section */
186 return (_cups_strcasecmp(a
->name
, b
->name
));
191 * 'compare_sections_files()' - Compare the number of files and section names.
194 static int /* O - Result of comparison */
195 compare_sections_files(
196 _cups_section_t
*a
, /* I - First section */
197 _cups_section_t
*b
) /* I - Second section */
199 int ret
= cupsArrayCount(b
->files
) - cupsArrayCount(a
->files
);
204 return (_cups_strcasecmp(a
->name
, b
->name
));
209 * 'write_index()' - Write an index file for the CUPS help.
213 write_index(const char *path
, /* I - File to write */
214 help_index_t
*hi
) /* I - Index of files */
216 cups_file_t
*fp
; /* Output file */
217 help_node_t
*node
; /* Current help node */
218 _cups_section_t
*section
, /* Current section */
219 key
; /* Section search key */
220 _cups_html_t
*html
; /* Current HTML file */
221 cups_array_t
*sections
, /* Sections in index */
222 *sections_files
,/* Sections sorted by size */
223 *columns
[3]; /* Columns in final HTML file */
224 int column
, /* Current column */
225 lines
[3], /* Number of lines in each column */
226 min_column
, /* Smallest column */
227 min_lines
; /* Smallest number of lines */
231 * Build an array of sections and their files.
234 sections
= cupsArrayNew((cups_array_func_t
)compare_sections
, NULL
);
236 for (node
= (help_node_t
*)cupsArrayFirst(hi
->nodes
);
238 node
= (help_node_t
*)cupsArrayNext(hi
->nodes
))
243 key
.name
= node
->section
? node
->section
: "Miscellaneous";
244 if ((section
= (_cups_section_t
*)cupsArrayFind(sections
, &key
)) == NULL
)
246 section
= (_cups_section_t
*)calloc(1, sizeof(_cups_section_t
));
247 section
->name
= key
.name
;
248 section
->files
= cupsArrayNew((cups_array_func_t
)compare_html
, NULL
);
250 cupsArrayAdd(sections
, section
);
253 html
= (_cups_html_t
*)calloc(1, sizeof(_cups_html_t
));
254 html
->path
= node
->filename
;
255 html
->title
= node
->text
;
257 cupsArrayAdd(section
->files
, html
);
261 * Build a sorted list of sections based on the number of files in each section
262 * and the section name...
265 sections_files
= cupsArrayNew((cups_array_func_t
)compare_sections_files
,
267 for (section
= (_cups_section_t
*)cupsArrayFirst(sections
);
269 section
= (_cups_section_t
*)cupsArrayNext(sections
))
270 cupsArrayAdd(sections_files
, section
);
273 * Then build three columns to hold everything, trying to balance the number of
274 * lines in each column...
277 for (column
= 0; column
< 3; column
++)
279 columns
[column
] = cupsArrayNew((cups_array_func_t
)compare_sections
, NULL
);
283 for (section
= (_cups_section_t
*)cupsArrayFirst(sections_files
);
285 section
= (_cups_section_t
*)cupsArrayNext(sections_files
))
287 for (min_column
= 0, min_lines
= lines
[0], column
= 1;
291 if (lines
[column
] < min_lines
)
294 min_lines
= lines
[column
];
298 cupsArrayAdd(columns
[min_column
], section
);
299 lines
[min_column
] += cupsArrayCount(section
->files
) + 2;
303 * Write the HTML file...
306 if ((fp
= cupsFileOpen(path
, "w")) == NULL
)
308 fprintf(stderr
, "makedocset: Unable to create %s: %s\n", path
,
313 cupsFilePuts(fp
, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 "
314 "Transitional//EN\" "
315 "\"http://www.w3.org/TR/html4/loose.dtd\">\n"
318 "<title>CUPS Documentation</title>\n"
319 "<link rel='stylesheet' type='text/css' "
320 "href='cups-printable.css'>\n"
323 "<h1 class='title'>CUPS Documentation</h1>\n"
324 "<table width='100%' summary=''>\n"
327 for (column
= 0; column
< 3; column
++)
330 cupsFilePuts(fp
, "<td> </td>\n");
332 cupsFilePuts(fp
, "<td valign='top' width='33%'>");
333 for (section
= (_cups_section_t
*)cupsArrayFirst(columns
[column
]);
335 section
= (_cups_section_t
*)cupsArrayNext(columns
[column
]))
337 cupsFilePrintf(fp
, "<h2 class='title'>%s</h2>\n", section
->name
);
338 for (html
= (_cups_html_t
*)cupsArrayFirst(section
->files
);
340 html
= (_cups_html_t
*)cupsArrayNext(section
->files
))
341 cupsFilePrintf(fp
, "<p class='compact'><a href='%s'>%s</a></p>\n",
342 html
->path
, html
->title
);
344 cupsFilePuts(fp
, "</td>\n");
346 cupsFilePuts(fp
, "</tr>\n"
355 * 'write_info()' - Write the Info.plist file.
359 write_info(const char *path
, /* I - File to write */
360 const char *revision
) /* I - Subversion revision number */
362 cups_file_t
*fp
; /* File */
365 if ((fp
= cupsFileOpen(path
, "w")) == NULL
)
367 fprintf(stderr
, "makedocset: Unable to create %s: %s\n", path
,
372 cupsFilePrintf(fp
, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
373 "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" "
374 "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
375 "<plist version=\"1.0\">\n"
377 "\t<key>CFBundleIdentifier</key>\n"
378 "\t<string>org.cups.docset</string>\n"
379 "\t<key>CFBundleName</key>\n"
380 "\t<string>CUPS Documentation</string>\n"
381 "\t<key>CFBundleVersion</key>\n"
382 "\t<string>%d.%d.%s</string>\n"
383 "\t<key>CFBundleShortVersionString</key>\n"
384 "\t<string>%d.%d.%d</string>\n"
385 "\t<key>DocSetFeedName</key>\n"
386 "\t<string>cups.org</string>\n"
387 "\t<key>DocSetFeedURL</key>\n"
388 "\t<string>http://www.cups.org/org.cups.docset.atom"
390 "\t<key>DocSetPublisherIdentifier</key>\n"
391 "\t<string>org.cups</string>\n"
392 "\t<key>DocSetPublisherName</key>\n"
393 "\t<string>CUPS</string>\n"
396 CUPS_VERSION_MAJOR
, CUPS_VERSION_MINOR
, revision
,
397 CUPS_VERSION_MAJOR
, CUPS_VERSION_MINOR
, CUPS_VERSION_PATCH
);
404 * 'write_nodes()' - Write the Nodes.xml file.
408 write_nodes(const char *path
, /* I - File to write */
409 help_index_t
*hi
) /* I - Index of files */
411 cups_file_t
*fp
; /* Output file */
412 int id
; /* Current node ID */
413 help_node_t
*node
; /* Current help node */
414 int subnodes
; /* Currently in Subnodes for file? */
415 int needclose
; /* Need to close the current node? */
418 if ((fp
= cupsFileOpen(path
, "w")) == NULL
)
420 fprintf(stderr
, "makedocset: Unable to create %s: %s\n", path
,
425 cupsFilePuts(fp
, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
426 "<DocSetNodes version=\"1.0\">\n"
429 "<Name>CUPS Documentation</Name>\n"
430 "<Path>Documentation/index.html</Path>\n"
433 for (node
= (help_node_t
*)cupsArrayFirst(hi
->nodes
), id
= 1, subnodes
= 0,
436 node
= (help_node_t
*)cupsArrayNext(hi
->nodes
), id
++)
442 cupsFilePuts(fp
, "<Subnodes>\n");
446 cupsFilePrintf(fp
, "<Node id=\"%d\">\n"
447 "<Path>Documentation/%s</Path>\n"
448 "<Anchor>%s</Anchor>\n"
450 "</Node>\n", id
, node
->filename
, node
->anchor
,
457 cupsFilePuts(fp
, "</Subnodes>\n");
462 cupsFilePuts(fp
, "</Node>\n");
464 cupsFilePrintf(fp
, "<Node id=\"%d\">\n"
465 "<Path>Documentation/%s</Path>\n"
466 "<Name>%s</Name>\n", id
, node
->filename
, node
->text
);
472 cupsFilePuts(fp
, "</Subnodes>\n");
475 cupsFilePuts(fp
, "</Node>\n");
477 cupsFilePuts(fp
, "</TOC>\n"