/* $XTermId: html.c,v 1.13 2018/07/02 18:30:45 tom Exp $ */ /* * Copyright 2015,2018 Jens Schweikhardt * Copyright 2018 Thomas E. Dickey * * All Rights Reserved * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Except as contained in this notice, the name(s) of the above copyright * holders shall not be used in advertising or otherwise to promote the sale, * use or other dealings in this Software without prior written * authorization. */ #include #include #define MakeDim(color) \ color = (unsigned short) ((2 * (unsigned) color) / 3) #define RGBPCT(c) \ ((double)c.red / 655.35), \ ((double)c.green / 655.35), \ ((double)c.blue / 655.35) #define DUMP_PREFIX "xterm" #define DUMP_SUFFIX ".xhtml" #define DEFAULTNAME DUMP_PREFIX DUMP_SUFFIX #ifdef VMS #define VMS_HTML_FILE "sys$scratch:" DEFAULTNAME #endif static void dumpHtmlHeader(XtermWidget xw, FILE *fp); static void dumpHtmlScreen(XtermWidget xw, FILE *fp); static void dumpHtmlLine(XtermWidget xw, int row, FILE *fp); static void dumpHtmlFooter(XtermWidget, FILE *fp); static void writeStyle(XtermWidget, FILE *fp); char *PixelToCSSColor(XtermWidget xw, Pixel p); void xtermDumpHtml(XtermWidget xw) { FILE *fp; TRACE(("xtermDumpHtml...\n")); #ifdef VMS fp = fopen(VMS_HTML_FILE, "wb"); #elif defined(HAVE_STRFTIME) { char fname[sizeof(DEFAULTNAME) + LEN_TIMESTAMP]; time_t now; struct tm *ltm; now = time((time_t *) 0); ltm = localtime(&now); if (strftime(fname, sizeof fname, DUMP_PREFIX FMT_TIMESTAMP DUMP_SUFFIX, ltm) > 0) { fp = fopen(fname, "wb"); } else { fp = fopen(DEFAULTNAME, "wb"); } } #else fp = fopen(DEFAULTNAME, "wb"); #endif if (fp != 0) { dumpHtmlHeader(xw, fp); dumpHtmlScreen(xw, fp); dumpHtmlFooter(xw, fp); fclose(fp); } TRACE(("...xtermDumpHtml done\n")); } static void dumpHtmlHeader(XtermWidget xw, FILE *fp) { fputs("\n", fp); fputs("\n", fp); fputs("\n", fp); fputs(" \n", fp); fprintf(fp, " \n", xtermVersion()); fputs(" \n", fp); fputs(" \n", fp); fputs(" Xterm\n", fp); writeStyle(xw, fp); fputs(" \n", fp); fputs(" \n", fp); fputs("
\n", fp); fputs("
", fp);
}

static void
writeStyle(XtermWidget xw, FILE *fp)
{
    TScreen *s = TScreenOf(xw);

    fputs("  \n", fp);
}

static void
dumpHtmlScreen(XtermWidget xw, FILE *fp)
{
    TScreen *s = TScreenOf(xw);
    int row;

    for (row = s->top_marg; row <= s->bot_marg; ++row) {
	dumpHtmlLine(xw, row, fp);
    }
}

/*
 * Note: initial and final space around values of class and style
 *       attribute are deliberate. They make it easier for XPath
 *       to test whether a particular name is among the attributes.
 *       It allows expressions such as
 *           [contains(@class, ' ul ')]
 *       instead of the unwieldy
 *           [contains(concat(' ', @class, ' '), ' ul ')]
 *       The ev and od (for even and odd rows) values
 *       avoid empty values when going back to old fg/bg.
 */
static void
dumpHtmlLine(XtermWidget xw, int row, FILE *fp)
{
    TScreen *s = TScreenOf(xw);
    char attrs[2][sizeof
		  ""];
    int attr_index = 0;
    char *attr = &attrs[attr_index][0];
    int inx = ROW2INX(s, row);
    LineData *ld = getLineData(s, inx);
    int col;

    if (ld == 0)
	return;

    for (col = 0; col < MaxCols(s); col++) {
	XColor fgcolor, bgcolor;
	IChar chr = ld->charData[col];
	int slen = 0;

	fgcolor.pixel = xw->old_foreground;
	bgcolor.pixel = xw->old_background;
#if OPT_ISO_COLORS
	if (ld->attribs[col] & FG_COLOR) {
	    Pixel fg = extract_fg(xw, ld->color[col], ld->attribs[col]);
#if OPT_DIRECT_COLOR
	    if (ld->attribs[col] & ATR_DIRECT_FG)
		fgcolor.pixel = fg;
	    else
#endif
		fgcolor.pixel = s->Acolors[fg].value;
	}
	if (ld->attribs[col] & BG_COLOR) {
	    Pixel bg = extract_bg(xw, ld->color[col], ld->attribs[col]);
#if OPT_DIRECT_COLOR
	    if (ld->attribs[col] & ATR_DIRECT_BG)
		bgcolor.pixel = bg;
	    else
#endif
		bgcolor.pixel = s->Acolors[bg].value;
	}
#endif

	XQueryColor(xw->screen.display, xw->core.colormap, &fgcolor);
	XQueryColor(xw->screen.display, xw->core.colormap, &bgcolor);
	if (ld->attribs[col] & BLINK) {
	    /* White on red. */
	    fgcolor.red = fgcolor.green = fgcolor.blue = 65535u;
	    bgcolor.red = 65535u;
	    bgcolor.green = bgcolor.blue = 0u;
	}
#if OPT_WIDE_ATTRS
	if (ld->attribs[col] & ATR_FAINT) {
	    MakeDim(fgcolor.red);
	    MakeDim(fgcolor.green);
	    MakeDim(fgcolor.blue);
	}
#endif
	if (ld->attribs[col] & INVERSE) {
	    XColor tmp = fgcolor;
	    fgcolor = bgcolor;
	    bgcolor = tmp;
	}

	slen = sprintf(attr + slen, "", RGBPCT(bgcolor));
	if (col == 0) {
	    fputs(attr, fp);
	    attr = &attrs[attr_index ^= 1][0];
	} else {
	    if (strcmp(&attrs[0][0], &attrs[1][0])) {
		fputs("", fp);
		fputs(attr, fp);
		attr = &attrs[attr_index ^= 1][0];
	    }
	}

#if OPT_WIDE_CHARS
	if (chr > 127) {
	    /* Ignore hidden characters. */
	    if (chr != HIDDEN_CHAR) {
		Char temp[10];
		*convertToUTF8(temp, chr) = 0;
		fputs((char *) temp, fp);
	    }
	} else
#endif
	    switch (chr) {
	    case 0:
		/* This sometimes happens when resizing... ignore. */
		break;
	    case '&':
		fputs("&", fp);
		break;
	    case '<':
		fputs("<", fp);
		break;
	    case '>':
		fputs(">", fp);
		break;
	    case ' ':
		fputs("\302\240", fp);
		break;
	    default:
		fputc((int) chr, fp);
	    }
    }
    fprintf(fp, "\n");
}

static void
dumpHtmlFooter(XtermWidget xw GCC_UNUSED, FILE *fp)
{
    fputs("
\n", fp); fputs("
\n", fp); fputs(" \n", fp); fputs("\n", fp); } char * PixelToCSSColor(XtermWidget xw, Pixel p) { static char rgb[sizeof "rgb(100.00%, 100.00%, 100.00%)"]; XColor c; c.pixel = p; XQueryColor(xw->screen.display, xw->core.colormap, &c); sprintf(rgb, "rgb(%.2f%%, %.2f%%, %.2f%%)", RGBPCT(c)); return rgb; } /* vim: set ts=8 sw=4 et: */