The program works perfectly on my updated Prime G2,
Remember that you have to enter user mode - Shift-Help (2 times to lock it) in order to use the program.
(08-21-2019 09:17 PM)Mosrod Wrote: The program works perfectly on my updated Prime G2,
Remember that you have to enter user mode - Shift-Help (2 times to lock it) in order to use the program.
Here's a patched version with some changes:
- Textbox follows selected color theme as well as light/dark theme.
- Removed box with layout info and moved shift/alpha icons to the right (more screen is visible).
- Toggle keyboard with [On] button instead of Alpha+Dot.
Cheers!
01-04-2022, 08:32 PM (This post was last modified: 01-05-2022 01:07 AM by IHarwell.)
(01-04-2022 02:23 AM)mushman Wrote: Here's a patched version with some changes:
- Textbox follows selected color theme as well as light/dark theme.
- Removed box with layout info and moved shift/alpha icons to the right (more screen is visible).
- Toggle keyboard with [On] button instead of Alpha+Dot.
Cheers!
Thanks for the update!
I'm relatively new here, so please forgive me if this isn't where this should go.
I'm getting an error on line 205. Did you mean to use the "time" system variable, or the "ticks" function?
I also noticed a few things that could use improvement (IMO, others' preferences may vary):
Perhaps draw icons on the title bar like the Prime does when you press the appropriate button?
Detect whether the current font size rather than making everything large enough to handle the largest font. (See Easy Sto II code for an example of this that works pretty well. It took some time to get it running reliably, so I wouldn't recommend writing it from scratch unless you know of a better way to do it.)
Use the "Shift" key to move to capital letters instead of "Alpha" (How the Prime does it natively)
Perhaps add a "Backspace" and/or "Enter" button on the keyboard?
If the user holds down either the "Shift" or "Alpha" keys, exit the mode when they're released and don't exit the mode while it's "Del" key with the "Shift" key down, which should delete the next character and leave the Shift mode on.
Perhaps add an option for it to remember the last mode it was in between calls?
Add pass-through support for the Apps, Home, Cas, Symb, Plot, Num, Help, View, and Menu buttons. Most built-in features exit whatever mode they're in and execute those buttons directly when they're pressed.
Take the lower commands on the screen on entry and redraw them above the keyboard when running it. This would only apply to the Home and CAS views, I think.
Move to Python for much faster drawing routines? It can be done here since it looks like they aren't trying to interact with the command line directly or read screen pixels from within the input loop. The Python methods for reading key states is quite efficient, but would require a poll loop rather than reading the key buffer. It would introduce a roughly fixed 15-20 ms latency on entry, but would get the execution loop to run significantly faster if my testing is any indication.
Change the exit routine to leave when the "On" key is released rather than when it's pressed, as it currently exits, the calculator sees that "On" is pressed, and immediately runs it again.
I can take a look at making those changes if any of them sound good to other people. Most of them are really simple to do from what I've seen of the code. Just let me know the numbers that sound worthwhile? I'd prefer to avoid making unwanted changes if I can avoid it.
** EDIT: I just checked a few things out, and it looks like the touchscreen reliably registers taps that are just outside the screen area. If people think it's a reasonable thing to do, it should be feasible to leave the current layout as-is, and just add the backspace button to one of the half-keys on the right edge of the keyboard.
01-05-2022, 04:53 AM (This post was last modified: 01-05-2022 04:54 AM by IHarwell.)
Perhaps draw icons on the title bar like the Prime does when you press the appropriate button?
Detect whether the current font size rather than making everything large enough to handle the largest font. (See Easy Sto II code for an example of this that works pretty well. It took some time to get it running reliably, so I wouldn't recommend writing it from scratch unless you know of a better way to do it.)
Use the "Shift" key to move to capital letters instead of "Alpha" (How the Prime does it natively)
Perhaps add a "Backspace" and/or "Enter" button on the keyboard?
If the user holds down either the "Shift" or "Alpha" keys, exit the mode when they're released and don't exit the mode while it's "Del" key with the "Shift" key down, which should delete the next character and leave the Shift mode on.
Perhaps add an option for it to remember the last mode it was in between calls?
Add pass-through support for the Apps, Home, Cas, Symb, Plot, Num, Help, View, and Menu buttons. Most built-in features exit whatever mode they're in and execute those buttons directly when they're pressed.
Take the lower commands on the screen on entry and redraw them above the keyboard when running it. This would only apply to the Home and CAS views, I think.
Move to Python for much faster drawing routines? It can be done here since it looks like they aren't trying to interact with the command line directly or read screen pixels from within the input loop. The Python methods for reading key states is quite efficient, but would require a poll loop rather than reading the key buffer. It would introduce a roughly fixed 15-20 ms latency on entry, but would get the execution loop to run significantly faster if my testing is any indication.
Change the exit routine to leave when the "On" key is released rather than when it's pressed, as it currently exits, the calculator sees that "On" is pressed, and immediately runs it again.
Okay. Here's a minor update. It addresses the error in the previous version as well as incorporating some of the easier items on the list.
It addresses #10 using a flag to indicate if the program is interrupted. Turns out hitting "On" just exits the program immediately.
It addresses #5, as that just made sense to do.
#2 was actually a bug in the previous version. It had the wrong value for small fonts, so it wasn't detecting those correctly.
#6 was already a thing and I just missed it. XD
I'll see if I can work in #7 tomorrow. The others depend heavily on preference or are major overhauls.
Okay, I was working on number 7 and ran across the feature that's built into the "View" key.
It's pretty handy, and it's good enough it's worth keeping instead of using passthrough. I added three more options to the list to further improve it. Now, you can go directly to the precise keyboard you want rather than having to hit the alpha key once you've arrived at one.
Two other small changes:
- The keys now scale with the size of the font you have the calculator set to.
- There's now a mouse offset property that you can use to preprocess mouse input if you're getting the wrong thing to show up when you think you're pressing the right key. It's an issue mainly at the small font size, where your finger obstructs the buttons.
Lastly, I forgot to mention another change I made in the previous version, so I'll mention it here. I reduced the length of the "wait" call in the flashing routine and increased the number of iterations between flashes. This was mainly to improve responsiveness, but I'm not totally sure if it made a difference.
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.
Here's the code for anyone who wants to go through it:
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]
// ===================================================================================================
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};
// 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 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;
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;
// 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;
Awesome update!
Since multiple people are working on this and it seems like a great project, I took liberty to put it on git so we can collaborate easier. When the original author shows up, I'll transfer the project.
I made additional commit changing '=' and ':=' keys to ':' and '='. Doubledot is used a lot in python and pascal people can still write ':=' fairly easy. If people don't like this change, I'm fine to revert and use separate patch privately.