slvideo.c
字号:
#include <windows.h>static HANDLE hStdout = INVALID_HANDLE_VALUE;#define MAXCOLS 256static 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 voidwrite_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 256static 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 voidwrite_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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -