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

📄 wcon.cpp

📁 UC Library Extensions UnderC comes with a pocket implementation of the standard C++ libraries, wh
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* C++ I/O using a GUI console window * UnderC C++ interpreter * Steve Donovan, 2001 * This is GPL'd software, and the usual disclaimers apply. * See LICENCE * * WCON is rather like Petzold's winio library, as described in his _Undocumented Windows_. * The C++ interface is using the 'fake' iostreams library (iostrm.cpp) rather than * pukka iostreams. Currently this feature is only available in the Windows version, altho * this file does not depend directly on the Win32 API.  Rather, all platform access goes  * through YAWL (Yet Another Windows Library) which should be portable. * * Ideally, WCON should be made independent of UnderC, but this version depends on being * able to tell whether it's in a program thread, and to kill that program thread if there's * a buffer overrun. Also the 'paste into' feature which Greg Perry had on his wishlist  * means we need uc_eval() from the main program.  */#include "twl.h"#include "keys.h"#include "gdi_stock.h"#include "twl_misc.h"//#include <stdio.h>#include <string.h>#include <ctype.h>//#include <stdarg.h>#include "classlib.h"  // iostreams & strings#include "ex_vfscanf.h"#include "wcon.h"

#include <list>// (a fiddle! WCON shd not depend on the rest of the program!!)#include "program.h"// for in_main_thread()
#include "main.h"
// for finalization call...

