summaryrefslogtreecommitdiff
path: root/src/fe-text
diff options
context:
space:
mode:
Diffstat (limited to 'src/fe-text')
-rw-r--r--src/fe-text/Makefile.am22
-rw-r--r--src/fe-text/term-curses.c415
-rw-r--r--src/fe-text/terminfo-core.c23
-rw-r--r--src/fe-text/tparm.c740
4 files changed, 2 insertions, 1198 deletions
diff --git a/src/fe-text/Makefile.am b/src/fe-text/Makefile.am
index b9538e60..847df150 100644
--- a/src/fe-text/Makefile.am
+++ b/src/fe-text/Makefile.am
@@ -4,8 +4,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src \
-I$(top_srcdir)/src/core/ \
-I$(top_srcdir)/src/fe-common/core/ \
- $(GLIB_CFLAGS) \
- $(CURSES_INCLUDEDIR)
+ $(GLIB_CFLAGS)
irssi_DEPENDENCIES = \
@COMMON_LIBS@ \
@@ -22,25 +21,11 @@ irssi_LDADD = \
@PROG_LIBS@ \
@TEXTUI_LIBS@
-tparm_sources = \
- tparm.c
-
terminfo_sources = \
term-terminfo.c \
terminfo-core.c
-curses_sources = \
- term-curses.c
-
-if NEED_TPARM
-use_tparm_sources = $(tparm_sources)
-endif
-
-if USE_CURSES
-use_term_sources = $(curses_sources)
-else
use_term_sources = $(terminfo_sources)
-endif
irssi_SOURCES = \
gui-entry.c \
@@ -57,7 +42,6 @@ irssi_SOURCES = \
statusbar-items.c \
term.c \
term-dummy.c \
- $(use_tparm_sources) \
$(use_term_sources) \
textbuffer.c \
textbuffer-commands.c \
@@ -85,6 +69,4 @@ noinst_HEADERS = \
module-formats.h
EXTRA_DIST = \
- $(tparm_sources) \
- $(terminfo_sources) \
- $(curses_sources)
+ $(terminfo_sources)
diff --git a/src/fe-text/term-curses.c b/src/fe-text/term-curses.c
deleted file mode 100644
index 752edd7f..00000000
--- a/src/fe-text/term-curses.c
+++ /dev/null
@@ -1,415 +0,0 @@
-/*
- term-curses.c : irssi
-
- Copyright (C) 1999-2001 Timo Sirainen
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
-
-#include "module.h"
-#include "signals.h"
-#include "settings.h"
-
-#include "term.h"
-#include "mainwindows.h"
-
-#if defined(USE_NCURSES) && !defined(RENAMED_NCURSES)
-# include <ncurses.h>
-#else
-# include <curses.h>
-#endif
-#include <termios.h>
-#include <signal.h>
-
-#ifndef COLOR_PAIRS
-# define COLOR_PAIRS 64
-#endif
-
-#if defined (TIOCGWINSZ) && defined (HAVE_CURSES_RESIZETERM)
-# define USE_RESIZE_TERM
-#endif
-
-#ifndef _POSIX_VDISABLE
-# define _POSIX_VDISABLE 0
-#endif
-
-struct _TERM_WINDOW {
- int x, y;
- int width, height;
- WINDOW *win;
-};
-
-TERM_WINDOW *root_window;
-
-static int curs_x, curs_y;
-static int freeze_refresh;
-static struct termios old_tio;
-
-static int init_curses(void)
-{
- char ansi_tab[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
- int num;
- struct termios tio;
-
- if (!initscr())
- return FALSE;
-
- cbreak(); noecho(); idlok(stdscr, 1);
-#ifdef HAVE_CURSES_IDCOK
- /*idcok(stdscr, 1); - disabled currently, causes redrawing problems with NetBSD */
-#endif
- intrflush(stdscr, FALSE); nodelay(stdscr, TRUE);
-
- /* Disable INTR, QUIT, VDSUSP and SUSP keys */
- if (tcgetattr(0, &old_tio) == 0) {
- memcpy(&tio, &old_tio, sizeof(tio));
- tio.c_cc[VINTR] = _POSIX_VDISABLE;
- tio.c_cc[VQUIT] = _POSIX_VDISABLE;
-#ifdef VDSUSP
- tio.c_cc[VDSUSP] = _POSIX_VDISABLE;
-#endif
-#ifdef VSUSP
- tio.c_cc[VSUSP] = _POSIX_VDISABLE;
-#endif
- tcsetattr(0, TCSADRAIN, &tio);
- }
-
- if (has_colors())
- start_color();
- else if (term_use_colors)
- term_use_colors = FALSE;
-
-#ifdef HAVE_NCURSES_USE_DEFAULT_COLORS
- /* this lets us to use the "default" background color for colors <= 7 so
- background pixmaps etc. show up right */
- use_default_colors();
-
- for (num = 1; num < COLOR_PAIRS; num++)
- init_pair(num, ansi_tab[num & 7], num <= 7 ? -1 : ansi_tab[num >> 3]);
-
- init_pair(63, 0, -1); /* hm.. not THAT good idea, but probably more
- people want dark grey than white on white.. */
-#else
- for (num = 1; num < COLOR_PAIRS; num++)
- init_pair(num, ansi_tab[num & 7], ansi_tab[num >> 3]);
- init_pair(63, 0, 0);
-#endif
-
- clear();
- return TRUE;
-}
-
-static int term_init_int(void)
-{
- int ret;
-
- ret = init_curses();
- if (!ret) return 0;
-
- curs_x = curs_y = 0;
- freeze_refresh = 0;
-
- root_window = g_new0(TERM_WINDOW, 1);
- root_window->win = stdscr;
-
- term_width = COLS;
- term_height = LINES;
- return ret;
-}
-
-static void term_deinit_int(void)
-{
- tcsetattr(0, TCSADRAIN, &old_tio);
-
- endwin();
- g_free_and_null(root_window);
-}
-
-int term_init(void)
-{
- if (!term_init_int())
- return FALSE;
-
- settings_add_int("lookandfeel", "default_color", 7);
- term_common_init();
- return TRUE;
-}
-
-void term_deinit(void)
-{
- term_common_deinit();
- term_deinit_int();
-}
-
-/* Resize terminal - if width or height is negative,
- the new size is unknown and should be figured out somehow */
-void term_resize(int width, int height)
-{
-#ifdef HAVE_CURSES_RESIZETERM
- if (width < 0 || height < 0) {
-#endif
- term_deinit_int();
- term_init_int();
-#ifdef HAVE_CURSES_RESIZETERM
- } else if (term_width != width || term_height != height) {
- term_width = width;
- term_height = height;
- resizeterm(term_height, term_width);
- }
-#endif
-}
-
-void term_resize_final(int width, int height)
-{
-#ifdef HAVE_CURSES_RESIZETERM
- if (width < 0 || height < 0)
- mainwindows_recreate();
-#else
- mainwindows_recreate();
-#endif
-}
-
-/* Returns TRUE if terminal has colors */
-int term_has_colors(void)
-{
- return has_colors();
-}
-
-/* Force the colors on any way you can */
-void term_force_colors(int set)
-{
- /* don't do anything with curses */
-}
-
-/* Clear screen */
-void term_clear(void)
-{
- term_set_color(root_window, 0);
- clear();
-}
-
-/* Beep */
-void term_beep(void)
-{
- beep();
-}
-
-/* Create a new window in terminal */
-TERM_WINDOW *term_window_create(int x, int y, int width, int height)
-{
- TERM_WINDOW *window;
-
- window = g_new0(TERM_WINDOW, 1);
- window->x = x; window->y = y;
- window->width = width; window->height = height;
- window->win = newwin(height, width, y, x);
- if (window->win == NULL)
- g_error("newwin() failed: %d,%d %d,%d", x, y, width, height);
- idlok(window->win, 1);
-
- return window;
-}
-
-/* Destroy a terminal window */
-void term_window_destroy(TERM_WINDOW *window)
-{
- delwin(window->win);
- g_free(window);
-}
-
-/* Move/resize a window */
-void term_window_move(TERM_WINDOW *window, int x, int y,
- int width, int height)
-{
- /* some checks to make sure the window is visible in screen,
- otherwise curses could get nasty and not show our window anymore. */
- if (width < 1) width = 1;
- if (height < 1) height = 1;
- if (x+width > term_width) x = term_width-width;
- if (y+height > term_height) y = term_height-height;
-
-#ifdef HAVE_CURSES_WRESIZE
- if (window->width != width || window->height != height)
- wresize(window->win, height, width);
- if (window->x != x || window->y != y)
- mvwin(window->win, y, x);
-#else
- if (window->width != width || window->height != height ||
- window->x != x || window->y != y) {
- delwin(window->win);
- window->win = newwin(height, width, y, x);
- idlok(window->win, 1);
- }
-#endif
- window->x = x; window->y = y;
- window->width = width; window->height = height;
-}
-
-/* Clear window */
-void term_window_clear(TERM_WINDOW *window)
-{
- werase(window->win);
-}
-
-/* Scroll window up/down */
-void term_window_scroll(TERM_WINDOW *window, int count)
-{
- scrollok(window->win, TRUE);
- wscrl(window->win, count);
- scrollok(window->win, FALSE);
-}
-
-static int get_attr(int color)
-{
- int attr;
-
- if ((color & FG_MASK) >> 4)
- color = (color & ~FG_MASK) | term_color256map[color & FG_MASK];
- if ((color & BG_MASK) >> (BG_SHIFT + 4))
- color = (color & ~BG_MASK) | (term_color256map[(color & BG_MASK) >> BG_SHIFT] << BG_SHIFT);
- if (!term_use_colors)
- attr = (color & (0x7 << BG_SHIFT)) ? A_REVERSE : 0;
- else if ((color & ((0xf << BG_SHIFT) | 0xf)) == 8 || (color & (FG_MASK | BG_MASK | ATTR_RESETFG)) == 0)
- attr = COLOR_PAIR(63);
- else if ((color & ((0x7 << BG_SHIFT) | 0x7)) == 0)
- attr = A_NORMAL;
- else {
- if (color & ATTR_RESETFG) {
- color &= ~FG_MASK;
- color |= settings_get_int("default_color");
- }
- attr = COLOR_PAIR((color&0x7) | ((color&(0x7<<BG_SHIFT))>>BG_SHIFT<<3));
- }
-
- if ((color & 0x8) || (color & ATTR_BOLD)) attr |= A_BOLD;
- if (color & ATTR_BLINK) attr |= A_BLINK;
-
- if (color & ATTR_UNDERLINE) attr |= A_UNDERLINE;
- if (color & ATTR_REVERSE) attr |= A_REVERSE;
-#ifdef A_ITALIC
- if (color & ATTR_ITALIC) attr |= A_ITALIC;
-#endif
- return attr;
-}
-
-/* Change active color */
-void term_set_color(TERM_WINDOW *window, int col)
-{
- wattrset(window->win, get_attr(col));
- wbkgdset(window->win, ' ' | get_attr(col));
-}
-
-void term_move(TERM_WINDOW *window, int x, int y)
-{
- wmove(window->win, y, x);
-}
-
-void term_addch(TERM_WINDOW *window, char chr)
-{
- waddch(window->win, chr);
-}
-
-void term_add_unichar(TERM_WINDOW *window, unichar chr)
-{
-#ifdef WIDEC_CURSES
- cchar_t wch;
- wchar_t temp[2];
- temp[0] = chr;
- temp[1] = 0;
- if (setcchar(&wch, temp, A_NORMAL, 0, NULL) == OK)
- wadd_wch(window->win, &wch);
- else
-#endif
- waddch(window->win, chr);
-}
-
-void term_addstr(TERM_WINDOW *window, const char *str)
-{
- waddstr(window->win, (const char *) str);
-}
-
-void term_clrtoeol(TERM_WINDOW *window)
-{
- wclrtoeol(window->win);
-}
-
-void term_move_cursor(int x, int y)
-{
- curs_x = x;
- curs_y = y;
-}
-
-void term_refresh_freeze(void)
-{
- freeze_refresh++;
-}
-
-void term_refresh_thaw(void)
-{
- if (freeze_refresh > 0) {
- freeze_refresh--;
- if (freeze_refresh == 0) term_refresh(NULL);
- }
-}
-
-void term_refresh(TERM_WINDOW *window)
-{
- if (window != NULL)
- wnoutrefresh(window->win);
-
- if (freeze_refresh == 0) {
- move(curs_y, curs_x);
- wnoutrefresh(stdscr);
- doupdate();
- }
-}
-
-void term_stop(void)
-{
- term_deinit_int();
- kill(getpid(), SIGTSTP);
- term_init_int();
- irssi_redraw();
-}
-
-void term_set_input_type(int type)
-{
-}
-
-void term_gets(GArray *buffer, int *line_count)
-{
-#ifdef WIDEC_CURSES
- wint_t key;
-#else
- int key;
-#endif
-
- for (;;) {
-#ifdef WIDEC_CURSES
- if (get_wch(&key) == ERR)
-#else
- if ((key = getch()) == ERR)
-#endif
- break;
-#ifdef KEY_RESIZE
- if (key == KEY_RESIZE)
- continue;
-#endif
-
- g_array_append_val(buffer, key);
- if (key == '\r' || key == '\n')
- (*line_count)++;
- }
-}
diff --git a/src/fe-text/terminfo-core.c b/src/fe-text/terminfo-core.c
index 15b00081..9c9179a5 100644
--- a/src/fe-text/terminfo-core.c
+++ b/src/fe-text/terminfo-core.c
@@ -17,7 +17,6 @@ inline static int term_putchar(int c)
char *tparm();
int tputs();
-#ifdef HAVE_TERMINFO
int setupterm();
char *tigetstr();
int tigetnum();
@@ -25,15 +24,6 @@ int tigetflag();
#define term_getstr(x, buffer) tigetstr(x.ti_name)
#define term_getnum(x) tigetnum(x.ti_name);
#define term_getflag(x) tigetflag(x.ti_name);
-#else
-int tgetent();
-char *tgetstr();
-int tgetnum();
-int tgetflag();
-#define term_getstr(x, buffer) tgetstr(x.tc_name, &buffer)
-#define term_getnum(x) tgetnum(x.tc_name)
-#define term_getflag(x) tgetflag(x.tc_name)
-#endif
#define CAP_TYPE_FLAG 0
#define CAP_TYPE_INT 1
@@ -415,9 +405,6 @@ static void term_fill_capabilities(TERM_REC *term)
char *sval;
void *ptr;
-#ifndef HAVE_TERMINFO
- char *tptr = term->buffer2;
-#endif
for (i = 0; i < sizeof(tcaps)/sizeof(tcaps[0]); i++) {
ptr = G_STRUCT_MEMBER_P(term, tcaps[i].offset);
@@ -583,9 +570,7 @@ void terminfo_stop(TERM_REC *term)
static int term_setup(TERM_REC *term)
{
GString *str;
-#ifdef HAVE_TERMINFO
int err;
-#endif
char *term_env;
term_env = getenv("TERM");
@@ -594,18 +579,10 @@ static int term_setup(TERM_REC *term)
return 0;
}
-#ifdef HAVE_TERMINFO
if (setupterm(term_env, 1, &err) != 0) {
fprintf(stderr, "setupterm() failed for TERM=%s: %d\n", term_env, err);
return 0;
}
-#else
- if (tgetent(term->buffer1, term_env) < 1)
- {
- fprintf(stderr, "Termcap not found for TERM=%s\n", term_env);
- return 0;
- }
-#endif
term_fill_capabilities(term);
diff --git a/src/fe-text/tparm.c b/src/fe-text/tparm.c
deleted file mode 100644
index 97c790da..00000000
--- a/src/fe-text/tparm.c
+++ /dev/null
@@ -1,740 +0,0 @@
-/*
- * tparm.c
- *
- * By Ross Ridge
- * Public Domain
- * 92/02/01 07:30:36
- *
- */
-#include <ctype.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-
-#ifndef MAX_PUSHED
-#define MAX_PUSHED 32
-#endif
-
-#define ARG 1
-#define NUM 2
-
-#define INTEGER 1
-#define STRING 2
-
-#define MAX_LINE 640
-
-typedef void* anyptr;
-
-typedef struct stack_str {
- int type;
- int argnum;
- int value;
-} stack;
-
-static stack S[MAX_PUSHED];
-static stack vars['z'-'a'+1];
-static int pos = 0;
-
-static struct arg_str {
- int type;
- int integer;
- char *string;
-} arg_list[10];
-
-static int argcnt;
-
-static va_list tparm_args;
-
-static int pusharg(int arg)
-{
- if (pos == MAX_PUSHED)
- return 1;
- S[pos].type = ARG;
- S[pos++].argnum = arg;
- return 0;
-}
-
-static int pushnum(int num)
-{
- if (pos == MAX_PUSHED)
- return 1;
- S[pos].type = NUM;
- S[pos++].value = num;
- return 0;
-}
-
-/* VARARGS2 */
-static int getarg(int argnum, int type, anyptr p)
-{
- while (argcnt < argnum) {
- arg_list[argcnt].type = INTEGER;
- arg_list[argcnt++].integer = (int) va_arg(tparm_args, int);
- }
- if (argcnt > argnum) {
- if (arg_list[argnum].type != type)
- return 1;
- else if (type == STRING)
- *(char **)p = arg_list[argnum].string;
- else
- *(int *)p = arg_list[argnum].integer;
- } else {
- arg_list[argcnt].type = type;
- if (type == STRING)
- *(char **)p = arg_list[argcnt++].string
- = (char *) va_arg(tparm_args, char *);
- else
- *(int *)p = arg_list[argcnt++].integer = (int) va_arg(tparm_args, int);
- }
- return 0;
-}
-
-
-static int popstring(char **str)
-{
- if (pos-- == 0)
- return 1;
- if (S[pos].type != ARG)
- return 1;
- return(getarg(S[pos].argnum, STRING, (anyptr) str));
-}
-
-static int popnum(int *num)
-{
- if (pos-- == 0)
- return 1;
- switch (S[pos].type) {
- case ARG:
- return (getarg(S[pos].argnum, INTEGER, (anyptr) num));
- case NUM:
- *num = S[pos].value;
- return 0;
- }
- return 1;
-}
-
-static int cvtchar(const char *sp, char *c)
-{
- switch(*sp) {
- case '\\':
- switch(*++sp) {
- case '\'':
- case '$':
- case '\\':
- case '%':
- *c = *sp;
- return 2;
- case '\0':
- *c = '\\';
- return 1;
- case '0':
- if (sp[1] == '0' && sp[2] == '0') {
- *c = '\0';
- return 4;
- }
- *c = '\200'; /* '\0' ???? */
- return 2;
- default:
- *c = *sp;
- return 2;
- }
- default:
- *c = *sp;
- return 1;
- }
-}
-
-static int termcap;
-
-/* sigh... this has got to be the ugliest code I've ever written.
- Trying to handle everything has its cost, I guess.
-
- It actually isn't to hard to figure out if a given % code is supposed
- to be interpeted with its termcap or terminfo meaning since almost
- all terminfo codes are invalid unless something has been pushed on
- the stack and termcap strings will never push things on the stack
- (%p isn't used by termcap). So where we have a choice we make the
- decision by whether or not somthing has been pushed on the stack.
- The static variable termcap keeps track of this; it starts out set
- to 1 and is incremented as each argument processed by a termcap % code,
- however if something is pushed on the stack it's set to 0 and the
- rest of the % codes are interpeted as terminfo % codes. Another way
- of putting it is that if termcap equals one we haven't decided either
- way yet, if it equals zero we're looking for terminfo codes, and if
- its greater than 1 we're looking for termcap codes.
-
- Terminfo % codes:
-
- %% output a '%'
- %[[:][-+# ][width][.precision]][doxXs]
- output pop according to the printf format
- %c output pop as a char
- %'c' push character constant c.
- %{n} push decimal constant n.
- %p[1-9] push parameter [1-9]
- %g[a-z] push variable [a-z]
- %P[a-z] put pop in variable [a-z]
- %l push the length of pop (a string)
- %+ add pop to pop and push the result
- %- subtract pop from pop and push the result
- %* multiply pop and pop and push the result
- %& bitwise and pop and pop and push the result
- %| bitwise or pop and pop and push the result
- %^ bitwise xor pop and pop and push the result
- %~ push the bitwise not of pop
- %= compare if pop and pop are equal and push the result
- %> compare if pop is less than pop and push the result
- %< compare if pop is greater than pop and push the result
- %A logical and pop and pop and push the result
- %O logical or pop and pop and push the result
- %! push the logical not of pop
- %? condition %t if_true [%e if_false] %;
- if condition evaulates as true then evaluate if_true,
- else evaluate if_false. elseif's can be done:
-%? cond %t true [%e cond2 %t true2] ... [%e condN %t trueN] [%e false] %;
- %i add one to parameters 1 and 2. (ANSI)
-
- Termcap Codes:
-
- %% output a %
- %. output parameter as a character
- %d output parameter as a decimal number
- %2 output parameter in printf format %02d
- %3 output parameter in printf format %03d
- %+x add the character x to parameter and output it as a character
-(UW) %-x subtract parameter FROM the character x and output it as a char
-(UW) %ax add the character x to parameter
-(GNU) %a[+*-/=][cp]x
- GNU arithmetic.
-(UW) %sx subtract parameter FROM the character x
- %>xy if parameter > character x then add character y to parameter
- %B convert to BCD (parameter = (parameter/10)*16 + parameter%16)
- %D Delta Data encode (parameter = parameter - 2*(parameter%16))
- %i increment the first two parameters by one
- %n xor the first two parameters by 0140
-(GNU) %m xor the first two parameters by 0177
- %r swap the first two parameters
-(GNU) %b backup to previous parameter
-(GNU) %f skip this parameter
-
- Note the two definitions of %a, the GNU definition is used if the characters
- after the 'a' are valid, otherwise the UW definition is used.
-
- (GNU) used by GNU Emacs termcap libraries
- (UW) used by the University of Waterloo (MFCF) termcap libraries
-
-*/
-
-char *tparm(const char *str, ...) {
- static char OOPS[] = "OOPS";
- static char buf[MAX_LINE];
- register const char *sp;
- register char *dp;
- register char *fmt;
- char conv_char;
- char scan_for;
- int scan_depth = 0, if_depth;
- static int i, j;
- static char *s, c;
- char fmt_buf[MAX_LINE];
- char sbuf[MAX_LINE];
-
- va_start(tparm_args, str);
-
- sp = str;
- dp = buf;
- scan_for = 0;
- if_depth = 0;
- argcnt = 0;
- pos = 0;
- termcap = 1;
- while (*sp != '\0') {
- switch(*sp) {
- case '\\':
- if (scan_for) {
- if (*++sp != '\0')
- sp++;
- break;
- }
- *dp++ = *sp++;
- if (*sp != '\0')
- *dp++ = *sp++;
- break;
- case '%':
- sp++;
- if (scan_for) {
- if (*sp == scan_for && if_depth == scan_depth) {
- if (scan_for == ';')
- if_depth--;
- scan_for = 0;
- } else if (*sp == '?')
- if_depth++;
- else if (*sp == ';') {
- if (if_depth == 0)
- return OOPS;
- else
- if_depth--;
- }
- sp++;
- break;
- }
- fmt = NULL;
- switch(*sp) {
- case '%':
- *dp++ = *sp++;
- break;
- case '+':
- if (!termcap) {
- if (popnum(&j) || popnum(&i))
- return OOPS;
- i += j;
- if (pushnum(i))
- return OOPS;
- sp++;
- break;
- }
- ;/* FALLTHROUGH */
- case 'C':
- if (*sp == 'C') {
- if (getarg(termcap - 1, INTEGER, &i))
- return OOPS;
- if (i >= 96) {
- i /= 96;
- if (i == '$')
- *dp++ = '\\';
- *dp++ = i;
- }
- }
- fmt = "%c";
- /* FALLTHROUGH */
- case 'a':
- if (!termcap)
- return OOPS;
- if (getarg(termcap - 1, INTEGER, (anyptr) &i))
- return OOPS;
- if (*++sp == '\0')
- return OOPS;
- if ((sp[1] == 'p' || sp[1] == 'c')
- && sp[2] != '\0' && fmt == NULL) {
- /* GNU aritmitic parameter, what they
- really need is terminfo. */
- int val, lc;
- if (sp[1] == 'p'
- && getarg(termcap - 1 + sp[2] - '@',
- INTEGER, (anyptr) &val))
- return OOPS;
- if (sp[1] == 'c') {
- lc = cvtchar(sp + 2, &c) + 2;
- /* Mask out 8th bit so \200 can be
- used for \0 as per GNU doc's */
- val = c & 0177;
- } else
- lc = 2;
- switch(sp[0]) {
- case '=':
- break;
- case '+':
- val = i + val;
- break;
- case '-':
- val = i - val;
- break;
- case '*':
- val = i * val;
- break;
- case '/':
- val = i / val;
- break;
- default:
- /* Not really GNU's %a after all... */
- lc = cvtchar(sp, &c);
- val = c + i;
- break;
- }
- arg_list[termcap - 1].integer = val;
- sp += lc;
- break;
- }
- sp += cvtchar(sp, &c);
- arg_list[termcap - 1].integer = c + i;
- if (fmt == NULL)
- break;
- sp--;
- /* FALLTHROUGH */
- case '-':
- if (!termcap) {
- if (popnum(&j) || popnum(&i))
- return OOPS;
- i -= j;
- if (pushnum(i))
- return OOPS;
- sp++;
- break;
- }
- fmt = "%c";
- /* FALLTHROUGH */
- case 's':
- if (termcap && (fmt == NULL || *sp == '-')) {
- if (getarg(termcap - 1, INTEGER, &i))
- return OOPS;
- if (*++sp == '\0')
- return OOPS;
- sp += cvtchar(sp, &c);
- arg_list[termcap - 1].integer = c - i;
- if (fmt == NULL)
- break;
- sp--;
- }
- if (!termcap)
- return OOPS;
- ;/* FALLTHROUGH */
- case '.':
- if (termcap && fmt == NULL)
- fmt = "%c";
- ;/* FALLTHROUGH */
- case 'd':
- if (termcap && fmt == NULL)
- fmt = "%d";
- ;/* FALLTHROUGH */
- case '2':
- if (termcap && fmt == NULL)
- fmt = "%02d";
- ;/* FALLTHROUGH */
- case '3':
- if (termcap && fmt == NULL)
- fmt = "%03d";
- ;/* FALLTHROUGH */
- case ':': case ' ': case '#': case 'u':
- case 'x': case 'X': case 'o': case 'c':
- case '0': case '1': case '4': case '5':
- case '6': case '7': case '8': case '9':
- if (fmt == NULL) {
- if (termcap)
- return OOPS;
- if (*sp == ':')
- sp++;
- fmt = fmt_buf;
- *fmt++ = '%';
- while(*sp != 's' && *sp != 'x' && *sp != 'X' && *sp != 'd' && *sp != 'o' && *sp != 'c' && *sp != 'u') {
- if (*sp == '\0')
- return OOPS;
- *fmt++ = *sp++;
- }
- *fmt++ = *sp;
- *fmt = '\0';
- fmt = fmt_buf;
- }
- conv_char = fmt[strlen(fmt) - 1];
- if (conv_char == 's') {
- if (popstring(&s))
- return OOPS;
- sprintf(sbuf, fmt, s);
- } else {
- if (termcap) {
- if (getarg(termcap++ - 1,
- INTEGER, &i))
- return OOPS;
- } else
- if (popnum(&i))
- return OOPS;
- if (i == 0 && conv_char == 'c')
- *sbuf = 0;
- else
- sprintf(sbuf, fmt, i);
- }
- sp++;
- fmt = sbuf;
- while(*fmt != '\0') {
- if (*fmt == '$')
- *dp++ = '\\';
- *dp++ = *fmt++;
- }
- break;
- case 'r':
- if (!termcap || getarg(1, INTEGER, &i))
- return OOPS;
- arg_list[1].integer = arg_list[0].integer;
- arg_list[0].integer = i;
- sp++;
- break;
- case 'i':
- if (getarg(1, INTEGER, &i)
- || arg_list[0].type != INTEGER)
- return OOPS;
- arg_list[1].integer++;
- arg_list[0].integer++;
- sp++;
- break;
- case 'n':
- if (!termcap || getarg(1, INTEGER, &i))
- return OOPS;
- arg_list[0].integer ^= 0140;
- arg_list[1].integer ^= 0140;
- sp++;
- break;
- case '>':
- if (!termcap) {
- if (popnum(&j) || popnum(&i))
- return OOPS;
- i = (i > j);
- if (pushnum(i))
- return OOPS;
- sp++;
- break;
- }
- if (getarg(termcap-1, INTEGER, &i))
- return OOPS;
- sp += cvtchar(sp, &c);
- if (i > c) {
- sp += cvtchar(sp, &c);
- arg_list[termcap-1].integer += c;
- } else
- sp += cvtchar(sp, &c);
- sp++;
- break;
- case 'B':
- if (!termcap || getarg(termcap-1, INTEGER, &i))
- return OOPS;
- arg_list[termcap-1].integer = 16*(i/10)+i%10;
- sp++;
- break;
- case 'D':
- if (!termcap || getarg(termcap-1, INTEGER, &i))
- return OOPS;
- arg_list[termcap-1].integer = i - 2 * (i % 16);
- sp++;
- break;
- case 'p':
- if (termcap > 1)
- return OOPS;
- if (*++sp == '\0')
- return OOPS;
- if (*sp == '0')
- i = 9;
- else
- i = *sp - '1';
- if (i < 0 || i > 9)
- return OOPS;
- if (pusharg(i))
- return OOPS;
- termcap = 0;
- sp++;
- break;
- case 'P':
- if (termcap || *++sp == '\0')
- return OOPS;
- i = *sp++ - 'a';
- if (i < 0 || i > 25)
- return OOPS;
- if (pos-- == 0)
- return OOPS;
- switch(vars[i].type = S[pos].type) {
- case ARG:
- vars[i].argnum = S[pos].argnum;
- break;
- case NUM:
- vars[i].value = S[pos].value;
- break;
- }
- break;
- case 'g':
- if (termcap || *++sp == '\0')
- return OOPS;
- i = *sp++ - 'a';
- if (i < 0 || i > 25)
- return OOPS;
- switch(vars[i].type) {
- case ARG:
- if (pusharg(vars[i].argnum))
- return OOPS;
- break;
- case NUM:
- if (pushnum(vars[i].value))
- return OOPS;
- break;
- }
- break;
- case '\'':
- if (termcap > 1)
- return OOPS;
- if (*++sp == '\0')
- return OOPS;
- sp += cvtchar(sp, &c);
- if (pushnum(c) || *sp++ != '\'')
- return OOPS;
- termcap = 0;
- break;
- case '{':
- if (termcap > 1)
- return OOPS;
- i = 0;
- sp++;
- while(isdigit((int) (unsigned char) *sp))
- i = 10 * i + *sp++ - '0';
- if (*sp++ != '}' || pushnum(i))
- return OOPS;
- termcap = 0;
- break;
- case 'l':
- if (termcap || popstring(&s))
- return OOPS;
- i = strlen(s);
- if (pushnum(i))
- return OOPS;
- sp++;
- break;
- case '*':
- if (termcap || popnum(&j) || popnum(&i))
- return OOPS;
- i *= j;
- if (pushnum(i))
- return OOPS;
- sp++;
- break;
- case '/':
- if (termcap || popnum(&j) || popnum(&i))
- return OOPS;
- i /= j;
- if (pushnum(i))
- return OOPS;
- sp++;
- break;
- case 'm':
- if (termcap) {
- if (getarg(1, INTEGER, &i))
- return OOPS;
- arg_list[0].integer ^= 0177;
- arg_list[1].integer ^= 0177;
- sp++;
- break;
- }
- if (popnum(&j) || popnum(&i))
- return OOPS;
- i %= j;
- if (pushnum(i))
- return OOPS;
- sp++;
- break;
- case '&':
- if (popnum(&j) || popnum(&i))
- return OOPS;
- i &= j;
- if (pushnum(i))
- return OOPS;
- sp++;
- break;
- case '|':
- if (popnum(&j) || popnum(&i))
- return OOPS;
- i |= j;
- if (pushnum(i))
- return OOPS;
- sp++;
- break;
- case '^':
- if (popnum(&j) || popnum(&i))
- return OOPS;
- i ^= j;
- if (pushnum(i))
- return OOPS;
- sp++;
- break;
- case '=':
- if (popnum(&j) || popnum(&i))
- return OOPS;
- i = (i == j);
- if (pushnum(i))
- return OOPS;
- sp++;
- break;
- case '<':
- if (popnum(&j) || popnum(&i))
- return OOPS;
- i = (i < j);
- if (pushnum(i))
- return OOPS;
- sp++;
- break;
- case 'A':
- if (popnum(&j) || popnum(&i))
- return OOPS;
- i = (i && j);
- if (pushnum(i))
- return OOPS;
- sp++;
- break;
- case 'O':
- if (popnum(&j) || popnum(&i))
- return OOPS;
- i = (i || j);
- if (pushnum(i))
- return OOPS;
- sp++;
- break;
- case '!':
- if (popnum(&i))
- return OOPS;
- i = !i;
- if (pushnum(i))
- return OOPS;
- sp++;
- break;
- case '~':
- if (popnum(&i))
- return OOPS;
- i = ~i;
- if (pushnum(i))
- return OOPS;
- sp++;
- break;
- case '?':
- if (termcap > 1)
- return OOPS;
- termcap = 0;
- if_depth++;
- sp++;
- break;
- case 't':
- if (popnum(&i) || if_depth == 0)
- return OOPS;
- if (!i) {
- scan_for = 'e';
- scan_depth = if_depth;
- }
- sp++;
- break;
- case 'e':
- if (if_depth == 0)
- return OOPS;
- scan_for = ';';
- scan_depth = if_depth;
- sp++;
- break;
- case ';':
- if (if_depth-- == 0)
- return OOPS;
- sp++;
- break;
- case 'b':
- if (--termcap < 1)
- return OOPS;
- sp++;
- break;
- case 'f':
- if (!termcap++)
- return OOPS;
- sp++;
- break;
- }
- break;
- default:
- if (scan_for)
- sp++;
- else
- *dp++ = *sp++;
- break;
- }
- }
- va_end(tparm_args);
- *dp = '\0';
- return buf;
-}