/* vim:expandtab:ts=2 sw=2: */ /* Grafx2 - The Ultimate 256-color bitmap paint program Copyright owned by various GrafX2 authors, see COPYRIGHT.txt for details. Grafx2 is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. Grafx2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Grafx2; if not, see */ /** * @file generatedoc.c * HTML doc generator */ #include #include #include #include "global.h" #include "hotkeys.h" #include "helpfile.h" #include "keyboard.h" // for Key_Name() #include "windows.h" // for T_Toolbar_button #if defined(USE_X11) word X11_key_mod = 0; #endif static T_Toolbar_button Buttons[NB_BUTTONS]; /// available skins const char * const skins[] = { "classic", "modern", "DPaint", "scenish", "Aurora", NULL }; /// /// Export the help to HTML files static int Export_help(const char * path); int main(int argc,char * argv[]) { int r; const char * path = "."; if (argc > 1) { if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0) { printf("Usage: %s [directory]\n", argv[0]); return 1; } path = argv[1]; } #define Init_button(btn, tooltip, x_offset, y_offset, width, height, shape, \ left_action, right_action, left_instant, right_instant, \ unselect_action, family) \ Buttons[btn].Tooltip = tooltip; \ Buttons[btn].X_offset = x_offset; \ Buttons[btn].Y_offset = y_offset; \ Buttons[btn].Width = width; \ Buttons[btn].Height = height; \ Buttons[btn].Shape = shape; \ Buttons[btn].Family = family; #include "init_buttons.h" #undef Init_button r = Export_help(path); if (r < 0) return -r; return 0; } /// similar to Shortcut() from help.c, but relying only on default shortcuts static word * Find_default_shortcut(word shortcut_number) { short order_index; // Recherche dans hotkeys order_index=0; while (Ordering[order_index]!=shortcut_number) { order_index++; if (order_index>=NB_SHORTCUTS) { return NULL; } } return &(ConfigKey[order_index].Key); } /// Similar to Keyboard_shortcut_value() from help.c, but relying only on default shortcuts static const char * Keyboard_default_shortcut(word shortcut_number) { static char shortcuts_name[80]; word * pointer = Find_default_shortcut(shortcut_number); if (pointer == NULL) return "(Problem)"; else { if (pointer[0] == 0 && pointer[1] == 0) return "None"; if (pointer[0] != 0 && pointer[1] == 0) return Key_name(pointer[0]); if (pointer[0] == 0 && pointer[1] != 0) return Key_name(pointer[1]); strcpy(shortcuts_name, Key_name(pointer[0])); strcat(shortcuts_name, " or "); strcat(shortcuts_name, Key_name(pointer[1])); return shortcuts_name; } } static void Print_button(FILE * f, int btn) { int x_offset, y_offset; if (btn < 0 || btn >= NB_BUTTONS) return; if (Buttons[btn].Width <= 1) return; x_offset = Buttons[btn].X_offset; y_offset = Buttons[btn].Y_offset; if (btn <= BUTTON_HIDE) // Status y_offset += 67; else if (btn <= BUTTON_ANIM_PLAY) // Animation y_offset += 53; else if (btn <= BUTTON_LAYER_SELECT) // Layers y_offset += 43; else // Main y_offset += 8; fprintf(f, "
 "); } /// static const char * Export_help_table(FILE * f, unsigned int page) { int hlevel = 1; static char title[256]; word index; const T_Help_table * table = Help_section[page].Help_table; word length = Help_section[page].Length; // Line_type : 'N' for normal line // 'S' for a bold line // 'K' for a line with keyboard shortcut // 'T' and '-' for upper and lower titles. for (index = 0; index < length; index++) { if (table[index].Line_type == 'T') { const char * p = table[index].Text; while (*p == ' ') p++; strncpy(title, p, sizeof(title)); title[sizeof(title)-1] = '\0'; while (index + 2 < length && table[index+2].Line_type == 'T') { size_t len = strlen(title); index += 2; if (table[index].Text[0] != ' ') title[len++] = ' '; if (len >= sizeof(title) - 1) break; strncpy(title + len, table[index].Text, sizeof(title)-len-1); } break; } } fprintf(f, "\n"); fprintf(f, "\n"); fprintf(f, "\n"); fprintf(f, "%s\n", title); fprintf(f, "\n"); fprintf(f, "\n"); fprintf(f, "\n"); fprintf(f, "\n"); fprintf(f, "\n"); fprintf(f, "