namespace Engine {  void kill(int retcode=0);  // in Engine}// from main.cppint uc_eval(char *expr, bool append_semicolon=true, bool synchronous=false, char *name=NULL, int lineno=0);
static TWin* sConsoleParent = NULL;
const int white = 0xFFFFFF;const char CTRL_C = 3, CTRL_V = 22, CTRL_Z = 26, CTRL_X = 24;// where are these buggers usually?template <class T>  T min(T t1, T t2) { return t1 < t2 ? t1 : t2; }template <class T>  T max(T t1, T t2) { return t1 > t2 ? t1 : t2; }struct Position {   int x,y;  void set(int _x, int _y)  { x = _x;  y = _y; }  Position(int _x, int _y)  : x(_x),y(_y) {}  Position()  : x(0),y(0) {}};typedef char *pchar;const int MAX_LINES = 5000,ROWS = 4000, COLUMNS = 100,
          CLIP_BUFF_SIZE = 4096;char gPromptChar;int  gPromptCol;class Buffer {protected:  char *m_buff[MAX_LINES];  long  m_line_colour[MAX_LINES];  int m_col, m_row;public:  void clear_line(int r)  {    char *line = m_buff[r];    for(int j = 0; j < m_col; j++) line[j] = ' '; //'A' + i;
	line[j] = '\0';	m_line_colour[r] = 0;  }  void alloc(int r1, int r2)  {    for(int i = r1; i <= r2; i++) {      m_buff[i] = new char[m_col+4];     clear_line(i);    }  }  void clear()  {    for(int i = 0; i < m_row; i++)        clear_line(i);  }  Buffer(int rows, int cols)  : m_col(cols), m_row(rows)  {    alloc(0,rows-1);  }  ~Buffer()  {   for(int i = 0; i < m_row; i++) delete[] m_buff[i];  }  void reserve(int nrows)  {    if (nrows > m_row) { 		  alloc(m_row,nrows-1);	      m_row = nrows;     }  }  void remove(Position& pos)  {    char *line = m_buff[pos.y];	for(int i = pos.x;  i < m_col-1; i++)	  line[i] = line[i+1];    line[m_col-1] = ' ';  }   void insert(Position& pos)  {    char *line = m_buff[pos.y];	for(int i = m_col-2;  i >= pos.x; i--)	  line[i+1] = line[i];    //line[m_col-1] = ' ';  }  int cols() const { return m_col; }  int rows() const { return m_row; }  long colour(int r) { return m_line_colour[r]; }  void colour(int r, long c) { m_line_colour[r] = c; }  char& operator() (int i, int j)  // x,y!  { return m_buff[j][i]; }  void copy_buffer(char *out,int iy, int ix1, int ix2=-1, bool strip_space=false)  {    char *line = m_buff[iy], *p = out;	if(ix2 == -1) ix2 = m_col-1;	if(strip_space) while(ix2 > ix1 && isspace(line[ix2])) ix2--;	for(int i = ix1; i <= ix2; i++) *p++ = line[i];	*p++ = '\0';  }  void copy_out(ostream& os, int iy1, int iy2, bool strip_prompts=false)  {   char tbuff[255];   for(int k = iy1; k <= iy2; k++) {     copy_buffer(tbuff,k,0,-1,true);	 char *ps = tbuff;	 if (strip_prompts && ps[gPromptCol] == gPromptChar)	    do { ps++; } while(!isspace(*ps));	 os << ps << endl;   }  }};

typedef std::list<string> StringList;const int default_cursor_width = 2, MAX_HISTORY=20;Point curr_pt;int curr_ln, end_ln, old_end_ln;long curr_tm;bool is_dragging = false;const int DRAG_WAIT = 150;int kount = 0;class ConsoleWin: public TFrameWindow {protected:  Position m_pos, m_start,m_end, m_char;  Buffer m_buff;  TCaret m_cursor;  long m_colour, m_write_colour;  bool m_insert_mode, m_immediate;  int m_buff_begin, m_buff_end, m_last_end, m_last_line;  int m_nchar;  char m_delim;  char *m_read_buff;  // scroll management  int m_pagesize, m_top;  // history list  StringList::iterator m_hlp;;  StringList m_history;public:  void reset_pos()  {  	m_top = 0;	m_pos.set(0,0);	m_start = m_pos;    m_end.set(m_buff.cols()-1,m_buff.rows()-1);    scroll_bar()->set_range(0,100);  }  ConsoleWin(int rows, int cols) 
	  : m_buff(rows,cols),TFrameWindow("",NULL,VERT_SCROLL,sConsoleParent)  {    //set_background(1.0,0.8,0.8);	m_colour = 0;	m_write_colour = 0;	m_insert_mode = false;	m_immediate = true;	m_buff_begin = 0;	m_buff_end = 0;	m_last_line = 0;	m_read_buff = NULL;	m_nchar = -1;	m_delim = '\r';	TClientDC dc(this);	dc.select_stock(SYSTEM_FIXED_FONT);	m_char.x = metrics(TM_CHAR_WIDTH);	m_char.y = metrics(TM_CHAR_HEIGHT);	m_cursor.set(this,default_cursor_width,m_char.y);    reset_pos();  }

  // *fix 1.1.1 Alex's problem w/ closing the UCW window
  void destroy() 
  {
	TFrameWindow::destroy();
	if (Program::in_main_thread())
 	  putchars("#q",true,true);
  }
 
  Buffer& buff() { return m_buff; }  void copy_out(ostream& os, int iy1, int iy2=-1, bool strip_prompts=false)  {   if(iy2==-1) iy2 = m_pos.y-1; //?   m_buff.copy_out(os,iy1,iy2,strip_prompts);  }  void copy_file_to_clip(char *file)  {  // this can properly become a TClipboard static method...     TClipboard clp(this);	 char *pstr = clp.buffer(CLIP_BUFF_SIZE); // we'll clean this up!	  // pull _all_ of the file in - binary mode gets the \r\n!	 ifstream(file,ios::binary).read(pstr,CLIP_BUFF_SIZE); 	 clp.write();  // and write the buffer to the clipboard  }  void copy_to_clip(int iy1, int iy2)  {    copy_out(ofstream("tmp.tmp"),iy1,iy2,true);	copy_file_to_clip("tmp.tmp");  }  void copy_selection()  {    copy_to_clip(min(curr_ln,end_ln),max(curr_ln,end_ln));	invalidate();  }  void paste_into()  {  // *add 0.9.8 Can directly paste expressions into the console    TClipboard clp(this);    uc_eval(clp.read(),false,false);  // *fix 1.2.5 async eval is safer...	putchars("",true,true);  // push an extra line...  }
  void vscroll(int action, int pos)  {    TScrollBar *sb = scroll_bar();	int old_pos = pos;    switch(action) {	case TScrollBar::LINEUP:   pos = max(0,pos-1);                  break;	case TScrollBar::LINEDOWN: pos = min(m_pos.y,pos+1);            break;
	case TScrollBar::PAGEUP: 
        pos = max(0,pos - m_pagesize);
        break;  
   	case TScrollBar::PAGEDOWN:
        pos = min(m_last_line,pos + m_pagesize);
        break;
//	case TScrollBar::PAGEUP:   pos = max(0,pos - m_pagesize);       break;//	case TScrollBar::PAGEDOWN: pos = min(m_pos.y,pos + m_pagesize); break;
	case TScrollBar::POS: break;	}	m_top = max(0,m_top + pos - old_pos);  // *fix 1.2.8 _must_ be +ve!	scroll_bar()->set_pos(m_top);	invalidate();  }  void set_read_buff(char *buff, int delim='\r', int nchar=-1)  { m_read_buff = buff; m_delim = delim; m_nchar = nchar; }  void size(int width, int height)  {   m_pagesize = height/m_char.y - 1;  //fiddle   m_end.x = min(width/m_char.x - 1,COLUMNS);  }   void immediate_paint(bool yes)  {    if (yes != m_immediate) {	  m_immediate = yes;	  if (m_immediate) invalidate();     }  }  void insert_mode(bool yes)  {    if (yes != m_insert_mode) {	   m_insert_mode = yes;	   m_cursor.set(this,	       m_insert_mode ? m_char.x : default_cursor_width,m_char.y);     }  }  void set_colour(long c)  {   m_write_colour = c;    m_buff.colour(m_pos.y, m_write_colour);  }  void clear_line()  {    m_buff.clear_line(m_pos.y);	m_buff_begin = 0;	m_pos.x = 0;    m_last_end = 0;	m_buff_end = 0;    draw_buff(TClientDC(this),m_pos,Position(m_end.x,m_pos.y));  }  
  // *fix 1.1.1 Command history list is now better behaved
  // *fix 1.2.8 Fails miserably if there's nothing in the history list.  void history_list(bool up)  {
    if (m_history.size()==0) return;    if(!up){	  ++m_hlp;
      if (m_hlp == m_history.end()) { --m_hlp; return; }	}	clear_line();    putchars(m_hlp->c_str(),false,true);
	if (up) {
	  if (m_hlp == m_history.begin()) return;
	  --m_hlp;
    }  }  void add_to_history_list(char *line)  {    m_history.push_back(line);
	m_hlp = m_history.end();
	--m_hlp;
	if (m_history.size() > MAX_HISTORY) m_history.pop_front();  }  int xc2pix(int x) { return x*m_char.x; }  int yc2pix(int y) { return (y-m_top)*m_char.y; }   int pix2xc(int x) { return x/m_char.x; }  int pix2yc(int y) { return y/m_char.y + m_top; }  int xpos()  { return xc2pix(m_pos.x);  }  int ypos()  { return yc2pix(m_pos.y);  }  void cursor_pos()   {  	 if (m_immediate) m_cursor.set_pos(xpos(),ypos());  }  void focus(bool yes)  {    if (yes) {	  m_cursor.create();      cursor_pos();	  m_cursor.show();    } else {      m_cursor.hide();	  m_cursor.destroy();	}  }  void draw_buff(TDC& dc, Position& s1, Position& s2, bool invert=false)  {    m_cursor.hide();	if(invert) {       dc.set_text_colour(white);       dc.set_back_colour(0,0,0);	}
	// *fix 1.1.1 limit width of _drawable_ buffer!
	int width = min(s2.x - s1.x, COLUMNS);  
    for(int iy = s1.y;  iy <= s2.y; iy++) {	  int x = xc2pix(s1.x), y = yc2pix(iy);
	  char *str = &m_buff(s1.x,iy);	  if (!invert && m_buff.colour(iy) != m_colour) {	     m_colour = m_buff.colour(iy);		 dc.set_text_colour(m_colour);      }	  dc.text_out(x,y,str,width);    }	if (invert) { // reset background	    dc.set_back_colour(1,1,1);  // really we shd choose this...        dc.set_text_colour(m_colour);    }    m_cursor.show();  }  void paint(TDC& dc)  {  // + 1 to account for end!    draw_buff(dc,
		Position(0,m_top),
		Position(m_end.x,m_top + m_pagesize + 1)
	);//m_start,m_end);  }   // mouse management  void mouse_down(Point& pt)  {	curr_pt = pt;	curr_tm = current_time();	curr_ln = pix2yc(pt.y);	old_end_ln = curr_ln;  }

  // *add 1.1.1 double-click on error line opens up Notepad!
  // *add 1.1.2 uses Metapad's '/g' option! Really shd make editor an option..
  void mouse_double_click(Point& pt)
  {
    char temp[COLUMNS], *file;
	int ln;
    m_buff.copy_buffer(temp,curr_ln,0);
    file = strdup(strtok(temp," "));  
	ln = atoi(strtok(NULL,":"));
	sprintf(temp,"metapad /g %d:1 %s",ln,file); 
	exec(temp);
  }  void mouse_move(Point& pt)  {    if (is_dragging) {	   end_ln = pix2yc(pt.y);	   if (end_ln != old_end_ln) {          draw_buff(TClientDC(this),		              Position(0,      min(old_end_ln,end_ln)),		              Position(m_end.x,max(old_end_ln,end_ln)),					  end_ln > old_end_ln);		 old_end_ln = end_ln;       } 	 } else

⌨️ 快捷键说明

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