📄 slvideo.c
字号:
/* Copyright (c) 1992, 1995 John E. Davis
* All rights reserved.
*
* You may distribute under the terms of either the GNU General Public
* License or the Perl Artistic License.
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifdef __WIN32__
# include <windows.h>
#endif
#ifdef __GO32__
# undef msdos
#endif
#if defined (msdos)
# include <conio.h>
# include <bios.h>
# include <mem.h>
#endif
#if defined (__WATCOMC__)
# include <graph.h>
# define int86 int386 /* simplify code writing */
#endif
#if defined (__GO32__)
# include <pc.h>
# define GO32_VIDEO
#endif
#if defined (__os2__) && !defined (EMX_VIDEO)
# define INCL_BASE
# define INCL_NOPM
# define INCL_VIO
# define INCL_KBD
# include <os2.h>
#else
# if defined (__EMX__) /* EMX video does both DOS & OS/2 */
# ifndef EMX_VIDEO
# define EMX_VIDEO
# endif
# include <sys/video.h>
# endif
#endif
#include <dos.h>
#include "slang.h"
#ifdef GO32_VIDEO
# define HAS_SAVE_SCREEN
#endif
/* ------------------------- global variables ------------------------- */
#ifdef WIN32
extern HANDLE hStdout, hStdin;
extern CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
#endif
int SLtt_Term_Cannot_Insert;
int SLtt_Term_Cannot_Scroll;
int SLtt_Ignore_Beep = 3;
int SLtt_Use_Ansi_Colors;
int SLtt_Screen_Rows = 25;
int SLtt_Screen_Cols = 80;
/* ------------------------- 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; /* 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 char *Color_Names [JMAX_COLOR_NAMES] =
{
"black", "blue", "green", "cyan",
"red", "magenta", "brown", "lightgray",
"gray", "brightblue", "brightgreen", "brightcyan",
"brightred", "brightmagenta", "yellow", "white"
};
/*
* set_color_from_attribute (int attribute);
* define the correspondence of color to attribute
*/
#define set_color_from_attribute(a)\
SLtt_set_color (\
JNORMAL_COLOR, NULL,\
Color_Names[(a) & 0xf],\
Color_Names[(a) >> 4])
/* this is how to make a space character */
#define mkSpaceChar() (((Attribute_Byte) << 8) | 0x20)
/* buffer to hold a line of character/attribute pairs */
#define MAXCOLS 256
static unsigned char Line_Buffer [MAXCOLS*2];
/*----------------------------------------------------------------------*\
* define various ways and means of writing to the screen
\*----------------------------------------------------------------------*/
#if defined (__GO32__) || defined (__WATCOMC__)
# if !defined (GO32_VIDEO)
# define HAS_LINEAR_SCREEN
# endif
#else /* __GO32__ or __WATCOMC__ */
# if defined (msdos)
# define USE_ASM
# endif
#endif /* __GO32__ or __WATCOMC__ */
/* define for direct to memory screen writes */
#if defined (USE_ASM) || defined (HAS_LINEAR_SCREEN)
static unsigned char *Video_Base;
# define mkScreenPointer(row,col) ((unsigned short *)\
(Video_Base +\
2 * (SLtt_Screen_Cols * (row)\
+ (col))))
# if defined (USE_ASM)
int SLtt_Msdos_Cheap_Video = 0;
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)); }
# endif /* USE_ASM */
#endif /* USE_ASM or HAS_LINEAR_SCREEN */
/* -------------------------------------------------------------------- */
#if defined (__WATCOMC__)
# 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);
}
#endif /* __WATCOMC__ */
#ifdef HAS_SAVE_SCREEN
static void *Saved_Screen_Buffer;
static int Saved_Cursor_Row;
static void save_screen (void)
{
int row, col;
if (Saved_Screen_Buffer != NULL)
{
SLFREE (Saved_Screen_Buffer);
Saved_Screen_Buffer = NULL;
}
#ifdef GO32_VIDEO
Saved_Screen_Buffer = SLMALLOC (sizeof (short) *
ScreenCols () * ScreenRows ());
if (Saved_Screen_Buffer == NULL)
return;
ScreenRetrieve (Saved_Screen_Buffer);
ScreenGetCursor (&row, &col);
Saved_Cursor_Row = row;
#endif
}
static void restore_screen (void)
{
if (Saved_Screen_Buffer == NULL) return;
#ifdef GO32_VIDEO
ScreenUpdate (Saved_Screen_Buffer);
SLtt_goto_rc (Saved_Cursor_Row, 0);
#endif
}
#endif /* HAS_SAVE_SCREEN */
/*----------------------------------------------------------------------*\
* Function: void SLtt_write_string (char *str);
*
* put string STR to 'stdout'
\*----------------------------------------------------------------------*/
void SLtt_write_string (char *str)
{
#ifdef WIN32
unsigned long bytes;
(void) WriteConsole(hStdout, str, strlen(str), &bytes, NULL);
#else
fputs (str, stdout);
#endif
}
/*----------------------------------------------------------------------*\
* 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;
}
/*----------------------------------------------------------------------*\
* Function: void SLtt_goto_rc (int row, int col);
*
* move the terminal cursor to x,y position COL, ROW and record the
* position in Cursor_Row, Cursor_Col
\*----------------------------------------------------------------------*/
void SLtt_goto_rc (int row, int col)
{
#ifdef WIN32
COORD newPosition;
newPosition.X = col;
newPosition.Y = row;
#endif
#if !defined (USE_ASM)
if (row > SLtt_Screen_Rows) row = SLtt_Screen_Rows;
if (col > SLtt_Screen_Cols) col = SLtt_Screen_Cols;
# if defined (EMX_VIDEO)
v_gotoxy (col, Scroll_r1 + row);
# else /* EMX_VIDEO_ */
# if defined (__os2__)
VioSetCurPos (Scroll_r1 + row, col, 0);
# elif defined(WIN32)
(void) SetConsoleCursorPosition(hStdout, newPosition);
# else /* __os2__ */
# if defined (__GO32__) || defined (__WATCOMC__)
ScreenSetCursor(Scroll_r1 + row, col);
# endif /* __GO32__ or __WATCOMC__ */
# endif /* __os2__ */
# endif /* EMX_VIDEO_ */
Cursor_Row = row;
Cursor_Col = col;
#else /* USE_ASM */
/* if (r > SLtt_Screen_Rows - 1) r = SLtt_Screen_Rows - 1; */
asm mov ax, row
asm mov bx, SLtt_Screen_Rows
asm dec bx
asm cmp ax, bx
asm jle L1
asm mov ax, bx
L1:
/* if (c > SLtt_Screen_Cols - 1) c = SLtt_Screen_Cols - 1; */
asm mov cx, SLtt_Screen_Cols
asm dec cx
asm mov bx, col
asm cmp bx, cx
asm jle L2
asm mov bx, cx
L2:
asm mov Cursor_Row, ax
asm mov Cursor_Col, bx
asm add ax, Scroll_r1
asm xor dx, dx
asm mov dh, al
asm mov dl, bl
asm xor bx, bx
asm mov ax, 0x200
asm int 0x10
#endif /* USE_ASM */
}
/*----------------------------------------------------------------------*\
* Function: static void slvid_getxy (void);
*
* retrieve the cursor position into Cursor_Row, Cursor_Col
\*----------------------------------------------------------------------*/
static void slvid_getxy (void)
{
#if !defined (USE_ASM)
# if defined (EMX_VIDEO)
v_getxy (&Cursor_Col, &Cursor_Row);
# else /* EMX_VIDEO */
# if defined (__os2__)
VioGetCurPos ((USHORT*) &Cursor_Row, (USHORT*) &Cursor_Col, 0);
# elif defined(WIN32)
CONSOLE_SCREEN_BUFFER_INFO screenInfo;
if (GetConsoleScreenBufferInfo(hStdout, &screenInfo) == TRUE)
{
Cursor_Row = screenInfo.dwCursorPosition.Y;
Cursor_Col = screenInfo.dwCursorPosition.X;
}
# else /* __os2__ */
# if defined (__GO32__) || defined (__WATCOMC__)
ScreenGetCursor (&Cursor_Row, &Cursor_Col);
# endif /* __GO32__ or __WATCOMC__ */
# endif /* __os2__ */
# endif /* EMX_VIDEO */
#else /* USE_ASM */
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
#endif /* USE_ASM */
}
/*----------------------------------------------------------------------*\
* static void slvid_deleol (int x);
*
* write space characters from column X of row Cursor_Row through to
* SLtt_Screen_Cols using the current Attribute_Byte
\*----------------------------------------------------------------------*/
#if defined (GO32_VIDEO)
static void slvid_deleol (int x)
{
while (x < SLtt_Screen_Cols)
ScreenPutChar (32, Attribute_Byte, x++, Cursor_Row);
}
#endif
#if defined (EMX_VIDEO)
static void slvid_deleol (int x)
{
unsigned char *p, *pmax;
int w = mkSpaceChar ();
int count = SLtt_Screen_Cols - x;
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);
}
#endif /* EMX_VIDEO */
/*----------------------------------------------------------------------*\
* Function: void SLtt_begin_insert (void);
*
* insert a single space, moving everything right 1 character to make room
\*----------------------------------------------------------------------*/
void SLtt_begin_insert (void)
{
#if !defined (GO32_VIDEO)
# if defined (HAS_LINEAR_SCREEN) || defined (USE_ASM)
unsigned short *p;
# if defined (HAS_LINEAR_SCREEN)
unsigned short *pmin;
# endif
# endif
int n;
slvid_getxy ();
n = SLtt_Screen_Cols - Cursor_Col;
/* Msdos_Insert_Mode = 1; */
# ifndef WIN32
# if defined (EMX_VIDEO)
v_getline (Line_Buffer, Cursor_Col, Cursor_Row, n);
v_putline (Line_Buffer, Cursor_Col+1, Cursor_Row, n - 1);
# else /* EMX_VIDEO */
# if defined (__os2__)
n = 2 * (n - 1);
VioReadCellStr ((PCH)Line_Buffer, (USHORT*) &n, Cursor_Row, Cursor_Col, 0);
VioWrtCellStr ((PCH)Line_Buffer, n, Cursor_Row, Cursor_Col + 1, 0);
# else /* __os2__ */
p = mkScreenPointer (Cursor_Row, SLtt_Screen_Cols - 1);
# if defined (HAS_LINEAR_SCREEN)
/* pmin = p - (n-1); */
pmin = mkScreenPointer (Cursor_Row, Cursor_Col);
while (p-- > pmin) *(p + 1) = *p;
# else
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
# endif /* HAS_LINEAR_SCREEN */
# endif /* __os2__ */
# endif /* EMX_VIDEO */
# endif /* WIN32 */
#endif /* not GO32_VIDEO */
}
/*----------------------------------------------------------------------*\
* Function: void SLtt_end_insert (void);
*
* any cleanup after insert a blank column
\*----------------------------------------------------------------------*/
void SLtt_end_insert (void)
{
}
/*----------------------------------------------------------------------*\
* Function: void SLtt_delete_char (void);
*
* delete a single character, moving everything left 1 column to take
* up the room
\*----------------------------------------------------------------------*/
void SLtt_delete_char (void)
{
#if !defined (GO32_VIDEO)
# if defined (HAS_LINEAR_SCREEN) || defined (USE_ASM)
unsigned short *p;
# if defined (HAS_LINEAR_SCREEN)
register unsigned short *p1;
# endif
# endif
int n;
slvid_getxy ();
n = SLtt_Screen_Cols - Cursor_Col - 1;
# ifndef WIN32
# if defined (EMX_VIDEO)
v_getline (Line_Buffer, Cursor_Col+1, Cursor_Row, n);
v_putline (Line_Buffer, Cursor_Col, Cursor_Row, n);
# else /* EMX_VIDEO */
# if defined (__os2__)
n *= 2;
VioReadCellStr ((PCH)Line_Buffer, (USHORT*)&n, Cursor_Row, Cursor_Col + 1, 0);
VioWrtCellStr ((PCH)Line_Buffer, n, Cursor_Row, Cursor_Col, 0);
return;
# else /* __os2__ */
p = mkScreenPointer (Cursor_Row, Cursor_Col);
# if defined (HAS_LINEAR_SCREEN)
while (n--)
{
p1 = p + 1;
*p = *p1;
p++;
}
# else /* HAS_LINEAR_SCREEN */
SNOW_CHECK;
asm mov ax, ds
asm mov bx, si
asm mov dx, di
asm mov cx, n
asm les di, p
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -