⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cursor.cpp

📁 由一个古老的BASIC解释器改进而成, 保留了ANSI C固有的艺术美感.
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// 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 + -