Пример #1
0
void WDL_CursesEditor::draw_status_state()
{
  int paney[2], paneh[2];
  const int pane_divy=GetPaneDims(paney, paneh);

  attrset(m_color_statustext);
  bkgdset(m_color_statustext);

  int line=LINES-1;
  const char* whichpane="";
  if (m_pane_div > 0.0 && m_pane_div < 1.0)
  {
    whichpane=(!m_curpane ? "Upper pane: " : "Lower pane: ");
    line=m_top_margin+pane_divy;
    move(line, 0);
    clrtoeol();
  }

  char str[512];
  snprintf(str, sizeof(str), "%sLine %d/%d, Col %d [%s]%s",
    whichpane, m_curs_y+1, m_text.GetSize(), m_curs_x, 
    (s_overwrite ? "OVR" : "INS"), (m_clean_undopos == m_undoStack_pos ? "" : "*"));
  int len=strlen(str);
  int x=COLS-len-1;
  mvaddnstr(line, x, str, len);
  clrtoeol();

  attrset(0);
  bkgdset(0);  

  const int col=m_curs_x-m_offs_x;
  line=m_curs_y+paney[m_curpane]-m_paneoffs_y[m_curpane];
  if (line >= paney[m_curpane] && line < paney[m_curpane]+paneh[m_curpane]) move(line, col);
}
Пример #2
0
/*
 * os_erase_area
 *
 * Fill a rectangular area of the screen with the current background
 * colour. Top left coordinates are (1,1). The cursor does not move.
 *
 * The final argument gives the window being changed, -1 if only a
 * portion of a window is being erased, or -2 if the whole screen is
 * being erased.  This is not relevant for the curses interface.
 *
 */
void os_erase_area (int top, int left, int bottom, int right, int win)
{
    int y, x, i, j;

    /* Catch the most common situation and do things the easy way */
    if ((top == 1) && (bottom == h_screen_rows) &&
	(left == 1) && (right == h_screen_cols)) {
#ifdef COLOR_SUPPORT
      /* Only set the curses background when doing an erase, so it won't
       * interfere with the copying we do in os_scroll_area.
       */
      bkgdset(u_setup.current_color | ' ');
      erase();
      bkgdset(0);
#else
      erase();
#endif
    } else {
        /* Sigh... */
	int saved_style = u_setup.current_text_style;
	os_set_text_style(u_setup.current_color);
	getyx(stdscr, y, x);
	top--; left--; bottom--; right--;
	for (i = top; i <= bottom; i++) {
	  move(i, left);
	  for (j = left; j <= right; j++)
	    addch(' ');
	}
	move(y, x);
	os_set_text_style(saved_style);
    }
}/* os_erase_area */
Пример #3
0
void WDL_CursesEditor::draw(int lineidx)
{
  attrset(A_NORMAL);

  if (lineidx >= 0)
  {
    int comment_state = GetCommentStateForLineStart(lineidx);
    WDL_FastString *s=m_text.Get(lineidx);
    if (s && lineidx >= m_offs_y && lineidx < m_offs_y+getVisibleLines())
    {
      doDrawString(lineidx-m_offs_y+m_top_margin,0,lineidx,s->Get(),COLS,&comment_state, min(s->GetLength(),m_offs_x));
    }
    return;
  }

  draw_top_line();

  attrset(A_NORMAL);
  bkgdset(A_NORMAL);

  move(m_top_margin,0);
  clrtoeol();

  int comment_state = GetCommentStateForLineStart(m_offs_y);
  const int VISIBLE_LINES = getVisibleLines();
  for(int i=0;i<VISIBLE_LINES;i++)
  { 
    int ln=i+m_offs_y;

    WDL_FastString *s=m_text.Get(ln);
    if(!s) 
    {
      move(i+m_top_margin,0);
      clrtoeol();
      continue;
    }

    doDrawString(i+m_top_margin,0,ln,s->Get(),COLS,&comment_state,min(m_offs_x,s->GetLength()));
  }
  
//  move(LINES-2,0);
//  clrtoeol();
  if (m_bottom_margin>0)
  {
    attrset(m_color_bottomline);
    bkgdset(m_color_bottomline);
    if (m_selecting) 
    {
      mvaddstr(LINES-1,0,"SELECTING - ESC-cancel, " "Ctrl+C,X,V, etc");
    }
    else 
    {
      draw_bottom_line();
    }
    clrtoeol();
    attrset(0);
    bkgdset(0);
  }
}
Пример #4
0
void curs_textattr(int attr)
{
	chtype   attrs=A_NORMAL;
	int	colour;

	if (lastattr==attr)
		return;

	lastattr=attr;
	
	if (attr & 8)  {
		attrs |= A_BOLD;
	}
	if (attr & 128)
	{
		attrs |= A_BLINK;
	}
	colour = COLOR_PAIR( ((attr&7)|((attr>>1)&56))+1 );
#ifdef NCURSES_VERSION_MAJOR
	attrset(attrs);
	color_set(colour,NULL);
#else
	attrset(attrs|colour);
#endif
	/* bkgdset(colour); */
	bkgdset(colour);

	cio_textinfo.attribute=attr;
}
Пример #5
0
void WDL_CursesEditor::draw_message(const char *str)
{
  int l=strlen(str);
  if (l > COLS-2) l=COLS-2;
  if (str[0]) 
  {
    attrset(m_color_message);
    bkgdset(m_color_message);
  }
  mvaddnstr(LINES-(m_bottom_margin>1?2:1),0,str,l);
  clrtoeol();
  if (str[0])
  {
    attrset(0);
    bkgdset(0);
  }
}
Пример #6
0
/*
 * Set display color on IBM PC.  Just convert MicroEMACS
 * color to ncurses background attribute.
 */
void ttcolor(int color)
{
  tthue = color;
#if 1
  bkgdset(' ' | (color == CMODE ? A_REVERSE : A_NORMAL));
#else
  attron (color == CMODE ? A_REVERSE : A_NORMAL);
#endif
}
Пример #7
0
void WDL_CursesEditor::draw_status_state()
{
  // always show this? if (m_bottom_margin>0)
  {
    char statusstr[512];
    snprintf(statusstr,sizeof(statusstr),"Line %d/%d, Col %d [%s%s]%s",m_curs_y+1,m_text.GetSize(),m_curs_x,s_overwrite?"OVR":"INS","",m_clean_undopos == m_undoStack_pos ? "" :"M");


    attrset(m_color_statustext);
    bkgdset(m_color_statustext);
 
    mvaddstr(LINES-1,COLS-28,statusstr);
    clrtoeol();

    attrset(0);
    bkgdset(0);
  }
}
Пример #8
0
/**
 * @brief Clear and draw background objects
 */
