Okay. This will be my final update for a while.
In this one, you're able to type on screen MUCH faster than before. I added a mouse buffer so it can now handle two simultaneous taps. I suspect that typing speed was limited in previous versions because it would ignore all additional taps until you let up with the first one. People were probably hitting the second letter before releasing the first.
I also threw in a lookup table for the buttons, so the hardware button section is much more concise now. Perhaps it's not as easy to read, but it did make it more responsive.
I also set it up to change the cursor color in dark mode so you can actually see it now.
There was a bug where it wouldn't be able to determine the current font size if you had the calculator set to almost any number format other than "normal". That's fixed now, too.
Unfortunately, the touch screen code is much more involved, so the file size actually went up a bit. My apologies for the somewhat excessive nested "if" statements in this one. There's probably a more graceful method, but I wasn't seeing it at the time I wrote this one.
Code:
#pragma mode( separator(.,;) integer(h32) )
// ===================================================================================================
// Author: F. Freire
// Thanks to: primer(Author of the vkb)
// Patched by: mushman
//
// Name: Virtual Keys
// Description: Virtual Keys is a Virtual Keyboard to make typing on HP Prime faster
// Version: 1.3c
// Create date: 04 July 2017
// Firmware Target: 10637 -> 29/08/2016
//
// Virtual_Keys Thread: http://www.hpmuseum.org/forum/thread-8262.html
// vkb Thread: http://www.hpmuseum.org/forum/thread-6948.html
//
// Assigned to User Key -> [On]
// ===================================================================================================
drawkb(); drawtxt(); chkkey(); addchar(); setup();
movecurs(); getmouse(); dropchar(); delchar(); check_display();
clearchar(); flashkey(); kbd_type_x(); kbd_type_y();
drawatpos(); text_width(); text_height(); txtwcurs(); redrawtxt();
LOCAL dirty_shutdown;
LOCAL dirt;
LOCAL t; // Start y keyboard position
LOCAL stay:=0; // chkkey Behaviour
LOCAL txt; // Screen Text
LOCAL curs; // Cursor position
LOCAL qoffs:={64,96}; // Qwerty offset (64 upper/96 lower)
LOCAL goffs:={-32,0}; // Greek Offset (913 upper/945 lower)
LOCAL soffs:={0,0}; // Symbol Offset - Not applied
LOCAL alphaOn:=0; // Alpha mode
LOCAL shiftOn:=0; // Shift mode
LOCAL flash_time:=50;
LOCAL flashed:=0; // Key Flash
LOCAL r:=1; // Release key
LOCAL vk_height; // Text box height
LOCAL st; // Animation STEP (0-4)
LOCAL posc; // Cursor position
LOCAL btnsz; // buttonsize.
LOCAL shift_down_mode;
LOCAL alpha_down_mode;
LOCAL shift_held_mode;
LOCAL alpha_held_mode;
LOCAL alpha_layout_keys := {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26};
LOCAL qwerty_layout_keys := {17,23,5,18,20,25,21,9,15,16,1,19,4,6,7,8,10,11,12,26,24,3,22,2,14,13};
LOCAL greek_layout_keys := {945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,1237};
LOCAL symb_layout_keys := {64,35,36,38,47,124,33,63,45,95,8734,57347,8804,60,62,8805,-10,8800,177,9654,8594,8737,-16,-17,65285,8710};
LOCAL symb_layout_keys_alphaOn := {8320,8321,8322,8323,8324,8325,8326,8327,8328,8329,57348,178,179,-11,-12,-13,-14,-15,94,176,8242,8243,46,58,170,8706};
LOCAL bypass_chars := {"== ","AND ","OR ","EQ()","NOT ","XOR ","''",""""""};
LOCAL bypass_chars_kbd := {"==","AND","OR","EQ","NOT","XOR","''",""""""};
LOCAL math_hold;
LOCAL aloffs; // Active Layout Offset Holder
LOCAL offset; // Actual Offset number
LOCAL active_layout_keys;
LOCAL active_layout := 1; // 1- Qwerty/ 2- Greek / 3- Symb
LOCAL aA_key, aA_x; // Posição no teclado do aA. / Posição x do aA.
LOCAL Sym_key, Sym_x; // Posição no teclado do Sym. / Posição x do Sym.
LOCAL kbd_x,kbd_y,kbd_size; // #Colunas do teclado. / #Linhas do teclado. / #Teclas.
LOCAL selected_layout_text:={"Qwerty","Greek","Symbolic","⇧Qwerty","⇧Greek","⇧Symbolic"};
LOCAL ht:={10,12,16,20,22,24,26}; // text_height() Table
// Physical Key Codes - Reference
LOCAL K_APPS=0, K_SYMB=1, K_ARROWUP=2, K_HELP=3, K_ESC=4, K_HOME=5;
LOCAL K_PLOT=6, K_ARROWLEFT=7, K_ARROWRIGHT=8, K_VIEW=9, K_CAS=10;
LOCAL K_NUM=11, K_ARROWDOWN=12, K_MENU=13;
LOCAL K_A=14, K_B=15, K_C=16, K_D=17, K_E=18, K_DEL=19;
LOCAL K_F=20, K_G=21, K_H=22, K_I=23, K_J=24, K_K=25;
LOCAL K_L=26, K_M=27, K_N=28, K_O=29, K_ENTER=30;
LOCAL K_P=31, K_Q=32, K_R=33, K_S=34, K_T=35;
LOCAL K_ALPHA=36, K_U=37, K_V=38, K_W=39, K_X=40;
LOCAL K_SHIFT=41, K_Y=42, K_Z=43, K_HASH=44, K_DOUBLEDOT=45;
LOCAL K_OFF=46, K_NOTES=47, K_EQUAL=48, K_UNDERSCORE=49, K_ANS=50;
CONST specials:={30,36,41,46};
CONST shift_specials:={34,36};
CONST shift_text:={" NTHROOT ","ASIN()","ACOS()","ATAN()","e^()","ALOG()","√","ABS()","''","EVAL()","","▶","7","{}","","","","4","[]","","∡","","1","","π",":","","""""","=","_","Ans"};
CONST norm_text:={"^","SIN()","COS()","TAN()","LN()","LOG()","^2","−","()",",","","ᴇ","7","8","9","/","","4","5","6","*","","1","2","3","-","","0","."," ","+"};
// Colors
LOCAL c_gray:=#AAAAAAh, c_white:=#FFFFFFh, c_purple:=#C8BFE7h, c_blue:=#3399FFh, c_black:=#000000h, c_dgray:=#AAAAAAh, c_lgray:=#AAAAAAh;
LOCAL c_darkblue:=#0066FFh, c_orange:=#FF6600h;
LOCAL c_cursor;
LOCAL color_textfieldbg:=Theme(1);
LOCAL theme:=Theme;
LOCAL mouseLoc1:={};
LOCAL mouseLoc2:={};
LOCAL mouseBuffer:={};
LOCAL buttonSize:={32,22};
CONST theme_colors:={{#FEABA0h,#410808h},{#FED897h,#412C08h},{#FBED8Bh,#454521h},{#CEF6A6h,#0A3B08h},{#ADCCFFh,#1D394Bh},{#EDC9FDh,#32134Dh}};
LOCAL theme_checked:=0;
// Checks and Changes values for the current Keyboard Layout
check_layout()
BEGIN
IF NOT theme_checked THEN
theme_checked:=1;
color_textfieldbg:=theme_colors(Theme(2),Theme(1));
c_cursor:=c_white * BITSR(Theme(1),1);
c_gray:= BITXOR(c_gray,c_cursor);
END;
CASE
IF active_layout == 1 THEN //Qwerty
active_layout_keys:=qwerty_layout_keys;
aloffs:=qoffs;
btnsz:= 32;
aA_key:= 21; aA_x:= 0.5;
kbd_x:= 10; kbd_y:= 4; kbd_size:= 40;
Sym_key:=29; Sym_x:=8.5;
END;
IF active_layout == 2 THEN //Greek
active_layout_keys:=greek_layout_keys;
aloffs:=goffs;
btnsz:= 32;
aA_key:= 21; aA_x:= 0.5;
kbd_x:= 10; kbd_y:= 4; kbd_size:= 40;
Sym_key:=29; Sym_x:=8.5;
END;
IF active_layout == 3 THEN //Symb
active_layout_keys:=when(alphaOn,symb_layout_keys_alphaOn,symb_layout_keys);
aloffs:=soffs;
btnsz:= 32;
aA_key:= 21; aA_x:= 0.5;
kbd_x:= 10; kbd_y:= 4; kbd_size:= 40;
Sym_key:=29; Sym_x:=8.5;
END;
END;
t:= 240-kbd_y*buttonSize(2);
offset:=aloffs(alphaOn);
END;
change_alpha()
BEGIN
alphaOn:=NOT (alphaOn XOR alpha_held_mode);
IF active_layout==3 THEN // Changes Symbols
active_layout_keys:=when(alphaOn,symb_layout_keys_alphaOn,symb_layout_keys);
ELSE
offset:=aloffs(alphaOn);
END;
drawkb();
check_display();
END;
change_shift(n)
BEGIN
IF (shift_held_mode) THEN RETURN; END;
IF n THEN
shiftOn:=1-shiftOn;
ELSE
shiftOn:=0;
END;
check_display()
END;
check_display()
BEGIN
dirt:=1;
drawtxt();
END;
change_layout(n) // 1- Qwerty/ 2- Greek / 3- Symb
BEGIN
CASE
IF n==-2 THEN
active_layout:=when(active_layout==2,1,2);
END;
IF n==-3 THEN
active_layout:=when(active_layout==3,1,3);
END;
IF n==-4 THEN
active_layout:=when(active_layout==3,1,1+active_layout);
END;
active_layout:=n;
END;
BLIT_P(G0,G7);
check_layout();
drawkb();
check_display();
END;
layout_choise()
BEGIN
LOCAL n;
CHOOSE(n,"Choose Layout",selected_layout_text);
LOCAL main:= ((n-1) MOD 3)+1;
alphaOn:=n>3;
change_layout(main);
END;
check_key(ch) // Bypass Offset for some characters
BEGIN
CASE
// Bypass Layout
// IF ch == THEN ch:=; END;
IF ch == 930 THEN ch:=978; END;
IF ch == 1205 THEN ch:=1236; END;
IF ch ≤ -10 THEN RETURN(bypass_chars(-ch-9)); END;
END;
RETURN CHAR(ch);
END;
// Main Behaviour
virtual_keys()
BEGIN
LOCAL c;
setup();
REPEAT
drawtxt();
c:=chkkey();
IF (c ≠ "") THEN addchar(c); END;
UNTIL stay;
//toggle_time:=time();
IF stay==1 THEN
RETURN(txt);
ELSE
RETURN "";
END;
END;
// Handles the Keys
chkkey()
BEGIN
LOCAL k,m;
k:=GETKEY();
IF shift_held_mode AND NOT iskeydown(K_SHIFT) THEN
shift_held_mode:=0;
shift_down_mode:=0;
change_shift(0);
END;
IF alpha_held_mode AND NOT iskeydown(K_ALPHA) THEN
alpha_held_mode:=0;
alpha_down_mode:=0;
change_alpha();
END;
IF shift_down_mode AND NOT iskeydown(K_SHIFT) THEN
shift_down_mode:=0;
END;
IF alpha_down_mode AND NOT iskeydown(K_ALPHA) THEN
alpha_down_mode:=0;
END;
IF k≠−1 THEN
IF (k<>K_SHIFT) AND shift_down_mode THEN
shift_held_mode:=1;
END;
IF (k<>K_ALPHA) AND alpha_down_mode THEN
alpha_held_mode:=1;
END;
IF (k<=19 OR (shiftOn AND (POS(shift_specials,k)>0)) OR (POS(specials,k)>0)) THEN
CASE // Physical Keyboard / stay=2 Exits the Keyboard without text, stay=1 Enters the text.
// Arrows [< >]
IF k==K_ARROWLEFT THEN
IF shiftOn THEN movecurs(-curs); change_shift(0);
ELSE movecurs(-1); END;
END;
IF k==K_ARROWRIGHT THEN
IF shiftOn THEN movecurs(DIM(txt)-curs); change_shift(0);
ELSE movecurs(1); END;
END;
// Common Keys [Esc View] [Math xtθn ab/c Backspace] [x^y SIN COS TAN LN LOG] [x^2 +/- () , Enter] [EEX] [ALPHA] [Shift] [On Dot Space]
// Special Keys
IF k==K_ESC THEN // Esc (Without shiftOn exits the kbd)
IF shiftOn THEN change_shift(0); clearchar();
ELSE
WHILE iskeydown(K_ESC) DO wait(0.001); END;
stay:=2;
END;
END;
IF k==K_VIEW THEN // View
layout_choise();
END;
// Row 1
IF k==K_C THEN // Math
change_layout(-3);
END;
IF k==K_D THEN // xtθn
change_layout(-2);
END;
IF k==K_E THEN // ab/c
change_layout(1);
END;
IF k==K_OFF THEN // Exits the kbd *** NEVER HIT, OS AUTO-EXITS PROGRAM
stay:=2;
RETURN "";
END;
IF k==K_DEL THEN // Backspace
IF shiftOn THEN change_shift(0); delchar(); RETURN("");
ELSE dropchar(); RETURN(""); END;
END;
IF k==K_ENTER THEN stay:=1; END; // Enter (Enters the text)
IF k==K_ALPHA THEN
change_alpha();
alpha_down_mode:=1;
END;
IF k==K_SHIFT THEN
change_shift(1);
shift_down_mode:=1;
END;
IF k==K_S THEN
IF shiftOn THEN change_shift(0); change_layout(-3);
ELSE RETURN ("9"); END;
END;
IF k==K_W THEN
IF shiftOn THEN change_shift(0); change_layout(-3);
ELSE RETURN ("6"); END;
END;
END;
ELSE
IF shiftOn THEN change_shift(0); RETURN shift_text(k-19);
ELSE RETURN norm_text(k-19); END;
END;
END;
IF stay THEN RETURN (""); END;
//Virtual Keyboard
m:=getmouse();
IF (m>0)AND(shift_down_mode AND iskeydown(K_SHIFT)) THEN shift_held_mode:=1; END;
IF (m>0)AND(alpha_down_mode AND iskeydown(K_ALPHA)) THEN alpha_held_mode:=1; END;
IF m==aA_key THEN // Aa Handle
m:=0;
change_alpha();
END;
IF m==Sym_key THEN // Sym Handle
change_layout(-4);
END;
IF m>0 THEN
IF m<29 OR m==31 OR m==32 OR m==38 OR m==39 OR (m>=33 AND m<=37) THEN
flashkey(m);
END;
IF m==20 OR m==21 OR m>28 THEN
CASE
IF m==31 THEN RETURN ("="); END;
IF m==32 THEN RETURN (":= "); END;
IF m>=33 AND m<=37 THEN RETURN (" "); END;
IF m==38 THEN RETURN (";"); END;
IF m==39 THEN RETURN (","); END;
RETURN ("");
END;
ELSE
IF m>21 THEN
RETURN check_key(active_layout_keys(m-2)+offset);
ELSE
RETURN check_key(active_layout_keys(m)+offset);
END;
END;
END;
RETURN ("");
END;
doflash(a)
BEGIN
LOCAL x:= kbd_type_x(a);
LOCAL y:= kbd_type_y(a);
IF y==3 AND x>=2.5 AND x<=6.5 THEN // Space Bar
INVERT_P(2.5*buttonSize(1)+1,t+y*buttonSize(2)+1,(6.5+1)*buttonSize(1)-1,t+(y+1)*buttonSize(2)-1);
ELSE
INVERT_P(x*buttonSize(1)+1,t+y*buttonSize(2)+1,(x+1)*buttonSize(1)-1,t+(y+1)*buttonSize(2)-1);
END;
END;
unflash()
BEGIN
IF flashed THEN
doflash(flashed-1);
flashed:=0;
END;
END;
flashkey(c) // Do a flash on key
BEGIN
LOCAL a=c-1;
unflash();
flashed:=c;
doflash(a);
END;
//LOCAL mouseLoc1;
//LOCAL mouseLoc2;
//LOCAL mouseBuffer:={};
// Get "key" from mouse
getmouse()
BEGIN
//LOCAL x:=MOUSE(0);
LOCAL mVals:=MOUSE();
LOCAL ml1Present:=0;
LOCAL ml2Present:=0;
LOCAL coord;
IF (Size(mVals(1))==0) AND (SIZE(mVals(2))==0) THEN
r:=1;
mouseBuffer:={};
END;
// No presses in log.
IF (SIZE(mouseLoc1)==0) AND (SIZE(mouseLoc2)==0) THEN
IF (SIZE(mVals(1))<>0) THEN
mouseBuffer(SIZE(mouseBuffer)+1):=mVals(1);
ml1Present:=1;
mouseLoc1:=mVals(1);
END;
IF (SIZE(mVals(2))<>0) THEN
mouseBuffer(SIZE(mouseBuffer)+1):=mVals(2);
IF (NOT ml1Present) THEN
ml1Present:=1;
mouseLoc1:=mVals(2);
ELSE
ml2Present:=1;
mouseLoc2:=mVals(2);
END;
END;
ELSE
IF (SIZE(mouseLoc1)<>0) AND (SIZE(mouseLoc2)<>0) THEN
// Two presses in log
IF (SIZE(mVals(1))<>0) THEN
IF (IsSameClick(mVals(1),mouseLoc1)) THEN
ml1Present:=1;
ELSE
IF (IsSameClick(mVals(1),mouseLoc2)) THEN
ml2Present:=1;
ELSE
// mVals(1) is a new click, so we find which to replace.
IF (SIZE(mVals(2))==0) THEN
// mVals(1) is the only click in the list.
ml1Present:=1;
mouseLoc1:=mVals(1);
mouseBuffer(SIZE(mouseBuffer)+1):=mVals(1);
ELSE
IF (IsSameClick(mVals(2),mouseLoc1)) THEN
ml1Present:=1;
ml2Present:=1;
mouseLoc2:=mVals(1);
mouseBuffer(SIZE(mouseBuffer)+1):=mVals(1);
ELSE
IF (IsSameClick(mVals(2),mouseLoc2)) THEN
ml1Present:=1;
ml2Present:=1;
mouseLoc1:=mVals(1);
mouseBuffer(SIZE(mouseBuffer)+1):=mVals(1);
ELSE
ml1Present:=1;
ml2Present:=1;
mouseLoc1:=mVals(1);
mouseLoc2:=mVals(2);
mouseBuffer(SIZE(mouseBuffer)+1):=mVals(1);
mouseBuffer(SIZE(mouseBuffer)+1):=mVals(2);
END;
END;
END;
END;
END;
END;
IF (SIZE(mVals(2)<>0)) THEN
IF (ml1Present AND NOT ml2Present) THEN
IF (IsSameClick(mVals(2),mouseLoc2)) THEN
ml2Present:=1;
ELSE
ml2Present:=1;
mouseLoc2:=mVals(2);
mouseBuffer(SIZE(mouseBuffer)+1):=mVals(2);
END;
ELSE
IF (ml2Present AND NOT ml1Present) THEN
IF (IsSameClick(mVals(2),mouseLoc1)) THEN
ml1Present:=1;
ELSE
ml1Present:=1;
mouseLoc1:=mVals(2);
mouseBuffer(SIZE(mouseBuffer)+1):=mVals(2);
END;
END;
END;
END;
ELSE
// At least one free spot.
IF (SIZE(mouseLoc1)==0) AND (SIZE(mouseLoc2)<>0) THEN
mouseLoc1:=mouseLoc2;
mouseLoc2:={};
END;
// ml2 is free
IF (SIZE(mVals(1))<>0) THEN
IF (IsSameClick(mVals(1),mouseLoc1)) THEN
ml1Present:=1;
ELSE
mouseLoc2:=mVals(1);
ml2Present:=1;
mouseBuffer(SIZE(mouseBuffer)+1):=mVals(1);
END;
IF (SIZE(mVals(2))<>0) THEN
IF (ml1Present) THEN
mouseLoc2:=mVals(2);
ml2Present:=1;
mouseBuffer(SIZE(mouseBuffer)+1):=mVals(2);
ELSE
IF (ml2Present) THEN
IF (IsSameClick(mouseLoc1,mVals(2))) THEN
ml1Present:=1;
ELSE
ml1Present:=1;
mouseLoc1:=mVals(2);
mouseBuffer(SIZE(mouseBuffer)+1):=mVals(2);
END;
END;
END;
END;
END;
END;
END;
IF (NOT ml1Present) THEN
mouseLoc1:={};
END;
IF (NOT ml2Present) THEN
mouseLoc2:={};
END;
IF (SIZE(mouseBuffer)>0) THEN
coord:=mouseBuffer(1);
mouseBuffer:=SUPPRESS(mouseBuffer,1);
RETURN btnFromCoords(coord(1),coord(2));
END;
RETURN 0;
END;
btnFromCoords(x,y)
BEGIN
IF y>t THEN
y:=IP((y-t)/buttonSize(2));
x:=min(x,buttonSize(1)*(kbd_x-1));
IF y > 0 THEN
x:=IP(x/(buttonSize(1)*0.5));
IF x < 3 THEN
x:=0;
ELSE
x:=IP((x-1)/2);
END;
ELSE // Always run for first line
x:=IP(x/buttonSize(1));
END;
RETURN 1+x+(y*kbd_x);
END;
END;
IsNewClick(click)
BEGIN
LOCAL isNew:=1;
IF (SIZE(mouseBuffer) >= 1) AND (SIZE(mouseBuffer(1)) <> 0) THEN
isNew:=(mouseBuffer(1,3)==click(3)) AND (mouseBuffer(1,4)==click(4));
END;
IF (SIZE(mouseBuffer) >= 2) AND (SIZE(mouseBuffer(2)) <> 0) THEN
isNew:=isNew OR ((mouseBuffer(2,3)==click(3)) AND (mouseBuffer(2,4)==click(4)));
END;
RETURN isNew;
END;
IsSameClick(clk1, clk2)
BEGIN
RETURN (clk1(3)==clk2(3)) AND (clk1(4)==clk2(4));
END;
// Move cursor
movecurs(d)
BEGIN
LOCAL n:=curs+d;
IF n<0 THEN n:=0; END;
IF n> DIM(txt) THEN n:=DIM(txt); END;
curs:=n;
dirt:=1; // Set to Redraw
END;
drawtxt()
BEGIN
IF dirt THEN // Redraw
redrawtxt();
st:=0;
dirt:=0;
ELSE
IF (st<>0) AND ((st MOD 4)==0) THEN
unflash();
END;
CASE
IF st==0 THEN
LINE_P(posc,t-vk_height+2,posc,t-4,c_cursor);
END;
IF st==40 THEN
LINE_P(posc,t-vk_height+2,posc,t-4,color_textfieldbg);
END;
IF st==80 THEN
st:=-1;
END;
END;
st:=st+1;
END;
WAIT(0.01);
END;
redrawtxt()
BEGIN
LOCAL t1,t2; // Text parts
LOCAL left_t:=2;
RECT_P(0,t-vk_height,kbd_x*buttonSize(1)-1,t-1,c_gray,color_textfieldbg); // Clear text
IF curs>0 THEN t1:=LEFT(txt,curs); ELSE t1:=""; END;
IF curs==DIM(txt) THEN t2:=""; ELSE t2:=MID(txt,1+curs); END;
//posc:=left_t+text_width(t1,0);
posc:=TEXTOUT_P(t1,left_t,t-vk_height+left_t);
TEXTOUT_P(t2,posc,t-vk_height+left_t);
IF shiftOn THEN
TEXTOUT_P("↑S",280,t-vk_height+left_t,0,c_darkblue);
END;
IF alphaOn THEN
TEXTOUT_P("↑AZ",295,t-vk_height+left_t,0,c_orange);
END;
END;
text_width(t,font_size)
BEGIN
LOCAL wi;
wi:=TEXTOUT_P(t,G9,0,0,font_size,0,320,0);
RETURN wi;
END;
text_height(font_size)
BEGIN
LOCAL wi,fs;
wi:=TEXTOUT_P("1",G9,0,0,font_size,0,320,0);
CASE
IF wi==8 THEN fs:=3; END; // Higher priority first, Normal Font
IF wi==7 THEN fs:=2; END; // Small Font
IF wi==9 THEN fs:=4; END; // Big Font
IF wi==5 THEN fs:=1; END;
IF wi==10 THEN fs:=5; END;
IF wi==11 THEN fs:=6; END;
fs:=7;
END;
RETURN ht(fs);
END;
txtwcurs(c)
BEGIN
LOCAL a:="";
LOCAL b:=MID(txt,1+curs);
IF curs>0 THEN a:=LEFT(txt,curs); END;
IF curs==DIM(txt) THEN b:=""; END;
RETURN a+c+b;
END;
// Add a char to the string
addchar(c)
BEGIN
txt:=txtwcurs(c);
IF DIM(c) > 2 THEN
movecurs(DIM(c)-1);
IF RIGHT(c,1)==" " THEN
delchar();
END;
ELSE
movecurs(1);
END;
END;
dropchar()
BEGIN
LOCAL a:="";
LOCAL b:=MID(txt,1+curs);
IF curs>1 THEN a:=LEFT(txt,curs-1); END;
IF curs==DIM(txt) THEN b:=""; END;
txt:=a+b;
movecurs(-1);
END;
delchar()
BEGIN
LOCAL a:=LEFT(txt,curs);
LOCAL b:="";
IF curs<(DIM(txt)-1) THEN b:=MID(txt,2+curs); END;
IF curs==0 THEN a:=""; END;
txt:=a+b;
movecurs(0);
END;
clearchar()
BEGIN
txt:=("");
movecurs(0);
END;
kbd_type_x(n)
BEGIN
RETURN (n MOD 10) + 0.5*(n>=10);
CASE
IF n<10 THEN
RETURN (n);
END;
IF n>=10 AND n<20 THEN
RETURN (n-9.5);
END;
IF n>=20 AND n<30 THEN
RETURN (n-19.5);
END;
IF n>=30 AND n<40 THEN
RETURN (n-29.5);
END;
END;
END;
kbd_type_y(n)
BEGIN
RETURN FLOOR(n/10);
CASE
IF n<10 THEN
RETURN(0);
END;
IF n>=10 AND n<20 THEN
RETURN(1);
END;
IF n>=20 AND n<30 THEN
RETURN(2);
END;
IF n>=30 AND n<40 THEN
RETURN(3);
END;
END;
END;
// Draws the Keyboard
drawkb()
BEGIN
LOCAL a;
LOCAL b:=-1;
//buttonSize(2):=text_height(0)+10;
RECT_P(0,t,kbd_x*buttonSize(1),240);
// Horizontal lines
FOR a FROM 0 TO kbd_y*buttonSize(2) STEP buttonSize(2) DO
IF a == kbd_y*buttonSize(2) THEN
LINE_P(0,t+a-1,kbd_x*buttonSize(1),t+a-1);
ELSE
LINE_P(0,t+a,kbd_x*buttonSize(1),t+a);
END;
END;
// Vertical lines
FOR a FROM 0 TO kbd_x*buttonSize(1) STEP buttonSize(1) DO
IF a==0 OR a==kbd_x*buttonSize(1) THEN
IF a == kbd_x*buttonSize(1) THEN a:=kbd_x*buttonSize(1)-1;END;
LINE_P(a,t,a,240);
ELSE
LINE_P(a,t,a,240-(kbd_y-1)*buttonSize(2));
LINE_P(a-buttonSize(1)/2,t+buttonSize(2),a-buttonSize(1)/2,240-buttonSize(2));
IF a == (kbd_x-1)*buttonSize(1) THEN
LINE_P(a+buttonSize(1)/2,t+buttonSize(2),a+buttonSize(1)/2,240-buttonSize(2));
END;
END;
END;
// Draws last line
LINE_P(0.5*buttonSize(1),240-buttonSize(2),0.5*buttonSize(1),240);
LINE_P(1.5*buttonSize(1),240-buttonSize(2),1.5*buttonSize(1),240);
LINE_P(2.5*buttonSize(1),240-buttonSize(2),2.5*buttonSize(1),240);
LINE_P(7.5*buttonSize(1),240-buttonSize(2),7.5*buttonSize(1),240);
LINE_P(8.5*buttonSize(1),240-buttonSize(2),8.5*buttonSize(1),240);
LINE_P(9.5*buttonSize(1),240-buttonSize(2),9.5*buttonSize(1),240);
// Draws Letters over Keys ae=1237 AE=1236
FOR a FROM 0 TO (kbd_size-2) DO
LOCAL x:= kbd_type_x(a);
LOCAL y:= kbd_type_y(a);
IF a<>19 AND a<>20 AND a<28 THEN
b:=b+1;
math_hold:=active_layout_keys(b+1);
IF active_layout==3 AND math_hold ≤ -10 THEN
math_hold:=bypass_chars_kbd(-math_hold-9);
drawatpos(x,y,math_hold);
ELSE
drawatpos(x,y,check_key(math_hold+offset));
END;
END;
END;
// Draws aA Key
RECT_P(aA_x*buttonSize(1)+1,t+2*buttonSize(2)+1,(aA_x+1)*buttonSize(1)-1,t+3*buttonSize(2)-1,c_gray);
CASE
IF active_layout==1 THEN
drawatpos(aA_x,2,"aA");
END;
IF active_layout==2 THEN
drawatpos(aA_x,2,"αΑ");
END;
drawatpos(aA_x,2,"++");
END;
// Draws Special Keys
IF active_layout > 0 THEN
RECT_P(Sym_x*buttonSize(1)+1,t+2*buttonSize(2)+1,(Sym_x+1)*buttonSize(1)-1,t+3*buttonSize(2)-1,c_gray,c_gray);
CASE
IF active_layout==1 THEN
drawatpos(Sym_x,2,"αβγ");
END;
IF active_layout==2 THEN
drawatpos(Sym_x,2,"Sym");
END;
drawatpos(Sym_x,2,"abc");
END;
drawatpos(0.5,3,"=");
drawatpos(1.5,3,":=");
drawatpos(4.5,3,"Space");
drawatpos(7.5,3,";");
drawatpos(8.5,3,",");
END;
vk_height:=text_height(0)+3;
END;
// Draws Key - Converts keyboard position to screen position
drawatpos(x,y,c)
BEGIN
TEXTOUT_P(c,G0,(x+0.5)*buttonSize(1)-(text_width(c,0)/2),t+(y+0.5)*buttonSize(2)-(text_height(0)/2));
END;
// Virtual_Keys Init
setup()
BEGIN
DIMGROB_P(G7,320,240);
DIMGROB_P(G9,320,240);
BLIT_P(G7,G0);
stay:=0; curs:=0; txt:=""; dirt:=1;
shift_down_mode:=iskeydown(K_SHIFT);
alpha_down_mode:=iskeydown(K_ALPHA);
buttonSize(2):=text_height(0)*2;
vk_height:=text_height(0)+3;
check_layout();
drawkb();
check_display();
END;
// Show or clear the keyboard : [On]
KEY K_On()
BEGIN
IF (dirty_shutdown) THEN
dirty_shutdown:=0;
RETURN "";
END;
dirty_shutdown:=1;
LOCAL val:=virtual_keys();
dirty_shutdown:=0;
RETURN val;
END;