Text_and_Number_Input

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!