Author Topic: Syntax Highlighting (This gonna be hard! :P)  (Read 3518 times)

0 Members and 1 Guest are viewing this topic.

Offline Prithak

  • Newbie
  • Posts: 56
  • Life itself is a Programming Language!
    • View Profile
    • My Programming Language
Syntax Highlighting (This gonna be hard! :P)
« on: March 12, 2019, 12:30:07 pm »
Ok, So I've made a really simple Text Editor here. The code:
Code: QB64: [Select]
  1. SCREEN _NEWIMAGE(800, 600, 32)
  2. DIM y(100000000) AS INTEGER
  3. DIM text(100000000) AS STRING
  4. leng = 1
  5.     FOR i = 1 TO leng
  6.         _PRINTSTRING (0, y(i)), text(i)
  7.         k$ = INKEY$
  8.         IF k$ = CHR$(13) THEN
  9.             leng = leng + 1
  10.             y(leng) = y(leng - 1) + 15
  11.         ELSEIF k$ = CHR$(8) THEN
  12.             text(leng) = LEFT$(text(leng), LEN(text(leng)) - 1)
  13.         ELSE
  14.             text(leng) = text(leng) + k$
  15.         END IF
  16.     NEXT i
  17.  
  18.     _DISPLAY
  19.     CLS
  20.  

Now, can I get a concept as to how the hell can I highlight the syntax here? Thank you in advance!

~Prithak
CLS
IF computer$ = "ON" THEN
me$ = "Happy!"
ELSE
me$ = "Time To Draw!"
END IF
END

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Syntax Highlighting (This gonna be hard! :P)
« Reply #1 on: March 12, 2019, 12:44:23 pm »
Ok, So I've made a really simple Text Editor here. The code:
Code: QB64: [Select]
  1. SCREEN _NEWIMAGE(800, 600, 32)
  2. DIM y(100000000) AS INTEGER
  3. DIM text(100000000) AS STRING
  4. leng = 1
  5.     FOR i = 1 TO leng
  6.         _PRINTSTRING (0, y(i)), text(i)
  7.         k$ = INKEY$
  8.         IF k$ = CHR$(13) THEN
  9.             leng = leng + 1
  10.             y(leng) = y(leng - 1) + 15
  11.         ELSEIF k$ = CHR$(8) THEN
  12.             text(leng) = LEFT$(text(leng), LEN(text(leng)) - 1)
  13.         ELSE
  14.             text(leng) = text(leng) + k$
  15.         END IF
  16.     NEXT i
  17.  
  18.     _DISPLAY
  19.     CLS
  20.  

Now, can I get a concept as to how the hell can I highlight the syntax here? Thank you in advance!

~Prithak

Dang! How do you escape that contraption?

Are you sure you want to highlight syntax and not just text? And shouldn't you get the editor part further along before highlighting either syntax or text?

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Syntax Highlighting (This gonna be hard! :P)
« Reply #2 on: March 12, 2019, 01:23:36 pm »
Here is a simple Screen Editor I posted at [abandoned, outdated and now likely malicious qb64 dot net website - don’t go there] sometime ago.

