361 lines
10 KiB
C
361 lines
10 KiB
C
/* -*- c -*- ------------------------------------------------------------- *
|
|
*
|
|
* Copyright 2004-2005 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 <string.h>
|
|
#include <com32.h>
|
|
#include "tui.h"
|
|
#include "syslnx.h"
|
|
#include "com32io.h"
|
|
#include "scancodes.h"
|
|
#include <stdlib.h>
|
|
|
|
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;
|
|
|
|
box_chars = getboxchars(bt);
|
|
// Top border
|
|
gotoxy(top,left,page);
|
|
cprint(box_chars[BOX_TOPLEFT],attr,1,page);
|
|
gotoxy(top,left+1,page);
|
|
cprint(box_chars[BOX_TOP],attr,right-left,page);
|
|
gotoxy(top,right,page);
|
|
cprint(box_chars[BOX_TOPRIGHT],attr,1,page);
|
|
// Bottom border
|
|
gotoxy(bot,left,page);
|
|
cprint(box_chars[BOX_BOTLEFT],attr,1,page);
|
|
gotoxy(bot,left+1,page);
|
|
cprint(box_chars[BOX_BOT],attr,right-left,page);
|
|
gotoxy(bot,right,page);
|
|
cprint(box_chars[BOX_BOTRIGHT],attr,1,page);
|
|
// Left & right borders
|
|
for (x=top+1; x < bot; x++)
|
|
{
|
|
gotoxy(x,left,page);
|
|
cprint(box_chars[BOX_LEFT],attr,1,page);
|
|
gotoxy(x,right,page);
|
|
cprint(box_chars[BOX_RIGHT],attr,1,page);
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|