slvideo.c
字号:
/* -*- 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 -1static 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 16static 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 256static 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -