Mercurial > hg > batmud > maputils
view colormap.c @ 98:c856945880be
Remove debugging
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Sun, 17 Dec 2006 11:57:21 +0000 |
parents | c094c3637841 |
children | 834bbe2fbb51 |
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 Tecnic Software productions (TNSP) */ #include "maputils.h" #include "th_args.h" #include "th_string.h" typedef struct { char *fmtName; char *fmtDescription; BOOL supBackColor; void (*putTagStart) (FILE *, int); void (*putTagEnd) (FILE *); BOOL (*putTagEOL) (FILE *); void (*putFileStart) (FILE *); void (*putFileEnd) (FILE *); } outfmt_t; char *srcFilename = NULL, *destFilename = NULL; char *optXHTMLTagName = "i", *optMapTitle = NULL; BOOL optPerformAnalysis = FALSE, optInputIsDiff = FALSE, optUseOldFormat = FALSE, optCheatMode = 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 }, { 5, 'd', "input-diff", "Input is a diff", 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 }, }; 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;47;30m"); } 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); } } void putFileEndText(FILE *outFile) { (void) outFile; } /* * XHTML+CSS output format functions */ #define XHTML_LOCTITLE_SPEC 'q' void putTagStartXHTML(FILE *outFile, int c) { int q; if (c < 0) q = XHTML_LOCTITLE_SPEC; else q = 'a'+c; if (optCheatMode) fprintf(outFile, "<i class=%c>", q); else fprintf(outFile, "<i class='%c'>", q); } 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, " <style type=\"text/css\">\n" " h2 { color: white; }\n" " body { background: black; color: %s; }\n" " %s { text-decoration: none; font-style: normal; }\n" " %s.%c { background: white; color: black; }\n", mapColors[optBackColor].css, optXHTMLTagName, optXHTMLTagName, XHTML_LOCTITLE_SPEC ); mcXHTMLcolors(outFile, optXHTMLTagName); fprintf(outFile, " </style>\n" "</head>\n" "<body>\n" ); if (optMapTitle) fprintf(outFile, "<h2>%s</h2>\n", optMapTitle); fprintf(outFile, "<pre>\n" ); } void putFileEndXHTML(FILE *outFile) { /* XHTML document end tags */ fprintf(outFile, "</pre>\n" "</body>\n" "</html>\n" ); } /* * Old HTML output format functions */ void putTagStartHTML(FILE *outFile, int c) { if (c < 0) { fprintf(outFile, "<font bgcolor='white' color='black'>"); } else { fprintf(outFile, "<font color='%s'>", mapColors[c].css); } } 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>%s</title>\n", optMapTitle); fprintf(outFile, "</head>\n" "<body bgcolor='black' text='%s'>\n", mapColors[optBackColor].css ); if (optMapTitle) fprintf(outFile, "<h2>%s</h2>\n", optMapTitle); fprintf(outFile, "<pre>\n" ); } void putFileEndHTML(FILE *outFile) { fprintf(outFile, "</pre>\n" "</body>\n" "</html>\n" ); } /* Process a normal format input */ void 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) { /* Location title mode */ if (p != -1 && (!fmt->supBackColor || p != optBackColor)) fmt->putTagEnd(outFile); c = p = -2; fmt->putTagStart(outFile, -1); while ((k = fgetc(inFile)) != EOF) { if (k == 0xfe) break; else fprintf(outFile, "%c", k); } } else { c = mcGetColor(k, optUseOldFormat); 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); } /* Get a symbol */ char getSymbol(int i, BOOL useOld) { if (useOld) return mapPieces[i].oldSymbol; else return mapPieces[i].symbol; } /* Process a diff */ BOOL processDiff(FILE *inFile, FILE *outFile, outfmt_t *fmt) { int c, p; size_t offs; offs = 0; c = p = -1; while ((c = fgetc(inFile)) != EOF) { if (c == 0xff) { if (fmt->putTagEOL(outFile)) c = -1; } else { if (c != p) { if (p != -1) fmt->putTagEnd(outFile); if (c >= 0) { int t = (c / 64), q = mcGetColor(c % 64, optUseOldFormat); if (t > 0) { /* FIXME FIXME TODO */ fprintf(outFile, "<i style='background:%s;color:black'>", mapColors[q].css); } else fmt->putTagStart(outFile, q); fprintf(outFile, "%c", getSymbol(q, optUseOldFormat)); } } else if (c >= 0) { fprintf(outFile, "%c", getSymbol(c % 64, optUseOldFormat)); } else { THERR("Broken map diff input at offset %d.\n", offs); exit(15); } } p = c; offs++; } if (p != -1) fmt->putTagEnd(outFile); return TRUE; } /* List of output formats */ outfmt_t outputFormats[] = { { "xhtml", "XHTML+CSS", TRUE, putTagStartXHTML, putTagEndXHTML, putEOLXHTML, putFileStartXHTML, putFileEndXHTML }, { "html", "Old HTML without CSS", TRUE, putTagStartHTML, putTagEndHTML, putEOLHTML, putFileStartHTML, putFileEndHTML }, { "ansi", "ANSI text", FALSE, putTagStartANSI, putTagEndANSI, putEOLANSI, putFileStartANSI, putFileEndANSI }, { "text", "Plain ASCII text", FALSE, putTagStartText, putTagEndText, putEOLText, putFileStartText, putFileEndText }, }; 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 5: optInputIsDiff = TRUE; THMSG(2, "Input is a 'diff', handling it as such.\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 (th_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; 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; } #define NMAX 256 /* Main program */ int main(int argc, char *argv[]) { FILE *inFile, *outFile; outfmt_t *fmt = NULL; /* Initialize */ th_init("colormap", "ASCII map colorizer", "0.1", NULL, NULL); th_verbosityLevel = 1; /* 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[NMAX]; int colChangesFrom[NMAX]; if (optInputIsDiff) { THERR("Cannot perform analysis for diff format files, sorry!\n"); exit(2); } 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); if ((c != p) && (c >= 0) && (c < NMAX)) { colChangesTo[c]++; if ((p >= 0) && (p < NMAX)) colChangesFrom[p]++; } } p = c; } fclose(inFile); /* Find highest frequency */ THMSG(2, "Computing results.\n"); tMax = fMax = tn = fn = -1; for (i = 0; i < NMAX; 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); fmt->putFileStart(outFile); if (optInputIsDiff) processDiff(inFile, outFile, fmt); else processNormal(inFile, outFile, fmt); fmt->putFileEnd(outFile); fclose(outFile); fclose(inFile); THMSG(1, "Done.\n"); exit(0); return 0; }