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

📄 edit.cpp

📁 由一个古老的BASIC解释器改进而成, 保留了ANSI C固有的艺术美感.
💻 CPP
字号:
// edit.cpp

#include "cursor.h"
#include "graphics.h"
#include "error.h"
#include "trace.h"
#include "util.h"

#include "edit.h"

using util::to_string;

#if 0

#if defined __linux__ || defined __unix__

#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

#endif

#include <cassert>
#define ASSERT assert

namespace {

void showstring (BlFile & bf, const std::string & str)
{
	for (size_t i= 0, l= str.size (); i < l; ++i)
	{
		char c= str [i];
		if (c < 32)
			bf << '\\' << char (c + 'A');
		else
			bf << c;
	}
	bf.flush ();
}

class Edit {
public:
	Edit (BlFile & bf, std::string & str, size_t npos) :
		bf (bf),
		str (str),
		npos (npos),
		width (getwidth () )
	{
                graphics::synchronize_suspend ();
	}
        ~Edit ()
        {
                graphics::synchronize_restart ();
        }
	bool do_it ();
private:
	BlFile & bf;
	std::string & str;
	size_t npos;
	size_t width;

	//void getwidth ();
	void back ();
	void forward ();
	void deletechar ();
	void showrest ();
	void showinitial ();
};

#if 0
void Edit::getwidth ()
{
	if (graphics::ingraphicsmode () )
		width= graphics::getlinewidth ();
	else
	{
		#ifdef __WIN32__
                HANDLE h= GetStdHandle (STD_INPUT_HANDLE);
                CONSOLE_SCREEN_BUFFER_INFO info;
                if (GetConsoleScreenBufferInfo (h, & info) )
                        width= info.dwSize.X;
                else
                        width= 80;
		#else
		STRUCT_WINSIZE win;
		ioctl (0, IOCTL_WINSIZE, & win);
		width= WINSIZE_COLS (win);
		#endif
	}

}
#endif

void Edit::back ()
{
	if (npos-- % width != 0)
		movecharback ();
	else
	{
		movecharup ();
		movecharforward (width - 1);
	}
}

void Edit::forward ()
{
	++npos;
	if (npos % width != 0)
		movecharforward ();
	else
	{
		if (npos == str.size () )
		{
			movecharforward ();
			bf << '\n';
		}
		else
		{
			//bf << '\r';
			//bf.flush ();
			movecharback (width - 1);
			movechardown ();
		}
	}
}

void Edit::deletechar ()
{
	if (npos < str.size () )
	{
		str.erase (npos, 1);
		// Vil chapuza.
		str+= ' ';
		showrest ();
		str.erase (str.size () - 1);
	}
}

void Edit::showrest ()
{
	TraceFunc tr ("Edit::showrest");

	if (npos == str.size () )
		return;
	//bf << str.substr (npos);
	//bf.flush ();
	showstring (bf, str.substr (npos) );

	size_t l= str.size ();
	size_t nlines= l / width;
	size_t actualline= npos / width;
	size_t actualcol= npos % width;
	size_t lastcol= l % width;
	#ifndef __WIN32__
	if (lastcol == 0 && nlines > 0)
	{
		--nlines;
		// The cursor position remains in the last valid column.
		lastcol= width - 1;
		//lastcol= width;
	}
	#endif
	movecharup (nlines - actualline);
	if (actualcol < lastcol)
	{
		tr.message (std::string ("moving back " +
			to_string (lastcol - actualcol) ) );
		movecharback (lastcol - actualcol);
	}
	else if (actualcol > lastcol)
	{
		tr.message ("moving forward");
		movecharforward (actualcol - lastcol);
	}
	else if (actualcol == width - 1)
	{
		// Without this the cursor sometimes keep in the next line.
		movecharback ();
		movecharforward ();
	}
}

void Edit::showinitial ()
{
	//bf << '\r' << str;
	//bf.flush ();
	bf << '\r';
	showstring (bf, str);

	size_t l= str.size ();
	size_t nlines= l / width;
	size_t actualline= npos / width;
	size_t actualcol= npos % width;
	size_t lastcol= l % width;
        #ifndef __WIN32__
	if (lastcol == 0 && nlines > 0)
	{
		--nlines;
		lastcol= width - 1;
	}
        #endif

	movecharup (nlines - actualline);
	if (actualcol < lastcol)
		movecharback (lastcol - actualcol);
	else
		movecharforward (actualcol - lastcol);
	//bf << '\r';
	//bf.flush ();
	//movecharforward (npos);
}

bool Edit::do_it ()
{
	showinitial ();

	bool editing= true;
	bool retval= true;
	while (editing)
	{
		showcursor ();
		std::string key= getkey ();
		hidecursor ();
		if (key.size () == 1)
		{
			char c= key [0];
			switch (c)
			{
			case '\r': case '\n':
				editing= false;
				break;
			case '\x1B':
				editing= false;
				retval= false;
				break;
			case '\t':
				{
					//size_t n= npos + 1;
					//n+= 7 - (n % 8);
					//n-= npos ;
					size_t n= 8 - npos % 8;
					str.insert (npos, n, ' ');
					showrest ();
					for (size_t i= 0; i < n; ++i)
						forward ();
				}
				break;
			case '\3': // Ctrl-C
				editing= false;
				retval= false;
				break;
			case '\5': // Ctrl-E, test debug
				//bf << str.substr (npos) << '\n';
				//bf.flush ();
				showstring (bf, str.substr (npos) );
				bf << '\n';
				bf.flush ();
				showinitial ();
				break;
			case '\x8':
			case '\x7F':
				if (npos > 0)
				{
					back ();
					deletechar ();
				}
				break;
			default:
				if (c >= ' ')
				{
					str.insert (npos, 1, c);
					showrest ();
					forward ();
				}
			}
		}
		else if (key == "RIGHT")
		{
			if (npos < str.size () )
			{
				forward ();
			}
		}
		else if (key == "LEFT")
		{
			if (npos > 0)
			{
				back ();
			}
		}
		else if (key == "DELETE")
		{
			if (npos < str.size () )
				deletechar ();
		}
		else if (key == "HOME")
		{
			while (npos > 0)
				back ();
		}
		else if (key == "END")
		{
			const size_t l= str.size ();
			while (npos < l)
				forward ();
		}
	}
	//hidecursor ();

	// After exit, cursor must be positioned after the line edited.
	bf << str.substr (npos) << '\n';
	bf.flush ();
	
	return retval;
}

} // namespace

bool editline (BlFile & bf, std::string & str, size_t npos)
{
	Edit edit (bf, str, npos);
	return edit.do_it ();
}

bool editline (BlFile & bf, Program & program, BlLineNumber bln,
	std::string & str)
{
	std::string buffer;
	{
		BlFileOutString bfos;
		program.list (bln, bln, bfos);
		buffer= bfos.str ();
		if (buffer.empty () )
		{
			bfos << bln << " \n";
			buffer= bfos.str ();
		}
	}
	buffer.erase (buffer.size () - 1);
	static const std::string number ("01234567890");
	size_t inipos= buffer.find_first_of (number);
	ASSERT (inipos != std::string::npos);
	inipos= buffer.find_first_not_of (number, inipos);
	ASSERT (inipos != std::string::npos);
	++inipos;

	bool r;
	if ( (r= editline (bf, buffer, inipos) ) == true)
		str= buffer;
	return r;
}

bool editline (BlFile & bf, Program & program, BlLineNumber bln)
{
	std::string buffer;

	bool r;
	if ( (r= editline (bf, program, bln, buffer) ) == true)
	{
		CodeLine code;
		code.scan (buffer);
		BlLineNumber nline= code.number ();
		if (nline == 0)
			throw ErrBlassicInternal;
		else
		{
			if (code.empty () )
				program.deletelines (nline, nline);
			else
				program.insert (code);
		}
	}
	return r;
}

// End of edit.cpp

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -