Author Topic: XE v1.12 - Simple file viewer/editor. Updated to work in Linux now.  (Read 1475 times)

0 Members and 1 Guest are viewing this topic.

Offline Dav

  • Forum Resident
  • Posts: 792
Updated this editor to work under linux, and also use a built-in font for larger editing screen.  I'm discovering some of my posted programs which I said would work under Linux actually doesn't.  XE was one of them so I've have fixed it.

- Dav

Code: QB64: [Select]
  1. '============
  2. 'XE.BAS v1.12
  3. '============
  4. 'A simple File editor/viewer.
  5. 'Coded by Dav, NOV/2021 with QB64-GL v2
  6. '
  7. ' * FIXED: Fixed FileSelect box to work correctly under Linux.
  8. ' * ADDED: Uses a resizable Code Page FONT to allow a larger SCREEN 0.
  9. '          (FONT is extracted/created temporarily then deleted after use)
  10. '
  11. '==========================================================================
  12. '* * * *          USE THIS PROGRAM AT YOUR OWN RISK ONLY!!          * * * *
  13. '==========================================================================
  14. '
  15. '
  16. ' ABOUT:
  17. ' ~~~~~
  18. '
  19. ' XE is a simple Binary File Editor (also called a HEX editor) that lets
  20. ' you view and edit raw data bytes of a file.  With XE you can peek inside
  21. ' EXE/DLL files and see what information they may contain.  XE also has the
  22. ' capacity to change bytes by either typing in ASCII characters or entering
  23. ' the HEX value for each byte.  XE was first coded in Qbasic - now in QB64.
  24. '
  25. ' Since the very nature of XE is to alter file data you should always use
  26. ' EXTREME caution when editing any file - AND ALWAYS MAKE A BACKUP FIRST!
  27. '
  28. '==========================================================================
  29. '
  30. ' HOW TO USE:
  31. ' ~~~~~~~~~~
  32. '
  33. ' XE accepts command line arguments.  You can drag/drop a file onto XE.
  34. ' If you don't specify a filename on startup, XE will ask you for one.
  35. '
  36. ' There are TWO ways to View & Edit files - in HEX (default) or ASCII mode.
  37. '
  38. ' Files are first opened in HEX mode displaying 2 windows of data.  The
  39. ' right window shows the charaters while the larger left window shows HEX
  40. ' values for them. HEX mode is best for patching and is the only way to
  41. ' edit the HEX values of bytes.
  42. '
  43. '
  44. ' Pressing ENTER switches to ASCII (non-HEX) mode, showing a larger page
  45. ' of raw data bytes - the ASCII chracter data only.  This mode is best for
  46. ' skimming through files faster.  ENTER toggles view modes back and forth.
  47. '
  48. ' While viewing a file you can browse through the file using the ARROWS,
  49. ' PAGEUP/DOWN, HOME and the END keys.
  50. '
  51. ' The currently opened filename is shown with full path in the title bar.
  52. ' and just filename is displayed in the FILE: area just below title bar.
  53. '
  54. ' While viewing a file, press E to enter into EDIT mode and begin editing
  55. ' bytes at the current position. If you're in HEX mode (2 windows), you can
  56. ' edit bytes either by typing characters on the right side or entering HEX
  57. ' values on the left window.  Press TAB to switch windows to edit in.
  58. ' Press ESC to save or disgard changes and to exit editing mode.
  59. '
  60. ' Press M for a complete MENU listing all of the Key COMMANDS.
  61. '
  62. '==========================================================================
  63. '
  64. ' COMMAND:
  65. ' ~~~~~~~~
  66. '
  67. '         E  =  Enters EDIT MODE. Only the displayed bytes can be edited.
  68. '
  69. '       TAB  =  Switchs panes (the cursor) while editing in HEX mode.
  70. '
  71. '         S  =  Searches file for a string starting at the current byte.
  72. '               A Match-Case option is available.  A high beep alerts you
  73. '               when match is found. A Low beep sounds when EOF reached.
  74. '
  75. '         N  =  Finds NEXT Match after a do a string search.
  76. '
  77. '         F  =  Toggles FILTERING of all non-standard-text characters.
  78. '               A flashing "F" is at the top-left corner when FILTER ON.
  79. '
  80. '         G  =  GOTO a certain byte position (number) in the file.
  81. '
  82. '         L  =  GOTO a specified location (Hex value) of the file.
  83. '
  84. '     ENTER  =  Toggles HEX and ASCII view modes.  The ASCII mode lets
  85. '               you browse more data per page.  You can EDIT in both
  86. '               modes but can only enter in HEX vaules in HEX mode.
  87. '
  88. '       ESC  =  EXITS out of editing mode, and also EXITS the program.
  89. '
  90. ' ALT+ENTER  =  Toggle FULLSCREEN/WINDOWED mode of the XE program.
  91. '
  92. '==========================================================================
  93. '==========================================================================
  94.  
  95.  
  96. '==========================================================================
  97. 'SETUP SCREEN MODE
  98. '=================
  99.  
  100. SCREEN Pete: WIDTH 80, 25 'Use Screen mode 0, aka the Pete...
  101.  
  102. 'Font size based on desktop resolution - it expands SCREEN 0 nicely.
  103. 'You may have to adjust it a bit to look the best on your screen res
  104. FONT (INT(_DESKTOPHEIGHT / 25) * .88)
  105.  
  106. _DELAY .25 'Be sure window exists before calling _TITLE
  107. _CONTROLCHR OFF 'Printing all 255 characters on screen, so this is needed.
  108.  
  109. _TITLE "XE v1.12" 'Everything has a name
  110.  
  111.  
  112. '==========================================================================
  113. 'LOAD FILE
  114. '=========
  115.  
  116. CLS , 1: COLOR 1, 15
  117. LOCATE 1, 1: PRINT STRING$(80, 32);
  118. LOCATE 1, 1: PRINT " Load file...";
  119.  
  120.     File$ = FileSelect$(5, 10, 15, 55, "*.*")
  121.     IF File$ = "" THEN
  122.         PRINT "No file selected."
  123.         END
  124.     END IF
  125.     File$ = COMMAND$
  126.  
  127. IF _FILEEXISTS(File$) = 0 THEN
  128.     COLOR 7, 0: CLS
  129.     PRINT "XE v1.12 - Binary file editor."
  130.     PRINT
  131.     PRINT File$; " not found!"
  132.     END
  133.  
  134. File$ = LTRIM$(RTRIM$(File$)) 'trim off any spaces is any...
  135. FullFileName$ = File$ 'make a copy For TITLE/OPEN to use...
  136.  
  137. 'If filename+path too long for display, strip off path
  138. IF LEN(File$) > 70 THEN
  139.     ts$ = ""
  140.     FOR q = LEN(File$) TO 1 STEP -1
  141.         t$ = MID$(File$, q, 1)
  142.         IF t$ = "/" OR t$ = "\" THEN EXIT FOR
  143.         ts$ = t$ + ts$
  144.     NEXT
  145.     File$ = ts$
  146.     'If filename too long, shorten it for display
  147.     IF LEN(File$) > 70 THEN
  148.         File$ = MID$(File$, 1, 67) + "..."
  149.     END IF
  150.  
  151. '==========================================================================
  152. 'OPEN FILE
  153. '=========
  154.  
  155. OPEN FullFileName$ FOR BINARY AS 7
  156.  
  157. _TITLE "XE v1.12 - " + FullFileName$
  158.  
  159. DisplayView% = 1 'Default to 2-PANE view
  160.  
  161. ByteLocation& = 1
  162. IF DisplayView% = 1 THEN
  163.     BufferSize% = (16 * 23)
  164.     BufferSize% = (79 * 23)
  165. IF BufferSize% > LOF(7) THEN BufferSize% = LOF(7)
  166.  
  167.  
  168. '==========================================================================
  169. 'DISPLAY FILE
  170. '============
  171.  
  172. COLOR 15, 1: CLS: LOCATE 1, 1, 0
  173.  
  174.     SEEK #7, ByteLocation&
  175.  
  176.     PageOfData$ = INPUT$(BufferSize%, 7)
  177.  
  178.     'If dual pane mode....
  179.     IF DisplayView% = 1 THEN
  180.         IF LEN(PageOfData$) < (16 * 23) THEN
  181.             PageFlag% = 1: PageLimit% = LEN(PageOfData$)
  182.             PageOfData$ = PageOfData$ + STRING$(16 * 23 - LEN(PageOfData$), CHR$(0))
  183.         END IF
  184.         'show right side
  185.         y% = 3: x% = 63
  186.         FOR c% = 1 TO LEN(PageOfData$)
  187.             CurrentByte% = ASC(MID$(PageOfData$, c%, 1))
  188.             'show a . instead of a null (looks better to me)
  189.             IF CurrentByte% = 0 THEN CurrentByte% = 46
  190.             IF Filter% = 1 THEN
  191.                 SELECT CASE CurrentByte%
  192.                     CASE 0 TO 31, 123 TO 255: CurrentByte% = 32
  193.                 END SELECT
  194.             END IF
  195.             LOCATE y%, x%: PRINT CHR$(CurrentByte%);
  196.             x% = x% + 1: IF x% = 79 THEN x% = 63: y% = y% + 1
  197.         NEXT
  198.         'show left side
  199.         y% = 3: x% = 15
  200.         FOR c% = 1 TO LEN(PageOfData$)
  201.             CurrentByte% = ASC(MID$(PageOfData$, c%, 1))
  202.             CurrentByte$ = HEX$(CurrentByte%): IF LEN(CurrentByte$) = 1 THEN CurrentByte$ = "0" + CurrentByte$
  203.             LOCATE y%, x%: PRINT CurrentByte$; " ";
  204.             x% = x% + 3: IF x% >= 62 THEN x% = 15: y% = y% + 1
  205.         NEXT
  206.     ELSE
  207.         'One page display, Full view
  208.         'Adjust data size used
  209.         IF LEN(PageOfData$) < (79 * 23) THEN 'Enough to fill screen?
  210.             PageFlag% = 1: PageLimit% = LEN(PageOfData$) 'No? Mark this and pad
  211.             PageOfData$ = PageOfData$ + SPACE$(79 * 23 - LEN(PageOfData$)) 'data with spaces.
  212.         END IF
  213.         y% = 3: x% = 1 'Screen location where data begins displaying
  214.         FOR c% = 1 TO LEN(PageOfData$) 'Show all the bytes.
  215.             CurrentByte% = ASC(MID$(PageOfData$, c%, 1)) 'Check the ASCII value.
  216.             IF Filter% = 1 THEN 'If Filter is turned on,
  217.                 SELECT CASE CurrentByte% 'changes these values to spaces
  218.                     CASE 0 TO 32, 123 TO 255: CurrentByte% = 32
  219.                 END SELECT
  220.             END IF
  221.             LOCATE y%, x%: PRINT CHR$(CurrentByte%);
  222.             'This line calculates when to go to next row.
  223.             x% = x% + 1: IF x% = 80 THEN x% = 1: y% = y% + 1
  224.         NEXT
  225.     END IF
  226.  
  227.     GOSUB DrawTopBar 'update viewing info at top
  228.  
  229.     'Get user input
  230.     DO
  231.  
  232.         DO UNTIL L$ <> "": L$ = INKEY$: LOOP
  233.         K$ = L$: L$ = ""
  234.  
  235.         GOSUB DrawTopBar
  236.         SELECT CASE UCASE$(K$)
  237.             CASE CHR$(27): EXIT DO
  238.             CASE "M": GOSUB Menu:
  239.             CASE "N"
  240.                 IF s$ <> "" THEN
  241.                     GOSUB Search
  242.                     GOSUB DrawTopBar
  243.                 END IF
  244.             CASE "E"
  245.                 IF DisplayView% = 1 THEN
  246.                     GOSUB EditRightSide
  247.                 ELSE
  248.                     GOSUB EditFullView
  249.                 END IF
  250.                 GOSUB DrawTopBar
  251.             CASE "F"
  252.                 IF Filter% = 0 THEN Filter% = 1 ELSE Filter% = 0
  253.             CASE "G"
  254.                 LOCATE 1, 1: PRINT STRING$(80 * 3, 32);
  255.                 LOCATE 1, 3: PRINT "TOTAL BYTES>"; LOF(7)
  256.                 INPUT "  GOTO BYTE# > ", GotoByte$
  257.                 IF GotoByte$ <> "" THEN
  258.                     TMP$ = ""
  259.                     FOR m% = 1 TO LEN(GotoByte$)
  260.                         G$ = MID$(GotoByte$, m%, 1) 'to numerical vales
  261.                         SELECT CASE ASC(G$)
  262.                             CASE 48 TO 57: TMP$ = TMP$ + G$
  263.                         END SELECT
  264.                     NEXT: GotoByte$ = TMP$
  265.                     IF VAL(GotoByte$) < 1 THEN GotoByte$ = "1"
  266.                     IF VAL(GotoByte$) > LOF(7) THEN GotoByte$ = STR$(LOF(7))
  267.                     IF GotoByte$ <> "" THEN ByteLocation& = 0 + VAL(GotoByte$)
  268.                 END IF
  269.             CASE "L"
  270.                 LOCATE 1, 1: PRINT STRING$(80 * 3, 32);
  271.                 LOCATE 1, 3: 'PRINT "TOTAL BYTES>"; LOF(7)
  272.                 INPUT "  GOTO HEX LOCATION-> ", GotoByte$
  273.                 IF GotoByte$ <> "" THEN
  274.                     GotoByte$ = "&H" + GotoByte$
  275.                     IF VAL(GotoByte$) < 1 THEN GotoByte$ = "1"
  276.                     IF VAL(GotoByte$) > LOF(7) THEN GotoByte$ = STR$(LOF(7))
  277.                     IF GotoByte$ <> "" THEN ByteLocation& = 0 + VAL(GotoByte$)
  278.                 END IF
  279.             CASE "S": s$ = ""
  280.                 LOCATE 1, 1: PRINT STRING$(80 * 3, 32);
  281.                 LOCATE 1, 3: INPUT "Search for> ", s$
  282.                 IF s$ <> "" THEN
  283.                     PRINT "  CASE sensitive (Y/N)? ";
  284.                     I$ = INPUT$(1): I$ = UCASE$(I$)
  285.                     IF I$ = "Y" THEN CaseOn% = 1 ELSE CaseOn% = 0
  286.                     GOSUB Search
  287.                 END IF
  288.                 GOSUB DrawTopBar
  289.             CASE CHR$(13)
  290.                 IF DisplayView% = 1 THEN
  291.                     DisplayView% = 0
  292.                     BufferSize% = (79 * 23)
  293.                 ELSE
  294.                     DisplayView% = 1
  295.                     BufferSize% = (16 * 23)
  296.                 END IF
  297.                 GOSUB DrawTopBar
  298.             CASE CHR$(0) + CHR$(72)
  299.                 IF DisplayView% = 1 THEN
  300.                     IF ByteLocation& > 15 THEN ByteLocation& = ByteLocation& - 16
  301.                 ELSE
  302.                     IF ByteLocation& > 78 THEN ByteLocation& = ByteLocation& - 79
  303.                 END IF
  304.             CASE CHR$(0) + CHR$(80)
  305.                 IF DisplayView% = 1 THEN
  306.                     IF ByteLocation& < LOF(7) - 15 THEN ByteLocation& = ByteLocation& + 16
  307.                 ELSE
  308.                     IF ByteLocation& < LOF(7) - 78 THEN ByteLocation& = ByteLocation& + 79
  309.                 END IF
  310.             CASE CHR$(0) + CHR$(73): ByteLocation& = ByteLocation& - BufferSize%: IF ByteLocation& < 1 THEN ByteLocation& = 1
  311.             CASE CHR$(0) + CHR$(81): IF ByteLocation& < LOF(7) - BufferSize% THEN ByteLocation& = ByteLocation& + BufferSize%
  312.             CASE CHR$(0) + CHR$(71): ByteLocation& = 1
  313.             CASE CHR$(0) + CHR$(79): IF NOT EOF(7) THEN ByteLocation& = LOF(7) - BufferSize%
  314.         END SELECT
  315.     LOOP UNTIL K$ <> ""
  316. LOOP UNTIL K$ = CHR$(27)
  317.  
  318.  
  319.  
  320. '==========================================================================
  321. '                              GOSUB ROUTINES
  322. '==========================================================================
  323.  
  324.  
  325. '==========================================================================
  326. Search:
  327. '======
  328.  
  329.     DO
  330.         B$ = INPUT$(BufferSize%, 7): ByteLocation& = ByteLocation& + BufferSize%
  331.         IF CaseOn% = 0 THEN B$ = UCASE$(B$): s$ = UCASE$(s$)
  332.         d$ = INKEY$: IF d$ <> "" THEN EXIT DO
  333.         IF INSTR(1, B$, s$) THEN SOUND 4000, .5: EXIT DO
  334.     LOOP UNTIL INSTR(1, B$, s$) OR EOF(7)
  335.     IF EOF(7) THEN SOUND 2000, 1: SOUND 1000, 1
  336.     ByteLocation& = ByteLocation& - LEN(s$)
  337.  
  338.  
  339. '==========================================================================
  340. EditRightSide: 'Editing Right side info in dual pane mode
  341. '============
  342.  
  343. Pane% = 1
  344.  
  345. x% = 63: IF rightx% THEN y% = CSRLIN ELSE y% = 3
  346. leftx% = 15
  347.  
  348. test% = POS(0)
  349.  
  350. IF test% = 15 OR test% = 16 THEN x% = 63: leftx% = 15
  351. IF test% = 18 OR test% = 19 THEN x% = 64: leftx% = 18
  352. IF test% = 21 OR test% = 22 THEN x% = 65: leftx% = 21
  353. IF test% = 24 OR test% = 25 THEN x% = 66: leftx% = 24
  354. IF test% = 27 OR test% = 28 THEN x% = 67: leftx% = 27
  355. IF test% = 30 OR test% = 31 THEN x% = 68: leftx% = 30
  356. IF test% = 33 OR test% = 34 THEN x% = 69: leftx% = 33
  357. IF test% = 36 OR test% = 37 THEN x% = 70: leftx% = 36
  358. IF test% = 39 OR test% = 40 THEN x% = 71: leftx% = 39
  359. IF test% = 42 OR test% = 43 THEN x% = 72: leftx% = 42
  360. IF test% = 45 OR test% = 46 THEN x% = 73: leftx% = 45
  361. IF test% = 48 OR test% = 49 THEN x% = 74: leftx% = 48
  362. IF test% = 51 OR test% = 52 THEN x% = 75: leftx% = 51
  363. IF test% = 54 OR test% = 55 THEN x% = 76: leftx% = 54
  364. IF test% = 57 OR test% = 58 THEN x% = 77: leftx% = 57
  365. IF test% = 60 OR test% = 61 THEN x% = 78: leftx% = 60
  366.  
  367. GOSUB DrawEditBar:
  368.  
  369. LOCATE y%, x%, 1, 1, 30
  370.  
  371.     DO
  372.         E$ = INKEY$
  373.         IF E$ <> "" THEN
  374.             SELECT CASE E$
  375.                 CASE CHR$(9)
  376.                     IF Pane% = 1 THEN
  377.                         Pane% = 2: GOTO EditLeftSide
  378.                     ELSE
  379.                         Pane% = 1: GOTO EditRightSide
  380.                     END IF
  381.                 CASE CHR$(27): EXIT DO
  382.                 CASE CHR$(0) + CHR$(72): IF y% > 3 THEN y% = y% - 1
  383.                 CASE CHR$(0) + CHR$(80): IF y% < 25 THEN y% = y% + 1
  384.                 CASE CHR$(0) + CHR$(75): IF x% > 63 THEN x% = x% - 1: leftx% = leftx% - 3
  385.                 CASE CHR$(0) + CHR$(77): IF x% < 78 THEN x% = x% + 1: leftx% = leftx% + 3
  386.                 CASE CHR$(0) + CHR$(73), CHR$(0) + CHR$(71): y% = 3
  387.                 CASE CHR$(0) + CHR$(81), CHR$(0) + CHR$(79): y% = 25
  388.                 CASE ELSE
  389.                     IF (ByteLocation& + ((y% - 3) * 16 + x% - 1) - 62) <= LOF(7) AND E$ <> CHR$(8) THEN
  390.                         changes% = 1
  391.                         'new color for changed bytes...
  392.                         COLOR 1, 15: LOCATE y%, x%: PRINT " ";
  393.                         LOCATE y%, leftx%
  394.                         CurrentByte$ = HEX$(ASC(E$)): IF LEN(CurrentByte$) = 1 THEN CurrentByte$ = "0" + CurrentByte$
  395.                         PRINT CurrentByte$;
  396.                         LOCATE y%, x%: PRINT E$;
  397.                         MID$(PageOfData$, ((y% - 3) * 16 + x% * 1) - 62) = E$
  398.                         IF x% < 78 THEN x% = x% + 1: leftx% = leftx% + 3 'skip space
  399.                     END IF
  400.             END SELECT
  401.         END IF
  402.     LOOP UNTIL E$ <> ""
  403.     LOCATE y%, x%
  404. LOOP UNTIL E$ = CHR$(27)
  405.  
  406. '==========================================================================
  407. SaveChanges:
  408. '===========
  409.  
  410. IF changes% = 1 THEN
  411.     SOUND 4500, .2: COLOR 15, 4: LOCATE , , 0
  412.     LOCATE 10, 29: PRINT CHR$(201); STRING$(21, 205); CHR$(187);
  413.     LOCATE 11, 29: PRINT CHR$(186); " Save Changes (Y/N)? "; CHR$(186);
  414.     LOCATE 12, 29: PRINT CHR$(200); STRING$(21, 205); CHR$(188);
  415.     N$ = INPUT$(1): COLOR 15, 1
  416.     IF UCASE$(N$) = "Y" THEN
  417.         IF PageFlag% = 1 THEN PageOfData$ = LEFT$(PageOfData$, PageLimit%)
  418.         PUT #7, ByteLocation&, PageOfData$:
  419.     END IF
  420. COLOR 15, 1: CLS: LOCATE 1, 1, 0
  421.  
  422.  
  423. '==========================================================================
  424. EditLeftSide: 'Editing Left side info in dual pane mode
  425. '===========
  426.  
  427. COLOR 1, 7
  428. x% = 15: 'y% = 3
  429. rightx% = 63
  430.  
  431. test% = POS(0)
  432. IF test% = 63 THEN x% = 15: rightx% = 63
  433. IF test% = 64 THEN x% = 18: rightx% = 64
  434. IF test% = 65 THEN x% = 21: rightx% = 65
  435. IF test% = 66 THEN x% = 24: rightx% = 66
  436. IF test% = 67 THEN x% = 27: rightx% = 67
  437. IF test% = 68 THEN x% = 30: rightx% = 68
  438. IF test% = 69 THEN x% = 33: rightx% = 69
  439. IF test% = 70 THEN x% = 36: rightx% = 70
  440. IF test% = 71 THEN x% = 39: rightx% = 71
  441. IF test% = 72 THEN x% = 42: rightx% = 72
  442. IF test% = 73 THEN x% = 45: rightx% = 73
  443. IF test% = 74 THEN x% = 48: rightx% = 74
  444. IF test% = 75 THEN x% = 51: rightx% = 75
  445. IF test% = 76 THEN x% = 54: rightx% = 76
  446. IF test% = 77 THEN x% = 57: rightx% = 77
  447. IF test% = 78 THEN x% = 60: rightx% = 78
  448.  
  449. GOSUB DrawEditBar:
  450.  
  451. LOCATE y%, x%, 1, 1, 30
  452.  
  453.     DO
  454.         E$ = INKEY$
  455.         IF E$ <> "" THEN
  456.             SELECT CASE E$
  457.                 CASE CHR$(9)
  458.                     IF Pane% = 1 THEN
  459.                         Pane% = 2: GOTO EditLeftSide
  460.                     ELSE
  461.                         Pane% = 1: GOTO EditRightSide
  462.                     END IF
  463.                 CASE CHR$(27): EXIT DO
  464.                 CASE CHR$(0) + CHR$(72): IF y% > 3 THEN y% = y% - 1
  465.                 CASE CHR$(0) + CHR$(80): IF y% < 25 THEN y% = y% + 1
  466.                 CASE CHR$(0) + CHR$(75) 'right arrow....
  467.                     IF x% > 15 THEN
  468.                         SELECT CASE x%
  469.                             CASE 17, 18, 20, 21, 23, 24, 26, 27, 29, 30, 32, 33, 35, 36, 38, 39, 41, 42, 44, 45, 47, 48, 50, 51, 53, 54, 56, 57, 59, 60, 62, 63
  470.                                 x% = x% - 2
  471.                                 rightx% = rightx% - 1
  472.                             CASE ELSE: x% = x% - 1
  473.                         END SELECT
  474.                     END IF
  475.  
  476.                 CASE CHR$(0) + CHR$(77)
  477.                     IF x% < 61 THEN
  478.                         SELECT CASE x%
  479.                             CASE 16, 17, 19, 20, 22, 23, 25, 26, 28, 29, 31, 32, 34, 35, 37, 38, 40, 41, 43, 44, 46, 47, 49, 50, 52, 53, 55, 56, 58, 59, 61, 62
  480.                                 x% = x% + 2
  481.                                 rightx% = rightx% + 1
  482.                             CASE ELSE: x% = x% + 1
  483.                         END SELECT
  484.                     END IF
  485.  
  486.                 CASE CHR$(0) + CHR$(73), CHR$(0) + CHR$(71): y% = 3
  487.                 CASE CHR$(0) + CHR$(81), CHR$(0) + CHR$(79): y% = 25
  488.                 CASE ELSE
  489.                     IF (ByteLocation& + ((y% - 3) * 16 + rightx% - 1) - 62) <= LOF(7) AND E$ <> CHR$(8) THEN
  490.                         SELECT CASE UCASE$(E$)
  491.                             CASE "A", "B", "C", "D", "E", "F", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"
  492.                                 E$ = UCASE$(E$)
  493.                                 changes% = 1
  494.                                 COLOR 1, 15: LOCATE y%, x%: PRINT " ";
  495.                                 LOCATE y%, x%: PRINT E$;
  496.                                 IF x% < 62 THEN
  497.  
  498.                                     SELECT CASE x%
  499.                                         CASE 16, 17, 19, 20, 22, 23, 25, 26, 28, 29, 31, 32, 34, 35, 37, 38, 40, 41, 43, 44, 46, 47, 49, 50, 52, 53, 55, 56, 58, 59, 61, 62
  500.                                             e2$ = CHR$(VAL("&H" + CHR$(SCREEN(y%, x% - 1)) + CHR$(SCREEN(y%, x%))))
  501.                                             'reflect changes on right panel
  502.                                             COLOR 1, 15: LOCATE y%, rightx%: PRINT " ";
  503.                                             LOCATE y%, rightx%: PRINT e2$;
  504.                                             MID$(PageOfData$, ((y% - 3) * 16 + rightx% * 1) - 62) = e2$
  505.                                             'dont advance cursor if at last place
  506.                                             IF x% < 61 THEN
  507.                                                 rightx% = rightx% + 1
  508.                                                 x% = x% + 2
  509.                                             END IF
  510.                                         CASE ELSE: x% = x% + 1
  511.                                     END SELECT
  512.                                 END IF
  513.                         END SELECT
  514.  
  515.                     END IF
  516.             END SELECT
  517.         END IF
  518.     LOOP UNTIL E$ <> ""
  519.     LOCATE y%, x%
  520. LOOP UNTIL E$ = CHR$(27)
  521.  
  522. GOTO SaveChanges:
  523.  
  524.  
  525. '==========================================================================
  526. EditFullView: 'Editing file in full display mode (one pane)
  527. '===========
  528.  
  529. COLOR 1, 7
  530. x% = 1: y% = 3
  531. changes% = 0
  532.  
  533. GOSUB DrawEditBar
  534.  
  535. LOCATE 3, 1, 1, 1, 30
  536.  
  537.     DO
  538.         E$ = INKEY$
  539.         IF E$ <> "" THEN
  540.             SELECT CASE E$
  541.                 CASE CHR$(27): EXIT DO
  542.                 CASE CHR$(0) + CHR$(72): IF y% > 3 THEN y% = y% - 1
  543.                 CASE CHR$(0) + CHR$(80): IF y% < 25 THEN y% = y% + 1
  544.                 CASE CHR$(0) + CHR$(75): IF x% > 1 THEN x% = x% - 1
  545.                 CASE CHR$(0) + CHR$(77): IF x% < 79 THEN x% = x% + 1
  546.                 CASE CHR$(0) + CHR$(73), CHR$(0) + CHR$(71): y% = 3
  547.                 CASE CHR$(0) + CHR$(81), CHR$(0) + CHR$(79): y% = 25
  548.                 CASE ELSE
  549.                     IF (ByteLocation& + (y% - 3) * 79 + x% - 1) <= LOF(7) AND E$ <> CHR$(8) THEN
  550.                         changes% = 1
  551.                         'new color for changed bytes
  552.                         COLOR 1, 15: LOCATE y%, x%: PRINT " ";
  553.                         LOCATE y%, x%: PRINT E$;
  554.                         MID$(PageOfData$, (y% - 3) * 79 + x% * 1) = E$
  555.                         IF x% < 79 THEN x% = x% + 1
  556.                     END IF
  557.             END SELECT
  558.         END IF
  559.     LOOP UNTIL E$ <> ""
  560.     GOSUB DrawEditBar
  561.     LOCATE y%, x%
  562. LOOP UNTIL E$ = CHR$(27)
  563.  
  564. GOTO SaveChanges:
  565.  
  566. '==========================================================================
  567. DrawEditBar:
  568. '===========
  569.  
  570. IF DisplayView% = 1 THEN
  571.     LOCATE 1, 1:
  572.     COLOR 31, 4: PRINT "  EDIT MODE: ";
  573.     COLOR 15, 4
  574.     PRINT " Press TAB to switch editing sides "; CHR$(179); " Arrows move cursor "; CHR$(179); " ESC=Exit ";
  575.     LOCATE 1, 1
  576.     COLOR 31, 4: PRINT " EDIT MODE ";
  577.     COLOR 15, 4
  578.     PRINT CHR$(179); " Arrows move cursor "; CHR$(179); " ESC=Exit "; CHR$(179);
  579.     LOCATE 1, 45: PRINT STRING$(35, " ");
  580.  
  581.     LOCATE 1, 46
  582.     CurrentByte& = ByteLocation& + (y% - 3) * 79 + x% - 1
  583.     CurrentValue% = ASC(MID$(PageOfData$, (y% - 3) * 79 + x% * 1, 1))
  584.     IF CurrentByte& > LOF(7) THEN
  585.         PRINT SPACE$(9); "PAST END OF FILE";
  586.     ELSE
  587.         PRINT "Byte:"; LTRIM$(STR$(CurrentByte&));
  588.         PRINT ", ASC:"; LTRIM$(STR$(CurrentValue%));
  589.         PRINT ", HEX:"; RTRIM$(HEX$(CurrentValue%));
  590.     END IF
  591.  
  592. '==========================================================================
  593. DrawTopBar:
  594. '============
  595.  
  596. COLOR 1, 15
  597. LOCATE 1, 1: PRINT STRING$(80, 32);
  598. LOCATE 2, 1: PRINT STRING$(80, 32);
  599.  
  600. LOCATE 1, 1
  601. IF Filter% = 1 THEN
  602.     COLOR 30, 4: PRINT "F";: COLOR 1, 15
  603.     PRINT " ";
  604.  
  605. PRINT "FILE: "; File$;
  606.  
  607. LOCATE 2, 2:
  608. PRINT "Total Bytes:"; LOF(7);
  609. EC& = ByteLocation& + BufferSize%: IF EC& > LOF(7) THEN EC& = LOF(7)
  610. PRINT CHR$(179); " Viewing Bytes:"; RTRIM$(STR$(ByteLocation&)); "-"; LTRIM$(STR$(EC&));
  611. LOCATE 1, 71: PRINT " M = Menu";
  612. COLOR 15, 1
  613. 'Draw bar on right side of screen
  614. FOR d% = 3 TO 25
  615.     LOCATE d%, 80: PRINT CHR$(176);
  616.  
  617. IF DisplayView% = 1 THEN
  618.     'Draw lines down screen
  619.     FOR d% = 3 TO 25
  620.         LOCATE d%, 79: PRINT CHR$(179);
  621.         LOCATE d%, 62: PRINT CHR$(179);
  622.         'add space around numbers...
  623.         '(full screen messes it...)
  624.         LOCATE d%, 13: PRINT " " + CHR$(179);
  625.         LOCATE d%, 1: PRINT CHR$(179) + " ";
  626.     NEXT
  627.  
  628.     'Draw location
  629.     FOR d% = 3 TO 25
  630.         LOCATE d%, 3
  631.         nm$ = HEX$(ByteLocation& - 32 + (d% * 16))
  632.         IF LEN(nm$) = 9 THEN nm$ = "0" + nm$
  633.         IF LEN(nm$) = 8 THEN nm$ = "00" + nm$
  634.         IF LEN(nm$) = 7 THEN nm$ = "000" + nm$
  635.         IF LEN(nm$) = 6 THEN nm$ = "0000" + nm$
  636.         IF LEN(nm$) = 5 THEN nm$ = "00000" + nm$
  637.         IF LEN(nm$) = 4 THEN nm$ = "000000" + nm$
  638.         IF LEN(nm$) = 3 THEN nm$ = "0000000" + nm$
  639.         IF LEN(nm$) = 2 THEN nm$ = "00000000" + nm$
  640.         IF LEN(nm$) = 1 THEN nm$ = "000000000" + nm$
  641.         PRINT nm$;
  642.     NEXT
  643.  
  644. Marker% = CINT(ByteLocation& / LOF(7) * 22)
  645. LOCATE Marker% + 3, 80: PRINT CHR$(178);
  646.  
  647. '==========================================================================
  648. Menu:
  649. '========
  650.  
  651. SOUND 4500, .2: COLOR 15, 0: LOCATE , , 0
  652. LOCATE 5, 24: PRINT CHR$(201); STRING$(34, 205); CHR$(187);
  653. FOR m = 6 TO 20
  654.     LOCATE m, 24: PRINT CHR$(186); SPACE$(34); CHR$(186);
  655. LOCATE 21, 24: PRINT CHR$(200); STRING$(34, 205); CHR$(188);
  656.  
  657. LOCATE 6, 26: PRINT "Use the arrow keys, page up/down";
  658. LOCATE 7, 26: PRINT "and Home/End keys to navigate.";
  659. LOCATE 9, 26: PRINT "E = Enter into file editing mode";
  660. LOCATE 10, 26: PRINT "F = Toggles the filter ON or OFF";
  661. LOCATE 11, 26: PRINT "G = Goto a certain byte position";
  662. LOCATE 12, 26: PRINT "L = Goto a certain HEX location";
  663. LOCATE 13, 26: PRINT "S = Searches for string in file";
  664. LOCATE 14, 26: PRINT "N = Find next match after search";
  665. LOCATE 16, 26: PRINT "ENTER = Toggle HEX/ASCII modes";
  666. LOCATE 17, 26: PRINT "TAB   = switch window (HEX mode)";
  667. LOCATE 18, 26: PRINT "ESC   = EXITS this program";
  668. LOCATE 20, 26: PRINT "ALT+ENTER for full screen window";
  669. Pause$ = INPUT$(1)
  670. COLOR 15, 1: CLS: LOCATE 1, 1, 0
  671.  
  672.  
  673. '==========================================================================
  674. '                           FUNCTIONS/SUBS
  675. '==========================================================================
  676.  
  677. FUNCTION FileSelect$ (y, x, y2, x2, Filespec$)
  678.  
  679.  
  680.     '=== save original place of cursor
  681.     origy = CSRLIN
  682.     origx = POS(1)
  683.  
  684.     '=== save colors
  685.     fg& = _DEFAULTCOLOR
  686.     bg& = _BACKGROUNDCOLOR
  687.  
  688.     '=== Save whole screen
  689.     DIM scr1 AS _MEM, scr2 AS _MEM
  690.     scr1 = _MEMIMAGE(0): scr2 = _MEMNEW(scr1.SIZE)
  691.     _MEMCOPY scr1, scr1.OFFSET, scr1.SIZE TO scr2, scr2.OFFSET
  692.  
  693.     '=== Generate a unique temp filename to use based on date + timer
  694.     tmp$ = "_qb64_" + DATE$ + "_" + LTRIM$(STR$(INT(TIMER))) + ".tmp"
  695.     IF INSTR(_OS$, "LINUX") THEN tmp$ = "/tmp/" + tmp$
  696.  
  697.     loadagain:
  698.  
  699.     top = 0
  700.     selection = 0
  701.  
  702.     '=== list directories
  703.     IF INSTR(_OS$, "LINUX") THEN
  704.         SHELL _HIDE "find . -maxdepth 1 -type d > " + tmp$
  705.     ELSE
  706.         SHELL _HIDE "dir /b /A:D > " + tmp$
  707.     END IF
  708.  
  709.     '=== make room for names
  710.     REDIM FileNames$(10000) 'space for 10000 filenames
  711.  
  712.     '=== only show the ".." when not at root dir
  713.     IF LEN(_CWD$) <> 3 THEN
  714.         FileNames$(0) = ".."
  715.         LineCount = 1
  716.     ELSE
  717.         LineCount = 0
  718.     END IF
  719.  
  720.     '=== Open temp file
  721.     FF = FREEFILE
  722.     OPEN tmp$ FOR INPUT AS #FF
  723.  
  724.     WHILE ((LineCount < UBOUND(FileNames$)) AND (NOT EOF(FF)))
  725.         LINE INPUT #FF, rl$
  726.  
  727.         '=== load, ignoring the . entry added under Linux
  728.         IF rl$ <> "." THEN
  729.  
  730.             'also remove the ./ added at the beginning when under linux
  731.             IF INSTR(_OS$, "LINUX") THEN
  732.                 IF LEFT$(rl$, 2) = "./" THEN
  733.                     rl$ = RIGHT$(rl$, LEN(rl$) - 2)
  734.                 END IF
  735.             END IF
  736.  
  737.             FileNames$(LineCount) = "[" + rl$ + "]"
  738.             LineCount = LineCount + 1
  739.  
  740.         END IF
  741.     WEND
  742.  
  743.     CLOSE #FF
  744.  
  745.     '=== now grab list of files...
  746.     IF INSTR(_OS$, "LINUX") THEN
  747.         SHELL _HIDE "rm " + tmp$
  748.         IF Filespec$ = "*.*" THEN Filespec$ = ""
  749.         SHELL _HIDE "find -maxdepth 1 -type f -name '" + Filespec$ + "*' > " + tmp$
  750.     ELSE
  751.         SHELL _HIDE "del " + tmp$
  752.         SHELL _HIDE "dir /b /A:-D " + Filespec$ + " > " + tmp$
  753.     END IF
  754.  
  755.     '=== open temp file
  756.     FF = FREEFILE
  757.     OPEN tmp$ FOR INPUT AS #FF
  758.  
  759.     WHILE ((LineCount < UBOUND(FileNames$)) AND (NOT EOF(FF)))
  760.  
  761.         LINE INPUT #FF, rl$
  762.  
  763.         '=== load, ignoring the generated temp file...
  764.         IF rl$ <> tmp$ THEN
  765.  
  766.             'also remove the ./ added at the beginning when under linux
  767.             IF INSTR(_OS$, "LINUX") THEN
  768.                 IF LEFT$(rl$, 2) = "./" THEN
  769.                     rl$ = RIGHT$(rl$, LEN(rl$) - 2)
  770.                 END IF
  771.             END IF
  772.  
  773.             FileNames$(LineCount) = rl$
  774.             LineCount = LineCount + 1
  775.         END IF
  776.  
  777.     WEND
  778.     CLOSE #FF
  779.  
  780.     '=== Remove the temp file created
  781.     IF INSTR(_OS$, "LINUX") THEN
  782.         SHELL _HIDE "rm " + tmp$
  783.     ELSE
  784.         SHELL _HIDE "del " + tmp$
  785.     END IF
  786.  
  787.  
  788.     '=== draw a box
  789.     COLOR _RGB(100, 100, 255)
  790.     FOR l = 0 TO y2 + 1
  791.         LOCATE y + l, x: PRINT STRING$(x2 + 4, CHR$(219));
  792.     NEXT
  793.  
  794.     '=== show current working dir at top
  795.     COLOR _RGB(255, 255, 255), _RGB(100, 100, 255)
  796.     CurDir$ = _CWD$
  797.     '=== Shorten it is too long, for display purposes
  798.     IF LEN(CurDir$) > x2 - x THEN
  799.         CurDir$ = MID$(CurDir$, 1, x2 - x - 3) + "..."
  800.     END IF
  801.     LOCATE y, x + 2: PRINT CurDir$;
  802.  
  803.     '=== scroll through list...
  804.     DO
  805.  
  806.         FOR l = 0 TO (y2 - 1)
  807.  
  808.             LOCATE (y + 1) + l, (x + 2)
  809.             IF l + top = selection THEN
  810.                 COLOR _RGB(0, 0, 64), _RGB(255, 255, 255) 'selected line
  811.             ELSE
  812.                 COLOR _RGB(255, 255, 255), _RGB(0, 0, 64) 'regular
  813.                 '=== directories get a different color...
  814.                 IF MID$(FileNames$(top + l), 1, 1) = "[" THEN
  815.                     COLOR _RGB(255, 255, 0), _RGB(0, 0, 64)
  816.                 END IF
  817.             END IF
  818.  
  819.             PRINT LEFT$(FileNames$(top + l) + STRING$(x2, " "), x2);
  820.  
  821.         NEXT
  822.  
  823.         '=== Get user input
  824.  
  825.         k$ = INKEY$
  826.         SELECT CASE k$
  827.  
  828.             CASE IS = CHR$(0) + CHR$(72) 'Up arrow
  829.                 IF selection > 0 THEN selection = selection - 1
  830.                 IF selection < top THEN top = selection
  831.  
  832.             CASE IS = CHR$(0) + CHR$(80) 'Down Arrow
  833.                 IF selection < (LineCount - 1) THEN selection = selection + 1
  834.                 IF selection > (top + (y2 - 2)) THEN top = selection - y2 + 1
  835.  
  836.             CASE IS = CHR$(0) + CHR$(73) 'Page up
  837.                 top = top - y2
  838.                 selection = selection - y2
  839.                 IF top < 0 THEN top = 0
  840.                 IF selection < 0 THEN selection = 0
  841.  
  842.             CASE IS = CHR$(0) + CHR$(81) 'Page Down
  843.                 top = top + y2
  844.                 selection = selection + y2
  845.                 IF top >= LineCount - y2 THEN top = LineCount - y2
  846.                 IF top < 0 THEN top = 0
  847.                 IF selection >= LineCount THEN selection = LineCount - 1
  848.  
  849.             CASE IS = CHR$(0) + CHR$(71) 'Home
  850.                 top = 0: selection = 0
  851.  
  852.             CASE IS = CHR$(0) + CHR$(79) 'End
  853.                 selection = LineCount - 1
  854.                 top = selection - y2 + 1
  855.                 IF top < 0 THEN top = 0
  856.  
  857.             CASE IS = CHR$(27) ' ESC cancels
  858.                 FileSelect$ = ""
  859.                 EXIT DO
  860.  
  861.             CASE IS = CHR$(13) 'Enter
  862.                 '=== if .. then go up one dir
  863.                 IF RTRIM$(FileNames$(selection)) = ".." THEN
  864.                     cd$ = _CWD$
  865.                     IF INSTR(_OS$, "LINUX") THEN
  866.                         cd$ = LEFT$(cd$, _INSTRREV(cd$, "/"))
  867.                     ELSE
  868.                         cd$ = LEFT$(cd$, _INSTRREV(cd$, "\"))
  869.                     END IF
  870.                     CHDIR cd$
  871.                     ERASE FileNames$
  872.                     GOTO loadagain
  873.                 END IF
  874.  
  875.                 'see if directory
  876.                 test$ = RTRIM$(FileNames$(selection))
  877.                 IF LEFT$(test$, 1) = "[" THEN
  878.                     test$ = MID$(test$, 2, LEN(test$) - 2)
  879.                     CHDIR test$
  880.                     ERASE FileNames$
  881.                     GOTO loadagain
  882.                 ELSE
  883.                     IF INSTR(_OS$, "LINUX") THEN
  884.                         IF RIGHT$(_CWD$, 1) = "/" THEN
  885.                             C$ = _CWD$
  886.                         ELSE
  887.                             C$ = _CWD$ + "/"
  888.                         END IF
  889.                     ELSE
  890.                         IF RIGHT$(_CWD$, 1) = "\" THEN
  891.                             C$ = _CWD$
  892.                         ELSE
  893.                             C$ = _CWD$ + "\"
  894.                         END IF
  895.                     END IF
  896.  
  897.                     FileSelect$ = C$ + RTRIM$(FileNames$(selection))
  898.                     EXIT DO
  899.  
  900.                 END IF
  901.  
  902.         END SELECT
  903.  
  904.     LOOP
  905.  
  906.     _KEYCLEAR
  907.  
  908.     '=== Restore the whole screen
  909.     _MEMCOPY scr2, scr2.OFFSET, scr2.SIZE TO scr1, scr1.OFFSET
  910.     _MEMFREE scr1: _MEMFREE scr2
  911.  
  912.     '=== restore original y,x and color
  913.     LOCATE origy, origx
  914.  
  915.     COLOR fg&, bg&
  916.  
  917.  
  918.  
  919. SUB FONT (size)
  920.     'load/set built-in CP437 font
  921.     A$ = ""
  922.     A$ = A$ + "haIgm]0MLEMMXkS^ST\\T]lHiaboe<Nl8c71HYa3f0VPiWa9H07n5a_0bn:K"
  923.     A$ = A$ + ";#FB8;c773hBD8T42E_#C:=QBC39PSQB=DB2UhdhVBB^9=_D2EQ#Ala?JFmi"
  924.     A$ = A$ + "ejeGKNiYTV4\UNkOWcmL791Y0Iefg<NdmNWiLfWmIoO_?WkeP10H6`NP0HS["
  925.     A$ = A$ + "KMGj5l9Nf7lH0HC;3of5MAGb9ef>>V6V60Vfa[_^=_m>j[Y]NOC7PDY`?kKc"
  926.     A$ = A$ + "gd0IQB1o20VfnaO?eFkH7m=nh8TP=]8ljY]e^_e]DhRj<;0CoG1`5>lfj\S`"
  927.     A$ = A$ + "IOn5Z6o]G6oLbK3oRZONcW6QoL`[Gfffn0gBQ5]P_=NmC3#5__^kMcMlg=[o"
  928.     A$ = A$ + "a=RPjY`[?W]ga]dWICVEPonZafW]W>fNWObWOGk3P[h7POg7[_Nga07oM<8f"
  929.     A$ = A$ + "f[2agZnF0=g`?kjkmmOT[]nel;PVZJ]hg0?OKcLadaGiKoLOB06[_P\Y8lOJ"
  930.     A$ = A$ + "#5Pl2kCZm?FO04TU^4o[1Bn:5m=VLhOH8jj9mj4UF4Te<4D9R7[U6eP\fS#H"
  931.     A$ = A$ + "5]c]X6G?2l1mUORGl9Rl3CcgPP3Yf?27leNXQi017VViP9PXlI5<D`Bg[8lC"
  932.     A$ = A$ + "8OFXkk2MW7jMNL?lKIT21l_VF:3>F2D;LOV8TRaP9n:<aIA^f=aF7iJaK2<#"
  933.     A$ = A$ + "L8<Ak3Q9<_mJcKe[TDPTc\936fA:ngRlXaf?Q:5<^GQ:NaoU>Jo437Vj6iV1"
  934.     A$ = A$ + "CjiCm;DJYL^oDO^mEPnIARTN`G4_b`GW:h^aS?8:nE5\4h>P72nB`S0?6lT`"
  935.     A$ = A$ + "G3n6`g4n^`g3nA`;PJd_>l_2S2oK`APa=OZPk;hn3NXP7>h;7l41OUP36l\1"
  936.     A$ = A$ + "OW\;=kJbN7IOTLOjLkMY;HY=]dSMY[OYM\d>cGAnIU?G1X#55Z[`\:<W2c[`"
  937.     A$ = A$ + "R:\\2]DHU5FCQ^;\W23Fh^;L?5^_2On2?FQW\`cDh05Nf2o]5n7JN==_fV?["
  938.     A$ = A$ + "V_^VgLcKYiK0]l#_nl<n]?Ho`G1N64oNF7nmJ`?5no0oBhG?1lkY#lk_a3o6"
  939.     A$ = A$ + "2a_i_dUXhG8SOIW2lKS>lKXb`_G\iCeQOMfleChgho?6o#SoJSo:SoBSoRSo"
  940.     A$ = A$ + "2SoS7o7=nc=ngKl_mh7LloZao6SOPaojSo<SodSglAKnX;mXckXcmXciXchX"
  941.     A$ = A$ + "eNDcA6o8SMX7j#Ol3]n3Uke>UGKi_jGkEOZGmAOe?i[^cGM7_b?iEnn_bGOT"
  942.     A$ = A$ + "GITGNTonAN^An_?bgOT_k87LTobANbANdA^oAn8SLWSL7S\kA^eAfn8KJT[I"
  943.     A$ = A$ + "T;OT;KT;LTe?bJNYGnUn7NYGlUnj_dOi;md_dG1if?hKUTeoQnbPBTY#kYE1"
  944.     A$ = A$ + "ESFZ[1V>D;D7jiJVX]gjQI1YQI3=0c1b0c5J4V7<OH1`2Aig5SB]=QF<c1;5"
  945.     A$ = A$ + "b3;3:0=3;7>6hHQS3>NX5h4#keW4\2XEX=X8\BX4Lb`ZPE3W2LZ`Y1[1>Mhm"
  946.     A$ = A$ + "0W1JUo<Qc2>KhLPc5F7LN`jQg;lnPc7f0L1`52G4\Ahm3G<L9`U2G6Li`70J"
  947.     A$ = A$ + "7^2h:Q[2^JhJP?8L]`e1M0K2f<Zke9\5H[`fP^P[7^1XKHk#?#_#O`=2m3k0"
  948.     A$ = A$ + "60f9LC`=3g2L[`^P?4\KhfPK7ejf3B0Z2o4TZbZZNJe<mJ[K6c\RjWEjIg`L"
  949.     A$ = A$ + "b<g6WglG`2GdRGBCIc]dl;[#c;oH>fSkhKi4>aCJ5]fFaEFjTGeZ?UCmdFcY"
  950.     A$ = A$ + "oN>SeNVWeIO>Wkj>_eoNOOWo6^P;lRfhkoR_T;mb^l?#kGaENEGmel1_f[[S"
  951.     A$ = A$ + "=]i`>gbFgFGGo=dmfkYgn^anga0klV^iKiFge7Jggf]O7kiCoI^ooX?kWk1n"
  952.     A$ = A$ + "CN`?oO:l5nR?lGjAfknnb?jSmWmWohko9PWj_h[lEQ?n7N`kjKO_oa2;k?4N"
  953.     A$ = A$ + "n?a?i5o8X?Fh_6nX3m=N8h?h>oHoXWn73gmo=hgcSeBVBdGon_Ub1Ll68O[5"
  954.     A$ = A$ + "Tn_7d>d?4niViJ>Ec5J^NcmJN6coD5c\REDAgEL?ElHEllElc2VE`E7\]P?E"
  955.     A$ = A$ + "`S5lM2NmD#ZIUJUYf#Z#lmNBMoYNfDoZ:?V:_^:k_bQZlaZliZlWFi_\Z:ZJ"
  956.     A$ = A$ + "VEeFEQE][ZfKE?GEoZZWGe[Yj[^jk^j7_j3Fm;<]:VfLWfI=]]<]kJJ?nd6N"
  957.     A$ = A$ + "JSECfJFG=K[Vk_VmGcgYV3=mY=mU>me>m?hdgedo\Co_Jj_N]cZfFZm\Z=\f"
  958.     A$ = A$ + "k\f7_fOH]7Y^IFg:[KMe]Ujj_^1[K_emm[k`cX^I\RILYcHgch1VaGM63?SO"
  959.     A$ = A$ + "c<Wi<?^I^^I^YINGcLOc<JVobjWKm]Eo6Zoj[ocDoG]nG]naVe\Ve9>[e?[^"
  960.     A$ = A$ + "aggm\NlIm2YQdK8MgYO`d?NjXd_n\[JfIWmJWm5>knVmGHf_D3;ZQef`0=lH"
  961.     A$ = A$ + "=llcYZidfLfdL^WilhcIh<EUIeIj9c3TIhi2cmHVkE>g?nL?hLoI=>k6GISG"
  962.     A$ = A$ + "ISkZamfhcghAVga=_;MNM?_?cl>hlnGVoLWoI=o]=oM=om=oGL1YF`:F#k;h"
  963.     A$ = A$ + ">G`3_P3\PGL1S^`U^`CNQGj2kKQ?h2?`2OQ5ncGDM;J5;jbGdNFdm^Xm]XO`"
  964.     A$ = A$ + "RNi5mcGlBFlZGLhR_g5oT;nK]hGLao;;ng\TY]Ti]TSI9WjBf`B^^U<`B^[U"
  965.     A$ = A$ + "lIGbC]TXUlB;iWeDE=U]YEfdjKjjJjVJjNJjQKj0=ml=m?W=Ef5UmmTmbcfG"
  966.     A$ = A$ + "fk=k3Wm0IOi\obLc<g9VKSij;g3TKOiNjLOWL3WkeGj3^\Y]\WJIO[Um3Gfo"
  967.     A$ = A$ + "DQZ:\T2_W2KZ`]GHO5>DceeljK^_VOPV?HcodUGeb?^U_nUOmXESBXnd[Vjh"
  968.     A$ = A$ + "#k:E3WhCHPCJ=?IeYPog]m4EEi;_VW<X2lDh92X_^Bj[ObZ[bLTelT6jk;V>"
  969.     A$ = A$ + "Gj2iBW[Ti;?fmH>San[CML_a;D:hPP69H#F<>]JAkB#YRUX6W;Mn<i<I:F:4"
  970.     A$ = A$ + "SnK\n27KHc#AAQELPa6nXk=<H`#fYLe^n6`m^1dBf2A[G#Yd5Cg#YLIbW9OY"
  971.     A$ = A$ + "PB5cT;OYR=T?MAC^<iBSOOHXIX`8l_]4B7>jiDAk7M_EdNH#fSL8jkTO1oNj"
  972.     A$ = A$ + ";TQ;U7N:S3=:8\:BXJY6bD4afRU:D\Dn:;U?3RfHog;1N4mYQ31NH82=nLNH"
  973.     A$ = A$ + "i917o06WJF4V`l=8<b`O#Xb_;A_aFc]WA<Yo4DE#``8TQ1REY9BH966lk4`a"
  974.     A$ = A$ + "oU0WhGalR1AJY5K4h#<Td1jE4b4=f`AdTPR9S>1I#]<f`S=L8bUdHR8h<5h3"
  975.     A$ = A$ + "bA`_QaW8QHPCW8T5;H2?KIhPa_EAkHloe2#1J28P9_ID^1J39lFc:9PTQV_9"
  976.     A$ = A$ + "GJS`>`nT9O#FTA49SBE[mGO`:>0gIJn6Bd]:>02OLn^ZHniYkgOQDAH8?Rj5"
  977.     A$ = A$ + ":CTWZ96o5ZH0=7CWWT2CgPRg4KP`678laZf]SS:EZl3>76[D]B;AXVVA]<5E"
  978.     A$ = A$ + "i_CcT>O2^:Q^Af[6[_8ETQc=RVg2LIiHBc#Whi]H9=8[2oV85RAd;jPIdHT?"
  979.     A$ = A$ + ":D08RWSo0\^1Y32\6<2UdjARBPTIJVRb7\43ZG]KFDnXWCH`QYiJE>IV0E;>"
  980.     A$ = A$ + "?6g1#<RUc65`g2bQBRi;QOG63nQd^[4IE4f55ZoQ\E4=FMAR#29HBcND2U^d"
  981.     A$ = A$ + "Z>jYkPdRDKPT0J=]E:eCc1O;<KFj<e6BXbT\o>IM6S5M>jMDLG<S:7OSWBPP"
  982.     A$ = A$ + "AT1IN<\:R`W>_Wn2B4EmGNfa2<j7a#5=a\cUD>n:ISV]W^:\kXNLj6eS2STN"
  983.     A$ = A$ + "IJYR3PDOmXWMhIPa62iHb<=58I3\SXL[P1H[AcJ13NTMSC5478iE#U1Hj#A<"
  984.     A$ = A$ + "n?XEbZ[Kn[ZBUHa\<iiojK=P>R>7\:LT=6QII9IATTSNiHeIWiFM`9LQdi8?"
  985.     A$ = A$ + "n3:V6#lgLYYc7[?V^;dZVNcXkRUZTdnS^g9BnEI1;<A:O39PFndZfN4ImQNQ"
  986.     A$ = A$ + ">M>#imIEZL^eRMXXd5BNn#NU_<K4KgZ1BVSXcNB\hX:NgHkcN6i;_O2nQDn<"
  987.     A$ = A$ + "2GQ\7CmP]dUXSNSIkD=J8o[i#NdXXZ6>oCRCaflcD<1NYc9oGZ]5WnU__\jI"
  988.     A$ = A$ + "]o4n>L\IA782:[mY5On>oMFJM5]K=OQbYH_ZXMKl6=TFmfVVD?bTGlXPLYf9"
  989.     A$ = A$ + "n;iA3=OdG4KcTVMXlMUTgX6HeK3KcT=b#n^B]1TdaVKR]M?XHknd=ZlUBCDi"
  990.     A$ = A$ + ";VVD`:MXl<AfWn3Qd\?EbD>2GIn>nZAlHoF[SX4:6HEndNBK\o1[1MQVCc2;"
  991.     A$ = A$ + "UV2VBXgReMNTHCS3[^=0]6KJ<5T]H`gdF9OSST9IbJLa<iC`KYiADTcU^SA`"
  992.     A$ = A$ + "TC?OK5`L;EOK>;4TVG9U:EB=3aF84KaR^WXB:aN8RBjg8fhKQ?#SX8O6BJn8"
  993.     A$ = A$ + "o3SJd`Z9HlPTNB45H6K3chT=J#R6#WXY]DE;la>A^[U8l\j7Nm=fnOa<fHiR"
  994.     A$ = A$ + "B#6\MFdK2b6[gTGUA4Ga5EI4a6ThQ;:JBRMS\S4YabDN\Bj;=f\XaO0d9N;4"
  995.     A$ = A$ + "M8W#6BCB_ZWBEGf<4B]6UT28M:RbAh:Gk]AaI:nm5`n:`f;6f5nV;WDVlAR3"
  996.     A$ = A$ + "NbL4=DTiHN#>7=T\dMJDJ15U`OJ0AO[dPe>\85hcN4j]8fiI_M6<ObJe7iaF"
  997.     A$ = A$ + "?[LOahCLc[3ChB[YSWF<Mc9Y:_Ao4Rm9:bH[GND3`9[6;kh5gQhgWdS9]HB["
  998.     A$ = A$ + "EQ<>OU8kR8^2ma2eaZ;dZf6JeI3mdWbT8ZKNV9J?5C_lRUD^P6?HTed53FR4"
  999.     A$ = A$ + "bfNBPO=h`_dDjCil`[j`4bZSS7D`941W8n#I;ihT<UBQ#A4H<9:D11KjD\IK"
  1000.     A$ = A$ + "CK:9N8aCb^CUY62#^mA2M?h`D_`8B6RW8#IbD^\fR3h=6C:aHC<=fBf]TJMR"
  1001.     A$ = A$ + "aGU`nE3fLUbiTB9J]>oHhaad[n64?;RgLl<2HE#eMg<:Zo#a]AJ_\HYXMaVA"
  1002.     A$ = A$ + "1a_5gVZI=l<R2>g^Q4S2BhiAabh3Bb]=<1EAG\G9R?e575ORE0>QAV:Xjccf"
  1003.     A$ = A$ + "HHlTb`f#IC;I?c6QKaJ;b=n[bUcR6;h4S_f5OLBLXlQ_LJNjHM#EP8GV68_#"
  1004.     A$ = A$ + "<b;ncXh]TT\h`oY\2RU]7TcF9>[?j<B6_431DNRlDRR2T869A<D4afBR7;dc"
  1005.     A$ = A$ + "b#6eJOjLH2PfL7UiShS:<>h?:<;>=f4bXB=<XXWi<7]BX5Hi1:3?a^6RJ43W"
  1006.     A$ = A$ + "LLEVHYWnBCnf?c;XCJ9]fRZ]DK0Haf3Hh7I=M69fU[`3ola>ENOiZmH[DS`l"
  1007.     A$ = A$ + "8TC=0S0=Ym>52B6BYe^[Zd2AbI_413IFRVVb<5MA53[6WBHUa3>C4:ncYi3i"
  1008.     A$ = A$ + "V2:5CSZ<_0N?J5IDHD^#0UA_TX>Z;9OXFF21=MaB6YiXR6KHbDUIXS<?cXff"
  1009.     A$ = A$ + "77G:DXHLa38KZ^DF9RZ?\[GR5gFW1f^LT]L5Te6KAWVLj_TG][>2<UcEE\Hj"
  1010.     A$ = A$ + "_6D[Z4A;bJIhPER8V7ZIPH7NGL5afbeL]U8UBcaYVF\QAmk`dhOTi9EAKZjK"
  1011.     A$ = A$ + "66kE>ObnJJ19]3YM^2?NAm9[KWc6]emS5SY59fG^_QTJU8];CPCSTT]BX?BF"
  1012.     A$ = A$ + "3ULRGM\NClhFTmALJ6>e3[?RQU8HLh#TVhg4\kEVe1JnCYfK]>4iQ;A\_#d?"
  1013.     A$ = A$ + "=S?9RWAlY7WQNIIVKmac\A_<`AjDT4CCTV76?k;;ggdiLa\C#B#<>Ll3`DIb"
  1014.     A$ = A$ + ">:ZNF^NB9[NR<fAdXAEJPnT#6Flh:FcBW\FYNnbdBL4WlLHIbAR^SlfV=VdO"
  1015.     A$ = A$ + "jM`PXIJbSm1`AgEGC;m;^X6IR=ZV?faJ6_8]LJCf8am>9A<Y=`ITJa7;m[TU"
  1016.     A$ = A$ + "#cic`N>XTdEc2`KJLZIbK3Jb6U:[OZ\=eOTee]Omb47XNfUZF\;AaLQN29L8"
  1017.     A$ = A$ + "REflmWbend_6JnE1[\LoU86\HR`MPb6?f:5Vgg#Al<65Z?blHn0Ua4V3LSCB"
  1018.     A$ = A$ + "mUER_ec[eETGL4L>d1I7o18?_I#Z4EK;nkS26d<:2G:7A1DfL4?LHRhfAeB["
  1019.     A$ = A$ + "6=m>CAKVZ<?C2NTC8=RmF8QZGWUhV`Vd<dZhTfYgUF[^#;R27ak36DLPe7Y?"
  1020.     A$ = A$ + "L8V[kS;aaaTAXHR7NEaEeTlBO`GFNnaEFVm98c3Ej;D[4AXjfSWCTbXjFb>?"
  1021.     A$ = A$ + "#L8=ViQ3;RaQ6#b3gjj\XA;RoC6PQZ8\R?];hSHQ[HJ??bJF<FYEE1O8[c:["
  1022.     A$ = A$ + "KM2>T6[T?M6>GjLJlnD1YUZ:8n9UdMdBOd774Th9Pn;kd\<O7=hiiTZZ_Fi8"
  1023.     A$ = A$ + "5SHC6\gBbN;ijQfhBaeKZVh<>Yn;EKR3HHh8NTYEfj`B]A2YiP]F\D6_B<8D"
  1024.     A$ = A$ + "09LMFhj1a>VYBMCZ58;9enSPYd?OiVWV<ole9G`5M:Y^H=naTHS8Y5YKnbQY"
  1025.     A$ = A$ + "iJ\JG1;m=;o#S1K]iXk53iQ<PEWW\CeBekTNYN9C79NJR\4C;9e[O_enceca"
  1026.     A$ = A$ + "Snb6X^;CCe#8\MW4L5:P;S?^j#R81ijcZg53WBU9K9E<V]1H5]2MhQEb:Z<m"
  1027.     A$ = A$ + "g<>In<>INENgYoIS^VC=f[_FOiUVBOiIVJOiClE2ObILfG5m?KV3YSdj7B9\"
  1028.     A$ = A$ + "g^LDP6AW;S_bNIY8NTJKcJNT]P8>aa#m_an1anE?Go]d>Okne2WRHVnT`O^c"
  1029.     A$ = A$ + "6hKRol:JW\1QSmXJIkB#3K=I=kV#]o\nDBh?ggHD\G\HiS6lSYA[<#9=fV#^"
  1030.     A$ = A$ + "d9L`RTL=9FTTnSmOaNeC;?cBCF`YLR4Qc=>VPJDH<bilIi7OQJG=?7m8;gTV"
  1031.     A$ = A$ + "5bRc\9Ai>0Yn4D]7TeERFK8^4:Bm9Xf?DIS1;_`e]Em<Ba065:EffEdIWAKe"
  1032.     A$ = A$ + "O^4kXVE_EB;S8n[A577W09SI[kOSN[=Z6eA1M1B]l6M=SlFMDYD5U_N0NBMU"
  1033.     A$ = A$ + "Bk]N0l2M;QX7<XG<KYfP^^M9[oNJGmF\aSJ3kSeoL:OAnaDP`RigC^[?QPh;"
  1034.     A$ = A$ + "bQPiXk=:Y?`j2C4;NC4o>^Rb^J:cI=8eK?:d?PDFF:bFfN]Z5Jl:oWbeg;PZ"
  1035.     A$ = A$ + "L6SG1RgB^ZD5IG\82RiHUG<``i1aag>Z4mb`\f197IGC\Uk_ZHan:;<A_WUL"
  1036.     A$ = A$ + "f0\cSX9^Q:LB[jJD9[M65YGndELP89V8MmhYO5W3bJBI;[U5o]:;BlflDg]N"
  1037.     A$ = A$ + "]IUml#[L]hdBnShH#FdBP`751^89f0cXHl]K`_2ai;[Ff5ejH7ib8P;CU7?P"
  1038.     A$ = A$ + "SOn1\[iFVBaFL9cCQjRFAa6X6ZSlfK9_MGOI3Y0BKn0:VMS\f3lRBhT1JWU1"
  1039.     A$ = A$ + "ZG\a9b09XR<Z4C9EaP#=7\bT3TEN<^NU4UYQ9\>[5;i4:M[NW_0[_P<SWbJg"
  1040.     A$ = A$ + "]1N=e>N_egLBF\TPd5W_aE3obbMBCV\\U#QH^SEWhL3]<DfhEl]LlX8J;U?N"
  1041.     A$ = A$ + "5hh8I:KLUUWTLEDGi[PSo`kVcCjj08NFMI8`[LHT\D0Lm5dUTT3<F]gVbIST"
  1042.     A$ = A$ + "PCC9bd=^^[dND:CJ]f[N[89]MU4lVR:C:R:7::ER\3cD;FJ8NLf?kGQg3:]j"
  1043.     A$ = A$ + "_:DNef=M\RC^Ea[<9K8fJdDUeRL[fWTDH2359Y?c?N\\ikT;]DKW<^Z[Z4U\"
  1044.     A$ = A$ + "QFoW4AWcUf^f`8\>Fk^gJb[mKA=F4[]<oZ0[aU`NldjXKmEIAj:Ld8JMjR[n"
  1045.     A$ = A$ + "G9N_4`^Z<abGdNhk0AlbHAeOG67>XAIa]UJmiA;HhVOb[bG#IA7hZjGDLL23"
  1046.     A$ = A$ + "bdNdn1Ao[c2NkNhSUQ\kF`4i>8b>YcI\[Q0Q\bb0akm#IEK8`OTMCeabOmUL"
  1047.     A$ = A$ + "`<A=\88FPRR`:Ic#RfDQl6;D#eb[=[GE2Uh#dXBY<=E97aD3eK]ZfJ5L>b^M"
  1048.     A$ = A$ + "d`=`B_CI5:J`I:S\<V\J5ZT#i5]##F?Mjgba`G6HB7S9<4I;g^1?6;o]J<:J"
  1049.     A$ = A$ + "cHJRSCXHJNZ6YbFoUhm?jT>J1JTDU?:B0RCf8h9OXFCVjIRcMEYL8cObZQT]"
  1050.     A$ = A$ + "DBC1[9In#iWPG<iXFoIRNE<ShGAc\B8HF_:AARi;ISiPaDZnlG\=NgL9Re=f"
  1051.     A$ = A$ + "VRHQ;bFcBIg\hfdZ2`mX;DMSb=EE>:M2idb[RT:XVXFBNk]_O;73e[8;Y>aa"
  1052.     A$ = A$ + "`Vd\g#X62;3n5Vbi`4TAW`HX2Y9W8^P7PHoOX<:=FcWcDH2SVjm;WQUAm65["
  1053.     A$ = A$ + "I<oQP;\QGN#T1H96d<D<Xa1kfP[VEan8`NYk4bS<?]fE^LY#HD313_JMi5_A"
  1054.     A$ = A$ + "TK[iX4FZ\GnjmflZZQl7F6<lXR>hHC#CPdPN4]0_m3YVK0_SAE8BD;19JA]V"
  1055.     A$ = A$ + "BK:E7Hl];D=7cQ[2E;_<_#EZ[3S^;J4o#\>P]ZEN15bUbZ<o6;LREaZL9o9A"
  1056.     A$ = A$ + "XGZ[E\0oK=<CHA^LHj1bF:gfX2cVV:HVDjNb4\C2I6fabd_inSEYi988CPDF"
  1057.     A$ = A$ + "[<1`J^0JM12dM:1B7;P`Lij>ZH\nhM3X61]gl[JIel]E[bg3I3NE^BMM55Go"
  1058.     A$ = A$ + ":EVk87bF8[Y6VNdOc4PYO=a\J4>Pj3c6]gS3Z?Y4LPThZ[d3^R]M0WLhiHag"
  1059.     A$ = A$ + "DNbiejh3>?NF8BWkLgU4E]XY\nd1Bm_B\WKV#=`hk;SBLU0RRgQ<lE9;8Vj8"
  1060.     A$ = A$ + "5L[KSToJ6AGd_D9YMefgV3AX=GDDUci2b]_k\cINO1Cf4`hDiEVOh8<BZHmo"
  1061.     A$ = A$ + "1I^hKjnA[T6>MVlU]Odd\1RlGl5e7[gjV5_o:U#bciE4UbZf77=]]FSnEl;f"
  1062.     A$ = A$ + "4CD\MDkn?eFQ:Y4RFlWi0lFCUe6DcDl6Lf5ACLQ=em8YU^ISl?AfATg8MciU"
  1063.     A$ = A$ + "FFWaTk>?c#f[i<Gd=IKMne<foN[YDRJ`J_?7R[iRj\LDOlTZ0Mllo`R_bEIW"
  1064.     A$ = A$ + "nB>Ki\Y<RI^9cNf?`#jB`kO_CHIKlNA;D[EHSfm7ZM7]Uc]OA2e]d6KFUn8Y"
  1065.     A$ = A$ + "oIaE_jmQfX#kCid2Q#ilaaFPJXd2F;iK<i[eAnhki3RW5C5\[dQoHT>I=EiA"
  1066.     A$ = A$ + ";S[4Jai2;[7OPFWV1In#>Y^hLdNfL7ejl#5h]AnZ#G#A^K;4k^NTa<nFgRf4"
  1067.     A$ = A$ + "KofNoll>lnH#[5DReDJEj2BYkRF^>JfEeQ9HafGYeY[9MM\8Nkl95liKR_k0"
  1068.     A$ = A$ + "TMU\^5a\ZLHd#Ad=<fQSRT<?E>^UGlfOOgofiN:h]km7`kTk5QgYkkogm^?H"
  1069.     A$ = A$ + "nMbmfQFoaAm[ohXNe_Wm;E_^BndVT#:3E9J?N>T\Fc3Q0<H#:RIIMI8I>I_O"
  1070.     A$ = A$ + "[e>8NGT:Jgl^jaNW4Zih[i1Zk?eO[^_<4o0ejEK1dOWFfMak=E>2oJPF_N?;"
  1071.     A$ = A$ + "T8:gb[mR;Bg8_c\<HohlXiIRHb>MS\cA=lN;WTJ5kM^=Rb4lOe#nb:JYGn91"
  1072.     A$ = A$ + "8D\5OeNXRf;K7\bKFQ9c_X_KgTk<e:]`e1IJgkVXFhl_l^fJAUHM2:akfJJ3"
  1073.     A$ = A$ + "F;ke2A6T^?3Um:UA;M0aBhJWC#13=hgl?GiL\aF`kUUJSGGD=f8Y>2S=LZ=#"
  1074.     A$ = A$ + "g5Jjnm?8KlnmWNF\8kgOJCZbgGSPQF9oASB]oOm1[J]>L1kCUTn0OoQV5]7R"
  1075.     A$ = A$ + "h::>=8_6Xmaj;^el#ZHoAf=olGQdW6R_W9YnccE:LPaZ;enYk9`\Z\;]WbM]"
  1076.     A$ = A$ + "Y4e6RlUJoH`Q\Y>;NXkI76>i58=L43ZSL82M]hS]MiEXaE[UVCXNPefY>_ZF"
  1077.     A$ = A$ + "X5ac\Q4=57mbK<;9H?Mg3c3J2H9l0;^IK[\mRKAaAk`cn_6R]94HaP2<7QJS"
  1078.     A$ = A$ + "N?^8]SbTi0<_Qg]BY?n:TUT5=TY<9UfP`Z6;?RliXl9JQ`aAVBSWae8MNGSB"
  1079.     A$ = A$ + "OH?<XY;ZD]VQ8VZ>mUaVQKURT81f:SK?_Y3aV`E8PU6LdO1GB;E0SgK84J`d"
  1080.     A$ = A$ + "f`ghYTWL#dlB`3A^9_\NIQFY76;Z#JW57TF^L1V3akjK]eA4L?\WlF=:_8SC"
  1081.     A$ = A$ + "VKHA^S3>Gh_AN]]X6D;ALi5:#U#aP=4JQC>^FK[[V38TJ?G70\CN#gG^^6E^"
  1082.     A$ = A$ + "^D\\]8D`9oXkI5jNaaQ;i4gb8\Y5h;De4\hR]]FL11K1i>lQJ?=0T`Q2LN_a"
  1083.     A$ = A$ + "6[oD[?M9O<UIH;bcJB:_WUm]cglFI?9aHOe>Djdfn:U8i<\LB1VTBi0SBnbJ"
  1084.     A$ = A$ + "3PhVJl#fZ6_aCAgFd#2MgJMj^UldOmdQIRV:K`j62>Vg8kCddL50#R#TCWW>"
  1085.     A$ = A$ + "0jm`]SfEO\45e?Johakd:i^;FU[8:H5]SXXNoWckgUJS]J8j]\N^XjB2^JNO"
  1086.     A$ = A$ + "Z^VfJk>URX5Q>3=\LNP3f9`[22ETlQ:JXSE7?64V9jLQ^m9QcFE]NF[XNZF\"
  1087.     A$ = A$ + "8dCHaVA]kEL]?>9JWD7]aTEE0WLGP[m1XDJmF[FDG4n<=GRhHBR4CHbF`Qhb"
  1088.     A$ = A$ + "#2kT=4KKXX_\XDd7W09K^#g3#Z=YbPQKO0iX]AjCE0ZcfH>R9cD=#lTCC;k\"
  1089.     A$ = A$ + "DO:Ml\aAaSWBnTm9<gXkJ7a7:mL1Phk:Q;F>8P_gVba?o96U[mPakI:Pf?ii"
  1090.     A$ = A$ + "4PCOHXhOSbM`nKdifnQLKlgLoJF8dmKEWh9V1]b47?LB#AHE`Y1W1Lf`i1W?"
  1091.     A$ = A$ + "LA`U0O0hZP[5f<\Eh6PNQM0g<lQPk#^oSJDo#aV]HSL\4NmZ`?E:EJ=CedWR"
  1092.     A$ = A$ + "bM8JejgAgknfn`mgoSnm5ljS]O1Nm?iFjES_[l0cN;KPl?nACP;QHj57QNHX"
  1093.     A$ = A$ + "Dk9M1KShUoCkAkj=9`QSkW\]n:oGI_e[eSGn>S^oQQ?:l9POOhnPo#hc1o9`"
  1094.     A$ = A$ + "31?2lX`O>lG0O=h[3OCh_1n^`O;lg1om`?161N=hO4nO2o_PoEho;l_1_1<^"
  1095.     A$ = A$ + "\C1W<JZUGIn]Q_RlVFYfhM<]geFNISJZFffH:[?]ZS1E9_Zc[Ka#mjPbPK1M"
  1096.     A$ = A$ + "LcHg0CNbEdgKd[]YginXO?Un>G7iT_R[6jD9UDf[4K=Y9ie4gBUC\7bjBk9o"
  1097.     A$ = A$ + "i;=YBJkm=AhLg>8Ie2hB_b[c]]DHNXQ01FjU;BQVhQ;cO5N2\dkLBkm;1fGY"
  1098.     A$ = A$ + "KB[aaQXHTM]ijTY?1XEX4L:`Y3W9L^`k5^0hm3G6L5`e0M0M2M1K7^AHW`]2"
  1099.     A$ = A$ + "g6m#\RbYd^cclnTAc\TbIV[RVl;[ba_adX`OYAmH3hAZZ<E[O2`V_HSL\4N]"
  1100.     A$ = A$ + "A_Vo=lcbmJC<Q9b]94]g_3_9l]hK_h9me_nP9^L24c9b<A>N<kgm]JM#JGll"
  1101.     A$ = A$ + "_:=?mHo5`To\\hOo?c4\[9mKgWi9okiI^`kdWA:_KmLji]kc9XOGmlmioOhi"
  1102.     A$ = A$ + "GeoAmLkig1?3SLk1Wg=OF;m^ec2[gEOfLmObNNSmfiIofk6?cY0HV`S3fWEa"
  1103.     A$ = A$ + "E2eYWK`cGRNN5XFj:ec3`_MGjidcFc_TNNUHF?OCmlZ`[nadC3fDdc[hYcmR"
  1104.     A$ = A$ + ">gPW?Kml:`aMIji1`J`gbiY`fl7YWG9fj7E?_:lkoNH\QK4a4:BAh\gh:;B7"
  1105.     A$ = A$ + "V`gLaX7g]RNKk6mmf?NIWKMWMg1Nbj`H8k16P?f?fR>aL1>ElC<4T[K3mTCn"
  1106.     A$ = A$ + "cK5oKK`:`?]RM^gN6HMmfoFk<kYVU77lHKU>QFKm4JK5]ejTQ6G>>0dSWc^h"
  1107.     A$ = A$ + "Q=;n6^l>kO7MeK?Ic>I]70kC4jaG=h^38lOIbQOZ`4HBIZdDUYJcd<eHV^YF"
  1108.     A$ = A$ + "CMVIHVYYNc\<Y=cfdPI>V<ViJJd<?cl=;`\#cR<;f\4CCV\84VZW8ZoGRW7Z"
  1109.     A$ = A$ + "VUJbSak?8lAP?3LG`O<lUQ_8V?`mIF6V;`MSAnoP`nPO1<:l5hWLZ3im\CmS"
  1110.     A$ = A$ + "1G?b:XWNZm0ONTULS#O<kIWX4QldCMGHlIdC?eW6cahfQmPAZm<`3K:HJf\L"
  1111.     A$ = A$ + "caH>FcaI>NC;`WcL2VCdLB`7e\2C[Vf<5=[dDbLbVEIF]iD<W:Z?lY<WVI=`"
  1112.     A$ = A$ + "SH>Mh?0ndVgSi<<[eLVVcbLfVcaL^VeI>?cj=_GckcLnV=H^0c5J^8c6=_Oc"
  1113.     A$ = A$ + "5K^4cUJ^<cUKn0Vf=GQi:=GUiZ=GSi3J^FceIj`\9cV=QV>=Ka\Ecf<MI^Nc"
  1114.     A$ = A$ + "=Hjf\MC?VN=mI^ACoVMH6`\Cc=I^Ic]H^Ec^<O8c^=gVif=gQI?VO?cMJn`V"
  1115.     A$ = A$ + "1=OTZgI?M]2lUNlLdS]Z7KC?FD?^BmH9mh9[7GUNLejaCA?NVjacB?NfjacE"
  1116.     A$ = A$ + "?^>iH[jhgZ>^]ZSK[jhfZ>^]ZSK[jhfZ>^]ZSK[jhfZ>^]ZSK[jhfZ>oJE7o"
  1117.     A$ = A$ + "FeaOEjacDaScZ]:?_>fnfkXb;MKM>#7EN9M]e]gA`6gFGl_Fl<?U:kXknfF7"
  1118.     A$ = A$ + "E6fIg3dAeMfg>jZkNkYbM`]JP>fI#OK[[JjlFfLgM\m`=e=eWf`AXZnjL78`"
  1119.     A$ = A$ + "ZYSnk_gK^k>gb0EcW]cnV>O\o^fjf6#na`N_iNTcfD_3\]JdV5fCM^cfd>jT"
  1120.     A$ = A$ + "1KK]N:C_gn7HKm^eNkYS^[[[N60]XdiV70=ZDKWgh>kjVjXk>kIcMFifjMWk"
  1121.     A$ = A$ + "XcIdOWgDgm^e^fL7MgC_3<MZaK]o>jNPnLW^Y1VfU\^F9aQE#WdZNb:LWDdN"
  1122.     A$ = A$ + "BKfCFYmTEK?iD\WLbfCFUmTBj9[d2Wf\M_TM8:IQLA;LJcn=]IKCKFhDbRZ["
  1123.     A$ = A$ + "dfhRFdX=g9fA_=;nDdMRmWFYM8Je=XF8gV5EGY[aF8_B;n\Bglb2iEJkN9g4"
  1124.     A$ = A$ + "d1WE:ZKm]Y^kMcg#e8_T>FYLEgKA>fo0je3\S]eAHWEbo]j`KP?FcFjZk^k<"
  1125.     A$ = A$ + "LCmN;CG>[OTSGm0mgE7KMWm97kG_>\7iHgKYZ=gEoK^k>[Y[N^Y=]C\C3#WY"
  1126.     A$ = A$ + "Og>fNGXlH7K^CD0jVLG4\SMfCEKYc]SR#YXoDi>j37lDK^kM^Y:gFWMP3AHG"
  1127.     A$ = A$ + "M\mNk9\f]_cMX2EM>C_cAIOa=ehScNbHoGSl3nVg6Mdooo4noEAM%%h1"
  1128.     btemp$ = ""
  1129.     FOR i& = 1 TO LEN(A$) STEP 4: B$ = MID$(A$, i&, 4)
  1130.         IF INSTR(1, B$, "%") THEN
  1131.             FOR C% = 1 TO LEN(B$): F$ = MID$(B$, C%, 1)
  1132.                 IF F$ <> "%" THEN C$ = C$ + F$
  1133.             NEXT: B$ = C$: END IF: FOR j = 1 TO LEN(B$)
  1134.             IF MID$(B$, j, 1) = "#" THEN
  1135.         MID$(B$, j) = "@": END IF: NEXT
  1136.         FOR t% = LEN(B$) TO 1 STEP -1
  1137.             B& = B& * 64 + ASC(MID$(B$, t%)) - 48
  1138.             NEXT: X$ = "": FOR t% = 1 TO LEN(B$) - 1
  1139.             X$ = X$ + CHR$(B& AND 255): B& = B& \ 256
  1140.     NEXT: btemp$ = btemp$ + X$: NEXT
  1141.     BASFILE$ = _INFLATE$(btemp$): btemp$ = ""
  1142.  
  1143.     '=== Generate a unique font name to use based on date + timer
  1144.     fontname$ = "_cp437_" + DATE$ + "_" + LTRIM$(STR$(INT(TIMER))) + ".ttf"
  1145.     IF INSTR(_OS$, "LINUX") THEN tmp$ = "/tmp/" + tmp$
  1146.     '=== Make font file
  1147.     FFF = FREEFILE: OPEN fontname$ FOR OUTPUT AS #FFF
  1148.     PRINT #FFF, BASFILE$;: CLOSE #FFF
  1149.     '=== Load then kill it after loading it into memory
  1150.     fnt& = _LOADFONT(fontname$, size, "monospace"): _FONT fnt&
  1151.     KILL fontname$
  1152.  
  1153.  
.

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
Re: XE v1.12 - Simple file viewer/editor. Updated to work in Linux now.
« Reply #1 on: November 26, 2021, 12:46:10 pm »
Very useful tool! Thanks for sharing!