home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Boot Disc 8
/
boot-disc-1997-04.iso
/
PDA_Soft
/
Psion
/
comms
/
p3nfs
/
nfsc
/
vt100.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-05-26
|
22KB
|
1,023 lines
/*
* vt100 emulator for p3nfs
* Rudolf Koenig, Michael Schroeder
* 5.1.1996
* Copyright GNU Public License
*/
#include <p_serial.h> /* set.P_SRCHAR */
#include <plib.h> /* P_FTEXT & co */
#include <wlib.h> /* WMSG_KEY */
#include "nfsc.h" /* set */
#ifdef HAVE_TERMEMU
P_RECT ttyrect; /* Scroll region */
W_CURSOR wc;
#define MAXARGS 10
#define MAXLINE 80 /* Longest line possible */
static WORD c_x, c_y, l_x, l_y;
static char sbuf[MAXLINE], bufoff, isbold; /* Speedup buffer */
static UINT clearmode;
#define E_NORMAL 255
#define E_ESCAPE 254
#define E_WRAP_MODE 0x01
#define E_ORIGIN_MODE 0x02
#define E_INSERT_MODE 0x04
#define E_ISINVERTED 0x08
static unsigned char
e_args[MAXARGS], /* Escape seq. arguments */
e_state = E_NORMAL, /* escape state machine */
e_interm, /* Intermediate character (?*..) */
e_flags, /* WRAP_MODE & co */
e_gstyle, /* Bold * co */
e_gflags, /* gray plane */
tabs[MAXLINE + 1];
static unsigned char altchar[0x20] = {
0x20,
0x04,0xb1,0x12,0x12,0x12,0x12,0xf8,0xf1,
0x12,0x12,0xd9,0xbf,0xda,0xc0,0xc5,0xc4,
0xc4,0xc4,0xc4,0xc4,0xc3,0xb4,0xc1,0xc2,
0xb3,0x11,0x10,0xf4,0xce,0x9c,0xfa
};
static unsigned char gl, font, charsets[4];
GLREF_C VOID Reset(void)
{
int i;
G_GC gc;
for(i = 0; i < MAXLINE; i++) /* Reset the tabs */
tabs[i] = i && (i & 7) == 0;
c_x = 0;
c_y = ascent;
bufoff = 0;
e_state = E_NORMAL;
e_flags = E_WRAP_MODE;
clearmode = G_TRMODE_CLR;
cur_appl = 0;
gl = 0;
font = charsets[0] = charsets[1] = charsets[2] = charsets[3] = 'B';
isbold = 0;
e_gstyle = G_STY_MONO; /* monospaced fonts, please */
e_gflags = G_GC_FLAG_BOTH_PLANES;
gc.style = e_gstyle;
gc.flags = e_gflags;
gSetGC(hgc, G_GC_MASK_STYLE|G_GC_MASK_GREY, &gc);
ttyrect.tl.x = 0;
ttyrect.tl.y = 0;
ttyrect.br.x = t_w;
ttyrect.br.y = t_h;
wc.width = charwidth; /* Cursor */
wc.height = charheight;
wc.ascent = ascent;
wc.pos.x = c_x;
wc.pos.y = c_y;
wTextCursor(main_win, &wc);
}
#define C_EOD 0
#define C_BOD 1
#define C_D 2
#define C_EOL 3
#define C_BOL 4
#define C_L 5
static void
clear(int n)
{
P_RECT pr;
switch(n)
{
/*----------------------------------------------- clear to end of page */
case C_EOD:
if(c_y + charheight < t_h) /* clear but the line itself */
{
pr.tl.x = 0;
pr.tl.y = c_y - ascent + charheight;
pr.br.x = t_w;
pr.br.y = t_h;
gClrRect(&pr, clearmode);
}
/*------------------------------------------------------- clear to eol */
case C_EOL:
pr.tl.x = c_x;
pr.tl.y = c_y - ascent;
pr.br.x = t_w;
pr.br.y = pr.tl.y + charheight;
gClrRect(&pr, clearmode);
break;
/*------------------------------------- clear to beginning of the page */
case C_BOD:
if(c_y > ascent) /* clear but the line itself */
{
pr.tl.x = 0;
pr.tl.y = 0;
pr.br.x = t_w;
pr.br.y = c_y - ascent;
gClrRect(&pr, clearmode);
}
/*------------------------------------- clear to beginning of the line */
case C_BOL:
if(c_x > 0)
{
pr.tl.x = 0;
pr.tl.y = c_y - ascent;
pr.br.x = c_x + charwidth;
pr.br.y = c_y - ascent + charheight;
gClrRect(&pr, clearmode);
}
break;
/*---------------------------------------------- clear the whole screen */
case C_D:
pr.tl.x = pr.tl.y = 0;
pr.br.x = t_w;
pr.br.y = t_h;
gClrRect(&pr, clearmode);
break;
/*---------------------------------------------- clear the whole line */
case C_L:
pr.tl.x = 0;
pr.tl.y = c_y - ascent;
pr.br.x = t_w;
pr.br.y = pr.tl.y + charheight;
gClrRect(&pr, clearmode);
break;
}
}
/* Scroll horizontally, using the ttyrect */
static void
h_scroll(int right, int pixel, int doclear)
{
P_RECT r;
P_POINT o;
r.tl.x = c_x;
r.tl.y = c_y - ascent;
r.br.y = r.tl.y + charheight;
r.br.x = t_w;
o.y = 0;
if(right)
{
o.x = pixel;
r.br.x -= pixel;
wScrollRect(main_win, &r, &o);
r.br.x = r.tl.x + pixel;
}
else
{
o.x = -pixel;
r.tl.x += pixel;
wScrollRect(main_win, &r, &o);
r.tl.x = r.br.x - pixel;
}
if(doclear)
gClrRect(&r, clearmode);
}
/* It works only within the scroll region (ttyrect) */
static void
v_scroll(int down, int pixel)
{
P_POINT o;
int i;
if(down)
{
i = ttyrect.br.y;
o.y = pixel;
o.x = 0;
ttyrect.br.y -= pixel;
wScrollRect(main_win, &ttyrect, &o);
ttyrect.br.y = ttyrect.tl.y + pixel;
gClrRect(&ttyrect, clearmode);
ttyrect.br.y = i;
}
else
{
i = ttyrect.tl.y;
o.y = -pixel;
o.x = 0;
ttyrect.tl.y += pixel;
wScrollRect(main_win, &ttyrect, &o);
ttyrect.tl.y = ttyrect.br.y - pixel;
gClrRect(&ttyrect, clearmode);
ttyrect.tl.y = i;
}
}
static void
nl(void)
{
if(c_y + charheight > ttyrect.br.y)
{
if(c_y < ttyrect.br.y)
v_scroll(0, charheight);
}
else
c_y += charheight;
}
static void
flsbuf(void)
{
int dx;
if(bufoff == 0)
return;
dx = bufoff * charwidth;
c_x -= dx;
if(e_flags & E_INSERT_MODE)
h_scroll(1, dx, 0);
gPrintText(c_x, c_y, sbuf, bufoff);
c_x += dx;
bufoff = 0;
}
static void
put(unsigned char ch)
{
int i, n;
char lbuf[32];
int a0, a1;
int nargs;
if(e_state == E_NORMAL)
{
if(ch >= ' ')
{
if(c_x >= t_w) /* last column printable */
{
if(e_flags & E_WRAP_MODE)
{
flsbuf();
nl();
c_x = 0;
}
else
{
c_x = t_w - charwidth;
if (bufoff > 0)
bufoff--;
}
}
if(ch > 127)
ch = iso2cp(ch);
switch (font)
{
case 'A':
if (ch == '#')
ch = 0x9c;
break;
case '0':
if (ch >= 0x5f && ch <= 0x7e)
ch = altchar[ch - 0x5f];
break;
default:
break;
}
sbuf[bufoff++] = ch;
/* We can't write bold characters buffered, as they are
1 Pixel wider and we NEED a monospaced font */
c_x += charwidth;
if(isbold)
flsbuf();
return;
}
flsbuf();
/* hack: normalize c_x for nowrap mode */
if (!(e_flags & E_WRAP_MODE) && c_x >= t_w)
c_x = t_w - charwidth;
switch(ch)
{
case 7: /* Bell*/
p_sound(5, 320);
break;
case '\b': /* BackSpace */
if(c_x > 0)
c_x -= charwidth;
return;
case '\t':
n = c_x / charwidth; /* current column */
if (n >= cols) /* curses bug workaround */
{
nl();
n = 0;
}
n++;
while (!tabs[n] && n < cols - 1)
n++;
c_x = n * charwidth;
return;
case '\n':
nl();
return;
case '\r':
c_x = 0;
return;
case 0x1b: /* Escape */
e_state = E_ESCAPE;
e_interm = 0;
return;
case 0x0e: /* C-n */
case 0x0f: /* C-o */
font = charsets[gl = 0x0f - ch];
break;
default:
break;
}
return;
}
if(ch < ' ') /* that's the way a vt100 does it */
{
int oldstate = e_state;
e_state = E_NORMAL;
put(ch);
if (e_state != E_ESCAPE)
e_state = oldstate;
return;
}
if(e_state == E_ESCAPE) /* first character after escape */
{
if(ch <= '/')
{
e_interm = e_interm ? -1 : ch;
return;
}
switch (e_interm)
{
case 0:
switch(ch)
{
case 'E': /* CR/NL */
nl();
c_x = 0;
return;
case 'D': /* Scroll down */
nl();
break;
case 'M': /* Scroll up */
if(c_y - charheight < ttyrect.tl.y)
{
if(c_y > ttyrect.tl.y)
v_scroll(1, charheight);
}
else
c_y -= charheight;
break;
case 'H':
n = c_x/charwidth; /* current column */
tabs[n] = 1;
break;
case 'Z':
p_atos(lbuf, "\033[?1;2c");
P_WRITE(serial, lbuf, p_slen(lbuf));
break;
case '7': /* save cursor position */
l_x = c_x; l_y = c_y;
break;
case '8': /* restore cursor */
c_x = l_x; c_y = l_y;
break;
case 'c': /* Reset */
clear(2);
Reset();
break;;
case '[': /* the longer ones */
e_state = 0;
e_interm = 0;
e_args[0] = e_args[1] = 0;
return;
case 'n':
case 'o':
font = charsets[gl = ch - ('n' - 2)];
return;
default:
break;
}
break;
case '#':
if (ch == '8') /* fill with 'E' */
{
for (i = 0; i < cols; i++)
sbuf[i] = 'E';
for (i = 0; i < rows; i++)
gPrintText(0, i * charheight + ascent, sbuf, cols);
}
break;
case '(':
case ')':
case '*':
case '+':
charsets[e_interm - '('] = ch;
font = charsets[gl];
break;
default:
break;
}
e_state = E_NORMAL;
return;
}
/* e_state >= 0 : longer escape sequences */
if(ch >= '0' && ch <= '9') /* Arguments */
{
if(e_state < MAXARGS)
e_args[e_state] = e_args[e_state] * 10 + (ch - '0');
return;
}
if(ch == ';' || ch == ':')
{
e_state++;
if(e_state < MAXARGS)
e_args[e_state] = 0;
return;
}
if(ch <= 0x3f) /* Intermediate */
{
e_interm = e_interm ? -1 : ch;
return;
}
nargs = e_state + 1;
if (nargs >= MAXARGS)
nargs = MAXARGS;
a0 = e_args[0];
if (a0 == 0)
a0++;
a1 = e_args[1];
if (a1 == 0)
a1++;
e_state = E_NORMAL; /* Last character in sequence */
switch (e_interm)
{
case 0:
switch(ch)
{
case 's': /* save cursor position */
l_x = c_x; l_y = c_y;
break;
case '8': /* restore cursor */
c_x = l_x; c_y = l_y;
break;
case 'H': /* Cursor movement */
case 'f':
c_y = (a0 - 1) * charheight;
c_x = (a1 - 1) * charwidth;
if(e_flags & E_ORIGIN_MODE)
{
if(c_y > ttyrect.br.y - charheight) c_y = ttyrect.br.y - charheight;
if(c_x > ttyrect.br.x - charwidth) c_x = ttyrect.br.x - charwidth;
c_y += ttyrect.tl.y;
c_x += ttyrect.tl.x;
}
else
{
if(c_y > t_h - charheight) c_y = t_h - charheight;
if(c_x > t_w - charwidth) c_x = t_w - charwidth;
}
c_y += ascent;
return;
case 'J': /* Clear Display*/
if(e_args[0] < 3)
clear(e_args[0]);
return;
case 'K': /* Clear Line */
if(e_args[0] < 3)
clear(e_args[0] + 3);
return;
case 'A': /* Up / don't scroll */
if(c_y > ttyrect.tl.y) /* Damn scroll region */
{
c_y -= a0 * charheight;
if(c_y < ttyrect.tl.y)
c_y = ttyrect.tl.y + ascent;
}
else
{
c_y -= a0 * charheight;
if(c_y < 0)
c_y = ascent;
}
return;
case 'B': /* Down / don't scroll*/
if(c_y < ttyrect.br.y)
{
c_y += a0 * charheight;
if(c_y >= ttyrect.br.y)
c_y = ttyrect.br.y - charheight + ascent;
}
else
{
c_y += a0 * charheight;
if(c_y >= t_h)
c_y = t_h - charheight + ascent;
}
return;
case 'C': /* Right */
c_x += a0 * charwidth;
if(c_x >= t_w)
c_x = t_w - charwidth;
return;
case 'D': /* Left */
c_x -= a0 * charwidth;
if(c_x < 0)
c_x = 0;
return;
case 'm': /* Attributes */
{
G_GC gc;
for(i = 0; i < nargs; i++)
switch(e_args[i])
{
case 0: e_gstyle = G_STY_MONO;
e_gflags = G_GC_FLAG_BOTH_PLANES;
isbold = 0;
break;
case 1: e_gstyle |= G_STY_BOLD; isbold = 1; break;
case 2: e_gflags = G_GC_FLAG_GREY_PLANE; break;
case 3: e_gstyle |= G_STY_ITALIC; break;
case 4: e_gstyle |= G_STY_UNDERLINE; break;
case 5: /* Blinking */
case 7: e_gstyle |= G_STY_INVERSE; break;
case 22: e_gflags = G_GC_FLAG_BOTH_PLANES; break;
case 23: e_gstyle &= ~G_STY_ITALIC; break;
case 24: e_gstyle &= ~G_STY_UNDERLINE; break;
case 25: /* Not Blinking */
case 27: e_gstyle &= ~G_STY_INVERSE; break;
default: break;
}
gc.style = e_flags & E_ISINVERTED ? e_gstyle ^ G_STY_INVERSE
: e_gstyle;
gc.flags = e_gflags;
gSetGC(hgc, G_GC_MASK_STYLE|G_GC_MASK_GREY, &gc);
}
case 'g': /* Tab clear */
if(e_args[0] == 3)
for(i = 0; i < MAXLINE; i++) /* Clear all the tabs */
tabs[i] = 0;
if(e_args[0] == 0)
tabs[c_x / charwidth] = 0;
break;
case 'r': /* Scroll region */
i = (a0 - 1) * charheight;
n = a1 * charheight;
for(i = 0; i < nargs; i++) /* Reset region ? */
if(e_args[i] != 0)
break;
if(i == nargs) /* Yes */
n = t_w;
if(i > t_h) i = t_h;
if(n > t_h) n = t_h;
if(i >= n)
return;
ttyrect.tl.y = i;
ttyrect.br.y = n;
c_x = 0;
c_y = ascent;
if (e_flags & E_ORIGIN_MODE)
{
c_y += ttyrect.tl.y;
c_x += ttyrect.tl.x;
}
return;
case 'I': /* Forward tabs */
while (a0-- > 0)
put('\t');
return;
case 'Z': /* Backward tabs */
n = c_x / charwidth; /* current column */
while (a0-- > 0)
{
if (n > 0)
n--;
while (!tabs[n] && n > 0)
n--;
}
c_x = n * charwidth;
return;
case 'M': /* delete lines (scroll up) */
case 'L': /* Insert lines (scroll down) */
if(c_y > ttyrect.br.y || c_y < ttyrect.tl.y)
return; /* not in scroll region */
n = ttyrect.tl.y;
ttyrect.tl.y = c_y - ascent;
i = a0 * charheight;
if(ttyrect.tl.y + i > ttyrect.br.y)
i = ttyrect.br.y - ttyrect.tl.y;
v_scroll(ch == 'M' ? 0 : 1, i);
ttyrect.tl.y = n;
break;
case 'P': /* delete characters (scroll left) */
case '@': /* Insert characters (scroll right) */
if(c_x > t_w)
return;
i = a0 * charwidth;
if(c_x + i > t_w)
i = t_w - c_x;
h_scroll(ch == 'P' ? 0 : 1, i, 1);
break;
case 'h': /* Set Mode */
case 'l': /* Reset Mode */
for(i = 0; i < nargs; i++)
{
switch(e_args[i])
{
case 4:
e_flags &= ~E_INSERT_MODE;
if (ch == 'h')
e_flags |= E_INSERT_MODE;
break;
default:
break;
}
}
return;
case 'c':
if (e_args[0] == 0)
{
p_atos(lbuf, "\033[?1;2c");
P_WRITE(serial, lbuf, p_slen(lbuf));
}
return;
case 'n':
if(a0 == 5) /* terminal status */
{
p_atos(lbuf, "\033[0n");
P_WRITE(serial, lbuf, p_slen(lbuf));
}
if(a0 == 6) /* get position / resize needs it */
{
p_atos(lbuf, "\033[%d;%dR",
(c_y-ascent) / charheight + 1, c_x / charwidth + 1);
P_WRITE(serial, lbuf, p_slen(lbuf));
}
return;
case 'x': /* decreqtparm */
/*
* Response CSI sol; par; nbits; xspeed; rspeed; clkmul; flags x
* DECREPTPARM Report of terminal parameters
* sol
* 0 terminal can send unsolicited reports, supported as sol = 1
* 1 terminal reports only on request
* 2 this is a report (DECREPTPARM)
* 3 terminal reporting only on request
* par = 1 none, 2 space, 3 mark, 4 odd, 5 even
* nbits = 1 (8 bits/char), 2 (7 bits/char)
* xspeed, rspeed = transmit and receive speed index:
* 0,8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,128 correspond to speeds of
* 50,75,110,134.5,150,200,300,600,1200,1800,2000,2400,3600,4800,9600,19200,
* clkmul = 1 (clock rate multiplier is 16)
* flags = 0-15 (Setup Block #5), always 0 here
*/
if (a0 == 1)
{
/* Convert baudrate */
a0 = set.tty.tbaud - 1;
if(a0 >= P_BAUD_300 && a0 < P_BAUD_7200)
a0++;
a0 *= 8;
p_atos(lbuf, "\033[%d;%d;%d;%d;%d;1;0x",
e_args[0] + 2,
(set.tty.frame & P_PARITY) ? 6 - set.tty.parity : 0,
4 - (set.tty.frame & P_DATA_FRM),
a0, a0);
P_WRITE(serial, lbuf, p_slen(lbuf));
}
return;
default:
break;
}
break;
case '?': /* DEC private */
switch(ch)
{
case 'h':
case 'l':
for(i = 0; i < nargs; i++)
{
switch(e_args[i])
{
case 1:
cur_appl = ch == 'h';
break;
case 5:
if((ch == 'h' && !(e_flags & E_ISINVERTED)) ||
(ch == 'l' && (e_flags & E_ISINVERTED)))
{
G_GC gc;
P_RECT p;
p.tl.x = 0; p.tl.y = 0;
p.br.x = t_w; p.br.y = t_h;
gClrRect(&p, G_TRMODE_INV);
e_flags ^= E_ISINVERTED;
gc.style = e_gstyle;
if (e_flags & E_ISINVERTED)
{
gc.style ^= G_STY_INVERSE;
clearmode = G_TRMODE_SET;
}
else
clearmode = G_TRMODE_CLR;
gSetGC(hgc, G_GC_MASK_STYLE, &gc);
}
break;
case 6:
e_flags &= ~E_ORIGIN_MODE;
if (ch == 'h')
e_flags |= E_ORIGIN_MODE;
c_x = 0;
c_y = ascent;
if (e_flags & E_ORIGIN_MODE)
{
c_y += ttyrect.tl.y;
c_x += ttyrect.tl.x;
}
break;
case 7:
e_flags &= ~E_WRAP_MODE;
if (ch == 'h')
e_flags |= E_WRAP_MODE;
break;
}
}
break;
default:
break;
}
break;
case '>':
if (ch == 'c' && e_args[0] == 0)
{
p_atos(lbuf, "\033[>%d;%d;0c", 'P', VERSION);
P_WRITE(serial, lbuf, p_slen(lbuf));
}
break;
default:
break;
}
}
GLDEF_C VOID TtyEmu(unsigned char *buf, INT len)
{
extern void *logfd;
if(logfd) /* Log into the file */
p_write(logfd, buf, len);
while(len-- > 0)
{
if(debug)
{
char mfb[6];
if(*buf >=' ' && *buf < 0x80)
AddToHistory(*buf);
else
{
p_atos(mfb, "%02x", *buf);
AddToHistory('\\');
AddToHistory(mfb[0]);
AddToHistory(mfb[1]);
}
}
/* Last line in scroll region && Jumpscroll */
if(*buf == '\n' && (set.flags & FLAGS_JUMPSCROLL) &&
c_y + charheight > ttyrect.br.y && c_y < ttyrect.br.y)
{
int i, n;
n = 1;
for(i = 1; i < len; i++)
if(buf[i] < ' ')
{
if(buf[i] == '\n')
n++;
else if(buf[i] != '\r')
break;
}
if(n >= rows)
{
c_y = ascent;
clear(C_D);
}
else if(n > 1)
{
v_scroll(0, n*charheight);
c_y -= n * charheight;
}
}
put(*buf++);
}
flsbuf();
wc.pos.x = c_x; wc.pos.y = c_y;
if(c_x >= t_w) /* last column printable */
wc.pos.x = t_w - charwidth;
wTextCursor(main_win, &wc);
wFlush();
}
void
AddFnKey(key, modifier, str)
int key;
int modifier;
char *str;
{
extern struct fkey *fk;
struct fkey **fp, *f;
char *s;
int l;
for(fp = &fk; *fp; fp = &(*fp)->next)
if((*fp)->key == key && (*fp)->modifier == modifier)
break;
l = *str + sizeof(struct fkey) + 1;
if((f = (struct fkey *)p_realloc(*fp, l)) == 0)
{
extern char c_nomem[];
wInfoMsgCorner(c_nomem, W_CORNER_BOTTOM_RIGHT);
return;
}
f->key = key;
f->modifier = modifier;
if(!*fp)
f->next = 0;
s = (char *)f + sizeof(struct fkey);
p_bcpy(s, str+1, *str);
s[*str] = 0;
*fp = f;
}
/*
* Parse \<nnn> and \s<nn>
* NOTE: \<nn> and \<n> are also accepted.
*/
void
SendFnKey(f)
struct fkey *f;
{
char *s;
unsigned char n;
#define isnum(s) s >= '0' && s <= '9'
for(s = (char *)f + sizeof(struct fkey); *s; s++)
{
if(*s == '\\')
{
if(s[1] == 's') /* sleep */
{
s++; n = 0;
if(isnum(s[1])) { s++; n = s[0] - '0'; }
if(isnum(s[1])) { s++; n = n * 10 + s[0] - '0'; }
p_sleep((ULONG)n);
continue;
}
else if(isnum(s[1]))
{
s++; n = s[0] - '0';
if(isnum(s[1])) { s++; n = n * 10 + s[0] - '0'; }
if(isnum(s[1])) { s++; n = n * 10 + s[0] - '0'; }
}
else if(s[1] == 0) /* \somenthing or */
break;
else
n = *s++;
}
else
n = *s;
P_WRITE(serial, (char *)&n, 1);
}
}
char cant_open_the_file[] = "Can't open the file";
#define BLEN 128
void
LoadFnKey(fname, warn)
char *fname;
int warn;
{
VOID *fcb;
char buf[BLEN], *p;
extern struct fkey *fk;
struct fkey **fp, *f;
int len;
UWORD key, modifier;
/* First delete all definitions */
for(fp = &fk, f = fk; *fp; f = *fp)
{
*fp = f->next;
p_free(f);
}
fname[*fname+1] = 0;
if(p_open(&fcb, fname+1, P_FTEXT | P_FSHARE))
{
if(warn)
wInfoMsgCorner(cant_open_the_file, W_CORNER_BOTTOM_RIGHT);
return;
}
while((len = p_read(fcb, buf, BLEN)) > 0)
{
if(*buf == '#') /* Allow comments */
continue;
p = buf; p_stog(&p, &key, 16);
p = buf+5; p_stog(&p, &modifier, 16);
p = buf+7; *p = len - 8;
AddFnKey(key, modifier, p);
}
p_close(fcb);
if(warn)
wInfoMsgCorner("Definition loaded", W_CORNER_BOTTOM_RIGHT);
return;
}
void
SaveFnKey(fname)
char *fname;
{
VOID *fcb;
char buf[BLEN];
extern struct fkey *fk;
struct fkey *f;
fname[*fname+1] = 0;
if(p_open(&fcb, fname+1, P_FTEXT | P_FREPLACE | P_FUPDATE))
{
wInfoMsgCorner(cant_open_the_file, W_CORNER_BOTTOM_RIGHT);
return;
}
p_atos(buf, "# Key(Hex) Modifier(Hex) String");
p_write(fcb, buf, p_slen(buf));
for(f = fk; f; f = f->next)
{
p_atos(buf, "%04x %02x %s", f->key, f->modifier, (char *)f+sizeof(*f));
p_write(fcb, buf, p_slen(buf));
}
p_close(fcb);
wInfoMsgCorner("Definition saved", W_CORNER_BOTTOM_RIGHT);
return;
}
#endif /* HAVE_TERMEMU */