static void Sv_DrawConsole_Background(void) {

	Sv_DrawConsole_Color(CON_COLOR_WHITE);

	bkgdset(' ');
	clear();

	border(0, 0, 0, ' ', 0, 0, 0, 0);

	Sv_DrawConsole_Color(CON_COLOR_ALT);
	mvaddstr(0, 2, va("Quetoo Dedicated %s", VERSION));
}
Пример #9
0
void WDL_CursesEditor::draw_message(const char *str)
{
  int l=strlen(str);
  if (l > COLS-2) l=COLS-2;
  if (str[0]) 
  {
    attrset(m_color_message);
    bkgdset(m_color_message);
  }
  mvaddnstr(LINES-(m_bottom_margin>1?2:1),0,str,l);
  clrtoeol();
  if (str[0])
  {
    attrset(0);
    bkgdset(0);
  }   

  int paney[2], paneh[2];
  const int pane_divy=GetPaneDims(paney, paneh);

  const int col=m_curs_x-m_offs_x;
  int line=m_curs_y+paney[m_curpane]-m_paneoffs_y[m_curpane];
  if (line >= paney[m_curpane] && line < paney[m_curpane]+paneh[m_curpane]) move(line, col);
}
Пример #10
0
VALUE tui_init(VALUE self) {
	setlocale(LC_ALL, "");
	
	initscr();


	/*intrflush(stdscr, 0);*/
	keypad(stdscr, TRUE); /* enable keyboard mapping */
	nonl();               /* tell curses not to do NL->CR/NL on output */
	raw();                /* characters typed are immediately passed through */
	noecho();             /* don't echo input */
	meta(stdscr, 1);

	if(has_colors() == 0) {
		endwin();
		return Qfalse;
	}
	start_color();
	
		
	init_pair(1, COLOR_YELLOW, COLOR_BLUE);  /* text */
	init_pair(2, COLOR_WHITE, COLOR_BLUE);  /* keyword */
	init_pair(3, COLOR_BLACK, COLOR_CYAN);  /* selection */
	init_pair(4, COLOR_GREEN, COLOR_BLUE);  /* strings */
	init_pair(5, COLOR_YELLOW, COLOR_BLACK);  /* fold */
	init_pair(6, COLOR_BLACK, COLOR_BLUE);  /* borders */
	init_pair(7, COLOR_CYAN, COLOR_BLUE);  /* - */
	init_pair(8, COLOR_BLUE, COLOR_BLUE);  /* tabs */
	init_pair(9, COLOR_BLACK, COLOR_RED);  /* error */
	init_pair(10, COLOR_RED, COLOR_BLUE);  /* error */
	
	color_set(1, 0);
	bkgdset(1);
	
	/*clear();
	move(0, 0);
	addnstr("hi", 2);
	refresh();*/
		
	return Qtrue;
}
Пример #11
0
/* init_curses: Initializes curses and sets up the terminal properly.
 * ------------
 *
 * Return Value: Zero on success, non-zero on failure.
 */
