Mercurial > hg > batmud > maputils
view colormap.c @ 945:81184d58133c aprilli2011
Sync.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Fri, 14 May 2010 11:18:20 +0000 |
parents | 87af6f129228 |
children | 5c2bd0ac3118 |
line wrap: on
line source
/* * Convert BatMUD ASCII map to different formats * Programmed by Matti 'ccr' Hämäläinen (Ggr Pupunen) * (C) Copyright 2006-2008 Tecnic Software productions (TNSP) */ #include "maputils.h" #include "th_args.h" #include "th_string.h" #define MAXCOL (256) #define MAXSTR (1024) typedef struct { char *fmtName; char *fmtDescription; BOOL supBackColor; void (*putTagLocation) (FILE *, char *, int); void (*putTagLocationEnd) (FILE *, char *); void (*putTagStart) (FILE *, int); void (*putTagEnd) (FILE *); BOOL (*putTagEOL) (FILE *); void (*putFileStart) (FILE *); void (*putFileEnd) (FILE *); void (*putString) (FILE *, char *); } outfmt_t; char *srcFilename = NULL, *destFilename = NULL; char *optXHTMLTagName = "i", *optMapTitle = NULL, *optUrchinFile = NULL; BOOL optPerformAnalysis = FALSE, optUseOldFormat = FALSE, optCheatMode = FALSE, optNoHeaders = FALSE, optPosGlue = FALSE, optCityFormat = FALSE; int optOutputFormat = 0, optBackColor = 0; /* Arguments */ optarg_t optList[] = { { 0, '?', "help", "Show this help", OPT_NONE }, { 1, 'v', "verbose", "Be more verbose", OPT_NONE }, { 2, 'q', "quiet", "Be quiet", OPT_NONE }, { 3, 'T', "html-tag", "XHTML tag used for map", OPT_ARGREQ }, { 4, 'a', "analysis", "Perform statistical analysis", OPT_NONE }, { 6, 'O', "old-format", "Input using old symbols/colors", OPT_NONE }, { 7, 'o', "output", "Output filename", OPT_ARGREQ }, { 8, 'f', "format", "Specify output format", OPT_ARGREQ }, { 9, 't', "title", "Map title", OPT_ARGREQ }, { 10,'C', "cheat-mode", "Use cheating in HTML", OPT_NONE }, { 11,'n', "no-headers", "Do not output headers/footers", OPT_NONE }, { 12,'P', "pos-glue", "Generate JavaScript, etc. for posglue", OPT_NONE }, { 13,'c', "city-format", "Input is a city map", OPT_NONE }, { 14,'u', "urchin-file", "Specify urchin file", OPT_ARGREQ }, }; const int optListN = (sizeof(optList) / sizeof(optarg_t)); /* * ANSI output format functions */ void putTagStartANSI(FILE *outFile, int c) { fputc(0x1b, outFile); if (c < 0) { fprintf(outFile, "[0;%d;30m", 10 + mapColors[-c-1].ansi); } else { fprintf(outFile, "[0;%d;%dm", mapColors[c].ansiAttr, mapColors[c].ansi); } } void putTagEndANSI(FILE *outFile) { (void) outFile; /* fputc(0x1b, outFile); fprintf(outFile, "[0m"); */ } BOOL putEOLANSI(FILE *outFile) { fprintf(outFile, "\n"); return TRUE; } void putFileStartANSI(FILE *outFile) { fputc(0x1b, outFile); fprintf(outFile, "[0m"); if (optMapTitle) { fprintf(outFile, "%s\n", optMapTitle); } } void putFileEndANSI(FILE *outFile) { fputc(0x1b, outFile); fprintf(outFile, "[0m"); } /* * ASCII output format functions */ void putTagStartText(FILE *outFile, int c) { (void) outFile; (void) c; // fprintf(outFile, "§"); } void putTagEndText(FILE *outFile) { (void) outFile; // fprintf(outFile, "$"); } BOOL putEOLText(FILE *outFile) { fprintf(outFile, "\n"); return FALSE; } void putFileStartText(FILE *outFile) { if (optMapTitle) { fprintf(outFile, "%s\n", optMapTitle); } } /* * XHTML+CSS output format functions */ #define XHTML_LOCLABEL "label" void putColorClassXHTML(FILE *outFile, int c) { int q = 'a'+c; if (optCheatMode) fprintf(outFile, "class=%c>", q); else fprintf(outFile, "class=\"%c\">", q); } void putTagLocationXHTML(FILE *outFile, char * locID, int c) { fprintf(outFile, "<i class=\"" XHTML_LOCLABEL "\"><a id=\"%s\" ", locID); putColorClassXHTML(outFile, c); } void putTagLocationEndXHTML(FILE *outFile, char *locID) { (void) locID; fprintf(outFile, "</a>"); } void putTagStartXHTML(FILE *outFile, int c) { fprintf(outFile, "<i "); putColorClassXHTML(outFile, c); } void putTagEndXHTML(FILE *outFile) { fprintf(outFile, "</i>"); } BOOL putEOLXHTML(FILE *outFile) { fprintf(outFile, "\n"); return FALSE; } void putFileStartXHTML(FILE *outFile) { mcXHTMLhead(outFile, optMapTitle); fprintf(outFile, " <script type=\"text/javascript\" src=\"util.js\"></script>\n" " <style type=\"text/css\">\n" " %s." XHTML_LOCLABEL " { background: white; color: black; %s}\n" " body { background: black; color: %s; font-family: Arial, Verdana, sans-serif; }\n" " h2 { color: white; font-size: 14pt; }\n" " pre { font-size: 10pt; }\n" " %s { text-decoration: none; font-style: normal; }\n", optXHTMLTagName, (optPosGlue) ? "position: relative; " : "", mcGetCSS(optBackColor), optXHTMLTagName ); mcXHTMLcolors(outFile, optXHTMLTagName, NULL, NULL); mcXHTMLcolors(outFile, "a", "background", " color: black;"); if (optPosGlue) { fprintf(outFile, " div.sgbox {\n" " background: #bbb;\n" " color: black;\n" " position: fixed;\n" " top: 0.5em;\n" " right: 0.5em;\n" " width: 25em;\n" " height: 6em;\n" " margin: 4px;\n" " padding: 4px;\n" " z-index: 10;\n" " border: 2px solid gray;\n" " font-size: 10pt;\n" " }\n" " i." XHTML_LOCLABEL " a {\n" " position: absolute;\n" " top: 0px;\n" " left: 0px;\n" " z-index: 2;\n" " }\n" ); } fprintf(outFile, " </style>\n" "</head>\n" "<body onLoad=\"gotoOnLoadPos();\">\n"); if (!optPosGlue) { if (optMapTitle) { fprintf(outFile, "<h2>"); fprinte(outFile, optMapTitle); fprintf(outFile, "</h2>\n"); } } else { fprintf(outFile, "<div id=\"sbox\" class=\"sgbox\">\n" " <b>"); fprinte(outFile, optMapTitle); fprintf(outFile, "</b>\n" " <form>\n" " <select name=\"slocation\" onChange=\"gotoPos();\">\n" "@LOCATIONS@\n" " </select>\n" " <br /><input name=\"shide\" onClick=\"toggleLabels();\" type=\"checkbox\" checked=\"checked\">Labels</input>\n" " </form>\n" "</div>\n" ); } fprintf(outFile, "<pre>\n" ); } void putFileEndXHTML(FILE *outFile) { FILE *f; /* XHTML document end tags */ fprintf(outFile, "</pre>\n" ); if (optUrchinFile) { if ((f = fopen(optUrchinFile, "rb")) != NULL) { int c; while ((c = fgetc(f)) != EOF) fputc(c, outFile); fclose(f); } else { THERR("Urchin file '%s' not found!\n", optUrchinFile); exit(17); } } fprintf(outFile, "</body>\n" "</html>\n" ); } /* * Old HTML output format functions */ void putTagStartHTML(FILE *outFile, int c) { if (c < 0) { fprintf(outFile, "<font bgcolor='%s' color='black'>", mcGetCSS(-c-1)); } else { fprintf(outFile, "<font color='%s'>", mcGetCSS(c)); } } void putTagEndHTML(FILE *outFile) { fprintf(outFile, "</font>"); } BOOL putEOLHTML(FILE *outFile) { fprintf(outFile, "\n"); return FALSE; } void putFileStartHTML(FILE *outFile) { fprintf(outFile, "<html>\n" "<head>\n" ); if (optMapTitle) { fprintf(outFile, " <title>"); fprinte(outFile, optMapTitle); fprintf(outFile, "</title>\n"); } fprintf(outFile, "</head>\n" "<body bgcolor=\"black\" text=\"%s\">\n", mcGetCSS(optBackColor) ); if (optMapTitle) { fprintf(outFile, "<h2>"); fprinte(outFile, optMapTitle); fprintf(outFile, "</h2>\n"); } fprintf(outFile, "<pre>\n" ); } void putFileEndHTML(FILE *outFile) { fprintf(outFile, "</pre>\n" "</body>\n" "</html>\n" ); } /* Process a normal format input */ BOOL processNormal(FILE *inFile, FILE *outFile, outfmt_t *fmt) { int k, c, p; c = p = -1; while ((k = fgetc(inFile)) != EOF) { if (k == '\n') { if (fmt->putTagEOL(outFile)) c = -1; } else if (k == 0xff) { char tmpStr[MAXSTR+1], tmpStr2[MAXSTR+1]; int i; /* Location title mode */ if (p != -1 && (!fmt->supBackColor || p != optBackColor)) fmt->putTagEnd(outFile); c = p = -2; /* Location marker tag */ for (i = 0; i < MAXSTR && (k = fgetc(inFile)) != EOF;) { if (k == 0xfc) break; else tmpStr[i++] = k; } tmpStr[i] = 0; if (k != 0xfc) { THERR("Unexpected end of file (location tag name).\n"); return FALSE; } /* Get colour */ k = fgetc(inFile); if (k == EOF) { THERR("Unexpected end of file (location tag colour).\n"); return FALSE; } if (!fmt->putTagLocation && fmt->putTagStart) fmt->putTagStart(outFile, -k - 1); if (fmt->putTagLocation) fmt->putTagLocation(outFile, tmpStr, k); for (i = 0; i < MAXSTR && (k = fgetc(inFile)) != EOF;) { if (k == 0xfe) break; else tmpStr2[i++] = k; } tmpStr2[i] = 0; if (k != 0xfe) { THERR("Expected location tag '%s' end, but did not find one.\n", tmpStr); return FALSE; } if (fmt->putString) fmt->putString(outFile, tmpStr2); else fputs(tmpStr2, outFile); if (fmt->putTagLocationEnd) fmt->putTagLocationEnd(outFile, tmpStr); } else { c = mcGetColor(k, optUseOldFormat, optCityFormat); if (c != p) { if (p != -1 && (!fmt->supBackColor || p != optBackColor)) fmt->putTagEnd(outFile); if (!fmt->supBackColor || (c != optBackColor)) fmt->putTagStart(outFile, c); fprintf(outFile, "%c", k); } else { fprintf(outFile, "%c", k); } } p = c; } if (p != -1 && (!fmt->supBackColor || p != optBackColor)) fmt->putTagEnd(outFile); return TRUE; } /* Get a symbol */ char getSymbol(int i, BOOL useOld) { if (useOld) return mapPieces[i].oldSymbol; else return mapPieces[i].symbol; } /* List of output formats */ outfmt_t outputFormats[] = { { "xhtml", "XHTML+CSS", TRUE, putTagLocationXHTML, putTagLocationEndXHTML, putTagStartXHTML, putTagEndXHTML, putEOLXHTML, putFileStartXHTML, putFileEndXHTML, fprinte }, { "html", "Old HTML without CSS", TRUE, putTagLocationXHTML, putTagLocationEndXHTML, putTagStartHTML, putTagEndHTML, putEOLHTML, putFileStartHTML, putFileEndHTML, fprinte }, { "ansi", "ANSI text", FALSE, NULL, NULL, putTagStartANSI, putTagEndANSI, putEOLANSI, putFileStartANSI, putFileEndANSI, NULL }, { "text", "Plain ASCII text", FALSE, NULL, NULL, putTagStartText, putTagEndText, putEOLText, putFileStartText, NULL, NULL }, }; const int noutputFormats = (sizeof(outputFormats) / sizeof(outfmt_t)); void argShowHelp(void) { int i; th_args_help(stderr, optList, optListN, th_prog_name, "[options] <input mapfile>"); fprintf(stderr, "\nAvailable OUTPUT formats:\n"); for (i = 0; i < noutputFormats; i++) { fprintf(stderr, " %-8s - %s %s\n", outputFormats[i].fmtName, outputFormats[i].fmtDescription, (i == optOutputFormat) ? "(default)" : "" ); } fprintf(stderr, "\n"); } BOOL argHandleOpt(const int optN, char *optArg, char *currArg) { int i, n; switch (optN) { case 0: argShowHelp(); exit(0); break; case 1: th_verbosityLevel++; break; case 2: th_verbosityLevel = -1; break; case 3: optXHTMLTagName = optArg; THMSG(2, "HTML tag set to '%s'\n", optXHTMLTagName); break; case 4: optPerformAnalysis = TRUE; THMSG(2, "Analysis enabled.\n"); break; case 6: optUseOldFormat = TRUE; THMSG(2, "Input is using old map symbols/colors.\n"); break; case 7: destFilename = optArg; THMSG(2, "Output file set to '%s'.\n", destFilename); break; case 8: /* Get format */ for (i = 0, n = -1; (i < noutputFormats) && (n < 0); i++) if (strcmp(optArg, outputFormats[i].fmtName) == 0) n = i; if (n < 0) { THERR("Invalid output format '%s'\n", optArg); return FALSE; } optOutputFormat = n; THMSG(2, "Output format set to '%s'\n", optArg); break; case 9: optMapTitle = optArg; THMSG(2, "Map title string set to '%s'.\n", optMapTitle); break; case 10: optCheatMode = TRUE; THMSG(2, "HTML cheats mode enabled!\n"); break; case 11: optNoHeaders = TRUE; THMSG(2, "Not outputting headers/footers\n"); break; case 12: optPosGlue = TRUE; THMSG(2, "Generating JavaScript junk for positioning glue\n"); break; case 13: optCityFormat = TRUE; THMSG(2, "Input is handled as a city map\n"); break; case 14: 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 (!srcFilename) srcFilename = currArg; else { THERR("Too many input map files specified!\n"); return FALSE; } return TRUE; } /* Main program */ int main(int argc, char *argv[]) { FILE *inFile, *outFile; outfmt_t *fmt = NULL; /* Initialize */ th_init("colormap", "ASCII map colorizer", "0.5", NULL, NULL); th_verbosityLevel = 0; /* Parse arguments */ if (!th_args_process(argc, argv, optList, optListN, argHandleOpt, argHandleFile, TRUE)) exit(1); if (srcFilename == NULL) { THERR("Nothing to do. (try --help)\n"); exit(0); } /* Do statistical analysis, if needed */ if (optPerformAnalysis) { int k, c, p, i, tMax, fMax, tn, fn; int colChangesTo[MAXCOL]; int colChangesFrom[MAXCOL]; THMSG(1, "Performing statistical frequency analysis ...\n"); THMSG(2, "Reading '%s' for analysis data ...\n", srcFilename); if ((inFile = fopen(srcFilename, "rb")) == NULL) { THERR("Error opening input file '%s'!\n", srcFilename); exit(1); } /* Initialize counters */ th_memset(colChangesTo, 0, sizeof(colChangesTo)); th_memset(colChangesFrom, 0, sizeof(colChangesFrom)); /* Read data, keeping statistics of colour change frequencies */ c = p = -1; while ((k = fgetc(inFile)) != EOF) { if (k != '\n' && k != ' ' && k < 0xfe) { c = mcGetColor(k, optUseOldFormat, optCityFormat); if ((c != p) && (c >= 0) && (c < MAXCOL)) { colChangesTo[c]++; if ((p >= 0) && (p < MAXCOL)) colChangesFrom[p]++; } } p = c; } fclose(inFile); /* Find highest frequency */ THMSG(2, "Computing results.\n"); tMax = fMax = tn = fn = -1; for (i = 0; i < MAXCOL; i++) { if (colChangesTo[i] > tMax) { tMax = colChangesTo[i]; tn = i; } if (colChangesFrom[i] > fMax) { fMax = colChangesFrom[i]; fn = i; } } THMSG(2, "tMax=%d, tn=%d -- fMax=%d, fn=%d\n", tMax, tn, fMax, fn); if (tMax > fMax) optBackColor = tn; else optBackColor = fn; THMSG(1, "Using colour %d as 'background' color.\n", optBackColor); } /* Open input file */ if ((inFile = fopen(srcFilename, "rb")) == NULL) { THERR("Error opening input file '%s'!\n", srcFilename); exit(1); } /* Open output file */ if (destFilename == NULL) outFile = stdout; else if ((outFile = fopen(destFilename, "wb")) == NULL) { THERR("Error opening output file '%s'!\n", destFilename); exit(1); } /* Okay, let's process the shit */ fmt = &outputFormats[optOutputFormat]; THMSG(1, "Converting to '%s' ...\n", fmt->fmtName); if (!optNoHeaders && fmt->putFileStart) fmt->putFileStart(outFile); processNormal(inFile, outFile, fmt); if (!optNoHeaders && fmt->putFileEnd) fmt->putFileEnd(outFile); fclose(outFile); fclose(inFile); THMSG(1, "Done.\n"); exit(0); return 0; }