home *** CD-ROM | disk | FTP | other *** search
- /*
- * 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 */
-