Code:
#include <string.h>
#include <stdlib.h>
#include "dtio.h"
int dt_edit(char *se, int slen, int row, int col, int flen,int *start, int *offset, int *insert, int ctype) {
int key=0, pos = strlen(se), cpos=*start, i, done=1;
char * origstring = NULL; /*Will hold copy of se*/
char * temp = NULL; /*Temporary Buffer for the string*/
char letter; /*temporary character for INS*/
int offval = *offset;
int startval = *start;
int min, max, j, ctypechk=0;
/*Temp is the output buffer for dt_draw( )*/
/*Note, extra DMA is required for this assignment*/
#ifdef __cplusplus
temp = new char[flen+1];
origstring = new char[(slen != 0) ? slen+1 : flen-1];
#else
temp = (char*) malloc(sizeof(char)*(flen+1));
origstring = (char*) malloc(sizeof(char)* (slen != 0) ? (slen+1) : (flen-1));
#endif
/*min and max are coordinates on the se for displaying. */
min = offval;
max = min + flen - 1;
pos=startval+offval;
/*No code will be processed if the DMA fails, returns a null byte if it fails*/
if(temp && origstring)
{
updatescreen(min, max, temp, se, row, col, flen);
dt_cursor(row, col+cpos);
/*Backup of the original string*/
strcpy(origstring, se);
/*Before editing can occur, this segment will "clean the buffer and put origstring into se
(workaround to a display bug in the ctype tests!)*/
for (i = strlen(se); i>=0; i--)
se[i]=' ';
strcpy(se, origstring);
key = dt_getkey( );
while(done==1) {
switch(key) {
case PGUP:
case PGDN:
case F1:
case F2:
case F3:
case F4:
case F5:
case F6:
case F7:
case F8:
case F9:
case F10:
case TAB:
case UP:
case DOWN:
case ENTER:
done = 0;
break;
/*Restores string to beginning of function's default*/
case ESC:
/*Before restoring can occur, this segment will "clean the buffer and put
origstring into se (workaround to a display bug in the ctype tests!)*/
for (i = strlen(se); i>=0; i--)
se[i]=' ';
strcpy(se, origstring);
min = offval;
max = min + flen - 1;
pos=startval+offval;
cpos = startval;
updatescreen(min, max, temp, se, row, col, flen);
dt_cursor(row, col+cpos);
done = 0;
break;
/*Scrolls to the left*/
case LEFT:
if(cpos > 0)
{
pos--;cpos--;
}
else
{
if(min > 0)
{
pos--;min--;max--;
updatescreen(min, max, temp, se, row, col, flen);
/*Find new null byte location (if string small)*/
for(i=min, j=0; i<=max+1 && j == 0; i++)
{
if(!se[i])
{
max = strlen(se);
j++;
}
else
{
max = min + flen - 1;
}
}
}
}
dt_cursor(row, cpos+col);
key = dt_getkey( );
break;
case RIGHT:
if(cpos < flen - 1 && pos != strlen(se))
{
pos++;cpos++;
}
else
{
if(pos < strlen(se))
{
pos++;min++;max++;
updatescreen(min, max, temp, se, row, col, flen);
}
}
dt_cursor(row, cpos+col);
key = dt_getkey( );
break;
case HOME:
max = (strlen(se) < flen) ? strlen(se) : flen - 1;
pos = cpos = min = 0;
updatescreen(min, max, temp, se, row, col, flen);
dt_cursor(row, cpos+col);
key = dt_getkey( );
break;
case END:
max = strlen(se) + 1;
cpos = (strlen(se) < flen) ? strlen(se) : flen - 1;
min = (max < flen) ? 0 : max - flen;
pos = max - 1;
updatescreen(min, max, temp, se, row, col, flen);
dt_cursor(row, col+cpos);
key = dt_getkey( );
break;
case DEL:
if(pos < strlen(se))
{
max -= (max > strlen(se)) ? 1 : 0;
for(i=pos; i<strlen(se); i++)
se[i] = se[i+1];
updatescreen(min, max, temp, se, row, col, flen);
dt_cursor(row, cpos+col);
}
key = dt_getkey( );
break;
case BS:
if(pos > 0)
{
cpos -= (cpos == 0) ? 0 : 1;
max -= (max > strlen(se)) ? 1 : 0;
min -= (cpos == 0 && min != 0) ? 1 : 0;
pos--;
for(i=pos; i<strlen(se); i++)
se[i] = se[i+1];
updatescreen(min, max, temp, se, row, col, flen);
/*Find new null byte location (if string small)*/
for(i=min, j=0; i<=max+1 && j == 0; i++)
{
if(!se[i])
{
max = strlen(se);
j++;
}
else
{
max = min + flen - 1;
}
}
dt_draw(temp, row, col, flen);
dt_cursor(row, cpos+col);
}
key = dt_getkey( );
break;
case INS:
*insert = (*insert == 1) ? 0 : 1;
key = dt_getkey( );
break;
default:
switch(ctype){
case 1: ctypechk = (key>=' ' && key<='~') ? 1 : 0;
break;
case 2: ctypechk = (key=='0' || key=='1') ? 1 : 0;
break;
case 4: ctypechk = (key>='0' && key<='9') ? 1 : 0;
break;
case 8: ctypechk = (key>='0' && key<='7') ? 1 : 0;
break;
case 16: ctypechk = ((key>='0' && key<='9') || (key>='A' && key<='F')) ? 1 : 0;
/*I allowed the use of lower case typing, it will convert to upper case, I did
this for easier typing and you didnt mention in your specs with that scenario
(I asked some CPA students and they said go for it! GG Bitshift 4tw)*/
key ^= (key>='a' && key<='f') ? 32 : 0;
ctypechk = ((key>='0' && key<='9') || (key>='A' && key<='F')) ? 1 : 0;
break;
default: ctypechk = 0;}
/*printf("%c, %d",key, ctypechk);*/
if(ctypechk)
{
/*Insert Mode*/
if(*insert == 1)
{
/*Will only add characters if the field has not exceeded*/
if(strlen(se) < slen)
{
/*increments if its at the end of the window*/
if(cpos == flen - 1)
{
min++; max++;
}
else{cpos++;}
/*Changes max if the string is too small (safeguard)*/
for(i=min, j=0; i<=max && j == 0; i++)
{
if(!se[i])
{
max = strlen(se);
j++;
}
else
{
max = min + flen - 1;
}
}
/* copying chars into 'actual' array backwards */
se[strlen(se)+1] = '\0';
for(i=strlen(se); i>pos; i--)
{
se[i] = se[i-1];
}
se[pos] = key;
updatescreen(min, max, temp, se, row, col, flen);
pos++;
}
dt_cursor(row, cpos+col);
}
/*Overstrike Mode*/
else
{
/*will only allow input of characters if pos is not at the limiter */
max -= (strlen(se) == slen) ? 1 : 0;
for(i=min, j=0; i<=max && j == 0; i++)
{
if(!se[i])
{
max = strlen(se);
j++;
}
else
{
max = min + flen - 1;
}
}
if(cpos == flen - 1)
{
min++;
}
else{cpos++;}
/*If the cursor isnt at the end and goes beyond the allocated length, it
will "Do nothing" (chars can still be put in overstrike)*/
if(!se[pos] && strlen(se) == slen)
{
se[pos] = '\0';
pos--;
min--;
max--;
}
/*If the string is too small, but its at the end, it will write a nullbyte
at that location ahead of it and overwrite the current null with a character
(bug fix for the ctype tests and other displays)*/
else if(!se[pos] && strlen(se) < slen)
{
se[pos+1] = '\0';
se[pos] = key;
}
/*anywhere else*/
else
{
se[pos] = key;
}
pos++;
updatescreen(min, max, temp, se, row, col, flen);
dt_cursor(row, cpos+col);
}
}
key = dt_getkey( );
}
}
/*Nukes memory that was allocated*/
#ifdef __cplusplus
/*if(temp) delete [ ] temp;
if(origstring) delete [ ] origstring;*/
#else
free(temp);
free(origstring);
#endif
}/*end of if for DMA*/
return key;
}
void updatescreen(int min, int max, char * temp, char * se, int row, int col, int flen)
{
int i, j;
/*Debug code, decided to keep it for later use*/
/*char msg[121];
sprintf(msg, "min: %d max:%d flen:%d se:%d", min, max, flen, strlen(se));
dt_cursor(24, 30);
dt_putstring(msg);
dt_cursor(row, col);*/
for(i=min, j=0; i<=max+1 && se[i]; i++, j++)
temp[j] = se[i];
for( ; j<flen; j++)
temp[j] = ' ';
temp[j+1] = '\0';
dt_draw(temp, row, col, flen);
}
I do admit it is a tad bit long, but its functionality is simple. It allows the user to use Direct Terminal I/O on a string. All the code within works except for the bolded text when its uncommented.