Synopsis #
This routine is used for single-line text input on the “homescreen” of the Prizm. It can handle scrolling (strings wider than the screen), it can handle shift, alpha, and alpha-lock modes, it has a cursor, and all that fun stuff. It also has four input modes: text, float, int, and positive int.
Definition #
Inputs #
int getTextLine(char* buf, int maxstrlen, int x, int y, int maxdisplen, unsigned short inmode);
-
char* buf - A buffer of at least maxstrlen+1 characters. May contain initial contents or just ‘\0’.
-
int maxstrlen - The max number of chars the user may enter
-
int x - The position of the first character, 1 through 21
-
int y - The y-coordinate of the line, 1 through 8
-
int maxdisplen - How long the input field can be. The field will scroll if the string is longer.
-
unsigned short inmode - The input mode. One of:
- INPUT_MODE_TEXT
- INPUT_MODE_FLOAT
- INPUT_MODE_INT
- INPUT_MODE_POSINT
:
Outputs #
An integer indicating the KEY_PRGM_ code of the key that caused the routine to quit. May be [F1]-[F6], [up], [down], or [enter]. Contents are filled into buf.
textinput.h #
// Include file for textinput.c
// Created by Christopher Mitchell / Kerm Martian
// [http://www.cemetech.net]
#include <keyboard.hpp>
#include <color.h>
#define bool unsigned char
#define INPUT_MODE_TEXT 0
#define INPUT_MODE_FLOAT 1
#define INPUT_MODE_INT 2
#define INPUT_MODE_POSINT 3
#define CURSOR_FLASH_RATE 32
#define true 1
#define false 0
int getTextLine(char* buf, int maxstrlen, int x, int y, int maxdisplen, unsigned short inmode);
void DrawCursor(int x, int y, int shiftmode, int alphamode, int cursorstate, char curchar);
textinput.c #
// textinput.c for the Casio Prizm and Cemetech's PrizmSDK
// Created by Christopher Mitchell / Kerm Martian
// [http://www.cemetech.net]
#include "textinput.h"
int getTextLine(char* buf, int maxstrlen, int x, int y, int maxdisplen, unsigned short inmode) {
//state variables
int dispoffset = 0; //the offset of the starting char displayed
int stroffset = 0; //the offset of the cursor into the string
int curlen = 0; //current string length (<= maxstrlen)
int cursorstate = 0; // 0 = char shown, 1 = cursor shown
int shiftmode = 0, alphamode = 0;
int cursorchangetime = RTC_GetTicks(); //last cursor change time
int kcol, krow;
bool finished = false; //if routine should end
unsigned short key = 0;
char dispcharbuf[21+2+1]; //max possible width is 21, 2 chars for the XX, 1 for null term
dispcharbuf[0] = dispcharbuf[1] = 'X';
char* row0[18] = { "", "^2", "^", "", "", "", "", "sqrt(", "xrt(", "", "", "", "", "r", "Theta", "", "", ""};
char* row1[18] = { "X", "log(", "ln(", "sin(", "cos(", "tan(", "angle", "10x", "ex", "asin(", "acos(", "atan(", "A", "B", "C", "D", "E", "F"};
char* row2[18] = { "", "", "(", ")", ", ", "", "", "", "cuberoot(", "^-1", "", "", "G", "H", "I", "J", "K", "L"};
char* row3[18] = { "7", "8", "9", "", "", "", "", "", "", "", "", "", "M", "N", "O", "", "", ""};
char* row4[18] = { "4", "5", "6", "*", "/", "", "", "", "", "{", "}", "", "P", "Q", "R", "S", "T", ""};
char* row5[18] = { "1", "2", "3", "+", "-", "", "", "", "", "[", "]", "", "U", "V", "W", "X", "Y", ""};
char* row6[18] = { "0", ".", "E", "-", "", "", "i", "=", "pi", "Ans", "", "", "Z", " ", "\"", "", "", ""};
char** rows[7] = { row0, row1, row2, row3, row4, row5, row6 };
//First, figure out starting position
while(buf[curlen] != '\0') {
curlen++;
if (curlen > maxstrlen)
return -1;
}
stroffset = curlen;
if (curlen >= maxdisplen)
dispoffset = curlen-maxdisplen+1;
//Main loop
do {
// display initial buffer contents
int i=0; //copy chars into the buffer
while(i<maxdisplen && buf[dispoffset+i] != '\0') {
dispcharbuf[2+i] = buf[dispoffset+i];
i++;
}
while(i<maxdisplen) {
dispcharbuf[2+i++] = ' ';
}
dispcharbuf[2+i] = '\0'; //null terminate it
PrintXY(x,y,dispcharbuf,0,TEXT_COLOR_BLACK);
cursorstate = 1;
DrawCursor(x+(stroffset-dispoffset),y,shiftmode,alphamode,cursorstate,dispcharbuf[2+stroffset-dispoffset]);
bool redraw = false;
do {
key = kcol = krow = 0;
int retval = GetKeyWait_OS(&kcol,&krow,KEYWAIT_HALTON_TIMERON,1,0,&key);
Bdisp_EnableColor(1);
key = (10*kcol)+(krow - 1);
if (retval == 1) {
//erase the cursor and switch it back to the letter here
cursorstate = 0;
cursorchangetime = RTC_GetTicks();
DrawCursor(x+(stroffset-dispoffset),y,shiftmode,alphamode,0,dispcharbuf[2+stroffset-dispoffset]);
if (krow == 10 || key == KEY_PRGM_UP || key == KEY_PRGM_DOWN || key == KEY_PRGM_RETURN)
return key;
if (key == KEY_PRGM_SHIFT) {
shiftmode = 1-shiftmode;
} else if (key == KEY_PRGM_ALPHA) {
if (shiftmode == 1) alphamode = 2;
else if (alphamode != 2) alphamode = 1-alphamode;
else alphamode = 0;
shiftmode = 0;
} else if (key == KEY_PRGM_LEFT && stroffset != 0) {
redraw = true; //cursor
if (stroffset == dispoffset) {
dispoffset--;
}
stroffset--;
} else if (key == KEY_PRGM_RIGHT && stroffset < curlen) {
redraw = true; //cursor
if (stroffset == dispoffset+maxdisplen-1) {
dispoffset++;
}
stroffset++;
} else if (key == KEY_PRGM_ACON) {
stroffset = dispoffset = 0;
buf[0] = '\0';
curlen = 0;
redraw = true;
} else if (key == KEY_PRGM_DEL && stroffset < curlen) {
int i = stroffset;
do {
buf[i] = buf[i+1];
i++;
} while (buf[i] != '\0');
curlen--;
redraw = true;
} else if (key == KEY_PRGM_DEL && stroffset == curlen && stroffset > 0) {
curlen--;
stroffset--;
buf[stroffset] = '\0';
redraw = true;
if (stroffset <= dispoffset && dispoffset > 0)
dispoffset--;
} else {
if (krow <= 8 && krow >= 2) {
char** rowdef = rows[8-krow];
char* thisstr = rowdef[6*(shiftmode)+12*(alphamode!=0 && shiftmode == 0)+(7-kcol)];
if (*thisstr != '\0') {
int len = _g_strlen(thisstr);
signed char valid = (len+curlen < maxstrlen);
switch (inmode) {
case INPUT_MODE_FLOAT:
if (len > 1) valid = false;
else if (*thisstr == '-') {
if (stroffset != 0 || buf[stroffset] == '-')
valid = false;
} else if (*thisstr == '.') {
for(int i=0; i<curlen; i++) {
if (buf[i] == '.') {
valid = false;
break;
}
}
} else if (*thisstr >= '0' && *thisstr <= '9') {
//this is fine
} else valid = false;
break;
case INPUT_MODE_INT:
if (len > 1) valid = false;
else if (*thisstr == '-') {
if (stroffset != 0 || buf[stroffset] == '-')
valid = false;
} else if (*thisstr >= '0' && *thisstr <= '9') {
//this is fine
} else valid = false;
break;
case INPUT_MODE_POSINT:
if (len > 1) valid = false;
else if (*thisstr >= '0' && *thisstr <= '9') {
//this is fine
} else valid = false;
break;
case INPUT_MODE_TEXT:
default:
valid = true;
break;
}
if (valid) {
for(int i=curlen+len;i>=stroffset+len;i--) { //make space to insert this
buf[i] = buf[i-len];
}
for(int i=0; i<len; i++) { //drop it into the space
buf[stroffset++] = thisstr[i];
}
curlen+=len;
while (stroffset >= dispoffset+maxdisplen-1) { //adjust the cursor to be on-screen
redraw = true;
dispoffset++;
}
}
redraw = 1;
if (shiftmode)
shiftmode = 0;
else if (alphamode == 1)
alphamode = 0;
}
}
}
} else if (cursorchangetime + CURSOR_FLASH_RATE < RTC_GetTicks()) { //and !key
cursorstate = 1-cursorstate;
cursorchangetime = RTC_GetTicks();
DrawCursor(x+(stroffset-dispoffset),y,shiftmode,alphamode,cursorstate,dispcharbuf[2+stroffset-dispoffset]);
}
} while (!redraw && !finished);
} while(!finished);
return KEY_PRGM_RETURN;
}
void DrawCursor(int x, int y, int shiftmode, int alphamode, int cursorstate, char curchar) {
char buf2[5] = {'X','X',' ','\0','\0'};
buf2[2] = (curchar?curchar:' ');
if (cursorstate) {
if (shiftmode == 0 && alphamode == 0) {
PrintXY(x,y,buf2,1,TEXT_COLOR_BLACK);
Bdisp_PutDisp_DD();
return;
} else if (shiftmode) {
buf2[2] = 0xE5;
buf2[3] = 0xEA;
} else if (alphamode == 1) {
buf2[2] = 0xE5;
buf2[3] = 0x9F;
} else {
buf2[2] = 0xE7;
buf2[3] = 0xAE;
}
}
PrintXY(x,y,buf2,0,TEXT_COLOR_BLACK);
Bdisp_PutDisp_DD();
}
Comments #
I created this routine for use in Graph3DP. Enjoy!