Code: QB64: [Select]
  1. _TITLE "Screen Editor by bplus, Ctrl + F1 for Help "
  2. 'started 2017-10-04
  3. '2017-10-05 post as work in progress for comments
  4.  
  5.  
  6. CONST xmax = 800 '100 chars wide
  7. CONST ymax = 600 ' 30 chars high (480) + 120 pixels
  8.  
  9. COMMON SHARED vS$(), FW, FH, maxCol, maxRow, cc, cr, fSaved, cyn&, ylw&, fn$
  10. SCREEN _NEWIMAGE(xmax, ymax, 32)
  11.  
  12. maxCol = xmax \ FW ' minCol = 1 for locate
  13. maxRow = 480 \ FH '  minRow = 1 for locate
  14. DIM vS$(1 TO maxCol, 1 TO maxRow) 'Ha! MarkSkit's charArray$() only  2D !!!
  15. cyn& = _RGB(0, 205, 205)
  16. ylw& = _RGB(255, 255, 0)
  17.  
  18. cScrn 'this loads vS$ with spaces and sets cc, cr the current row and current column
  19. fSaved = -1
  20. DO 'main interface loop
  21.     CLS
  22.         IF _MOUSEBUTTON(1) THEN 'mouse click in edit area?
  23.             tx = _MOUSEX \ FW + 1
  24.             ty = _MOUSEY \ FH + 1
  25.             IF ty <= maxRow THEN cc = tx: cr = ty
  26.         END IF
  27.     LOOP
  28.  
  29.  
  30.     k$ = INKEY$
  31.     IF LEN(k$) THEN 'handle 1 and 2 char key presses, maybe replace with _keyhit later
  32.  
  33.         'this code at least as helpful as wiki
  34.         'WHILE 1   'find code for keypress
  35.         '    k$ = INKEY$
  36.         '    IF LEN(k$) THEN
  37.         '        SELECT CASE LEN(k$)
  38.         '            CASE 1: PRINT "1 char keypress = "; ASC(k$)
  39.         '                IF ASC(k$) = 27 THEN EXIT WHILE
  40.         '            CASE 2: PRINT "2 char keypress = "; ASC(RIGHT$(k$, 1))
  41.         '        END SELECT
  42.         '    END IF
  43.         '    _DISPLAY
  44.         '    _LIMIT 60
  45.         'WEND
  46.         'SLEEP
  47.         '
  48.         ' HA! Ctrl + M = <enter>
  49.  
  50.         SELECT CASE LEN(k$)
  51.  
  52.             CASE 1
  53.                 '                                ASCII Keyboard Codes
  54.                 '
  55.                 ' Esc  F1  F2  F3  F4  F5  F6  F7  F8  F9  F10  F11  F12  Sys ScL Pause
  56.                 '  27 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68  +133 +134   -   -    -
  57.                 ' `~  1!  2@  3#  4$  5%  6^  7&  8*  9(  0) -_ =+ BkSp   Ins Hme PUp   NumL  /   *    -
  58.                 ' 126 33  64  35  36  37  94  38  42  40  41 95 43   8    +82 +71 +73    -    47  42   45
  59.                 '  96 49  50  51  52  53  54  55  56  57  48 45 61
  60.                 ' Tab Q   W   E   R   T   Y   U   I   O   P  [{  ]}  \|   Del End PDn   7Hme 8/?  9PU  +
  61.                 '  9  81  87  69  82  84  89  85  73  79  80 123 125 124  +83 +79 +81   +71  +72  +73  43
  62.                 '    113 119 101 114 116 121 117 105 111 112  91  93  92                 55   56   57
  63.                 ' CapL  A   S   D   F   G   H   J   K   L   ;:  '" Enter                4/?-  5   6/-?
  64.                 '   -   65  83  68  70  71  72  74  75  76  58  34  13                  +75  +76  +77  E
  65.                 '       97 115 100 102 103 104 106 107 108  59  39                       52   53   54  n
  66.                 ' Shift  Z   X   C   V   B   N   M   ,<  .>  /?    Shift       ?        1End 2/?  3PD  t
  67.                 '   *    90  88  67  86  66  78  77  60  62  63      *        +72       +79  +80  +81  e
  68.                 '       122 120  99 118  98 110 109  44  46  47                          49   50   51  r
  69.                 ' Ctrl Win Alt       Spacebar          Alt Win Menu Ctrl   ?-  ?   -?   0Ins     .Del
  70.                 '  *    -   *           32              *   -   -    *    +75 +80 +77   +82       +83  13
  71.                 '                                                                        48        46
  72.                 '
  73.                 '     Italics = LCase/NumLock On  * = 2 byte combo only,  + = 2 Byte: CHR$(0) + CHR$(code)
  74.                 'PRINT "1 "; k$
  75.                 'INPUT "OK "; t$
  76.                 SELECT CASE ASC(k$)
  77.                     CASE 1 'Ctrl + A
  78.                         saveA
  79.                     CASE 3 'Ctrl + C
  80.                         cScrn
  81.                     CASE 8 ' backspace          more to do
  82.                         IF cc > 1 THEN
  83.                             s$ = ""
  84.                             FOR i = cc TO maxCol - 1
  85.                                 vS$(i - 1, cr) = vS$(i, cr)
  86.                             NEXT
  87.                             vS$(maxCol, cr) = " "
  88.                             cc = cc - 1
  89.                             fSaved = 0
  90.                         END IF
  91.  
  92.                     CASE 12 'Ctrl + L
  93.                         fLoad
  94.                     CASE 13 '                          more too
  95.                         IF cr < maxRow THEN cr = cr + 1: cc = 1
  96.  
  97.                     CASE 19 'Ctrl + S
  98.                         Save
  99.                     CASE 27 'esc
  100.                         checkSave
  101.                         END
  102.                     CASE ELSE
  103.                         IF 31 < ASC(k$) AND ASC(k$) < 127 THEN 'normal print chars
  104.                             vS$(cc, cr) = k$
  105.                             fSaved = 0
  106.                             IF cc < maxCol THEN
  107.                                 cc = cc + 1
  108.                             ELSE
  109.                                 IF cr < maxRow THEN cr = cr + 1: cc = 1
  110.                             END IF
  111.                         END IF
  112.                 END SELECT
  113.  
  114.             CASE 2
  115.                 'CLS: PRINT "2 "; ASC(RIGHT$(k$, 1))
  116.                 'INPUT "OK ", t$
  117.                 SELECT CASE ASC(RIGHT$(k$, 1))
  118.                     'from wiki help,
  119.                     'Two Byte Characters        Key                 CHR$(0) + "?"
  120.                     'CHR$(0) + CHR$(16-50)      [Alt] + letter
  121.                     'CHR$(0) + CHR$(59)         [F1]                 ";"
  122.                     'CHR$(0) + CHR$(60)         [F2]                 "<"
  123.                     'CHR$(0) + CHR$(61)         [F3]                 "="
  124.                     'CHR$(0) + CHR$(62)         [F4]                 ">"
  125.                     'CHR$(0) + CHR$(63)         [F5]                 "?"
  126.                     'CHR$(0) + CHR$(64)         [F6]                 "@"
  127.                     'CHR$(0) + CHR$(65)         [F7]                 "A"
  128.                     'CHR$(0) + CHR$(66)         [F8]                 "B"
  129.                     'CHR$(0) + CHR$(67)         [F9]                 "C"
  130.                     'CHR$(0) + CHR$(68)         [F10]                "D"
  131.                     'CHR$(0) + CHR$(71)         [Home]               "G"
  132.                     'CHR$(0) + CHR$(72)         [?] Arrow            "H"
  133.                     'CHR$(0) + CHR$(73)         [Page Up]            "I"
  134.                     'CHR$(0) + CHR$(75)         [?] Arrow            "K"
  135.                     'CHR$(0) + CHR$(76)         [5 NumberPad]        "L" (NumLock off in QB64)
  136.                     'CHR$(0) + CHR$(77)         [?] Arrow            "M"
  137.                     'CHR$(0) + CHR$(79)         [End]                "O"
  138.                     'CHR$(0) + CHR$(80)         [?] Arrow            "P"
  139.                     'CHR$(0) + CHR$(81)         [Page Down]          "Q"
  140.                     'CHR$(0) + CHR$(82)         [Insert]             "R"
  141.                     'CHR$(0) + CHR$(83)         [Delete]             "S"
  142.                     'CHR$(0) + CHR$(84-93)      [Shift] + F1-10
  143.                     'CHR$(0) + CHR$(94-103)     [Ctrl] + F1-10
  144.                     'CHR$(0) + CHR$(104-113)    [Alt] + F1-10
  145.                     'CHR$(0) + CHR$(114-119)    [Ctrl] + keypad
  146.                     'CHR$(0) + CHR$(120-129)    [Alt] + number
  147.                     'CHR$(0) + CHR$(130 or 131) [Alt] + _/- or +/=   "Ă©" or "â"
  148.                     'CHR$(0) + CHR$(133)        [F11]                "Ă "
  149.                     'CHR$(0) + CHR$(134)        [F12]                "ĂĄ"
  150.                     'CHR$(0) + CHR$(135)        [Shift] + [F11]      "ç"
  151.                     'CHR$(0) + CHR$(136)        [Shift] + [F12]      "ĂŞ"
  152.                     'CHR$(0) + CHR$(137)        [Ctrl] + [F11]       "Ă«"
  153.                     'CHR$(0) + CHR$(138)        [Ctrl] + [F12]       "è"
  154.                     'CHR$(0) + CHR$(139)        [Alt] + [F11]        "ĂŻ"
  155.                     'CHR$(0) + CHR$(140)        [Alt] + [F12]        "Ă®"
  156.  
  157.  
  158.                     CASE 72 ' up
  159.                         IF cr > 1 THEN cr = cr - 1
  160.                     CASE 80 'down
  161.                         IF cr < maxRow THEN cr = cr + 1
  162.                     CASE 75 'left
  163.                         IF cc > 1 THEN cc = cc - 1
  164.                     CASE 77 'right
  165.                         IF cc < maxCol THEN cc = cc + 1
  166.                     CASE 94 'Ctrl + F1
  167.                         menu
  168.  
  169.                 END SELECT
  170.         END SELECT
  171.     END IF
  172.  
  173.     pScrn 'shows exactly what is in vS$() that gets saved to file or loaded from file
  174.     drwCrs 'updates file, save status, current position of "cursor"
  175.     _DISPLAY 'flicker free
  176.     _LIMIT 60 'easy on the cpu?
  177.  
  178. SUB menu
  179.     CLS
  180.     cP 2, "Edit Menu press:"
  181.     lp 10, 4, "1 to clear screen or while editing             Ctrl + C"
  182.     lp 10, 5, "2 prompts for file name to open and Load text, Ctrl + L"
  183.     lp 10, 6, "3 Save text to last file name loaded,          Ctrl + S"
  184.     lp 10, 7, "4 Save text to Another file name (save As),    Ctrl + A"
  185.     lp 10, 8, "0 Exit Menu"
  186.     LOCATE 10, 10: INPUT "Enter your choice ", choice
  187.     SELECT CASE choice
  188.         CASE 0: EXIT SUB
  189.         CASE 1: cScrn
  190.         CASE 2: fLoad
  191.         CASE 3: Save
  192.         CASE 4: saveA
  193.     END SELECT
  194.  
  195.  
  196. SUB saveA
  197.     CLS
  198.     cP 2, "(" + fn$ + ") Save As File:"
  199.     LOCATE 5, 3: INPUT "Enter file name for Save or nothing ", test$
  200.     IF fn$ <> "" THEN
  201.         IF _FILEEXISTS(test$) THEN
  202.             cP 7, "Warning: " + test$ + " already exists."
  203.             LOCATE 9, 15: INPUT "Do you wish to overwite that file? use y for yes ", yes$
  204.             IF UCASE$(yes$) = "Y" THEN fn$ = test$: Save
  205.         ELSE
  206.             fn$ = test$: Save
  207.         END IF
  208.     END IF
  209.  
  210. SUB Save
  211.     IF fn$ <> "" THEN
  212.         OPEN fn$ FOR OUTPUT AS #1
  213.         FOR y = 1 TO maxRow
  214.             s$ = ""
  215.             FOR x = 1 TO maxCol
  216.                 s$ = s$ + vS$(x, y)
  217.             NEXT
  218.             PRINT #1, s$
  219.         NEXT
  220.         CLOSE #1
  221.         fSaved = -1
  222.     END IF
  223.  
  224. SUB fLoad () 'to do a .txt file getter plug-in here
  225.     checkSave
  226.     CLS
  227.     cP 2, "Load File:"
  228.     LOCATE 5, 3: INPUT "Enter filename for Load or nothing ", fn$
  229.     IF fn$ <> "" THEN
  230.         IF _FILEEXISTS(fn$) THEN
  231.             OPEN fn$ FOR INPUT AS #1
  232.             WHILE NOT EOF(1) AND lc < maxRow
  233.                 LINE INPUT #1, fline$
  234.                 lc = lc + 1
  235.                 IF LEN(fline$) > maxCol THEN stopit = maxCol ELSE stopit = LEN(fline$)
  236.                 FOR i = 1 TO stopit
  237.                     vS$(i, lc) = MID$(fline$, i, 1)
  238.                 NEXT
  239.             WEND
  240.             CLOSE #1
  241.         END IF
  242.     END IF
  243.  
  244. SUB cP (row, txt$) 'on row center Print txt$
  245.     col = (maxCol - LEN(txt$)) \ 2
  246.     LOCATE row, col: PRINT txt$
  247.  
  248. SUB drwCrs
  249.     COLOR ylw&
  250.     LINE ((cc - 1) * FW, (cr - 1) * FH)-(cc * FW, cr * FH), , B
  251.     IF fSaved THEN s$ = " Saved  " ELSE s$ = " Unsaved  "
  252.     LOCATE 33, 70: PRINT fn$; s$; cc; " : "; cr;
  253.     LOCATE cr, cc
  254.  
  255. SUB cScrn
  256.     FOR y = 1 TO maxRow
  257.         FOR x = 1 TO maxCol
  258.             vS$(x, y) = " "
  259.         NEXT
  260.     NEXT
  261.     cc = 1: cr = 1: fn$ = "untitled.txt"
  262.  
  263. SUB pScrn
  264.     COLOR cyn&
  265.     FOR y = 1 TO maxRow
  266.         FOR x = 1 TO maxCol
  267.             LOCATE y, x: PRINT vS$(x, y);
  268.         NEXT
  269.     NEXT
  270.     LINE (0, 485)-(xmax, 485), ylw&
  271.  
  272. SUB checkSave
  273.     IF fSaved = 0 THEN
  274.         CLS
  275.         COLOR ylw&
  276.         cP 10, fn$ + " changes have not been saved."
  277.         cP 15, "Do you wish to Save them to same file?"
  278.         LOCATE 20, 1: INPUT " Enter y for yes ", yes$
  279.         IF UCASE$(yes$) = "Y" THEN Save
  280.     END IF
  281.  
  282. SUB lp (col, row, txt$) 'just to save some typing
  283.     LOCATE row, col: PRINT txt$
  284.  

  [ You are not allowed to view this attachment ]  

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Re: Syntax Highlighting (This gonna be hard! :P)
« Reply #3 on: March 12, 2019, 01:28:00 pm »
Mark is right. First,  you've allocated way too much memory for arrays. It appears you are just getting familiar with keyboard input porgrams, so start small. Next, learn more about INKEY$. The way you have is not useful. You should at least make an IF LEN(k$) THEN, so blank INKEY$ readings are not feed to the variables. BTW, real WP projects are freakin' huge. 1000s of line of code. What you created, so far, will not work and will crash some systems. What I posted below is part of what you will need to get started. It at least shows how to position everything, and has a key method for displaying the input correctly to the screen. Highlighting would be just making a key toggle for highlighting characters when they are typed, and toggling it off when you're done. There are more advanced mouse methods, too. Anyway, have a look, ask questions if you have any, but see if any of this helps you gain a little more perspective. Sorry, I don't have any tutorials to share, and to be frank, I think what I'm posting may be ahead of where you are, which might make you feel like I'm expecting you to understand all this code. I don't, so don't worry about asking questions.

