| /* -*- 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 <string.h> |
| #include <com32.h> |
| #include <stdlib.h> |
| #include "com32io.h" |
| |
| com32sys_t inreg, outreg; // Global register sets for use |
| |
| char bkspstr[] = " \b$"; |
| char eolstr[] = "\n$"; |
| |
| // 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 int c; |
| 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 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 |
| |
| getpos(&row, &col, 0); // 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); |
| csprint(str, GETSTRATTR); |
| } |
| while (1) { // Do forever |
| c = get_key(stdin, 0); |
| if (c == KEY_ENTER) |
| break; // User hit Enter getout of loop |
| if (c == KEY_ESC) // 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 (c) { |
| case KEY_HOME: |
| p = str; |
| break; |
| case KEY_END: |
| p = last; |
| break; |
| case KEY_LEFT: |
| if (p > str) |
| p--; |
| break; |
| case KEY_CTRL(KEY_LEFT): |
| 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 KEY_RIGHT: |
| if (p < last) |
| p++; |
| break; |
| case KEY_CTRL(KEY_RIGHT): |
| 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 KEY_DEL: |
| case KEY_DELETE: |
| q = p; |
| while (*(q + 1)) { |
| *q = *(q + 1); |
| q++; |
| } |
| if (last > str) |
| last--; |
| fudge = 1; |
| break; |
| case KEY_INSERT: |
| insmode = 1 - insmode; // Switch mode |
| if (insmode == 0) |
| setcursorshape(1, 7); // Block cursor |
| else |
| setcursorshape(6, 7); // Normal cursor |
| break; |
| case KEY_BACKSPACE: // 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 KEY_CTRL('U'): /* 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); |
| csprint(str, GETSTRATTR); |
| if (fudge > 0) |
| cprint(' ', GETSTRATTR, fudge); |
| gotoxy(row, col + (p - str)); |
| } |
| } /* while */ |
| *p = '\0'; |
| if (password == 0) |
| csprint("\r\n", GETSTRATTR); |
| setcursorshape(start, end); // Block cursor |
| // If user hit ESCAPE so return without any changes |
| if (c != KEY_ESC) |
| strcpy(stra, str); |
| free(str); |
| } |
| |
| //////////////////////////////Box Stuff |
| |
| // Draw box and lines |
| void drawbox(const char top, const char left, const char bot, |
| const char right, const char attr) |
| { |
| unsigned char x; |
| putchar(SO); |
| // Top border |
| gotoxy(top, left); |
| putch(TOP_LEFT_CORNER_BORDER, attr); |
| cprint(TOP_BORDER, attr, right - left - 1); |
| putch(TOP_RIGHT_CORNER_BORDER, attr); |
| // Bottom border |
| gotoxy(bot, left); |
| putch(BOTTOM_LEFT_CORNER_BORDER, attr); |
| cprint(BOTTOM_BORDER, attr, right - left - 1); |
| putch(BOTTOM_RIGHT_CORNER_BORDER, attr); |
| // Left & right borders |
| for (x = top + 1; x < bot; x++) { |
| gotoxy(x, left); |
| putch(LEFT_BORDER, attr); |
| gotoxy(x, right); |
| putch(RIGHT_BORDER, attr); |
| } |
| putchar(SI); |
| } |
| |
| void drawhorizline(const char top, const char left, const char right, |
| const char attr, char dumb) |
| { |
| unsigned char start, end; |
| if (dumb == 0) { |
| start = left + 1; |
| end = right - 1; |
| } else { |
| start = left; |
| end = right; |
| } |
| gotoxy(top, start); |
| putchar(SO); |
| cprint(MIDDLE_BORDER, attr, end - start + 1); |
| if (dumb == 0) { |
| gotoxy(top, left); |
| putch(MIDDLE_BORDER, attr); |
| gotoxy(top, right); |
| putch(MIDDLE_BORDER, attr); |
| } |
| putchar(SI); |
| } |