/* Terminality - a portable terminal handling library * Copyright (C) 1998-2002, Emil Mikulic. * This is LGPL - look at COPYING.LIB */ /* Project: Terminality/GUI * File: textarea.cpp * Author: Michal Safranek * Description: Implements the textarea class */ #include const char textarea_rcsid[] = "$Id: textarea.cpp,v 1.7 2002/07/26 01:39:40 darkmoon Exp $"; /* Textbox elements */ void textarea::element(const textarea_element el) { if(has_color()) { /* Pretty colors */ switch(el){ case TA_begin: if (focus) setcolor(SELECTED_FRAME,SELECTED_FRAME_BG); else setcolor(FRAME,FRAME_BG); printw("%c", BEG_CHR); break; case TA_middle: if (focus) setcolor(SELECTED_SPACE,SELECTED_SPACE_BG); else setcolor(SPACE,SPACE_BG); printw("%c", MID_CHR); break; case TA_char: if (focus) setcolor(SELECTED_TEXT,SELECTED_TEXT_BG); else setcolor(TEXT,TEXT_BG); break; case TA_end: if (focus) setcolor(SELECTED_FRAME,SELECTED_FRAME_BG); else setcolor(FRAME,FRAME_BG); printw("%c", END_CHR); break; } } else { /* Plain */ switch (el) { case TA_begin: if (focus) highvideo(); else normvideo(); printw("%c", BEG_CHR); break; case TA_middle: lowvideo(); printw("%c", MID_CHR); break; case TA_char: if (focus) normvideo(); else lowvideo(); break; case TA_end: if (focus) highvideo(); else normvideo(); printw("%c", END_CHR); break; } } } #define TA_SETUP() FRAME = COLOR_TEXTAREA_FRAME; \ SPACE = COLOR_TEXTAREA_SPACE; SELECTED_SPACE = COLOR_TEXTAREA_SSPACE; \ TEXT_BG = COLOR_TEXTAREA_TEXTBG; SPACE_BG = COLOR_TEXTAREA_SPACEBG; \ FRAME_BG = COLOR_TEXTAREA_FRAMEBG; TEXT = COLOR_TEXTAREA_TEXT; \ SELECTED_TEXT_BG = COLOR_TEXTAREA_STEXTBG; \ BEG_CHR = '|'; END_CHR = '|'; \ SELECTED_SPACE_BG = COLOR_TEXTAREA_SSPACEBG; MID_CHR = '.'; \ SELECTED_FRAME_BG = COLOR_TEXTAREA_SFRAMEBG; \ SELECTED_TEXT = COLOR_TEXTAREA_STEXT; \ SELECTED_FRAME = COLOR_TEXTAREA_SFRAME; // Construct textarea at width height textarea::textarea(const int xx, const int yy, const int w, const int h) { // Encapsulate data x = xx; y = yy; width = w; height = h; // Allocate buffer buf = (char*) xmalloc(width * height + 1); memset(buf, 0, width * height + 1); buf[0] = 0; posx = posy = count = 0; focus = false; charmap = NULL; type_id = Textarea; visible = true; fixed_colors = false; TA_SETUP(); } // Construct textarea at width height with content textarea::textarea(const int xx, const int yy, const int w, const int h, const char *s) { // Encapsulate data x = xx; y = yy; width = w; height = h; // Allocate buffer buf = (char*) xmalloc(width * height + 1); memset(buf, 0, width * height + 1); // Copy buffer strncpy(buf, s, width * height); buf[width*height] = 0; count = strlen(s)>(unsigned) width * height?width * height:strlen(s); posx = posy = 0; focus = false; charmap = NULL; type_id = Textarea; visible = true; fixed_colors = false; TA_SETUP(); } // Destroy textarea textarea::~textarea() { // Deallocate buffer! xfree(buf); } // Draw textarea in its current state void textarea::draw(void) { char *temp; int h; if (!visible) return; for(h = 0; h < height; h++) { // Draw empty box gotoxy(x, y + h); element(TA_begin); for (int i=0; i 0) { posy--; } else { result = -1; break; } break; case KEY_BACKSPACE: #if !(__DJGPP__) && !(_WIN32) case 0x08: /* alt. backspace, thanks kromJx! */ #endif /* Backspace - move back a letter if we can */ if (posx+posy) { killch(posy * width + posx); count--; if (posx) { posx--; } else { posy--; posx = width - 1; } draw(); if(onchange) onchange(Textarea, this); } else { beep(); } break; case KEY_DEL: /* Delete - delete letter in front (if we can) */ if (posy * width + posx < count) { killch(posy * width + posx + 1); count--; draw(); if(onchange) onchange(Textarea, this); } else { beep(); } break; case KEY_RIGHT: if (posy * width + posx == count) { beep(); } else { if (posx == width - 1) { if (posy+1 < height) { posy++; posx = 0; } else { beep(); } } else { posx++; } } break; case KEY_LEFT: if (!posx) { if (!posy) { beep(); } else { posy--; posx = width - 1; } } else { posx--; } break; case KEY_HOME: posx = 0; break; case KEY_END: if ((posy+1)*width > count) { posx = count % width; } else { posx = width - 1; } break; default: /* Is it acceptable? */ if (32 > c || c > 255) { beep(); break; } if (charmap) { if (!strrchr(charmap, c)) { beep(); break; } } if (count == width * height) { beep(); } else { for (tmp = count; tmp > posx+width*posy - 1; tmp--) { buf[tmp] = buf[tmp-1]; } buf[posx + width * posy] = c; count++; if (posx == width - 1) { if (count != width * height) { posy++; posx = 0; } } else { posx++; } draw(); if(onchange) onchange(Textarea, this); } break; } } while (result == 101); visible = old_vis; /* Mark end of string */ buf[count] = 0; set_cursor(cs); focus = false; return result; } // Blocking get (cannot be aborted) char *textarea::get(void) { while (1) { switch (getnb()) { case 27: return NULL; case 0: return buf; } } } // Sets ta's content int textarea::set_buf(char *buffer) { int i; memset(buf, 0, width * height + 1); for (i = 0; i < width*height && (unsigned) i < strlen(buffer); i++) { buf[i] = buffer[i]; } buf[++i] = 0; count = i-1; posx = posy = 0; if(onchange) onchange(Textarea, this); return 1; } // Change scheme void textarea::change_scheme(void) { if (fixed_colors) return; SELECTED_FRAME = COLOR_TEXTAREA_SFRAME; FRAME = COLOR_TEXTAREA_FRAME; SPACE = COLOR_TEXTAREA_SPACE; SELECTED_SPACE = COLOR_TEXTAREA_SSPACE; TEXT_BG = COLOR_TEXTAREA_TEXTBG; SPACE_BG = COLOR_TEXTAREA_SPACEBG; FRAME_BG = COLOR_TEXTAREA_FRAMEBG; TEXT = COLOR_TEXTAREA_TEXT; SELECTED_SPACE_BG = COLOR_TEXTAREA_SSPACEBG; SELECTED_FRAME_BG = COLOR_TEXTAREA_SFRAMEBG; SELECTED_TEXT_BG = COLOR_TEXTAREA_STEXTBG; SELECTED_TEXT = COLOR_TEXTAREA_STEXT; }