diff options
Diffstat (limited to 'libslang/src/slvideo.c')
-rw-r--r-- | libslang/src/slvideo.c | 2337 |
1 files changed, 2337 insertions, 0 deletions
diff --git a/libslang/src/slvideo.c b/libslang/src/slvideo.c new file mode 100644 index 0000000..7c4a26c --- /dev/null +++ b/libslang/src/slvideo.c @@ -0,0 +1,2337 @@ +/* -*- mode: C; mode: fold -*- */ +/* Copyright (c) 1992, 1997, 2001, 2002, 2003 John E. Davis + * This file is part of the S-Lang library. + * + * You may distribute under the terms of either the GNU General Public + * License or the Perl Artistic License. + */ + +/* This file is best edited with a folding editor */ + +#include "slinclud.h" + +#if !defined(__WIN32__) && !defined(__IBMC__) +# include <dos.h> +#endif + +#include "slang.h" +#include "_slang.h" + +int SLtt_Term_Cannot_Insert; +int SLtt_Term_Cannot_Scroll; +int SLtt_Ignore_Beep = 3; +int SLtt_Use_Ansi_Colors; +int SLtt_Has_Status_Line = 0; +int SLtt_Screen_Rows = 25; +int SLtt_Screen_Cols = 80; +int SLtt_Msdos_Cheap_Video = 0; + +void (*_SLtt_color_changed_hook)(void); + +/* This definition will need changing when SLsmg_Char_Type changes. */ +#define SLSMG_CHAR_TO_USHORT(x) ((unsigned short)(x)) + +/*{{{ ------------- static local variables ---------- */ + +static int Attribute_Byte; +static int Scroll_r1 = 0, Scroll_r2 = 25; +static int Cursor_Row = 1, Cursor_Col = 1; +static int Current_Color; +static int IsColor = 1; +static int Blink_Killed = 1; /* high intensity background enabled */ + +#define JMAX_COLORS 256 +#define JNORMAL_COLOR 0 +#define JNO_COLOR -1 + +static unsigned char Color_Map [JMAX_COLORS] = +{ + 0x7, 0x70, 0x70, 0x70, 0x70, 0x7, 0x7, 0x7, + 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, + 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, + 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, + 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, + 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, + 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, + 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, + 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, + 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, + 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, + 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, + 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, + 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, + 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, + 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, + 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, + 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, + 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, + 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, + 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, + 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, + 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, + 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, + 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, + 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, + 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, + 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, + 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, + 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, + 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, + 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7 +}; + +#define JMAX_COLOR_NAMES 16 +static SLCONST char *Color_Names [JMAX_COLOR_NAMES] = +{ + "black", "blue", "green", "cyan", + "red", "magenta", "brown", "lightgray", + "gray", "brightblue", "brightgreen", "brightcyan", + "brightred", "brightmagenta", "yellow", "white" +}; + +static void fixup_colors (void); + +/*}}}*/ + +static void goto_rc_abs (int r, int c) +{ + SLtt_goto_rc (r - Scroll_r1, c); +} + +#if defined(__BORLANDC__) && defined(__MSDOS__) +# define IBMPC_ASM_VIDEO 1 +#endif + +#if defined(__WATCOMC__) && !defined(__NT__) && !defined(__os2__) +# define WATCOM_VIDEO 1 +#endif + +#if defined (__GO32__) +# define GO32_VIDEO 1 +#endif + +#if defined (__EMX__) /* EMX video does both DOS & OS/2 */ +# define EMX_VIDEO 1 +#else +# if defined(__os2__) +# define OS2_VIDEO 1 +# endif +#endif + +#if defined (__WIN32__) +# define WIN32_VIDEO 1 +#endif + +/* The functions in these folds contain somewhat video system specific code + * that if merged together into single functions will become a confusing + * mess. + */ + +#ifdef IBMPC_ASM_VIDEO /*{{{*/ + +# include <conio.h> +# include <bios.h> +# include <mem.h> + +/* buffer to hold a line of character/attribute pairs */ +#define MAXCOLS 256 +static unsigned char Line_Buffer [MAXCOLS*2]; + +#define MK_SPACE_CHAR() (((Attribute_Byte) << 8) | 0x20) + +static unsigned char *Video_Base; +# define MK_SCREEN_POINTER(row,col) ((unsigned short *)\ + (Video_Base +\ + 2 * (SLtt_Screen_Cols * (row)\ + + (col)))) +static int Video_Status_Port; + +# define MONO_STATUS 0x3BA +# define CGA_STATUS 0x3DA +# define CGA_SETMODE 0x3D8 + +# define SNOW_CHECK \ + if (SLtt_Msdos_Cheap_Video)\ + { while ((inp (CGA_STATUS) & 0x08)); while (!(inp (CGA_STATUS) & 0x08)); } + +void SLtt_write_string (char *str) +{ + /* FIXME: Priority=medium + * This should not go to stdout. */ + fputs (str, stdout); +} + +/* row is with respect to the scrolling region. */ +void SLtt_goto_rc (int r, int c) +{ + union REGS regs; + + r += Scroll_r1; + + if (r > SLtt_Screen_Rows - 1) r = SLtt_Screen_Rows - 1; + if (c > SLtt_Screen_Cols - 1) c = SLtt_Screen_Cols - 1; + + Cursor_Row = r; + Cursor_Col = c; + + regs.h.dh = r; + regs.h.dl = c; + regs.h.bh = 0; + regs.h.ah = 2; + int86 (0x10, ®s, ®s); +} + +static void asm_video_getxy (void) +{ + asm mov ah, 3 + asm mov bh, 0 + asm int 10h + asm xor ax, ax + asm mov al, dh + asm mov Cursor_Row, ax + asm xor ax, ax + asm mov al, dl + asm mov Cursor_Col, ax +} + +void SLtt_begin_insert (void) +{ + unsigned short *p; + int n; + + asm_video_getxy (); + n = SLtt_Screen_Cols - Cursor_Col; + p = MK_SCREEN_POINTER (Cursor_Row, SLtt_Screen_Cols - 1); + + SNOW_CHECK; + asm mov ax, ds + asm mov bx, di + asm mov dx, si + + asm mov cx, n + asm les di, p + asm lds si, p + asm sub si, 2 + asm std + asm rep movsw + + asm mov ds, ax + asm mov di, bx + asm mov si, dx +} + +void SLtt_end_insert (void) +{ +} + +void SLtt_delete_char (void) +{ + unsigned short *p; + int n; + + asm_video_getxy (); + n = SLtt_Screen_Cols - Cursor_Col - 1; + p = MK_SCREEN_POINTER (Cursor_Row, Cursor_Col); + + SNOW_CHECK; + asm mov ax, ds + asm mov bx, si + asm mov dx, di + + asm mov cx, n + asm les di, p + asm lds si, p + asm add si, 2 + asm cld + asm rep movsw + + asm mov ds, ax + asm mov si, bx + asm mov di, dx +} + +void SLtt_erase_line (void) +{ + unsigned short w, *p; + + p = MK_SCREEN_POINTER (Cursor_Row, 0); + Attribute_Byte = 0x07; + + w = MK_SPACE_CHAR (); + + SNOW_CHECK; + asm mov dx, di + asm mov ax, w + asm mov cx, SLtt_Screen_Cols + asm les di, p + asm cld + asm rep stosw + asm mov di, dx + + Current_Color = JNO_COLOR; /* since we messed with attribute byte */ +} + +void SLtt_delete_nlines (int nlines) +{ + SLtt_normal_video (); + + /* This has the effect of pulling all lines below it up */ + asm mov ax, nlines + asm mov ah, 6 /* int 6h */ + asm xor cx, cx + asm mov ch, byte ptr Scroll_r1 + asm mov dx, SLtt_Screen_Cols + asm dec dx + asm mov dh, byte ptr Scroll_r2 + asm mov bh, byte ptr Attribute_Byte + asm int 10h +} + +void SLtt_reverse_index (int nlines) +{ + SLtt_normal_video (); + asm xor cx, cx + asm mov ch, byte ptr Scroll_r1 + asm mov dx, SLtt_Screen_Cols + asm dec dx + asm mov dh, byte ptr Scroll_r2 + asm mov bh, byte ptr Attribute_Byte + asm mov ah, 7 + asm mov al, byte ptr nlines + asm int 10h +} + +static void asm_video_invert_region (int top_row, int bot_row) +{ + register unsigned short ch, sh; + register unsigned short *pmin = MK_SCREEN_POINTER (top_row, 0); + register unsigned short *pmax = MK_SCREEN_POINTER (bot_row, 0); + + while (pmin < pmax) + { + sh = *pmin; + ch = sh; + ch = ch ^ 0xFF00; + *pmin = (ch & 0xFF00) | (sh & 0x00FF); + pmin++; + } +} + +void SLtt_del_eol (void) +{ + unsigned short *p; + unsigned short w; + int n; + + n = SLtt_Screen_Cols - Cursor_Col; + p = MK_SCREEN_POINTER (Cursor_Row, Cursor_Col); + if (Current_Color != JNO_COLOR) SLtt_normal_video (); + w = MK_SPACE_CHAR (); + + SNOW_CHECK; + asm mov dx, di + asm les di, p + asm mov ax, w + asm mov cx, n + asm cld + asm rep stosw + + asm mov di, dx +} + +static unsigned short *asm_video_write (register unsigned char *pp, + register unsigned char *p, + register unsigned short *pos) +{ + int n = (int) (p - pp); /* num of characters of PP to write */ + + asm push si + asm push ds + asm push di + + /* set up register for BOTH fast and slow */ + asm mov bx, SLtt_Msdos_Cheap_Video + + /* These are the registers needed for both fast AND slow */ + asm mov ah, byte ptr Attribute_Byte + asm mov cx, n + asm lds si, dword ptr pp + asm les di, dword ptr pos + asm cld + + asm cmp bx, 0 /* cheap video test */ + asm je L_fast + asm mov bx, ax + asm mov dx, CGA_STATUS + asm jg L_slow_blank + + /* slow video */ + asm cli + + /* wait for retrace */ + L_slow: + asm in al, dx + asm test al, 1 + asm jnz L_slow + + L_slow1: + asm in al, dx + asm test al, 1 + asm jz L_slow1 + + /* move a character out */ + asm mov ah, bh + asm lodsb + asm stosw + asm loop L_slow + + asm sti + asm jmp done + +/* -------------- slow video, vertical retace and pump --------------*/ + L_slow_blank: + L_slow_blank_loop: + asm in al, dx + asm test al, 8 + asm jnz L_slow_blank_loop + + L_slow_blank1: + asm in al, dx + asm test al, 8 + asm jz L_slow_blank1 + /* write line */ + asm mov ah, bh + L_slow_blank2: + asm lodsb + asm stosw + asm loop L_slow_blank2 + + asm jmp done +/*-------------- Fast video --------------*/ + + L_fast: + asm lodsb + asm stosw + asm loop L_fast + done: + asm pop di + asm pop ds + asm pop si + return (pos + n); +} + +static void write_attributes (SLsmg_Char_Type *src, unsigned int count) +{ + register unsigned char *p; + register unsigned short pair; + unsigned char ch, color; + register unsigned short *pos; + + p = Line_Buffer; + pos = MK_SCREEN_POINTER (Cursor_Row, 0); + + while (count--) + { + pair = SLSMG_CHAR_TO_USHORT(*src); /* character/color pair */ + src++; + ch = pair & 0xff; /* character value */ + color = pair >> 8; /* color value */ + if (color != Current_Color) /* need a new color */ + { + if (p != Line_Buffer) + { + pos = asm_video_write (Line_Buffer, p, pos); + p = Line_Buffer; + } + SLtt_reverse_video (color); /* change color */ + } + *(p++) = ch; + } + pos = asm_video_write (Line_Buffer, p, pos); +} + +void SLtt_cls (void) +{ + SLtt_normal_video (); + + asm mov dx, SLtt_Screen_Cols + asm dec dx + asm mov ax, SLtt_Screen_Rows + asm dec ax + asm mov dh, al + asm xor cx, cx + asm xor ax, ax + asm mov ah, 7 + asm mov bh, byte ptr Attribute_Byte + asm int 10h +} + +void SLtt_putchar (char ch) +{ + unsigned short p, *pp; + + if (Current_Color) SLtt_normal_video (); + asm_video_getxy (); /* get current position */ + switch (ch) + { + case 7: /* ^G - break */ + SLtt_beep (); break; + case 8: /* ^H - backspace */ + goto_rc_abs (Cursor_Row, Cursor_Col - 1); break; + case 13: /* ^M - carriage return */ + goto_rc_abs (Cursor_Row, 0); break; + default: + /* write character to screen */ + pp = MK_SCREEN_POINTER (Cursor_Row, Cursor_Col); + p = (Attribute_Byte << 8) | (unsigned char) ch; + SNOW_CHECK; + *pp = p; + goto_rc_abs (Cursor_Row, Cursor_Col + 1); + } +} + +void SLtt_get_screen_size (void) +{ + int w, h; + + h = 0; + + /* Get BIOS's screenwidth, this works on ALL displays. */ + w = *((int *)MK_FP(0x40, 0x4a)); + + /* Use Ralf Brown test for EGA or greater */ + asm mov ah, 12h + asm mov bl, 10h + asm mov bh, 0xFF /* EGA or greater will change this */ + asm int 10h + asm cmp bh, 0xFF + asm je L1 + /* if EGA or compatible: Get BIOS's number of rows. */ + h = *(char *)MK_FP(0x40, 0x84) + 1; + /* scan_lines = *(int *) 0x485; */ + + L1: + if (h <= 0) h = 25; + + SLtt_Screen_Rows = h; + SLtt_Screen_Cols = w; +} + +void SLtt_get_terminfo (void) +{ + SLtt_get_screen_size (); +} + +/*----------------------------------------------------------------------*\ + * Function: int SLtt_init_video (void); +\*----------------------------------------------------------------------*/ +int SLtt_init_video (void) +{ + unsigned char *p; + +#ifdef HAS_SAVE_SCREEN + save_screen (); +#endif + + Cursor_Row = Cursor_Col = 0; + p = (unsigned char far *) 0x00400049L; + if (*p == 7) + { + Video_Status_Port = MONO_STATUS; + Video_Base = (unsigned char *) MK_FP (0xb000,0000); + IsColor = 0; + } + else + { + Video_Status_Port = CGA_STATUS; + Video_Base = (unsigned char *) MK_FP (0xb800,0000); + IsColor = 1; + } + + /* test for video adapter type. Of primary interest is whether there is + * snow or not. Assume snow if the card is color and not EGA or greater. + */ + + /* Use Ralf Brown test for EGA or greater */ + asm mov ah, 0x12 + asm mov bl, 0x10 + asm mov bh, 0xFF + asm int 10h + asm cmp bh, 0xFF + asm je L1 + + /* (V)EGA */ + asm xor bx, bx + asm mov SLtt_Msdos_Cheap_Video, bx + asm mov ax, Attribute_Byte + asm cmp ax, bx + asm jne L2 + asm mov ax, 0x17 + asm mov Attribute_Byte, ax + asm jmp L2 + + L1: + /* Not (V)EGA */ + asm mov ah, 0x0F + asm int 10h + asm cmp al, 7 + asm je L3 + asm mov ax, 1 + asm mov SLtt_Msdos_Cheap_Video, ax + L3: + asm mov ax, Attribute_Byte + asm cmp ax, 0 + asm jne L2 + asm mov ax, 0x07 + asm mov Attribute_Byte, ax + L2: + /* toggle the blink bit so we can use hi intensity background */ + if (IsColor && !SLtt_Msdos_Cheap_Video) + { + asm mov ax, 0x1003 + asm mov bx, 0 + asm int 0x10 + Blink_Killed = 1; + } + + SLtt_Use_Ansi_Colors = IsColor; + SLtt_get_screen_size (); + SLtt_reset_scroll_region (); + fixup_colors (); + return 0; +} + +void SLtt_beep (void) +{ + int audible; /* audible bell */ + int special = 0; /* first row to invert */ + int visual = 0; /* final row to invert */ + + if (!SLtt_Ignore_Beep) return; + + audible = (SLtt_Ignore_Beep & 1); + if ( (SLtt_Ignore_Beep & 4) ) + { + special = SLtt_Screen_Rows - 1; + visual = special--; /* only invert bottom status line */ + } + else if ( (SLtt_Ignore_Beep & 2) ) + { + visual = SLtt_Screen_Rows; + } + + if (visual) asm_video_invert_region (special, visual); + if (audible) sound (1500); delay (100); if (audible) nosound (); + if (visual) asm_video_invert_region (special, visual); +} + +#endif /* IBMPC_ASM_VIDEO */ + +/*}}}*/ + +#ifdef GO32_VIDEO /*{{{*/ + +# include <pc.h> +# define HAS_SAVE_SCREEN 1 + +# ifdef HAS_SAVE_SCREEN +static void *Saved_Screen_Buffer; +static int Saved_Cursor_Row; + +static void save_screen (void) +{ + int row, col; + + SLfree ((char *) Saved_Screen_Buffer); + Saved_Screen_Buffer = NULL; + + Saved_Screen_Buffer = (short *) SLmalloc (sizeof (short) * + ScreenCols () * ScreenRows ()); + + if (Saved_Screen_Buffer == NULL) + return; + + ScreenRetrieve (Saved_Screen_Buffer); + ScreenGetCursor (&row, &col); + Saved_Cursor_Row = row; +} + +static void restore_screen (void) +{ + if (Saved_Screen_Buffer == NULL) return; + ScreenUpdate (Saved_Screen_Buffer); + goto_rc_abs (Saved_Cursor_Row, 0); +} +#endif /* HAS_SAVE_SCREEN */ + +void SLtt_write_string (char *str) +{ + while (Cursor_Col < SLtt_Screen_Cols) + { + char ch = *str++; + + if (ch == 0) + break; + + ScreenPutChar (ch, Attribute_Byte, Cursor_Col, Cursor_Row); + Cursor_Col++; + } + goto_rc_abs (Cursor_Row, Cursor_Col); +} + +void SLtt_goto_rc (int row, int col) +{ + row += Scroll_r1; + if (row > SLtt_Screen_Rows) row = SLtt_Screen_Rows; + if (col > SLtt_Screen_Cols) col = SLtt_Screen_Cols; + + ScreenSetCursor (row, col); + + Cursor_Row = row; + Cursor_Col = col; +} + +static void go32_video_getxy (void) +{ + ScreenGetCursor (&Cursor_Row, &Cursor_Col); +} + +static void go32_video_deleol (int x) +{ + while (x < SLtt_Screen_Cols) + ScreenPutChar (32, Attribute_Byte, x++, Cursor_Row); +} + +void SLtt_begin_insert (void) +{ +} + +void SLtt_end_insert (void) +{ +} + +void SLtt_delete_char (void) +{ +} + +void SLtt_erase_line (void) +{ + Attribute_Byte = 0x07; + go32_video_deleol (0); + Current_Color = JNO_COLOR; /* since we messed with attribute byte */ +} + +void SLtt_delete_nlines (int nlines) +{ + union REGS r; + + SLtt_normal_video (); + + r.x.ax = nlines; + r.x.cx = 0; + r.h.ah = 6; + r.h.ch = Scroll_r1; + r.h.dl = SLtt_Screen_Cols - 1; + r.h.dh = Scroll_r2; + r.h.bh = Attribute_Byte; + int86 (0x10, &r, &r); +} + +void SLtt_reverse_index (int nlines) +{ + union REGS r; + + SLtt_normal_video (); + + r.h.al = nlines; + r.x.cx = 0; + r.h.ah = 7; + r.h.ch = Scroll_r1; + r.h.dl = SLtt_Screen_Cols - 1; + r.h.dh = Scroll_r2; + r.h.bh = Attribute_Byte; + int86 (0x10, &r, &r); +} + +static void go32_video_invert_region (int top_row, int bot_row) +{ + unsigned char buf [2 * 180 * 80]; /* 180 cols x 80 rows */ + unsigned char *b, *bmax; + + b = buf + 1 + 2 * SLtt_Screen_Cols * top_row; + bmax = buf + 1 + 2 * SLtt_Screen_Cols * bot_row; + + ScreenRetrieve (buf); + while (b < bmax) + { + *b ^= 0xFF; + b += 2; + } + ScreenUpdate (buf); +} + +void SLtt_beep (void) +{ + int audible; /* audible bell */ + int special = 0; /* first row to invert */ + int visual = 0; /* final row to invert */ + + if (!SLtt_Ignore_Beep) return; + + audible = (SLtt_Ignore_Beep & 1); + if ( (SLtt_Ignore_Beep & 4) ) + { + special = SLtt_Screen_Rows - 1; + visual = special--; /* only invert bottom status line */ + } + else if ( (SLtt_Ignore_Beep & 2) ) + { + visual = SLtt_Screen_Rows; + } + + if (visual) go32_video_invert_region (special, visual); + if (audible) sound (1500); delay (100); if (audible) nosound (); + if (visual) go32_video_invert_region (special, visual); +} + +void SLtt_del_eol (void) +{ + if (Current_Color != JNO_COLOR) SLtt_normal_video (); + go32_video_deleol (Cursor_Col); +} + +static void +write_attributes (SLsmg_Char_Type *src, unsigned int count) +{ + register unsigned short pair; + unsigned int n; + + /* write into a character/attribute pair */ + n = Cursor_Col; + while (count) + { + pair = SLSMG_CHAR_TO_USHORT(*src);/* character/color pair */ + src++; + SLtt_reverse_video (pair >> 8); /* color change */ + ScreenPutChar ((int)pair & 0xFF, Attribute_Byte, n, Cursor_Row); + n++; + count--; + } +} + +/*----------------------------------------------------------------------*\ + * Function: void SLtt_cls (void); +\*----------------------------------------------------------------------*/ +void SLtt_cls (void) +{ + SLtt_normal_video (); + SLtt_reset_scroll_region (); + SLtt_goto_rc (0, 0); + SLtt_delete_nlines (SLtt_Screen_Rows); +} + +void SLtt_putchar (char ch) +{ + if (Current_Color) SLtt_normal_video (); + + go32_video_getxy (); /* get current position */ + + switch (ch) + { + case 7: /* ^G - break */ + SLtt_beep (); break; + case 8: /* ^H - backspace */ + goto_rc_abs (Cursor_Row, Cursor_Col - 1); break; + case 13: /* ^M - carriage return */ + goto_rc_abs (Cursor_Row, 0); break; + default: /* write character to screen */ + ScreenPutChar ((int) ch, Attribute_Byte, Cursor_Col, Cursor_Row); + goto_rc_abs (Cursor_Row, Cursor_Col + 1); + } +} + +void SLtt_get_screen_size (void) +{ + SLtt_Screen_Rows = ScreenRows (); + SLtt_Screen_Cols = ScreenCols (); +} + +void SLtt_get_terminfo (void) +{ + SLtt_get_screen_size (); +} + +int SLtt_init_video (void) +{ +#ifdef HAS_SAVE_SCREEN + save_screen (); +#endif + + if (!Attribute_Byte) Attribute_Byte = 0x17; + + IsColor = 1; /* is it really? */ + + if (IsColor) + { + union REGS r; + r.x.ax = 0x1003; r.x.bx = 0; + int86 (0x10, &r, &r); + Blink_Killed = 1; + } + + Cursor_Row = Cursor_Col = 0; + + SLtt_Term_Cannot_Insert = 1; + SLtt_reset_scroll_region (); + SLtt_Use_Ansi_Colors = IsColor; + fixup_colors (); + return 0; +} + +#endif /* GO32_VIDEO */ + +/*}}}*/ + +#ifdef EMX_VIDEO /*{{{*/ + +# define INCL_VIO +# define INCL_DOSPROCESS +# include <os2.h> +# include <os2emx.h> +# include <sys/video.h> + +static VIOMODEINFO vioModeInfo; +/* buffer to hold a line of character/attribute pairs */ +#define MAXCOLS 256 +static unsigned char Line_Buffer [MAXCOLS*2]; + +/* this is how to make a space character */ +#define MK_SPACE_CHAR() (((Attribute_Byte) << 8) | 0x20) + +void SLtt_write_string (char *str) +{ + /* FIXME: Priority=medium + * This should not go to stdout. */ + fputs (str, stdout); +} + +void SLtt_goto_rc (int row, int col) +{ + row += Scroll_r1; + if (row > SLtt_Screen_Rows) row = SLtt_Screen_Rows; + if (col > SLtt_Screen_Cols) col = SLtt_Screen_Cols; + v_gotoxy (col, row); + Cursor_Row = row; + Cursor_Col = col; +} + +static void emx_video_getxy (void) +{ + v_getxy (&Cursor_Col, &Cursor_Row); +} + +static void emx_video_deleol (int x) +{ + unsigned char *p, *pmax; + int count = SLtt_Screen_Cols - x; + int w = MK_SPACE_CHAR (); + + p = Line_Buffer; + pmax = p + 2 * count; + + while (p < pmax) + { + *p++ = (unsigned char) w; + *p++ = (unsigned char) (w >> 8); + } + + v_putline (Line_Buffer, x, Cursor_Row, count); +} + +void SLtt_begin_insert (void) +{ + int n; + + emx_video_getxy (); + + n = SLtt_Screen_Cols - Cursor_Col; + v_getline (Line_Buffer, Cursor_Col, Cursor_Row, n); + v_putline (Line_Buffer, Cursor_Col+1, Cursor_Row, n - 1); +} + +void SLtt_end_insert (void) +{ +} + +void SLtt_delete_char (void) +{ + int n; + + emx_video_getxy (); + + n = SLtt_Screen_Cols - Cursor_Col - 1; + v_getline (Line_Buffer, Cursor_Col+1, Cursor_Row, n); + v_putline (Line_Buffer, Cursor_Col, Cursor_Row, n); +} + +void SLtt_erase_line (void) +{ + Attribute_Byte = 0x07; + emx_video_deleol (0); + Current_Color = JNO_COLOR; /* since we messed with attribute byte */ +} + +void SLtt_delete_nlines (int nlines) +{ + SLtt_normal_video (); + v_attrib (Attribute_Byte); + v_scroll (0, Scroll_r1, SLtt_Screen_Cols-1, Scroll_r2, nlines, V_SCROLL_UP); +} + +void SLtt_reverse_index (int nlines) +{ + SLtt_normal_video (); + + v_attrib (Attribute_Byte); + v_scroll (0, Scroll_r1, SLtt_Screen_Cols-1, Scroll_r2, nlines, + V_SCROLL_DOWN); +} + +static void emx_video_invert_region (int top_row, int bot_row) +{ + int row, col; + + for (row = top_row; row < bot_row; row++) + { + v_getline (Line_Buffer, 0, row, SLtt_Screen_Cols); + for (col = 1; col < SLtt_Screen_Cols * 2; col += 2) + Line_Buffer [col] ^= 0xff; + v_putline (Line_Buffer, 0, row, SLtt_Screen_Cols); + } +} + +void SLtt_beep (void) +{ + int audible; /* audible bell */ + int special = 0; /* first row to invert */ + int visual = 0; /* final row to invert */ + + if (!SLtt_Ignore_Beep) return; + + audible = (SLtt_Ignore_Beep & 1); + if ( (SLtt_Ignore_Beep & 4) ) + { + special = SLtt_Screen_Rows - 1; + visual = special--; /* only invert bottom status line */ + } + else if ( (SLtt_Ignore_Beep & 2) ) + { + visual = SLtt_Screen_Rows; + } + + if (visual) emx_video_invert_region (special, visual); + if (audible) /*sound (1500)*/; _sleep2 (100); if (audible) /* nosound () */; + if (visual) emx_video_invert_region (special, visual); +} + +void SLtt_del_eol (void) +{ + if (Current_Color != JNO_COLOR) SLtt_normal_video (); + emx_video_deleol (Cursor_Col); +} + +static void +write_attributes (SLsmg_Char_Type *src, unsigned int count) +{ + register unsigned char *p = Line_Buffer; + register unsigned short pair; + int n = count; + + /* write into a character/attribute pair */ + while (n-- > 0) + { + pair = SLSMG_CHAR_TO_USHORT(*src);/* character/color pair */ + src++; + SLtt_reverse_video (pair >> 8); /* color change */ + *(p++) = pair & 0xff; /* character byte */ + *(p++) = Attribute_Byte; /* attribute byte */ + } + v_putline (Line_Buffer, Cursor_Col, Cursor_Row, count); +} + +void SLtt_cls (void) +{ + SLtt_normal_video (); + SLtt_reset_scroll_region (); + SLtt_goto_rc (0, 0); + SLtt_delete_nlines (SLtt_Screen_Rows); +} + +void SLtt_putchar (char ch) +{ + if (Current_Color) SLtt_normal_video (); + + emx_video_getxy (); /* get current position */ + switch (ch) + { + case 7: /* ^G - break */ + SLtt_beep (); break; + case 8: /* ^H - backspace */ + goto_rc_abs (Cursor_Row, Cursor_Col - 1); break; + case 13: /* ^M - carriage return */ + goto_rc_abs (Cursor_Row, 0); break; + default: /* write character to screen */ + v_putn (ch, 1); + goto_rc_abs (Cursor_Row, Cursor_Col + 1); + } +} + +void SLtt_get_terminfo (void) +{ + SLtt_get_screen_size (); +} + +void SLtt_get_screen_size (void) +{ + vioModeInfo.cb = sizeof(vioModeInfo); + VioGetMode (&vioModeInfo, 0); + SLtt_Screen_Cols = vioModeInfo.col; + SLtt_Screen_Rows = vioModeInfo.row; +} + +int SLtt_init_video (void) +{ + int OldCol, OldRow; + PTIB ptib; + PPIB ppib; + USHORT args[3] = { 6, 2, 1 }; + +#ifdef HAS_SAVE_SCREEN + save_screen (); +#endif + + Cursor_Row = Cursor_Col = 0; + + v_init (); + if ( v_hardware () != V_MONOCHROME ) IsColor = 1; else IsColor = 0; + + v_getxy(&OldCol,&OldRow); + v_gotoxy (0, 0); + if (IsColor) + { + if (_osmode == OS2_MODE) + { +# if 0 + /* Enable high-intensity background colors */ + VIOINTENSITY RequestBlock; + RequestBlock.cb = sizeof (RequestBlock); + RequestBlock.type = 2; RequestBlock.fs = 1; + VioSetState (&RequestBlock, 0); /* nop if !fullscreen */ +# endif + } + } + + DosGetInfoBlocks (&ptib, &ppib); + if ((ppib->pib_ultype) == 2) /* VIO */ + Blink_Killed = 1; + else + { /* Fullscreen */ + if (VioSetState (args, 0) == 0) + Blink_Killed = 1; + else + Blink_Killed = 0; + } + + if (!Attribute_Byte) + { + /* find the attribute currently under the cursor */ + v_getline (Line_Buffer, OldCol, OldRow, 1); + Attribute_Byte = Line_Buffer[1]; + SLtt_set_color (JNORMAL_COLOR, NULL, + Color_Names[(Attribute_Byte) & 0xf], + Color_Names[(Attribute_Byte) >> 4]); + } + + v_attrib (Attribute_Byte); + + fixup_colors (); + + SLtt_get_screen_size (); + SLtt_Use_Ansi_Colors = IsColor; + SLtt_reset_scroll_region (); + return 0; +} + +#endif /* EMX_VIDEO */ + +/*}}}*/ + +#ifdef WIN32_VIDEO /*{{{*/ + +#include <windows.h> + +static HANDLE hStdout = INVALID_HANDLE_VALUE; + +#define MAXCOLS 256 +static CHAR_INFO Line_Buffer [MAXCOLS]; + +void SLtt_write_string (char *str) +{ + DWORD bytes; + int n, c; + if (str == NULL) return; + + n = (int) strlen (str); + c = n + Cursor_Col; + if (c >= SLtt_Screen_Cols) + n = SLtt_Screen_Cols - Cursor_Col; + if (n < 0) n = 0; + + (void) WriteConsole (hStdout, str, (unsigned int) n, &bytes, NULL); + + goto_rc_abs (Cursor_Row, Cursor_Col + n); +} + +void SLtt_goto_rc (int row, int col) +{ + COORD newPosition; + + row += Scroll_r1; + if (row > SLtt_Screen_Rows) row = SLtt_Screen_Rows; + if (col > SLtt_Screen_Cols) col = SLtt_Screen_Cols; + newPosition.X = col; + newPosition.Y = row; + + (void) SetConsoleCursorPosition(hStdout, newPosition); + + Cursor_Row = row; + Cursor_Col = col; +} + +static void win32_video_getxy (void) +{ + CONSOLE_SCREEN_BUFFER_INFO screenInfo; + + if (TRUE == GetConsoleScreenBufferInfo(hStdout, &screenInfo)) + { + Cursor_Row = screenInfo.dwCursorPosition.Y; + Cursor_Col = screenInfo.dwCursorPosition.X; + } +} + +static void win32_video_hscroll (int n) +{ + SMALL_RECT rc; + COORD c; + CHAR_INFO ci; + WORD w = 227; + DWORD d; + + win32_video_getxy (); + + rc.Left = Cursor_Col; + rc.Right = SLtt_Screen_Cols; + rc.Top = rc.Bottom = Cursor_Row; + + c.Y = Cursor_Row; +#if 1 + c.X = SLtt_Screen_Cols - 1; + ReadConsoleOutputAttribute(hStdout, &w, 1, c, &d); +#else + /* New region gets the current color */ + w = Attribute_Byte; +#endif + c.X = Cursor_Col + n; + + ci.Char.AsciiChar = ' '; + ci.Attributes = w; + + ScrollConsoleScreenBuffer(hStdout, &rc, &rc, c, &ci); +} + +static void win32_video_deleol (int x) +{ + DWORD d; + COORD c; + + c.X = x; + c.Y = Cursor_Row; + + x = SLtt_Screen_Cols - x; + FillConsoleOutputCharacter(hStdout, ' ', x, c, &d); + FillConsoleOutputAttribute(hStdout, (char)Attribute_Byte, x, c, &d); +} + +static void win32_video_vscroll (int n) +{ + SMALL_RECT rc, clip_rc; + COORD c; + CHAR_INFO ci; + + SLtt_normal_video(); + + /* ScrollConsoleScreenBuffer appears to have a bug when + * Scroll_r1 == Scroll_r2. Sigh. + */ + if (Scroll_r2 == Scroll_r1) + { + SLtt_goto_rc (0, 0); + win32_video_deleol (0); + return; + } + + rc.Left = clip_rc.Left = 0; + rc.Right = clip_rc.Right = SLtt_Screen_Cols - 1; + rc.Top = clip_rc.Top = Scroll_r1; + rc.Bottom = clip_rc.Bottom = Scroll_r2; + + c.X = 0; + c.Y = Scroll_r1 + n; + + ci.Char.AsciiChar = ' '; + ci.Attributes = Attribute_Byte; + + ScrollConsoleScreenBuffer(hStdout, &rc, &clip_rc, c, &ci); +} + +void SLtt_begin_insert (void) +{ + win32_video_hscroll (1); +} + +void SLtt_end_insert (void) +{ +} + +void SLtt_delete_char (void) +{ + win32_video_hscroll (-1); +} + +void SLtt_erase_line (void) +{ + Attribute_Byte = 0x7; + win32_video_deleol (0); + Current_Color = JNO_COLOR; +} + +void SLtt_delete_nlines (int nlines) +{ + win32_video_vscroll (-nlines); +} + +void SLtt_reverse_index (int nlines) +{ + win32_video_vscroll (nlines); +} + +static void win32_invert_region (int top_row, int bot_row) +{ + (void) top_row; (void) bot_row; +} + +void SLtt_beep (void) +{ + int audible; /* audible bell */ + int special = 0; /* first row to invert */ + int visual = 0; /* final row to invert */ + + if (!SLtt_Ignore_Beep) return; + + audible = (SLtt_Ignore_Beep & 1); + + if ( (SLtt_Ignore_Beep & 4) ) + { + special = SLtt_Screen_Rows - 1; + visual = special--; /* only invert bottom status line */ + } + else if ( (SLtt_Ignore_Beep & 2) ) + { + visual = SLtt_Screen_Rows; + } + + if (visual) win32_invert_region (special, visual); + if (audible) Beep (1500, 100); else Sleep (100); + if (visual) win32_invert_region (special, visual); +} + +void SLtt_del_eol (void) +{ + if (Current_Color != JNO_COLOR) + SLtt_normal_video (); + win32_video_deleol (Cursor_Col); +} + +static void +write_attributes (SLsmg_Char_Type *src, unsigned int count) +{ + unsigned short pair; + COORD coord, c; + CHAR_INFO *p; + unsigned int n; + SMALL_RECT rc; + + /* write into a character/attribute pair */ + n = count; + p = Line_Buffer; + while (n) + { + n--; + pair = SLSMG_CHAR_TO_USHORT(*src);/* character/color pair */ + src++; + SLtt_reverse_video (pair >> 8); /* color change */ + p->Char.AsciiChar = pair & 0xff; + p->Attributes = Attribute_Byte; + p++; + } + + c.X = count; + c.Y = 1; + coord.X = coord.Y = 0; + rc.Left = Cursor_Col; + rc.Right = Cursor_Col + count - 1; + rc.Top = rc.Bottom = Cursor_Row; + WriteConsoleOutput(hStdout, Line_Buffer, c, coord, &rc); +} + +void SLtt_cls (void) +{ + DWORD bytes; + COORD coord; + char ch; + + SLtt_normal_video (); + /* clear the WIN32 screen in one shot */ + coord.X = 0; + coord.Y = 0; + + ch = ' '; + + (void) FillConsoleOutputCharacter(hStdout, + ch, + SLtt_Screen_Cols * SLtt_Screen_Rows, + coord, + &bytes); + + /* now set screen to the current attribute */ + ch = Attribute_Byte; + (void) FillConsoleOutputAttribute(hStdout, + ch, + SLtt_Screen_Cols * SLtt_Screen_Rows, + coord, + &bytes); +} + +void SLtt_putchar (char ch) +{ + DWORD bytes; + WORD attr; + COORD c; + + if (Current_Color) SLtt_normal_video (); + win32_video_getxy (); + switch (ch) + { + case 7: /* ^G - break */ + SLtt_beep (); break; + case 8: /* ^H - backspace */ + goto_rc_abs (Cursor_Row, Cursor_Col - 1); break; + case 13: /* ^M - carriage return */ + goto_rc_abs (Cursor_Row, 0); break; + default: /* write character to screen */ + c.X = Cursor_Col; + c.Y = Cursor_Row; + attr = Attribute_Byte; + WriteConsoleOutputCharacter(hStdout, &ch, 1, c, &bytes); + WriteConsoleOutputAttribute(hStdout, &attr, 1, c, &bytes); + goto_rc_abs (Cursor_Row, Cursor_Col + 1); + } +} + +void SLtt_get_screen_size (void) +{ + CONSOLE_SCREEN_BUFFER_INFO csbi; + HANDLE h; + + h = hStdout; + if (h == INVALID_HANDLE_VALUE) + h = GetStdHandle (STD_OUTPUT_HANDLE); + + if ((h == INVALID_HANDLE_VALUE) + || (FALSE == GetConsoleScreenBufferInfo(h, &csbi))) + { + SLang_exit_error ("Unable to determine the screen size"); + return; + } +#if 0 + SLtt_Screen_Rows = csbi.dwSize.Y; + SLtt_Screen_Cols = csbi.dwSize.X; +#else + SLtt_Screen_Rows = (csbi.srWindow.Bottom - csbi.srWindow.Top) + 1; + SLtt_Screen_Cols = (csbi.srWindow.Right - csbi.srWindow.Left) + 1; +#endif +} + +void SLtt_get_terminfo (void) +{ + SLtt_get_screen_size (); +} + +static int win32_resize (void) +{ + SMALL_RECT windowRect; + + SLtt_get_screen_size (); + + windowRect.Left = 0; + windowRect.Top = 0; + windowRect.Right = SLtt_Screen_Cols - 1; + windowRect.Bottom = SLtt_Screen_Rows - 1; + + if (FALSE == SetConsoleWindowInfo(hStdout, TRUE, &windowRect)) + return -1; + + return 0; +} + +static int win32_init (void) +{ + SECURITY_ATTRIBUTES sec; + + memset ((char *) &sec, 0, sizeof(SECURITY_ATTRIBUTES)); + sec.nLength = sizeof (SECURITY_ATTRIBUTES); + sec.bInheritHandle = FALSE; + + hStdout = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ|FILE_SHARE_WRITE, + &sec, + CONSOLE_TEXTMODE_BUFFER, + 0); + + if (hStdout == INVALID_HANDLE_VALUE) + return -1; + + if ((FALSE == SetConsoleActiveScreenBuffer(hStdout)) + || (FALSE == SetConsoleMode(hStdout, 0)) + || (-1 == win32_resize ())) + { + SLtt_reset_video (); + return -1; + } + + return 0; +} + +int SLtt_init_video (void) +{ + SLtt_reset_video (); + + if (-1 == win32_init ()) + return -1; + + /* It is possible for SLtt_init_video to be called after suspension. + * For all I know, the window size may have changed. So, resize it + * now. + */ + + Cursor_Row = Cursor_Col = 0; + SLtt_Use_Ansi_Colors = IsColor = 1; + Blink_Killed = 1; + + SLtt_reset_scroll_region (); + goto_rc_abs (0, 0); + fixup_colors (); + + return 0; +} + +int SLtt_reset_video (void) +{ + if (hStdout == INVALID_HANDLE_VALUE) + return 0; + + SLtt_reset_scroll_region (); + SLtt_goto_rc (SLtt_Screen_Rows - 1, 0); + Attribute_Byte = 0x7; + Current_Color = JNO_COLOR; + SLtt_del_eol (); + (void) CloseHandle (hStdout); + + hStdout = GetStdHandle (STD_OUTPUT_HANDLE); + if (hStdout != INVALID_HANDLE_VALUE) + (void) SetConsoleActiveScreenBuffer(hStdout); + + hStdout = INVALID_HANDLE_VALUE; + return 0; +} + +#endif + +/*}}}*/ + +#ifdef OS2_VIDEO /*{{{*/ + +# define INCL_BASE +# define INCL_NOPM +# define INCL_VIO +# define INCL_KBD + +# define INCL_DOSPROCESS + +# include <os2.h> +# ifndef __IBMC__ +# include <dos.h> +# endif +/* this is how to make a space character */ +#define MK_SPACE_CHAR() (((Attribute_Byte) << 8) | 0x20) + +/* buffer to hold a line of character/attribute pairs */ +#define MAXCOLS 256 +static unsigned char Line_Buffer [MAXCOLS*2]; + +void SLtt_write_string (char *str) +{ + /* FIXME: Priority=medium + * This should not go to stdout. */ + fputs (str, stdout); +} + +void SLtt_goto_rc (int row, int col) +{ + row += Scroll_r1; + VioSetCurPos (row, col, 0); + Cursor_Row = row; + Cursor_Col = col; +} + +static void os2_video_getxy (void) +{ + USHORT r, c; + + VioGetCurPos (&r, &c, 0); + Cursor_Row = r; + Cursor_Col = c; +} + +void SLtt_begin_insert (void) +{ + USHORT n; + + os2_video_getxy (); + n = SLtt_Screen_Cols - Cursor_Col; + + n = 2 * (n - 1); + VioReadCellStr ((PCH)Line_Buffer, &n, Cursor_Row, Cursor_Col, 0); + VioWrtCellStr ((PCH)Line_Buffer, n, Cursor_Row, Cursor_Col + 1, 0); +} + +void SLtt_end_insert (void) +{ +} + +void SLtt_delete_char (void) +{ + USHORT n; + + os2_video_getxy (); + n = SLtt_Screen_Cols - Cursor_Col - 1; + + n *= 2; + VioReadCellStr ((PCH)Line_Buffer, &n, Cursor_Row, Cursor_Col + 1, 0); + VioWrtCellStr ((PCH)Line_Buffer, n, Cursor_Row, Cursor_Col, 0); +} + +void SLtt_erase_line (void) +{ + USHORT w; + + Attribute_Byte = 0x07; + w = MK_SPACE_CHAR (); + + VioWrtNCell ((BYTE*)&w, SLtt_Screen_Cols, Cursor_Row, 0, 0); + + Current_Color = JNO_COLOR; /* since we messed with attribute byte */ +} + +void SLtt_delete_nlines (int nlines) +{ + SLtt_normal_video (); + + Line_Buffer[0] = ' '; Line_Buffer[1] = Attribute_Byte; + VioScrollUp (Scroll_r1, 0, Scroll_r2, SLtt_Screen_Cols-1, + nlines, (PCH) Line_Buffer, 0); +} + +void SLtt_reverse_index (int nlines) +{ + SLtt_normal_video (); + + Line_Buffer[0] = ' '; Line_Buffer[1] = Attribute_Byte; + VioScrollDn (Scroll_r1, 0, Scroll_r2, SLtt_Screen_Cols-1, + nlines, (PCH) Line_Buffer, 0); +} + +static void os2_video_invert_region (int top_row, int bot_row) +{ + int row, col; + USHORT length = SLtt_Screen_Cols * 2; + + for (row = top_row; row < bot_row; row++) + { + VioReadCellStr ((PCH)Line_Buffer, &length, row, 0, 0); + for (col = 1; col < length; col += 2) + Line_Buffer [col] ^= 0xff; + VioWrtCellStr ((PCH)Line_Buffer, length, row, 0, 0); + } +} + +void SLtt_beep (void) +{ + int audible; /* audible bell */ + int special = 0; /* first row to invert */ + int visual = 0; /* final row to invert */ + + if (!SLtt_Ignore_Beep) return; + + audible = (SLtt_Ignore_Beep & 1); + + if ( (SLtt_Ignore_Beep & 4) ) + { + special = SLtt_Screen_Rows - 1; + visual = special--; /* only invert bottom status line */ + } + else if ( (SLtt_Ignore_Beep & 2) ) + { + visual = SLtt_Screen_Rows; + } + + if (visual) os2_video_invert_region (special, visual); + if (audible) DosBeep (1500, 100); else DosSleep (100); + if (visual) os2_video_invert_region (special, visual); +} + +void SLtt_del_eol (void) +{ + USHORT w; + if (Current_Color != JNO_COLOR) SLtt_normal_video (); + + w = MK_SPACE_CHAR (); + + VioWrtNCell ((BYTE*)&w, (SLtt_Screen_Cols - Cursor_Col), + Cursor_Row, Cursor_Col, 0); +} + +static void +write_attributes (SLsmg_Char_Type *src, unsigned int count) +{ + register unsigned char *p = Line_Buffer; + register unsigned short pair; + int n = count; + + /* write into a character/attribute pair */ + while (n-- > 0) + { + pair = SLSMG_CHAR_TO_USHORT(*src);/* character/color pair */ + src++; + SLtt_reverse_video (pair >> 8); /* color change */ + *(p++) = pair & 0xff; /* character byte */ + *(p++) = Attribute_Byte; /* attribute byte */ + } + + VioWrtCellStr ((PCH)Line_Buffer, (USHORT)(2 * count), + (USHORT)Cursor_Row, (USHORT)Cursor_Col, 0); +} + +void SLtt_cls (void) +{ + SLtt_normal_video (); + Line_Buffer [0] = ' '; Line_Buffer [1] = Attribute_Byte; + VioScrollUp (0, 0, -1, -1, -1, (PCH)Line_Buffer, 0); +} + +void SLtt_putchar (char ch) +{ + unsigned short p, *pp; + + if (Current_Color) SLtt_normal_video (); + os2_video_getxy (); /* get current position */ + + switch (ch) + { + case 7: /* ^G - break */ + SLtt_beep (); break; + case 8: /* ^H - backspace */ + goto_rc_abs (Cursor_Row, Cursor_Col - 1); break; + case 13: /* ^M - carriage return */ + goto_rc_abs (Cursor_Row, 0); break; + default: /* write character to screen */ + VioWrtCharStrAtt (&ch, 1, Cursor_Row, Cursor_Col, + (BYTE*)&Attribute_Byte, 0); + goto_rc_abs (Cursor_Row, Cursor_Col + 1); + } +} + +void SLtt_get_screen_size (void) +{ +#ifdef __os2__ +# ifdef __IBMC__ + VIOMODEINFO vioModeInfo; +# endif + vioModeInfo.cb = sizeof(vioModeInfo); + VioGetMode (&vioModeInfo, 0); + SLtt_Screen_Cols = vioModeInfo.col; + SLtt_Screen_Rows = vioModeInfo.row; +#endif +} + +void SLtt_get_terminfo (void) +{ + SLtt_get_screen_size (); +} + +int SLtt_init_video (void) +{ + VIOINTENSITY RequestBlock; + PTIB ptib; + PPIB ppib; + USHORT args[3] = { 6, 2, 1 }; + + Cursor_Row = Cursor_Col = 0; + + IsColor = 1; /* is it really? */ + + /* Enable high-intensity background colors */ + RequestBlock.cb = sizeof (RequestBlock); + RequestBlock.type = 2; RequestBlock.fs = 1; + VioSetState (&RequestBlock, 0); /* nop if !fullscreen */ + + DosGetInfoBlocks (&ptib, &ppib); + if ((ppib->pib_ultype) == 2) /* VIO */ + Blink_Killed = 1; + else + { /* Fullscreen */ + if (VioSetState (args, 0) == 0) + Blink_Killed = 1; + else + Blink_Killed = 0; + } + + if (!Attribute_Byte) + { + /* find the attribute currently under the cursor */ + USHORT len, r, c; + + len = 2; + VioGetCurPos (&r, &c, 0); + VioReadCellStr ((PCH)Line_Buffer, &len, r, c, 0); + Attribute_Byte = Line_Buffer[1]; + + SLtt_set_color (JNORMAL_COLOR, NULL, + Color_Names[(Attribute_Byte) & 0xf], + Color_Names[(Attribute_Byte) >> 4]); + } + + SLtt_Use_Ansi_Colors = IsColor; + SLtt_get_screen_size (); + SLtt_reset_scroll_region (); + fixup_colors (); + + return 0; +} + +#endif /* OS2_VIDEO */ +/*}}}*/ + +#ifdef WATCOM_VIDEO /*{{{*/ + +# include <graph.h> +# define int86 int386 /* simplify code writing */ + +#include <dos.h> + +/* this is how to make a space character */ +#define MK_SPACE_CHAR() (((Attribute_Byte) << 8) | 0x20) + +/* buffer to hold a line of character/attribute pairs */ +#define MAXCOLS 256 +static unsigned char Line_Buffer [MAXCOLS*2]; + +/* define for direct to memory screen writes */ +static unsigned char *Video_Base; +#define MK_SCREEN_POINTER(row,col) \ + ((unsigned short *)(Video_Base + 2 * (SLtt_Screen_Cols * (row) + (col)))) + +#define ScreenPrimary (0xb800 << 4) +#define ScreenSize (SLtt_Screen_Cols * SLtt_Screen_Rows) +#define ScreenSetCursor(x,y) _settextposition (x+1,y+1) + +void ScreenGetCursor (int *x, int *y) +{ + struct rccoord rc = _gettextposition (); + *x = rc.row - 1; + *y = rc.col - 1; +} + +void ScreenRetrieve (unsigned char *dest) +{ + memcpy (dest, (unsigned char *) ScreenPrimary, 2 * ScreenSize); +} + +void ScreenUpdate (unsigned char *src) +{ + memcpy ((unsigned char *) ScreenPrimary, src, 2 * ScreenSize); +} + +void SLtt_write_string (char *str) +{ + /* FIXME: Priority=medium + * This should not go to stdout. */ + fputs (str, stdout); +} + +void SLtt_goto_rc (int row, int col) +{ + row += Scroll_r1; + if (row > SLtt_Screen_Rows) row = SLtt_Screen_Rows; + if (col > SLtt_Screen_Cols) col = SLtt_Screen_Cols; + ScreenSetCursor(row, col); + Cursor_Row = row; + Cursor_Col = col; +} + +static void watcom_video_getxy (void) +{ + ScreenGetCursor (&Cursor_Row, &Cursor_Col); +} + +void SLtt_begin_insert (void) +{ + unsigned short *p; + unsigned short *pmin; + int n; + + watcom_video_getxy (); + n = SLtt_Screen_Cols - Cursor_Col; + + p = MK_SCREEN_POINTER (Cursor_Row, SLtt_Screen_Cols - 1); + pmin = MK_SCREEN_POINTER (Cursor_Row, Cursor_Col); + + while (p-- > pmin) *(p + 1) = *p; +} + +void SLtt_end_insert (void) +{ +} + +void SLtt_delete_char (void) +{ + unsigned short *p; + register unsigned short *p1; + int n; + + watcom_video_getxy (); + n = SLtt_Screen_Cols - Cursor_Col - 1; + + p = MK_SCREEN_POINTER (Cursor_Row, Cursor_Col); + while (n--) + { + p1 = p + 1; + *p = *p1; + p++; + } +} + +void SLtt_erase_line (void) +{ + unsigned short w; + unsigned short *p = MK_SCREEN_POINTER (Cursor_Row, 0); + register unsigned short *pmax = p + SLtt_Screen_Cols; + + Attribute_Byte = 0x07; + w = MK_SPACE_CHAR (); + while (p < pmax) *p++ = w; + Current_Color = JNO_COLOR; /* since we messed with attribute byte */ +} + +void SLtt_delete_nlines (int nlines) +{ + union REGS r; + + SLtt_normal_video (); + r.x.eax = nlines; + r.x.ecx = 0; + r.h.ah = 6; + r.h.ch = Scroll_r1; + r.h.dl = SLtt_Screen_Cols - 1; + r.h.dh = Scroll_r2; + r.h.bh = Attribute_Byte; + int86 (0x10, &r, &r); +} + +void SLtt_reverse_index (int nlines) +{ + union REGS r; + + SLtt_normal_video (); + r.h.al = nlines; + r.x.ecx = 0; + r.h.ah = 7; + r.h.ch = Scroll_r1; + r.h.dl = SLtt_Screen_Cols - 1; + r.h.dh = Scroll_r2; + r.h.bh = Attribute_Byte; + int86 (0x10, &r, &r); +} + +static void watcom_video_invert_region (int top_row, int bot_row) +{ + unsigned char buf [2 * 180 * 80]; /* 180 cols x 80 rows */ + unsigned char *b, *bmax; + + b = buf + 1 + 2 * SLtt_Screen_Cols * top_row; + bmax = buf + 1 + 2 * SLtt_Screen_Cols * bot_row; + ScreenRetrieve (buf); + while (b < bmax) + { + *b ^= 0xFF; + b += 2; + } + ScreenUpdate (buf); +} + +void SLtt_beep (void) +{ + int audible; /* audible bell */ + int special = 0; /* first row to invert */ + int visual = 0; /* final row to invert */ + + if (!SLtt_Ignore_Beep) return; + + audible = (SLtt_Ignore_Beep & 1); + if ( (SLtt_Ignore_Beep & 4) ) + { + special = SLtt_Screen_Rows - 1; + visual = special--; /* only invert bottom status line */ + } + else if ( (SLtt_Ignore_Beep & 2) ) + { + visual = SLtt_Screen_Rows; + } + + if (visual) watcom_video_invert_region (special, visual); + if (audible) sound (1500); delay (100); if (audible) nosound (); + if (visual) watcom_video_invert_region (special, visual); +} + +void SLtt_del_eol (void) +{ + unsigned short *p, *pmax; + unsigned short w; + int n; + + n = SLtt_Screen_Cols - Cursor_Col; + p = MK_SCREEN_POINTER (Cursor_Row, Cursor_Col); + pmax = p + n; + + if (Current_Color != JNO_COLOR) SLtt_normal_video (); + + w = MK_SPACE_CHAR (); + while (p < pmax) *p++ = w; +} + +static void +write_attributes (SLsmg_Char_Type *src, unsigned int count) +{ + register unsigned short pair; + register unsigned short *pos = MK_SCREEN_POINTER (Cursor_Row, 0); + + /* write into a character/attribute pair */ + while (count--) + { + pair = SLSMG_CHAR_TO_USHORT(*src);/* character/color pair */ + src++; + SLtt_reverse_video (pair >> 8); /* color change */ + *(pos++) = ((unsigned short) Attribute_Byte << 8) | (pair & 0xff); + } +} + +void SLtt_cls (void) +{ + SLtt_normal_video (); + SLtt_reset_scroll_region (); + SLtt_goto_rc (0, 0); + SLtt_delete_nlines (SLtt_Screen_Rows); +} + +void SLtt_putchar (char ch) +{ + unsigned short p, *pp; + + if (Current_Color) SLtt_normal_video (); + watcom_video_getxy (); + switch (ch) + { + case 7: /* ^G - break */ + SLtt_beep (); break; + case 8: /* ^H - backspace */ + goto_rc_abs (Cursor_Row, Cursor_Col - 1); break; + case 13: /* ^M - carriage return */ + goto_rc_abs (Cursor_Row, 0); break; + default: /* write character to screen */ + p = (Attribute_Byte << 8) | (unsigned char) ch; + pp = MK_SCREEN_POINTER (Cursor_Row, Cursor_Col); + *pp = p; + goto_rc_abs (Cursor_Row, Cursor_Col + 1); + } +} + +void SLtt_get_screen_size (void) +{ + struct videoconfig vc; + _getvideoconfig(&vc); + + SLtt_Screen_Rows = vc.numtextrows; + SLtt_Screen_Cols = vc.numtextcols; +} + +void SLtt_get_terminfo (void) +{ + SLtt_get_screen_size (); +} + +int SLtt_init_video (void) +{ +#ifdef HAS_SAVE_SCREEN + save_screen (); +#endif + + Cursor_Row = Cursor_Col = 0; + Video_Base = (unsigned char *) ScreenPrimary; + if (!Attribute_Byte) Attribute_Byte = 0x17; + IsColor = 1; /* is it really? */ + + if (IsColor) + { + union REGS r; + r.x.eax = 0x1003; r.x.ebx = 0; + int86 (0x10, &r, &r); + Blink_Killed = 1; + } + + SLtt_Use_Ansi_Colors = IsColor; + SLtt_get_screen_size (); + SLtt_reset_scroll_region (); + fixup_colors (); + + return 0; +} + +#endif /* WATCOM_VIDEO */ + +/*}}}*/ + +/* -------------------------------------------------------------------------*\ + * The rest of the functions are, for the most part, independent of a specific + * video system. +\* ------------------------------------------------------------------------ */ + +/*----------------------------------------------------------------------*\ + * Function: void SLtt_set_scroll_region (int r1, int r2); + * + * define a scroll region of top_row to bottom_row +\*----------------------------------------------------------------------*/ +void SLtt_set_scroll_region (int top_row, int bottom_row) +{ + Scroll_r1 = top_row; + Scroll_r2 = bottom_row; +} + +/*----------------------------------------------------------------------*\ + * Function: void SLtt_reset_scroll_region (void); + * + * reset the scrol region to be the entire screen, + * ie, SLtt_set_scroll_region (0, SLtt_Screen_Rows); +\*----------------------------------------------------------------------*/ +void SLtt_reset_scroll_region (void) +{ + Scroll_r1 = 0; + Scroll_r2 = SLtt_Screen_Rows - 1; +} + +/*----------------------------------------------------------------------*\ + * Function: int SLtt_flush_output (void); +\*----------------------------------------------------------------------*/ +int SLtt_flush_output (void) +{ +#if defined(WIN32_VIDEO) + return 0; +#else + /* FIXME: Priority=medium + * This should not go to stdout. */ + fflush (stdout); + return 0; +#endif +} + +int SLtt_set_cursor_visibility (int show) +{ +#if defined(WIN32_VIDEO) + CONSOLE_CURSOR_INFO c; + + if (0 == GetConsoleCursorInfo (hStdout, &c)) + return -1; + c.bVisible = (show ? TRUE: FALSE); + if (0 == SetConsoleCursorInfo (hStdout, &c)) + return -1; + return 0; +#else + (void) show; + return -1; +#endif +} + +/*----------------------------------------------------------------------*\ + * Function: void SLtt_reverse_video (int color); + * + * set Attribute_Byte corresponding to COLOR. + * Use Current_Color to remember the color which was set. + * convert from the COLOR number to the attribute value. +\*----------------------------------------------------------------------*/ +void SLtt_reverse_video (int color) +{ + if ((color >= JMAX_COLORS) || (color < 0)) + return; + + Attribute_Byte = Color_Map [color]; + Current_Color = color; +} + +/*----------------------------------------------------------------------*\ + * Function: void SLtt_normal_video (void); + * + * reset the attributes for normal video +\*----------------------------------------------------------------------*/ +void SLtt_normal_video (void) +{ + SLtt_reverse_video (JNORMAL_COLOR); +} + +/*----------------------------------------------------------------------*\ + * Function: void SLtt_smart_puts (SLsmg_Char_Type *new_string, + * SLsmg_Char_Type *old_string, + * int len, int row); + * + * puts NEW_STRING, which has length LEN, at row ROW. NEW_STRING contains + * characters/colors packed in the form value = ((color << 8) | (ch)); + * + * the puts tries to avoid overwriting the same characters/colors + * + * OLD_STRING is not used, maintained for compatibility with other systems +\*----------------------------------------------------------------------*/ +void SLtt_smart_puts (SLsmg_Char_Type *new_string, + SLsmg_Char_Type *old_string, + int len, int row) +{ + (void) old_string; + Cursor_Row = row; + Cursor_Col = 0; + write_attributes (new_string, len); +} + +/*----------------------------------------------------------------------*\ + * Function: int SLtt_reset_video (void); +\*----------------------------------------------------------------------*/ +#ifndef WIN32_VIDEO +int SLtt_reset_video (void) +{ + SLtt_reset_scroll_region (); + SLtt_goto_rc (SLtt_Screen_Rows - 1, 0); +#ifdef HAS_SAVE_SCREEN + restore_screen (); +#endif + Attribute_Byte = 0x07; + Current_Color = JNO_COLOR; + SLtt_del_eol (); + return 0; +} +#endif + +/*----------------------------------------------------------------------*\ + * Function: void SLtt_set_color (int obj, char *what, char *fg, char *bg); + * + * set foreground and background colors of OBJ to the attributes which + * correspond to the names FG and BG, respectively. + * + * WHAT is the name corresponding to the object OBJ, but is not used in + * this routine. +\*----------------------------------------------------------------------*/ +void SLtt_set_color (int obj, char *what, char *fg, char *bg) +{ + int i, b = 0, f = 7; + + (void) what; + + if ((obj < 0) || (obj >= JMAX_COLORS)) + return; + + for (i = 0; i < JMAX_COLOR_NAMES; i++ ) + { + if (!strcmp (fg, Color_Names [i])) + { + f = i; + break; + } + } + + for (i = 0; i < JMAX_COLOR_NAMES; i++) + { + if (!strcmp (bg, Color_Names [i])) + { + if (Blink_Killed) b = i; else b = i & 0x7; + break; + } + } + if (f == b) return; + + Color_Map [obj] = (b << 4) | f; + + /* if we're setting the normal color, and the attribute byte hasn't + been set yet, set it to the new color */ + if ((obj == 0) && (Attribute_Byte == 0)) + SLtt_reverse_video (0); + + if (_SLtt_color_changed_hook != NULL) + (*_SLtt_color_changed_hook)(); +} + +static void fixup_colors (void) +{ + unsigned int i; + + if (Blink_Killed) + return; + + for (i = 0; i < JMAX_COLORS; i++) + Color_Map[i] &= 0x7F; + + SLtt_normal_video (); +} + + +/* FIXME!!! Add mono support. + * The following functions have not been fully implemented. + */ +void SLtt_set_mono (int obj_unused, char *unused, SLtt_Char_Type c_unused) +{ + (void) obj_unused; + (void) unused; + (void) c_unused; +} + +#if 0 +void SLtt_add_color_attribute (int obj, SLtt_Char_Type attr) +{ + (void) obj; + (void) attr; +} +#endif |