-
Notifications
You must be signed in to change notification settings - Fork 3
/
vwatch.bas
7835 lines (7317 loc) · 426 KB
/
vwatch.bas
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
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
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
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
'vWATCH64 - A debug/variable watch system for QB64 programs
'Fellippe Heitor, 2015-2020 - [email protected] - @fellippeheitor
'
'Code repository: https://github.com/FellippeHeitor/vWATCH64
'
'Requirements: QB64 1.3.
'------------------------------------------------------------------------------
$VERSIONINFO:FILEVERSION#=1,2,0,0
$VERSIONINFO:PRODUCTVERSION#=1,2,0,0
$VERSIONINFO:CompanyName=Fellippe Heitor
$VERSIONINFO:FileDescription=vWATCH64 - A debug/variable watch system for QB64 programs
$VERSIONINFO:FileVersion=v1.2
$VERSIONINFO:InternalName=vwatch.bas
$VERSIONINFO:LegalCopyright=Open source
$VERSIONINFO:OriginalFilename=vwatch.exe
$VERSIONINFO:ProductName=vWATCH64
$VERSIONINFO:ProductVersion=v1.2
$VERSIONINFO:Comments=Requires the latest build of QB64
$VERSIONINFO:Web=www.qb64.org/vwatch
'------------------------------------------------------------------------------
$EXEICON:'./resources/wasp.ico'
_ICON
$RESIZE:ON
DEFLNG A-Z
$IF WIN THEN
DECLARE LIBRARY
FUNCTION PlaySound (pszSound AS STRING, BYVAL hmod AS INTEGER, BYVAL fdwSound AS INTEGER)
END DECLARE
DECLARE DYNAMIC LIBRARY "kernel32"
FUNCTION OpenProcess& (BYVAL dwDesiredAccess AS LONG, BYVAL bInheritHandle AS LONG, BYVAL dwProcessId AS LONG)
FUNCTION CloseHandle& (BYVAL hObject AS LONG)
FUNCTION GetExitCodeProcess& (BYVAL hProcess AS LONG, lpExitCode AS LONG)
END DECLARE
$ELSE
DECLARE LIBRARY
FUNCTION PROCESS_CLOSED& ALIAS kill (BYVAL pid AS INTEGER, BYVAL signal AS INTEGER)
END DECLARE
$END IF
DECLARE CUSTOMTYPE LIBRARY
SUB memcpy (BYVAL dest AS _OFFSET, BYVAL source AS _OFFSET, BYVAL bytes AS LONG)
END DECLARE
'Constants: -------------------------------------------------------------------
CONST ID = "vWATCH64"
CONST VERSION = "1.2.0"
CONST LF = 10
CONST TIMEOUTLIMIT = 10 'SECONDS
'Messagebox
CONST MB_CUSTOM = -1
CONST OK_ONLY = 0
CONST YN_QUESTION = 1
CONST MB_YES = 6
CONST MB_NO = 7
'OpenInclude return codes:
CONST MERGESUCCESSFUL = 0
CONST MISSINGFILE = -1
CONST NOINCLUDES = -2
'Breakpoint control:
CONST CONTINUE = 1
CONST NEXTSTEP = 2
CONST READY = 3
CONST SETVAR = 4
CONST SKIPSUB = 5
CONST SETNEXT = 7
'Filters:
CONST VARIABLENAMES = 1
CONST VALUES = 2
CONST SCOPE = 3
CONST DATATYPES = 4
CONST CODE = 5
CONST LINENUMBERS = 6
'CONST SETNEXT = 7
'Screen:
CONST DEFAULT_WIDTH = 1000
CONST DEFAULT_HEIGHT = 600
CONST SCREEN_TOPBAR = 50
'Custom data types: -----------------------------------------------------------
TYPE HEADERTYPE
CLIENT_ID AS STRING * 8
VERSION AS STRING * 5
CONNECTED AS _BYTE
RESPONSE AS _BYTE
PID AS LONG
END TYPE
TYPE CLIENTTYPE
NAME AS STRING * 256
CHECKSUM AS STRING * 8
TOTALSOURCELINES AS LONG
EXENAME AS STRING * 256
LINENUMBER AS LONG
TOTALVARIABLES AS LONG
PID AS LONG
END TYPE
TYPE BREAKPOINTTYPE
ACTION AS _BYTE
LINENUMBER AS LONG
END TYPE
TYPE VARIABLESTYPE
NAME AS STRING * 256
SCOPE AS STRING * 50
UDT AS STRING * 40
DATATYPE AS STRING * 20
END TYPE
TYPE VARIABLEVALUETYPE
VALUE AS STRING * 256
END TYPE
TYPE WATCHPOINTTYPE
EXPRESSION AS STRING * 256
END TYPE
TYPE UDTTYPE
UDT AS STRING * 40
ELEMENT AS STRING * 256
DATATYPE AS STRING * 20
END TYPE
TYPE SUBFUNC_TYPE
NAME AS STRING * 50
LINE AS LONG
ENDING AS LONG
EXTERNAL AS _BYTE
END TYPE
TYPE BUTTONSTYPE
ID AS LONG
CAPTION AS STRING * 120
X AS INTEGER
Y AS INTEGER
W AS INTEGER
END TYPE
'Shared variables: ------------------------------------------------------------
DIM SHARED BREAKPOINTLIST AS STRING
DIM SHARED CLIENT_CURRENTMODULE AS STRING * 50
DIM SHARED POSITION_IN_LINE AS LONG
DIM SHARED DEFAULTDATATYPE(65 TO 90) AS STRING * 20
DIM SHARED EXCHANGEDATASIZE$4
DIM SHARED EXCHANGEDATA AS STRING
DIM SHARED FILE AS INTEGER
DIM SHARED FILENAME$
DIM SHARED FILEERRORRAISED AS _BYTE
DIM SHARED FIRSTEXECUTION AS _BYTE
DIM SHARED CONVERSIONERRORRAISED AS _BYTE
DIM SHARED PAGE_HEIGHT AS LONG
DIM SHARED INTERNALKEYWORDS AS INTEGER
DIM SHARED GETELEMENT_LASTPOSITION AS LONG
DIM SHARED LIST_AREA AS INTEGER
DIM SHARED LINE_TRAIL AS INTEGER
DIM SHARED LONGESTLINE AS LONG
DIM SHARED LONGESTSCOPESPEC AS LONG
DIM SHARED LONGESTVARNAME AS LONG
DIM SHARED MAINSCREEN AS LONG
DIM SHARED MENU%
DIM SHARED MESSAGEBOX_RESULT AS INTEGER
DIM SHARED NEWFILENAME$
DIM SHARED RUNTOTHISLINE AS LONG
DIM SHARED SB_TRACK AS INTEGER
DIM SHARED SELECTED_VARIABLES AS STRING
DIM SHARED SCREEN_WIDTH AS INTEGER
DIM SHARED SCREEN_HEIGHT AS INTEGER
DIM SHARED SET_OPTIONBASE AS INTEGER
DIM SHARED SOURCEFILE AS STRING
DIM SHARED CHECKINGOFF_LINES AS STRING
DIM SHARED TITLESTRING AS STRING
DIM SHARED TOTALBREAKPOINTS AS LONG
DIM SHARED TOTALSKIPLINES AS LONG
DIM SHARED TOTALVARIABLES AS LONG
DIM SHARED TOTAL_SELECTEDVARIABLES AS LONG
DIM SHARED TOTALWATCHPOINTS AS LONG
DIM SHARED WATCHPOINTLIST AS STRING
DIM SHARED WATCHPOINTBREAK AS LONG
DIM SHARED PATHSEP$
'File structure:
DIM SHARED HEADERBLOCK AS LONG
DIM SHARED CLIENTBLOCK AS LONG
DIM SHARED BREAKPOINTBLOCK AS LONG
DIM SHARED BREAKPOINTLISTBLOCK AS LONG
DIM SHARED DATAINFOBLOCK AS LONG
DIM SHARED DATABLOCK AS LONG
DIM SHARED WATCHPOINTLISTBLOCK AS LONG
DIM SHARED WATCHPOINTEXPBLOCK AS LONG
DIM SHARED WATCHPOINTCOMMANDBLOCK AS LONG
DIM SHARED EXCHANGEBLOCK AS LONG
'Custom structures:
DIM SHARED BREAKPOINT AS BREAKPOINTTYPE
DIM SHARED WATCHPOINT_COMMAND AS BREAKPOINTTYPE
DIM SHARED CLIENT AS CLIENTTYPE
DIM SHARED HEADER AS HEADERTYPE
'Eye-candy control
DIM SHARED SetPause#, SetRun#, ShowPauseIcon, ShowRunIcon
DIM SHARED WASP AS LONG
'Switches:
DIM SHARED DONTCOMPILE AS _BYTE
DIM SHARED STEPMODE AS _BYTE
DIM SHARED SKIPARRAYS AS _BYTE
DIM SHARED USERQUIT AS _BYTE
DIM SHARED CLOSE_SESSION AS _BYTE
DIM SHARED DEBUGGEE_CLOSED AS _BYTE
DIM SHARED TRACE AS _BYTE
DIM SHARED VARIABLE_HIGHLIGHT AS _BYTE
'Dynamic arrays:
REDIM SHARED QB64KEYWORDS(0) AS STRING
REDIM SHARED SOURCECODE(0) AS STRING
REDIM SHARED SOURCECODE_COLORIZED(0) AS _BYTE
REDIM SHARED SUBFUNC(0) AS SUBFUNC_TYPE
REDIM SHARED VARIABLES(0) AS VARIABLESTYPE
REDIM SHARED VARIABLE_DATA(0) AS VARIABLEVALUETYPE
REDIM SHARED WATCHPOINT(0) AS WATCHPOINTTYPE
DIM i AS INTEGER
'Variables initialization: ----------------------------------------------------
SET_DEF "A-Z", "SINGLE"
SET_OPTIONBASE = 0
DONTCOMPILE = 0
SKIPARRAYS = 0
VARIABLE_HIGHLIGHT = -1
SCREEN_WIDTH = DEFAULT_WIDTH
SCREEN_HEIGHT = DEFAULT_HEIGHT
LIST_AREA = SCREEN_HEIGHT - SCREEN_TOPBAR
READ_KEYWORDS
'Screen setup: ----------------------------------------------------------------
WASP = WASP_IMAGE&
MAINSCREEN = _NEWIMAGE(SCREEN_WIDTH, SCREEN_HEIGHT, 32)
SCREEN MAINSCREEN
DO: _LIMIT 30: LOOP UNTIL _SCREENEXISTS
TITLESTRING = "vWATCH64 - v" + VERSION
_TITLE TITLESTRING
'QB64 version check: ----------------------------------------------------------
IF (INSTR(_OS$, "WIN") > 0 AND _FILEEXISTS("qb64.exe") = 0) OR (INSTR(_OS$, "WIN") = 0 AND _FILEEXISTS("qb64") = 0) THEN
MESSAGEBOX_RESULT = MESSAGEBOX(ID, "vWATCH64 must be in QB64's main folder.", MKI$(OK_ONLY), 1, 0)
SYSTEM
ELSE
IF _FILEEXISTS("source/qb64.bas") THEN
OPEN "source/qb64.bas" FOR BINARY AS #1
a$ = SPACE$(LOF(1))
GET #1, , a$
CLOSE #1
IF INSTR(a$, "IF FileDropEnabled = 0 THEN FileDropEnabled = -1: _ACCEPTFILEDROP") = 0 THEN 'Snippet added to QB64 v1.3
MESSAGEBOX_RESULT = MESSAGEBOX(ID, "vWATCH64 needs a newer version of QB64.", MKI$(OK_ONLY), 1, 0)
SYSTEM
END IF
a$ = ""
ELSE
MESSAGEBOX_RESULT = MESSAGEBOX(ID, "vWATCH64 needs a newer version of QB64.", MKI$(OK_ONLY), 1, 0)
SYSTEM
END IF
END IF
'Restore 'timers.h' -----------------------------------------------------------
RESTORE_LIBRARY
'Parse the command line: ------------------------------------------------------
'Did the user drag a .BAS file onto this program or enter parameters?
'Syntax: VWATCH64 [source filename.bas] [-options] [-target <newfilename>]
'If no parameters are passed, vWATCH64 starts in MONITOR MODE
IF LEN(COMMAND$) THEN
IF _COMMANDCOUNT > 1 THEN
'Set flags based on command line arguments:
FOR i = 1 TO _COMMANDCOUNT
SELECT CASE LCASE$(COMMAND$(i))
CASE "--dontcompile", "-d": DONTCOMPILE = -1
CASE "--noarrays", "-n": SKIPARRAYS = -1
CASE "--target", "-t": IF i < _COMMANDCOUNT THEN NEWFILENAME$ = COMMAND$(i + 1): i = i + 1
CASE ELSE
'Any other arguments are ignored.
END SELECT
NEXT i
END IF
END IF
$IF WIN THEN
PATHSEP$ = "\"
$ELSE
PATHSEP$ = "/"
$END IF
IF LEN(COMMAND$) THEN
IF _FILEEXISTS(COMMAND$(1)) THEN FILENAME$ = COMMAND$(1): PROCESSFILE ELSE MESSAGEBOX_RESULT = MESSAGEBOX(ID, "File not found.", MKI$(OK_ONLY), 1, 0)
NEWFILENAME$ = ""
END IF
GOTO MainLoop
OpenFileMenu:
IF SCREEN_WIDTH < DEFAULT_WIDTH OR SCREEN_HEIGHT < DEFAULT_HEIGHT THEN CHECK_RESIZE DEFAULT_WIDTH, DEFAULT_HEIGHT
_RESIZE OFF
PCOPY 0, 1
MESSAGEBOX_RESULT = INPUTBOX("Open and Process .BAS", "File to open:", "", FILENAME$, 0, 0)
_RESIZE ON
'Reset flags:
SET_DEF "A-Z", "SINGLE"
SET_OPTIONBASE = 0
DONTCOMPILE = 0
SKIPARRAYS = 0
tryOpen:
IF LEN(FILENAME$) THEN
IF _FILEEXISTS(FILENAME$) THEN
PROCESSFILE
ELSE
IF RIGHT$(LCASE$(FILENAME$), 4) <> ".bas" THEN FILENAME$ = FILENAME$ + ".bas": GOTO tryOpen
MESSAGEBOX_RESULT = MESSAGEBOX(ID, "File not found.", MKI$(OK_ONLY), 1, 0)
END IF
END IF
NEWFILENAME$ = ""
'------------------------------------------------------------------------------
MainLoop:
'------------------------------------------------------------------------------
DO
_RESIZE OFF
TITLESTRING = "vWATCH64 - v" + VERSION
_TITLE TITLESTRING
SETUP_CONNECTION
IF MENU% = 101 THEN GOTO OpenFileMenu
IF _TOTALDROPPEDFILES > 0 THEN FILENAME$ = _DROPPEDFILE$(1): _FINISHDROP: GOTO tryOpen
_RESIZE ON
SOURCE_VIEW
LOOP UNTIL USERQUIT
'------------------------------------------------------------------------------
SYSTEM
FileError:
FILEERRORRAISED = -1
RESUME NEXT
DataConversionERROR:
CONVERSIONERRORRAISED = -1
RESUME NEXT
DataTypeKeywordDATA:
DATA _BIT,_UNSIGNED _BIT,_BYTE,_UNSIGNED _BYTE,INTEGER
DATA _UNSIGNED INTEGER,LONG,_UNSIGNED LONG,_INTEGER64
DATA _UNSIGNED _INTEGER64,SINGLE,DOUBLE,_FLOAT,STRING
DATA **END**
QB64KeywordsDATA:
DATA $IF,$ELSE,$END
DATA _ALPHA,_ALPHA32,_AUTODISPLAY,_AXIS,_BACKGROUNDCOLOR,_BIT,
DATA _BLEND,_BLUE,_BLUE32,_BUTTON,_BUTTONCHANGE,_BYTE,$CHECKING
DATA _CLEARCOLOR,_CLIP,_CLIPBOARD$,_CONNECTED,_CONNECTIONADDRESS$
DATA $CONSOLE,_CONSOLE,_CONSOLETITLE,_CONTROLCHR,_COPYIMAGE,_COPYPALETTE
DATA _CV,_DEFAULTCOLOR,_DEFINE,_DELAY,_DEST,_DEST,_DEVICE$,_DEVICEINPUT
DATA _DEVICES,_DIREXISTS,_DISPLAY,_DISPLAY,_DONTBLEND,_DONTWAIT
DATA _ERRORLINE,_EXIT,_FILEEXISTS,_FLOAT,_FONT,_FONT,_FONTHEIGHT
DATA _FONTWIDTH,_FREEFONT,_FREEIMAGE,_FREETIMER,_FULLSCREEN,_FULLSCREEN
DATA _GREEN,_GREEN32,_HEIGHT,_HIDE,_ICON,_INTEGER64,_KEYHIT,_KEYDOWN
DATA _LASTAXIS,_LASTBUTTON,_LASTWHEEL,_LIMIT,_LOADFONT,_LOADIMAGE
DATA _MAPTRIANGLE,_MAPUNICODE,_MEM,_MEMCOPY,_MEMELEMENT,_MEMFILL
DATA _MEMFREE,_MEMGET,_MEMIMAGE,_MEMNEW,_MEMPUT,_MIDDLE,_MK$,_MOUSEBUTTON
DATA _MOUSEHIDE,_MOUSEINPUT,_MOUSEMOVE,_MOUSEMOVEMENTX,_MOUSEMOVEMENTY
DATA _MOUSESHOW,_MOUSEWHEEL,_MOUSEX,_MOUSEY,_NEWIMAGE,_NONE,_OFFSET
DATA _OPENCLIENT,_OPENCONNECTION,_OPENHOST,_OS$,_PALETTECOLOR,_PIXELSIZE
DATA _PRESERVE,_PRINTIMAGE,_PRINTMODE,_PRINTSTRING,_PRINTWIDTH,_PUTIMAGE
DATA _RED,_RED32,$RESIZE,_RESIZE,_RGB,_RGB32,_RGBA,_RGBA32
DATA _ROUND,_SCREENCLICK,$SCREENHIDE,_SCREENHIDE,_SCREENIMAGE,_SCREENMOVE
DATA _SCREENPRINT,$SCREENSHOW,_SCREENSHOW,_SCREENX,_SCREENY,_SETALPHA
DATA _SHELLHIDE,_SNDBAL,_SNDCLOSE,_SNDCOPY,_SNDGETPOS,_SNDLEN,_SNDLIMIT
DATA _SNDLOOP,_SNDOPEN,_SNDPAUSE,_SNDPAUSED,_SNDPLAY,_SNDPLAYCOPY
DATA _SNDPLAYFILE,_SNDPLAYING,_SNDRATE,_SNDRAW,_SNDRAWLEN,_SNDRAWDONE
DATA _SNDRAWOPEN,_SNDSETPOS,_SNDSTOP,_SNDVOL,_SOURCE,_TITLE,_UNSIGNED
DATA _WHEEL,_WIDTH,ABS,ABSOLUTE,ACCESS,ALIAS,AND,ANY,APPEND
DATA AS,ASC,ATN,BEEP,BINARY,BLOAD,BSAVE,BYVAL,CALL,CALLS
DATA CASE,CDBL,CDECL,CHAIN,CHDIR,CHR$,CINT,CIRCLE,CLEAR,CLNG
DATA CLOSE,CLS,COLOR,COMMAND$,COMMON,CONST,COS,CSNG,CSRLIN
DATA CVD,CVDMBF,CVI,CVL,CVS,CVSMBF,DATA,DATE$,DECLARE,DEF
DATA DEFDBL,DEFINT,DEFLNG,DEFSNG,DEFSTR,DIM,DO,DOUBLE,DRAW
DATA $DYNAMIC,ELSE,ELSEIF,END,ENVIRON,EOF,EQV,ERASE,ERDEV
DATA ERL,ERR,ERROR,EXIT,EXP,FIELD,FILEATTR,FILES,FIX,FOR
DATA FRE,FREE,FREEFILE,FUNCTION,GET,GOSUB,GOTO,HEX$,IF,IMP
DATA $INCLUDE,INKEY$,INP,INPUT,INSTR,INT,INTEGER,INTERRUPT
DATA INTERRUPTX,IOCTL,IOCTL$,IS,KEY,KILL,LBOUND,LCASE$,LEFT$,LEN
DATA LET,LINE,LIST,LOC,LOCATE,LOCK,LOF,LOG,LONG,LOOP,LPOS
DATA LPRINT,LSET,LTRIM$,MID,MID$,MKD$,MKDIR,MKDMBF$,MKI$,MKL$
DATA MKS$,MKSMBF$,MOD,NAME,NEXT,NOT,OCT$,OFF,ON,OPEN,OPTION
DATA OR,OUT,OUTPUT,PAINT,PALETTE,PCOPY,PEEK,PEN,PLAY,PMAP
DATA POINT,POKE,POS,PRESET,PRINT,PSET,PUT,RANDOM,RANDOMIZE
DATA READ,REDIM,REM,RESET,RESTORE,RESUME,RETURN,RIGHT$,RMDIR
DATA RND,RSET,RTRIM$,RUN,SADD,SCREEN,SEEK,SEG,SELECT,SETMEM,SGN
DATA SHARED,SHELL,SIGNAL,SIN,SINGLE,SLEEP,SOUND,SPACE$,SPC
DATA SQR,STATIC,$STATIC,STEP,STICK,STOP,STR$,STRIG,STRING
DATA STRING$,SUB,SWAP,SYSTEM,TAB,TAN,THEN,TIME$,TIMER,TO
DATA TROFF,TRON,TYPE,UBOUND,UCASE$,UEVENT,UNLOCK,UNTIL,VAL
DATA VARPTR,VARPTR$,VARSEG,VIEW,WAIT,WEND,WHILE,WIDTH,WINDOW
DATA WRITE,XOR,_CEIL,BASE,_EXPLICIT,_INCLERRORLINE,_DIR$
DATA _INCLERRORFILE$,$EXEICON,**END**
'------------------------------------------------------------------------------
'SUBs and FUNCTIONs: -
'------------------------------------------------------------------------------
SUB SOURCE_VIEW
'Allows setting breakpoints and stepping through code
DIM SB_Ratio AS SINGLE
DIM SourceLine AS STRING
DIM ListEnd_Label AS STRING
STATIC SearchIn
STATIC PrevSearchIn, PrevFilter$
STATIC TempQuickWatchVars AS LONG
TotalButtons = 7
DIM Buttons(1 TO TotalButtons) AS BUTTONSTYPE
TOTALSKIPLINES = 0
BREAKPOINT.ACTION = 0 'Start paused; execution starts with F5 or F8.
BREAKPOINT.LINENUMBER = 0
PUT #FILE, BREAKPOINTBLOCK, BREAKPOINT
COLOR _RGB32(0, 0, 0), _RGBA32(0, 0, 0, 0)
CLS , _RGB32(255, 255, 255)
Filter$ = ""
IF SearchIn = 0 THEN SearchIn = CODE
SB_ThumbY = 0
grabbedY = -1
SB_X = 1
ListEnd_Label = "(end of source file)"
ShowTempMessage = 0
STEPMODE = -1
TRACE = -1
_KEYCLEAR
CLOSE_SESSION = 0
DEBUGGEE_CLOSED = 0
FIRSTEXECUTION = -1
DO: _LIMIT 500
GOSUB ProcessInput
GET #FILE, CLIENTBLOCK, CLIENT
FIND_CURRENTMODULE
PUT #FILE, BREAKPOINTLISTBLOCK, BREAKPOINTLIST
PUT #FILE, WATCHPOINTLISTBLOCK, WATCHPOINTLIST
PUT #FILE, WATCHPOINTEXPBLOCK, WATCHPOINT()
GET #FILE, DATABLOCK, VARIABLE_DATA()
GET #FILE, WATCHPOINTCOMMANDBLOCK, WATCHPOINT_COMMAND
IF LEN(SOURCEFILE) > 0 THEN
FOR i = 1 TO CLIENT.TOTALVARIABLES
IF (TRIM$(UCASE$(VARIABLES(i).SCOPE)) <> UCASE$(GETELEMENT$(CLIENT_CURRENTMODULE, 1) + " " + GETELEMENT$(CLIENT_CURRENTMODULE, 2))) AND TRIM$(VARIABLES(i).SCOPE) <> "SHARED" THEN
VARIABLE_DATA(i).VALUE = "<out of scope>"
END IF
NEXT i
END IF
IF CLIENT.LINENUMBER <> prevLineNumber THEN
prevLineNumber = CLIENT.LINENUMBER
IF ASC(BREAKPOINTLIST, CLIENT.LINENUMBER) = 1 THEN
STEPMODE = -1
SetPause# = TIMER
ShowPauseIcon = -1
ShowRunIcon = 0
IF CLIENT.LINENUMBER = RUNTOTHISLINE THEN
ASC(BREAKPOINTLIST, CLIENT.LINENUMBER) = 0
RUNTOTHISLINE = 0
FOR MultiLineToggle = CLIENT.LINENUMBER + 1 TO CLIENT.TOTALSOURCELINES
IF RIGHT$(TRIM$(GETLINE$(MultiLineToggle - 1)), 1) = "_" THEN
ASC(BREAKPOINTLIST, MultiLineToggle) = ASC(BREAKPOINTLIST, CLIENT.LINENUMBER)
ELSE
EXIT FOR
END IF
NEXT MultiLineToggle
END IF
END IF
IF WATCHPOINT_COMMAND.ACTION = NEXTSTEP THEN
WATCHPOINTBREAK = WATCHPOINT_COMMAND.LINENUMBER
STEPMODE = -1
SetPause# = TIMER
ShowPauseIcon = -1
ShowRunIcon = 0
WATCHPOINT_COMMAND.ACTION = READY
WATCHPOINT_COMMAND.LINENUMBER = 0
PUT #FILE, WATCHPOINTCOMMANDBLOCK, WATCHPOINT_COMMAND
GOSUB ClearTempQuickWatchVars
VARIABLE_VIEW
GOSUB AddTempQuickWatchVar
END IF
'Dynamically add QUICK WATCH variables based on the current line of code
GOSUB AddTempQuickWatchVar
END IF
GOSUB UpdateList
IF _EXIT THEN USERQUIT = -1
SEND_PING
LOOP UNTIL HEADER.CONNECTED = 0 OR USERQUIT OR CLOSE_SESSION OR DEBUGGEE_CLOSED
EndMessage:
IF CLOSE_SESSION OR USERQUIT THEN
HEADER.CONNECTED = 0
PUT #FILE, HEADERBLOCK, HEADER
CLOSE #FILE
ON ERROR GOTO FileError
DO WHILE _FILEEXISTS(_CWD$ + PATHSEP$ + "vwatch64.dat")
_LIMIT 10
KILL _CWD$ + PATHSEP$ + "vwatch64.dat"
LOOP
ON ERROR GOTO 0
EXIT SUB
END IF
IF USERQUIT THEN EXIT SUB
IF HEADER.CONNECTED = 0 OR DEBUGGEE_CLOSED THEN
EndMessage$ = "Connection closed by client."
END IF
IF HEADER.CONNECTED = 0 OR DEBUGGEE_CLOSED THEN
MESSAGEBOX_RESULT = MESSAGEBOX(ID, EndMessage$, MKI$(OK_ONLY), 1, -1)
END IF
EXIT SUB
ProcessInput:
k = _KEYHIT: modKey = k
IF modKey = 100303 OR modKey = 100304 THEN shiftDown = -1
IF modKey = -100303 OR modKey = -100304 THEN shiftDown = 0
IF modKey = 100305 OR modKey = 100306 THEN ctrlDown = -1
IF modKey = -100305 OR modKey = -100306 THEN ctrlDown = 0
DO
prevy = y
y = y + (_MOUSEWHEEL * ((_HEIGHT - 50) / 5))
IF y <> prevy THEN TRACE = 0
mx = _MOUSEX
my = _MOUSEY
mb = _MOUSEBUTTON(1)
mb2 = _MOUSEBUTTON(2)
LOOP WHILE _MOUSEINPUT
SELECT EVERYCASE k
CASE 32 TO 126 'Printable ASCII characters
SELECT CASE SearchIn
CASE CODE
Filter$ = Filter$ + CHR$(k)
CASE LINENUMBERS
IF (k >= 48 AND k <= 57) OR (k = 45) OR (k = 44) THEN
Filter$ = Filter$ + CHR$(k)
ELSE
Filter$ = Filter$ + CHR$(k)
SearchIn = CODE
END IF
CASE SETNEXT
IF (k >= 48 AND k <= 57) THEN Filter$ = Filter$ + CHR$(k)
END SELECT
CASE 8 'Backspace
IF LEN(Filter$) THEN Filter$ = LEFT$(Filter$, LEN(Filter$) - 1)
CASE 9 'TAB
IF SearchIn = SETNEXT THEN
SearchIn = CODE
Filter$ = ""
ELSEIF SearchIn = CODE THEN
SearchIn = LINENUMBERS
ELSE
SearchIn = CODE
END IF
IF LEN(Filter$) > 0 AND VAL(Filter$) = 0 AND SearchIn = LINENUMBERS THEN Filter$ = ""
CASE 13 'ENTER confirms SET NEXT LINE, after proper evaluation of Filter$
IF SearchIn = SETNEXT THEN
IF LEN(Filter$) = 0 THEN
SearchIn = PrevSearchIn
Filter$ = PrevFilter$
ELSEIF LEN(Filter$) > 0 AND VAL(Filter$) > 0 THEN
DesiredLine = VAL(Filter$)
SetNext_Click:
IF DesiredLine <= CLIENT.TOTALSOURCELINES THEN
DesiredSourceLine$ = TRIM$(STRIPCOMMENTS$(GETLINE$(DesiredLine)))
IF LEN(DesiredSourceLine$) > 0 THEN
IF ASC(DesiredSourceLine$, 1) = 1 OR ASC(DesiredSourceLine$, 1) = 3 THEN DesiredSourceLine$ = MID$(DesiredSourceLine$, 2)
END IF
PrevDesiredSourceLine$ = " "
IF DesiredLine > 1 THEN PrevDesiredSourceLine$ = TRIM$(STRIPCOMMENTS$(GETLINE$(DesiredLine - 1)))
CanGo = -1
IF LEN(DesiredSourceLine$) = 0 THEN CanGo = 3
IF RIGHT$(PrevDesiredSourceLine$, 1) = "_" THEN CanGo = 3
IF LEFT$(DesiredSourceLine$, 1) = "$" THEN CanGo = 3
IF LEFT$(DesiredSourceLine$, 4) = "DIM " THEN CanGo = 3
IF LEFT$(DesiredSourceLine$, 5) = "DATA " THEN CanGo = 3
IF LEFT$(DesiredSourceLine$, 5) = "CASE " THEN CanGo = 3
IF LEFT$(DesiredSourceLine$, 5) = "TYPE " THEN CanGo = 3
IF LEFT$(DesiredSourceLine$, 6) = "REDIM " THEN CanGo = 3
IF LEFT$(DesiredSourceLine$, 6) = "CONST " THEN CanGo = 3
IF LEFT$(DesiredSourceLine$, 7) = "STATIC " THEN CanGo = 3
IF LEFT$(DesiredSourceLine$, 7) = "DEFINT " THEN CanGo = 3
IF LEFT$(DesiredSourceLine$, 7) = "DEFLNG " THEN CanGo = 3
IF LEFT$(DesiredSourceLine$, 7) = "DEFSTR " THEN CanGo = 3
IF LEFT$(DesiredSourceLine$, 7) = "DEFSNG " THEN CanGo = 3
IF LEFT$(DesiredSourceLine$, 7) = "DEFDBL " THEN CanGo = 3
IF LEFT$(DesiredSourceLine$, 8) = "DECLARE " THEN CanGo = 3
IF LEFT$(DesiredSourceLine$, 8) = "_DEFINE " THEN CanGo = 3
IF LEFT$(DesiredSourceLine$, 11) = "END DECLARE" THEN CanGo = 3
IF LEFT$(DesiredSourceLine$, 16) = "OPTION _EXPLICIT" THEN CanGo = 3
IF CanGo = -1 THEN
IF TRIM$(CLIENT_CURRENTMODULE) = "MAIN MODULE" THEN
CanGo = -1
DeclaringLibrary = 0
FOR dl.Check = DesiredLine TO 1 STEP -1
SearchedLine$ = TRIM$(STRIPCOMMENTS$(GETLINE$(dl.Check)))
IF LEN(SearchedLine$) > 0 THEN
IF ASC(SearchedLine$, 1) = 1 OR ASC(SearchedLine$, 1) = 3 THEN SearchedLine$ = MID$(SearchedLine$, 2)
END IF
IF GETELEMENT$(SearchedLine$, 1) = "DECLARE" AND FIND_SYMBOL(1, SearchedLine$, "LIBRARY") THEN
DeclaringLibrary = 0
ELSEIF GETELEMENT$(SearchedLine$, 1) = "END" AND GETELEMENT$(SearchedLine$, 2) = "DECLARE" THEN
DeclaringLibrary = -1
END IF
IF (GETELEMENT$(SearchedLine$, 1) = "SUB" OR GETELEMENT$(SearchedLine$, 1) = "FUNCTION") AND DeclaringLibrary = 0 THEN
CanGo = 1
EXIT FOR
END IF
NEXT dl.Check
ELSE
CanGo = 2
FOR dl.Check = DesiredLine TO 1 STEP -1
SearchedLine$ = TRIM$(GETLINE$(dl.Check))
IF LEN(SearchedLine$) > 0 THEN
IF ASC(SearchedLine$, 1) = 1 OR ASC(SearchedLine$, 1) = 3 THEN SearchedLine$ = MID$(SearchedLine$, 2)
END IF
cm$ = CLIENT_CURRENTMODULE
IF (GETELEMENT$(SearchedLine$, 1) = "SUB" OR GETELEMENT$(SearchedLine$, 1) = "FUNCTION") THEN
IF GETELEMENT$(SearchedLine$, 2) = GETELEMENT$(cm$, 2) THEN
'We're in the same module as the desired line
CanGo = -1
EXIT FOR
ELSE
EXIT FOR
END IF
END IF
NEXT dl.Check
END IF
END IF
IF CanGo = -1 THEN
BREAKPOINT.ACTION = SETNEXT
BREAKPOINT.LINENUMBER = DesiredLine
PUT #FILE, BREAKPOINTBLOCK, BREAKPOINT
BREAKPOINT.ACTION = 0
BREAKPOINT.LINENUMBER = 0
IF NOT Clicked THEN
SearchIn = PrevSearchIn
Filter$ = PrevFilter$
END IF
ELSEIF CanGo = 1 OR CanGo = 2 THEN
Message$ = ""
Message$ = Message$ + "Next line must be " + IIFSTR$(CanGo = 1, "in the main module", "inside " + GETELEMENT$(cm$, 1) + " " + GETELEMENT$(cm$, 2)) + CHR$(LF)
MESSAGEBOX_RESULT = MESSAGEBOX("Outside boundaries", Message$, MKI$(OK_ONLY), 1, -1)
ELSE
Message$ = ""
Message$ = Message$ + "The specified source line can't be set as the next statement" + CHR$(LF)
MESSAGEBOX_RESULT = MESSAGEBOX("Nonexecutable statement", Message$, MKI$(OK_ONLY), 1, -1)
END IF
ELSE
Message$ = "Invalid line number."
MESSAGEBOX_RESULT = MESSAGEBOX(ID, Message$, MKI$(OK_ONLY), 1, -1)
END IF
IF Clicked THEN Clicked = 0: RETURN
END IF
END IF
CASE 27 'ESC clears the current search filter or exits interactive mode
ExitButton_Click:
IF (SearchIn = CODE OR SearchIn = LINENUMBERS) AND LEN(Filter$) > 0 THEN
Filter$ = ""
ELSEIF SearchIn = SETNEXT THEN
SearchIn = PrevSearchIn
Filter$ = PrevFilter$
ELSE
CLOSE_SESSION = -1
END IF
IF Clicked THEN Clicked = 0: RETURN
CASE 18432 'Up
ArrowStep! = ((_HEIGHT - 50) * SB_Ratio)
IF ArrowStep! < _FONTHEIGHT THEN ArrowStep! = _FONTHEIGHT
IF ctrlDown = -1 THEN y = y - _FONTHEIGHT ELSE y = y - ArrowStep!
TRACE = 0
CASE 20480 'Down
ArrowStep! = ((_HEIGHT - 50) * SB_Ratio)
IF ArrowStep! < _FONTHEIGHT THEN ArrowStep! = _FONTHEIGHT
IF ctrlDown = -1 THEN y = y + _FONTHEIGHT ELSE y = y + ArrowStep!
TRACE = 0
CASE 19200 'Left
IF SB_X > 1 THEN SB_X = SB_X - 1
CASE 19712 'Right
IF SB_X < LONGESTLINE THEN SB_X = SB_X + 1
CASE 16128 'F5
RunButton_Click:
FIRSTEXECUTION = 0
IF WATCHPOINTBREAK > 0 THEN
IF ASC(WATCHPOINTLIST, WATCHPOINTBREAK) = 1 THEN
Message$ = "Execution was halted on a watchpoint (" + TRIM$(VARIABLES(WATCHPOINTBREAK).NAME) + TRIM$(WATCHPOINT(WATCHPOINTBREAK).EXPRESSION) + ")" + CHR$(LF)
Message$ = Message$ + "Clear it before resuming?"
MESSAGEBOX_RESULT = MESSAGEBOX("Run/Resume", Message$, MKI$(YN_QUESTION), 1, -1)
IF MESSAGEBOX_RESULT = MB_YES THEN
ASC(WATCHPOINTLIST, WATCHPOINTBREAK) = 0
TOTALWATCHPOINTS = TOTALWATCHPOINTS - 1
WATCHPOINT(WATCHPOINTBREAK).EXPRESSION = ""
END IF
END IF
END IF
IF STEPMODE = -1 THEN SetRun# = TIMER: ShowRunIcon = -1: ShowPauseIcon = 0
STEPMODE = 0
WATCHPOINTBREAK = 0
BREAKPOINT.ACTION = CONTINUE
PUT #FILE, BREAKPOINTBLOCK, BREAKPOINT
IF Clicked THEN Clicked = 0: RETURN
CASE 16384 'F6
WindowButton_Click:
IF CLIENT.TOTALVARIABLES > 0 THEN
_KEYCLEAR
GOSUB ClearTempQuickWatchVars
VARIABLE_VIEW
GOSUB AddTempQuickWatchVar
ELSE
Message$ = "There are no variables in your watch list."
MESSAGEBOX_RESULT = MESSAGEBOX("No variables", Message$, MKI$(OK_ONLY), 1, -1)
END IF
IF Clicked THEN Clicked = 0: RETURN
CASE 16896 'F8
StepButton_Click:
FIRSTEXECUTION = 0
IF shiftDown THEN
IF SOURCECODE_COLORIZED(CLIENT.LINENUMBER) = 0 THEN ADDCOLORCODE CLIENT.LINENUMBER
IF INSTR(SOURCECODE(CLIENT.LINENUMBER), CHR$(5)) > 0 THEN
StepOverMenu_Click:
IF STEPMODE = 0 THEN SetPause# = TIMER: ShowPauseIcon = -1: ShowRunIcon = 0
STEPMODE = -1
TRACE = -1
BREAKPOINT.ACTION = SKIPSUB
PUT #FILE, BREAKPOINTBLOCK, BREAKPOINT
IF Clicked THEN Clicked = 0: RETURN
ELSE
GOTO NormalF8
END IF
ELSE
NormalF8:
IF STEPMODE = 0 THEN SetPause# = TIMER: ShowPauseIcon = -1: ShowRunIcon = 0
STEPMODE = -1
TRACE = -1
BREAKPOINT.ACTION = NEXTSTEP
PUT #FILE, BREAKPOINTBLOCK, BREAKPOINT
END IF
IF Clicked THEN Clicked = 0: RETURN
CASE 17152 'F9
ToggleButton_Click:
IF LEN(FilteredList$) = 0 THEN
IF ASC(BREAKPOINTLIST, CLIENT.LINENUMBER) = 1 AND GETELEMENT$(GETLINE$(CLIENT.LINENUMBER), 1) <> "STOP" THEN
ASC(BREAKPOINTLIST, CLIENT.LINENUMBER) = 0
TOTALBREAKPOINTS = TOTALBREAKPOINTS - 1
ELSEIF ASC(BREAKPOINTLIST, CLIENT.LINENUMBER) = 1 AND GETELEMENT$(GETLINE$(CLIENT.LINENUMBER), 1) = "STOP" THEN
Message$ = ""
Message$ = Message$ + "The STOP statement creates a permanent breakpoint." + CHR$(LF)
Message$ = Message$ + "Would you like to skip this line instead?"
IF MESSAGEBOX("Permanent breakpoint", Message$, MKI$(YN_QUESTION), 1, -1) = MB_YES THEN
TOTALBREAKPOINTS = TOTALBREAKPOINTS - 1
TOTALSKIPLINES = TOTALSKIPLINES + 1
ASC(BREAKPOINTLIST, CLIENT.LINENUMBER) = 2
END IF
ELSE
IF ASC(BREAKPOINTLIST, CLIENT.LINENUMBER) = 2 THEN TOTALSKIPLINES = TOTALSKIPLINES - 1
ASC(BREAKPOINTLIST, CLIENT.LINENUMBER) = 1
TOTALBREAKPOINTS = TOTALBREAKPOINTS + 1
END IF
FOR MultiLineToggle = CLIENT.LINENUMBER + 1 TO CLIENT.TOTALSOURCELINES
IF RIGHT$(TRIM$(GETLINE$(MultiLineToggle - 1)), 1) = "_" THEN
ASC(BREAKPOINTLIST, MultiLineToggle) = ASC(BREAKPOINTLIST, CLIENT.LINENUMBER)
ELSE
EXIT FOR
END IF
NEXT MultiLineToggle
ELSE
FOR setAll = 1 TO LEN(FilteredList$) / 4
which_Line = CVL(MID$(FilteredList$, setAll * 4 - 3, 4))
IF ASC(BREAKPOINTLIST, which_Line) = 0 AND LEN(STRIPCOMMENTS$(GETLINE$(which_Line))) THEN
IF ASC(BREAKPOINTLIST, which_Line) = 2 THEN TOTALSKIPLINES = TOTALSKIPLINES - 1
ASC(BREAKPOINTLIST, which_Line) = 1
TOTALBREAKPOINTS = TOTALBREAKPOINTS + 1
FOR MultiLineToggle = which_Line + 1 TO CLIENT.TOTALSOURCELINES
IF RIGHT$(TRIM$(GETLINE$(MultiLineToggle - 1)), 1) = "_" THEN
ASC(BREAKPOINTLIST, MultiLineToggle) = ASC(BREAKPOINTLIST, which_Line)
ELSE
EXIT FOR
END IF
NEXT MultiLineToggle
END IF
NEXT setAll
END IF
IF Clicked THEN Clicked = 0: RETURN
CASE 17408 'F10
ClearButton_Click:
IF LEN(FilteredList$) = 0 THEN
FOR clear.BP = 1 TO CLIENT.TOTALSOURCELINES
IF ASC(BREAKPOINTLIST, clear.BP) = 1 AND GETELEMENT$(GETLINE$(clear.BP), 1) <> "STOP" THEN ASC(BREAKPOINTLIST, clear.BP) = 0: TOTALBREAKPOINTS = TOTALBREAKPOINTS - 1
NEXT clear.BP
ELSE
FOR setAll = 1 TO LEN(FilteredList$) / 4
which_Line = CVL(MID$(FilteredList$, setAll * 4 - 3, 4))
IF ASC(BREAKPOINTLIST, which_Line) = 1 AND GETELEMENT$(GETLINE$(which_Line), 1) <> "STOP" THEN
ASC(BREAKPOINTLIST, which_Line) = 0
TOTALBREAKPOINTS = TOTALBREAKPOINTS - 1
FOR MultiLineToggle = which_Line + 1 TO CLIENT.TOTALSOURCELINES
IF RIGHT$(TRIM$(GETLINE$(MultiLineToggle - 1)), 1) = "_" THEN
ASC(BREAKPOINTLIST, MultiLineToggle) = ASC(BREAKPOINTLIST, which_Line)
ELSE
EXIT FOR
END IF
NEXT MultiLineToggle
END IF
NEXT setAll
END IF
IF Clicked THEN Clicked = 0: RETURN
END SELECT
'Scrollbar check:
IF PAGE_HEIGHT > LIST_AREA THEN
IF mb THEN
IF mx > _WIDTH(MAINSCREEN) - 30 AND mx < _WIDTH(MAINSCREEN) THEN
TRACE = 0
'Clicked inside the scroll bar. Check if click was on the thumb:
IF my > SCREEN_TOPBAR + SB_ThumbY + 24 AND my < SCREEN_TOPBAR + SB_ThumbY + 24 + SB_ThumbH THEN
'Clicked on the thumb:
grabbedY = my: starty = y
DISPLAYSCROLLBAR y, grabbedY, SB_ThumbY, SB_ThumbH, SB_Ratio, mx, my
DO WHILE _MOUSEBUTTON(1): _LIMIT 500
WHILE _MOUSEINPUT: WEND
my = _MOUSEY
y = starty + ((my - grabbedY) / SB_Ratio)
CHECK_SCREEN_LIMITS y
IF prevy <> y THEN
DISPLAYSCROLLBAR y, grabbedY, SB_ThumbY, SB_ThumbH, SB_Ratio, mx, my: prevy = y
GOSUB UpdateList
END IF
SEND_PING
_DISPLAY
LOOP
grabbedY = -1
ELSEIF my > SCREEN_TOPBAR AND my <= SCREEN_TOPBAR + 20 THEN
'Up arrow
IF ctrlDown = -1 THEN y = y - _FONTHEIGHT ELSE y = y - (LIST_AREA / 10)
_DELAY .1
ELSEIF my > SCREEN_HEIGHT - 21 THEN
'Down arrow
IF ctrlDown = -1 THEN y = y + _FONTHEIGHT ELSE y = y + (LIST_AREA / 10)
_DELAY .1
ELSE
'Clicked above or below the thumb:
IF my < SCREEN_TOPBAR + 25 + SB_ThumbY AND my > SCREEN_TOPBAR + 21 THEN
y = y - ((LIST_AREA / 6) / SB_Ratio)
_DELAY .1
ELSEIF my > SCREEN_TOPBAR + 25 + SB_ThumbY + SB_ThumbH AND my < SCREEN_HEIGHT - 21 THEN
y = y + ((LIST_AREA / 6) / SB_Ratio)
_DELAY .1
END IF
END IF
END IF
END IF
END IF
RETURN
UpdateList:
CHECK_RESIZE 0, 0
LIST_AREA = SCREEN_HEIGHT - SCREEN_TOPBAR - ((TOTAL_SELECTEDVARIABLES + 1) * _FONTHEIGHT)
CLS , _RGB32(255, 255, 255)
cursorBlink% = cursorBlink% + 1
IF cursorBlink% > 50 THEN cursorBlink% = 0
IF LEN(SOURCEFILE) > 0 THEN
'Build a filtered list, if a filter is active:
i = 0: FilteredList$ = ""
PAGE_HEIGHT = _FONTHEIGHT * (CLIENT.TOTALSOURCELINES + 3)
IF LEN(Filter$) > 0 AND SearchIn <> SETNEXT THEN
DO
i = i + 1
IF i > CLIENT.TOTALSOURCELINES THEN EXIT DO
Found = 0
IF SearchIn = CODE THEN Found = MULTI_SEARCH(UCASE$(GETLINE$(i)), UCASE$(Filter$))
IF SearchIn = LINENUMBERS THEN Found = INTERVAL_SEARCH(Filter$, i)
IF Found THEN
FilteredList$ = FilteredList$ + MKL$(i)
END IF
LOOP
IF LEN(FilteredList$) > 0 THEN PAGE_HEIGHT = _FONTHEIGHT * ((LEN(FilteredList$) / 4) + 3)
END IF
'Scroll to the next line of code that will be run
IF TRACE AND LEN(FilteredList$) = 0 THEN
CurrentLineY = (CLIENT.LINENUMBER - 1) * _FONTHEIGHT
IF CurrentLineY > y + LIST_AREA - _FONTHEIGHT THEN
y = (CurrentLineY - LIST_AREA) + SCREEN_TOPBAR
ELSEIF CurrentLineY < y THEN
y = CurrentLineY - SCREEN_TOPBAR + (_FONTHEIGHT * 3)
END IF
END IF
CHECK_SCREEN_LIMITS y
CLS , _RGB32(255, 255, 255)
'Print list items to the screen:
IF LEN(FilteredList$) > 0 THEN
ListStart = ((y \ _FONTHEIGHT) + 1)
ListEnd = LEN(FilteredList$) / 4
FOR ii = ListStart TO ListEnd
i = CVL(MID$(FilteredList$, ii * 4 - 3, 4))
SourceLine = GETLINE$(i)
printY = (SCREEN_TOPBAR + 3 + ((ii - 1) * _FONTHEIGHT)) - y
IF printY > SCREEN_HEIGHT THEN EXIT FOR
IF (printY >= (SCREEN_TOPBAR - _FONTHEIGHT)) AND printY < SCREEN_HEIGHT THEN
'Print only inside the program area
GOSUB ColorizeList
IF (my > SCREEN_TOPBAR + 1) AND (my >= printY) AND (my <= (printY + _FONTHEIGHT - 1)) AND (mx < (_WIDTH - 30)) THEN GOSUB DetectClick
IF MenuWasInvoked THEN MenuWasInvoked = 0: RETURN
IF SOURCECODE_COLORIZED(i) = 0 THEN ADDCOLORCODE i
v$ = "[" + IIFSTR$(ASC(BREAKPOINTLIST, i) = 1, CHR$(7), IIFSTR$(ASC(BREAKPOINTLIST, i) = 2, CHR$(9), " ")) + "]" + IIFSTR$(i = CLIENT.LINENUMBER, CHR$(16) + " ", " ") + SPACE$(LEN(TRIM$(STR$(CLIENT.TOTALSOURCELINES))) - LEN(TRIM$(STR$(i)))) + TRIM$(STR$(i)) + " " + SourceLine
PRINT_COLORIZED 5 - ((SB_X - 1) * _FONTWIDTH), printY, v$, i
COLOR _RGB32(0, 0, 0)
END IF
NEXT ii
ELSEIF LEN(Filter$) = 0 OR SearchIn = SETNEXT THEN
ListStart = ((y \ _FONTHEIGHT) + 1)
ListEnd = CLIENT.TOTALSOURCELINES
FOR i = ListStart TO ListEnd
SourceLine = GETLINE$(i)
printY = (SCREEN_TOPBAR + 3 + ((i - 1) * _FONTHEIGHT)) - y
IF printY > SCREEN_HEIGHT THEN EXIT FOR
'Print only inside the program area
GOSUB ColorizeList
IF (my > SCREEN_TOPBAR + 1) AND (my >= printY) AND (my <= (printY + _FONTHEIGHT - 1)) AND (mx < (_WIDTH - 30)) THEN GOSUB DetectClick
IF MenuWasInvoked THEN MenuWasInvoked = 0: RETURN
IF SOURCECODE_COLORIZED(i) = 0 THEN ADDCOLORCODE i
v$ = "[" + IIFSTR$(ASC(BREAKPOINTLIST, i) = 1, CHR$(7), IIFSTR$(ASC(BREAKPOINTLIST, i) = 2, CHR$(9), " ")) + "]" + IIFSTR$(i = CLIENT.LINENUMBER, CHR$(16) + " ", " ") + SPACE$(LEN(TRIM$(STR$(CLIENT.TOTALSOURCELINES))) - LEN(TRIM$(STR$(i)))) + TRIM$(STR$(i)) + " " + SourceLine
PRINT_COLORIZED 5 - ((SB_X - 1) * _FONTWIDTH), printY, v$, i
COLOR _RGB32(0, 0, 0)
NEXT i
END IF
IF LEN(Filter$) AND LEN(FilteredList$) = 0 AND SearchIn <> SETNEXT THEN 'A filter is on, but nothing was found
_PRINTSTRING (5, 4 * _FONTHEIGHT), "Search terms not found."
_PRINTSTRING (5, 4 * _FONTHEIGHT + _FONTHEIGHT), "(ESC to reset filter)"
END IF
IF PAGE_HEIGHT > LIST_AREA THEN
IF LEN(FilteredList$) > 0 THEN
_PRINTSTRING (5, ((5 + (LEN(FilteredList$) / 4)) * _FONTHEIGHT) - y), ListEnd_Label + "(filtered)"
ELSE
_PRINTSTRING (5, ((5 + CLIENT.TOTALSOURCELINES) * _FONTHEIGHT) - y), ListEnd_Label
END IF
DISPLAYSCROLLBAR y, grabbedY, SB_ThumbY, SB_ThumbH, SB_Ratio, mx, my
ELSE
'End of list message:
IF LEN(FilteredList$) > 0 THEN
_PRINTSTRING (5, ((5 + (LEN(FilteredList$) / 4)) * _FONTHEIGHT) - y), ListEnd_Label + "(filtered)"
ELSE
_PRINTSTRING (5, PAGE_HEIGHT + (_FONTHEIGHT * 2) - y), ListEnd_Label
END IF
END IF
ELSE
LINE (0, SCREEN_TOPBAR)-STEP(_WIDTH, _HEIGHT - SCREEN_TOPBAR), _RGB32(200, 200, 200), BF
Message$ = "<Source file(s) changed/not found>"
COLOR _RGB32(255, 0, 0)
_PRINTSTRING (_WIDTH / 2 - _PRINTWIDTH(Message$) / 2, SCREEN_TOPBAR + (_HEIGHT - SCREEN_TOPBAR) / 2 - _FONTHEIGHT / 2), Message$
END IF
'Top bar:
' SOURCE VIEW: <F5 = Run> <Trace ???> <F6 = View Variables> <F8 = Step> <F9 = Toggle Breakpoint> <ESC = Exit>
' Breakpoints 0 * Next line: ####
' Filter (code):
LINE (0, 0)-STEP(_WIDTH(MAINSCREEN), SCREEN_TOPBAR), _RGB32(179, 255, 255), BF
LINE (0, 0)-STEP(_WIDTH(MAINSCREEN), _FONTHEIGHT + 1), _RGB32(0, 178, 179), BF
ModeTitle$ = "SOURCE VIEW: "
_PRINTSTRING (5, 3), ModeTitle$
COLOR _RGB32(255, 255, 255)
_PRINTSTRING (4, 2), ModeTitle$
COLOR _RGB32(0, 0, 0)
TopLine$ = "Breakpoints: " + SPACE$(LEN(TRIM$(STR$(CLIENT.TOTALSOURCELINES))) - LEN(TRIM$(STR$(TOTALBREAKPOINTS)))) + TRIM$(STR$(TOTALBREAKPOINTS)) + TAB(5) + "Next line: " + SPACE$(LEN(TRIM$(STR$(CLIENT.TOTALSOURCELINES))) - LEN(TRIM$(STR$(CLIENT.LINENUMBER)))) + TRIM$(STR$(CLIENT.LINENUMBER)) + " (in " + GETELEMENT$(CLIENT_CURRENTMODULE, 1) + " " + GETELEMENT$(CLIENT_CURRENTMODULE, 2) + ")"