static int init_curses()
{
    if (putenv("ESCDELAY=0") == -1)
        fprintf(stderr, "(%s:%d) putenv failed\r\n", __FILE__, __LINE__);

    initscr();                  /* Start curses mode */

    if ((curses_colors = has_colors())) {
        start_color();
#ifdef NCURSES_VERSION
        use_default_colors();
#else
        bkgdset(0);
        bkgd(COLOR_WHITE);
#endif
    }

    refresh();                  /* Refresh the initial window once */
    curses_initialized = 1;

    return 0;
}
Пример #12
0
static void
test_background(void)
{
    NCURSES_COLOR_T f, b;
    int row;
    int chr;

    if (pair_content(0, &f, &b) == ERR) {
	printw("pair 0 contains no data\n");
    } else {
	printw("pair 0 contains (%d,%d)\n", (int) f, (int) b);
    }
    getch();

    printw("Initializing pair 1 to red/%s\n", color_name(default_bg));
    init_pair(1, COLOR_RED, (NCURSES_COLOR_T) default_bg);
    bkgdset((chtype) (' ' | COLOR_PAIR(1)));
    printw("RED/BLACK\n");
    getch();

    printw("Initializing pair 2 to %s/blue\n", color_name(default_fg));
    init_pair(2, (NCURSES_COLOR_T) default_fg, COLOR_BLUE);
    bkgdset((chtype) (' ' | COLOR_PAIR(2)));
    printw("This line should be %s/blue\n", color_name(default_fg));
    getch();

    printw("Initializing pair 3 to %s/cyan (ACS_HLINE)\n", color_name(default_fg));
    init_pair(3, (NCURSES_COLOR_T) default_fg, COLOR_CYAN);
    printw("...and drawing a box which should be followed by lines\n");
    bkgdset(ACS_HLINE | COLOR_PAIR(3));
    /*
     * Characters from vt100 line-drawing should be mapped to line-drawing,
     * since A_ALTCHARSET is set in the background, and the character part
     * of the background is replaced by the nonblank characters written.
     *
     * Characters not in the line-drawing range are usually sent as-is.
     *
     * With SVr4 curses it is possible to rely on this to mix uppercase text
     * with the (lowercase) line-drawing characters.  ncurses uses some of
     * the uppercase characters for encoding thick- and double-lines.
     */
    row = 7;
    mvprintw(row++, 10, "l");
    for (chr = 0; chr < 32; ++chr)
	addch(' ');
    printw("x\n");
    chr = 32;
    while (chr < 128) {
	if ((chr % 32) == 0)
	    mvprintw(row++, 10, "x");
	addch((chtype) ((chr == 127) ? ' ' : chr));
	if ((++chr % 32) == 0)
	    printw("x\n");
    }
    mvprintw(row++, 10, "m");
    for (chr = 0; chr < 32; ++chr)
	addch(' ');
    printw("j\n");
    getch();

    bkgdset((chtype) (' ' | COLOR_PAIR(0)));
    printw("Default Colors\n");
    getch();

    printw("Resetting colors to pair 1\n");
    bkgdset((chtype) (' ' | COLOR_PAIR(1)));
    printw("This line should be red/%s\n", color_name(default_bg));
    getch();

    printw("Setting screen to pair 0\n");
    bkgd((chtype) (' ' | COLOR_PAIR(0)));
    getch();

    printw("Setting screen to pair 1\n");
    bkgd((chtype) (' ' | COLOR_PAIR(1)));
    getch();

    printw("Setting screen to pair 2\n");
    bkgd((chtype) (' ' | COLOR_PAIR(2)));
    getch();

    printw("Setting screen to pair 3\n");
    bkgd((chtype) (' ' | COLOR_PAIR(3)));
    getch();

    printw("Setting screen to pair 0\n");
    bkgd((chtype) (' ' | COLOR_PAIR(0)));
    getch();
}
Пример #13
0
void MultiTab_Editor::draw_top_line()
{
  int ypos=0;
  if (m_top_margin > 1)
  {
    int xpos=0;
    int x;
    move(ypos++,0);
    const int cnt= GetTabCount();
    int tsz=16;
    // this is duplicated in onMouseMessage
    if (cnt>0) tsz=COLS/cnt;
    if (tsz>128)tsz=128;
    if (tsz<12) tsz=12;

    for (x= 0; x < cnt && xpos < COLS; x ++)
    {
      MultiTab_Editor *ed = GetTab(x);
      if (ed)
      {
        char buf[128 + 8];
        memset(buf,' ',tsz);
        const char *p = WDL_get_filepart(ed->GetFileName());
        const int lp=strlen(p);
        int skip=0;        
        if (x<9) 
        { 
          if (tsz>16)
          {
#ifdef __APPLE__
            memcpy(buf,"<Cmd+",skip=5);
#else
            memcpy(buf,"<Ctrl+",skip=6);
#endif
          }
          buf[skip++]='F'; 
          buf[skip++] = '1'+x; 
          buf[skip++] = '>';
          skip++;
        }
        memcpy(buf+skip,p,min(tsz-1-skip,lp));
        buf[tsz]=0;
        int l = tsz;
        if (l > COLS-xpos) l = COLS-xpos;
        if (ed == this)
        {
          attrset(SYNTAX_HIGHLIGHT2|A_BOLD);
        }
        else
        {
          attrset(A_NORMAL);
        }
        addnstr(buf,l);
        xpos += l;
      }
    }
    if (xpos < COLS) clrtoeol();
  }
  attrset(COLOR_TOPLINE|A_BOLD);
  bkgdset(COLOR_TOPLINE);
  const char *p=GetFileName();
  move(ypos,0);
  if (COLS>4)
  {
    const int pl = (int) strlen(p);
    if (pl > COLS-1 && COLS > 4)
    {
      addstr("...");
      p+=pl - (COLS-1) + 4;
    }
    addstr(p);
  }
  clrtoeol();
}
Пример #14
0
int MultiTab_Editor::onChar(int c)
{
  if (!m_state && !SHIFT_KEY_DOWN && !ALT_KEY_DOWN && c =='W'-'A'+1)
  {
    if (GetTab(0) == this) return 0; // first in list = do nothing

    if (IsDirty())
    {
      m_state=UI_STATE_SAVE_ON_CLOSE;
      attrset(m_color_message);
      bkgdset(m_color_message);
      mvaddstr(LINES-1,0,"Save file before closing (y/N)? ");
      clrtoeol();
      attrset(0);
      bkgdset(0);
    }
    else
    {
      CloseCurrentTab();

      delete this;
      // context no longer valid!
      return 1;
    }
    return 0;
  }

  if (m_state == UI_STATE_SAVE_ON_CLOSE)
  {
    if (isalnum(c) || isprint(c) || c==27)
    {
      if (c == 27)
      {
        m_state=0;
        draw();
        draw_message("Cancelled close of file.");
        setCursor();
        return 0;
      }
      if (toupper(c) == 'N' || toupper(c) == 'Y')
      {
        if (toupper(c) == 'Y') 
        {
          if(updateFile())
          {
            m_state=0;
            draw();
            draw_message("Error writing file, changes not saved!");
            setCursor();
            return 0;
          }
        }
        CloseCurrentTab();

        delete this;
        // this no longer valid, return 1 to avoid future calls in onChar()

        return 1;
      }
    }
    return 0;
  }
  else if (m_state == UI_STATE_SAVE_AS_NEW)
  {
    if (isalnum(c) || isprint(c) || c==27 || c == '\r' || c=='\n')
    {
      if (toupper(c) == 'N' || c == 27) 
      {
        m_state=0;
        draw();
        draw_message("Cancelled create new file.");
        setCursor();
        return 0;
      }
      m_state=0;

      AddTab(m_newfn.Get());
    }
    return 0;
  }

  if ((c==27 || c==29 || (c >= KEY_F1 && c<=KEY_F10)) && CTRL_KEY_DOWN)
  {
    int idx=c-KEY_F1;
    bool rel=true;
    if (c==27) idx=-1;
    else if (c==29) idx=1;
    else rel=false;
    SwitchTab(idx,rel);

    return 1;
  }

  return WDL_CursesEditor::onChar(c);
}
Пример #15
0
void WDL_CursesEditor::draw(int lineidx)
{
  const int VISIBLE_LINES = getVisibleLines();

  int paney[2], paneh[2];
  const int pane_divy=GetPaneDims(paney, paneh);

#ifdef WDL_IS_FAKE_CURSES
  if (m_cursesCtx)
  {
    CURSES_INSTANCE->offs_y[0]=m_paneoffs_y[0];
    CURSES_INSTANCE->offs_y[1]=m_paneoffs_y[1];
    CURSES_INSTANCE->div_y=pane_divy;
    CURSES_INSTANCE->tot_y=m_text.GetSize();

    CURSES_INSTANCE->scrollbar_topmargin = m_top_margin;
    CURSES_INSTANCE->scrollbar_botmargin = m_bottom_margin;
  }
#endif

  attrset(A_NORMAL);

  if (lineidx >= 0)
  {
    int comment_state = GetCommentStateForLineStart(lineidx);
    WDL_FastString *s=m_text.Get(lineidx);
    if (s)
    {
      int y=lineidx-m_paneoffs_y[0];
      if (y >= 0 && y < paneh[0])
      {
        doDrawString(paney[0]+y, 0, lineidx, s->Get(), COLS, &comment_state, min(s->GetLength(), m_offs_x));
      } 
      y=lineidx-m_paneoffs_y[1];
      if (y >= 0 && y < paneh[1])
      {
        doDrawString(paney[1]+y, 0, lineidx, s->Get(), COLS, &comment_state, min(s->GetLength(), m_offs_x));
      }
    }
    return;
  }

  __curses_invalidatefull((win32CursesCtx*)m_cursesCtx,false);

  draw_top_line();

  attrset(A_NORMAL);
  bkgdset(A_NORMAL);

  move(m_top_margin,0);
  clrtoeol();

  int pane, i;
  for (pane=0; pane < 2; ++pane)
  {
    int ln=m_paneoffs_y[pane];
    int y=paney[pane];
    int h=paneh[pane];

    int comment_state=GetCommentStateForLineStart(ln);
 
    for(i=0; i < h; ++i, ++ln, ++y)
    { 
      WDL_FastString *s=m_text.Get(ln);
      if (!s) 
      {
        move(y,0);
        clrtoeol();
      }
      else
      {
        doDrawString(y,0,ln,s->Get(),COLS,&comment_state,min(m_offs_x,s->GetLength()));
      }
    }
  }

  attrset(m_color_bottomline);
  bkgdset(m_color_bottomline);

  if (m_bottom_margin>0)
  {
    move(LINES-1, 0);
#define BOLD(x) { attrset(m_color_bottomline|A_BOLD); addstr(x); attrset(m_color_bottomline&~A_BOLD); }
    if (m_selecting) 
    {
      mvaddstr(LINES-1,0,"SELECTING  ESC:cancel Ctrl+(");
      BOLD("C"); addstr("opy ");
      BOLD("X"); addstr(":cut ");
      BOLD("V"); addstr(":paste)");
    }
    else 
    {
      mvaddstr(LINES-1, 0, "Ctrl+(");

      if (m_pane_div <= 0.0 || m_pane_div >= 1.0) 
      {
        BOLD("P"); addstr("ane ");
      }
      else
      {
        BOLD("O"); addstr("therpane ");
        addstr("no"); BOLD("P"); addstr("anes ");
      }
      BOLD("F"); addstr("ind ");
      addstr("ma"); BOLD("T"); addstr("ch");
      draw_bottom_line();
      addstr(")");
    }
#undef BOLD
    clrtoeol();
  }

  attrset(0);
  bkgdset(0);

  __curses_invalidatefull((win32CursesCtx*)m_cursesCtx,true);
}
Пример #16
0
void MultiTab_Editor::OpenFileInTab(const char *fnp)
{
  // try to find file to open
  WDL_FastString s;        
  FILE *fp=NULL;
  {
    const char *ptr = fnp;
    while (!fp && *ptr)
    {          
      // first try same path as loading effect
      if (m_filename.Get()[0])
      {
        s.Set(m_filename.Get());
        const char *sp=s.Get()+s.GetLength();
        while (sp>=s.Get() && *sp != '\\' && *sp != '/') sp--;
        s.SetLen(sp + 1 - s.Get());
        if (s.GetLength())
        {
          s.Append(ptr);
          fp=fopenUTF8(s.Get(),"rb");
        }
      }

      // scan past any / or \\, and try again
      if (!fp)
      {
        while (*ptr && *ptr != '\\' && *ptr != '/') ptr++;
        if (*ptr) ptr++;
      }
    }
  }

  if (!fp) 
  {
    s.Set("");
    fp = tryToFindOrCreateFile(fnp,&s);
  }

  if (!fp && s.Get()[0])
  {
    m_newfn.Set(s.Get());

    if (COLS > 25)
    {
      int allowed = COLS-25;
      if (s.GetLength()>allowed)
      {
        s.DeleteSub(0,s.GetLength() - allowed + 3);
        s.Insert("...",0);
      }
      s.Insert("Create new file '",0);
      s.Append("' (Y/n)? ");
    }
    else
      s.Set("Create new file (Y/n)? ");

    m_state=UI_STATE_SAVE_AS_NEW;
    attrset(m_color_message);
    bkgdset(m_color_message);
    mvaddstr(LINES-1,0,s.Get());
    clrtoeol();
    attrset(0);
    bkgdset(0);
  }
  else if (fp)
  {
    fclose(fp);
    int x;
    for (x=0;x<GetTabCount();x++)
    {
      MultiTab_Editor *e = GetTab(x);
      if (e && !stricmp(e->GetFileName(),s.Get()))
      {
        SwitchTab(x,false);
        return;
      }
    }
    AddTab(s.Get());
  }
}
Пример #17
0
static void
cob_screen_attr (cob_field *fgc, cob_field *bgc, const int attr)
{
	size_t		i;
	int		styles = 0;
	int		line;
	int		column;
	short		fgcolor;
	short		bgcolor;
	short		fgdef;
	short		bgdef;

	attrset (A_NORMAL);
	if (attr & COB_SCREEN_REVERSE) {
		styles |= A_REVERSE;
	}
	if (attr & COB_SCREEN_HIGHLIGHT) {
		styles |= A_BOLD;
	}
	if (attr & COB_SCREEN_BLINK) {
		styles |= A_BLINK;
	}
	if (attr & COB_SCREEN_UNDERLINE) {
		styles |= A_UNDERLINE;
	}
	if (styles) {
		attron (styles);
	}
	if (cob_has_color) {
		fgcolor = fore_color;
		bgcolor = back_color;
		if (fgc) {
			switch (cob_get_int (fgc)) {
			case COB_SCREEN_BLACK:
				fgcolor = COLOR_BLACK;
				break;
			case COB_SCREEN_BLUE:
				fgcolor = COLOR_BLUE;
				break;
			case COB_SCREEN_GREEN:
				fgcolor = COLOR_GREEN;
				break;
			case COB_SCREEN_CYAN:
				fgcolor = COLOR_CYAN;
				break;
			case COB_SCREEN_RED:
				fgcolor = COLOR_RED;
				break;
			case COB_SCREEN_MAGENTA:
				fgcolor = COLOR_MAGENTA;
				break;
			case COB_SCREEN_YELLOW:
				fgcolor = COLOR_YELLOW;
				break;
			case COB_SCREEN_WHITE:
				fgcolor = COLOR_WHITE;
				break;
			default:
				break;
			}
		}
		if (bgc) {
			switch (cob_get_int (bgc)) {
			case COB_SCREEN_BLACK:
				bgcolor = COLOR_BLACK;
				break;
			case COB_SCREEN_BLUE:
				bgcolor = COLOR_BLUE;
				break;
			case COB_SCREEN_GREEN:
				bgcolor = COLOR_GREEN;
				break;
			case COB_SCREEN_CYAN:
				bgcolor = COLOR_CYAN;
				break;
			case COB_SCREEN_RED:
				bgcolor = COLOR_RED;
				break;
			case COB_SCREEN_MAGENTA:
				bgcolor = COLOR_MAGENTA;
				break;
			case COB_SCREEN_YELLOW:
				bgcolor = COLOR_YELLOW;
				break;
			case COB_SCREEN_WHITE:
				bgcolor = COLOR_WHITE;
				break;
			default:
				break;
			}
		}
		for (i = 0; i < (size_t)COLOR_PAIRS; i++) {
			pair_content ((short)i, &fgdef, &bgdef);
			if (fgdef == fgcolor && bgdef == bgcolor) {
				break;
			}
			if (fgdef == 0 && bgdef == 0) {
				init_pair ((short)i, fgcolor, bgcolor);
				break;
			}
		}
		if (i != (size_t)COLOR_PAIRS) {
#ifdef	HAVE_COLOR_SET
			color_set (COLOR_PAIR((short)i), (void *)0);
#else
			attrset (COLOR_PAIR(i));
#endif
			bkgdset (COLOR_PAIR(i));
		} else {
			attrset (A_NORMAL);
		}
	}
	if (attr & COB_SCREEN_BLANK_SCREEN) {
		getyx (stdscr, line, column);
		clear ();
		move (line, column);
	}
	if (attr & COB_SCREEN_BLANK_LINE) {
		getyx (stdscr, line, column);
		move (line, 0);
		clrtoeol ();
		move (line, column);
	}
	if (attr & COB_SCREEN_ERASE_EOL) {
		clrtoeol ();
	}
	if (attr & COB_SCREEN_ERASE_EOS) {
		clrtobot ();
	}
	if (attr & COB_SCREEN_BELL) {
		beep ();
	}
}
Пример #18
0
int WDL_CursesEditor::onChar(int c)
{
  if (m_state == -3 || m_state == -4)
  {
    switch (c)
    {
       case '\r': case '\n':
         m_state=0;
         runSearch();
       break;
       case 27: 
         m_state=0; 
         draw();
         setCursor();
         draw_message("Find cancelled.");
       break;
       case KEY_BACKSPACE: if (s_search_string[0]) s_search_string[strlen(s_search_string)-1]=0; m_state=-4; break;
       default: 
         if (VALIDATE_TEXT_CHAR(c)) 
         { 
           int l=m_state == -3 ? 0 : strlen(s_search_string); 
           m_state = -4;
           if (l < (int)sizeof(s_search_string)-1) { s_search_string[l]=c; s_search_string[l+1]=0; } 
         } 
        break;
     }
     if (m_state)
     {
       attrset(m_color_message);
       bkgdset(m_color_message);
       mvaddstr(LINES-1,29,s_search_string);
       clrtoeol(); 
       attrset(0);
       bkgdset(0);
     }
     return 0;
  }
  if (c==KEY_DOWN || c==KEY_UP || c==KEY_PPAGE||c==KEY_NPAGE || c==KEY_RIGHT||c==KEY_LEFT||c==KEY_HOME||c==KEY_END)
  {
    if (SHIFT_KEY_DOWN)      
    {
      if (!m_selecting)
      {
        m_select_x2=m_select_x1=m_curs_x; m_select_y2=m_select_y1=m_curs_y;
        m_selecting=1;
      }
    }
    else if (m_selecting) { m_selecting=0; draw(); }
  }

  switch(c)
  {
    case 'O'-'A'+1:
      if (!SHIFT_KEY_DOWN && !ALT_KEY_DOWN)
      {
        if (m_pane_div <= 0.0 || m_pane_div >= 1.0)
        {
          onChar('P'-'A'+1);
        }
        if (m_pane_div > 0.0 && m_pane_div < 1.0) 
        {
          m_curpane=!m_curpane;
          draw();
          draw_status_state();
          int paney[2], paneh[2];
          GetPaneDims(paney, paneh);
          if (m_curs_y-m_paneoffs_y[m_curpane] < 0) m_curs_y=m_paneoffs_y[m_curpane];
          else if (m_curs_y-m_paneoffs_y[m_curpane] >= paneh[m_curpane]) m_curs_y=paneh[m_curpane]+m_paneoffs_y[m_curpane]-1;
          setCursor();
        }
      }
    break;
    case 'P'-'A'+1:
      if (!SHIFT_KEY_DOWN && !ALT_KEY_DOWN)
      {
        if (m_pane_div <= 0.0 || m_pane_div >= 1.0) 
        {
          m_pane_div=0.5;
          m_paneoffs_y[1]=m_paneoffs_y[0];
        }
        else 
        {
          m_pane_div=1.0;
          if (m_curpane) m_paneoffs_y[0]=m_paneoffs_y[1];
          m_curpane=0;
        }
        draw();
        draw_status_state();

        int paney[2], paneh[2];
        const int pane_divy=GetPaneDims(paney, paneh);
        setCursor();
      }
    break;
    
    case 407:
    case 'Z'-'A'+1:
      if (!SHIFT_KEY_DOWN && !ALT_KEY_DOWN)
      {
        if (m_undoStack_pos > 0)
        {
           m_undoStack_pos--;
           loadUndoState(m_undoStack.Get(m_undoStack_pos));
           draw();
           setCursor();
           char buf[512];
           snprintf(buf,sizeof(buf),"Undid action - %d items in undo buffer",m_undoStack_pos);
           draw_message(buf);
        }
        else 
        {
          draw_message("Can't Undo");
        }   
        break;
      }
    // fall through
    case 'Y'-'A'+1:
      if ((c == 'Z'-'A'+1 || !SHIFT_KEY_DOWN) && !ALT_KEY_DOWN)
      {
        if (m_undoStack_pos < m_undoStack.GetSize()-1)
        {
          m_undoStack_pos++;
          loadUndoState(m_undoStack.Get(m_undoStack_pos));
          draw();
          setCursor();
          char buf[512];
          snprintf(buf,sizeof(buf),"Redid action - %d items in redo buffer",m_undoStack.GetSize()-m_undoStack_pos-1);
          draw_message(buf);
        }
        else 
        {
          draw_message("Can't Redo");  
        }
      }
    break;
    case KEY_IC:
      if (!SHIFT_KEY_DOWN && !ALT_KEY_DOWN)
      {
        s_overwrite=!s_overwrite;
        setCursor();
        break;
      }
      // fqll through
    case 'V'-'A'+1:
      if (!SHIFT_KEY_DOWN && !ALT_KEY_DOWN)
      {
        // generate a m_clipboard using win32 clipboard data
        WDL_PtrList<const char> lines;
        WDL_String buf;
#ifdef WDL_IS_FAKE_CURSES
        if (CURSES_INSTANCE)
        {
          OpenClipboard(CURSES_INSTANCE->m_hwnd);
          HANDLE h=GetClipboardData(CF_TEXT);
          if (h)
          {
            char *t=(char *)GlobalLock(h);
            int s=GlobalSize(h);
            buf.Set(t,s);
            GlobalUnlock(t);        
          }
          CloseClipboard();
        }
        else
#endif
        {
          buf.Set(s_fake_clipboard.Get());
        }

        if (buf.Get() && buf.Get()[0])
        {
          char *src=buf.Get();
          while (*src)
          {
            char *seek=src;
            while (*seek && *seek != '\r' && *seek != '\n') seek++;
            char hadclr=*seek;
            if (*seek) *seek++=0;
            lines.Add(src);

            if (hadclr == '\r' && *seek == '\n') seek++;

            if (hadclr && !*seek)
            {
              lines.Add("");
            }
            src=seek;
          }
        }
        if (lines.GetSize())
        {
          removeSelect();
          // insert lines at m_curs_y,m_curs_x
          if (m_curs_y >= m_text.GetSize()) m_curs_y=m_text.GetSize()-1;
          if (m_curs_y < 0) m_curs_y=0;

          preSaveUndoState();
          WDL_FastString poststr;
          int x;
          int indent_to_pos = -1;
          for (x = 0; x < lines.GetSize(); x ++)
          {
            WDL_FastString *str=m_text.Get(m_curs_y);
            const char *tstr=lines.Get(x);
            if (!tstr) tstr="";
            if (!x)
            {
              if (str)
              {
                if (m_curs_x < 0) m_curs_x=0;
                int tmp=str->GetLength();
                if (m_curs_x > tmp) m_curs_x=tmp;
  
                poststr.Set(str->Get()+m_curs_x);
                str->SetLen(m_curs_x);

                const char *p = str->Get();
                while (*p == ' ' || *p == '\t') p++;
                if (!*p && p > str->Get())
                {
                  if (lines.GetSize()>1)
                  {
                    while (*tstr == ' ' || *tstr == '\t') tstr++;
                  }
                  indent_to_pos = m_curs_x;
                }

                str->Append(tstr);
              }
              else
              {
                m_text.Insert(m_curs_y,(str=new WDL_FastString(tstr)));
              }
              if (lines.GetSize() > 1)
              {
                m_curs_y++;
              }
              else
              {
                m_curs_x = str->GetLength();
                str->Append(poststr.Get());
              }
           }
           else if (x == lines.GetSize()-1)
           {
             WDL_FastString *s=newIndentedFastString(tstr,indent_to_pos);
             m_curs_x = s->GetLength();
             s->Append(poststr.Get());
             m_text.Insert(m_curs_y,s);
           }
           else
           {
             m_text.Insert(m_curs_y,newIndentedFastString(tstr,indent_to_pos));
             m_curs_y++;
           }
         }
         draw();
         setCursor();
         draw_message("Pasted");
         saveUndoState();
       }
       else 
       {
         setCursor();
         draw_message("Clipboard empty");
       }
     }
  break;

  case KEY_DC:
    if (!SHIFT_KEY_DOWN && !ALT_KEY_DOWN)
    {
      WDL_FastString *s;
      if (m_selecting)
      {
        preSaveUndoState();
        removeSelect();
        draw();
        saveUndoState();
        setCursor();
      }
      else if ((s=m_text.Get(m_curs_y)))
      {
        if (m_curs_x < s->GetLength())
        {
          preSaveUndoState();

          bool hadCom = LineCanAffectOtherLines(s->Get(),m_curs_x,1); 
          s->DeleteSub(m_curs_x,1);
          if (!hadCom) hadCom = LineCanAffectOtherLines(s->Get(),-1,-1);
          draw(hadCom ? -1 : m_curs_y);
          saveUndoState();
          setCursor();
        }
        else // append next line to us
        {
          if (m_curs_y < m_text.GetSize()-1)
          {
            preSaveUndoState();

            WDL_FastString *nl=m_text.Get(m_curs_y+1);
            if (nl)
            {
              s->Append(nl->Get());
            }
            m_text.Delete(m_curs_y+1,true);

            draw();
            saveUndoState();
            setCursor();
          }
        }
      }
      break;
    }
  case 'C'-'A'+1:
  case 'X'-'A'+1:
    if (!SHIFT_KEY_DOWN && !ALT_KEY_DOWN && m_selecting)
    {
      if (c!= 'C'-'A'+1) m_selecting=0;
      int miny,maxy,minx,maxx;
      int x;
      getselectregion(minx,miny,maxx,maxy);
      const char *status="";
      char statusbuf[512];

      if (minx != maxx|| miny != maxy) 
      {
        int bytescopied=0;
        s_fake_clipboard.Set("");

        int lht=0,fht=0;
        if (c != 'C'-'A'+1) preSaveUndoState();

        for (x = miny; x <= maxy; x ++)
        {
          WDL_FastString *s=m_text.Get(x);
          if (s) 
          {
            const char *str=s->Get();
            int sx,ex;
            if (x == miny) sx=max(minx,0);
            else sx=0;
            int tmp=s->GetLength();
            if (sx > tmp) sx=tmp;
      
            if (x == maxy) ex=min(maxx,tmp);
            else ex=tmp;
      
            bytescopied += ex-sx + (x!=maxy);
            if (s_fake_clipboard.Get() && s_fake_clipboard.Get()[0]) s_fake_clipboard.Append("\r\n");
            s_fake_clipboard.Append(ex-sx?str+sx:"",ex-sx);

            if (c != 'C'-'A'+1)
            {
              if (sx == 0 && ex == tmp) // remove entire line
              {
                m_text.Delete(x,true);
                if (x==miny) miny--;
                x--;
                maxy--;
              }
              else { if (x==miny) fht=1; if (x == maxy) lht=1; s->DeleteSub(sx,ex-sx); }
            }
          }
        }
        if (fht && lht && miny+1 == maxy)
        {
          m_text.Get(miny)->Append(m_text.Get(maxy)->Get());
          m_text.Delete(maxy,true);
        }
        if (c != 'C'-'A'+1)
        {
          m_curs_y=miny;
          if (m_curs_y < 0) m_curs_y=0;
          m_curs_x=minx;
          saveUndoState();
          snprintf(statusbuf,sizeof(statusbuf),"Cut %d bytes",bytescopied);
        }
        else
          snprintf(statusbuf,sizeof(statusbuf),"Copied %d bytes",bytescopied);

#ifdef WDL_IS_FAKE_CURSES
        if (CURSES_INSTANCE)
        {
          int l=s_fake_clipboard.GetLength()+1;
          HANDLE h=GlobalAlloc(GMEM_MOVEABLE,l);
          void *t=GlobalLock(h);
          memcpy(t,s_fake_clipboard.Get(),l);
          GlobalUnlock(h);
          OpenClipboard(CURSES_INSTANCE->m_hwnd);
          EmptyClipboard();
          SetClipboardData(CF_TEXT,h);
          CloseClipboard();
        }
#endif

        status=statusbuf;
      }
      else status="No selection";

      draw();
      setCursor();
      draw_message(status);
    }
  break;
  case 'A'-'A'+1:
    if (!SHIFT_KEY_DOWN && !ALT_KEY_DOWN)
    {
      m_selecting=1;
      m_select_x1=0;
      m_select_y1=0;
      m_select_y2=m_text.GetSize()-1;
      m_select_x2=0;
      if (m_text.Get(m_select_y2))
        m_select_x2=m_text.Get(m_select_y2)->GetLength();
      draw();
      setCursor();
    }
  break;
  case 27:
    if (!SHIFT_KEY_DOWN && !ALT_KEY_DOWN && m_selecting)
    {
      m_selecting=0;
      draw();
      setCursor();
      break;
    }
  break;
  case KEY_F3:
  case 'G'-'A'+1:
    if (!SHIFT_KEY_DOWN && !ALT_KEY_DOWN && s_search_string[0])
    {
      runSearch();
      return 0;
    }
  // fall through
  case 'F'-'A'+1:
    if (!SHIFT_KEY_DOWN && !ALT_KEY_DOWN)
    {
      draw_message("");
      attrset(m_color_message);
      bkgdset(m_color_message);
      mvaddstr(LINES-1,0,"Find string (ESC to cancel): ");
      if (m_selecting && m_select_y1==m_select_y2)
      {
        WDL_FastString* s=m_text.Get(m_select_y1);
        if (s)
        {
          const char* p=s->Get();
          int xlo=min(m_select_x1, m_select_x2);
          int xhi=max(m_select_x1, m_select_x2);
          int i;
          for (i=xlo; i < xhi; ++i)
          {
            if (!isalnum(p[i]) && p[i] != '_') break;
          }
          if (i == xhi && xhi > xlo && xhi-xlo < sizeof(s_search_string))
          {
            lstrcpyn(s_search_string, p+xlo, xhi-xlo+1);
          }
        }
      }
      addstr(s_search_string);
      clrtoeol();
      attrset(0);
      bkgdset(0);
      m_state=-3; // find, initial (m_state=4 when we've typed something)
    }
  break;
  case KEY_DOWN:
    {
      if (CTRL_KEY_DOWN)
      {
        int paney[2], paneh[2];
        GetPaneDims(paney, paneh);
        int maxscroll=m_text.GetSize()-paneh[m_curpane]+4;
        if (m_paneoffs_y[m_curpane] < maxscroll-1)
        {
          m_paneoffs_y[m_curpane]++;
          if (m_curs_y < m_paneoffs_y[m_curpane]) m_curs_y=m_paneoffs_y[m_curpane];
          draw();
        }
      }
      else
      {
        m_curs_y++;
        if (m_curs_y>=m_text.GetSize()) m_curs_y=m_text.GetSize()-1;
        if (m_curs_y < 0) m_curs_y=0;
      }
      if (m_selecting) { setCursor(1); m_select_x2=m_curs_x; m_select_y2=m_curs_y; draw(); }
      setCursor(1);
    }
  break;
  case KEY_UP:
    {
      if (CTRL_KEY_DOWN)
      {
        if (m_paneoffs_y[m_curpane] > 0)
        {
          int paney[2], paneh[2];
          GetPaneDims(paney, paneh);
          m_paneoffs_y[m_curpane]--;
          if (m_curs_y >  m_paneoffs_y[m_curpane]+paneh[m_curpane]-1) m_curs_y = m_paneoffs_y[m_curpane]+paneh[m_curpane]-1;
          if (m_curs_y < 0) m_curs_y=0;
          draw();
        }
      }
      else
      {
        if(m_curs_y>0) m_curs_y--;
      }
      if (m_selecting) { setCursor(1); m_select_x2=m_curs_x; m_select_y2=m_curs_y; draw(); }
      setCursor(1);
    }
  break;
  case KEY_PPAGE:
    {
      if (m_curs_y > m_paneoffs_y[m_curpane])
      {
        m_curs_y=m_paneoffs_y[m_curpane];
        if (m_curs_y < 0) m_curs_y=0;
      }
      else 
      {
        int paney[2], paneh[2];
        GetPaneDims(paney, paneh);
        m_curs_y -= paneh[m_curpane];
        if (m_curs_y < 0) m_curs_y=0;
        m_paneoffs_y[m_curpane]=m_curs_y;
      }
      if (m_selecting) { setCursor(1); m_select_x2=m_curs_x; m_select_y2=m_curs_y; }
      draw();
      setCursor(1);
    }
  break; 
  case KEY_NPAGE:
    {
      int paney[2], paneh[2]; 
      GetPaneDims(paney, paneh);
      if (m_curs_y >= m_paneoffs_y[m_curpane]+paneh[m_curpane]-1) m_paneoffs_y[m_curpane]=m_curs_y-1;
      m_curs_y = m_paneoffs_y[m_curpane]+paneh[m_curpane]-1;
      if (m_curs_y >= m_text.GetSize()) m_curs_y=m_text.GetSize()-1;
      if (m_curs_y < 0) m_curs_y=0;
      if (m_selecting) { setCursor(1); m_select_x2=m_curs_x; m_select_y2=m_curs_y; }
      draw();
      setCursor(1);
    }
  break;
  case KEY_RIGHT:
    {
      if (1) // wrap across lines
      {
        WDL_FastString *s = m_text.Get(m_curs_y);
        if (s && m_curs_x >= s->GetLength() && m_curs_y < m_text.GetSize()) { m_curs_y++; m_curs_x = -1; }
      }

      if(m_curs_x<0) 
      {
        m_curs_x=0;
      }
      else
      {
        if (CTRL_KEY_DOWN)
        {
          WDL_FastString *s = m_text.Get(m_curs_y);
          if (!s||m_curs_x >= s->GetLength()) break;
          int lastType = categorizeCharForWordNess(s->Get()[m_curs_x++]);
          while (m_curs_x < s->GetLength())
          {
            int thisType = categorizeCharForWordNess(s->Get()[m_curs_x]);
            if (thisType != lastType && thisType != 0) break;
            lastType=thisType;
            m_curs_x++;
          }
        }
        else 
        {
          m_curs_x++;
        }
      }
      if (m_selecting) { setCursor(); m_select_x2=m_curs_x; m_select_y2=m_curs_y; draw(); }
      setCursor();
    }
  break;
  case KEY_LEFT:
    {
      bool doMove=true;
      if (1) // wrap across lines
      {
        WDL_FastString *s = m_text.Get(m_curs_y);
        if (s && m_curs_y>0 && m_curs_x == 0) 
        { 
          s = m_text.Get(--m_curs_y);
          if (s) 
          {
            m_curs_x = s->GetLength(); 
            doMove=false;
          }
        }
      }

      if(m_curs_x>0 && doMove) 
      {
        if (CTRL_KEY_DOWN)
        {
          WDL_FastString *s = m_text.Get(m_curs_y);
          if (!s) break;
          if (m_curs_x > s->GetLength()) m_curs_x = s->GetLength();
          m_curs_x--;

          int lastType = categorizeCharForWordNess(s->Get()[m_curs_x--]);
          while (m_curs_x >= 0)
          {
            int thisType = categorizeCharForWordNess(s->Get()[m_curs_x]);
            if (thisType != lastType && lastType != 0) break;
            lastType=thisType;
            m_curs_x--;
          }
          m_curs_x++;
        }
        else 
        {
          m_curs_x--;
        }
      }
      if (m_selecting) { setCursor(); m_select_x2=m_curs_x; m_select_y2=m_curs_y; draw(); }
      setCursor();
    }
  break;
  case KEY_HOME:
    {
      m_curs_x=0;
      if (CTRL_KEY_DOWN) m_curs_y=0;
      if (m_selecting) { setCursor(); m_select_x2=m_curs_x; m_select_y2=m_curs_y; draw(); }
      setCursor();
    }
  break;
  case KEY_END:
    {
      if (m_text.Get(m_curs_y)) m_curs_x=m_text.Get(m_curs_y)->GetLength();
      if (CTRL_KEY_DOWN) m_curs_y=m_text.GetSize();
      if (m_selecting) { setCursor(); m_select_x2=m_curs_x; m_select_y2=m_curs_y; draw(); }
      setCursor();
    }
  break;
  case KEY_BACKSPACE: // backspace, baby
    if (m_selecting)
    {
      preSaveUndoState();
      removeSelect();
      draw();
      saveUndoState();
      setCursor();
    }
    else if (m_curs_x > 0)
    {
      WDL_FastString *tl=m_text.Get(m_curs_y);
      if (tl)
      {
        preSaveUndoState();

        bool hadCom = LineCanAffectOtherLines(tl->Get(), m_curs_x-1,1);
        tl->DeleteSub(--m_curs_x,1);
        if (!hadCom) hadCom = LineCanAffectOtherLines(tl->Get(),-1,-1);
        draw(hadCom?-1:m_curs_y);
        saveUndoState();
        setCursor();
      }
    }
    else // append current line to previous line
    {
      WDL_FastString *fl=m_text.Get(m_curs_y-1), *tl=m_text.Get(m_curs_y);
      if (!tl) 
      {
        m_curs_y--;
        if (fl) m_curs_x=fl->GetLength();
        draw();
        saveUndoState();
        setCursor();
      }
      else if (fl)
      {
        preSaveUndoState();
        m_curs_x=fl->GetLength();
        fl->Append(tl->Get());

        m_text.Delete(m_curs_y--,true);
        draw();
        saveUndoState();
        setCursor();
      }
    }
  break;
  case 'L'-'A'+1:
    if (!SHIFT_KEY_DOWN && !ALT_KEY_DOWN)
    {
      draw();
      setCursor();
    }
  break;
  case 13: //KEY_ENTER:
    //insert newline
    preSaveUndoState();

    if (m_selecting) { removeSelect(); draw(); setCursor(); }
    if (m_curs_y >= m_text.GetSize())
    {
      m_curs_y=m_text.GetSize();
      m_text.Add(new WDL_FastString);
    }
    if (s_overwrite)
    {
      WDL_FastString *s = m_text.Get(m_curs_y);
      int plen=0;
      const char *pb=NULL;
      if (s)
      {
        pb = s->Get();
        while (plen < m_curs_x && (pb[plen]== ' ' || pb[plen] == '\t')) plen++;
      }
      if (++m_curs_y >= m_text.GetSize())
      {
        m_curs_y = m_text.GetSize();
        WDL_FastString *ns=new WDL_FastString;
        if (plen>0) ns->Set(pb,plen);
        m_text.Insert(m_curs_y,ns);
      }
      s = m_text.Get(m_curs_y);
      if (s && plen > s->GetLength()) plen=s->GetLength();
      m_curs_x=plen;
    }
    else 
    {
      WDL_FastString *s = m_text.Get(m_curs_y);
      if (s)
      {
        if (m_curs_x > s->GetLength()) m_curs_x = s->GetLength();
        WDL_FastString *nl = new WDL_FastString();
        int plen=0;
        const char *pb = s->Get();
        while (plen < m_curs_x && (pb[plen]== ' ' || pb[plen] == '\t')) plen++;

        if (plen>0) nl->Set(pb,plen);

        nl->Append(pb+m_curs_x);
        m_text.Insert(++m_curs_y,nl);
        s->SetLen(m_curs_x);
        m_curs_x=plen;
      }
    }
    m_offs_x=0;

    draw();
    saveUndoState();
    setCursor();
  break;
  case '\t':
    if (m_selecting)
    {
      preSaveUndoState();

      bool isRev = !!(GetAsyncKeyState(VK_SHIFT)&0x8000);
      indentSelect(isRev?-m_indent_size:m_indent_size);
      // indent selection:
      draw();
      setCursor();
      saveUndoState();
      break;
    }
  default:
    //insert char
    if(VALIDATE_TEXT_CHAR(c))
    { 
      preSaveUndoState();

      if (m_selecting) { removeSelect(); draw(); setCursor(); }
      if (!m_text.Get(m_curs_y)) m_text.Insert(m_curs_y,new WDL_FastString);

      WDL_FastString *ss;
      if ((ss=m_text.Get(m_curs_y)))
      {
        char str[64];
        int slen ;
        if (c == '\t') 
        {
          slen = min(m_indent_size,64);
          if (slen<1) slen=1;
          int x; 
          for(x=0;x<slen;x++) str[x]=' ';
        }
        else
        {
          str[0]=c;
          slen = 1;
        }


        bool hadCom = LineCanAffectOtherLines(ss->Get(),-1,-1);
        if (s_overwrite)
        {
          if (!hadCom) hadCom = LineCanAffectOtherLines(ss->Get(),m_curs_x,slen);
          ss->DeleteSub(m_curs_x,slen);
        }
        ss->Insert(str,m_curs_x,slen);
        if (!hadCom) hadCom = LineCanAffectOtherLines(ss->Get(),m_curs_x,slen);

        m_curs_x += slen;

        draw(hadCom ? -1 : m_curs_y);
      }
      saveUndoState();
      setCursor();
    }
    break;
  }
  return 0;
}