Code: QB64: [Select]
  1. numofspaces% = 40
  2. LOCATE 10, 29
  3. COLOR 8, 7: PRINT "|";
  4. COLOR 0, 7: PRINT SPACE$(numofspaces%);
  5. COLOR 8, 7: PRINT "|";
  6. COLOR 0, 7
  7. LOCATE 10, 30, 1, 7, 7
  8. startpos% = POS(1)
  9. endpos% = startpos% + numofspaces%
  10. b$ = INKEY$
  11. IF b$ <> "" THEN EXIT DO
  12. xx% = CSRLIN: yy% = POS(1)
  13.  
  14. CASE CHR$(0) + "K"
  15. mov% = -1: GOSUB action
  16. CASE CHR$(0) + "M"
  17. mov% = 1: GOSUB action
  18. CASE CHR$(0) + "S"
  19. GOSUB wash: GOSUB delete
  20. CASE CHR$(0) + "R"
  21. IF ins% = 0 THEN ins% = -1 ELSE ins% = 0
  22. IF ins% = 0 THEN LOCATE , , 1, 7, 7 ELSE LOCATE , , 1, 7, 30
  23. CASE CHR$(0) + "O"
  24. IF word$ <> "" THEN LOCATE xx%, startpos% + LEN(word$)
  25. CASE CHR$(0) + "G"
  26. LOCATE xx%, startpos%
  27. IF yy% > startpos% THEN
  28. LOCATE , POS(1) - 1
  29. yy% = POS(1)
  30. GOSUB wash: GOSUB delete
  31. REM Enter your routine here.
  32. CASE CHR$(32) TO CHR$(126)
  33. key$ = b$: GOSUB action
  34. mov% = 0: key$ = ""
  35.  
  36. action:
  37. IF POS(1) + mov% >= startpos% AND POS(1) + mov% < endpos% THEN
  38. IF key$ <> "" THEN
  39. IF LEN(word$) + LEN(key$) > endpos% - startpos% THEN EXIT DO
  40. word$ = MID$(word$, 1, POS(1) - startpos%) + key$ + MID$(word$, POS(1) - startpos% + 1)
  41. CASE -1
  42. word$ = MID$(word$, 1, POS(1) - startpos%) + key$ + MID$(word$, POS(1) - startpos% + 2)
  43. IF POS(1) - startpos% >= LEN(word$) - LEN(key$) AND key$ <> "" OR key$ = "" OR ins% = -1 THEN
  44. IF key$ = "" AND mov% = 1 THEN IF POS(1) - startpos% = LEN(word$) THEN EXIT DO
  45. LOCATE , POS(1) + mov%: PRINT key$;
  46. LOCATE xx%, startpos%: PRINT MID$(word$, 1, yy% - startpos%); key$; : yy2% = POS(1): PRINT MID$(word$, yy% - startpos% + 2); : LOCATE xx%, yy2%
  47.  
  48. wash:
  49. IF POS(1) >= startpos% AND word$ <> "" AND POS(1) - startpos% < LEN(word$) THEN
  50. LOCATE xx%, startpos% + LEN(word$) - 1
  51. PRINT " ";
  52. LOCATE xx%, yy%
  53.  
  54. delete:
  55. IF POS(1) - startpos% = 0 THEN
  56. word$ = MID$(word$, 2)
  57. word$ = MID$(word$, 1, POS(1) - startpos%) + MID$(word$, POS(1) - startpos% + 2)
  58. PRINT MID$(word$, yy% - startpos% + 1); : LOCATE xx%, yy%
  59.  

Pete
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Syntax Highlighting (This gonna be hard! :P)
« Reply #4 on: March 12, 2019, 02:42:37 pm »
Yes a line editor is a good way to get your feet wet.

This is probably best taught as a building process, certainly with more comments.

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Re: Syntax Highlighting (This gonna be hard! :P)
« Reply #5 on: March 12, 2019, 09:38:41 pm »
Arrays are going to end up biting you. Go with a linked list:

