Mercurial > hg > batmud > maputils
view mkbcmap.c @ 945:81184d58133c aprilli2011
Sync.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Fri, 14 May 2010 11:18:20 +0000 |
parents | 51fe97e83115 |
children | 5c2bd0ac3118 |
line wrap: on
line source
/* * mkbcmap - Create interactive XHTML+CSS+JS map from input * Programmed by Matti 'ccr' Hämäläinen (Ggr Pupunen) * (C) Copyright 2006-2009 Tecnic Software productions (TNSP) */ #include "maputils.h" #include "th_args.h" #include "th_string.h" typedef struct { char c; char *desc; char *extra; } location_t; enum { OUT_ASCII, OUT_HTML }; #define MAX_LOC (512) int nlocations = 0; location_t locations[MAX_LOC]; char *optDestFilename = NULL, *optMapFilename = NULL, *optDescFilename = NULL, *optUrchinFile = NULL, *optMapTitle = NULL; BOOL optUseTable = FALSE; int optOutputFormat = OUT_HTML; /* Arguments */ optarg_t optList[] = { { 0, '?', "help", "Show this help", OPT_NONE }, { 1, 'v', "verbose", "Be more verbose", OPT_NONE }, { 2, 'o', "output", "Output filename", OPT_ARGREQ }, { 3, 'A', "ascii", "Use plain ASCII output", OPT_NONE }, { 4, 'T', "table", "Use HTML table", OPT_NONE }, { 5, 't', "title", "Map title", OPT_ARGREQ }, { 6, 'u', "urchin-file", "Specify urchin file", OPT_ARGREQ }, }; const int optListN = (sizeof(optList) / sizeof(optarg_t)); void argShowHelp(void) { th_args_help(stderr, optList, optListN, th_prog_name, "[options] <input mapfile> <descfile>"); } BOOL argHandleOpt(const int optN, char *optArg, char *currArg) { switch (optN) { case 0: argShowHelp(); exit(0); break; case 1: th_verbosityLevel++; break; case 2: optDestFilename = optArg; THMSG(2, "Output file set to '%s'.\n", optDestFilename); break; case 3: optOutputFormat = OUT_ASCII; break; case 4: optUseTable = TRUE; THMSG(2, "Using HTML table formatting.\n"); break; case 5: optMapTitle = optArg; THMSG(2, "Map title string set to '%s'.\n", optMapTitle); break; case 6: optUrchinFile = optArg; THMSG(2, "Urchin filename set to '%s'.\n", optUrchinFile); break; default: THERR("Unknown option '%s'.\n", currArg); return FALSE; } return TRUE; } BOOL argHandleFile(char *currArg) { if (!optMapFilename) optMapFilename = currArg; else if (!optDescFilename) optDescFilename = currArg; else { THERR("Too many filenames specified!\n"); return FALSE; } return TRUE; } void addLoc(char c, char *desc, char *extra) { if (nlocations < MAX_LOC) { locations[nlocations].c = c; locations[nlocations].desc = th_strdup(desc); locations[nlocations].extra = th_strdup(extra); nlocations++; } else { THERR("Maximum number of locations (%d) exceeded!\n", MAX_LOC); exit(5); } } int getLoc(char c) { int i; for (i = 0; i < nlocations; i++) if (locations[i].c == c) return i; return -1; } void putEnd(FILE *f, int c, int p) { if (p != -1) { fprintf(f, "</span>"); } if (c >= 0) { BOOL isURL = FALSE; int i = mcGetColor(c, FALSE, TRUE); int l = getLoc(c); if (l >= 0 && locations[l].desc) { isURL = TRUE; i = col_light_red; } fprintf(f, "<span class=\"%c\">", 'a'+i); if (isURL) { fprintf(f, "<a onmouseover=\"stt(%d);\" " "onmouseout=\"htt();\" " "class=\"loc\" id=\"maploc%d\" " "href=\"?%d\">", l, l, l); } fprintfe(f, "%c", c); if (isURL) { fprintf(f, "</a>"); } } } void processMapHTML(FILE *outFile, FILE *inFile) { int c, p; c = p = -1; while ((c = fgetc(inFile)) != EOF) { if (c == '\n') { if (p != -1) fprintf(outFile, "</span>"); c = -1; fprintf(outFile, "\n"); } else { if (c != p) putEnd(outFile, c, p); else fprintfe(outFile, "%c", c); } p = c; } } void printBlockHTML(FILE *outFile, int nStart, int nEnd) { int n; if (nStart >= nlocations || nStart < 0 || nStart > nEnd) return; if (nEnd >= nlocations) nEnd = nlocations-1; fprintf(outFile, "<td>\n"); for (n = nStart; n <= nEnd; n++) { fprintf(outFile, "<a class=\"loc\" id=\"listloc%d\" href=\"?%d\" onmouseover=\"qh(%d)", n, n, n); if (locations[n].extra) { fprintf(outFile, ";stt(%d);", n); } fprintf(outFile, "\" " "onmouseout=\"qn(%d);htt();\">", n); fprintf(outFile, "[<span class=\"%c\">", 'a' + (locations[n].c % 14) + 1); fprintfe(outFile, "%c", locations[n].c); fprintf(outFile, "</span>]"); if (locations[n].desc) { fprintf(outFile, " <span style=\"color: gray;\">%s</span>", locations[n].desc); } fprintf(outFile, "</a>"); fprintf(outFile, "<br />\n"); } fprintf(outFile, "</td>\n"); } int copyFile(FILE *outFile, char *filename) { FILE *inFile; if ((inFile = fopen(filename, "rb")) != NULL) { int c; while ((c = fgetc(inFile)) != EOF) { if (fputc(c, outFile) == EOF) { fclose(inFile); return -2; } } fclose(inFile); return 0; } else { THERR("File '%s' not found!\n", optUrchinFile); return -1; } } void outputHTML(FILE *outFile, FILE *inFile) { int n, k; /* Output XHTML header */ mcXHTMLhead(outFile, optMapTitle); /* Output CSS style information */ fprintf(outFile, " <script type=\"text/javascript\" src=\"tooltip.js\"></script>\n" " <style type=\"text/css\">\n" " body { background: black; color: white; font-family: Arial, Verdana, sans-serif; %s }\n" " a.loc { background: black; color: red; text-decoration: none; }\n" " a.loc:hover { background: white; color: red; }\n" " pre.map { font-size: 9pt; %s }\n", optUseTable ? "" : "height: 100%; padding: 0; margin: 0;", optUseTable ? "" : "overflow: auto;" ); fprintf(outFile, " .tooltip { position: absolute; display: none; min-width: 200px; background-color: white; color: black; padding: 5px; border: 1px solid gray; font-size: 8pt; z-index: 15; }\n" " .holder { display: block; color: #000; }\n" " * html .tooltip { border-right: 400px solid #fff; }\n" " * html .holder { display: inline-block; position: relative; margin-right: -400px; }\n" " div.loctab table tr { vertical-align: top; font-size: 8pt; }\n" ); if (!optUseTable) { fprintf(outFile, " div.map {\n" " font-weight: bold;\n" " position: absolute;\n" " left: 0;\n" " right: 0;\n" " top: 0;\n" " margin: 0;\n" " padding: 0;\n" " height: 75%%;\n" " overflow: auto;\n" " text-align: center;\n" " }\n" " div.loctab {\n" " background: black;\n" " color: white;\n" " position: absolute;\n" " right: 0;\n" " left: 0;\n" " height: 20%%;\n" " bottom: 0;\n" " padding: 4px;\n" " z-index: 10;\n" " border-top: 4px solid gray;\n" " font-size: 8pt;\n" " overflow: auto;\n" " }\n" " div.loctab table { width: 95%%; }\n" ); } mcXHTMLcolors(outFile, "span", NULL, NULL); fprintf(outFile, " </style>\n" "</head>\n" "<body onload=\"httOnLoad();\">\n" ); if (optUseTable && optMapTitle) { fprintf(outFile, "<h3>"); fprinte(outFile, optMapTitle); fprintf(outFile, "</h3>\n"); } if (optUseTable) fprintf(outFile, "<table>\n" " <tr>\n" " <td>\n" ); fprintf(outFile, "<div class=\"map\">" "<pre class=\"map\">" ); /* Process input, convert to map */ processMapHTML(outFile, inFile); /* Another table */ fprintf(outFile, "</pre>" "</div>\n" ); if (optUseTable) { fprintf(outFile, " </td>\n" " <td>\n" ); } fprintf(outFile, "<div class=\"loctab\">\n" "<table><tr>\n" ); k = (nlocations / (optUseTable ? 2 : 4)) + 1; for (n = 0; n < nlocations; n += k) printBlockHTML(outFile, n, n + k - 1); fprintf(outFile, "</tr></table>\n" "</div>\n" ); if (optUseTable) { fprintf(outFile, " </td>\n" " </tr>\n" "</table>\n" ); } for (n = 0; n < nlocations; n++) if (locations[n].desc) { fprintf(outFile, "<div class=\"tooltip\" id=\"tt%d\"><div class=\"holder\"><b>%s</b>", n, locations[n].desc); if (locations[n].extra) { fprintf(outFile, "<br />%s", locations[n].extra); } fprintf(outFile, "</div></div>\n"); } if (optUrchinFile) copyFile(outFile, optUrchinFile); /* XHTML document end tags */ fprintf(outFile, "</body>\n" "</html>\n" ); } void outputASCII(FILE *outFile, FILE *inFile) { int c, n, m; size_t i; char fmt[32]; /* Output title */ if (optMapTitle) { fprintf(outFile, "%s\n", optMapTitle); for (i = 0; i < strlen(optMapTitle); i++) fputc('-', outFile); fprintf(outFile, "\n\n"); } /* Process input, convert to map */ while ((c = fgetc(inFile)) != EOF) { fputc(c, outFile); } fprintf(outFile, "\n"); /* Find max width of location descs */ for (m = 0, n = 0; n < nlocations; n++) { c = strlen(locations[n].desc); if (c > m) m = c; } snprintf(fmt, sizeof(fmt), "%%c %%-%ds | ", m); /* Print location lists */ m = (nlocations / 2); for (n = 0; n < m; n++) { c = m + n; fprintf(outFile, fmt, locations[n].c, locations[n].desc); if (c < nlocations) { fprintf(outFile, "%c %s", locations[c].c, locations[c].desc); } fprintf(outFile, "\n"); } fprintf(outFile, "\n"); if (optUrchinFile) copyFile(outFile, optUrchinFile); } int parseLocFile(char *filename) { FILE *inFile; char s[4096]; size_t i, j, k; if ((inFile = fopen(filename, "rb")) == NULL) { THERR("Could not open file '%s' for reading.\n", filename); return -1; } while (fgets(s, sizeof(s), inFile)) { int len = strlen(s); if (len < 3 || s[0] == 0) continue; if (s[len-1] == '\n' || s[len-1] == '\r') s[len-1] = 0; i = 1; th_findnext(s, &i); j = i; while (s[i] && s[i] != '[' && !th_iscrlf(s[i])) i++; if (s[i] == '[') { k = i; while (s[k] && s[k] != ']' && !th_iscrlf(s[k])) k++; s[k] = 0; s[i] = 0; addLoc(s[0], &s[j], &s[i+1]); } else { s[i] = 0; addLoc(s[0], &s[j], NULL); } } fclose(inFile); return 0; } int main(int argc, char *argv[]) { FILE *inFile, *outFile; th_init("mkbcmap", "ASCII map converter", "0.3", NULL, NULL); th_verbosityLevel = 0; /* Parse arguments */ if (!th_args_process(argc, argv, optList, optListN, argHandleOpt, argHandleFile, TRUE)) exit(1); if (optMapFilename == NULL || optDescFilename == NULL) { THERR("You need to specify at least map and desc filenames. (try --help)\n"); exit(0); } /* Parse desc file */ if (parseLocFile(optDescFilename) < 0) { THERR("Could not properly parse desc file '%s'\n", optDescFilename); exit(3); } THMSG(1, "Parsed %d locations from '%s'.\n", nlocations, optDescFilename); /* Open mapfile */ if ((inFile = fopen(optMapFilename, "rb")) == NULL) { THERR("Could not open mapfile '%s' for reading.\n", optMapFilename); exit(3); } if (optDestFilename == NULL) outFile = stdout; else if ((outFile = fopen(optDestFilename, "wb")) == NULL) { fclose(inFile); THERR("Error opening output file '%s'!\n", optDestFilename); exit(1); } THMSG(1, "Using input map '%s', processing ..\n", optMapFilename); /* Output data */ switch (optOutputFormat) { case OUT_ASCII: outputASCII(outFile, inFile); break; case OUT_HTML: outputHTML(outFile, inFile); break; } /* Close input and output files */ fclose(inFile); fclose(outFile); exit(0); return 0; }