/* -*- c -*- ------------------------------------------------------------- * * * Copyright 2004-2006 Murali Krishnan Ganapathy - All Rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, Inc., 53 Temple Place Ste 330, * Boston MA 02111-1307, USA; either version 2 of the License, or * (at your option) any later version; incorporated herein by reference. * * ----------------------------------------------------------------------- */ #include "tui.h" #include #include #include com32sys_t inreg, outreg; // Global register sets for use char bkspstr[] = " \b$"; char eolstr[] = "\n$"; #define GETSTRATTR 0x07 // Reads a line of input from stdin. Replace CR with NUL byte // password <> 0 implies not echoed on screen // showoldvalue <> 0 implies currentvalue displayed first // If showoldvalue <> 0 then caller responsibility to ensure that // str is NULL terminated. void getuserinput(char *stra, unsigned int size, unsigned int password, unsigned int showoldvalue) { unsigned char c, scan; char *p, *q; // p = current char of string, q = tmp char *last; // The current last char of string char *str; // pointer to string which is going to be allocated char page; char row, col; char start, end; // Cursor shape char fudge; // How many chars should be removed from output char insmode; // Are we in insert or overwrite page = getdisppage(); getpos(&row, &col, page); // Get current position getcursorshape(&start, &end); insmode = 1; str = (char *)malloc(size + 1); // Allocate memory to store user input memset(str, 0, size + 1); // Zero it out if (password != 0) showoldvalue = 0; // Password's never displayed if (showoldvalue != 0) strcpy(str, stra); // If show old value copy current value last = str; while (*last) { last++; } // Find the terminating null byte p = str + strlen(str); if (insmode == 0) setcursorshape(1, 7); // Block cursor else setcursorshape(6, 7); // Normal cursor // Invariants: p is the current char // col is the corresponding column on the screen if (password == 0) // Not a password, print initial value { gotoxy(row, col, page); csprint(str, GETSTRATTR); } while (1) { // Do forever c = inputc(&scan); if (c == '\r') break; // User hit Enter getout of loop if (scan == ESCAPE) // User hit escape getout and nullify string { *str = 0; break; } fudge = 0; // if scan code is regognized do something // else if char code is recognized do something // else ignore switch (scan) { case HOMEKEY: p = str; break; case ENDKEY: p = last; break; case LTARROW: if (p > str) p--; break; case CTRLLT: if (p == str) break; if (*p == ' ') while ((p > str) && (*p == ' ')) p--; else { if (*(p - 1) == ' ') { p--; while ((p > str) && (*p == ' ')) p--; } } while ((p > str) && ((*p == ' ') || (*(p - 1) != ' '))) p--; break; case RTARROW: if (p < last) p++; break; case CTRLRT: if (*p == 0) break; // At end of string if (*p != ' ') while ((*p != 0) && (*p != ' ')) p++; while ((*p != 0) && ((*p == ' ') && (*(p + 1) != ' '))) p++; if (*p == ' ') p++; break; case DELETE: q = p; while (*(q + 1)) { *q = *(q + 1); q++; } if (last > str) last--; fudge = 1; break; case INSERT: insmode = 1 - insmode; // Switch mode if (insmode == 0) setcursorshape(1, 7); // Block cursor else setcursorshape(6, 7); // Normal cursor break; default: // Unrecognized scan code, look at the ascii value switch (c) { case '\b': // Move over by one q = p; while (q <= last) { *(q - 1) = *q; q++; } if (last > str) last--; if (p > str) p--; fudge = 1; break; case '\x15': /* Ctrl-U: kill input */ fudge = last - str; while (p > str) *p-- = 0; p = str; *p = 0; last = str; break; default: // Handle insert and overwrite mode if ((c >= ' ') && (c < 128) && ((unsigned int)(p - str) < size - 1)) { if (insmode == 0) { // Overwrite mode if (p == last) last++; *last = 0; *p++ = c; } else { // Insert mode if (p == last) { // last char last++; *last = 0; *p++ = c; } else { // Non-last char q = last++; while (q >= p) { *q = *(q - 1); q--; } *p++ = c; } } } else beep(); } break; } // Now the string has been modified, print it if (password == 0) { gotoxy(row, col, page); csprint(str, GETSTRATTR); if (fudge > 0) cprint(' ', GETSTRATTR, fudge, page); gotoxy(row, col + (p - str), page); } } *p = '\0'; if (password == 0) csprint("\r\n", GETSTRATTR); setcursorshape(start, end); // Block cursor // If user hit ESCAPE so return without any changes if (scan != ESCAPE) strcpy(stra, str); free(str); } /* Print a C string (NUL-terminated) */ void cswprint(const char *str, char attr, char left) { char page = getdisppage(); char newattr = 0, cha, chb; char row, col; char nr, nc; nr = getnumrows(); nc = getnumcols(); getpos(&row, &col, page); while (*str) { switch (*str) { case '\b': --col; break; case '\n': ++row; col = left; break; case '\r': //col=left; break; case BELL: // Bell Char beep(); break; case CHRELATTR: // change attribute (relatively) case CHABSATTR: // change attribute (absolute) cha = *(str + 1); chb = *(str + 2); if ((((cha >= '0') && (cha <= '9')) || ((cha >= 'A') && (cha <= 'F'))) && (((chb >= '0') && (chb <= '9')) || ((chb >= 'A') && (chb <= 'F')))) // Next two chars are legal { if ((cha >= 'A') && (cha <= 'F')) cha = cha - 'A' + 10; else cha = cha - '0'; if ((chb >= 'A') && (chb <= 'F')) chb = chb - 'A' + 10; else chb = chb - '0'; newattr = (cha << 4) + chb; attr = (*str == CHABSATTR ? newattr : attr ^ newattr); str += 2; // Will be incremented again later } break; default: putch(*str, attr, page); ++col; } if (col >= nc) { ++row; col = left; } if (row > nr) { scrollup(); row = nr; } gotoxy(row, col, page); str++; } } void clearwindow(char top, char left, char bot, char right, char page, char fillchar, char fillattr) { char x; for (x = top; x < bot + 1; x++) { gotoxy(x, left, page); cprint(fillchar, fillattr, right - left + 1, page); } } void cls(void) { unsigned char dp = getdisppage(); gotoxy(0, 0, dp); cprint(' ', GETSTRATTR, (1 + getnumrows()) * getnumcols(), dp); } //////////////////////////////Box Stuff // This order of numbers must match // the values of BOX_TOPLEFT,... in the header file unsigned char SINSIN_CHARS[] = { 218, 192, 191, 217, //Corners 196, 179, // Horiz and Vertical 195, 180, 194, 193, 197 }; // Connectors & Middle unsigned char DBLDBL_CHARS[] = { 201, 200, 187, 188, // Corners 205, 186, // Horiz and Vertical 199, 182, 203, 202, 206 }; // Connectors & Middle unsigned char SINDBL_CHARS[] = { 214, 211, 183, 189, // Corners 196, 186, // Horiz & Vert 199, 182, 210, 208, 215 }; // Connectors & Middle unsigned char DBLSIN_CHARS[] = { 213, 212, 184, 190, // Corners 205, 179, // Horiz & Vert 198, 181, 209, 207, 216 }; // Connectors & Middle unsigned char *getboxchars(boxtype bt) { switch (bt) { case BOX_SINSIN: return SINSIN_CHARS; break; case BOX_DBLDBL: return DBLDBL_CHARS; break; case BOX_SINDBL: return SINDBL_CHARS; break; case BOX_DBLSIN: return DBLSIN_CHARS; break; default: return SINSIN_CHARS; break; } return SINSIN_CHARS; } // Draw box and lines void drawbox(char top, char left, char bot, char right, char page, char attr, boxtype bt) { unsigned char *box_chars; // pointer to array of box chars unsigned char x; fputs(SO, stdout); box_chars = getboxchars(bt); // Top border gotoxy(top, left, page); cprint(TOP_LEFT_CORNER_BORDER, attr, 1, page); cprint(TOP_BORDER, attr, right - left - 1, page); cprint(TOP_RIGHT_CORNER_BORDER, attr, 1, page); // Bottom border gotoxy(bot, left, page); cprint(BOTTOM_LEFT_CORNER_BORDER, attr, 1, page); cprint(BOTTOM_BORDER, attr, right - left - 1, page); cprint(BOTTOM_RIGHT_CORNER_BORDER, attr, 1, page); // Left & right borders for (x = top + 1; x < bot; x++) { gotoxy(x, left, page); cprint(LEFT_BORDER, attr, 1, page); gotoxy(x, right, page); cprint(RIGHT_BORDER, attr, 1, page); } fputs(SI, stdout); } void drawhorizline(char top, char left, char right, char page, char attr, boxtype bt, char dumb) { unsigned char start, end; unsigned char *box_chars = getboxchars(bt); if (dumb == 0) { start = left + 1; end = right - 1; } else { start = left; end = right; } gotoxy(top, start, page); cprint(box_chars[BOX_HORIZ], attr, end - start + 1, page); if (dumb == 0) { gotoxy(top, left, page); cprint(box_chars[BOX_LTRT], attr, 1, page); gotoxy(top, right, page); cprint(box_chars[BOX_RTLT], attr, 1, page); } }