📄 cursor.cpp
字号:
#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 (strMoveBackN, strMoveBack, n);
#endif
}
void movecharup (size_t n)
{
if (graphics::ingraphicsmode () )
{
graphics::movecharup (n);
return;
}
#ifdef BLASSIC_USE_WINDOWS
HANDLE h= GetStdHandle (STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO info;
if (GetConsoleScreenBufferInfo (h, & info) )
{
info.dwCursorPosition.Y-= SHORT (n);
SetConsoleCursorPosition (h, info.dwCursorPosition);
}
#elif defined BLASSIC_USE_TERMINFO
auxmovechar (strMoveUpN, strMoveUp, n);
#endif
}
void movechardown (size_t n)
{
if (graphics::ingraphicsmode () )
{
graphics::movechardown (n);
return;
}
#ifdef BLASSIC_USE_WINDOWS
HANDLE h= GetStdHandle (STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO info;
if (GetConsoleScreenBufferInfo (h, & info) )
{
info.dwCursorPosition.Y+= SHORT (n);
SetConsoleCursorPosition (h, info.dwCursorPosition);
}
#elif defined BLASSIC_USE_TERMINFO
auxmovechar (strMoveDownN, strMoveDown, n);
#endif
}
void savecursorpos ()
{
#ifdef BLASSIC_USE_WINDOWS
#elif defined BLASSIC_USE_TERMINFO
calltputs (strSaveCursorPos);
#endif
}
void restorecursorpos ()
{
#ifdef BLASSIC_USE_WINDOWS
#elif defined BLASSIC_USE_TERMINFO
calltputs (strRestoreCursorPos);
#endif
}
#ifndef __WIN32__
namespace {
static const int newcolor []=
{ 0, 4, 2, 6, 1, 5, 3, 7};
inline int mapcolor (int n)
{
// Intensity bit unchanged
return newcolor [n & 7] | (n & 8);
}
}
#endif
void textcolor (int color)
{
#ifdef __WIN32__
HANDLE h= GetStdHandle (STD_OUTPUT_HANDLE);
attributes= (attributes & WORD (0xF0) ) | WORD (color & 0x0F);
SetConsoleTextAttribute (h, attributes);
#elif defined BLASSIC_USE_TERMINFO
color= mapcolor (color & 0xF);
bool intensity= color > 7;
if (intensity)
{
color&= 7;
calltputs (strEnterBold);
}
else
{
if (strExitBold)
{
calltputs (strExitBold);
// sgr0 reset the background, then we need to set it.
textbackground (background);
}
}
//if (strForeground)
// calltputs (tparm ( (char *) strForeground, color) );
calltparm (strForeground, color);
#endif
}
void textbackground (int color)
{
#ifdef __WIN32__
HANDLE h= GetStdHandle (STD_OUTPUT_HANDLE);
attributes= (attributes & WORD (0xF) ) | WORD ( (color & 0xF) << 4);
SetConsoleTextAttribute (h, attributes);
#else
background= color;
color= mapcolor (color & 0xF);
//if (strBackground)
// calltputs (tparm ( (char *) strBackground, color) );
calltparm (strBackground, color);
#endif
}
namespace {
enum ReadType { ReadWait, ReadNoWait };
#ifdef __WIN32__
std::string string_from_key_event (const KEY_EVENT_RECORD & kr)
{
char c= kr.uChar.AsciiChar;
if (c != '\0')
return std::string (1, c);
WORD k= kr.wVirtualKeyCode;
std::string str= string_from_key (k);
if (! str.empty () )
return str;
if (k != VK_SHIFT &&
k != VK_CONTROL &&
k != VK_MENU &&
k != VK_CAPITAL &&
k != VK_NUMLOCK &&
k != VK_SCROLL)
{
std::string str (1, '\0');
str+= char (kr.wVirtualScanCode);
return str;
}
return std::string ();
}
std::string string_from_input (const INPUT_RECORD & input)
{
std::string str;
if (input.EventType == KEY_EVENT && input.Event.KeyEvent.bKeyDown)
{
str= string_from_key_event (input.Event.KeyEvent);
}
return str;
}
std::string readkey (ReadType type)
{
std::string str;
HANDLE h= GetStdHandle (STD_INPUT_HANDLE);
DWORD mode, orgmode;
GetConsoleMode (h, & mode);
orgmode= mode;
//mode&= ~ (ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT);
mode= 0;
SetConsoleMode (h, mode);
DWORD n= 0;
INPUT_RECORD input;
if (type == ReadNoWait)
PeekConsoleInput (h, & input, 1, & n);
else
n= 1;
if (n)
{
sigue:
ReadConsoleInput (h, & input, 1, & n);
str= string_from_input (input);
if (type == ReadWait && str.empty () )
goto sigue;
}
SetConsoleMode (h, orgmode);
return str;
}
#elif defined BLASSIC_USE_TERMINFO
class MapSpecial {
public:
enum Result { NoMapped, Found, MoreNeeded };
void addkey (const string & str, string::size_type pos,
const string & keyname)
{
//TraceFunc tr ("MapSpecial::addkey");
ASSERT (pos < str.size () );
char c= str [pos];
if (pos == str.size () - 1)
kname [c]= keyname;
else
{
//if (kmap.find (c) == kmap.end () )
// kmap [c]= MapSpecial ();
kmap [c].addkey (str, pos + 1, keyname);
}
}
Result findkey (const string & str, string::size_type pos,
string & keyname, string::size_type & consumed)
{
if (pos >= str.size () )
return MoreNeeded;
char c= str [pos];
//cout << "Buscando: " << c << endl;
{
map <char, std::string>::iterator it= kname.find (c);
if (it != kname.end () )
{
keyname= it->second;
consumed= pos;
return Found;
}
}
map <char, MapSpecial>::iterator it= kmap.find (c);
if (it != kmap.end () )
return it->second.findkey
(str, pos + 1, keyname, consumed);
else
return NoMapped;
}
private:
map <char, std::string> kname;
map <char, MapSpecial> kmap;
};
struct KeyDescription {
const char * tiId;
//const char * blName;
const std::string & blName;
};
const std::string
strMULT ("*"),
strMINUS ("-"),
strPLUS ("+"),
strDIV ("/");
const KeyDescription keyname [] = {
{ "kpp", strPAGEUP }, // previous-page key
{ "knp", strPAGEDOWN }, // next-page key
{ "kend", strEND }, // end key
{ "kslt", strEND }, // select key
{ "kc1", strEND }, // lower left of keypad
{ "khome", strHOME }, // home key
{ "kfnd", strHOME }, // find key
{ "ka1", strHOME }, // upper left of keypad
{ "kcub1", strLEFT }, // left-arrow key
{ "kcuu1", strUP }, // up-arrow key
{ "kcuf1", strRIGHT }, // right-arrow key
{ "kcud1", strDOWN }, // down-arrow key
{ "kich1", strINSERT }, // insert-character key
{ "kdch1", strDELETE }, // delete-character key
{ "kent", strENTER }, // enter/send key
{ "kf1", strF1 }, // F1 function key
{ "kf2", strF2 }, // F2 function key
{ "kf3", strF3 }, // F3 function key
{ "kf4", strF4 }, // F4 function key
{ "kf5", strF5 }, // F5 function key
{ "kf6", strF6 }, // F6 function key
{ "kf7", strF7 }, // F7 function key
{ "kf8", strF8 }, // F8 function key
{ "kf9", strF9 }, // F9 function key
{ "kf10", strF10 }, // F10 function key
{ "kf11", strF11 }, // F11 function key
{ "kf12", strF12 }, // F12 function key
{ "kf54", strDIV }, // F54 function key, / in xterm
{ "kf55", strMULT }, // F55 function key, * in xterm
{ "kf56", strMINUS }, // F56 function key, - in xterm
{ "kf57", strPLUS }, // f57 function key, + in xterm
};
#ifndef NDEBUG
bool checktable ()
{
const size_t nkeys= util::dim_array (keyname);
for (size_t i= 0; i < nkeys - 1; ++i)
for (size_t j= i + 1; j < nkeys; ++j)
if (strcmp (keyname [i].tiId, keyname [j].tiId) == 0)
{
std::cerr << "Code repeated in keyname: " <<
keyname [i].tiId << std::endl;
throw 1;
}
return true;
}
bool tablechecked= checktable ();
#endif
MapSpecial ms;
void initkeytable ()
{
TraceFunc tr ("initkeytable");
const size_t nkeys= util::dim_array (keyname);
for (size_t i= 0; i < nkeys; ++i)
{
const KeyDescription & keydesc= keyname [i];
const char * const strkey= keydesc.tiId;
const char * str= calltigetstr (strkey);
if (str != NULL)
{
#if 0
cerr << keydesc.blName << "=";
for (size_t i= 0, l= strlen (str); i < l; ++i)
{
char c= str [i];
if (c >= 32) cerr << c;
else cerr << "\\(" << hex << int (c) << ')';
}
cerr << endl;
#endif
tr.message (std::string ("Adding ") + keydesc.blName);
ms.addkey (str, 0, keydesc.blName);
}
}
}
class PollInput {
public:
PollInput ()
{
pfd.fd= STDIN_FILENO;
pfd.events= POLLIN | POLLERR | POLLNVAL;
}
int poll ()
{
return ::poll (& pfd, 1, 100);
}
private:
struct pollfd pfd;
};
void wait_event ()
{
PollInput pi;
int r;
do {
graphics::idle ();
} while ( (r= pi.poll () ) == 0);
if (r < 0)
{
cerr << "Error in poll: " << strerror (errno) << endl;
}
}
void do_poll ()
{
PollInput ().poll ();
}
std::string readkey (ReadType type)
{
checkinit ();
static std::string charpending;
std::string str;
bool reset_blocking_mode= false;
int l;
char c;
if (! charpending.empty () )
goto check_it;
#if 0
if (type == ReadWait)
{
//fcntl (STDIN_FILENO, F_SETFL, 0);
wait_event ();
}
else
{
fcntl (STDIN_FILENO, F_SETFL, O_NONBLOCK);
reset_blocking_mode= true;
}
//read_another:
l= read (STDIN_FILENO, & c, 1);
if (l == 1)
str+= c;
#else
fcntl (STDIN_FILENO, F_SETFL, O_NONBLOCK);
reset_blocking_mode= true;
l= read (STDIN_FILENO, & c, 1);
if (l != 1 && type == ReadWait)
{
do {
wait_event ();
l= read (STDIN_FILENO, & c, 1);
} while (l != 1);
}
if (l == 1)
str+= c;
#endif
read_another:
charpending+= str;
str.erase ();
check_it:
std::string keyname;
std::string::size_type pos;
if (! charpending.empty () )
{
MapSpecial::Result r=
ms.findkey (charpending, 0, keyname, pos);
switch (r)
{
case MapSpecial::NoMapped:
str= charpending [0];
charpending.erase (0, 1);
break;
case MapSpecial::Found:
str= keyname;
charpending.erase (0, pos + 1);
break;
case MapSpecial::MoreNeeded:
fcntl (STDIN_FILENO, F_SETFL, O_NONBLOCK);
reset_blocking_mode= true;
do_poll ();
l= read (STDIN_FILENO, & c, 1);
if (l == 1)
{
str= c;
goto read_another;
}
str= charpending [0];
charpending.erase (0, 1);
break;
}
}
if (type == ReadWait)
cursorinvisible ();
if (reset_blocking_mode)
fcntl (STDIN_FILENO, F_SETFL, 0);
return str;
}
#endif
} // namespace
std::string inkey ()
{
if (graphics::ingraphicsmode () )
return graphics::getkey ();
return readkey (ReadNoWait);
}
std::string getkey ()
{
if (graphics::ingraphicsmode () )
{
std::string str;
do {
str= graphics::getkey ();
} while (str.empty () );
return str;
}
return readkey (ReadWait);
}
#ifdef __WIN32__
void clean_input ()
{
Sleep (100);
HANDLE h= GetStdHandle (STD_INPUT_HANDLE);
INPUT_RECORD input;
DWORD n= 0;
PeekConsoleInput (h, & input, 1, & n);
if (n && input.EventType == KEY_EVENT &&
! input.Event.KeyEvent.bKeyDown)
ReadConsoleInput (h, & input, 1, & n);
}
#endif
// Fin de cursor.cpp
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -