#include "textcommon.h"
int WrapLines = 1,
SizeLines = 60,
SizeColumns = 80,
PageColumns = 1,
ColumnGutter = 0,
ColumnWidth = 80,
PrettyPrint = 0,
Copies = 1;
lchar_t **Page = NULL;
int NumPages = 0;
float CharsPerInch = 10;
float LinesPerInch = 6;
int UTF8 = 0;
int NumKeywords = 0;
char **Keywords = NULL;
static char *code_keywords[] =
{
"and",
"and_eq",
"asm",
"auto",
"bitand",
"bitor",
"bool",
"break",
"case",
"catch",
"char",
"class",
"compl",
"const",
"const_cast",
"continue",
"default",
"delete",
"do",
"double",
"dynamic_cast",
"else",
"enum",
"explicit",
"extern",
"false",
"float",
"for",
"friend",
"goto",
"if",
"inline",
"int",
"long",
"mutable",
"namespace",
"new",
"not",
"not_eq",
"operator",
"or",
"or_eq",
"private",
"protected",
"public",
"register",
"reinterpret_cast",
"return",
"short",
"signed",
"sizeof",
"static",
"static_cast",
"struct",
"switch",
"template",
"this",
"throw",
"true",
"try",
"typedef",
"typename",
"union",
"unsigned",
"virtual",
"void",
"volatile",
"while",
"xor",
"xor_eq"
},
*sh_keywords[] =
{
"alias",
"bg",
"break",
"case",
"cd",
"command",
"continue",
"do",
"done",
"echo",
"elif",
"else",
"esac",
"eval",
"exec",
"exit",
"export",
"fc",
"fg",
"fi",
"for",
"function",
"getopts",
"if",
"in",
"jobs",
"kill",
"let",
"limit",
"newgrp",
"print",
"pwd",
"read",
"readonly",
"return",
"select",
"set",
"shift",
"test",
"then",
"time",
"times",
"trap",
"typeset",
"ulimit",
"umask",
"unalias",
"unlimit",
"unset",
"until",
"wait",
"whence"
"while",
},
*csh_keywords[] =
{
"alias",
"aliases",
"bg",
"bindkey",
"break",
"breaksw",
"builtins",
"case",
"cd",
"chdir",
"complete",
"continue",
"default",
"dirs",
"echo",
"echotc",
"else",
"end",
"endif",
"eval",
"exec",
"exit",
"fg",
"foreach",
"glob",
"goto",
"history",
"if",
"jobs",
"kill",
"limit",
"login",
"logout",
"ls",
"nice",
"nohup",
"notify",
"onintr",
"popd",
"pushd",
"pwd",
"rehash",
"repeat",
"set",
"setenv",
"settc",
"shift",
"source",
"stop",
"suspend",
"switch",
"telltc",
"then",
"time",
"umask",
"unalias",
"unbindkey",
"unhash",
"unlimit",
"unset",
"unsetenv",
"wait",
"where",
"which",
"while"
},
*perl_keywords[] =
{
"abs",
"accept",
"alarm",
"and",
"atan2",
"bind",
"binmode",
"bless",
"caller",
"chdir",
"chmod",
"chomp",
"chop",
"chown",
"chr",
"chroot",
"closdir",
"close",
"connect",
"continue",
"cos",
"crypt",
"dbmclose",
"dbmopen",
"defined",
"delete",
"die",
"do",
"dump",
"each",
"else",
"elsif",
"endgrent",
"endhostent",
"endnetent",
"endprotoent",
"endpwent",
"endservent",
"eof",
"eval",
"exec",
"exists",
"exit",
"exp",
"fcntl",
"fileno",
"flock",
"for",
"foreach",
"fork",
"format",
"formline",
"getc",
"getgrent",
"getgrgid",
"getgrnam",
"gethostbyaddr",
"gethostbyname",
"gethostent",
"getlogin",
"getnetbyaddr",
"getnetbyname",
"getnetent",
"getpeername",
"getpgrp",
"getppid",
"getpriority",
"getprotobyname",
"getprotobynumber",
"getprotoent",
"getpwent",
"getpwnam",
"getpwuid",
"getservbyname",
"getservbyport",
"getservent",
"getsockname",
"getsockopt",
"glob",
"gmtime",
"goto",
"grep",
"hex",
"if",
"import",
"index",
"int",
"ioctl",
"join",
"keys",
"kill",
"last",
"lc",
"lcfirst",
"length",
"link",
"listen",
"local",
"localtime",
"log",
"lstat",
"map",
"mkdir",
"msgctl",
"msgget",
"msgrcv",
"msgsend",
"my",
"next",
"no",
"not",
"oct",
"open",
"opendir",
"or",
"ord",
"pack",
"package",
"pipe",
"pop",
"pos",
"print",
"printf",
"push",
"quotemeta",
"rand",
"read",
"readdir",
"readlink",
"recv",
"redo",
"ref",
"rename",
"require",
"reset",
"return",
"reverse",
"rewinddir",
"rindex",
"rmdir",
"scalar",
"seek",
"seekdir",
"select",
"semctl",
"semget",
"semop",
"send",
"setgrent",
"sethostent",
"setnetent",
"setpgrp",
"setpriority",
"setprotoent",
"setpwent",
"setservent",
"setsockopt",
"shift",
"shmctl",
"shmget",
"shmread",
"shmwrite",
"shutdown",
"sin",
"sleep",
"socket",
"socketpair",
"sort",
"splice",
"split",
"sprintf",
"sqrt",
"srand",
"stat",
"study",
"sub",
"substr",
"symlink",
"syscall",
"sysread",
"sysseek",
"system",
"syswrite",
"tell",
"telldir",
"tie",
"tied",
"time",
"times"
"times",
"truncate",
"uc",
"ucfirst",
"umask",
"undef",
"unless",
"unlink",
"unpack",
"unshift",
"untie",
"until",
"use",
"utime",
"values",
"vec",
"wait",
"waitpid",
"wantarray",
"warn",
"while",
"write"
};
static int compare_keywords(const void *, const void *);
static int getutf8(FILE *fp);
int
TextMain(const char *name,
int argc,
char *argv[])
{
FILE *fp;
ppd_file_t *ppd;
int i,
ch,
lastch,
attr,
line,
column,
page_column;
int num_options;
cups_option_t *options;
const char *val;
char keyword[64],
*keyptr;
int keycol;
int ccomment;
int cstring;
setbuf(stderr, NULL);
if (argc < 6 || argc > 7)
{
fprintf(stderr, "ERROR: %s job-id user title copies options [file]\n",
name);
return (1);
}
if (argc == 6)
fp = stdin;
else
{
if ((fp = fopen(argv[6], "rb")) == NULL)
{
perror("ERROR: unable to open print file - ");
return (1);
}
}
options = NULL;
num_options = cupsParseOptions(argv[5], 0, &options);
if ((val = cupsGetOption("prettyprint", num_options, options)) != NULL &&
strcasecmp(val, "no") && strcasecmp(val, "off") &&
strcasecmp(val, "false"))
{
PageLeft = 72.0f;
PageRight = PageWidth - 36.0f;
PageBottom = PageBottom > 36.0f ? PageBottom : 36.0f;
PageTop = PageLength - 36.0f;
CharsPerInch = 12;
LinesPerInch = 8;
if ((val = getenv("CONTENT_TYPE")) == NULL)
{
PrettyPrint = PRETTY_CODE;
NumKeywords = sizeof(code_keywords) / sizeof(code_keywords[0]);
Keywords = code_keywords;
}
else if (strcasecmp(val, "application/x-cshell") == 0)
{
PrettyPrint = PRETTY_SHELL;
NumKeywords = sizeof(csh_keywords) / sizeof(csh_keywords[0]);
Keywords = csh_keywords;
}
else if (strcasecmp(val, "application/x-perl") == 0)
{
PrettyPrint = PRETTY_PERL;
NumKeywords = sizeof(perl_keywords) / sizeof(perl_keywords[0]);
Keywords = perl_keywords;
}
else if (strcasecmp(val, "application/x-shell") == 0)
{
PrettyPrint = PRETTY_SHELL;
NumKeywords = sizeof(sh_keywords) / sizeof(sh_keywords[0]);
Keywords = sh_keywords;
}
else
{
PrettyPrint = PRETTY_CODE;
NumKeywords = sizeof(code_keywords) / sizeof(code_keywords[0]);
Keywords = code_keywords;
}
}
ppd = SetCommonOptions(num_options, options, 1);
if ((val = cupsGetOption("wrap", num_options, options)) == NULL)
WrapLines = 1;
else
WrapLines = !strcasecmp(val, "true") || !strcasecmp(val, "on") ||
!strcasecmp(val, "yes");
if ((val = cupsGetOption("columns", num_options, options)) != NULL)
PageColumns = atoi(val);
if ((val = cupsGetOption("cpi", num_options, options)) != NULL)
CharsPerInch = atof(val);
if ((val = cupsGetOption("lpi", num_options, options)) != NULL)
LinesPerInch = atof(val);
if (PrettyPrint)
PageTop -= 216.0f / LinesPerInch;
Copies = atoi(argv[4]);
WriteProlog(argv[3], argv[2], getenv("CLASSIFICATION"),
cupsGetOption("page-label", num_options, options), ppd);
lastch = 0;
column = 0;
line = 0;
page_column = 0;
attr = 0;
keyptr = keyword;
keycol = 0;
ccomment = 0;
cstring = 0;
while ((ch = getutf8(fp)) >= 0)
{
switch (ch)
{
case 0x08 :
if (column > 0)
column --;
keyptr = keyword;
keycol = column;
break;
case 0x09 :
if (PrettyPrint && keyptr > keyword)
{
*keyptr = '\0';
keyptr = keyword;
if (bsearch(&keyptr, Keywords, NumKeywords, sizeof(char *),
compare_keywords))
{
i = page_column * (ColumnWidth + ColumnGutter);
while (keycol < column)
{
Page[line][keycol + i].attr |= ATTR_BOLD;
keycol ++;
}
}
}
column = (column + 8) & ~7;
if (column >= ColumnWidth && WrapLines)
{
line ++;
column = 0;
if (line >= SizeLines)
{
page_column ++;
line = 0;
if (page_column >= PageColumns)
{
WritePage();
page_column = 0;
}
}
}
keycol = column;
break;
case 0x0d :
#ifndef __APPLE__
column = 0;
break;
#else
{
int nextch;
if ((nextch = getc(fp)) != 0x0a)
ungetc(nextch, fp);
else
ch = nextch;
}
#endif
case 0x0a :
if (PrettyPrint && keyptr > keyword)
{
*keyptr = '\0';
keyptr = keyword;
if (bsearch(&keyptr, Keywords, NumKeywords, sizeof(char *),
compare_keywords))
{
i = page_column * (ColumnWidth + ColumnGutter);
while (keycol < column)
{
Page[line][keycol + i].attr |= ATTR_BOLD;
keycol ++;
}
}
}
line ++;
column = 0;
keycol = 0;
if (!ccomment && !cstring)
attr &= ~(ATTR_ITALIC | ATTR_BOLD | ATTR_RED | ATTR_GREEN | ATTR_BLUE);
if (line >= SizeLines)
{
page_column ++;
line = 0;
if (page_column >= PageColumns)
{
WritePage();
page_column = 0;
}
}
break;
case 0x0b :
if (line > 0)
line --;
keyptr = keyword;
keycol = column;
if (!ccomment && !cstring)
attr &= ~(ATTR_ITALIC | ATTR_BOLD | ATTR_RED | ATTR_GREEN | ATTR_BLUE);
break;
case 0x0c :
if (PrettyPrint && keyptr > keyword)
{
*keyptr = '\0';
keyptr = keyword;
if (bsearch(&keyptr, Keywords, NumKeywords, sizeof(char *),
compare_keywords))
{
i = page_column * (ColumnWidth + ColumnGutter);
while (keycol < column)
{
Page[line][keycol + i].attr |= ATTR_BOLD;
keycol ++;
}
}
}
page_column ++;
column = 0;
keycol = 0;
line = 0;
if (!ccomment && !cstring)
attr &= ~(ATTR_ITALIC | ATTR_BOLD | ATTR_RED | ATTR_GREEN | ATTR_BLUE);
if (page_column >= PageColumns)
{
WritePage();
page_column = 0;
}
break;
case 0x1b :
ch = getutf8(fp);
if (ch == '7')
{
if (line > 0)
line --;
}
else if (ch == '8')
{
if ((attr & ATTR_RAISED) && line > 0)
{
attr &= ~ATTR_RAISED;
line --;
}
else if (attr & ATTR_LOWERED)
attr &= ~ATTR_LOWERED;
else
attr |= ATTR_RAISED;
}
else if (ch == '9')
{
if ((attr & ATTR_LOWERED) && line < (SizeLines - 1))
{
attr &= ~ATTR_LOWERED;
line ++;
}
else if (attr & ATTR_RAISED)
attr &= ~ATTR_RAISED;
else
attr |= ATTR_LOWERED;
}
break;
default :
if (ch < ' ')
break;
if (PrettyPrint)
{
if ((ch == ' ' || ch == '\t') && (attr & ATTR_BOLD))
{
attr &= ~ATTR_BOLD;
}
else if (!(isalnum(ch & 255) || ch == '_') && keyptr > keyword)
{
*keyptr = '\0';
keyptr = keyword;
if (!(attr & ATTR_ITALIC) &&
bsearch(&keyptr, Keywords, NumKeywords, sizeof(char *),
compare_keywords))
{
i = page_column * (ColumnWidth + ColumnGutter);
while (keycol < column)
{
Page[line][keycol + i].attr |= ATTR_BOLD;
keycol ++;
}
}
}
else if ((isalnum(ch & 255) || ch == '_') && !ccomment && !cstring)
{
if (keyptr == keyword)
keycol = column;
if (keyptr < (keyword + sizeof(keyword) - 1))
*keyptr++ = ch;
}
else if (ch == '\"' && lastch != '\\' && !ccomment && !cstring)
{
cstring = -1;
attr |= ATTR_BLUE;
}
else if (ch == '*' && lastch == '/' && !cstring &&
PrettyPrint != PRETTY_SHELL)
{
ccomment = 1;
attr |= ATTR_ITALIC | ATTR_GREEN;
}
else if (ch == '/' && lastch == '/' && !cstring &&
PrettyPrint == PRETTY_CODE)
{
attr |= ATTR_ITALIC | ATTR_GREEN;
}
else if (ch == '#' && !cstring && PrettyPrint != PRETTY_CODE)
{
attr |= ATTR_ITALIC | ATTR_GREEN;
}
else if (ch == '#' && column == 0 && !ccomment && !cstring &&
PrettyPrint == PRETTY_CODE)
{
attr |= ATTR_BOLD | ATTR_RED;
}
}
if (column >= ColumnWidth && WrapLines)
{
column = 0;
line ++;
if (line >= SizeLines)
{
page_column ++;
line = 0;
if (page_column >= PageColumns)
{
WritePage();
page_column = 0;
}
}
}
if (column < ColumnWidth)
{
i = column + page_column * (ColumnWidth + ColumnGutter);
if (PrettyPrint)
Page[line][i].attr = attr;
else if (ch == ' ' && Page[line][i].ch)
ch = Page[line][i].ch;
else if (ch == Page[line][i].ch)
Page[line][i].attr |= ATTR_BOLD;
else if (Page[line][i].ch == '_')
Page[line][i].attr |= ATTR_UNDERLINE;
else if (ch == '_')
{
Page[line][i].attr |= ATTR_UNDERLINE;
if (Page[line][i].ch)
ch = Page[line][i].ch;
}
else
Page[line][i].attr = attr;
Page[line][i].ch = ch;
}
if (PrettyPrint)
{
if ((ch == '{' || ch == '}') && !ccomment && !cstring &&
column < ColumnWidth)
{
Page[line][column].attr |= ATTR_BOLD;
}
else if ((ch == '/' || ch == '*') && lastch == '/' &&
column < ColumnWidth && PrettyPrint != PRETTY_SHELL)
{
Page[line][column - 1].attr = attr;
}
else if (ch == '\"' && lastch != '\\' && !ccomment && cstring > 0)
{
cstring = 0;
attr &= ~ATTR_BLUE;
}
else if (ch == '/' && lastch == '*' && ccomment)
{
ccomment = 0;
attr &= ~(ATTR_ITALIC | ATTR_GREEN);
}
if (cstring < 0)
cstring = 1;
}
column ++;
break;
}
lastch = ch;
}
if (line > 0 || page_column > 0 || column > 0)
WritePage();
WriteEpilogue();
if (ppd != NULL)
ppdClose(ppd);
return (0);
}
static int
compare_keywords(const void *k1,
const void *k2)
{
return (strcmp(*((const char **)k1), *((const char **)k2)));
}
static int
getutf8(FILE *fp)
{
int ch;
int next;
if ((ch = getc(fp)) == EOF)
return (EOF);
if (ch < 0xc0 || !UTF8)
return (ch);
else if ((ch & 0xe0) == 0xc0)
{
if ((next = getc(fp)) == EOF)
return (EOF);
else
return (((ch & 0x1f) << 6) | (next & 0x3f));
}
else if ((ch & 0xf0) == 0xe0)
{
if ((next = getc(fp)) == EOF)
return (EOF);
ch = ((ch & 0x0f) << 6) | (next & 0x3f);
if ((next = getc(fp)) == EOF)
return (EOF);
else
return ((ch << 6) | (next & 0x3f));
}
else
{
return (EOF);
}
}