#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "aalib.h"
#include "aaint.h"
#define NORMALPRINTS { "%s", "%s", "%s", "%s", "%s", }
#define NONE { "", "", "", "", "", }
static __AA_CONST char * __AA_CONST html_escapes[] =
{"<", "<", ">", ">", "&", "&", NULL};
static __AA_CONST char * __AA_CONST html_alt_escapes[] =
{"<", "<", ">", ">", "&", "&", "\"", """, NULL};
#ifdef VYHEN_SUPPORT
static __AA_CONST char * __AA_CONST vyhen_escapes[] =
{"|", "||","~", "~~", NULL};
#endif
__AA_CONST static char * __AA_CONST irc_escapes[] =
{"@", "@@", NULL};
static char *generate_filename(__AA_CONST char *template, char *result, int x, int y, int pages, __AA_CONST char *extension);
__AA_CONST struct aa_format aa_nhtml_format =
{
79, 36,
79, 36,
0,
AA_NORMAL_MASK | AA_BOLD_MASK | AA_BOLDFONT_MASK | AA_DIM_MASK,
&aa_fontcourier,
"Nestcapeized html",
".html",
"<HTML>\n<HEAD><TITLE>Ascii arted image done using aalib</TITLE>\n</HEAD>\n<BODY BGCOLOR=\"#000000\" TEXT=\"#b2b2b2\" LINK=\"#FFFFFF\">\n<FONT COLOR=#b2b2b2 SIZE=2><PRE>\n",
"</PRE></FONT></BODY>\n</HTML>\n",
"\n",
NORMALPRINTS,
{"",
"<FONT COLOR=\"686868\">",
"<FONT COLOR=\"ffffff\">",
"",
"<B>"
},
{"",
"</FONT>",
"</FONT>",
"",
"</B>"
},
html_escapes
};
__AA_CONST struct aa_format aa_html_format =
{
79, 25,
79, 25,
0,
AA_NORMAL_MASK | AA_BOLD_MASK | AA_BOLDFONT_MASK,
NULL,
"Pure html",
".html",
"<HTML>\n <HEAD> <TITLE>Ascii arted image done using aalib</TITLE>\n</HEAD>\n<BODY><PRE>\n",
"</PRE></BODY>\n</HTML>\n",
"\n",
NORMALPRINTS,
{"",
"",
"<B>",
"",
"<B>"
},
{"",
"",
"</B>",
"",
"</B>"
},
html_escapes
};
__AA_CONST struct aa_format aa_ansi_format =
{
80, 25,
80, 25,
0,
AA_NORMAL_MASK | AA_BOLD_MASK | AA_BOLDFONT_MASK | AA_REVERSE_MASK | AA_DIM_MASK,
NULL,
"ANSI escape seqences",
".ansi",
"",
"",
"\n",
NORMALPRINTS,
{"",
"\33[8m",
"\33[1m",
"\33[1m",
"\33[7m"
},
{"",
"\33[0;10m",
"\33[0;10m",
"\33[0;10m",
"\33[0;10m",
},
NULL
};
#ifdef VYHEN_SUPPORT
__AA_CONST struct aa_format aa_vyhen_format =
{
80, 30,
80, 30,
0,
AA_NORMAL_MASK | AA_BOLD_MASK | AA_REVERSE_MASK | AA_DIM_MASK | AA_EXTENDED,
NULL,
"vyhen",
".vyhen",
"",
"",
"\n",
NORMALPRINTS,
{"|07",
"|08",
"|15",
"||7|00",
"||1|15"
},
{"",
"",
"",
"||9",
"||0",
},
vyhen_escapes
};
#endif
__AA_CONST struct aa_format aa_text_format =
{
80, 25,
80, 25,
0,
AA_NORMAL_MASK,
NULL,
"Text file",
".txt",
"",
"",
"\n",
NORMALPRINTS,
NONE,
NONE,
NULL
};
__AA_CONST struct aa_format aa_more_format =
{
80, 25,
80, 25,
AA_NORMAL_SPACES,
AA_NORMAL_MASK | AA_BOLD_MASK | AA_BOLDFONT_MASK,
NULL,
"For more/less",
".cat",
"",
"",
"\n",
/* Can leave these %c iff there are no conversions to multi-character
* thingies. */
{"%s", "%s", "%s\10%s", "%s\10%s", "%s"},
NONE,
NONE,
NULL
};
__AA_CONST struct aa_format aa_hp_format =
{
130 * 2, 64 * 2 - 1,
130, 64 * 2 - 1,
AA_USE_PAGES,
AA_NORMAL_MASK,
&aa_fontline,
"HP laser jet - A4 small font",
".hp",
"\33(10U\33(s0p16.67h8.5v0s0b0T\33%%0A\33&/0U\33&/0Z\33&/24D",
"\14",
"\r\33=",
NORMALPRINTS,
NONE,
NONE,
NULL
};
__AA_CONST struct aa_format aa_hp2_format =
{
80 * 2, 64 - 1,
80, 64 - 1,
AA_USE_PAGES,
AA_NORMAL_MASK,
&aa_font16,
"HP laser jet - A4 big font",
".hp",
"\33(s7B\33*p0Y@",
"\14",
"\r\n",
NORMALPRINTS,
NONE,
NONE,
NULL
};
__AA_CONST struct aa_format aa_irc_format =
{
70, 25,
70, 25,
0,
AA_NORMAL_MASK | AA_BOLD_MASK | AA_REVERSE_MASK,
&aa_font16,
"For catting to an IRC channel",
".irc",
"",
"",
"\n",
NORMALPRINTS,
{"",
"",
"",
"",
""
},
{"",
"",
"",
"",
""
},
NULL
};
__AA_CONST struct aa_format aa_zephyr_format =
{
70, 25,
70, 25,
0,
AA_NORMAL_MASK | AA_DIM_MASK | AA_BOLD_MASK,
&aa_font16,
"For catting to an IRC channel II",
".irc",
"",
"",
"\n",
NORMALPRINTS,
{"",
"@color(gray50)",
"@b(",
"",
""
},
{"",
"@color(black)",
")",
"",
""
},
irc_escapes
};
__AA_CONST struct aa_format aa_roff_format =
{
70, 25,
70, 25,
0,
AA_NORMAL_MASK | AA_BOLD_MASK,
&aa_font16,
"For including in a man page",
".man",
"",
"",
"\n.br\n",
NORMALPRINTS,
{"",
"",
"\\fB",
"",
""
},
{"",
"",
"\\fP",
"",
""
},
irc_escapes
};
__AA_CONST struct aa_format aa_html_alt_format =
{
79, 25,
79, 25,
0,
AA_NORMAL_MASK,
NULL,
"HTML <IMG ALT= tag",
".html",
/* Need that newline, because lynx inserts a space, thus shifting
* the first line of our art. */
"<PRE><IMG SRC=\"your image here\" ALT=\"\n",
"\"></PRE>\n",
"\n",
NORMALPRINTS,
{"",
"",
"",
"",
""
},
{"",
"",
"",
"",
""
},
html_alt_escapes
};
__AA_CONST struct aa_format * __AA_CONST aa_formats[] =
{
#ifdef VYHEN_SUPPORT
&aa_vyhen_format,
#endif
&aa_text_format,
&aa_html_format,
&aa_nhtml_format,
&aa_html_alt_format,
&aa_more_format,
&aa_ansi_format,
&aa_hp_format,
&aa_hp2_format,
&aa_irc_format,
&aa_zephyr_format,
&aa_roff_format,
NULL
};
__AA_CONST struct aa_driver save_d;
#define FORMAT ((struct aa_savedata *)c->driverdata)->format
#define DATA ((struct aa_savedata *)c->driverdata)
__AA_CONST static char **build_conversions(__AA_CONST char * __AA_CONST *in, __AA_CONST char **conv)
{
unsigned char c;
memset(conv, 0, sizeof(char *) * 256);
if (in != NULL)
while (*in != NULL && *(in + 1) != NULL) {
c = **in;
in++;
conv[c] = *in;
in++;
}
return conv;
}
static int save_init(__AA_CONST struct aa_hardware_params *p, __AA_CONST void *none,
struct aa_hardware_params *dest, void **data)
{
__AA_CONST struct aa_savedata *d = (__AA_CONST struct aa_savedata *) none;
static struct aa_hardware_params def;
*data = (void *) malloc(sizeof(struct aa_savedata));
memcpy(*data, d, sizeof(struct aa_savedata));
*dest = def;
if (p->font == NULL)
dest->font = d->format->font;
dest->width = d->format->width;
dest->height = d->format->height;
dest->supported = d->format->supported;
return 1;
}
static void save_uninit(aa_context * c)
{
}
static void save_getsize(aa_context * c, int *width, int *height)
{
}
static void save_gotoxy(aa_context * c, int x, int y)
{
}
static int lastattr;
static FILE *f;
static aa_context *c;
static void stop_tag(void)
{
if (lastattr != -1)
fputs(FORMAT->ends[lastattr], f);
lastattr = -1;
}
static void start_tag(int attr)
{
if (attr > AA_NATTRS)
attr = AA_NATTRS;
lastattr = attr;
fputs(FORMAT->begin[lastattr], f);
}
static void encodechar(unsigned char attr, unsigned char ch, __AA_CONST char **conversions)
{
char chr[2];
if (FORMAT->flags & AA_NORMAL_SPACES && ch == ' ' && (attr != AA_REVERSE))
attr = AA_NORMAL;
if (attr != lastattr) {
stop_tag();
start_tag(attr);
}
if (conversions[ch] == NULL) {
chr[0] = ch;
chr[1] = 0;
fprintf(f, FORMAT->prints[attr], chr, chr, chr, chr);
} else {
fprintf(f, FORMAT->prints[attr], conversions[ch], conversions[ch],
conversions[ch], conversions[ch]);
}
}
static void savearea(int x1, int y1, int x2, int y2, __AA_CONST char **conversions)
{
int x, y;
fputs(FORMAT->head, f);
lastattr = -1;
for (y = y1; y < y2; y++) {
for (x = x1; x < x2; x++) {
if (x < 0 || x >= aa_scrwidth(c) ||
y < 0 || y >= aa_scrheight(c))
encodechar(AA_NORMAL, ' ', conversions);
else {
int pos = x + y * aa_scrwidth(c);
encodechar(c->attrbuffer[pos], c->textbuffer[pos], conversions);
}
}
stop_tag();
fputs(FORMAT->newline, f);
}
fputs(FORMAT->end, f);
fflush(f);
}
static void save_flush(aa_context * c1)
{
char fname[4096];
__AA_CONST char *conversions[256];
c = c1;
build_conversions(FORMAT->conversions, conversions);
if (FORMAT->flags & AA_USE_PAGES) {
int xpages = (aa_scrwidth(c1) + FORMAT->pagewidth - 1) /
FORMAT->pagewidth;
int ypages = (aa_scrheight(c1) + FORMAT->pageheight - 1) /
FORMAT->pageheight;
int x, y;
for (x = 0; x < xpages; x++)
for (y = 0; y < ypages; y++) {
if (DATA->name != NULL) {
generate_filename(DATA->name, fname, x, y, 1, FORMAT->extension);
f = fopen(fname, "w");
} else
f = DATA->file;
if (f == NULL)
return;
savearea(x * FORMAT->pagewidth, y * FORMAT->pageheight,
(x + 1) * FORMAT->pagewidth,
(y + 1) * FORMAT->pageheight, conversions);
if (DATA->name != NULL)
fclose(f);
}
} else {
if (DATA->name != NULL) {
generate_filename(DATA->name, fname, 0, 0, 0, FORMAT->extension);
f = fopen(fname, "w");
} else
f = DATA->file;
if (f == NULL)
return;
savearea(0, 0, /*DATA->width, DATA->height */ aa_scrwidth(c1), aa_scrheight(c1), conversions);
if (DATA->name != NULL)
fclose(f);
}
}
/*
* Takes a template of the form blah%xfu%y.extension and will return
* either blah<x>fu<y>.extension or blahfu.extension depending on whether
* pages is true or not. %x and %y may be flipped, but may appear only once.
* If you want a % in the output, you'll have to use %%.
* Using %[^%xy] is not defined. The results are also undefined if you don't
* include both %x and %y.
*
* Rewrote by Jan Hubicka to accept unlimited (and zero) number of % stuff
* and %e for extension and %c for coordinates in format %x_%y.
* You might now add after filename simply %c%e to get filename
* blahX_Y.txt or blah.txt
* Also avoided memory owerflows.
*/
static char *generate_filename(__AA_CONST char *template, char *result, int x, int y, int pages, __AA_CONST char *extension)
{
char *a;
__AA_CONST char *b;
char *end = result + 4090;
b = template - 1, a = result - 1;
while ((*++a = *++b)) {
if (a >= end)
break; /*Too long filename - probably bug in caller,
since filenames longer than 4KB are useless :) */
if (*b == '%') {
switch (b[1]) {
case 'x':
a--;
if (pages) {
char text[8];
char *e = text - 1;
sprintf(text, "%i", x);
while ((*++a = *++e))
if (a >= end)
break;
a--;
}
b++;
break;
case 'y':
a--;
if (pages) {
char text[8];
char *e = text - 1;
sprintf(text, "%i", y);
while ((*++a = *++e))
if (a >= end)
break;
a--;
}
b++;
break;
case 'c':
a--;
if (pages) {
char text[8];
char *e = text - 1;
sprintf(text, "_%i_%i", x, y);
while ((*++a = *++e))
if (a >= end)
break;
a--;
}
b++;
break;
case 'e':
a--;
{
__AA_CONST char *e = extension - 1;
while ((*++a = *++e))
if (a >= end)
break;
a--;
}
b++;
break;
case '%':
a--;
b++;
break;
}
if (!*b)
break;
}
}
*a = 0;
return result;
}
__AA_CONST struct aa_driver save_d =
{
"save", "Special driver for saving to files",
save_init,
save_uninit,
save_getsize,
NULL,
NULL,
save_gotoxy,
save_flush,
};