📄 cursor.cpp
字号:
// cursor.cpp
#include "cursor.h"
#include "graphics.h"
#include "key.h"
#include "util.h"
#include "trace.h"
#ifdef __WIN32__
#include <windows.h>
#else
#include <unistd.h>
#include <fcntl.h>
#include <sys/poll.h>
#include <errno.h>
#include <cassert>
#define ASSERT assert
#include <ncurses.h>
#include <term.h>
#endif
#if defined __linux__ || defined __unix__
// Stuff needed by getwidth
#include <stdlib.h>
#include <sys/ioctl.h>
#include <termios.h>
// This is from ncurses.
#ifdef TIOCGSIZE
# define IOCTL_WINSIZE TIOCGSIZE
# define STRUCT_WINSIZE struct ttysize
# define WINSIZE_ROWS(n) (int)n.ts_lines
# define WINSIZE_COLS(n) (int)n.ts_cols
#else
# ifdef TIOCGWINSZ
# define IOCTL_WINSIZE TIOCGWINSZ
# define STRUCT_WINSIZE struct winsize
# define WINSIZE_ROWS(n) (int)n.ws_row
# define WINSIZE_COLS(n) (int)n.ws_col
# endif
#endif
#endif
#include <iostream>
#include <map>
namespace {
#ifdef BLASSIC_USE_TERMINFO
bool fInit= true;
int background= 8;
const char
* strCls= NULL, * strCup= NULL,
* strCursorNormal= NULL, * strCursorInvisible= NULL,
* strForeground= NULL, * strBackground= NULL,
* strEnterBold= NULL, * strExitBold= NULL,
* strMoveForward= NULL, * strMoveBack= NULL,
* strMoveForwardN= NULL, * strMoveBackN= NULL,
* strMoveUp= NULL, * strMoveDown= NULL,
* strMoveUpN= NULL, * strMoveDownN= NULL,
* strSaveCursorPos= NULL, * strRestoreCursorPos= NULL;
const char * newstr (const char * str)
{
if (str == NULL)
return NULL;
size_t l= strlen (str);
char *n= new char [l + 1];
strcpy (n, str);
return n;
}
inline const char * calltigetstr (const char * id)
{
const char * str= tigetstr ( (char *) id);
if (str == (char *) -1)
return NULL;
return str;
}
inline const char * mytigetstr (const char * id)
{
return newstr (calltigetstr (id) );
}
int putfunc (int ic)
{
char c= ic;
write (STDOUT_FILENO, & c, 1);
return c;
}
inline void calltputs (const char * str)
{
if (str != NULL)
tputs (str, 1, putfunc);
}
inline void calltparm (const char * str, int n)
{
if (str != NULL)
calltputs (tparm ( (char *) str, n) );
}
void initkeytable ();
struct str_terminfo {
const char * & str;
const char * tinfoname;
};
const str_terminfo strinfo []= {
{ strCls, "clear" },
{ strCup, "cup" },
{ strCursorNormal, "cnorm" },
{ strCursorInvisible, "civis" },
{ strForeground, "setaf" },
{ strBackground, "setab" },
{ strEnterBold, "bold" },
{ strExitBold, "sgr0" },
{ strMoveForward, "cuf1" },
{ strMoveBack, "cub1" },
{ strMoveForwardN, "cuf" },
{ strMoveBackN, "cub" },
{ strMoveUp, "cuu1" },
{ strMoveDown, "cud1" },
{ strMoveUpN, "cuu" },
{ strMoveDownN, "cud" },
{ strSaveCursorPos, "sc" },
{ strRestoreCursorPos, "rc" },
};
void init ()
{
TraceFunc tr ("init");
fInit= false;
int errret;
setupterm (0, 1, & errret);
if (isatty (STDOUT_FILENO) )
{
#if 0
//calltputs (tgetstr ( (char *) "smcup", 0) );
const char * str= calltigetstr ("smcup");
calltputs (str);
#endif
const char * str_keypad_xmit= calltigetstr ("smkx");
calltputs (str_keypad_xmit);
}
for (size_t i= 0; i < util::dim_array (strinfo); ++i)
strinfo [i].str= mytigetstr (strinfo [i].tinfoname);
initkeytable ();
}
inline void checkinit ()
{
if (fInit)
init ();
}
#endif
} // namespace
void initconsole ()
{
TraceFunc tr ("initconsole");
cursorinvisible ();
}
void quitconsole ()
{
TraceFunc tr ("quitconsole");
cursorvisible ();
#ifdef BLASSIC_USE_TERMINFO
if (! fInit)
{
if (isatty (STDOUT_FILENO) )
{
#if 0
//calltputs (tgetstr ( (char *) "rmcup", 0) );
const char * str= calltigetstr ("rmcup");
if (str != 0)
calltputs (str);
#endif
const char * str_keypad_local= calltigetstr ("rmkx");
calltputs (str_keypad_local);
}
}
#endif
}
size_t getwidth ()
{
size_t width;
if (graphics::ingraphicsmode () )
width= graphics::getlinewidth ();
else
{
#ifdef __WIN32__
HANDLE h= GetStdHandle (STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO info;
if (GetConsoleScreenBufferInfo (h, & info) )
width= info.dwSize.X;
else
width= 80;
#else
STRUCT_WINSIZE win;
if (ioctl (0, IOCTL_WINSIZE, & win) == 0)
width= WINSIZE_COLS (win);
else
{
const char * aux= getenv ("COLUMNS");
if (aux)
width= atoi (aux);
else
width= 80;
}
#endif
}
return width;
}
void cursorvisible ()
{
// checkinit not needed, is done by showcursor
showcursor ();
#ifndef __WIN32__
struct termios ter;
tcgetattr (STDIN_FILENO, & ter);
//ter.c_lflag|= (ECHO | ICANON | PENDIN);
ter.c_lflag|= (ECHO | ICANON);
tcsetattr (STDIN_FILENO, TCSANOW, & ter);
#endif
}
void cursorinvisible ()
{
// checkinit not needed, is done by hidecursor
hidecursor ();
#ifndef __WIN32__
struct termios ter;
tcgetattr (STDIN_FILENO, & ter);
ter.c_lflag&= ~ (ECHO | ICANON);
tcsetattr (STDIN_FILENO, TCSANOW, & ter);
#endif
}
void showcursor ()
{
if (graphics::ingraphicsmode () )
{
graphics::showcursor ();
return;
}
#ifdef __WIN32__
HANDLE h= GetStdHandle (STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO info;
GetConsoleCursorInfo (h, & info);
info.bVisible= TRUE;
SetConsoleCursorInfo (h, & info);
#elif defined BLASSIC_USE_TERMINFO
checkinit ();
if (isatty (STDOUT_FILENO) )
calltputs (strCursorNormal );
#endif
}
void hidecursor ()
{
if (graphics::ingraphicsmode () )
{
graphics::hidecursor ();
return;
}
#ifdef __WIN32__
HANDLE h= GetStdHandle (STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO info;
GetConsoleCursorInfo (h, & info);
info.bVisible= FALSE;
SetConsoleCursorInfo (h, & info);
#elif defined BLASSIC_USE_TERMINFO
checkinit ();
if (isatty (STDOUT_FILENO) )
calltputs (strCursorInvisible);
#endif
}
#ifdef __WIN32__
const WORD init_attributes=
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
WORD attributes= init_attributes;
#endif
void cls ()
{
#ifdef __WIN32__
HANDLE h= GetStdHandle (STD_OUTPUT_HANDLE);
if (h != INVALID_HANDLE_VALUE)
{
CONSOLE_SCREEN_BUFFER_INFO info;
if (GetConsoleScreenBufferInfo (h, & info) )
{
DWORD l= info.dwSize.X * info.dwSize.Y;
COORD coord= {0, 0};
DWORD notused;
FillConsoleOutputAttribute (h,
attributes,
l, coord, & notused);
FillConsoleOutputCharacter (h,
' ', l, coord, & notused);
SetConsoleCursorPosition (h, coord);
}
}
#elif defined BLASSIC_USE_TERMINFO
checkinit ();
calltputs (strCls);
#endif
}
#if 0
void locate (int row, int col)
{
#ifdef BLASSIC_USE_WINDOWS
COORD coord= { SHORT (col - 1), SHORT (row - 1) };
SetConsoleCursorPosition (GetStdHandle (STD_OUTPUT_HANDLE), coord);
#elif defined BLASSIC_USE_TERMINFO
checkinit ();
if (strCup)
calltputs (tgoto (strCup, col - 1, row - 1) );
#endif
}
#endif
void gotoxy (int x, int y)
{
if (graphics::ingraphicsmode () )
{
graphics::gotoxy (x, y);
return;
}
#ifdef BLASSIC_USE_WINDOWS
COORD coord= { SHORT (x), SHORT (y) };
SetConsoleCursorPosition (GetStdHandle (STD_OUTPUT_HANDLE), coord);
#elif defined BLASSIC_USE_TERMINFO
checkinit ();
if (strCup)
calltputs (tgoto (strCup, x, y) );
#endif
}
void movecharforward ()
{
if (graphics::ingraphicsmode () )
{
graphics::movecharforward (1);
return;
}
#ifdef BLASSIC_USE_WINDOWS
movecharforward (1);
#elif defined BLASSIC_USE_TERMINFO
calltputs (strMoveForward);
#endif
}
void movecharback ()
{
if (graphics::ingraphicsmode () )
{
graphics::movecharback (1);
return;
}
#ifdef BLASSIC_USE_WINDOWS
movecharback (1);
#elif defined BLASSIC_USE_TERMINFO
calltputs (strMoveBack);
#endif
}
void movecharup ()
{
if (graphics::ingraphicsmode () )
{
graphics::movecharup (1);
return;
}
#ifdef BLASSIC_USE_WINDOWS
movecharup (1);
#elif defined BLASSIC_USE_TERMINFO
calltputs (strMoveUp);
#endif
}
void movechardown ()
{
if (graphics::ingraphicsmode () )
{
graphics::movechardown (1);
return;
}
#ifdef BLASSIC_USE_WINDOWS
movechardown (1);
#elif defined BLASSIC_USE_TERMINFO
calltputs (strMoveDown);
#endif
}
namespace {
#ifdef BLASSIC_USE_TERMINFO
inline void auxmovechar (const char * strN, const char * str, size_t n)
{
if (n != 0)
{
if (strN)
//calltputs (tparm ( (char *) strN, n) );
calltparm (strN, n);
else
if (str)
for (size_t i= 0; i < n; ++i)
calltputs (str);
}
}
#endif
#ifdef __WIN32__
#endif
} // namespace
void movecharforward (size_t n)
{
if (graphics::ingraphicsmode () )
{
graphics::movecharforward (n);
return;
}
#ifdef BLASSIC_USE_WINDOWS
HANDLE h= GetStdHandle (STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO info;
if (GetConsoleScreenBufferInfo (h, & info) )
{
info.dwCursorPosition.X+= SHORT (n);
SetConsoleCursorPosition (h, info.dwCursorPosition);
}
#elif defined BLASSIC_USE_TERMINFO
auxmovechar (strMoveForwardN, strMoveForward, n);
#endif
}
void movecharback (size_t n)
{
if (graphics::ingraphicsmode () )
{
graphics::movecharback (n);
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -