| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364 |
- #include <stdarg.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include "vt.h"
- #include "misc.h"
- #include "export.h"
- extern struct export_module export_txt;
- extern struct export_module export_ansi;
- extern struct export_module export_html;
- extern struct export_module export_png;
- extern struct export_module export_ppm;
- struct export_module *modules[] =
- {
- &export_txt,
- &export_ansi,
- &export_html,
- &export_ppm,
- #ifdef WITH_PNG
- &export_png,
- #endif
- 0
- };
- static char *glbl_opts[] =
- {
- "reveal", // show hidden text
- "hide", // don't show hidden text (default)
- 0
- };
- static char errbuf[64];
- void export_error(char *str, ...)
- {
- va_list args;
- va_start(args, str);
- vsnprintf(errbuf, sizeof(errbuf)-1, str, args);
- }
- char * export_errstr(void)
- {
- return errbuf;
- }
- static int find_opt(char **opts, char *opt, char *arg)
- {
- int err = 0;
- char buf[256];
- char **oo, *o, *a;
- if (oo = opts)
- while (o = *oo++)
- {
- if (a = strchr(o, '='))
- {
- a = buf + (a - o);
- o = strcpy(buf, o);
- *a++ = 0;
- }
- if (strcasecmp(o, opt) == 0)
- {
- if ((a != 0) == (arg != 0))
- return oo - opts;
- err = -1;
- }
- }
- return err;
- }
- struct export * export_open(char *fmt)
- {
- struct export_module **eem, *em;
- struct export *e;
- char *opt, *optend, *optarg;
- int opti;
- if (fmt = strdup(fmt))
- {
- if (opt = strchr(fmt, ','))
- *opt++ = 0;
- for (eem = modules; em = *eem; eem++)
- if (strcasecmp(em->fmt_name, fmt) == 0)
- break;
- if (em)
- {
- if (e = malloc(sizeof(*e) + em->local_size))
- {
- e->mod = em;
- e->fmt_str = fmt;
- e->reveal = 0;
- memset(e + 1, 0, em->local_size);
- if (not em->open || em->open(e) == 0)
- {
- for (; opt; opt = optend)
- {
- if (optend = strchr(opt, ','))
- *optend++ = 0;
- if (not *opt)
- continue;
- if (optarg = strchr(opt, '='))
- *optarg++ = 0;
- if ((opti = find_opt(glbl_opts, opt, optarg)) > 0)
- {
- if (opti == 1) // reveal
- e->reveal = 1;
- else if (opti == 2) // hide
- e->reveal = 0;
- }
- else if (opti == 0 &&
- (opti = find_opt(em->options, opt, optarg)) > 0)
- {
- if (em->option(e, opti, optarg))
- break;
- }
- else
- {
- if (opti == 0)
- export_error("%s: unknown option", opt);
- else if (optarg)
- export_error("%s: takes no arg", opt);
- else
- export_error("%s: missing arg", opt);
- break;
- }
- }
- if (opt == 0)
- return e;
- if (em->close)
- em->close(e);
- }
- free(e);
- }
- else
- export_error("out of memory");
- }
- else
- export_error("unknown format: %s", fmt);
- free(fmt);
- }
- else
- export_error("out of memory");
- return 0;
- }
- void export_close(struct export *e)
- {
- if (e->mod->close)
- e->mod->close(e);
- free(e->fmt_str);
- free(e);
- }
- static char * hexnum(char *buf, unsigned int num)
- {
- char *p = buf + 5;
- num &= 0xffff;
- *--p = 0;
- do
- {
- *--p = "0123456789abcdef"[num % 16];
- num /= 16;
- } while (num);
- return p;
- }
- static char * adjust(char *p, char *str, char fill, int width)
- {
- int l = width - strlen(str);
- while (l-- > 0)
- *p++ = fill;
- while (*p = *str++)
- p++;
- return p;
- }
- char * export_mkname(struct export *e, char *fmt, struct vt_page *vtp, char *usr)
- {
- char bbuf[1024];
- char *p = bbuf;
- while (*p = *fmt++)
- if (*p++ == '%')
- {
- char buf[32], buf2[32];
- int width = 0;
- p--;
- while (*fmt >= '0' && *fmt <= '9')
- width = width*10 + *fmt++ - '0';
- switch (*fmt++)
- {
- case '%':
- p = adjust(p, "%", '%', width);
- break;
- case 'e': // extension
- p = adjust(p, e->mod->extension, '.', width);
- break;
- case 'p': // pageno[.subno]
- if (vtp->subno)
- p = adjust(p,strcat(strcat(hexnum(buf, vtp->pgno),
- "."), hexnum(buf2, vtp->subno)), ' ', width);
- else
- p = adjust(p, hexnum(buf, vtp->pgno), ' ', width);
- break;
- case 'S': // subno
- p = adjust(p, hexnum(buf, vtp->subno), '0', width);
- break;
- case 'P': // pgno
- p = adjust(p, hexnum(buf, vtp->pgno), '0', width);
- break;
- case 's': // user strin
- p = adjust(p, usr, ' ', width);
- break;
- //TODO: add date, channel name, ...
- }
- }
- p = strdup(bbuf);
- if (not p)
- export_error("out of memory");
- return p;
- }
- static void fmt_page(struct export *e, struct fmt_page *pg, struct vt_page *vtp)
- {
- char buf[16];
- int x, y;
- u8 *p = vtp->data[0];
- pg->dbl = 0;
- sprintf(buf, "\2%x.%02x\7", vtp->pgno, vtp->subno & 0xff);
- for (y = 0; y < H; y++)
- {
- struct fmt_char c;
- int last_ch = ' ';
- int dbl = 0, hold = 0;
- c.fg = 7;
- c.bg = 0;
- c.attr = 0;
- for (x = 0; x < W; ++x)
- {
- c.ch = *p++;
- if (y == 0 && x < 8)
- c.ch = buf[x];
- switch (c.ch)
- {
- case 0x00 ... 0x07: /* alpha + fg color */
- c.fg = c.ch & 7;
- c.attr &= ~(EA_GRAPHIC | EA_CONCEALED);
- goto ctrl;
- case 0x08: /* flash */
- c.attr |= EA_BLINK;
- goto ctrl;
- case 0x09: /* steady */
- c.attr &= ~EA_BLINK;
- goto ctrl;
- case 0x0a: /* end box */
- case 0x0b: /* start box */
- goto ctrl;
- case 0x0c: /* normal height */
- c.attr &= EA_DOUBLE;
- goto ctrl;
- case 0x0d: /* double height */
- if (y < H-2) /* ignored on last 2 lines */
- {
- c.attr |= EA_DOUBLE;
- dbl = 1;
- }
- goto ctrl;
- case 0x10 ... 0x17: /* gfx + fg color */
- c.fg = c.ch & 7;
- c.attr |= EA_GRAPHIC;
- c.attr &= ~EA_CONCEALED;
- goto ctrl;
- case 0x18: /* conceal */
- c.attr |= EA_CONCEALED;
- goto ctrl;
- case 0x19: /* contiguous gfx */
- c.attr &= ~EA_SEPARATED;
- goto ctrl;
- case 0x1a: /* separate gfx */
- c.attr |= EA_SEPARATED;
- goto ctrl;
- case 0x1c: /* black bg */
- c.bg = 0;
- goto ctrl;
- case 0x1d: /* new bg */
- c.bg = c.fg;
- goto ctrl;
- case 0x1e: /* hold gfx */
- hold = 1;
- goto ctrl;
- case 0x1f: /* release gfx */
- hold = 0;
- goto ctrl;
- case 0x0e: /* SO */
- case 0x0f: /* SI */
- case 0x1b: /* ESC */
- c.ch = ' ';
- break;
- ctrl:
- c.ch = ' ';
- if (hold && (c.attr & EA_GRAPHIC))
- c.ch = last_ch;
- break;
- }
- if (c.attr & EA_GRAPHIC)
- if ((c.ch & 0xa0) == 0x20)
- {
- last_ch = c.ch;
- c.ch += (c.ch & 0x40) ? 32 : -32;
- }
- if (c.attr & EA_CONCEALED)
- if (not e->reveal)
- c.ch = ' ';
- pg->data[y][x] = c;
- }
- if (dbl)
- {
- pg->dbl |= 1 << y;
- for (x = 0; x < W; ++x)
- {
- if (~pg->data[y][x].attr & EA_DOUBLE)
- pg->data[y][x].attr |= EA_HDOUBLE;
- pg->data[y+1][x] = pg->data[y][x];
- pg->data[y+1][x].ch = ' ';
- }
- y++;
- p += W;
- }
- }
- pg->hid = pg->dbl << 1;
- }
- int export(struct export *e, struct vt_page *vtp, char *name)
- {
- struct fmt_page pg[1];
- fmt_page(e, pg, vtp);
- return e->mod->output(e, name, pg);
- }
|