"); fprintf(f, "\n
"); if (page > 0) fprintf(f, "Previous\n", page - 1); fprintf(f, "GrafX2 Help"); if (page < sizeof(Help_section)/sizeof(Help_section[0]) - 1) fprintf(f, "Next\n", page + 1); fprintf(f, "
"); fprintf(f, "
\n"); fprintf(f, "
"); for (index = 0; index < length; index++) { if (table[index].Line_type == '-') continue; // if (table[index].Line_type != 'N') printf("%c %s\n", table[index].Line_type, table[index].Text); if (table[index].Line_type == 'S') fprintf(f, ""); else if (table[index].Line_type == 'T' && !(index > 1 && table[index-2].Line_type == 'T')) { fprintf(f, "", hlevel); if (hlevel == 1 && page >= 4) Print_button(f, page-4); } if (table[index].Line_type == 'K') { char keytmp[90]; snprintf(keytmp, sizeof(keytmp), "%s", Keyboard_default_shortcut(table[index].Line_parameter)); fprintf(f, table[index].Text, keytmp); } else { const char * prefix = ""; char * link = strstr(table[index].Text, "http://"); if (link == NULL) { link = strstr(table[index].Text, "https://"); if (link == NULL) { link = strstr(table[index].Text, "www."); prefix = "http://"; } } if (link != NULL) { char * link_end = strchr(link, ' '); if (link_end == NULL) { link_end = strchr(link, ')'); if (link_end == NULL) link_end = link + strlen(link); } fprintf(f, "%.*s", (int)(link - table[index].Text), table[index].Text); fprintf(f, "%.*s%s", prefix, (int)(link_end - link), link, (int)(link_end - link), link, link_end); } else { // print the string and escape < and > characters const char * text = table[index].Text; while (text[0] != '\0') { size_t i = strcspn(text, "<>"); if (text[i] == '\0') { // no character to escape fprintf(f, "%s", text); break; } if (i > 0) fprintf(f, "%.*s", (int)i, text); switch(text[i]) { case '<': fprintf(f, "<"); break; case '>': fprintf(f, ">"); break; } // continue with the remaining of the string text += i + 1; } } } if (table[index].Line_type == 'S') fprintf(f, ""); else if (table[index].Line_type == 'T') { if (index < length-2 && table[index+2].Line_type == 'T') fprintf(f, "\n"); else { fprintf(f, "", hlevel); if (hlevel == 1) { hlevel++; if (page >= 4 && page < NB_BUTTONS + 4 && Buttons[page-4].Tooltip != NULL) fprintf(f, "\n%s", Buttons[page-4].Tooltip); } } } if (table[index].Line_type != 'T') fprintf(f, "\n"); // fprintf(f, "
\n"); } fprintf(f, "
"); fprintf(f, "\n"); fprintf(f, "\n"); return title; } /// /// Export the help to HTML files static int Export_help(const char * path) { FILE * f; FILE * findex; char * filename; size_t filename_size; unsigned int i; filename_size = strlen(path) + 64; filename = malloc(filename_size); if (filename == NULL) { fprintf(stderr, "Failed to allocate %lu bytes\n", (unsigned long)filename_size); return -1; } snprintf(filename, filename_size, "%s/index.html", path); //GFX2_Log(GFX2_INFO, "Creating %s\n", filename); findex = fopen(filename, "w"); if (findex == NULL) { fprintf(stderr, "Cannot save index HTML file %s\n", filename); free(filename); return -1; } fprintf(findex, "\n"); fprintf(findex, "\n"); fprintf(findex, "\n"); fprintf(findex, "GrafX2 Help\n"); fprintf(findex, "\n"); fprintf(findex, "\n"); fprintf(findex, "\n"); fprintf(findex, "\n"); fprintf(findex, "\n"); fprintf(findex, "\n"); fprintf(findex, "
\n"); fprintf(findex, "
\n"); fprintf(findex, "Choose your skin :\n"); for (i = 0; skins[i] != NULL; i++) { fprintf(findex, "%s\n", skins[i], skins[i]); } fprintf(findex, "
\n"); fprintf(findex, "
"); fprintf(findex, "
    \n"); for (i = 0; i < sizeof(Help_section)/sizeof(Help_section[0]); i++) { const char * title; snprintf(filename, filename_size, "%s/grafx2_%02d.html", path, i); f = fopen(filename, "w"); if (f == NULL) { fprintf(stderr, "Cannot save HTML file %s\n", filename); fclose(findex); free(filename); return -1; } //GFX2_Log(GFX2_INFO, "Saving %s\n", filename); title = Export_help_table(f, i); // Button = i - 4 fclose(f); fprintf(findex, "
  • "); fprintf(findex, "", i); if (i >= 4) Print_button(findex, i-4); fprintf(findex, "%s", title); if (i >= 4 && Buttons[i-4].Tooltip != NULL) fprintf(findex, " %s", Buttons[i-4].Tooltip); fprintf(findex, "
  • \n"); } fprintf(findex, "