Code: QB64: [Select]
  1. '$EXEICON:'qXedlogo.ico'
  2. '$RESIZE:ON
  3.  
  4. 'REM $Include: 'sxmath.bi'
  5. 'REM $Include: 'sxript.bi'
  6.  
  7. scrHand& = _NEWIMAGE(90, 30, 0)
  8. SCREEN scrHand&
  9. '_FREEIMAGE scrHand&
  10.  
  11. ' Define fundamental structures.
  12. TYPE Vector
  13.     X AS INTEGER
  14.     Y AS INTEGER
  15.  
  16. TYPE Cell
  17.     Identity AS LONG
  18.     Pointer AS LONG
  19.     Lagger AS LONG
  20.     Content AS STRING * 1
  21.  
  22. DIM SHARED ChainLimit AS LONG
  23. DIM SHARED BOC AS LONG ' Beginning of chain.
  24. DIM SHARED EOC AS LONG ' End of chain.
  25. ChainLimit = 128000
  26. BOC = -1
  27. EOC = ChainLimit
  28.  
  29. ' Define text window properties.
  30. DIM SHARED WindowHeight
  31. DIM SHARED WindowWidth
  32. DIM SHARED VisibleLines
  33. DIM SHARED TopIndent
  34. DIM SHARED LeftIndent
  35. DIM SHARED TextHeight
  36. DIM SHARED TextWidth
  37. DIM SHARED HScroll
  38. DIM SHARED TextWrapping
  39. DIM SHARED TextFormatting
  40. DIM SHARED InsertKey
  41. TopIndent = 1
  42. LeftIndent = 1
  43. WindowWidth = _WIDTH '
  44. WindowHeight = _HEIGHT '- 2
  45. TextHeight = WindowHeight - 2 * TopIndent
  46. TextWidth = WindowWidth - 2 * LeftIndent
  47. HScroll = 1
  48. TextWrapping = 0
  49. TextFormatting = -1
  50. InsertKey = -1
  51.  
  52. ' Initiate text inside window.
  53. DIM SHARED StartIndex
  54. DIM SHARED LineAsMapped(TextHeight) AS STRING
  55. DIM SHARED Cursor1 AS Vector
  56. DIM SHARED Cursor2 AS Vector
  57.  
  58. ' Auxiliary 2D text grid.
  59. DIM SHARED GOLSwitch
  60. DIM SHARED AuxGrid(TextWidth, TextHeight, 2) AS STRING
  61. GOLSwitch = -1
  62.  
  63. ' Load text file into memory if applicable, use example string if not.
  64. DIM SHARED FileName$
  65. IF (c$ <> "") THEN
  66.     q$ = ""
  67.     OPEN c$ FOR INPUT AS #1
  68.     DO WHILE NOT EOF(1)
  69.         LINE INPUT #1, r$
  70.         q$ = q$ + r$ + CHR$(13)
  71.     LOOP
  72.     CLOSE #1
  73.     i = INSTR(c$, ".")
  74.     IF (i <> 0) THEN j = i - 1 ELSE j = LEN(c$)
  75.     FileName$ = LEFT$(c$, j) + "-" + LTRIM$(RTRIM$(STR$(INT(TIMER)))) + ".txt"
  76.     _TITLE FileName$
  77.     FileName$ = "Newfile" + "-" + DATE$ + "-" + LTRIM$(RTRIM$(STR$(INT(TIMER)))) + ".txt"
  78.     q$ = "I sank to the floor. I [experienced] this hallucination of tumbling forward into these fractal geometric spaces made of light and then I found myself in the equivalent of the Pope's private chapel and there were insect elf machines proffering strange little tablets with strange writing on them, and I was aghast, completely appalled, because [in] a matter of seconds . . . my entire expectation of the nature of the world was just being shredded in front of me. I've never actually gotten over it. These self-transforming machine elf creatures were speaking in a colored language which condensed into rotating machines that were like Faberge eggs but crafted out of luminescent superconducting ceramics and liquid crystal gels. All this stuff was just so weird and so alien and so un-English-able that it was a complete shock - I mean, the literal turning inside out of [my] intellectual universe!" + CHR$(13) + CHR$(13) + "This went on for two or three minutes, this situation of [discontinuous] orthogonal dimensions to reality just engulfing me. As I came out of it and the room reassembled itself, I said, " + CHR$(34) + "I can't believe it, it's impossible." + CHR$(34) + " To call that a drug is ridiculous; that just means that you just don't have a word for it and so you putter around and you come upon this sloppy concept [that] something goes into your body and there's a change. It's not like that; it's like being struck by noetic lightning. [Note: " + CHR$(34) + "Noetic" + CHR$(34) + " derives from the theologian Pierre Teilhard de Chardin's " + CHR$(34) + "noosphere" + CHR$(34) + " - the collective consciousness of humankind conceived of as a sort of philosophical virtuality.]" + CHR$(13) + CHR$(13) + "[What] astonished me was [that] . . . in the carpets of Central Asia, in the myths of the Maya, in the visions of an Arcimboldi or a Fra Angelico or a Bosch, there is not a hint, not a clue, not an atom of the presence of this thing, This was more [multiplex] than the universe that we share with each other. It was the victory of Neo-Platonic metaphysics; everything [was] made out of a fourth-dimensional mosaic of energy. I was knocked off my feet, and set myself the goal of understanding this. There was really no choice, you see."
  79.     'q$ = " "
  80.  
  81. _TITLE "qXed"
  82.  
  83. ' Create memory space for string.
  84. DIM SHARED TheChain(ChainLimit) AS Cell
  85.  
  86. ' Create character list.
  87. CALL Assimilate(q$)
  88.  
  89. ' Prime main loop.
  90. CALL MapText
  91. CALL CalibrateCursor(ID1)
  92. CALL CalibrateCursor(ID2)
  93. CALL PrintEverything
  94.  
  95. DIM SHARED DEBUG$
  96.  
  97. ' Main loop.
  98.     IF (StateChange = 1) THEN
  99.         CALL PrintEverything
  100.     END IF
  101.  
  102.     IF (GOLSwitch = 1) THEN
  103.         CALL ConvertToGrid
  104.         CALL GOL
  105.         CALL ConvertFromGrid
  106.         CALL MapText
  107.         CALL PrintEverything
  108.     END IF
  109.  
  110.     'IF _RESIZE = -1 THEN
  111.     '    _DELAY .1
  112.     '    oldimage& = scrHand&
  113.     '    scrHand& = _NEWIMAGE(_RESIZEWIDTH / 8, _RESIZEHEIGHT / 16, 0)
  114.     '    SCREEN scrHand&
  115.     '    _FREEIMAGE oldimage&
  116.     '    WindowWidth = INT(_RESIZEWIDTH / 8)
  117.     '    WindowHeight = INT(_RESIZEHEIGHT / 16)
  118.     '    TextHeight = WindowHeight - 2 * TopIndent
  119.     '    TextWidth = WindowWidth - 2 * LeftIndent
  120.     '    REDIM LineAsMapped(TextHeight)
  121.     '    REDIM AuxGrid(TextWidth, TextHeight, 2)
  122.     '    CALL MapText
  123.     '    CALL CalibrateCursor(ID1)
  124.     '    CALL CalibrateCursor(ID2)
  125.     '    CALL PrintEverything
  126.     'END IF
  127.  
  128.     _DISPLAY
  129.     _LIMIT 120
  130.  
  131. SUB PrintEverything
  132.     CLS
  133.  
  134.     c$ = "qXed" + " " + DEBUG$
  135.     CALL DisplayText(1, 1, 11, 0, c$)
  136.  
  137.     ' Main text
  138.     FOR i = 1 TO VisibleLines
  139.         c$ = LineAsMapped(i)
  140.         IF ((TextFormatting = 1) AND (TextWrapping <> 2)) THEN
  141.             FOR j = 1 TO TextWidth - LEN(c$)
  142.                 c$ = c$ + "_"
  143.             NEXT
  144.         END IF
  145.         d$ = MID$(c$, HScroll, TextWidth)
  146.         CALL DisplayText(LeftIndent + 1, TopIndent + i, 7, 1, d$)
  147.     NEXT
  148.  
  149.     ' Cursor2
  150.     IF ((Cursor2.X > 0 AND Cursor2.X < WindowWidth) AND ((Cursor2.Y > 0) AND (Cursor2.Y < WindowHeight))) THEN
  151.         p1 = LinearCount(StartIndex, ID1)
  152.         p2 = LinearCount(StartIndex, ID2)
  153.         pe = LinearCount(StartIndex, EOC)
  154.         IF ((p2 > p1) AND (p2 < pe)) THEN
  155.             c$ = TheChain(ID2).Content
  156.             IF (c$ = " ") THEN c$ = "_"
  157.             IF (c$ = CHR$(13)) THEN c$ = "~"
  158.             CALL DisplayText(Cursor2.X, Cursor2.Y, 0, 6, c$)
  159.         END IF
  160.     END IF
  161.  
  162.     ' Cursor1
  163.     IF ((Cursor1.X > 0 AND Cursor1.X < WindowWidth) AND ((Cursor1.Y > 0) AND (Cursor1.Y < WindowHeight))) THEN
  164.         c$ = TheChain(ID1).Content
  165.         IF (c$ = " ") THEN c$ = "_"
  166.         IF (c$ = CHR$(13)) THEN c$ = "~"
  167.         IF ((Cursor1.X = Cursor2.X) AND (Cursor1.Y = Cursor2.Y)) THEN
  168.             a = 16: b = 5
  169.         ELSE
  170.             a = 16: b = 3
  171.         END IF
  172.         CALL DisplayText(Cursor1.X, Cursor1.Y, a, b, c$)
  173.     END IF
  174.  
  175.     ' Cursor status
  176.     d$ = TheChain(ID1).Content
  177.     e$ = TheChain(ID2).Content
  178.     IF ((ASC(d$) = 10) OR (ASC(d$) = 13)) THEN d$ = "~"
  179.     IF ((ASC(e$) = 10) OR (ASC(e$) = 13)) THEN e$ = "~"
  180.     IF (ASC(d$) = 32) THEN d$ = "_"
  181.     IF (ASC(e$) = 32) THEN e$ = "_"
  182.     c$ = "(" + LTRIM$(RTRIM$(STR$(Cursor1.X - LeftIndent))) + "," + LTRIM$(RTRIM$(STR$(Cursor1.Y - TopIndent))) + ":" + " " + LTRIM$(RTRIM$(d$)) + " " + LTRIM$(RTRIM$(STR$(ID1))) + ")"
  183.     a = 0: b = 3
  184.     IF ((Cursor1.X = Cursor2.X) AND (Cursor1.Y = Cursor2.Y)) THEN
  185.         a = 15: b = 5
  186.     END IF
  187.     CALL DisplayText(2, WindowHeight, a, b, c$)
  188.     g$ = "(" + LTRIM$(RTRIM$(STR$(Cursor2.X - LeftIndent))) + "," + LTRIM$(RTRIM$(STR$(Cursor2.Y - TopIndent))) + ":" + " " + LTRIM$(RTRIM$(e$)) + " " + LTRIM$(RTRIM$(STR$(ID2))) + ")"
  189.     a = 6: b = 0
  190.     IF (LinearCount(StartIndex, ID2) > LinearCount(StartIndex, ID1)) THEN
  191.         a = 0: b = 6
  192.     END IF
  193.     CALL DisplayText(3 + LEN(c$), WindowHeight, a, b, g$)
  194.     ' Horizontal scrollbar
  195.     p = LinearCount(NthP(StartIndex, FindID(LeftIndent + 1, Cursor1.Y)), ID1)
  196.     q = LEN(LineAsMapped(Cursor1.Y - TopIndent))
  197.     r = p / q
  198.     IF r > 1 THEN r = 1
  199.     IF r < 0 THEN r = 0
  200.     i = 2 + INT(r * (WindowWidth - 2))
  201.     IF i < 1 THEN i = 1
  202.     IF i > WindowWidth THEN i = WindowWidth
  203.     CALL DisplayText(i, WindowHeight - 1, 8, 7, "^")
  204.  
  205.     ' Vertical scrollbar
  206.     p = LinearCount(ID1, NthP(ID1, ChainLimit + 1))
  207.     q = LinearCount(NthL(ID1, ChainLimit + 1), NthP(ID1, ChainLimit + 1))
  208.     IF (q = 0) THEN r = 1 ELSE r = 1 - p / q
  209.     CALL DisplayText(WindowWidth, 1 + INT(r * (WindowHeight - 1)), 8, 7, "<")
  210.  
  211.     ' Help
  212.     SELECT CASE TextWrapping
  213.         CASE 0: d$ = "Square"
  214.         CASE 1: d$ = "Fluid"
  215.         CASE 2: d$ = "None"
  216.     END SELECT
  217.     c$ = "[F6=Save] [F11=Format] [F12=Wrap: " + d$ + "]"
  218.     IF (TextWrapping = 2) THEN c$ = "[F1/2=HScroll] " + c$
  219.     c$ = c$ + STR$(INT(100 * r)) + "%"
  220.     IF (LEN(c$) >= TextWidth) THEN c$ = LEFT$(c$, TextWidth)
  221.     CALL DisplayText(WindowWidth - LEN(c$), 1, 15, 0, c$)
  222.     c$ = "[Esc=Sync] [Mouse2=Copy] [Mouse3=Paste]"
  223.     IF (InsertKey = 1) THEN c$ = "[Ins] " + c$
  224.     IF (LEN(c$) >= TextWidth) THEN c$ = LEFT$(c$, TextWidth)
  225.     CALL DisplayText(WindowWidth - LEN(c$), WindowHeight, 15, 0, c$)
  226.  
  227.     ' Pointer
  228.     IF ((_MOUSEX >= 1) AND (_MOUSEX <= WindowWidth) AND (_MOUSEY >= 1) AND (_MOUSEY <= WindowHeight)) THEN
  229.         a$ = CHR$(SCREEN(_MOUSEY, _MOUSEX))
  230.         CALL DisplayText(_MOUSEX, _MOUSEY, 0, 15, a$)
  231.     END IF
  232.  
  233.     COLOR 15, 0
  234.  
  235.  
  236. SUB Assimilate (a AS STRING)
  237.     ' Load a string to initialize chain.
  238.     FOR k = 1 TO ChainLimit
  239.         TheChain(k).Identity = 0
  240.     NEXT
  241.     StartIndex = 1
  242.     PreviousIdentity = BOC
  243.     NextIdentity = NextOpenIdentity(StartIndex)
  244.     FOR k = 1 TO LEN(a)
  245.         j = NextIdentity
  246.         TheChain(j).Identity = j
  247.         TheChain(j).Content = ReFormat$(MID$(a, k, 1))
  248.         TheChain(j).Lagger = PreviousIdentity
  249.         PreviousIdentity = j
  250.         IF (k < LEN(a)) THEN
  251.             NextIdentity = NextOpenIdentity(j)
  252.             TheChain(j).Pointer = NextIdentity
  253.         ELSE
  254.             TheChain(j).Pointer = EOC
  255.         END IF
  256.         PRINT TheChain(j).Content
  257.     NEXT
  258.     ID1 = StartIndex
  259.     ID2 = NthP(ID1, ChainLimit + 1)
  260.  
  261. FUNCTION ReFormat$ (a AS STRING)
  262.     c$ = a
  263.     IF c$ = CHR$(10) THEN c$ = CHR$(13)
  264.     IF c$ = CHR$(9) THEN c$ = "    "
  265.     ReFormat = c$
  266.  
  267. FUNCTION NthP (a AS LONG, b AS LONG)
  268.     ' Returns the address that is b jumps ahead of address a.
  269.     i = a
  270.     IF (i <> EOC) THEN
  271.         k = 0
  272.         j = 0
  273.         DO WHILE (k < b)
  274.             k = k + 1
  275.             j = TheChain(i).Identity
  276.             i = TheChain(j).Pointer
  277.             IF (i = EOC) THEN EXIT DO
  278.         LOOP
  279.     END IF
  280.     NthP = j
  281.  
  282. FUNCTION NthPC (a AS LONG, b AS STRING)
  283.     ' Returns the address holding b first enLinearCountered from a.
  284.     i = a
  285.     DO
  286.         j = TheChain(i).Identity
  287.         i = TheChain(j).Pointer
  288.         IF (TheChain(j).Content = b) THEN EXIT DO
  289.         IF (i = EOC) THEN
  290.             j = BOC
  291.             EXIT DO
  292.         END IF
  293.     LOOP
  294.     NthPC = j
  295.  
  296. FUNCTION NthL (a AS LONG, b AS LONG)
  297.     ' Returns the address that is b jumps behind address a.
  298.     i = a
  299.     k = 0
  300.     DO WHILE k < b
  301.         k = k + 1
  302.         j = TheChain(i).Identity
  303.         i = TheChain(j).Lagger
  304.         IF (i = BOC) THEN EXIT DO
  305.     LOOP
  306.     NthL = j
  307.  
  308. FUNCTION NextOpenIdentity (a AS LONG)
  309.     ' Returns first nonzero identity.
  310.     FOR j = a TO ChainLimit
  311.         IF (TheChain(j).Identity = 0) THEN EXIT FOR
  312.     NEXT
  313.     IF (j > ChainLimit) THEN
  314.         PRINT "Out of memory: "; ChainLimit
  315.         SLEEP
  316.         SYSTEM
  317.     END IF
  318.     NextOpenIdentity = j
  319.  
  320. FUNCTION BackBreak (a AS LONG)
  321.     ' Function for scrolling up.
  322.     j = a
  323.     lastbreak = 0
  324.     c$ = ""
  325.     DO
  326.         IF (j = BOC) THEN EXIT DO
  327.         k = TheChain(j).Lagger
  328.         IF (k = BOC) THEN
  329.             lastbreak = j
  330.             EXIT DO
  331.         END IF
  332.         j = k
  333.         d$ = TheChain(j).Content
  334.         IF ((TextWrapping = 1) AND (d$ = " ")) THEN lastbreak = j
  335.         c$ = d$ + c$
  336.         IF (TextWrapping <> 2) AND (LEN(c$) = TextWidth) THEN EXIT DO
  337.         IF (d$ = CHR$(13)) THEN EXIT DO
  338.     LOOP
  339.     IF (lastbreak <> 0) THEN j = TheChain(lastbreak).Identity
  340.     BackBreak = j
  341.  
  342. SUB InsertBefore (a AS LONG, b AS STRING)
  343.     ' Inserts a single cell before address a in the chain.
  344.     j = NextOpenIdentity(a)
  345.     al = TheChain(a).Lagger
  346.     TheChain(j).Identity = j
  347.     TheChain(j).Pointer = a
  348.     TheChain(j).Lagger = al
  349.     TheChain(j).Content = ReFormat$(b)
  350.     TheChain(a).Lagger = j
  351.     IF (al = BOC) THEN StartIndex = j ELSE TheChain(al).Pointer = j
  352.  
  353. SUB InsertAfter (a AS LONG, b AS STRING)
  354.     ' Inserts a single cell after address a in the chain.
  355.     j = NextOpenIdentity(a)
  356.     ap = TheChain(a).Pointer
  357.     TheChain(j).Identity = j
  358.     TheChain(j).Pointer = ap
  359.     TheChain(j).Lagger = a
  360.     TheChain(j).Content = ReFormat$(b)
  361.     TheChain(a).Pointer = j
  362.     IF (ap <> EOC) THEN TheChain(ap).Lagger = j
  363.  
  364. SUB InsertRange (a AS LONG, b AS STRING)
  365.     ' Inserts a sub-chain anywhere.
  366.     FOR k = 1 TO LEN(b)
  367.         c$ = MID$(b, k, 1)
  368.         CALL InsertBefore(a, c$)
  369.     NEXT
  370.  
  371. SUB UnlinkCell (a AS LONG)
  372.     ' Remove single cell from chain and clear identity.
  373.     ap = TheChain(a).Pointer
  374.     al = TheChain(a).Lagger
  375.     IF ((ap = EOC) AND (al = BOC)) THEN
  376.         TheChain(a).Content = " "
  377.         'ID1 = a
  378.         'ID2 = ID1
  379.     ELSE
  380.         TheChain(a).Identity = 0
  381.         IF ((ap <> EOC) AND (al <> BOC)) THEN
  382.             TheChain(al).Pointer = ap
  383.             TheChain(ap).Lagger = al
  384.         END IF
  385.         IF (ap = EOC) THEN TheChain(al).Pointer = EOC
  386.         IF (al = BOC) THEN
  387.             StartIndex = ap
  388.             TheChain(ap).Lagger = BOC
  389.         END IF
  390.     END IF
  391.  
  392. SUB UnlinkRange (a AS LONG, b AS LONG)
  393.     ' Remove sub-chain and clear identity of each cell.
  394.     bp = TheChain(b).Pointer
  395.     al = TheChain(a).Lagger
  396.     IF ((al = BOC) AND (bp = EOC)) THEN
  397.         CALL UnlinkRange(NthP(a, 2), b)
  398.         TheChain(a).Content = " "
  399.         TheChain(a).Pointer = bp
  400.     ELSE
  401.         k = a
  402.         DO WHILE ((k <> b) AND (k <> EOC))
  403.             TheChain(k).Identity = 0
  404.             k = TheChain(k).Pointer
  405.         LOOP
  406.         TheChain(b).Identity = 0
  407.         TheChain(bp).Lagger = al
  408.         IF (al = BOC) THEN StartIndex = bp ELSE TheChain(al).Pointer = bp
  409.     END IF
  410.  
  411. FUNCTION LinearCount (a AS LONG, b AS LONG)
  412.     ' Returns number of links between two addresses.
  413.     i = a
  414.     k = 0
  415.     DO WHILE (i <> b)
  416.         k = k + 1
  417.         j = TheChain(i).Identity
  418.         i = TheChain(j).Pointer
  419.         IF (i = EOC) THEN EXIT DO
  420.     LOOP
  421.     LinearCount = k
  422.  
  423. FUNCTION LinearCount2 (a AS LONG, b AS LONG, c AS LONG)
  424.     ' Returns number of links between two addresses, with exit condition.
  425.     i = a
  426.     k = 0
  427.     DO WHILE (i <> b)
  428.         k = k + 1
  429.         j = TheChain(i).Identity
  430.         i = TheChain(j).Pointer
  431.         IF (i = EOC) THEN EXIT DO
  432.         IF (k = c) THEN EXIT DO
  433.     LOOP
  434.     LinearCount2 = k
  435.  
  436. FUNCTION Projection$ (a AS LONG, b AS LONG)
  437.     ' Returns the linear content for all address between a and b, inclusive.
  438.     DIM TheReturn AS STRING
  439.     TheReturn = ""
  440.     IF (a = b) THEN
  441.         TheReturn = TheChain(a).Content
  442.     ELSE
  443.         j = a
  444.         DO
  445.             c$ = TheChain(j).Content
  446.             TheReturn = TheReturn + c$
  447.             k = TheChain(j).Pointer
  448.             IF (j = b) THEN EXIT DO
  449.             IF (k = EOC) THEN EXIT DO
  450.             j = k
  451.         LOOP
  452.     END IF
  453.     Projection$ = TheReturn
  454.  
  455. SUB MapText
  456.     IF (TextFormatting = 1) THEN br$ = "~" ELSE br$ = " "
  457.     j = StartIndex
  458.     i = 1
  459.     q$ = ""
  460.     d$ = ""
  461.     DO ' Begin with any left-over text from previous iteration.
  462.         q$ = d$
  463.         d$ = ""
  464.         r = TextWidth - LEN(q$)
  465.         IF (TextWrapping <> 2) THEN k1 = NthP(j, r) ELSE k1 = EOC
  466.         k2 = NthPC(j, CHR$(13))
  467.         IF (TextWrapping <> 2) THEN c1 = LinearCount(j, k1) ELSE c1 = LinearCount2(j, k1, TextWidth * TextHeight)
  468.         c2 = LinearCount(j, k2)
  469.         IF (c2 = 0) THEN ' Line is blank-returned.
  470.             k = k2
  471.             q$ = q$ + br$
  472.             j = NthP(k, 2)
  473.         ELSE
  474.             IF (c1 = c2) THEN ' Possible end of chain.
  475.                 k = TheChain(k1).Lagger
  476.                 q$ = q$ + Projection$(j, k)
  477.                 j = NthP(k, 2)
  478.             END IF
  479.             IF (c1 < c2) THEN ' Width limit case (not always maximum).
  480.                 k = k1
  481.                 q$ = q$ + Projection$(j, k)
  482.                 j = NthP(k, 2)
  483.             END IF
  484.             IF (c1 > c2) THEN ' Break return somewhere in line (not first).
  485.                 k = k2
  486.                 q$ = q$ + Projection$(j, TheChain(k).Lagger) + br$
  487.                 n = TheChain(k).Pointer
  488.                 IF (n <> EOC) THEN j = n
  489.             END IF
  490.         END IF
  491.         IF (TextWrapping = 1) THEN ' Wrap text at first space from right, send remainder to next line.
  492.             IF (LEN(q$) >= TextWidth) THEN
  493.                 FOR m = LEN(q$) TO 1 STEP -1
  494.                     c$ = MID$(q$, m, 1)
  495.                     IF (c$ = " ") OR (c$ = "-") THEN
  496.                         q$ = LEFT$(q$, m)
  497.                         EXIT FOR
  498.                     END IF
  499.                     d$ = c$ + d$
  500.                     IF (m = 1) THEN ' Line is too long for allowed space and contains no wrapping characters.
  501.                         q$ = LEFT$(q$, TextWidth)
  502.                         d$ = ""
  503.                         EXIT FOR
  504.                     END IF
  505.                 NEXT
  506.             END IF
  507.         END IF
  508.         LineAsMapped(i) = q$
  509.         i = i + 1
  510.         IF (i >= TextHeight) THEN EXIT DO
  511.         IF (j = k) THEN EXIT DO
  512.     LOOP
  513.     VisibleLines = i - 1
  514.  
  515. FUNCTION StateChange
  516.     DIM TheReturn
  517.     MH = 0
  518.     MW = 0
  519.     MT = 0
  520.         MH1 = _MOUSEBUTTON(1)
  521.         MH2 = _MOUSEBUTTON(2)
  522.         MH3 = _MOUSEBUTTON(3)
  523.         MW = _MOUSEWHEEL
  524.         IF (MW <> 0) THEN MT = MW
  525.     LOOP
  526.     MW = MT
  527.  
  528.     IF (MH1 = -1) THEN
  529.         ' Move Cursor1 among text.
  530.         MH = 1
  531.         IF ((_MOUSEX > LeftIndent) AND (_MOUSEX < TextWidth + LeftIndent + 1) AND (_MOUSEY > TopIndent) AND (_MOUSEY < TopIndent + TextHeight)) THEN
  532.             Cursor1.X = _MOUSEX
  533.             q = LeftIndent + LEN(LineAsMapped(_MOUSEY - TopIndent))
  534.             IF (Cursor1.X > q) THEN Cursor1.X = q
  535.             Cursor1.Y = _MOUSEY
  536.             CALL ReassignID1
  537.         END IF
  538.         ' Move by vertical scrollbar.
  539.         IF (_MOUSEX = WindowWidth) THEN
  540.             i = NthL(ID1, ChainLimit + 1)
  541.             j = NthP(ID1, ChainLimit + 1)
  542.             IF (_MOUSEY = WindowHeight) THEN i = j
  543.             IF (_MOUSEY > 1) AND (_MOUSEY < WindowHeight) THEN
  544.                 t = LinearCount(i, j)
  545.                 f = _MOUSEY / WindowHeight
  546.                 FOR k = 1 TO t
  547.                     IF (k / t >= f) THEN EXIT FOR
  548.                     i = TheChain(i).Pointer
  549.                 NEXT
  550.             END IF
  551.             StartIndex = i
  552.             ID1 = i
  553.         END IF
  554.         ' Move by horizontal scrollbar.
  555.         IF (_MOUSEY = WindowHeight - 1) THEN
  556.             j = ID1
  557.             i = NthP(StartIndex, FindID(LeftIndent + 1, Cursor1.Y))
  558.             'IF (_MOUSEX = windowwidth - 1) THEN i = NthP(StartIndex, FindID(LeftIndent + LEN(LineAsMapped(Cursor1.Y - TopIndent)), Cursor1.Y) + (HScroll - 1))
  559.             IF (_MOUSEX > 1) AND (_MOUSEX < WindowWidth) THEN
  560.                 t = LEN(LineAsMapped(Cursor1.Y - TopIndent))
  561.                 f = _MOUSEX / WindowWidth
  562.                 FOR k = 1 TO t
  563.                     IF (k / t >= f) THEN EXIT FOR
  564.                     i = TheChain(i).Pointer
  565.                 NEXT
  566.             END IF
  567.             ID1 = i
  568.             d = LinearCount(StartIndex, i) - LinearCount(StartIndex, j)
  569.             IF (TextWrapping = 2) THEN HScroll = HScroll + d
  570.             IF HScroll < 1 THEN HScroll = 1
  571.         END IF
  572.     END IF
  573.     IF (MH2 = -1) THEN
  574.         ' Move Cursor2 and copy anything between Cursor1 and Cursor2 to clipboard.
  575.         MH = 1
  576.         IF (_MOUSEX > LeftIndent) AND (_MOUSEX < TextWidth + LeftIndent + 1) AND (_MOUSEY > TopIndent) AND (_MOUSEY < TopIndent + TextHeight + 1) THEN
  577.             Cursor2.X = _MOUSEX
  578.             q = LeftIndent + LEN(LineAsMapped(_MOUSEY - TopIndent))
  579.             IF (Cursor2.X > q) THEN Cursor2.X = q
  580.             Cursor2.Y = _MOUSEY
  581.             CALL ReassignID2
  582.             IF (LinearCount(StartIndex, ID2) > LinearCount(StartIndex, ID1)) THEN _CLIPBOARD$ = Projection$(ID1, ID2)
  583.         END IF
  584.     END IF
  585.     IF (MH3 = -1) THEN
  586.         ' Paste at Cursor1 position.
  587.         MH = 1
  588.         'IF (LinearCount(StartIndex, ID2) >= LinearCount(StartIndex, ID1)) THEN
  589.         CALL InsertRange(ID1, _CLIPBOARD$)
  590.     END IF
  591.     IF (MW = -1) THEN
  592.         ' Wheel up
  593.         MH = 1
  594.         StartIndex = BackBreak(StartIndex)
  595.         CALL ReassignID1
  596.     END IF
  597.     IF (MW = 1) THEN
  598.         ' Wheel down
  599.         MH = 1
  600.         IF (VisibleLines > 1) THEN
  601.             StartIndex = NthP(StartIndex, LEN(LineAsMapped(1)) + 1)
  602.             CALL MapText
  603.         END IF
  604.         CALL ReassignID1
  605.     END IF
  606.  
  607.     KH = 0
  608.     '''k$ = ""
  609.     '''k$ = INKEY$
  610.     '''IF k$ <> "" THEN KH = ASC(k$)
  611.     KH = _KEYHIT
  612.  
  613.     ' Bksp
  614.     IF (KH = 8) THEN
  615.         r = TheChain(ID1).Pointer
  616.         q = TheChain(ID1).Lagger
  617.         CALL UnlinkCell(ID1)
  618.         IF ((r = EOC) AND (q = BOC)) THEN
  619.         ELSE
  620.             IF (q <> BOC) THEN ID1 = q ELSE ID1 = r
  621.             IF (r = EOC) THEN ID2 = ID1
  622.         END IF
  623.     END IF
  624.     ' Tab
  625.     IF (KH = 9) THEN CALL InsertRange(ID1, "    ")
  626.     ' Esc
  627.     IF (KH = 27) THEN
  628.         IF (ID2 <> ID1) THEN ID2 = ID1 ELSE ID2 = StartIndex 'NthL(ID2, 2)
  629.     END IF
  630.     ' Enter, Alphanumerics
  631.     IF (KH = 13) OR ((KH >= 32) AND (KH <= 126)) THEN
  632.         IF (InsertKey = -1) THEN
  633.             IF (ID1 = ID2) THEN
  634.                 CALL InsertBefore(ID1, LTRIM$(RTRIM$(CHR$(KH))))
  635.             ELSE
  636.                 CALL InsertAfter(ID1, LTRIM$(RTRIM$(CHR$(KH))))
  637.                 ID1 = NthP(ID1, 2)
  638.             END IF
  639.         ELSE
  640.             TheChain(ID1).Content = LTRIM$(RTRIM$(CHR$(KH)))
  641.             IF (ID1 = ID2) THEN
  642.                 ID1 = NthP(ID1, 2)
  643.                 ID2 = ID1
  644.             ELSE
  645.                 ID1 = NthP(ID1, 2)
  646.             END IF
  647.         END IF
  648.         IF ((TextWrapping = 2) AND (Cursor1.X - LeftIndent = TextWidth)) THEN HScroll = HScroll + 1
  649.     END IF
  650.     ' F1
  651.     IF (KH = 15104) THEN
  652.         IF (TextWrapping = 2) THEN
  653.             HScroll = HScroll - 1
  654.             IF (HScroll < 1) THEN HScroll = 1
  655.             CALL ReassignID1
  656.             CALL ReassignID2
  657.         END IF
  658.     END IF
  659.     ' F2
  660.     IF (KH = 15360) THEN
  661.         IF (TextWrapping = 2) THEN
  662.             HScroll = HScroll + 1
  663.             CALL ReassignID1
  664.             CALL ReassignID2
  665.         END IF
  666.     END IF
  667.     ' F5
  668.     IF (KH = 16128) THEN
  669.         q$ = Projection$(NthL(ID1, ChainLimit + 1), NthP(ID1, ChainLimit + 1))
  670.         Assimilate q$
  671.     END IF
  672.     ' F4
  673.     IF (KH = 15872) THEN
  674.         'CALL InsertRange(NthP(ID2, 2), CHR$(10) + "=" + CoreProcess$(Projection(ID1, ID2)))
  675.         'CALL InsertRange(NthP(ID2, 2), CHR$(10) + "=" + SxriptEval$(Projection(ID1, ID2)))
  676.         ID2 = StartIndex
  677.     END IF
  678.     ' F6
  679.     IF (KH = 16384) THEN
  680.         OPEN FileName$ FOR OUTPUT AS #1
  681.         q$ = Projection$(NthL(ID1, ChainLimit + 1), NthP(ID1, ChainLimit + 1))
  682.         PRINT #1, q$
  683.         CLOSE #1
  684.     END IF
  685.     ' F7
  686.     IF (KH = 16640) THEN
  687.         GOLSwitch = -GOLSwitch
  688.     END IF
  689.     ' F8 IF (KH = 16896) THEN
  690.     ' Home
  691.     IF (KH = 18176) THEN
  692.         IF (TextWrapping = 2) THEN HScroll = 1
  693.         Cursor1.X = LeftIndent + 1
  694.         CALL ReassignID1
  695.     END IF
  696.     ' UpArrow
  697.     IF (KH = 18432) THEN
  698.         IF (Cursor1.Y > TopIndent + 1) THEN
  699.             Cursor1.Y = Cursor1.Y - 1
  700.         ELSE
  701.             StartIndex = BackBreak(StartIndex)
  702.         END IF
  703.         q = LEN(LineAsMapped(Cursor1.Y - TopIndent)) + 1
  704.         IF (Cursor1.X > q) THEN Cursor1.X = q
  705.         CALL ReassignID1
  706.     END IF
  707.     ' PgUp
  708.     IF (KH = 18688) THEN
  709.         FOR k = 1 TO INT(TextHeight / 2)
  710.             StartIndex = BackBreak(StartIndex)
  711.         NEXT
  712.         CALL ReassignID1
  713.     END IF
  714.     ' LeftArrow
  715.     IF (KH = 19200) THEN
  716.         ID1 = NthL(ID1, 2)
  717.         IF (TextWrapping = 2) THEN
  718.             IF (Cursor1.X = LeftIndent + 1) THEN
  719.                 IF (HScroll > 1) THEN
  720.                     HScroll = HScroll - 1
  721.                 ELSE
  722.                     j = Cursor1.Y - TopIndent - 1
  723.                     IF (j >= 1) THEN
  724.                         k = LEN(LineAsMapped(j)) - TextWidth + 1
  725.                         IF (k >= 1) THEN
  726.                             HScroll = k
  727.                         END IF
  728.                     END IF
  729.                 END IF
  730.             END IF
  731.         ELSE
  732.             IF ((Cursor1.X - LeftIndent = 1) AND Cursor1.Y - TopIndent = 1) THEN
  733.                 StartIndex = BackBreak(StartIndex)
  734.             END IF
  735.         END IF
  736.     END IF
  737.     ' RightArrow
  738.     IF (KH = 19712) THEN
  739.         ID1 = NthP(ID1, 2)
  740.         m = Cursor1.X - LeftIndent
  741.         n = LEN(LineAsMapped(Cursor1.Y - TopIndent)) - HScroll + 1
  742.         IF (TextWrapping = 2) THEN
  743.             IF (m >= TextWidth) THEN
  744.                 HScroll = HScroll + 1
  745.                 CALL ReassignID1
  746.             END IF
  747.             IF (m >= n) THEN
  748.                 j = Cursor1.Y - TopIndent + 1
  749.                 IF ((j <= TextHeight) AND (VisibleLines > 1)) THEN HScroll = 1
  750.             END IF
  751.         ELSE
  752.             IF ((m >= n) AND (Cursor1.Y - TopIndent = VisibleLines)) THEN
  753.                 IF (VisibleLines > 1) THEN StartIndex = NthP(StartIndex, LEN(LineAsMapped(1)) + 1)
  754.             END IF
  755.         END IF
  756.     END IF
  757.     ' End
  758.     IF (KH = 20224) THEN
  759.         Cursor1.X = LeftIndent + LEN(LineAsMapped(Cursor1.Y - TopIndent))
  760.         CALL ReassignID1
  761.         IF (TextWrapping = 2) THEN
  762.             q = LEN(LineAsMapped(Cursor1.Y - TopIndent)) - TextWidth + 1
  763.             IF (q >= 1) THEN HScroll = q
  764.         END IF
  765.     END IF
  766.     ' DownArrow
  767.     IF (KH = 20480) THEN
  768.         IF (Cursor1.Y = TopIndent + VisibleLines) THEN
  769.             IF (VisibleLines > 1) THEN
  770.                 StartIndex = NthP(StartIndex, LEN(LineAsMapped(1)) + 1)
  771.                 CALL MapText
  772.             END IF
  773.         ELSE
  774.             Cursor1.Y = Cursor1.Y + 1
  775.         END IF
  776.         q = LEN(LineAsMapped(Cursor1.Y - TopIndent)) + 1
  777.         IF (Cursor1.X > q) THEN
  778.             Cursor1.X = q
  779.         END IF
  780.         CALL ReassignID1
  781.     END IF
  782.     ' PgDn
  783.     IF (KH = 20736) THEN
  784.         FOR k = 1 TO INT(TextHeight / 2)
  785.             IF (VisibleLines > 1) THEN
  786.                 StartIndex = NthP(StartIndex, LEN(LineAsMapped(1)) + 1)
  787.                 CALL MapText
  788.             END IF
  789.         NEXT
  790.         CALL ReassignID1
  791.     END IF
  792.     ' Insert
  793.     IF (KH = 20992) THEN
  794.         InsertKey = -InsertKey
  795.     END IF
  796.     ' Del
  797.     IF (KH = 21248) THEN
  798.         IF (LinearCount(StartIndex, ID2) > LinearCount(StartIndex, ID1)) THEN
  799.             r = TheChain(ID2).Pointer
  800.             q = TheChain(ID1).Lagger
  801.             p = ID1
  802.             CALL UnlinkRange(ID1, ID2)
  803.             IF ((r = EOC) AND (q = BOC)) THEN
  804.                 ID1 = p
  805.                 ID2 = ID1
  806.                 StartIndex = p
  807.             ELSE
  808.                 IF (q <> BOC) THEN ID1 = q ELSE ID1 = r
  809.                 ID2 = NthP(ID1, 2)
  810.             END IF
  811.         END IF
  812.     END IF
  813.     ' F11
  814.     IF (KH = 34048) THEN TextFormatting = -TextFormatting
  815.     ' F12
  816.     IF (KH = 34304) THEN
  817.         TextWrapping = TextWrapping + 1
  818.         IF (TextWrapping > 2) THEN TextWrapping = 0
  819.         ID1 = StartIndex
  820.         ID2 = ID1
  821.         HScroll = 1
  822.     END IF
  823.     ' Exit sequence
  824.     TheReturn = 0
  825.     IF ((MH <> 0) OR (KH > 0)) THEN
  826.         TheReturn = 1
  827.         CALL MapText
  828.         CALL CalibrateCursor(ID1)
  829.         CALL CalibrateCursor(ID2)
  830.         ' Cursor sync and autoscrolling.
  831.         IF (Cursor1.Y > TopIndent + TextHeight - 1) THEN StartIndex = NthP(StartIndex, LEN(LineAsMapped(1)) + 1)
  832.     END IF
  833.     _KEYCLEAR
  834.     StateChange = TheReturn
  835.  
  836. SUB CalibrateCursor (a AS LONG)
  837.     ' Place Cursor under ID on rendered line.
  838.     s = StartIndex
  839.     IF ((TextWrapping = 2) AND (HScroll > 1)) THEN s = NthP(s, HScroll)
  840.     c = LinearCount(s, a)
  841.     k = 0
  842.     i = -1
  843.     FOR j = 1 TO VisibleLines
  844.         n = LEN(LineAsMapped(j))
  845.         IF (k + n < c) THEN
  846.             k = k + n
  847.         ELSE
  848.             i = c - k + 1
  849.             EXIT FOR
  850.         END IF
  851.     NEXT
  852.     IF (i >= LeftIndent + LEN(LineAsMapped(j))) THEN
  853.         IF (j <= VisibleLines) THEN
  854.             i = 1
  855.             j = j + 1
  856.         END IF
  857.     END IF
  858.     IF (a = ID1) THEN
  859.         Cursor1.X = LeftIndent + i
  860.         Cursor1.Y = TopIndent + j
  861.     END IF
  862.     IF (a = ID2) THEN
  863.         Cursor2.X = LeftIndent + i
  864.         Cursor2.Y = TopIndent + j
  865.     END IF
  866.  
  867. FUNCTION FindID (a AS INTEGER, b AS LONG)
  868.     ' Find identity under a map location.
  869.     RelX = a - LeftIndent
  870.     RelY = b - TopIndent
  871.     FOR k = 1 TO RelY - 1
  872.         t = t + LEN(LineAsMapped(k))
  873.     NEXT
  874.     t = t + RelX
  875.     FindID = t
  876.  
  877. SUB ReassignID1
  878.     ' Reassign identity under Cursor1.
  879.     ID1 = NthP(StartIndex, FindID(Cursor1.X, Cursor1.Y) + (HScroll - 1))
  880.  
  881. SUB ReassignID2
  882.     ' Reassign identity under Cursor2.
  883.     ID2 = NthP(StartIndex, FindID(Cursor2.X, Cursor2.Y) + (HScroll - 1))
  884.  
  885. SUB ConvertToGrid
  886.     FOR j = 1 TO VisibleLines
  887.         c$ = LineAsMapped(j)
  888.         FOR i = 1 TO LEN(c$) - 1 ' BR offset to exclude break return at line end.
  889.             AuxGrid(i, j, 1) = MID$(c$, i, 1)
  890.         NEXT
  891.     NEXT
  892.  
  893. SUB ConvertFromGrid
  894.     q$ = ""
  895.     FOR j = 1 TO VisibleLines
  896.         FOR i = 1 TO LEN(LineAsMapped(j)) - 1
  897.             q$ = q$ + AuxGrid(i, j, 1)
  898.         NEXT
  899.         q$ = q$ + CHR$(13) ' Undoes BR offset.
  900.     NEXT
  901.     Assimilate q$
  902.  
  903. SUB GOL
  904.     FOR j = 1 TO VisibleLines
  905.         FOR i = 1 TO LEN(LineAsMapped(j)) - 1
  906.             c$ = AuxGrid(i, j, 1)
  907.             IF (c$ = " ") THEN c$ = "0" ELSE c$ = "1"
  908.             AuxGrid(i, j, 1) = c$
  909.             AuxGrid(i, j, 2) = c$
  910.         NEXT
  911.     NEXT
  912.     FOR j = 2 TO VisibleLines - 2 ' BR offset.
  913.         FOR i = 2 TO LEN(LineAsMapped(j)) - 2 ' BR offset.
  914.             c$ = AuxGrid(i, j, 1)
  915.             a1 = VAL(AuxGrid(i - 1, j + 1, 1))
  916.             a2 = VAL(AuxGrid(i, j + 1, 1))
  917.             a3 = VAL(AuxGrid(i + 1, j + 1, 1))
  918.             a4 = VAL(AuxGrid(i - 1, j, 1))
  919.             a6 = VAL(AuxGrid(i + 1, j, 1))
  920.             a7 = VAL(AuxGrid(i - 1, j - 1, 1))
  921.             a8 = VAL(AuxGrid(i, j - 1, 1))
  922.             a9 = VAL(AuxGrid(i + 1, j - 1, 1))
  923.             t = a1 + a2 + a3 + a4 + a6 + a7 + a8 + a9
  924.             IF (c$ = "1") THEN
  925.                 SELECT CASE t
  926.                     CASE IS < 2
  927.                         AuxGrid(i, j, 2) = "0"
  928.                     CASE 2
  929.                         AuxGrid(i, j, 2) = "1"
  930.                     CASE 3
  931.                         AuxGrid(i, j, 2) = "1"
  932.                     CASE IS > 3
  933.                         AuxGrid(i, j, 2) = "0"
  934.                 END SELECT
  935.             ELSE
  936.                 IF (t = 3) THEN AuxGrid(i, j, 2) = "1"
  937.             END IF
  938.         NEXT
  939.     NEXT
  940.     FOR j = 1 TO VisibleLines
  941.         FOR i = 1 TO LEN(LineAsMapped(j)) - 1
  942.             c$ = AuxGrid(i, j, 2)
  943.             IF (c$ = "0") THEN c$ = " " ELSE c$ = CHR$(219)
  944.             AuxGrid(i, j, 1) = c$
  945.             AuxGrid(i, j, 2) = c$
  946.         NEXT
  947.     NEXT
  948.  
  949. SUB ThrowOutput
  950.     'i = NthP(ID1, ChainLimit + 1)
  951.     'FOR k = 1 TO LogTextCount
  952.     '    CALL InsertRange(i, LogText(k) + CHR$(13))
  953.     'NEXT
  954.     LogTextCount = 0
  955.     CALL MapText
  956.     ID1 = NthP(ID1, ChainLimit + 1)
  957.     CALL CalibrateCursor(ID1)
  958.     CALL CalibrateCursor(ID2)
  959.     DO WHILE (Cursor1.Y > TopIndent + TextHeight - 1)
  960.         StartIndex = NthP(StartIndex, LEN(LineAsMapped(1)) + 1)
  961.         CALL MapText
  962.         CALL CalibrateCursor(ID1)
  963.         CALL CalibrateCursor(ID2)
  964.     LOOP
  965.     ID1 = NthP(ID1, ChainLimit + 1)
  966.     CALL PrintEverything
  967.  
  968. SUB DisplayText (Col AS INTEGER, Row AS INTEGER, Shade1 AS INTEGER, Shade2 AS INTEGER, Text AS STRING)
  969.     COLOR Shade1, Shade2
  970.     _PRINTSTRING (Col, Row), Text
  971.     'LOCATE Row, Col: PRINT Text
  972.  
  973. 'REM $Include: 'sxmath.bm'
  974. 'REM $Include: 'sxript.bm'
  975.  
You're not done when it works, you're done when it's right.

Offline Prithak

  • Newbie
  • Posts: 56
  • Life itself is a Programming Language!
    • View Profile
    • My Programming Language
Re: Syntax Highlighting (This gonna be hard! :P)
« Reply #6 on: March 12, 2019, 10:18:57 pm »
Thank you for all the help bplus, Pete and STxAxTIC. You're right! I should get the text editor further along with the text editor before I do that lol. I just wanted to make an IDE for my programming language that I am making and I wanted to highlight the syntax. I made this program late at night with my eyes sore xD. So, I forgot to include IF LEN(k$). I would have done that lol. Thank you Pete for the code and also bplus! I would try to make it happen though with my own mind ;P
CLS
IF computer$ = "ON" THEN
me$ = "Happy!"
ELSE
me$ = "Time To Draw!"
END IF
END

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Syntax Highlighting (This gonna be hard! :P)
« Reply #7 on: March 13, 2019, 09:55:01 am »
Thank you for all the help bplus, Pete and STxAxTIC. You're right! I should get the text editor further along with the text editor before I do that lol. I just wanted to make an IDE for my programming language that I am making and I wanted to highlight the syntax. I made this program late at night with my eyes sore xD. So, I forgot to include IF LEN(k$). I would have done that lol. Thank you Pete for the code and also bplus! I would try to make it happen though with my own mind ;P

When I play around with interpreters, I used a standard text editor to write the programs and saved them with a special extension like bas.txt so myNextProgram is named "myNextProgram bas.txt". I could drag and drop such a file onto the .exe interpreter and from a COMMAND$ check, it would recognize the file as meant to run with interpreter. If COMMAND$ was blank, when the interpreter was run or not a proper file, it would show the files in folder with a "* bas.txt" extension that could be selected to run. This saves you all the trouble of writing an editor/IDE and you can focus on the Interpreter or PL you are developing.

Quote
Arrays are going to end up biting you. Go with a linked list:
Not so much with lines to a program which naturally fall into an array. WP with word wrap and all the bells and whistles of text editor, yeah, after a certain size, arrays become too slow.

Offline Aurel

  • Forum Regular
  • Posts: 167
    • View Profile
Re: Syntax Highlighting (This gonna be hard! :P)
« Reply #8 on: March 19, 2019, 04:21:52 am »
Quote
I just wanted to make an IDE for my programming language

then you must use scintilla or something similar if you whish to do it on a quick way.
If you whish o do it from scratch then you can use richedit control ..but this require
windows api and lot of learning and thinkering.
for scintilla you may look into codeProject site or maybe you can look into my forum
for my own editor (witen in o2)....or you may look into DAVs IDE but then you need to know pureBasic.
hmmm lot of problems...
//////////////////////////////////////////////////////////////////
https://aurelsoft.ucoz.com
https://www.facebook.com/groups/470369984111370
//////////////////////////////////////////////////////////////////