home *** CD-ROM | disk | FTP | other *** search
/ PC Plus SuperCD 45 / SuperCD45.iso / talleres / rincon_prog / PIECRUST.BAS < prev    next >
Encoding:
BASIC Source File  |  1998-01-01  |  56.5 KB  |  2,475 lines

  1. '+-------------------------------------------------------------------+
  2. '▌                                                                   ▌
  3. '▌                                                                   ▌
  4. '▌                                                                   ▌
  5. '▌                                                                   ▌
  6. '+-------------------------------------------------------------------+
  7. '<->
  8. DEFINT A-Z
  9. DECLARE SUB ziDragging ()
  10. ' Return if mouse active and still dragging, or else exhausted
  11.  
  12. DECLARE SUB ziDrawBank (FromButton, ToButton)
  13. ' Draw a bank of buttons (using Bank array)
  14.  
  15. DECLARE SUB ziExhaust ()
  16. ' Return when no keystrokes and no mouse buttons
  17.  
  18. DECLARE SUB ziLoadFont (Font$)
  19. ' Load a specified font
  20.  
  21. DECLARE SUB ziLocateMCursor (XCoord, YCoord)
  22. ' Locate mouse cursor to a named point
  23.  
  24. DECLARE SUB ziMouseOnButton (FromButton, ToButton)
  25. ' Sets FoundButton
  26.  
  27. DECLARE SUB ziPublish (Printstring$, size, italic)
  28. ' Print a string at graphics cursor (advanced)
  29. '   Size   = magnitude (per 8 pixels)
  30. '   Italic = +1 to make italic
  31. '          = +2 to make overprint (no background)
  32.  
  33. DECLARE SUB ziPublishHere (row, col, Printstring$, size, italic)
  34. ' Print a string at the specified text position
  35.  
  36. DECLARE SUB ziRadio (Button, FromButton, ToButton)
  37. ' Set one button in a Bank, resetting the rest
  38.  
  39. DECLARE SUB ziReadField (Min, Max, Permitted$)
  40. ' Read a field at the current TCursor location
  41. '   Permitted$ contains:
  42. '     * - any characters
  43. '     . - allow one full-stop (as decimal)
  44. '     A - auto-enter (when filled)
  45. '     C - capitalise letters
  46. '     E - ESC allowed to finish (skip) field
  47. '     J - justify (especially for numeric)
  48. '     N - numerics
  49. '     P - password-type display
  50. '     S - space
  51. '     X - alphabetic
  52. '     Y - Y or N (upper or lower)
  53.  
  54. DECLARE SUB ziSetMCursorVis (Status)
  55. ' Set visibility of mouse cursor
  56. '   Status = 0 for OFF
  57. '            1 for ON
  58. '            2 for ENQUIRE (set MCursorVis)
  59. '           10 for TEMPORARILY OFF
  60. '           11 for RESTORED (set MCursorVis)
  61.  
  62. DECLARE SUB ziWander (Timeout!)
  63. ' Timeout  = in seconds (0 = none)
  64. ' Response =   0 = (0:00) timed out
  65. '              n = (0:n)  displacement into Allowed$
  66.  
  67. ' key           &h01xx  &h02xx  &h04xx  &h08xx  &h10xx  &h20xx  &h40xx
  68. '                plain   CTRL    shift   Mouse    Fn   CTRL-Fn  shift-Fn
  69.  
  70. ' Enter      0    *       *       -      double    -      -       -
  71. ' (left)     1    *       *       -      left     F1     ^F1     +F1
  72. ' (right)    2    *       *       -      right    F2     ^F2     +F2
  73. ' (up)       3    *       -       -      both     F3     ^F3     +F3
  74. ' (down)     4    *       -       -    leftdrag   F4     ^F4     +F4
  75.  
  76. ' Backspace  5    *       *       -    rightdrag  F5     ^F5     +F5
  77. ' Home       6    *       *       -    bothdrag   F6     ^F6     +F6
  78. ' End        7    *       *       -       -       F7     ^F7     +F7
  79.  
  80. ' PgUP       8    *       *       -       -       F8     ^F8     +F8
  81. ' PgDN       9    *       *       -       -       F9     ^F9     +F9
  82.  
  83. ' Tab       10    *       -       *       -       F10    ^F10    +F10
  84. ' Escape    11    *       -       -       -       F11    ^F11    +F11
  85. '           12    -       -       -       -       F12    ^F12    +F12
  86.  
  87. ' Allowed$  = other allowed strokes
  88. ' (Note:  DClick is a flag permitting Double-clicks of mouse - slower!)
  89.  
  90. DEFINT A-Z
  91. DECLARE SUB zsAlignGCursor ()
  92. ' Align graphic cursor to same as text cursor
  93. '  - sets Row, Col, GXloc, GYloc
  94.  
  95. DECLARE SUB zsAlignTCursor ()
  96. ' Align text cursor to same as graphic cursor
  97. '  - sets Row, Col, GXloc, GYloc
  98.  
  99. DECLARE SUB zsLocateGCursor (XCoord, YCoord)
  100. ' Locate graphic cursor to a named point
  101.  
  102. DECLARE SUB zsPastel (XCoord, YCoord, Wide, Deep, colour1, colour2)
  103. ' Colour the defined oblong with a pastel mix of two colours
  104. '  Deep = 0 or 1 - square
  105. '       = n      - Y-pixel depth
  106.  
  107. DECLARE SUB zsSetScrnMode (Mode, HiRows, HiCols)
  108. ' Mode = 9, 12 or 13
  109. ' HiRows = 1 to make high number of rows
  110. ' HiCols = 1 to make high number of cols (80)
  111. ' Set SCREEN parameters and blank the screen
  112. '  - sets ScrnMode, Xmax, Ymax, Rows, Cols, XYRatio!
  113. '  - uses FG and optionally BG (colours)
  114.  
  115. DECLARE SUB zsSubstitute (XCoord, YCoord, Wide, Deep, colour1, colour2)
  116. ' Substitute one colour with another within the defined oblong
  117. '  Deep = 0 or 1 - square
  118. '       = n      - Y-pixel depth
  119.  
  120. DECLARE SUB zzAlphaSort (Table$())
  121. ' Sort alphabetically the strings in the table; limited by " SortCount"
  122.  
  123. DECLARE SUB zzBasicInt (IntType)
  124. ' Execute interrupt (params in REGS.AX etc)
  125.  
  126. DECLARE SUB zzChangeDir (Directory$)
  127. ' Change to a particular directory
  128. '  -sets Directory$; eg "." will be changed to current directory
  129. ' if error occurs, Directory$ is returned as "?"
  130.  
  131. DECLARE SUB zzChangeDrive (Drive$)
  132. ' Change to a particular drive
  133. ' if Drive$ is empty on input, current drive is returned
  134. ' if error occurs, Drive$ is returned as "?"
  135.  
  136. DECLARE SUB zzCritOff ()
  137. ' turns off Critical Error Handling
  138.  
  139. DECLARE SUB zzCritOn ()
  140. ' restores normal Critical Error Handling
  141.  
  142. DECLARE SUB zzFileSelectBox (Pattern$)
  143. ' File Select Box function to choose an input file
  144.  
  145. DECLARE SUB zzInPath (Field$)
  146. ' Return full path to a file (in same string)
  147.  
  148. DECLARE SUB zzSearchD (Pattern$)
  149. ' Search for DIRECTORIES matching the pattern
  150. '  - sets Directories and Directories$()
  151.  
  152. DECLARE SUB zzSearchF (Pattern$)
  153. ' Search for FIILENAMES matching the pattern
  154. '  - sets FileNames and FileNames$()
  155.  
  156. DECLARE SUB zzValidate (Directory$)
  157. ' validate the named path and return its full
  158. '   (unqualified) name, including drive
  159. ' if error occcurs, Directory$ is returned as "?"
  160.  
  161. '================================================
  162. '/  UK copyright (c) 1998 by Future Publishing
  163. '/
  164. '/
  165. '/
  166. '/
  167. '================================================
  168. TYPE REGISTERS
  169.   AX AS INTEGER
  170.   BX AS INTEGER
  171.   CX AS INTEGER
  172.   DX AS INTEGER
  173.   DS AS INTEGER
  174.   SI AS INTEGER
  175.   ES AS INTEGER
  176.   DI AS INTEGER
  177.   FL AS INTEGER
  178. END TYPE
  179.  
  180. TYPE Buttons
  181.   Xloc AS INTEGER
  182.   Yloc AS INTEGER
  183.   Wide AS INTEGER
  184.   Deep AS INTEGER
  185. '  0 = checkbutton
  186. '  1 = square sculptured
  187. '  n = Y-pixels deep
  188.   State AS INTEGER
  189. '  0 = off
  190. '  1 = on
  191.   Active AS INTEGER
  192. '  0 = inactive
  193. '  1 = active
  194. END TYPE
  195.  
  196. CONST Pi! = 3.14159
  197. CONST Ex! = 2.71828
  198. CONST DegToRad! = .0174533
  199. CONST RadToDeg! = 57.2958
  200.  
  201. CONST ziNoShift = &H1
  202. CONST ziCTRL = &H2
  203. CONST ziShift = &H4
  204. CONST ziMouse = &H8
  205. CONST ziFn = &H10
  206. CONST ziCTRLFn = &H20
  207. CONST ziShiftFn = &H40
  208.  
  209. CONST ziL = 1
  210. CONST ziR = 2
  211. CONST ziUp = 3
  212. CONST ziDn = 4
  213. CONST ziBS = 5
  214. CONST ziHome = 6
  215. CONST ziEnd = 7
  216. CONST ziPgUp = 8
  217. CONST ziPgDn = 9
  218. CONST ziTab = 10
  219. CONST ziEsc = 11
  220.  
  221. CONST ziDbl = 0
  222. CONST ziBoth = 3
  223. CONST ziLDrag = 4
  224. CONST ziRDrag = 5
  225. CONST ziBothDrag = 6
  226.  
  227. DIM SHARED Regs AS REGISTERS
  228. DIM SHARED Bank(20) AS Buttons
  229. DIM SHARED Bad, Module$
  230. DIM SHARED Mouse, MCursorVis, MXloc, MYloc
  231. DIM SHARED DClick
  232. DIM SHARED ScrnMode, bg, fg, TCursor
  233. DIM SHARED Xmax, Ymax, GXloc, GYloc, XYratio!
  234. DIM SHARED Rows, Cols, row, col
  235. DIM SHARED Allowed$, Field$
  236. DIM SHARED FoundButton
  237. DIM SHARED Font(255, 7)
  238. DIM SHARED Response, HResponse, LResponse
  239. DIM SHARED SortCount
  240. REDIM SHARED Directories$(500)
  241. REDIM SHARED FileNames$(500)
  242. DIM SHARED Directories, FileNames
  243.  
  244. DIM SHARED IRET AS STRING * 3
  245. IRET = CHR$(&HB0) + CHR$(&H0) + CHR$(&HCF)
  246. DIM SHARED CritSeg, CritPtr, CritCount
  247.  
  248. '++++++++++++++++++++++++
  249. RANDOMIZE TIMER
  250. ON ERROR GOTO RESUMENEXT
  251. RESUMENEXT:
  252.   IF ERR = 255 THEN
  253.     CLS
  254.     BEEP
  255.     PRINT "Cannot find module "; Module$
  256.     SLEEP
  257.     SYSTEM
  258.   END IF
  259.   IF ERR THEN
  260.     Bad = ERR
  261.     RESUME NEXT
  262.   END IF
  263. Regs.AX = &H3524
  264. CALL zzBasicInt(&H21)
  265. CritSeg = Regs.ES
  266. CritPtr = Regs.BX
  267. '++++++++++++++++++++++++
  268. ' Test for presence of a mouse
  269. Mouse = 0
  270. Regs.AX = 0
  271. CALL zzBasicInt(&H33)
  272. IF Regs.AX THEN
  273.   Mouse = 1
  274.   CALL ziSetMCursorVis(0)
  275. END IF
  276. '++++++++++++++++++++++++
  277. ' Load the ASCII font
  278. CALL ziLoadFont("Ascii8x8")
  279. ' Create PAINT shades
  280. DIM Shades(7, 4) AS STRING * 8
  281. A$ = CHR$(&H55): B$ = CHR$(&HAA): C$ = CHR$(&HFF): D$ = CHR$(0)
  282. ' Blue
  283.  Shades(1, 0) = A$ + D$ + D$ + A$ + B$ + D$ + D$ + B$
  284.  Shades(1, 1) = A$ + D$ + D$ + C$ + B$ + D$ + D$ + C$
  285.  Shades(1, 2) = C$ + D$ + D$ + C$ + C$ + D$ + D$ + C$
  286.  Shades(1, 3) = C$ + B$ + D$ + A$ + C$ + A$ + D$ + B$
  287.  Shades(1, 4) = C$ + A$ + D$ + C$ + C$ + B$ + D$ + C$
  288. ' Green
  289.  Shades(2, 0) = D$ + A$ + D$ + D$ + D$ + B$ + D$ + D$
  290.  Shades(2, 1) = D$ + B$ + D$ + A$ + D$ + A$ + D$ + B$
  291.  Shades(2, 2) = D$ + A$ + D$ + C$ + D$ + B$ + D$ + C$
  292.  Shades(2, 3) = B$ + C$ + B$ + A$ + A$ + C$ + A$ + B$
  293.  Shades(2, 4) = A$ + C$ + A$ + C$ + B$ + C$ + B$ + C$
  294. ' Cyan
  295.  Shades(3, 0) = A$ + A$ + D$ + D$ + B$ + B$ + D$ + D$
  296.  Shades(3, 1) = B$ + B$ + D$ + A$ + A$ + A$ + D$ + B$
  297.  Shades(3, 2) = A$ + A$ + D$ + C$ + B$ + B$ + D$ + C$
  298.  Shades(3, 3) = C$ + C$ + B$ + A$ + C$ + C$ + A$ + B$
  299.  Shades(3, 4) = C$ + C$ + A$ + C$ + C$ + C$ + B$ + C$
  300. ' Red
  301.  Shades(4, 0) = D$ + D$ + A$ + D$ + D$ + D$ + B$ + D$
  302.  Shades(4, 1) = D$ + D$ + C$ + D$ + D$ + D$ + C$ + D$
  303.  Shades(4, 2) = D$ + D$ + C$ + A$ + D$ + D$ + C$ + B$
  304.  Shades(4, 3) = D$ + D$ + C$ + C$ + D$ + D$ + C$ + C$
  305.  Shades(4, 4) = A$ + A$ + C$ + C$ + B$ + B$ + C$ + C$
  306. ' Magenta
  307.  Shades(5, 0) = A$ + D$ + A$ + A$ + B$ + D$ + B$ + B$
  308.  Shades(5, 1) = A$ + D$ + A$ + C$ + B$ + D$ + B$ + C$
  309.  Shades(5, 2) = A$ + D$ + C$ + A$ + B$ + D$ + C$ + B$
  310.  Shades(5, 3) = C$ + D$ + C$ + C$ + C$ + D$ + C$ + C$
  311.  Shades(5, 4) = C$ + A$ + C$ + C$ + C$ + B$ + C$ + C$
  312. ' Yellow
  313.  Shades(6, 0) = D$ + B$ + A$ + D$ + D$ + A$ + B$ + D$
  314.  Shades(6, 1) = D$ + A$ + A$ + A$ + D$ + B$ + B$ + B$
  315.  Shades(6, 2) = D$ + B$ + A$ + C$ + D$ + A$ + B$ + C$
  316.  Shades(6, 3) = B$ + C$ + C$ + A$ + A$ + C$ + C$ + B$
  317.  Shades(6, 4) = A$ + C$ + C$ + C$ + B$ + C$ + C$ + C$
  318. ' White
  319.  Shades(7, 0) = D$ + D$ + D$ + C$ + D$ + D$ + D$ + C$
  320.  Shades(7, 1) = B$ + B$ + B$ + A$ + A$ + A$ + A$ + B$
  321.  Shades(7, 2) = A$ + A$ + A$ + C$ + B$ + B$ + B$ + C$
  322.  Shades(7, 3) = C$ + C$ + C$ + A$ + C$ + C$ + C$ + B$
  323.  Shades(7, 4) = C$ + C$ + C$ + C$ + C$ + C$ + C$ + C$
  324. '/==================================/'
  325. '/  End of Standard Piecrust code   /'
  326. '/==================================/'
  327. '<+>
  328.  
  329.  
  330.  
  331.  
  332.  
  333.   SYSTEM
  334.  
  335. '+-------------------------------------------------------------------+
  336. '▌                         SUBROUTINES                               ▌
  337. '▌                         ===========                               ▌
  338. '+-------------------------------------------------------------------+
  339. '▌                                                                   ▌
  340. '▌                                                                   ▌
  341. '▌                                                                   ▌
  342. '▌                                                                   ▌
  343. '+-------------------------------------------------------------------+
  344.  
  345. '<->
  346. '<p>
  347. '++++++++++++++++++++++++
  348. SUB ziDragging
  349.  
  350.   IF Mouse AND MCursorVis THEN
  351.     SELECT CASE Response
  352.     CASE 2052 TO 2054
  353.       Regs.AX = 3
  354.       CALL zzBasicInt(&H33)
  355.       IF Regs.BX = Response - 2051 THEN
  356.     EXIT SUB
  357.       END IF
  358.     END SELECT
  359.   END IF
  360.   CALL ziExhaust
  361.  
  362. END SUB
  363.  
  364. '<p>
  365. '++++++++++++++++++++++++
  366. SUB ziDrawBank (FromButton, ToButton)
  367.  
  368.   CALL ziSetMCursorVis(10)
  369.  
  370.   FOR i = FromButton TO ToButton
  371.  
  372.     IF Bank(i).Active THEN
  373.  
  374.       IF Bank(i).State THEN
  375.     colour1 = 8
  376.       ELSE
  377.     colour1 = 15
  378.       END IF
  379.       colour2 = colour1 XOR 7
  380.  
  381.       XCoord = Bank(i).Xloc
  382.       YCoord = Bank(i).Yloc
  383.       XWidth = Bank(i).Wide
  384.       YDepth = Bank(i).Deep
  385.       X2Coord = XCoord + XWidth
  386.  
  387.       IF YDepth THEN
  388.     IF YDepth = 1 THEN
  389.       Y2Coord = YCoord + XWidth / XYratio!
  390.     ELSE
  391.       Y2Coord = YCoord + YDepth
  392.     END IF
  393.     LINE (XCoord, YCoord)-(X2Coord - 1, YCoord), colour1
  394.     LINE (XCoord, YCoord)-(XCoord, Y2Coord - 1), colour1
  395.     LINE (XCoord + 1, Y2Coord)-(X2Coord, Y2Coord), colour2
  396.     LINE (X2Coord, YCoord)-(X2Coord, Y2Coord), colour2
  397.       ELSE
  398.     A = XWidth \ 2
  399.     B = A / XYratio!
  400.     C = XCoord + A
  401.     D = YCoord + B
  402.  
  403.     LINE (XCoord, YCoord)-(C + A, D + B), 7, BF
  404.  
  405.     CIRCLE (C, D), A, 8
  406.     CIRCLE (C, D), A - 1, 8
  407.     PAINT (C, D), 7, 7
  408.     IF Bank(i).State THEN
  409.       CIRCLE (C, D), XWidth \ 3, 8
  410.       PAINT (C, D), 8, 8
  411.     END IF
  412.       END IF
  413.     END IF
  414.  
  415.   NEXT
  416.  
  417.   CALL ziSetMCursorVis(11)
  418.  
  419. END SUB
  420.  
  421. '<p>
  422. '++++++++++++++++++++++++
  423. SUB ziExhaust
  424.  
  425.   DO
  426.     x$ = INKEY$
  427.   LOOP WHILE LEN(x$)
  428.  
  429.   IF Mouse AND MCursorVis THEN
  430.     DO
  431.       Regs.AX = 3
  432.       CALL zzBasicInt(&H33)
  433.     LOOP WHILE (Regs.BX AND 3)
  434.   END IF
  435.   Response = 0
  436. END SUB
  437.  
  438. '<p>
  439. '++++++++++++++++++++++++
  440. SUB ziLoadFont (Font$)
  441.  
  442.   DEF SEG = VARSEG(Font(0, 0))
  443.  
  444.   Module$ = Font$ + ".OVL"
  445.   CALL zzInPath(Module$)
  446.   IF Module$ = "" THEN
  447.     Module$ = Font$ + ".OVL"
  448.     ERROR 255
  449.   ELSE
  450.     BLOAD Module$, VARPTR(Font(0, 0))
  451.   END IF
  452.  
  453.   DEF SEG
  454.  
  455. END SUB
  456.  
  457. '<p>
  458. '++++++++++++++++++++++++
  459. SUB ziLocateMCursor (XCoord, YCoord)
  460.  
  461.   IF Mouse THEN
  462.     MXloc = XCoord
  463.     MYloc = YCoord
  464.     Regs.AX = 4
  465.     Regs.CX = XCoord
  466.     Regs.DX = YCoord
  467.     CALL zzBasicInt(&H33)
  468.     CALL ziSetMCursorVis(1)
  469.   END IF
  470.  
  471. END SUB
  472.  
  473. '<p>
  474. '++++++++++++++++++++++++
  475. SUB ziMouseOnButton (FromButton, ToButton)
  476.  
  477.   FoundButton = 0
  478.   FOR i = FromButton TO ToButton
  479.     IF Bank(i).Active THEN
  480.       IF Bank(i).Deep < 2 THEN
  481.     j = Bank(i).Wide / XYratio!
  482.       ELSE
  483.     j = Bank(i).Deep
  484.       END IF
  485.       IF MXloc > Bank(i).Xloc THEN
  486.     IF MXloc < Bank(i).Xloc + Bank(i).Wide THEN
  487.       IF MYloc > Bank(i).Yloc THEN
  488.         IF MYloc < Bank(i).Yloc + j THEN
  489.           FoundButton = i
  490.           EXIT SUB
  491.         END IF
  492.       END IF
  493.     END IF
  494.       END IF
  495.     ELSE
  496.       EXIT SUB
  497.     END IF
  498.   NEXT
  499.  
  500. END SUB
  501.  
  502. '<p>
  503. '++++++++++++++++++++++++
  504. SUB ziPublish (Printstring$, size, italic)
  505.  
  506.   CALL ziSetMCursorVis(10)
  507.  
  508.   xx = POINT(0)
  509.   yy = POINT(1)
  510.   IF size THEN
  511.     Scale = size
  512.   ELSE
  513.     Scale = 1
  514.   END IF
  515.  
  516.   LenString = LEN(Printstring$)
  517.  
  518.   ExpScale = 8 * Scale
  519.   limxx = xx + ExpScale * LenString - 1
  520.   limyy = yy + ExpScale - 1
  521.  
  522.   IF italic AND 1 THEN
  523.     limxx = limxx + 4 * Scale
  524.   END IF
  525.  
  526.  
  527.   IF italic AND 2 THEN
  528.   ELSE
  529.     LINE (xx, yy)-(limxx, limyy), bg, BF
  530.   END IF
  531.  
  532.  
  533.   FOR A = 0 TO LenString - 1
  534.     x = ASC(MID$(Printstring$, A + 1, 1))
  535.     B = xx + ExpScale * A
  536.     FOR y = 0 TO 7
  537.       C = Font(x, y)
  538.       D = y * Scale
  539.       e = yy + D
  540.       IF italic AND 1 THEN
  541.     F = B + 4 * Scale - (D + Scale - 1) \ 2 - 1
  542.       ELSE
  543.     F = B
  544.       END IF
  545.       G = 128
  546.       DO
  547.     IF C AND G THEN
  548.       FOR h = 0 TO Scale - 1
  549.         FOR i = 0 TO Scale - 1
  550.           PSET (F + h, e + i), fg
  551.         NEXT
  552.       NEXT
  553.     END IF
  554.     F = F + Scale
  555.     G = G \ 2
  556.       LOOP UNTIL G = 0
  557.     NEXT
  558.   NEXT
  559.   CALL zsLocateGCursor(limxx + 1, yy)
  560.  
  561.   CALL ziSetMCursorVis(11)
  562.  
  563. END SUB
  564.  
  565. SUB ziPublishHere (row, col, Printstring$, size, italic)
  566.  
  567.  IF row + col > 0 THEN
  568.   LOCATE row, col
  569.  END IF
  570.  CALL zsAlignGCursor
  571.  CALL ziPublish(Printstring$, size, italic)
  572.  CALL zsAlignTCursor
  573.  
  574. END SUB
  575.  
  576. '<p>
  577. '++++++++++++++++++++++++
  578. SUB ziRadio (Button, FromButton, ToButton)
  579.  
  580.   IF Button >= FromButton THEN
  581.     IF Button <= ToButton THEN
  582.       FOR A = FromButton TO ToButton
  583.     Bank(A).State = 0
  584.       NEXT
  585.     END IF
  586.   END IF
  587.  
  588.   Bank(Button).State = 1
  589.   CALL ziDrawBank(FromButton, ToButton)
  590.  
  591. END SUB
  592.  
  593. '<p>
  594. '++++++++++++++++++++++++
  595. SUB ziReadField (Min, Max, Permitted$)
  596.  
  597.   CALL ziSetMCursorVis(10)
  598.  
  599.   atRow = CSRLIN
  600.   atCol = POS(x)
  601.   Field$ = ""
  602.   PRINT CHR$(219); SPACE$(Max);
  603.   Rules$ = UCASE$(Permitted$)
  604.  
  605.   brake = 1
  606.   WHILE brake
  607.     x$ = ""
  608.     WHILE LEN(x$) = 0
  609.       x$ = INKEY$
  610.     WEND
  611.     IF INSTR(Rules$, "C") THEN x$ = UCASE$(x$)
  612.     oldLen = LEN(Field$)
  613.     Good = 0
  614.     IF INSTR(Rules$, ".") THEN
  615.       IF x$ = "." THEN
  616.     IF INSTR(Field$, ".") = 0 THEN
  617.       Good = 1
  618.     END IF
  619.       END IF
  620.     END IF
  621.     IF INSTR(Rules$, "N") THEN
  622.       IF INSTR("0123456789", x$) THEN
  623.     Good = 1
  624.       END IF
  625.     END IF
  626.     IF INSTR(Rules$, "S") THEN
  627.       IF x$ = " " THEN
  628.     Good = 1
  629.       END IF
  630.     END IF
  631.     IF INSTR(Rules$, "X") THEN
  632.       IF INSTR("ABCDEFGHIJKLMNOPQRSTUVWXYZ", UCASE$(x$)) THEN
  633.     Good = 1
  634.       END IF
  635.     END IF
  636.     IF INSTR(Rules$, "Y") THEN
  637.       IF INSTR("YyNy", x$) THEN
  638.     Good = 1
  639.       END IF
  640.     END IF
  641.     IF Good THEN
  642.       Field$ = Field$ + x$
  643.       IF INSTR(Field$, ".") THEN
  644.     NewMax = Max + 1
  645.       ELSE
  646.     NewMax = Max
  647.       END IF
  648.       Field$ = MID$(Field$, 1, NewMax)
  649.     END IF
  650.  
  651.     ' handle Bkspace
  652.     IF ASC(x$) = 8 AND LEN(Field$) THEN
  653.       Field$ = MID$(Field$, 1, LEN(Field$) - 1)
  654.     END IF
  655.  
  656.     Signif$ = Field$ + "X"
  657.     WHILE INSTR(" 0", MID$(Signif$, 1, 1))
  658.       Signif$ = MID$(Signif$, 2)
  659.     WEND
  660.     IF INSTR(Signif$, ".") THEN
  661.       SignifLen = LEN(Signif$) - 2
  662.     ELSE
  663.       SignifLen = LEN(Signif$) - 1
  664.     END IF
  665.  
  666.     ' handle Enter
  667.     IF ASC(x$) = 13 AND SignifLen >= Min THEN
  668.       oldLen = LEN(Field$) + 1
  669.       brake = 0
  670.     END IF
  671.  
  672.     ' handle Esc
  673.     IF ASC(x$) = 27 THEN
  674.       LOCATE atRow, atCol
  675.       PRINT CHR$(219); SPACE$(Max);
  676.       Field$ = ""
  677.       IF INSTR(Rules$, "E") THEN
  678.     EXIT SUB
  679.       END IF
  680.     END IF
  681.  
  682.     ' reprint if change, or beep if no change
  683.     IF oldLen = LEN(Field$) THEN
  684.       BEEP
  685.     ELSE
  686.       LOCATE atRow, atCol
  687.       IF INSTR(Rules$, "P") THEN
  688.     PRINT STRING$(LEN(Field$), 254); CHR$(219); " ";
  689.       ELSE
  690.     PRINT Field$; CHR$(219); " ";
  691.       END IF
  692.     END IF
  693.  
  694.     ' check for auto-Enter
  695.     IF INSTR(Rules$, "A") THEN
  696.       IF SignifLen = Max THEN
  697.     brake = 0
  698.       END IF
  699.     END IF
  700.   WEND
  701.  
  702.   ' justify if required
  703.   IF INSTR(Rules$, "J") THEN
  704.     WHILE MID$(Field$, 1, 1) = "0"
  705.       Field$ = MID$(Field$, 2)
  706.     WEND
  707.     Field$ = RIGHT$(SPACE$(NewMax) + Field$, NewMax)
  708.   END IF
  709.  
  710.   ' reprint, deleting the cursor
  711.   LOCATE atRow, atCol
  712.   IF INSTR(Rules$, "P") THEN
  713.     PRINT STRING$(LEN(Field$), 254); " ";
  714.   ELSE
  715.     PRINT Field$; " ";
  716.   END IF
  717.  
  718.   CALL ziSetMCursorVis(11)
  719.  
  720. END SUB
  721.  
  722. '<p>
  723. '++++++++++++++++++++++++
  724. SUB ziSetMCursorVis (Status) STATIC
  725.  
  726.   IF Mouse THEN
  727.     SELECT CASE Status
  728.     CASE 0
  729.       IF MCursorVis THEN
  730.        Regs.AX = 2
  731.        CALL zzBasicInt(&H33)
  732.       END IF
  733.     CASE 1
  734.       Regs.AX = 1
  735.       CALL zzBasicInt(&H33)
  736.     CASE 10
  737.       Regs.AX = &H2A
  738.       CALL zzBasicInt(&H33)
  739.       IF Regs.AX = 0 THEN
  740.     TempFlag = 1
  741.     Regs.AX = 2
  742.     CALL zzBasicInt(&H33)
  743.       ELSE
  744.     TempFlag = 0
  745.       END IF
  746.     CASE 11
  747.       IF TempFlag THEN
  748.     Regs.AX = 1
  749.     CALL zzBasicInt(&H33)
  750.       END IF
  751.     END SELECT
  752.     Regs.AX = &H2A
  753.     CALL zzBasicInt(&H33)
  754.     IF Regs.AX = 0 THEN
  755.       MCursorVis = 1
  756.     ELSE
  757.       MCursorVis = 0
  758.     END IF
  759.   END IF
  760. END SUB
  761.  
  762. '<p>
  763. '++++++++++++++++++++++++
  764. SUB ziWander (Timeout!)
  765.  
  766.   IF Timeout! = 0 THEN
  767.     WatchFor! = TIMER + 3600
  768.   ELSE
  769.     WatchFor! = TIMER + Timeout!
  770.   END IF
  771.  
  772.   Response = 0
  773.  
  774.   DO
  775.     x$ = INKEY$
  776.     IF LEN(x$) THEN
  777.       SELECT CASE LEN(x$)
  778.       CASE 1
  779.     A = INSTR(Allowed$, x$)
  780.     IF A THEN
  781.       Response = A
  782.       EXIT DO
  783.     END IF
  784.     SELECT CASE ASC(x$)
  785.     CASE 8: Response = 261
  786.     CASE 9: Response = 266
  787.     CASE 10: Response = 512
  788.     CASE 13: Response = 256
  789.     CASE 27: Response = 267
  790.     CASE 127: Response = 517
  791.     END SELECT
  792.     IF Response THEN
  793.       EXIT DO
  794.     END IF
  795.       CASE 2
  796.     Rightmost = ASC(RIGHT$(x$, 1))
  797.     SELECT CASE Rightmost
  798.     CASE 15: Response = 1019
  799.     CASE 59 TO 68
  800.       Response = 4038
  801.     CASE 72: Response = 187
  802.     CASE 71 TO 73
  803.       Response = 191
  804.     CASE 75: Response = 182
  805.     CASE 77: Response = 181
  806.     CASE 80: Response = 180
  807.     CASE 79 TO 81
  808.       Response = 184
  809.     CASE 84 TO 93
  810.       Response = 16301
  811.     CASE 94 TO 103
  812.       Response = 8099
  813.     CASE 115 TO 116
  814.       Response = 398
  815.     CASE 117: Response = 402
  816.     CASE 118: Response = 403
  817.     CASE 119: Response = 399
  818.     CASE 127: Response = 390
  819.     CASE 132: Response = 388
  820.     CASE 133 TO 134
  821.       Response = 3974
  822.     CASE 135 TO 136
  823.       Response = 16260
  824.     CASE 137 TO 138
  825.       Response = 8066
  826.     END SELECT
  827.     IF Response THEN
  828.       Response = Response + Rightmost
  829.       EXIT DO
  830.     END IF
  831.       END SELECT
  832.     END IF
  833.  
  834.     IF Mouse AND MCursorVis THEN
  835.       Regs.AX = 3
  836.       CALL zzBasicInt(&H33)
  837.       SELECT CASE Regs.BX
  838.       CASE 1 TO 3
  839.     Response = 2048 + Regs.BX
  840.     nowtime! = TIMER
  841.     DO
  842.       Regs.AX = 3
  843.       CALL zzBasicInt(&H33)
  844.       IF Regs.BX = 0 THEN EXIT DO
  845.     LOOP UNTIL TIMER - nowtime! > .3
  846.     IF Regs.BX = Response - 2048 THEN
  847.       Response = Response + 3
  848.     ELSE
  849.       IF Regs.BX = 0 AND Response = 2049 AND DClick THEN
  850.         nowtime! = TIMER
  851.         DO
  852.           Regs.AX = 3
  853.           CALL zzBasicInt(&H33)
  854.           IF Regs.BX = 1 THEN EXIT DO
  855.         LOOP UNTIL TIMER - nowtime! > .3
  856.         IF Regs.BX = 1 THEN
  857.           Response = 2048
  858.           CALL ziExhaust
  859.         END IF
  860.       END IF
  861.       IF Regs.BX = 3 THEN
  862.         Response = 2051
  863.       END IF
  864.     END IF
  865.       END SELECT
  866.       IF Response THEN
  867.     MXloc = Regs.CX
  868.     MYloc = Regs.DX
  869.     EXIT DO
  870.       END IF
  871.     END IF
  872.  
  873.   LOOP UNTIL WatchFor! < TIMER
  874.   HResponse = Response \ 256
  875.   LResponse = Response MOD 256
  876.  
  877. END SUB
  878.  
  879. '<p>
  880. '++++++++++++++++++++++++
  881. SUB zsAlignGCursor
  882.  
  883.   row = CSRLIN
  884.   col = POS(0)
  885.   GXloc = (col - 1) * ((Xmax + 1) \ Cols)
  886.   GYloc = (row - 1) * ((((Ymax + 1) \ Rows) * Rows + 1) \ Rows)
  887.   CALL zsLocateGCursor(GXloc, GYloc)
  888.  
  889. END SUB
  890.  
  891. '<p>
  892. '++++++++++++++++++++++++
  893. SUB zsAlignTCursor
  894.  
  895.   GXloc = POINT(0)
  896.   GYloc = POINT(1)
  897.   A = (Xmax + 1) / Cols
  898.   B = (Ymax + 1) / Rows
  899.   col = (GXloc + A - 1) \ A + 1
  900.   row = (GYloc + B - 1) \ B + 1
  901.   LOCATE row, col
  902.   CALL zsAlignGCursor
  903.  
  904. END SUB
  905.  
  906. '<p>
  907. '++++++++++++++++++++++++
  908. SUB zsLocateGCursor (XCoord, YCoord)
  909.  
  910.   GXloc = XCoord
  911.   GYloc = YCoord
  912.   PSET (GXloc, GYloc), POINT(GXloc, GYloc)
  913.  
  914. END SUB
  915.  
  916. '<p>
  917. '++++++++++++++++++++++++
  918. SUB zsPastel (XCoord, YCoord, Wide, Deep, colour1, colour2)
  919.  
  920.   CALL ziSetMCursorVis(10)
  921.  
  922.   IF Deep < 2 THEN
  923.     A = Wide / XYratio!
  924.   ELSE
  925.     A = Deep
  926.   END IF
  927.  
  928.   LINE (XCoord, YCoord)-(XCoord + Wide - 1, YCoord + A - 1), colour1, BF
  929.   FOR B = XCoord TO XCoord + Wide - 1 STEP 2
  930.     LINE (B, YCoord)-(B, YCoord + A - 1), colour2, , &H5555
  931.   NEXT
  932.   FOR B = XCoord + 1 TO XCoord + Wide - 1 STEP 2
  933.     LINE (B, YCoord)-(B, YCoord + A - 1), colour2, , &HAAAA
  934.   NEXT
  935.  
  936.   CALL ziSetMCursorVis(11)
  937.  
  938. END SUB
  939.  
  940. '<p>
  941. '++++++++++++++++++++++++
  942. SUB zsSetScrnMode (Mode, HiRows, HiCols)
  943.  
  944.   CALL ziSetMCursorVis(10)
  945.  
  946.   ScrnMode = Mode
  947.   SELECT CASE Mode
  948.   CASE 9
  949.     SCREEN 9
  950.     IF HiRows THEN
  951.       Rows = 43
  952.     ELSE
  953.       Rows = 25
  954.     END IF
  955.     Xmax = 639
  956.     Ymax = 349
  957.   CASE 12
  958.     SCREEN 12
  959.     IF HiRows THEN
  960.       Rows = 60
  961.     ELSE
  962.       Rows = 30
  963.     END IF
  964.     Xmax = 639
  965.     Ymax = 479
  966.   CASE 13
  967.     SCREEN 13
  968.     Rows = 25
  969.     Cols = 40
  970.     Xmax = 319
  971.     Ymax = 199
  972.   CASE ELSE
  973.     RETURN
  974.   END SELECT
  975.  
  976.   IF Mode <> 13 THEN
  977.     IF HiCols THEN
  978.       Cols = 80
  979.     ELSE
  980.       Cols = 40
  981.     END IF
  982.   END IF
  983.   WIDTH Cols, Rows
  984.   CLS
  985.   IF Mode = 9 THEN COLOR fg, 0
  986.  
  987.   LINE (0, 0)-(Xmax, Ymax), bg, BF
  988.   LOCATE 1, 1, 0
  989.   PSET (0, 0), bg
  990.   XYratio! = .75 * (Xmax + 1) / (Ymax + 1)
  991.  
  992.   CALL ziSetMCursorVis(11)
  993.  
  994. END SUB
  995.  
  996. '<p>
  997. '++++++++++++++++++++++++
  998. SUB zsSubstitute (XCoord, YCoord, Wide, Deep, colour1, colour2)
  999.  
  1000.   CALL ziSetMCursorVis(10)
  1001.  
  1002.   IF Deep < 2 THEN
  1003.     A = Wide / XYratio!
  1004.   ELSE
  1005.     A = Deep
  1006.   END IF
  1007.   FOR B = XCoord TO XCoord + Wide - 1
  1008.     FOR C = YCoord TO YCoord + A - 1
  1009.       IF POINT(B, C) = colour1 THEN
  1010.     PSET (B, C), colour2
  1011.       END IF
  1012.     NEXT
  1013.   NEXT
  1014.  
  1015.   CALL ziSetMCursorVis(11)
  1016.  
  1017. END SUB
  1018.  
  1019. '<p>
  1020. '++++++++++++++++++++++++
  1021. SUB zzAlphaSort (SortData$())
  1022.  
  1023.  DIM SortPointers(SortCount, 2)
  1024.  
  1025.  FOR i = 2 TO SortCount
  1026.   j = 1
  1027.  
  1028.   DO
  1029.    k = j
  1030.    IF SortData$(i) < SortData$(j) THEN
  1031.     j = SortPointers(j, 1)
  1032.    ELSE
  1033.     j = SortPointers(j, 2)
  1034.    END IF
  1035.   LOOP WHILE j <> 0
  1036.  
  1037.   IF SortData$(i) < SortData$(k) THEN
  1038.    SortPointers(k, 1) = i
  1039.   ELSE
  1040.    SortPointers(k, 2) = i
  1041.   END IF
  1042.  NEXT
  1043.  
  1044.  SortPointers(0, 1) = 1
  1045.  
  1046.  
  1047.  FOR i = 1 TO SortCount
  1048.   j = 0
  1049.   DO WHILE SortPointers(j, 1) <> 0
  1050.    k = j
  1051.    j = SortPointers(j, 1)
  1052.   LOOP
  1053.   SortPointers(k, 1) = SortPointers(j, 2)
  1054.  
  1055.   SWAP SortData$(i), SortData$(j)
  1056.   SWAP SortPointers(i, 1), SortPointers(j, 1)
  1057.   SWAP SortPointers(i, 2), SortPointers(j, 2)
  1058.  
  1059.   FOR k = 0 TO SortCount
  1060.    FOR l = 1 TO 2
  1061.     IF SortPointers(k, l) = i THEN SortPointers(k, l) = j
  1062.    NEXT
  1063.   NEXT
  1064.  NEXT
  1065.  
  1066. END SUB
  1067.  
  1068. '<p>
  1069. '++++++++++++++++++++++++
  1070. SUB zzBasicInt (IntType) STATIC
  1071.  
  1072.   DIM ASM(54)
  1073.   DEF SEG = VARSEG(ASM(0))
  1074.  
  1075.   IF ASM(1) = 0 THEN
  1076.     Module$ = "BASICINT.OVL"
  1077.     CALL zzInPath(Module$)
  1078.     IF Module$ = "" THEN
  1079.       Module$ = "BASICINT.OVL"
  1080.       ERROR 255
  1081.     ELSE
  1082.       BLOAD Module$, VARPTR(ASM(0))
  1083.     END IF
  1084.   END IF
  1085.  
  1086.   CALL ABSOLUTE(Regs, IntType, VARPTR(ASM(0)))
  1087.  
  1088.   DEF SEG
  1089.  
  1090. END SUB
  1091.  
  1092. '<p>
  1093. '++++++++++++++++++++++++
  1094. SUB zzChangeDir (Directory$)
  1095.  DIM str AS STRING * 65
  1096.  
  1097.  str = LTRIM$(RTRIM$(UCASE$(Directory$))) + CHR$(0)
  1098.  IF MID$(str, 2, 1) = ":" THEN
  1099.   curdrive$ = MID$(str, 1, 1)
  1100.   str = MID$(str, 3)
  1101.  ELSE
  1102.   Regs.AX = &H1900
  1103.   CALL zzBasicInt(&H21)
  1104.   curdrive$ = CHR$(65 + (Regs.AX AND 255))
  1105.  END IF
  1106.  IF MID$(str, 1, 1) = CHR$(0) THEN
  1107.   GOSUB zzChangeDirAA
  1108.   EXIT SUB
  1109.  END IF
  1110.  str = curdrive$ + ":" + str
  1111.  Regs.AX = &H3B00
  1112.  Regs.DS = VARSEG(str)
  1113.  Regs.DX = VARPTR(str)
  1114.  CALL zzBasicInt(&H21)
  1115.  IF (Regs.FL AND 256) = 256 THEN
  1116.   Directory$ = ""
  1117.  ELSE
  1118.   GOSUB zzChangeDirAA
  1119.  END IF
  1120.  EXIT SUB
  1121.  
  1122. zzChangeDirAA:
  1123.   Regs.AX = &H4700
  1124.   Regs.DX = ASC(curdrive$) - 64
  1125.   Regs.DS = VARSEG(str)
  1126.   Regs.SI = VARPTR(str)
  1127.   CALL zzBasicInt(&H21)
  1128.   i = INSTR(str, CHR$(0))
  1129.   Directory$ = curdrive$ + ":\" + MID$(str, 1, i - 1)
  1130.   RETURN
  1131. END SUB
  1132.  
  1133. '<p>
  1134. '++++++++++++++++++++++++
  1135. SUB zzChangeDrive (Drive$)
  1136.  
  1137.  CALL zzCritOff
  1138.  GOSUB zzChangeDriveProcess
  1139.  CALL zzCritOn
  1140.  
  1141.  EXIT SUB
  1142.  
  1143. zzChangeDriveProcess:
  1144.  
  1145.  Drive$ = LTRIM$(RTRIM$(UCASE$(Drive$)))
  1146.  IF LEN(Drive$) = 0 THEN
  1147.   Regs.AX = &H1900
  1148.   CALL zzBasicInt(&H21)
  1149.   Drive$ = CHR$(65 + (Regs.AX AND 255)) + ":"
  1150.   RETURN
  1151.  END IF
  1152.  
  1153.  IF LEN(Drive$) = 1 THEN Drive$ = Drive$ + ":"
  1154.  IF LEN(Drive$) > 2 THEN Drive$ = "?"
  1155.  
  1156.  IF MID$(Drive$, 2, 1) = ":" THEN
  1157.   drv = ASC(Drive$)
  1158.   Drive$ = "?"
  1159.   IF drv < 65 THEN RETURN
  1160.   IF drv > 90 THEN RETURN
  1161.   drv = drv - 65
  1162.  
  1163. ' establish whether this is a shared drive
  1164.  
  1165.   Regs.AX = &H440E
  1166.   Regs.BX = drv + 1
  1167.   CALL zzBasicInt(&H21)
  1168.   IF (Regs.FL AND 256) = 256 THEN
  1169.    Regs.AX = 0
  1170.   END IF
  1171.   Regs.AX = Regs.AX AND 255
  1172.   IF Regs.AX <> 0 THEN
  1173.    IF Regs.AX <> drv + 1 THEN
  1174.     drv = Regs.AX - 1
  1175.    END IF
  1176.   END IF
  1177.  
  1178. ' establish whether this is a valid drive
  1179.  
  1180.   Regs.AX = &H1C00
  1181.   Regs.DX = drv + 1
  1182.   CALL zzBasicInt(&H21)
  1183.   IF (Regs.AX AND 255) = 255 THEN RETURN
  1184.  
  1185. ' now change to it
  1186.  
  1187.   Regs.AX = &HE00
  1188.   Regs.DX = drv
  1189.   CALL zzBasicInt(&H21)
  1190.  
  1191.   Drive$ = CHR$(65 + drv) + ":"
  1192.  
  1193.  
  1194.  ELSE
  1195.   Drive$ = "?"
  1196.  END IF
  1197.  RETURN
  1198.  
  1199. END SUB
  1200.  
  1201. SUB zzCritOff
  1202.  
  1203.  Regs.AX = &H2524
  1204.  Regs.DS = VARSEG(IRET)
  1205.  Regs.DX = VARPTR(IRET)
  1206.  CALL zzBasicInt(&H21)
  1207.  CritCount = CritCount + 1
  1208.  
  1209. END SUB
  1210.  
  1211. SUB zzCritOn
  1212.  
  1213.  CritCount = CritCount - 1
  1214.  IF CritCount = 0 THEN
  1215.   Regs.AX = &H2524
  1216.   Regs.DS = CritSeg
  1217.   Regs.DX = CritPtr
  1218.   CALL zzBasicInt(&H21)
  1219.  END IF
  1220.  
  1221. END SUB
  1222.  
  1223. '<p>
  1224. '++++++++++++++++++++++++
  1225. SUB zzFileSelectBox (Pattern$)
  1226.  
  1227. DIM Devices(26)  ';valid devices have a non-zero value
  1228. DIM validDevs(27)
  1229.  
  1230. DIM parts$(11) ';ten deep is allowed
  1231. DIM Dirs$(200) ';lots of subdirectories
  1232. DIM Files$(200) ';lots of files
  1233. DIM str AS STRING * 65
  1234.  
  1235.  CALL zzCritOff
  1236.  GOSUB zzFileSelectBoxProcess
  1237.  CALL zzCritOn
  1238.  
  1239.  EXIT SUB
  1240.  
  1241. zzFileSelectBoxProcess:
  1242.  
  1243. ' create the screen
  1244.  
  1245.   IF screendone = 0 THEN
  1246.    bg = 7: fg = 15
  1247.    CALL zsSetScrnMode(9, 1, 1)
  1248.    fg = 0
  1249.    CALL ziPublishHere(3, 34, "Select a File", 1, 3)
  1250.    Stuff$ = "(Please Wait)"
  1251.    fg = 14
  1252.    GOSUB zzFileSelectBoxDD
  1253.  
  1254. ' print the headers
  1255.  
  1256.    fg = 8
  1257.    CALL ziPublishHere(42, 17, "Use left & right arrow keys to change columns", 0, 1)
  1258.   END IF
  1259.   screendone = 1
  1260.  
  1261.   fg = 8: CALL ziPublishHere(8, 2, "Drives", 2, 1): fg = 0
  1262.   LINE (10, 7)-(Xmax - 10, Ymax - 7), 4, B
  1263.  
  1264.  
  1265.   IF NoDriveSelection = 0 THEN
  1266.    dev = 0: GOSUB zzFileSelectBoxAA
  1267.  
  1268. ' find the DTA
  1269.  
  1270.    Regs.AX = &H2F00
  1271.    CALL zzBasicInt(&H21)
  1272.    DTAseg = Regs.ES
  1273.    DTAptr = Regs.BX
  1274.  
  1275. ' establish the existing devices
  1276.  
  1277.    MaxDevs = 0
  1278.    FOR i = 1 TO 26
  1279.     Devices(i) = 0
  1280.     validDevs(i) = 0
  1281.     Regs.AX = &H440E
  1282.     Regs.BX = i
  1283.     CALL zzBasicInt(&H21)
  1284.     IF (Regs.FL AND 256) = 256 THEN
  1285.      Regs.AX = 0
  1286.     END IF
  1287.     Regs.AX = Regs.AX AND 255
  1288.     IF (Regs.AX = 0) OR (Regs.AX = i) THEN
  1289.      Regs.AX = &H1C00
  1290.      Regs.DX = i
  1291.      CALL zzBasicInt(&H21)
  1292.      IF (Regs.AX AND 255) <> 255 THEN
  1293.       MaxDevs = MaxDevs + 1
  1294.       Devices(i) = MaxDevs '; set the crossreference
  1295.       validDevs(MaxDevs) = i
  1296.      END IF
  1297.     END IF
  1298.    NEXT
  1299.  
  1300. ' print the valid drives as a list
  1301.  
  1302.    fg = 0
  1303.    FOR i = 1 TO MaxDevs
  1304.     x$ = CHR$(64 + validDevs(i)) + ":"
  1305.     CALL ziPublishHere(10 + i + i, 7, x$, 1, 0)
  1306.    NEXT
  1307.   END IF
  1308.   LINE (GXloc - 16, GYloc + 8)-(GXloc, 319), 7, BF 'clear rest of list
  1309.  
  1310.  
  1311.   NoDriveSelection = 0
  1312.  
  1313.   fg = 8: CALL ziPublishHere(8, 20, "Tree", 2, 1): fg = 0
  1314.   LINE (10, 7)-(Xmax - 10, Ymax - 7), 4, B
  1315.  
  1316. ' carve off any 'wildcard' from the specified input parameter
  1317.  
  1318.   Pattern$ = UCASE$(LTRIM$(RTRIM$(Pattern$)))
  1319.   str = Pattern$
  1320.   IF INSTR(str, "?") + INSTR(str, "*") = 0 THEN
  1321.    base$ = Pattern$
  1322.    wild$ = "*.*"
  1323.   ELSE
  1324.    IF MID$(str, 2, 1) = ":" THEN
  1325.     start = 3
  1326.    ELSE
  1327.     start = 1
  1328.    END IF
  1329.    DO
  1330.     i = INSTR(start, str, "\")
  1331.     IF i <> 0 THEN
  1332.      start = i + 1
  1333.     END IF
  1334.    LOOP UNTIL i = 0
  1335.    base$ = MID$(str, 1, start - 1)
  1336.    wild$ = MID$(RTRIM$(str), start)
  1337.   END IF
  1338.  
  1339.   CALL zzValidate(base$)
  1340.   IF base$ = "?" THEN
  1341.    base$ = ""
  1342.    CALL zzChangeDir(base$)
  1343.   END IF
  1344.  
  1345.  
  1346.   IF MID$(base$, LEN(base$)) = "\" THEN
  1347.    basex$ = MID$(base$, 1, LEN(base$) - 1)
  1348.   ELSE
  1349.    basex$ = base$
  1350.   END IF
  1351.  
  1352.  
  1353.  
  1354. ' validate the "wildcard" portion
  1355.  
  1356. ' (make sure no more than one ".")
  1357.  
  1358.   i = INSTR(wild$, ".")
  1359.   IF i <> 0 THEN
  1360.    x$ = wild$
  1361.    MID$(x$, i, 1) = "+"
  1362.    IF INSTR(x$, ".") THEN
  1363.     wild$ = "*.*"
  1364.     i = 2
  1365.    END IF
  1366.   END IF
  1367.  
  1368. ' (divide it into its two component parts)
  1369.  
  1370.   IF i < 2 THEN
  1371.    wildl$ = wild$
  1372.    wildr$ = ""
  1373.   ELSE
  1374.    wildl$ = MID$(wild$, 1, i - 1)
  1375.    wildr$ = MID$(wild$, i + 1)
  1376.   END IF
  1377.   IF LEN(wildl$) > 8 OR LEN(wildr$) > 3 THEN
  1378.    wild$ = "*.*"
  1379.    wildl$ = "*"
  1380.    wildr$ = "*"
  1381.   END IF
  1382.  
  1383. ' (make sure no more than one TRAILING "*" in left part)
  1384.  
  1385.   i = INSTR(wildl$, "*")
  1386.   IF i <> 0 THEN
  1387.    IF i <> LEN(wildl$) THEN
  1388.     wild$ = "*.*"
  1389.     wildl$ = "*"
  1390.     wildr$ = "*"
  1391.    END IF
  1392.   END IF
  1393.  
  1394. ' (make sure no more than one TRAILING "*" in right part)
  1395.  
  1396.   i = INSTR(wildr$, "*")
  1397.   IF i <> 0 THEN
  1398.    IF i <> LEN(wildr$) THEN
  1399.     wild$ = "*.*"
  1400.     wildl$ = "*"
  1401.     wildr$ = "*"
  1402.    END IF
  1403.   END IF
  1404.  
  1405.   i = 39 - LEN(wild$) \ 2
  1406.   x$ = "[" + wild$ + "]"
  1407.   CALL ziPublishHere(7, i, x$, 0, 0)
  1408.  
  1409. ' determine the specified drive
  1410.  
  1411.   dev = Devices(ASC(base$) - 64)
  1412.   GOSUB zzFileSelectBoxAA
  1413.  
  1414. ' create the tree
  1415.  
  1416.   FOR i = 0 TO 11
  1417.    parts$(i) = ""
  1418.   NEXT
  1419.   x$ = basex$ + "\"
  1420.  
  1421.   levels = 0
  1422.   DO
  1423.    i = INSTR(x$, "\")
  1424.    IF i <> 0 THEN
  1425.     parts$(levels) = MID$(x$, 1, i - 1)
  1426.     levels = levels + 1
  1427.     x$ = MID$(x$, i + 1)
  1428.    END IF
  1429.   LOOP UNTIL i = 0
  1430.   parts$(0) = parts$(0) + "\"
  1431.   levels = levels - 1
  1432.  
  1433.   CALL ziPublishHere(12, 15, parts$(0), 0, 0)
  1434.  
  1435.   IF levels > 0 THEN
  1436.    FOR i = 1 TO levels
  1437.     x$ = SPACE$(i + i) + CHR$(179)
  1438.     CALL ziPublishHere(11 + i + i, 13, x$, 0, 0)
  1439.     x$ = SPACE$(i + i) + CHR$(192) + CHR$(196) + parts$(i)
  1440.     CALL ziPublishHere(12 + i + i, 13, x$, 0, 0)
  1441.    NEXT
  1442.   END IF
  1443.  
  1444.   oldtree = 255
  1445.   tree = levels
  1446.   GOSUB zzFileSelectBoxHH
  1447.  
  1448.  
  1449. ' test for subdirectories present
  1450.  
  1451.   olddline = 0
  1452.   x$ = basex$ + "\*.*"
  1453.   CALL zzSearchD(x$)
  1454.  
  1455.   IF Directories <> 0 THEN
  1456.    fg = 8: CALL ziPublishHere(8, 64, "Subdirs", 2, 1): fg = 0
  1457.    FromDir = 1
  1458.    GOSUB zzFileSelectBoxEE
  1459.   END IF
  1460.  
  1461. ' test for files present
  1462.  
  1463.   x$ = basex$ + "\" + wild$
  1464.   CALL zzSearchF(x$)
  1465.  
  1466.   IF FileNames <> 0 THEN
  1467.    fg = 8: CALL ziPublishHere(8, 51, "Files", 2, 1): fg = 0
  1468.    FromFile = 1
  1469.    GOSUB zzFileSelectBoxFF
  1470.   END IF
  1471.  
  1472. ' determine where to start
  1473.  
  1474.   IF FileNames = 0 THEN
  1475.    IF Directories = 0 THEN
  1476.     fg = 4: CALL ziPublishHere(8, 20, "Tree", 2, 1): fg = 0
  1477.     Stuff$ = basex$ + "\"
  1478.     GOSUB zzFileSelectBoxDD
  1479.     Column = 2
  1480.    ELSE
  1481.     fg = 4: CALL ziPublishHere(8, 64, "Subdirs", 2, 1): fg = 0
  1482.     dline = 1
  1483.     GOSUB zzFileSelectBoxBB
  1484.     Stuff$ = basex$ + "\" + Directories$(FromDir)
  1485.     GOSUB zzFileSelectBoxDD
  1486.     Column = 4
  1487.    END IF
  1488.  
  1489.   ELSE
  1490.    fg = 4: CALL ziPublishHere(8, 51, "Files", 2, 1): fg = 0
  1491.    fline = 1
  1492.    GOSUB zzFileSelectBoxCC
  1493.    Column = 3
  1494.   END IF
  1495.  
  1496.  
  1497. ' determine what to do, based on keystroke
  1498.  
  1499.   DO
  1500.    stroke$ = "X"
  1501.    DO
  1502.     stroke$ = INKEY$
  1503.    LOOP UNTIL LEN(stroke$) = 0
  1504.    DO
  1505.     stroke$ = INKEY$
  1506.    LOOP WHILE LEN(stroke$) = 0
  1507.    IF LEN(stroke$) = 1 THEN
  1508.     stroke$ = UCASE$(stroke$)
  1509.     SELECT CASE ASC(stroke$)
  1510.     CASE 27   'ESC
  1511.      Pattern$ = "?"
  1512.      RETURN
  1513.     CASE 13   'Enter
  1514.      SELECT CASE Column
  1515.      CASE 1    'enactivate new drive
  1516.       x$ = CHR$(validDevs(dev) + 64) + ":"
  1517.       Pattern$ = x$ + "\" + wild$
  1518.       LINE (112, 88)-(383, 319), 7, BF  'clear the "tree" area
  1519.  
  1520.  
  1521.       GOSUB zzFileSelectBoxII
  1522.       GOTO zzFileSelectBoxProcess
  1523.  
  1524.      CASE 2    'choose new directory
  1525.       IF tree <> levels THEN
  1526.        base$ = ""
  1527.        FOR i = 0 TO tree
  1528.     base$ = base$ + parts$(i)
  1529.     IF MID$(base$, LEN(base$)) <> "\" THEN
  1530.      base$ = base$ + "\"
  1531.     END IF
  1532.        NEXT
  1533.        IF MID$(base$, LEN(base$)) <> "\" THEN
  1534.     base$ = base$ + "\"
  1535.        END IF
  1536.        Pattern$ = base$ + wild$
  1537.        NoDriveSelection = 1
  1538.        GOSUB zzFileSelectBoxII
  1539.        GOTO zzFileSelectBoxProcess
  1540.       END IF
  1541.  
  1542.  
  1543.      CASE 3    'exit with chosen filename
  1544.       Pattern$ = Stuff$
  1545.       RETURN
  1546.  
  1547.      CASE 4    'choose new subdirectory
  1548.       Pattern$ = basex$ + "\" + Directories$(FromDir + dline - 1)
  1549.       Pattern$ = Pattern$ + "\" + wild$
  1550.       NoDriveSelection = 1
  1551.       GOSUB zzFileSelectBoxII
  1552.       GOTO zzFileSelectBoxProcess
  1553.  
  1554.  
  1555.      END SELECT
  1556.  
  1557.     CASE ASC("A") TO ASC("Z")
  1558.      SELECT CASE Column
  1559.      CASE 1
  1560.       i = ASC(stroke$) - 64
  1561.       IF Devices(i) <> 0 THEN
  1562.        dev = Devices(i)
  1563.        GOSUB zzFileSelectBoxAA
  1564.       END IF
  1565.      CASE 3
  1566.       i = FileNames
  1567.       x$ = MID$(FileNames$(i), 1, 1)
  1568.       IF x$ >= stroke$ THEN
  1569.        i = 0
  1570.        DO
  1571.     i = i + 1
  1572.     x$ = MID$(FileNames$(i), 1, 1)
  1573.        LOOP WHILE x$ < stroke$
  1574.       END IF
  1575.       FromFile = i
  1576.       GOSUB zzFileSelectBoxFF
  1577.       fline = 1: GOSUB zzFileSelectBoxCC
  1578.  
  1579.      CASE 4
  1580.       i = Directories
  1581.       x$ = MID$(Directories$(i), 1, 1)
  1582.       IF x$ >= stroke$ THEN
  1583.        i = 0
  1584.        DO
  1585.     i = i + 1
  1586.     x$ = MID$(Directories$(i), 1, 1)
  1587.        LOOP WHILE x$ < stroke$
  1588.       END IF
  1589.       FromDir = i
  1590.       GOSUB zzFileSelectBoxEE
  1591.       dline = 1: GOSUB zzFileSelectBoxBB
  1592.  
  1593.      END SELECT
  1594.     END SELECT
  1595.    ELSE
  1596.     SELECT CASE MID$(stroke$, 2)
  1597.     CASE "I"    'Page UP
  1598.      SELECT CASE Column
  1599.      CASE 3
  1600.       OldFromFile = FromFile
  1601.       IF FromFile + fline > 31 THEN
  1602.        FromFile = FromFile + fline - 31
  1603.       ELSE
  1604.        FromFile = 1
  1605.       END IF
  1606.       IF OldFromFile <> FromFile THEN GOSUB zzFileSelectBoxFF
  1607.       fline = 1: GOSUB zzFileSelectBoxCC
  1608.      CASE 4
  1609.       OldFromDir = FromDir
  1610.       IF FromDir + dline > 31 THEN
  1611.        FromDir = FromDir + dline - 31
  1612.       ELSE
  1613.        FromDir = 1
  1614.       END IF
  1615.       IF OldFromDir <> FromDir THEN GOSUB zzFileSelectBoxEE
  1616.       dline = 1: GOSUB zzFileSelectBoxBB
  1617.      END SELECT
  1618.     CASE "Q"    'Page DN
  1619.      SELECT CASE Column
  1620.      CASE 3
  1621.       OldFromFile = FromFile
  1622.       IF FromFile + fline + 30 < FileNames THEN
  1623.        FromFile = FromFile + fline + 29
  1624.        IF OldFromFile <> FromFile THEN GOSUB zzFileSelectBoxFF
  1625.        fline = 1: GOSUB zzFileSelectBoxCC
  1626.       END IF
  1627.      CASE 4
  1628.       OldFromDir = FromDir
  1629.       IF FromDir + dline + 30 < Directories THEN
  1630.        FromDir = FromDir + dline + 29
  1631.        IF OldFromDir <> FromDir THEN GOSUB zzFileSelectBoxEE
  1632.        dline = 1: GOSUB zzFileSelectBoxBB
  1633.       END IF
  1634.      END SELECT
  1635.     CASE "G"    'HOME
  1636.      SELECT CASE Column
  1637.      CASE 3
  1638.       IF FromFile <> 1 THEN
  1639.        FromFile = 1
  1640.        GOSUB zzFileSelectBoxFF
  1641.       END IF
  1642.       fline = 1: GOSUB zzFileSelectBoxCC
  1643.      CASE 4
  1644.       IF FromDir <> 1 THEN
  1645.        FromDir = 1
  1646.        GOSUB zzFileSelectBoxEE
  1647.       END IF
  1648.       dline = 1: GOSUB zzFileSelectBoxBB
  1649.      END SELECT
  1650.     CASE "O"    'END
  1651.      SELECT CASE Column
  1652.      CASE 3
  1653.       OldFromFile = FromFile
  1654.       FromFile = FileNames - 29
  1655.       IF FromFile < 1 THEN
  1656.        FromFile = 1
  1657.       END IF
  1658.       IF OldFromFile <> FromFile THEN GOSUB zzFileSelectBoxFF
  1659.       fline = 1: GOSUB zzFileSelectBoxCC
  1660.      CASE 4
  1661.       OldFromDir = FromDir
  1662.       FromDir = Directories - 29
  1663.       IF FromDir < 1 THEN
  1664.        FromDir = 1
  1665.       END IF
  1666.       IF OldFromDir <> FromDir THEN GOSUB zzFileSelectBoxEE
  1667.       dline = 1: GOSUB zzFileSelectBoxBB
  1668.      END SELECT
  1669.     CASE "H"    'UP
  1670.      SELECT CASE Column
  1671.      CASE 1     'drives
  1672.       IF dev > 1 THEN
  1673.        dev = dev - 1
  1674.        GOSUB zzFileSelectBoxAA
  1675.       END IF
  1676.      CASE 2     'tree
  1677.       IF tree > 0 THEN
  1678.        tree = tree - 1
  1679.        GOSUB zzFileSelectBoxHH
  1680.       END IF
  1681.      CASE 3     'files
  1682.       i = FromFile + fline - 2
  1683.       IF i > 0 THEN
  1684.        IF fline > 1 THEN
  1685.     fline = fline - 1
  1686.     GOSUB zzFileSelectBoxCC
  1687.        ELSE
  1688.     OldFromFile = FromFile
  1689.     FromFile = FromFile - 30
  1690.     fline = fline + 29
  1691.     IF FromFile < 1 THEN
  1692.      fline = fline + FromFile - 1
  1693.      FromFile = 1
  1694.     END IF
  1695.     IF OldFromFile <> FromFile THEN GOSUB zzFileSelectBoxFF
  1696.     GOSUB zzFileSelectBoxCC
  1697.        END IF
  1698.       END IF
  1699.      CASE 4     'subdirs
  1700.       i = FromDir + dline - 2
  1701.       IF i > 0 THEN
  1702.        IF dline > 1 THEN
  1703.     dline = dline - 1
  1704.     GOSUB zzFileSelectBoxBB
  1705.        ELSE
  1706.     OldFromDir = FromDir
  1707.     FromDir = FromDir - 30
  1708.     dline = dline + 29
  1709.     IF FromDir < 1 THEN
  1710.      dline = dline + FromDir - 1
  1711.      FromDir = 1
  1712.     END IF
  1713.     IF OldFromDir <> FromDir THEN GOSUB zzFileSelectBoxEE
  1714.     GOSUB zzFileSelectBoxBB
  1715.        END IF
  1716.       END IF
  1717.      END SELECT
  1718.  
  1719.     CASE "P"   'DOWN
  1720.      SELECT CASE Column
  1721.      CASE 1     'drives
  1722.       IF dev < MaxDevs THEN
  1723.        dev = dev + 1
  1724.        GOSUB zzFileSelectBoxAA
  1725.       END IF
  1726.      CASE 2     'tree
  1727.       IF tree < levels THEN
  1728.        tree = tree + 1
  1729.        GOSUB zzFileSelectBoxHH
  1730.       END IF
  1731.      CASE 3     'files
  1732.       i = FromFile + fline
  1733.       IF i <= FileNames THEN
  1734.        IF fline < 30 THEN
  1735.     fline = fline + 1
  1736.     GOSUB zzFileSelectBoxCC
  1737.        ELSE
  1738.     FromFile = i: GOSUB zzFileSelectBoxFF
  1739.     fline = 1: GOSUB zzFileSelectBoxCC
  1740.        END IF
  1741.       END IF
  1742.      CASE 4     'subdirs
  1743.       i = FromDir + dline
  1744.       IF i <= Directories THEN
  1745.        IF dline < 30 THEN
  1746.     dline = dline + 1
  1747.     GOSUB zzFileSelectBoxBB
  1748.        ELSE
  1749.     FromDir = i: GOSUB zzFileSelectBoxEE
  1750.     dline = 1: GOSUB zzFileSelectBoxBB
  1751.        END IF
  1752.       END IF
  1753.      END SELECT
  1754.     CASE "K"   'LEFT
  1755.      SELECT CASE Column
  1756.      CASE 2     'from TREE to DRIVES
  1757.       tree = levels
  1758.       GOSUB zzFileSelectBoxHH
  1759.       fg = 8: CALL ziPublishHere(8, 20, "Tree", 2, 1)
  1760.       fg = 4: CALL ziPublishHere(8, 2, "Drives", 2, 1): fg = 0
  1761.       LINE (10, 7)-(Xmax - 10, Ymax - 7), 4, B
  1762.       Column = 1
  1763.      CASE 3     'from FILES to TREE
  1764.       fg = 8: CALL ziPublishHere(8, 51, "Files", 2, 1)
  1765.       fg = 4: CALL ziPublishHere(8, 20, "Tree", 2, 1): fg = 0
  1766.       Column = 2
  1767.      CASE 4     'from SUBDIRS to ?
  1768.       dline = 0: GOSUB zzFileSelectBoxBB
  1769.       fg = 8: CALL ziPublishHere(8, 64, "Subdirs", 2, 1): fg = 4
  1770.       IF FileNames = 0 THEN
  1771.        CALL ziPublishHere(8, 20, "Tree", 2, 1)
  1772.        Column = 2
  1773.       ELSE
  1774.        CALL ziPublishHere(8, 51, "Files", 2, 1)
  1775.        Column = 3
  1776.       END IF
  1777.       fg = 0
  1778.      END SELECT
  1779.  
  1780.     CASE "M"   'RIGHT
  1781.      SELECT CASE Column
  1782.      CASE 1     'from DRIVES to TREE
  1783.       dev = Devices(ASC(base$) - 64)
  1784.       GOSUB zzFileSelectBoxAA     'return to original drive
  1785.       fg = 8: CALL ziPublishHere(8, 2, "Drives", 2, 1)
  1786.       fg = 15: LINE (10, 7)-(Xmax - 10, Ymax - 7), 4, B
  1787.       fg = 4: CALL ziPublishHere(8, 20, "Tree", 2, 1): fg = 0
  1788.       Column = 2
  1789.      CASE 2     'from TREE to ?
  1790.       tree = levels
  1791.       GOSUB zzFileSelectBoxHH
  1792.       IF FileNames = 0 THEN
  1793.        IF Directories <> 0 THEN
  1794.     fg = 8: CALL ziPublishHere(8, 20, "Tree", 2, 1)
  1795.     fg = 4: CALL ziPublishHere(8, 64, "Subdirs", 2, 1): fg = 0
  1796.     dline = 1: GOSUB zzFileSelectBoxBB
  1797.     Column = 4
  1798.        END IF
  1799.       ELSE
  1800.        fg = 8: CALL ziPublishHere(8, 20, "Tree", 2, 1)
  1801.        fg = 4: CALL ziPublishHere(8, 51, "Files", 2, 1): fg = 0
  1802.        Column = 3
  1803.       END IF
  1804.      CASE 3     'from FILES to SUBDIRS (if possible)
  1805.       IF Directories <> 0 THEN
  1806.        fg = 8: CALL ziPublishHere(8, 51, "Files", 2, 1)
  1807.        fg = 4: CALL ziPublishHere(8, 64, "Subdirs", 2, 1): fg = 0
  1808.        dline = 1: GOSUB zzFileSelectBoxBB
  1809.        Column = 4
  1810.       END IF
  1811.      END SELECT
  1812.     END SELECT
  1813.    END IF
  1814.  
  1815.   LOOP
  1816.  
  1817. '   ╔════════════════╗
  1818. '   ║      AA        ╟─────────────────────────────────────────────┐
  1819. '   ╚╤═══════════════╝                                             │
  1820. '    │         change the cursor bar on "dev"                      │
  1821. '    │                                                             │
  1822. '    │         input: dev   output: olddev                         │
  1823. '    └─────────────────────────────────────────────────────────────┘
  1824. zzFileSelectBoxAA:
  1825.  IF dev <> olddev THEN
  1826.   FromRow = 10 + olddev + olddev
  1827.   ToRow = FromRow
  1828.   FromCol = 5
  1829.   ToCol = 10
  1830.   swap1 = bg: swap2 = fg
  1831.   IF olddev > 0 THEN
  1832.    GOSUB zzFileSelectBoxGG
  1833.   END IF
  1834.   FromRow = 10 + dev + dev
  1835.   ToRow = FromRow
  1836.   olddev = dev
  1837.   IF olddev > 0 THEN
  1838.    GOSUB zzFileSelectBoxGG
  1839.   END IF
  1840.  END IF
  1841.  RETURN
  1842.  
  1843.  
  1844.  
  1845. '   ╔════════════════╗
  1846. '   ║      BB        ╟─────────────────────────────────────────────┐
  1847. '   ╚╤═══════════════╝                                             │
  1848. '    │         change the cursor bar on "dline"                    │
  1849. '    │                                                             │
  1850. '    │         input: dline   output: olddline                     │
  1851. '    └─────────────────────────────────────────────────────────────┘
  1852. zzFileSelectBoxBB:
  1853.  IF dline <> olddline THEN
  1854.   FromRow = 10 + olddline
  1855.   ToRow = FromRow
  1856.   FromCol = 67
  1857.   ToCol = 78
  1858.   swap1 = bg: swap2 = fg
  1859.   IF olddline > 0 THEN GOSUB zzFileSelectBoxGG
  1860.   FromRow = 10 + dline
  1861.   ToRow = FromRow
  1862.   olddline = dline
  1863.   IF dline > 0 THEN GOSUB zzFileSelectBoxGG
  1864.  END IF
  1865.  RETURN
  1866.  
  1867.  
  1868.  
  1869. '   ╔════════════════╗
  1870. '   ║      CC        ╟─────────────────────────────────────────────┐
  1871. '   ╚╤═══════════════╝                                             │
  1872. '    │         change the cursor bar on "fline"                    │
  1873. '    │                                                             │
  1874. '    │         input: fline   output: oldfline                     │
  1875. '    └─────────────────────────────────────────────────────────────┘
  1876. zzFileSelectBoxCC:
  1877.  IF fline <> oldfline THEN
  1878.   FromRow = 10 + oldfline
  1879.   ToRow = FromRow
  1880.   FromCol = 51
  1881.   ToCol = 62
  1882.   swap1 = bg: swap2 = fg
  1883.   IF oldfline > 0 THEN
  1884.    GOSUB zzFileSelectBoxGG
  1885.   END IF
  1886.   FromRow = 10 + fline
  1887.   ToRow = FromRow
  1888.   oldfline = fline
  1889.   GOSUB zzFileSelectBoxGG
  1890.   Stuff$ = basex$ + "\" + FileNames$(FromFile + fline - 1)
  1891.   GOSUB zzFileSelectBoxDD
  1892.  END IF
  1893.  RETURN
  1894.  
  1895.  
  1896. '   ╔════════════════╗
  1897. '   ║      DD        ╟─────────────────────────────────────────────┐
  1898. '   ╚╤═══════════════╝                                             │
  1899. '    │     Determine middle of line for publishing "Stuff$"        │
  1900. '    │                                                             │
  1901. '    │                                                             │
  1902. '    └─────────────────────────────────────────────────────────────┘
  1903. zzFileSelectBoxDD:
  1904.  LINE (38, 26)-(601, 46), 3, BF
  1905.  LINE (38, 26)-(601, 46), 8, B
  1906.  CALL ziPublishHere(5, 40 - LEN(Stuff$) \ 2, Stuff$, 1, 2)
  1907.  
  1908.  RETURN
  1909.  
  1910.  
  1911.  
  1912. '   ╔════════════════╗
  1913. '   ║      EE        ╟─────────────────────────────────────────────┐
  1914. '   ╚╤═══════════════╝                                             │
  1915. '    │         Show 30 subdirectories                              │
  1916. '    │                                                             │
  1917. '    │   input: FromDir                                            │
  1918. '    │                                                             │
  1919. '    │                                                             │
  1920. '    └─────────────────────────────────────────────────────────────┘
  1921. zzFileSelectBoxEE:
  1922.  
  1923.  LINE (512, 80)-(Xmax - 11, 319), 7, BF
  1924.  IF FromDir > Directories THEN RETURN
  1925.  IF FromDir > 1 THEN
  1926.   fg = 4: CALL ziPublishHere(11, 65, CHR$(24), 0, 0): fg = 0
  1927.  END IF
  1928.  IF FromDir + 30 <= Directories THEN
  1929.   fg = 4: CALL ziPublishHere(40, 65, CHR$(25), 0, 0): fg = 0
  1930.   j = FromDir + 29
  1931.  ELSE
  1932.   j = Directories
  1933.  END IF
  1934.  
  1935.  FOR i = FromDir TO j
  1936.   k = INSTR(Directories$(i), ".")
  1937.   IF k = 0 THEN
  1938.    x$ = Directories$(i)
  1939.   ELSE
  1940.    x$ = MID$(Directories$(i), 1, k - 1) + SPACE$(8)
  1941.    x$ = MID$(x$, 1, 9) + MID$(Directories$(i), k + 1)
  1942.   END IF
  1943.   CALL ziPublishHere(11 + i - FromDir, 67, x$, 0, 1)
  1944.  NEXT
  1945.  olddline = 0
  1946.  
  1947.  RETURN
  1948.  
  1949.  
  1950. '   ╔════════════════╗
  1951. '   ║      FF        ╟─────────────────────────────────────────────┐
  1952. '   ╚╤═══════════════╝                                             │
  1953. '    │         Show 30 filenames                                   │
  1954. '    │                                                             │
  1955. '    │   input: FromFile                                           │
  1956. '    │                                                             │
  1957. '    │                                                             │
  1958. '    └─────────────────────────────────────────────────────────────┘
  1959. zzFileSelectBoxFF:
  1960.  
  1961.  LINE (384, 80)-(495, 319), 7, BF
  1962.  IF FromFile > FileNames THEN RETURN
  1963.  IF FromFile > 1 THEN
  1964.   fg = 4: CALL ziPublishHere(11, 49, CHR$(24), 0, 0): fg = 0
  1965.  END IF
  1966.  IF FromFile + 30 <= FileNames THEN
  1967.   fg = 4: CALL ziPublishHere(40, 49, CHR$(25), 0, 0): fg = 0
  1968.   j = FromFile + 29
  1969.  ELSE
  1970.   j = FileNames
  1971.  END IF
  1972.  
  1973.  FOR i = FromFile TO j
  1974.   k = INSTR(FileNames$(i), ".")
  1975.   IF k = 0 THEN
  1976.    x$ = FileNames$(i)
  1977.   ELSE
  1978.    x$ = MID$(FileNames$(i), 1, k - 1) + SPACE$(8)
  1979.    x$ = MID$(x$, 1, 9) + MID$(FileNames$(i), k + 1)
  1980.   END IF
  1981.   CALL ziPublishHere(11 + i - FromFile, 51, x$, 0, 0)
  1982.  NEXT
  1983.  oldfline = 0
  1984.  
  1985.  RETURN
  1986.  
  1987.  
  1988. '   ╔════════════════╗
  1989. '   ║      GG        ╟─────────────────────────────────────────────┐
  1990. '   ╚╤═══════════════╝                                             │
  1991. '    │         Swap the colours (swap1 and swap2) of a region      │
  1992. '    │                                                             │
  1993. '    │  input: FromCol, FromRow, ToCol, ToRow, swap1, swap2        │
  1994. '    │                                                             │
  1995. '    │                                                             │
  1996. '    └─────────────────────────────────────────────────────────────┘
  1997. zzFileSelectBoxGG:
  1998.  fx = FromCol * 8 - 8
  1999.  fy = FromRow * 8 - 8
  2000.  tx = ToCol * 8 - 1
  2001.  ty = ToRow * 8 - 1
  2002.  FOR ix = fx TO tx
  2003.   FOR iy = fy TO ty
  2004.    SELECT CASE POINT(ix, iy)
  2005.    CASE swap1
  2006.     PSET (ix, iy), swap2
  2007.    CASE swap2
  2008.     PSET (ix, iy), swap1
  2009.    END SELECT
  2010.   NEXT
  2011.  NEXT
  2012.  RETURN
  2013.  
  2014. '   ╔════════════════╗
  2015. '   ║      HH        ╟─────────────────────────────────────────────┐
  2016. '   ╚╤═══════════════╝                                             │
  2017. '    │         change the cursor bar on "tree"                     │
  2018. '    │                                                             │
  2019. '    │         input: tree   output: oldtree                       │
  2020. '    └─────────────────────────────────────────────────────────────┘
  2021. zzFileSelectBoxHH:
  2022.  IF tree <> oldtree THEN
  2023.   FromRow = 12 + oldtree + oldtree
  2024.   ToRow = FromRow
  2025.   FromCol = 15 + oldtree + oldtree
  2026.   ToCol = FromCol + 11
  2027.   swap1 = bg: swap2 = fg
  2028.   IF oldtree <> 255 THEN
  2029.    GOSUB zzFileSelectBoxGG
  2030.   END IF
  2031.   FromRow = 12 + tree + tree
  2032.   ToRow = FromRow
  2033.   FromCol = 15 + tree + tree
  2034.   ToCol = FromCol + 11
  2035.   oldtree = tree
  2036.   GOSUB zzFileSelectBoxGG
  2037.  END IF
  2038.  RETURN
  2039.  
  2040.  
  2041. '   ╔════════════════╗
  2042. '   ║      II        ╟─────────────────────────────────────────────┐
  2043. '   ╚╤═══════════════╝                                             │
  2044. '    │         clear screen areas when changing directory          │
  2045. '    │                                                             │
  2046. '    │                                                             │
  2047. '    └─────────────────────────────────────────────────────────────┘
  2048. zzFileSelectBoxII:
  2049.  oldtree = 255
  2050.  oldfline = 0
  2051.  olddline = 0
  2052.  LINE (112, 16 * tree + 80)-(383, 319), 7, BF
  2053.  LINE (384, 56)-(495, 319), 7, BF
  2054.  LINE (504, 56)-(Xmax - 11, 319), 7, BF
  2055.  Stuff$ = "(Please Wait)"
  2056.  fg = 14: GOSUB zzFileSelectBoxDD: fg = 0
  2057.  RETURN
  2058.  
  2059. END SUB
  2060.  
  2061. '<p>
  2062. '++++++++++++++++++++++++
  2063. SUB zzInPath (Field$)
  2064.  
  2065.   x$ = ".;" + ENVIRON$("PATH")
  2066.   IF RIGHT$(x$, 1) <> ";" THEN x$ = x$ + ";"
  2067.   i = 1
  2068.   DO
  2069.     j = INSTR(i, x$, ";")
  2070.     IF j THEN
  2071.       y$ = UCASE$(MID$(x$, i, j - i))
  2072.       i = j + 1
  2073.       IF RIGHT$(y$, 1) <> "\" THEN y$ = y$ + "\"
  2074.       F$ = y$ + Field$
  2075.       Bad = 0
  2076.       OPEN "I", 1, F$
  2077.       IF Bad = 0 THEN
  2078.     CLOSE 1
  2079.     EXIT DO
  2080.       END IF
  2081.       F$ = ""
  2082.     END IF
  2083.   LOOP WHILE j
  2084.   Bad = 0
  2085.   Field$ = F$
  2086.  
  2087. END SUB
  2088.  
  2089. '<p>
  2090. '++++++++++++++++++++++++
  2091. SUB zzSearchD (Pattern$)
  2092.  
  2093. DIM str AS STRING * 65
  2094.  
  2095.  CALL zzCritOff
  2096.  GOSUB zzSearchDProcess
  2097.  CALL zzCritOn
  2098.  
  2099.  EXIT SUB
  2100.  
  2101. zzSearchDProcess:
  2102.   upperbound = UBOUND(Directories$)
  2103.   str = LTRIM$(RTRIM$(UCASE$(Pattern$)))
  2104.   Pattern$ = "?"
  2105.  
  2106. ' clear the Directories$ array
  2107.  
  2108.  FOR i = 1 TO 500
  2109.   Directories$(i) = ""
  2110.  NEXT
  2111.  Directories = 0
  2112.  
  2113. ' locate the DTA
  2114.  
  2115.  Regs.AX = &H2F00
  2116.  CALL zzBasicInt(&H21)
  2117.  DTAseg = Regs.ES
  2118.  DTAptr = Regs.BX
  2119.  
  2120. ' confirm that the drive (if specified) is valid
  2121.  
  2122.  IF MID$(str, 2, 1) = ":" THEN
  2123.   i = ASC(str)
  2124.   IF i < 65 THEN RETURN
  2125.   IF i > 90 THEN RETURN
  2126.   Regs.AX = &H440E
  2127.   Regs.BX = i - 64
  2128.   CALL zzBasicInt(&H21)
  2129.   IF (Regs.FL AND 256) <> 256 THEN
  2130.    j = Regs.AX AND 255
  2131.    IF (j <> 0) AND (j <> i - 64) THEN
  2132.     i = j + 64
  2133.    END IF
  2134.   END IF
  2135.   Regs.AX = &H1C00
  2136.   Regs.DX = i - 64
  2137.   CALL zzBasicInt(&H21)
  2138.   IF (Regs.AX AND 255) = 255 THEN RETURN
  2139.  END IF
  2140.  
  2141.  x$ = RTRIM$(str)
  2142.  IF (x$ = "") OR (MID$(x$, 2) = ":") THEN
  2143.   x$ = x$ + "*.*"
  2144.  END IF
  2145.  IF (MID$(x$, LEN(x$)) = "\") THEN
  2146.   x$ = x$ + "*.*"
  2147.  END IF
  2148.  
  2149.  IF INSTR(x$, "*") + INSTR(x$, "?") = 0 THEN
  2150.   x$ = x$ + "\*.*"
  2151.  END IF
  2152.  
  2153. ' initiate the search
  2154.  
  2155.  Pattern$ = x$
  2156.  str = x$ + CHR$(0)
  2157.  Regs.AX = &H4E00
  2158.  Regs.CX = &H10
  2159.  Regs.DS = VARSEG(str)
  2160.  Regs.DX = VARPTR(str)
  2161.  CALL zzBasicInt(&H21)
  2162.  
  2163.  DO WHILE (Regs.FL AND 256) = 0
  2164.   DEF SEG = DTAseg
  2165.  
  2166. ' pull the name (letter by letter) from the DTA
  2167.  
  2168.   IF (PEEK(DTAptr + &H15) AND &H10) = &H10 THEN
  2169.    Name$ = ""
  2170.    i = &H1E
  2171.    DO
  2172.     j = PEEK(DTAptr + i)
  2173.     IF j <> 0 THEN
  2174.      Name$ = Name$ + CHR$(j)
  2175.     END IF
  2176.     i = i + 1
  2177.    LOOP UNTIL j = 0
  2178.  
  2179. ' omit "." and ".."
  2180.  
  2181.    IF MID$(Name$, 1, 1) <> "." THEN
  2182.     Directories = Directories + 1
  2183.     IF Directories > upperbound THEN RETURN
  2184.     Directories$(Directories) = Name$
  2185.    END IF
  2186.   END IF
  2187.  
  2188. ' keep going until all matches are found
  2189.  
  2190.   Regs.AX = &H4F00
  2191.   CALL zzBasicInt(&H21)
  2192.  LOOP
  2193.  
  2194. ' now find the first byte of the directory pattern itself
  2195.  
  2196.  IF MID$(str, 2, 1) = ":" THEN
  2197.   start = 3
  2198.  ELSE
  2199.   start = 1
  2200.  END IF
  2201.  DO
  2202.   i = INSTR(start, str, "\")
  2203.   IF i <> 0 THEN
  2204.    start = i + 1
  2205.   END IF
  2206.  LOOP UNTIL i = 0
  2207.  x$ = MID$(str, 1, start - 1)
  2208.  CALL zzValidate(x$)
  2209.  IF MID$(x$, LEN(x$)) <> "\" THEN x$ = x$ + "\"
  2210.  i = INSTR(str, CHR$(0))
  2211.  
  2212.  Pattern$ = RTRIM$(x$ + MID$(str, start, i - start))
  2213.  
  2214.  IF Directories <> 0 THEN
  2215.   SortCount = Directories
  2216.   CALL zzAlphaSort(Directories$())
  2217.  END IF
  2218.  RETURN
  2219. END SUB
  2220.  
  2221. '<p>
  2222. '++++++++++++++++++++++++
  2223. SUB zzSearchF (Pattern$)
  2224.  
  2225. DIM str AS STRING * 65
  2226.  
  2227.  CALL zzCritOff
  2228.  GOSUB zzSearchFProcess
  2229.  CALL zzCritOn
  2230.  
  2231.  EXIT SUB
  2232.  
  2233. zzSearchFProcess:
  2234.  upperbound = UBOUND(FileNames$)
  2235.  str = LTRIM$(RTRIM$(UCASE$(Pattern$)))
  2236.  Pattern$ = "?"
  2237.  
  2238. ' clear the FileNames$ array
  2239.  
  2240.  FOR i = 1 TO 500
  2241.   FileNames$(i) = ""
  2242.  NEXT
  2243.  FileNames = 0
  2244.  
  2245. ' locate the DTA
  2246.  
  2247.  Regs.AX = &H2F00
  2248.  CALL zzBasicInt(&H21)
  2249.  DTAseg = Regs.ES
  2250.  DTAptr = Regs.BX
  2251.  
  2252. ' confirm that the drive (if specified) is valid
  2253.  
  2254.  IF MID$(str, 2, 1) = ":" THEN
  2255.   i = ASC(str)
  2256.   IF i < 65 THEN RETURN
  2257.   IF i > 90 THEN RETURN
  2258.   Regs.AX = &H440E
  2259.   Regs.BX = i - 64
  2260.   CALL zzBasicInt(&H21)
  2261.   IF (Regs.FL AND 256) <> 256 THEN
  2262.    j = Regs.AX AND 255
  2263.    IF (j <> 0) AND (j <> i - 64) THEN
  2264.     i = j + 64
  2265.    END IF
  2266.   END IF
  2267.   Regs.AX = &H1C00
  2268.   Regs.DX = i - 64
  2269.   CALL zzBasicInt(&H21)
  2270.   IF (Regs.AX AND 255) = 255 THEN RETURN
  2271.  END IF
  2272.  
  2273.  x$ = RTRIM$(str)
  2274.  IF (x$ = "") OR (MID$(x$, 2) = ":") THEN
  2275.   x$ = x$ + "*.*"
  2276.  END IF
  2277.  IF (MID$(x$, LEN(x$)) = "\") THEN
  2278.   x$ = x$ + "*.*"
  2279.  END IF
  2280.  
  2281.  IF INSTR(x$, "*") + INSTR(x$, "?") = 0 THEN
  2282.   x$ = x$ + "\*.*"
  2283.  END IF
  2284.  
  2285. ' initiate the search
  2286.  
  2287.  Pattern$ = x$
  2288.  str = x$ + CHR$(0)
  2289.  Regs.AX = &H4E00
  2290.  Regs.CX = &H27
  2291.  Regs.DS = VARSEG(str)
  2292.  Regs.DX = VARPTR(str)
  2293.  CALL zzBasicInt(&H21)
  2294.  
  2295.  DO WHILE (Regs.FL AND 256) = 0
  2296.   DEF SEG = DTAseg
  2297.  
  2298. ' pull the name (letter by letter) from the DTA
  2299.  
  2300.   Name$ = ""
  2301.   i = &H1E
  2302.   DO
  2303.    j = PEEK(DTAptr + i)
  2304.    IF j <> 0 THEN
  2305.     Name$ = Name$ + CHR$(j)
  2306.    END IF
  2307.    i = i + 1
  2308.   LOOP UNTIL j = 0
  2309.  
  2310.   FileNames = FileNames + 1
  2311.   IF FileNames > upperbound THEN RETURN
  2312.   FileNames$(FileNames) = Name$
  2313.  
  2314.   Regs.AX = &H4F00
  2315.   CALL zzBasicInt(&H21)
  2316.  LOOP
  2317.  
  2318.  
  2319. ' now find the first byte of the file pattern itself
  2320.  
  2321.  IF MID$(str, 2, 1) = ":" THEN
  2322.   start = 3
  2323.  ELSE
  2324.   start = 1
  2325.  END IF
  2326.  DO
  2327.   i = INSTR(start, str, "\")
  2328.   IF i <> 0 THEN
  2329.    start = i + 1
  2330.   END IF
  2331.  LOOP UNTIL i = 0
  2332.  x$ = MID$(str, 1, start - 1)
  2333.  CALL zzValidate(x$)
  2334.  IF MID$(x$, LEN(x$)) <> "\" THEN x$ = x$ + "\"
  2335.  i = INSTR(str, CHR$(0))
  2336.  
  2337.  Pattern$ = RTRIM$(x$ + MID$(str, start, i - start))
  2338.  
  2339.  IF FileNames <> 0 THEN
  2340.   SortCount = FileNames
  2341.   CALL zzAlphaSort(FileNames$())
  2342.  END IF
  2343.  RETURN
  2344. END SUB
  2345.  
  2346. '<p>
  2347. '++++++++++++++++++++++++
  2348. SUB zzValidate (Directory$)
  2349.  
  2350. DIM str AS STRING * 65
  2351.  
  2352.  CALL zzCritOff
  2353.  GOSUB zzValidateProcess
  2354.  CALL zzCritOn
  2355.  
  2356.  EXIT SUB
  2357.  
  2358. zzValidateProcess:
  2359.  
  2360.  Candpath$ = LTRIM$(RTRIM$(UCASE$(Directory$)))
  2361.  IF MID$(Candpath$, LEN(Candpath$)) = "\" THEN
  2362.   IF LEN(Candpath$) > 1 THEN
  2363.    IF MID$(Candpath$, 2) <> ":\" THEN
  2364.     Candpath$ = MID$(Candpath$, 1, LEN(Candpath$) - 1)
  2365.    END IF
  2366.   END IF
  2367.  END IF
  2368.  
  2369.  Directory$ = "?"
  2370.  
  2371. ' check that any named drive is valid
  2372.  
  2373.  IF MID$(Candpath$, 2, 1) = ":" THEN
  2374.   i = ASC(MID$(Candpath$, 1, 1))
  2375.   IF i < 65 THEN RETURN
  2376.   IF i > 90 THEN RETURN
  2377.   Regs.AX = &H440E
  2378.   Regs.BX = i - 64
  2379.   CALL zzBasicInt(&H21)
  2380.   IF (Regs.FL AND 256) <> 256 THEN
  2381.    j = Regs.AX AND 255
  2382.    IF (j <> 0) AND (j <> i - 64) THEN
  2383.     i = j + 64
  2384.    END IF
  2385.   END IF
  2386.   Regs.AX = &H1C00
  2387.   Regs.DX = i - 64
  2388.   CALL zzBasicInt(&H21)
  2389.   IF (Regs.AX AND 255) = 255 THEN RETURN
  2390.  END IF
  2391.  
  2392. ' handle special case of root directory
  2393.  
  2394.  IF Candpath$ = "\" THEN
  2395.   Directory$ = ""
  2396.   CALL zzChangeDrive(Directory$)
  2397.   Directory$ = Directory$ + "\"
  2398.   RETURN
  2399.  END IF
  2400.  IF MID$(Candpath$, 2) = ":\" THEN
  2401.   Directory$ = Candpath$
  2402.   RETURN
  2403.  END IF
  2404.  
  2405. ' handle special case of NO directory
  2406.  
  2407.  IF Candpath$ = "" THEN
  2408.   CALL zzChangeDir(Candpath$)
  2409.   Directory$ = Candpath$
  2410.   RETURN
  2411.  END IF
  2412.  IF MID$(Candpath$, 2) = ":" THEN
  2413.   Regs.AX = &H4700
  2414.   Regs.DX = ASC(MID$(Candpath$, 1, 1)) - 64
  2415.   Regs.DS = VARSEG(str)
  2416.   Regs.SI = VARPTR(str)
  2417.   CALL zzBasicInt(&H21)
  2418.   i = INSTR(str, CHR$(0))
  2419.   Directory$ = Candpath$ + "\" + MID$(str, 1, i - 1)
  2420.   RETURN
  2421.  END IF
  2422.  
  2423.  str = Candpath$ + CHR$(0)
  2424.  IF INSTR(str, "*") + INSTR(str, "?") > 0 THEN RETURN
  2425.  
  2426.  
  2427. ' initiate the search
  2428.  
  2429.  Regs.AX = &H4E00
  2430.  Regs.CX = &H10
  2431.  Regs.DS = VARSEG(str)
  2432.  Regs.DX = VARPTR(str)
  2433.  CALL zzBasicInt(&H21)
  2434.  
  2435. ' abandon if not a valid directory
  2436.  
  2437.  IF (Regs.FL AND 256) <> 0 THEN RETURN
  2438. ' locate the DTA
  2439.  
  2440.  Regs.AX = &H2F00
  2441.  CALL zzBasicInt(&H21)
  2442.  DTAseg = Regs.ES
  2443.  DTAptr = Regs.BX
  2444.  
  2445.  DEF SEG = DTAseg
  2446.  attr = PEEK(DTAptr + &H15)
  2447.  IF (attr AND &H10) = 0 THEN RETURN
  2448.  
  2449. ' establish the status quo so that we can change back
  2450.  
  2451.  olddrv$ = ""
  2452.  CALL zzChangeDrive(olddrv$)
  2453.  
  2454.  IF MID$(str, 2, 1) = ":" THEN
  2455.   newdrv$ = MID$(str, 1, 2)
  2456.  ELSE
  2457.   newdrv$ = olddrv$
  2458.  END IF
  2459.  
  2460.  CALL zzChangeDrive(newdrv$)    'change to new drive
  2461.  olddir$ = ""
  2462.  CALL zzChangeDir(olddir$)      'find the current directory on new drive
  2463.  CALL zzChangeDir(str)          'change to the desired directory
  2464.  CALL zzChangeDir(olddir$)      'change back to the current directory
  2465.  CALL zzChangeDrive(olddrv$)    'change back to old drive
  2466.  IF Root = 0 THEN
  2467.   Directory$ = RTRIM$(str)
  2468.  ELSE
  2469.   Directory$ = MID$(str, 1, 2) + "\"
  2470.  END IF
  2471.  RETURN
  2472.  
  2473. END SUB
  2474.  
  2475.