/* ** FILE: input.c ** ** DESC: doskey-like read() function ** ** (C) Rainer Schnitker 1994 ** ** 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; either version ** 2 of the License, or (at your option) any later version. */ #include #include #include #include #include #include /* ** the read function, arguments: ** input buffer, size of buffer, boolean (newline after pressed) ** return size of input */ int get_input(char *, int, int); /* ** this function reads a key from the console ** low byte: ascii ** high byte: scan code, if ascii = 0 */ static int _read_keybrd(void) { int c = getch(); if (c == 0 || c == 0xE0) c = getch() << 8; return c; } /* history strings can contain 256 entries */ static char * oldstr[256]; static int istr = 0; /* get previus string */ static void cpy_up_string(char *str) { if (istr == 0 || !str) return; istr--; if (istr == 0) { if (oldstr[255]) istr = 255; } if (oldstr[istr]) strcpy(str, oldstr[istr]); else istr ++; } static void cpy_down_string(char *str) { if (istr == 0 || !str) return; istr++; if (istr == 256) istr = 1; if (oldstr[istr]) strcpy(str, oldstr[istr]); else istr--; } /* put next string */ static void cpy_new_strcpy(char *str) { static int line_index = 0; line_index++; if (line_index >= 256) line_index = 1; if (! oldstr[line_index]) oldstr[line_index] = malloc(strlen(str)+1); else oldstr[line_index] = realloc(oldstr[line_index], strlen(str)+1); if (oldstr[line_index]) strcpy(oldstr[line_index], str); istr = line_index + 1; } int get_input(char *str, int size, int opt_newline) { char ins_flag; int strpos; int strend; unsigned int key, scan; unsigned char ascii = 0; int i; strpos = 0; strend = 0; ins_flag = 1; memset(str, 0, size); for (;;) { key = _read_keybrd(); scan = (key >> 8) & 0xFF; ascii = (unsigned char) (key & 0xFF); if (ascii == 0xE0) ascii = 0; if (ascii >= 32) { /* show char */ if (strpos == strend) { putchar(ascii); *(str + strpos) = ascii; strend++; } else if (ins_flag) { /* shift right chars */ for (i = strend; i >= strpos; --i) *(str + i + 1) = *(str + i); *(str + strpos) = ascii; printf("%s",str + strpos); for (i = strend; i > strpos; i--) putchar('\b'); strend++; } else { putchar(ascii); *(str + strpos) = ascii; } strpos++; fflush(stdout); continue; } /* backspace or delete */ else if ((ascii == '\b' && strpos != 0) || (scan == 0x53 && strend != strpos)) { if (ascii == '\b') { putchar('\b'); strpos--; } for (i = strpos; i < strend; ++i) *(str + i) = *(str + i + 1); strend--; *(str + strend) = '\0'; printf("%s",str + strpos); putchar(' '); putchar('\b'); for (i = strend; i > strpos; i--) putchar('\b'); fflush(stdout); continue; } else if (ascii == 13) { /* return */ if (opt_newline) putchar('\n'); while (strend > 0 && *(str + strend - 1) == ' ') strend--; *(str + strend) = 0; if (strend>0) cpy_new_strcpy(str); break; } else if (ascii == 27) { /* ESC */ for (; strpos < strend; strpos++) putchar(' '); for (; strpos != 0; strpos--) { putchar('\b'); putchar(' '); putchar('\b'); } memset(str, 0, size); strpos = strend = 0; fflush(stdout); continue; } else if (scan == 0x4b && strpos != 0) { putchar('\b'); strpos--; fflush(stdout); continue; } else if (scan == 0x48) { /* up */ for (; strpos != 0; strpos--) { putchar('\b'); putchar(' '); putchar('\b'); } cpy_up_string(str); printf("%s",str); strpos = strend = strlen(str); fflush(stdout); continue; } else if (scan == 0x50) { /* down */ for (; strpos != 0; strpos--) { putchar('\b'); putchar(' '); putchar('\b'); } cpy_down_string(str); printf("%s",str); strpos = strend = strlen(str); fflush(stdout); continue; } else if (scan == 0x4d && strpos < strend) { /* -> */ putchar(*(str + strpos)); strpos++; fflush(stdout); continue; } else if (scan == 0x47) { /* home */ for (; strpos != 0; strpos--) putchar('\b'); strpos = 0; fflush(stdout); continue; } else if (scan == 0x4F) { /* end */ printf("%s",str + strpos); strpos = strend; fflush(stdout); continue; } else if (scan == 0x52)/* ins */ ins_flag ^= 1; fflush(stdout); } return strend; }