]>
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 * Licensed under Apache License v2.0. See the file "LICENSE" for more information.
11 * makedocset directory *.tokens
15 * Include necessary headers...
18 #include "cgi-private.h"
26 typedef struct _cups_html_s
/**** Help file ****/
28 char *path
; /* Path to help file */
29 char *title
; /* Title of help file */
32 typedef struct _cups_section_s
/**** Help section ****/
34 char *name
; /* Section name */
35 cups_array_t
*files
; /* Files in this section */
43 static int compare_html(_cups_html_t
*a
, _cups_html_t
*b
);
44 static int compare_sections(_cups_section_t
*a
, _cups_section_t
*b
);
45 static int compare_sections_files(_cups_section_t
*a
, _cups_section_t
*b
);
46 static void write_index(const char *path
, help_index_t
*hi
);
47 static void write_info(const char *path
, const char *revision
);
48 static void write_nodes(const char *path
, help_index_t
*hi
);
52 * 'main()' - Test the help index code.
55 int /* O - Exit status */
56 main(int argc
, /* I - Number of command-line args */
57 char *argv
[]) /* I - Command-line arguments */
59 int i
; /* Looping var */
60 char path
[1024], /* Path to documentation */
61 line
[1024]; /* Line from file */
62 help_index_t
*hi
; /* Help index */
63 cups_file_t
*tokens
, /* Tokens.xml file */
64 *fp
; /* Current file */
69 puts("Usage: makedocset directory revision *.tokens");
74 * Index the help documents...
77 snprintf(path
, sizeof(path
), "%s/Contents/Resources/Documentation", argv
[1]);
78 if ((hi
= helpLoadIndex(NULL
, path
)) == NULL
)
80 fputs("makedocset: Unable to index help files!\n", stderr
);
84 snprintf(path
, sizeof(path
), "%s/Contents/Resources/Documentation/index.html",
86 write_index(path
, hi
);
88 snprintf(path
, sizeof(path
), "%s/Contents/Resources/Nodes.xml", argv
[1]);
89 write_nodes(path
, hi
);
92 * Write the Info.plist file...
95 snprintf(path
, sizeof(path
), "%s/Contents/Info.plist", argv
[1]);
96 write_info(path
, argv
[2]);
99 * Merge the Tokens.xml files...
102 snprintf(path
, sizeof(path
), "%s/Contents/Resources/Tokens.xml", argv
[1]);
103 if ((tokens
= cupsFileOpen(path
, "w")) == NULL
)
105 fprintf(stderr
, "makedocset: Unable to create \"%s\": %s\n", path
,
110 cupsFilePuts(tokens
, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
111 cupsFilePuts(tokens
, "<Tokens version=\"1.0\">\n");
113 for (i
= 3; i
< argc
; i
++)
115 if ((fp
= cupsFileOpen(argv
[i
], "r")) == NULL
)
117 fprintf(stderr
, "makedocset: Unable to open \"%s\": %s\n", argv
[i
],
122 if (!cupsFileGets(fp
, line
, sizeof(line
)) || strncmp(line
, "<?xml ", 6) ||
123 !cupsFileGets(fp
, line
, sizeof(line
)) || strncmp(line
, "<Tokens ", 8))
125 fprintf(stderr
, "makedocset: Bad Tokens.xml file \"%s\"!\n", argv
[i
]);
129 while (cupsFileGets(fp
, line
, sizeof(line
)))
131 if (strcmp(line
, "</Tokens>"))
132 cupsFilePrintf(tokens
, "%s\n", line
);
138 cupsFilePuts(tokens
, "</Tokens>\n");
140 cupsFileClose(tokens
);
143 * Return with no errors...
151 * 'compare_html()' - Compare the titles of two HTML files.
154 static int /* O - Result of comparison */
155 compare_html(_cups_html_t
*a
, /* I - First file */
156 _cups_html_t
*b
) /* I - Second file */
158 return (_cups_strcasecmp(a
->title
, b
->title
));
163 * 'compare_sections()' - Compare the names of two help sections.
166 static int /* O - Result of comparison */
167 compare_sections(_cups_section_t
*a
, /* I - First section */
168 _cups_section_t
*b
) /* I - Second section */
170 return (_cups_strcasecmp(a
->name
, b
->name
));
175 * 'compare_sections_files()' - Compare the number of files and section names.
178 static int /* O - Result of comparison */
179 compare_sections_files(
180 _cups_section_t
*a
, /* I - First section */
181 _cups_section_t
*b
) /* I - Second section */
183 int ret
= cupsArrayCount(b
->files
) - cupsArrayCount(a
->files
);
188 return (_cups_strcasecmp(a
->name
, b
->name
));
193 * 'write_index()' - Write an index file for the CUPS help.
197 write_index(const char *path
, /* I - File to write */
198 help_index_t
*hi
) /* I - Index of files */
200 cups_file_t
*fp
; /* Output file */
201 help_node_t
*node
; /* Current help node */
202 _cups_section_t
*section
, /* Current section */
203 key
; /* Section search key */
204 _cups_html_t
*html
; /* Current HTML file */
205 cups_array_t
*sections
, /* Sections in index */
206 *sections_files
,/* Sections sorted by size */
207 *columns
[3]; /* Columns in final HTML file */
208 int column
, /* Current column */
209 lines
[3], /* Number of lines in each column */
210 min_column
, /* Smallest column */
211 min_lines
; /* Smallest number of lines */
215 * Build an array of sections and their files.
218 sections
= cupsArrayNew((cups_array_func_t
)compare_sections
, NULL
);
220 for (node
= (help_node_t
*)cupsArrayFirst(hi
->nodes
);
222 node
= (help_node_t
*)cupsArrayNext(hi
->nodes
))
227 key
.name
= node
->section
? node
->section
: "Miscellaneous";
228 if ((section
= (_cups_section_t
*)cupsArrayFind(sections
, &key
)) == NULL
)
230 section
= (_cups_section_t
*)calloc(1, sizeof(_cups_section_t
));
231 section
->name
= key
.name
;
232 section
->files
= cupsArrayNew((cups_array_func_t
)compare_html
, NULL
);
234 cupsArrayAdd(sections
, section
);
237 html
= (_cups_html_t
*)calloc(1, sizeof(_cups_html_t
));
238 html
->path
= node
->filename
;
239 html
->title
= node
->text
;
241 cupsArrayAdd(section
->files
, html
);
245 * Build a sorted list of sections based on the number of files in each section
246 * and the section name...
249 sections_files
= cupsArrayNew((cups_array_func_t
)compare_sections_files
,
251 for (section
= (_cups_section_t
*)cupsArrayFirst(sections
);
253 section
= (_cups_section_t
*)cupsArrayNext(sections
))
254 cupsArrayAdd(sections_files
, section
);
257 * Then build three columns to hold everything, trying to balance the number of
258 * lines in each column...
261 for (column
= 0; column
< 3; column
++)
263 columns
[column
] = cupsArrayNew((cups_array_func_t
)compare_sections
, NULL
);
267 for (section
= (_cups_section_t
*)cupsArrayFirst(sections_files
);
269 section
= (_cups_section_t
*)cupsArrayNext(sections_files
))
271 for (min_column
= 0, min_lines
= lines
[0], column
= 1;
275 if (lines
[column
] < min_lines
)
278 min_lines
= lines
[column
];
282 cupsArrayAdd(columns
[min_column
], section
);
283 lines
[min_column
] += cupsArrayCount(section
->files
) + 2;
287 * Write the HTML file...
290 if ((fp
= cupsFileOpen(path
, "w")) == NULL
)
292 fprintf(stderr
, "makedocset: Unable to create %s: %s\n", path
,
297 cupsFilePuts(fp
, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 "
298 "Transitional//EN\" "
299 "\"http://www.w3.org/TR/html4/loose.dtd\">\n"
302 "<title>CUPS Documentation</title>\n"
303 "<link rel='stylesheet' type='text/css' "
304 "href='cups-printable.css'>\n"
307 "<h1 class='title'>CUPS Documentation</h1>\n"
308 "<table width='100%' summary=''>\n"
311 for (column
= 0; column
< 3; column
++)
314 cupsFilePuts(fp
, "<td> </td>\n");
316 cupsFilePuts(fp
, "<td valign='top' width='33%'>");
317 for (section
= (_cups_section_t
*)cupsArrayFirst(columns
[column
]);
319 section
= (_cups_section_t
*)cupsArrayNext(columns
[column
]))
321 cupsFilePrintf(fp
, "<h2 class='title'>%s</h2>\n", section
->name
);
322 for (html
= (_cups_html_t
*)cupsArrayFirst(section
->files
);
324 html
= (_cups_html_t
*)cupsArrayNext(section
->files
))
325 cupsFilePrintf(fp
, "<p class='compact'><a href='%s'>%s</a></p>\n",
326 html
->path
, html
->title
);
328 cupsFilePuts(fp
, "</td>\n");
330 cupsFilePuts(fp
, "</tr>\n"
339 * 'write_info()' - Write the Info.plist file.
343 write_info(const char *path
, /* I - File to write */
344 const char *revision
) /* I - Subversion revision number */
346 cups_file_t
*fp
; /* File */
349 if ((fp
= cupsFileOpen(path
, "w")) == NULL
)
351 fprintf(stderr
, "makedocset: Unable to create %s: %s\n", path
,
356 cupsFilePrintf(fp
, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
357 "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" "
358 "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
359 "<plist version=\"1.0\">\n"
361 "\t<key>CFBundleIdentifier</key>\n"
362 "\t<string>org.cups.docset</string>\n"
363 "\t<key>CFBundleName</key>\n"
364 "\t<string>CUPS Documentation</string>\n"
365 "\t<key>CFBundleVersion</key>\n"
366 "\t<string>%d.%d.%s</string>\n"
367 "\t<key>CFBundleShortVersionString</key>\n"
368 "\t<string>%d.%d.%d</string>\n"
369 "\t<key>DocSetFeedName</key>\n"
370 "\t<string>cups.org</string>\n"
371 "\t<key>DocSetFeedURL</key>\n"
372 "\t<string>http://www.cups.org/org.cups.docset.atom"
374 "\t<key>DocSetPublisherIdentifier</key>\n"
375 "\t<string>org.cups</string>\n"
376 "\t<key>DocSetPublisherName</key>\n"
377 "\t<string>CUPS</string>\n"
380 CUPS_VERSION_MAJOR
, CUPS_VERSION_MINOR
, revision
,
381 CUPS_VERSION_MAJOR
, CUPS_VERSION_MINOR
, CUPS_VERSION_PATCH
);
388 * 'write_nodes()' - Write the Nodes.xml file.
392 write_nodes(const char *path
, /* I - File to write */
393 help_index_t
*hi
) /* I - Index of files */
395 cups_file_t
*fp
; /* Output file */
396 int id
; /* Current node ID */
397 help_node_t
*node
; /* Current help node */
398 int subnodes
; /* Currently in Subnodes for file? */
399 int needclose
; /* Need to close the current node? */
402 if ((fp
= cupsFileOpen(path
, "w")) == NULL
)
404 fprintf(stderr
, "makedocset: Unable to create %s: %s\n", path
,
409 cupsFilePuts(fp
, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
410 "<DocSetNodes version=\"1.0\">\n"
413 "<Name>CUPS Documentation</Name>\n"
414 "<Path>Documentation/index.html</Path>\n"
417 for (node
= (help_node_t
*)cupsArrayFirst(hi
->nodes
), id
= 1, subnodes
= 0,
420 node
= (help_node_t
*)cupsArrayNext(hi
->nodes
), id
++)
426 cupsFilePuts(fp
, "<Subnodes>\n");
430 cupsFilePrintf(fp
, "<Node id=\"%d\">\n"
431 "<Path>Documentation/%s</Path>\n"
432 "<Anchor>%s</Anchor>\n"
434 "</Node>\n", id
, node
->filename
, node
->anchor
,
441 cupsFilePuts(fp
, "</Subnodes>\n");
446 cupsFilePuts(fp
, "</Node>\n");
448 cupsFilePrintf(fp
, "<Node id=\"%d\">\n"
449 "<Path>Documentation/%s</Path>\n"
450 "<Name>%s</Name>\n", id
, node
->filename
, node
->text
);
456 cupsFilePuts(fp
, "</Subnodes>\n");
459 cupsFilePuts(fp
, "</Node>\n");
461 cupsFilePuts(fp
, "</TOC>\n"