-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathui_input_box.tbs
More file actions
555 lines (510 loc) · 17.7 KB
/
ui_input_box.tbs
File metadata and controls
555 lines (510 loc) · 17.7 KB
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
'*********************************************************************************
' ON SCREEN INPUT BOX CONTROL
'
' Input box module is used to edit string on screen. This input box supports
' numeric, upper case and lower case aphabetics. It also supports 'hidden'
' character(in the case such as password), the screen will display "*" instead of
' the actual character. Since the key config and layout is differ in each device,
' the printing and operating of the keys are defined in the external device
' specific functions. User can use device_input_box_pre() to prepare the input
' box including printing of buttons, and use device_ib_key_proc() to process the
' keys.
' Another important feature of this input box is the "mask", the mask is used
' when editing string that requires special format.(ex. time 12:00, ip 192.168.001.001)
' For example, the mask_str for time would be " : ", and for ip, it would be
' " . . . " these special characters in the mask string will be displayed
' even the string is empty, and this characters will be uneditable.
'
'*********************************************************************************
include "global.tbh"
'--------------------------------------------------------------------------------
declare sub ib_print()
declare sub ib_str_pos_selector()
declare sub ib_str_pos_increament(restart as no_yes)
declare sub ui_input_box_timer_proc()
declare sub ui_input_box_action(byref key_action as input_box_key_actions,byref key_asc as byte, byref insert_mode as no_yes)
'--------------------------------------------------------------------------------
dim chr_asc, lcd_pos_index, sourcestr_index, ib_len, display_len, display_start_index, ib_input_length as byte
dim cursor_x, prev_x as word
dim sourcestr, mask as string(IB_MAX_LEN)
dim ib_str as string(IB_MAX_LEN+2)
dim ib_secret_mode, ib_insert_mode as no_yes
dim input_type as input_box_char_ranges
dim input_box_result as ui_input_box_results
dim ib_timeout_ctr, ib_timeout as byte
'================================================================================
public function ui_input_box(
byref mask_str as string(IB_MAX_LEN), 'uneditable part of the input string
byref edit_str as string(IB_MAX_LEN), 'input string
char_range as input_box_char_ranges, 'the input range. INPUT_BOX_CHAR_RANGE_09 only allows numeric input, INPUT_BOX_CHAR_RANGE_AZ allows alphabetic, INPUT_BOX_CHAR_RANGE_09AZ allows both numeric and alphabetic input.
secret_mode as no_yes, 'if secret_mode=yes, all editable part of the input string will be display on the LCD as "*", this are mostly used for password.
insert_mode as no_yes, 'if insert_mode=yes, the new character is insert before the cursor, if insert_mode=no, the character replaces the character at the cursor position.
byref initial_pos as byte, 'initial cursor position
timeout as byte, 'if no keypad activity for the amount of time defined by timeout, input box is automatically closed and return to previous screen.
input_length as byte 'the maximum number of characters
) as ui_input_box_results
dim i as byte
dim kp_event as pl_kp_event_codes
dim kp_code as byte
dim t,w1,w2 as word
if kp.enabled=NO or kp.genkpevent<>NO then
kp.enabled=NO
kp.genkpevent=NO
kp.enabled=YES
else
kp.clearbuffer
end if
romfile.open(LCD_FIX_FONT)
lcd.setfont(romfile.offset)
lcd.texthorizontalspacing=UIB_HOR_SPACING
sourcestr=""
mask=mask_str
ib_secret_mode=secret_mode
ib_insert_mode=insert_mode
ib_timeout_ctr=timeout
ib_timeout=timeout
ib_input_length=0
input_box_result=INPUT_BOX_RESULT_TIMEOUT
input_type=char_range
w2=lcd.getprintwidth("0")+lcd.texthorizontalspacing
w1=INPUT_BOX_W
w1=w1/w2
display_len=w1-2
sourcestr_index=0
display_start_index=0
lcd_pos_index=0
chr_asc=255
'prepare mask string
if mask="" then
for i=1 to len(edit_str)
mask=mask + CHR(&h20) 'adding space for unfilled part of the mask
next i
end if
i=0
do
i=instr(i+1,mask,CHR(&h20),1)
if i=0 then exit do
ib_input_length=ib_input_length+1
loop while true
if ib_input_length<input_length then ib_input_length=input_length
'prepare sourcestr, sourcestr is the actual raw string(without mask characters) we are editing
for i=1 to len(edit_str)
if mid(mask,i,1)=CHR(&h20) then
sourcestr=sourcestr+mid(edit_str,i,1)
if lcd_pos_index<initial_pos then ib_str_pos_increament(no)
end if
next i
if insert_mode=no and len(sourcestr)=0 then
sourcestr=chr(&h20)
mask=mask + chr(&h20)
ib_str_pos_increament(no)
end if
device_input_box_pre(mask_str,edit_str,char_range ,secret_mode,insert_mode,initial_pos,timeout,input_length) 'prepre the input box
ib_print()
ib_str_pos_selector()
wait:
device_ib_interrupt() 'allow user to executes other procedures while inside the input box
if kp.enabled=NO then kp.enabled=YES
if kp.getkey(kp_event,kp_code)=OK then
if kp_event=PL_KP_EVENT_LOCKEDUP then
reset_keypad()
goto wait
end if
ui_input_box_key_proc(kp_event,kp_code)
end if
if input_box_result<>INPUT_BOX_RESULT_TIMEOUT then
ui_input_box=input_box_result
initial_pos=sourcestr_index
goto key_pressed
end if
'making sure that ui_msg_box_timer_proc() is not excuted more than once per timer interval(500ms)
if t<> sys.timercount then
t=sys.timercount
ui_input_box_timer_proc()
end if
if timeout=0 then
goto wait
else
if ib_timeout_ctr=0 then
ui_input_box=INPUT_BOX_RESULT_TIMEOUT
initial_pos=sourcestr_index
key_pressed:
if input_box_result=INPUT_BOX_RESULT_OK then
edit_str=sourcestr
mask_str=mask
end if
lcd_clear(INPUT_BOX_X,INPUT_BOX_Y,lcd.getprintwidth(ib_str),lcd.fontheight+2)
device_input_box_post(mask_str,edit_str,char_range ,secret_mode,insert_mode,initial_pos,timeout,input_length)
exit function
end if
goto wait
end if
end function
'--------------------------------------------------------------------------------
function ib_insert_format(edit_str as string(IB_MAX_LEN), mask_str as string(IB_MAX_LEN)) as string(IB_MAX_LEN)
'edit_str contains the editable part of the input string, mask_str contains the uneditable part. They are separated during editing process, this function put them back together.
dim i, j, k, l as byte
dim s1 as string(IB_MAX_LEN)
k=1
l=0
for i=1 to len(mask_str)
if mid(mask_str,i,1)=CHR(&h20) then
if not(k > len(edit_str)) then
s1=s1 + mid(edit_str,k,1)
else
s1=s1 + CHR(&h20)
end if
k=k+1
else
s1=s1 + mid(mask_str,i,1)
j=i
l=l+1
end if
next i
if len(edit_str)+l < j then
s1=left(s1,j)
else
s1=left(s1,len(edit_str)+l)
end if
ib_insert_format=s1
end function
'--------------------------------------------------------------------------------
sub ib_str_pos_increament(restart as no_yes)
'Move the cursor in the input box to the right
increment_pos:
if sourcestr_index=len(sourcestr) and ib_insert_mode=NO and right(sourcestr,1) <> chr(&h20) and len(sourcestr) < ib_input_length then
sourcestr=sourcestr + chr(&h20)
mask=mask + chr(&h20)
end if
if sourcestr_index < len(sourcestr) then
sourcestr_index=sourcestr_index+1
lcd_pos_index=lcd_pos_index + 1
if mid(mask,lcd_pos_index,1) <> CHR(&h20) and not(lcd_pos_index > len(mask)) then
lcd_pos_index=lcd_pos_index + 1
end if
if lcd_pos_index - display_start_index+1 > display_len then
display_start_index=lcd_pos_index - display_len +1
end if
else
if restart=YES then
sourcestr_index=1
lcd_pos_index=1
display_start_index=0
end if
end if
chr_asc=asc(mid(sourcestr,sourcestr_index,1))
end sub
'--------------------------------------------------------------------------------
sub ib_str_pos_decreament()
'Move the cursor in the input box to the left
if lcd_pos_index > 0 then
lcd_pos_index=lcd_pos_index - 1
sourcestr_index=sourcestr_index-1
if mid(mask,lcd_pos_index,1) <> CHR(&h20) and lcd_pos_index > 0 then
lcd_pos_index=lcd_pos_index - 1
end if
if display_start_index > 0 then display_start_index=display_start_index-1
end if
chr_asc=asc(mid(sourcestr,sourcestr_index,1))
end sub
'--------------------------------------------------------------------------------
sub ib_backspace()
'Remove the character that on the left of the cursor.
dim s1, s2 as string(IB_MAX_LEN)
dim i,j,k as byte
if sourcestr_index > 0 then
s1=left(sourcestr, sourcestr_index-1)
s2=right(sourcestr, len(sourcestr)-sourcestr_index)
j=0
for i=1 to len(mask)
if mid(mask,i,1)=chr(&h20) then
j=j+1
else
k=i
end if
next i
sourcestr=s1+s2
if len(sourcestr) < j and len(mask) > k then
mask=left(mask, len(mask)-1)
end if
ib_str_pos_decreament
end if
end sub
'--------------------------------------------------------------------------------
sub ib_delete()
'Remove the character that right above the cursor
dim s1, s2 as string(IB_MAX_LEN)
dim i,j,k as byte
if sourcestr_index > len(sourcestr) or sourcestr_index=0 then exit sub
if ib_insert_mode=YES then
if sourcestr_index=len(sourcestr) then exit sub
s1=left(sourcestr, sourcestr_index)
s2=right(sourcestr, len(sourcestr)-sourcestr_index-1)
else
if sourcestr_index > 0 then sourcestr_index=sourcestr_index - 1
s1=left(sourcestr, sourcestr_index-1)
s2=right(sourcestr, len(sourcestr)-sourcestr_index)
if len(s1)+len(s2)=0 then s2= chr(&h20)
end if
j=0
for i=1 to len(mask)
if mid(mask,i,1)=chr(&h20) then
j=j+1
else
k=i
end if
next i
sourcestr=s1+s2
if len(sourcestr) < j and len(mask) > k then
mask=left(mask, len(mask)-1)
end if
end sub
'--------------------------------------------------------------------------------
function remove_trailing_chr(s as string, c as string(1)) as string
while right(s,1)=c
s=left(s,len(s)-1)
wend
remove_trailing_chr=s
end function
'--------------------------------------------------------------------------------
sub ib_insert(s as string(1))
dim s2 as string(IB_MAX_LEN)
dim i,j as byte
j=0
for i=1 to len(mask)
if mid(mask,i,1)=chr(&h20) then
j=j+1
end if
next i
s2=right(sourcestr, len(sourcestr)-sourcestr_index)
if len(mask)<IB_MAX_LEN and len(sourcestr)<ib_input_length+1 then
sourcestr=left(sourcestr, sourcestr_index)+s+s2
if len(sourcestr)>j then mask=mask + chr(&h20)
ib_str_pos_increament(RESTART)
end if
end sub
'--------------------------------------------------------------------------------
sub ib_overwrite(s as string(1))
dim s2 as string(IB_MAX_LEN)
s2=right(sourcestr, len(sourcestr)-sourcestr_index)
sourcestr=left(sourcestr, sourcestr_index-1)+s+s2
end sub
'--------------------------------------------------------------------------------
sub ib_print()
dim i, b as byte
dim s1, s2 as string(IB_MAX_LEN)
if ib_secret_mode=YES then
for i=1 to len(sourcestr)
if mid(sourcestr,i,1)=chr(&h20) then
s2=s2+chr(&h20)
else
s2=s2+"*"
end if
next i
if chr_asc<>255 then
s2=left(s2,sourcestr_index-1)+mid(sourcestr,sourcestr_index,1)+right(s2,len(sourcestr)-sourcestr_index)
end if
if len(sourcestr)>ib_input_length then
s2=left(s2,ib_input_length)
sourcestr=left(sourcestr,ib_input_length)
ib_str_pos_decreament()
end if
s2=ib_insert_format(s2,mask)
else
if len(sourcestr)>ib_input_length then
sourcestr=left(sourcestr,ib_input_length)
ib_str_pos_decreament()
end if
s2=ib_insert_format(sourcestr,mask)
end if
if len(s2)>display_len then
if display_start_index > 0 then
if len(s2) - display_start_index <= display_len then
s1=mid(s2,display_start_index,display_len)
if ib_str <> "<" + s1 + "]" then
ib_str="<" + s1 + "]"
end if
else
if ib_str <> "<" + mid(s2,display_start_index,display_len)+ ">" then
ib_str="<" + mid(s2,display_start_index,display_len)+ ">"
else
goto print
end if
end if
else
ib_str="["+mid(s2,display_start_index,display_len)+ ">"
end if
else
b=display_len-len(s2)
for i=1 to b
s2=s2 + chr(&h20)
next i
ib_str="["+ s2 + "]"
display_start_index=0
if len(ib_str) < ib_len then
lcd_clear(INPUT_BOX_X,INPUT_BOX_Y,lcd.getprintwidth(ib_str+"]"),lcd.fontheight+2)
end if
ib_len=len(ib_str)
end if
print:
lcd.textalignment=PL_LCD_TEXT_ALIGNMENT_MIDDLE_LEFT
lcd.printaligned(ib_str, INPUT_BOX_X, INPUT_BOX_Y,INPUT_BOX_W,INPUT_BOX_H)
end sub
'--------------------------------------------------------------------------------
sub ib_str_pos_selector()
#if INPUT_BOX_CURSOR_STYLE > 0
dim pos as word
dim w as word
dim s1,s2 as string(IB_MAX_LEN)
pos=lcd_pos_index - display_start_index +1
if pos > display_len+1 then
exit sub
end if
s1=mid(ib_str,pos,1)
s2=left(ib_str,pos-1)
w=lcd.getprintwidth(s1)
cursor_x=lcd.getprintwidth(s2)
cursor_x=INPUT_BOX_X+cursor_x
if ib_insert_mode=YES then
lcd_clear(prev_x+w+2,INPUT_BOX_Y-1,1,lcd.fontheight+2)
lcd.fill(cursor_x+w+2,INPUT_BOX_Y-1,1,lcd.fontheight+2)
prev_x=cursor_x
else
'lcd_clear(INPUT_BOX_X,INPUT_BOX_Y+lcd.fontheight+INPUT_BOX_CURSOR_OFFSET-INPUT_BOX_CURSOR_WIDTH,lcd.getprintwidth(ib_str),INPUT_BOX_CURSOR_WIDTH)
lcd_clear(cursor_x+1,INPUT_BOX_Y+lcd.fontheight+INPUT_BOX_CURSOR_OFFSET-INPUT_BOX_CURSOR_WIDTH,w,INPUT_BOX_CURSOR_WIDTH)
lcd.fill(cursor_x+1,INPUT_BOX_Y+lcd.fontheight+INPUT_BOX_CURSOR_OFFSET-INPUT_BOX_CURSOR_WIDTH,w,INPUT_BOX_CURSOR_WIDTH)
end if
#else
dim s2 as string(IB_MAX_LEN)
dim pos as word
pos=lcd_pos_index - display_start_index +2
if pos > display_len+1 then
exit sub
end if
s2=left(ib_str,pos-1)
cursor_x=lcd.getprintwidth(s2)
cursor_x=INPUT_BOX_X+cursor_x
#endif
end sub
'--------------------------------------------------------------------------------
sub ib_chr_changing(dir as input_box_change_chr_dir)
dim s1, s2 as string(IB_MAX_LEN)
select case dir
case INPUT_BOX_CHANGE_CHR_BACKWARD:
select case chr_asc
case &h41:
if input_type=INPUT_BOX_CHAR_RANGE_AZ then chr_asc=&h7A 'A->z
if input_type=INPUT_BOX_CHAR_RANGE_09AZ then chr_asc=&h39 'A->9
case &h61:chr_asc=&h5A 'a->Z
case &h30:
if input_type=INPUT_BOX_CHAR_RANGE_09AZ then chr_asc=&h7A '0->z
if input_type=INPUT_BOX_CHAR_RANGE_09 then chr_asc=&h39 '0->9
case else
chr_asc=chr_asc-1
end select
case INPUT_BOX_CHANGE_CHR_FORWARD:
select case chr_asc
case &h20:
if input_type=INPUT_BOX_CHAR_RANGE_09 then chr_asc=&h30 'space->0
if input_type=INPUT_BOX_CHAR_RANGE_09AZ then chr_asc=&h41 'space->A
case &h39:chr_asc=&h20 '9->space
case &h5A:chr_asc=&h61 'Z->a
case &h7A:
if input_type=INPUT_BOX_CHAR_RANGE_AZ then chr_asc=&h20 'z->space
if input_type=INPUT_BOX_CHAR_RANGE_09AZ then chr_asc=&h30 'z->0
case else
chr_asc=chr_asc+1
end select
end select
verified:
s1=left(sourcestr,sourcestr_index-1)
s2=right(sourcestr,len(sourcestr)-sourcestr_index)
sourcestr=s1+chr(chr_asc)+s2
lcd.print(chr(chr_asc),cursor_x+2,INPUT_BOX_Y+3)
#if INPUT_BOX_CURSOR_STYLE > 0
ib_str_pos_selector
#endif
end sub
'--------------------------------------------------------------------------------
sub ib_delete_all()
sourcestr=""
sourcestr_index=0
lcd_pos_index=0
display_start_index=0
ib_print()
ib_str_pos_selector()
end sub
'--------------------------------------------------------------------------------
sub ib_type_in_style(s as string(1), insert_mode as no_yes)
chr_asc=asc(s)
if insert_mode=YES then
ib_insert(s)
else
ib_overwrite(s)
end if
ib_print()
ib_str_pos_selector()
end sub
'--------------------------------------------------------------------------------
public sub ui_input_box_key_proc(key_event as pl_kp_event_codes, key_code as byte)
dim key_action as input_box_key_actions
dim insert_mode as no_yes
ib_timeout_ctr=ib_timeout
key_action=INPUT_BOX_NONE
device_ib_key_proc(key_event,key_code,key_action,chr_asc,insert_mode)
ui_input_box_action(key_action,chr_asc,insert_mode)
end sub
'--------------------------------------------------------------------------------
sub ui_input_box_timer_proc()
'The timer process for ui_input_box module, beside counting down the input box timeout,
'this subroutin also calls device_ib_timer_event() for device specific timer behavior,
'such as moving the input box curosr forward after keypad is idle for a certain from
'scrolling through the characters.
dim key_action as input_box_key_actions
dim insert_mode as no_yes
key_action=INPUT_BOX_NONE
if ib_timeout_ctr>0 then
ib_timeout_ctr=ib_timeout_ctr-1
end if
'device specific timer behavior. for example, user repeatedly press a one key to scroll through characters, and stopped for 3 second,
'the input box cursor move to the next position.
device_ib_timer_event(key_action,chr_asc,insert_mode)
ui_input_box_action(key_action,chr_asc,insert_mode)
end sub
'--------------------------------------------------------------------------------
sub ui_input_box_action(byref key_action as input_box_key_actions,byref key_asc as byte, byref insert_mode as no_yes)
'the actual actions on input box, and they are independ from the operation of the keys.
select case key_action
case INPUT_BOX_INPUT: 'adding character to the input string
ib_type_in_style(chr(chr_asc),insert_mode)
case INPUT_BOX_CHAR_FORWARD: 'scrolling through characters forward (ex. A->B->C...)
ib_chr_changing(INPUT_BOX_CHANGE_CHR_FORWARD)
case INPUT_BOX_CHAR_BACKWARD: 'scrolling through characters backward (ex. C->B->A...)
ib_chr_changing(INPUT_BOX_CHANGE_CHR_BACKWARD)
case INPUT_BOX_POS_FORWARD:
ib_str_pos_increament(RESTART)
ib_print()
ib_str_pos_selector()
case INPUT_BOX_POS_BACKWARD:
ib_str_pos_decreament
ib_print()
ib_str_pos_selector()
case INPUT_BOX_BACKSPACE:
ib_backspace
ib_print()
ib_str_pos_selector()
case INPUT_BOX_DELETE:
ib_delete()
ib_print()
ib_str_pos_selector()
case INPUT_BOX_DELETE_ALL:
ib_delete_all()
case INPUT_BOX_CONFIRM:
sourcestr=ib_insert_format(sourcestr, mask)
sourcestr=remove_trailing_chr(sourcestr, chr(&h20))
input_box_result=INPUT_BOX_RESULT_OK
case INPUT_BOX_CANCEL:
input_box_result=INPUT_BOX_RESULT_CANCEL
case else
end select
end sub