Mercurial > hg > batmud > maputils
view mkcitymap.c @ 1770:cc59f80b0e78
Various cleanups.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Fri, 27 Oct 2017 04:35:51 +0300 |
parents | b8c4dad080ce |
children | 72adabd8e746 |
line wrap: on
line source
/* * mkcitymap - Create interactive XHTML+CSS+JS map from input * Programmed by Matti 'ccr' Hämäläinen (Ggr Pupunen) * (C) Copyright 2006-2015 Tecnic Software productions (TNSP) */ #include "libmaputils.h" #include "liblocfile.h" #include "th_args.h" #include "th_string.h" char *optDestFilename = NULL, *optMapFilename = NULL, *optLocFilename = NULL, *optUrchinFile = NULL, *optMapTitle = NULL; BOOL optUseTable = FALSE; /* Arguments */ static const th_optarg optList[] = { { 0, '?', "help", "Show this help", OPT_NONE }, { 1, 'v', "verbose", "Be more verbose", OPT_NONE }, { 2, 'o', "output", "Output filename", OPT_ARGREQ }, { 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(optList[0]); void argShowHelp(void) { th_print_banner(stdout, th_prog_name, "[options] <mapfile> <locfile>"); th_args_help(stdout, optList, optListN, 0); } 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 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 (!optLocFilename) optLocFilename = currArg; else { THERR("Too many filenames specified!\n"); return FALSE; } return TRUE; } void outputLocationBlockHTML(FILE *outFile, MapLocations *l, int nStart, int nEnd) { int n; if (nStart >= l->n || nStart < 0 || nStart > nEnd) return; if (nEnd >= l->n) nEnd = l->n-1; fprintf(outFile, "<td>\n"); for (n = nStart; n <= nEnd; n++) if (l->locations[n] != NULL) { LocMarker *tmp = l->locations[n]; if (tmp->flags & LOCF_INVIS) continue; fprintf(outFile, "<a class=\"loc\" id=\"listloc%d_%d\" href=\"?%d_%d\" onmouseover=\"qh('%d_%d')", tmp->x, tmp->y, tmp->x, tmp->y, tmp->x, tmp->y); if (tmp->freeform) { fprintf(outFile, ";stt('%d_%d');", tmp->x, tmp->y); } fprintf(outFile, "\" " "onmouseout=\"qn('%d_%d');\">", tmp->x, tmp->y); if (tmp->names[0].name != NULL) { fprintf(outFile, " <span class=\"desc\">%s</span>", tmp->names[0].name); } fprintf(outFile, "</a><br />\n"); } fprintf(outFile, "</td>\n"); } void outputHTMLHeader(FILE *outFile, MapLocations *l) { (void) l; muPrintHTMLhead(outFile, optMapTitle, TRUE); 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 {\n" " position: absolute;\n" " display: none;\n" " min-width: 200px; max-width: 500px;\n" " background: white; color: black;\n" " padding: 5px;\n" " border: 2px solid gray;\n" " -moz-border-radius: 5px;\n" " border-radius: 5px;\n" " font-size: 8pt;\n" " z-index: 15;\n" " }\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; }\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: 10pt;\n" " overflow: auto;\n" " }\n" " div.loctab table { width: 95%%; }\n" ); } muPrintHTMLcolors(outFile, "span", NULL, NULL); fprintf(outFile, " </style>\n" ); if (optUrchinFile && muCopyFileToStream(outFile, optUrchinFile) < 0) { THERR("Error copying urchin file '%s' to output.\n", optUrchinFile); } fprintf(outFile, "</head>\n" "<body onload=\"httOnLoad();\">\n" ); if (optUseTable && optMapTitle) { fprintf(outFile, "<h3>"); fputse(optMapTitle, outFile); fprintf(outFile, "</h3>\n"); } if (optUseTable) { fprintf(outFile, "<table>\n" " <tr>\n" " <td>\n" ); } fprintf(outFile, "<div class=\"map\">" "<pre class=\"map\">" ); } void outputHTMLFooter(FILE *outFile, MapLocations *l) { int n, k, num; fprintf(outFile, "</pre>" "</div>\n" ); if (optUseTable) { fprintf(outFile, " </td>\n" " <td>\n" ); } fprintf(outFile, "<div class=\"loctab\">\n" "<table><tr>\n" ); for (num = n = 0; n < l->n; n++) if (l->locations[n] != NULL) { LocMarker *tmp = l->locations[n]; if ((tmp->flags & LOCF_INVIS) == 0) num++; } k = (num / (optUseTable ? 2 : 4)) + 1; for (n = 0; n < l->n; n += k) outputLocationBlockHTML(outFile, l, 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 < l->n; n++) if (l->locations[n] != NULL) { LocMarker *tmp = l->locations[n]; if (tmp->flags & LOCF_INVIS) continue; fprintf(outFile, "<div class=\"tooltip\" name=\"tooltip\" id=\"tt%d_%d\">" "<div class=\"holder\">", tmp->x, tmp->y); if (tmp->names[0].name != NULL) { fprintf(outFile, "<b>%s</b>", tmp->names[0].name); } if (tmp->freeform) { fprintf(outFile, "<br />%s", tmp->freeform); } fprintf(outFile, "</div></div>\n"); } fprintf(outFile, "</body>\n" "</html>\n" ); } void outputMapHTML(FILE *outFile, MapBlock *map, MapLocations *l) { int x, y, n, p = -1, c; BOOL span = FALSE; for (y = 0; y < map->height; y++) { unsigned char *d = map->data + (map->scansize * y); for (x = 0; x < map->width; x++) { if ((n = locFindByCoords(l, x, y, TRUE)) >= 0) { LocMarker *tmp = l->locations[n]; if (span) fprintf(outFile, "</span>"); if (tmp->uri) { c = atoi(tmp->uri); if (c < 0 || c >= nmapColors) c = 0; fprintf(outFile, "<span class=\"%c\">%c</span>", 'a' + c, *d); } else { fprintf(outFile, "<span class=\"%c\">" "<a name=\"locpt\" onmouseover=\"stt('%d_%d');\" " "onmouseout=\"htt();\" " "class=\"loc\" id=\"maploc%d_%d\" " "href=\"?%d_%d\">%c</span></a></span>", 'a' + col_light_red, tmp->x, tmp->y, tmp->x, tmp->y, tmp->x, tmp->y, *d); } span = FALSE; p = -1; } else { if (p != *d) { if (span) fprintf(outFile, "</span>"); c = muGetMapPieceColor(*d, FALSE, TRUE); fprintf(outFile, "<span class=\"%c\">", 'a' + c); span = TRUE; } fputc(*d, outFile); p = *d; } d++; } if (span) fprintf(outFile, "</span>\n"); p = -1; span = FALSE; } } int main(int argc, char *argv[]) { MapBlock *map = NULL; FILE *outFile, *inFile; LocFileInfo locFile; MapLocations locations; memset(&locations, 0, sizeof(locations)); th_init("mkcitymap", "ASCII citymap converter", "0.5", NULL, NULL); th_verbosityLevel = 0; // Parse arguments if (!th_args_process(argc, argv, optList, optListN, argHandleOpt, argHandleFile, OPTH_BAILOUT)) exit(1); if (optMapFilename == NULL || optLocFilename == NULL) { THERR("You need to specify at least map and loc filenames. (try --help)\n"); exit(0); } // Parse location file setLocFileInfo(&locFile, optLocFilename, NULL); if ((inFile = fopen(locFile.filename, "rb")) == NULL) { THERR("Could not open location file '%s' for reading.\n", locFile.filename); exit(3); } if (!locParseLocStream(inFile, &locFile, &locations, locFile.x, locFile.y)) exit(1); fclose(inFile); // Open mapfile map = mapBlockParseFile(optMapFilename, FALSE); if (map == NULL) { THERR("Error parsing/opening mapfile '%s'.\n", optMapFilename); exit(3); } if (optDestFilename == NULL) outFile = stdout; else if ((outFile = fopen(optDestFilename, "wb")) == NULL) { THERR("Error opening output file '%s'!\n", optDestFilename); exit(1); } // Output data outputHTMLHeader(outFile, &locations); outputMapHTML(outFile, map, &locations); outputHTMLFooter(outFile, &locations); // Close input and output files fclose(outFile); mapBlockFree(map); locFreeMapLocations(&locations); exit(0); return 0; }