gno/bin/less/charset.c

213 lines
3.6 KiB
C

/*
* Functions to define the character set
* and do things specific to the character set.
*/
#pragma noroot
#include "less.h"
#ifdef _ORCAC_
segment "LoadSegONE";
#endif
/*
* Predefined character sets,
* selected by the LESSCHARSET environment variable.
*/
struct charset {
char *name;
char *desc;
} charsets[] = {
{ "ascii", "8bcccbcc18b95.b" },
{ "latin1", "8bcccbcc18b95.33b." },
{ NULL }
};
#define IS_BINARY_CHAR 01
#define IS_CONTROL_CHAR 02
static char chardef[256];
static char *binfmt = "\\%o";
public int binattr = BLINK;
extern char *getenv(char *);
static void ichardef(char *s);
static int icharset(char *name);
/*
* Define a charset, given a description string.
* The string consists of 256 letters,
* one for each character in the charset.
* If the string is shorter than 256 letters, missing letters
* are taken to be identical to the last one.
* A decimal number followed by a letter is taken to be a
* repetition of the letter.
*
* Each letter is one of:
* . normal character
* b binary character
* c control character
*/
static void
ichardef(s)
char *s;
{
register char *cp;
register int n;
register char v;
n = 0;
cp = chardef;
while (*s != '\0')
{
switch (*s++)
{
case '.':
v = 0;
break;
case 'c':
v = IS_CONTROL_CHAR;
break;
case 'b':
v = IS_BINARY_CHAR|IS_CONTROL_CHAR;
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
n = (10 * n) + (s[-1] - '0');
continue;
default:
error("invalid chardef", NULL_PARG);
quit(1);
/*NOTREACHED*/
}
do
{
if (cp >= chardef + sizeof(chardef))
{
error("chardef longer than 256", NULL_PARG);
quit(1);
/*NOTREACHED*/
}
*cp++ = v;
} while (--n > 0);
n = 0;
}
while (cp < chardef + sizeof(chardef))
*cp++ = v;
}
/*
* Define a charset, given a charset name.
* The valid charset names are listed in the "charsets" array.
*/
static int
icharset(name)
register char *name;
{
register struct charset *p;
if (name == NULL || *name == '\0')
return (0);
for (p = charsets; p->name != NULL; p++)
{
if (strcmp(name, p->name) == 0)
{
ichardef(p->desc);
return (1);
}
}
error("invalid charset name", NULL_PARG);
quit(1);
/*NOTREACHED*/
}
/*
* Initialize charset data structures.
*/
public void
init_charset(void)
{
register char *s;
/*
* Try environment variable LESSCHARSET.
* If LESSCHARSET is not set, try LESSCHARDEF.
* If LESSCHARDEF is not set, default to "ascii" charset.
*/
s = getenv("LESSCHARSET");
if (icharset(s))
return;
s = getenv("LESSCHARDEF");
if (s != NULL && *s != '\0')
{
ichardef(s);
return;
}
(void) icharset("ascii");
s = getenv("LESSBINFMT");
if (s != NULL && *s != '\0')
{
if (*s == '*')
{
switch (s[1])
{
case 'd': binattr = BOLD; break;
case 'k': binattr = BLINK; break;
case 'u': binattr = UNDERLINE; break;
default: binattr = NORMAL; break;
}
s += 2;
}
if (*s != '\0')
binfmt = s;
}
}
/*
* Is a given character a "binary" character?
*/
public int
binary_char(c)
int c;
{
return (chardef[c] & IS_BINARY_CHAR);
}
/*
* Is a given character a "control" character?
*/
public int
control_char(c)
int c;
{
return (chardef[c] & IS_CONTROL_CHAR);
}
/*
* Return the printable form of a character.
* For example, in the "ascii" charset '\3' is printed as "^C".
*/
public char *
prchar(c)
int c;
{
static char buf[8];
if (!control_char(c))
sprintf(buf, "%c", c);
else if (!control_char(c ^ 0100))
sprintf(buf, "^%c", c ^ 0100);
else
sprintf(buf, binfmt, c);
return (buf);
}