\n"); fprintf(findex, "
\n"); fprintf(findex, "\n"); fclose(findex); snprintf(filename, filename_size, "%s/grafx2.css", path); f = fopen(filename, "w"); if (f != NULL) { fprintf(f, "body {\n"); fprintf(f, "font-family: sans-serif;\n"); fprintf(f, "color: #222;\n"); fprintf(f, "max-width: 40rem;\n"); fprintf(f, "margin: auto;\n"); fprintf(f, "}\n"); fprintf(f, ".center {\n"); fprintf(f, "margin: auto;\n"); fprintf(f, "text-align: center;\n"); fprintf(f, "}\n"); fprintf(f, ".help {\n"); fprintf(f, "font-family: %s;\n", "monospace"); fprintf(f, "white-space: %s;\n", "pre"); fprintf(f, "}\n"); fprintf(f, "div.button {\n"); fprintf(f, "display: inline-block;\n"); fprintf(f, "width: 16px;\n"); fprintf(f, "height: 16px;\n"); fprintf(f, "}\n"); for (i = 0; skins[i] != NULL; i++) { fprintf(f, ".skin_%s .button {\n", skins[i]); fprintf(f, "background-image: url(\"skin_%s.png\");\n", skins[i]); fprintf(f, "}\n"); } fprintf(f, "@media print {\n"); fprintf(f, " .skinselector {\n"); fprintf(f, " display: none;\n"); fprintf(f, " }\n"); fprintf(f, " body {\n"); fprintf(f, " -webkit-print-color-adjust: exact; /*Chrome, Safari */\n"); fprintf(f, " color-adjust: exact; /*Firefox*/\n"); fprintf(f, " }\n"); fprintf(f, "}\n"); fprintf(f, "@viewport {\n"); fprintf(f, " width: device-width;\n"); fprintf(f, " zoom: 1;\n"); fprintf(f, "}\n"); fclose(f); } snprintf(filename, filename_size, "%s/grafx2.js", path); f = fopen(filename, "w"); if (f != NULL) { fprintf(f, "function setCookie(cname, cvalue) {\n" " document.cookie = cname + '=' + cvalue /*+ ';path=/'*/;\n" "}\n"); fprintf(f, "function getCookie(cname) {\n" " var name = cname + '=';\n" " var ca = decodeURIComponent(document.cookie).split(';');\n" " for (var i = 0; i < ca.length; i++) {\n" " var c = ca[i];\n" " while (c.charAt(0) == ' ') c = c.substring(1);\n" " if (c.indexOf(name) == 0) {\n" " return c.substring(name.length);\n" " }\n" " }\n" " return '';\n" "}\n"); fprintf(f, "function change_skin(newskin) {\n" " var elts = document.getElementsByClassName('skin');\n" " for (var i = 0; i < elts.length; i++) {\n" " elts[0].className = elts[0].className.replace(/skin_.*/, newskin);\n" " }\n" "}\n"); fprintf(f, "function choose_skin(skin) {\n" " setCookie('skin', skin);\n" " change_skin('skin_' + skin);\n" "}\n"); fprintf(f, "window.onload = function () {\n" " var skin = getCookie('skin');\n" " if (skin != '') choose_skin(skin);\n" "}\n"); fclose(f); } free(filename); return 0; }