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); }
/* * 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 */
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); } }
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; }
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); } }
/* * 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 }
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); } }
/** * @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)); }
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); }
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; }
/* 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; }
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(); }
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(); }
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); }
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); }
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()); } }
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 (); } }
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; }