home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / books / bassc.db < prev    next >
Encoding:
Text File  |  1991-03-01  |  2.0 MB  |  46,339 lines

Text Truncated. Only the first 1MB is shown below. Download the file for the complete contents.
  1. %@1@%%@AH@%Microsoft BASIC (Professional Development System) Sample Code%@EH@%%@AE@%
  2. %@NL@%
  3. %@NL@%
  4. %@2@%%@AH@%BALLPSET.BAS%@AE@%%@EH@%%@NL@%
  5. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\BALLPSET.BAS%@AE@%%@NL@%
  6. %@NL@%
  7. DECLARE FUNCTION GetArraySize (WLeft, WRight, WTop, WBottom)%@NL@%
  8. %@NL@%
  9. SCREEN 2%@NL@%
  10. %@NL@%
  11. %@AB@%' Define a viewport and draw a border around it:%@AE@%%@NL@%
  12. VIEW (20, 10)-(620, 190),,1%@NL@%
  13. %@NL@%
  14. CONST PI = 3.141592653589#%@NL@%
  15. %@NL@%
  16. %@AB@%' Redefine the coordinates of the viewport with view%@AE@%%@NL@%
  17. %@AB@%' coordinates:%@AE@%%@NL@%
  18. WINDOW (-3.15, -.14)-(3.56, 1.01)%@NL@%
  19. %@NL@%
  20. %@AB@%' Arrays in program are now dynamic:%@AE@%%@NL@%
  21. %@AB@%' $DYNAMIC%@AE@%%@NL@%
  22. %@NL@%
  23. %@AB@%' Calculate the view coordinates for the top and bottom of a%@AE@%%@NL@%
  24. %@AB@%' rectangle large enough to hold the image that will be%@AE@%%@NL@%
  25. %@AB@%' drawn with CIRCLE and PAINT:%@AE@%%@NL@%
  26. WLeft = -.21%@NL@%
  27. WRight = .21%@NL@%
  28. WTop = .07%@NL@%
  29. WBottom = -.07%@NL@%
  30. %@NL@%
  31. %@AB@%' Call the GetArraySize function,%@AE@%%@NL@%
  32. %@AB@%' passing it the rectangle's view coordinates:%@AE@%%@NL@%
  33. ArraySize% = GetArraySize(WLeft, WRight, WTop, WBottom)%@NL@%
  34. %@NL@%
  35. DIM Array (1 TO ArraySize%) AS INTEGER%@NL@%
  36. %@NL@%
  37. %@AB@%' Draw and paint the circle:%@AE@%%@NL@%
  38. CIRCLE (0, 0), .18%@NL@%
  39. PAINT (0, 0)%@NL@%
  40. %@NL@%
  41. %@AB@%' Store the rectangle in Array:%@AE@%%@NL@%
  42. GET (WLeft, WTop)-(WRight, WBottom), Array%@NL@%
  43. CLS%@NL@%
  44. %@AB@%' Draw a box and fill it with a pattern:%@AE@%%@NL@%
  45. LINE (-3, .8)-(3.4, .2), , B%@NL@%
  46. Pattern$ = CHR$(126) + CHR$(0) + CHR$(126) + CHR$(126)%@NL@%
  47. PAINT (0, .5), Pattern$%@NL@%
  48. %@NL@%
  49. LOCATE 21, 29%@NL@%
  50. PRINT "Press any key to end."%@NL@%
  51. %@NL@%
  52. %@AB@%' Initialize loop variables:%@AE@%%@NL@%
  53. StepSize = .02%@NL@%
  54. StartLoop = -PI%@NL@%
  55. Decay = 1%@NL@%
  56. %@NL@%
  57. DO%@NL@%
  58.    EndLoop = -StartLoop%@NL@%
  59.    FOR X = StartLoop TO EndLoop STEP StepSize%@NL@%
  60. %@NL@%
  61. %@AB@%      ' Each time the ball "bounces" (hits the bottom of the%@AE@%%@NL@%
  62. %@AB@%      ' viewport), the Decay variable gets smaller, making%@AE@%%@NL@%
  63. %@AB@%      ' the height of the next bounce smaller:%@AE@%%@NL@%
  64.       Y = ABS(COS(X)) * Decay - .14%@NL@%
  65.       IF Y < -.13 THEN Decay = Decay * .9%@NL@%
  66. %@NL@%
  67. %@AB@%      ' Stop if key pressed or Decay less than .01:%@AE@%%@NL@%
  68.       Esc$ = INKEY$%@NL@%
  69.       IF Esc$ <> "" OR Decay < .01 THEN EXIT FOR%@NL@%
  70. %@NL@%
  71. %@AB@%      ' Put the image on the screen. The StepSize offset is%@AE@%%@NL@%
  72. %@AB@%      ' smaller than the border around the circle. Thus,%@AE@%%@NL@%
  73. %@AB@%      ' each time the image moves, it erases any traces%@AE@%%@NL@%
  74. %@AB@%      ' left from the previous PUT (and also erases anything%@AE@%%@NL@%
  75. %@AB@%      ' else on the screen):%@AE@%%@NL@%
  76.       PUT (X, Y), Array, PSET%@NL@%
  77.    NEXT X%@NL@%
  78. %@NL@%
  79. %@AB@%   ' Reverse direction:%@AE@%%@NL@%
  80.    StepSize = -StepSize%@NL@%
  81.    StartLoop = -StartLoop%@NL@%
  82. LOOP UNTIL Esc$ <> "" OR Decay < .01%@NL@%
  83. %@NL@%
  84. END%@NL@%
  85. %@NL@%
  86. FUNCTION GetArraySize (WLeft, WRight, WTop, WBottom) STATIC%@NL@%
  87. %@NL@%
  88. %@AB@%   ' Map the view coordinates passed to this function to%@AE@%%@NL@%
  89. %@AB@%   ' their physical-coordinate equivalents:%@AE@%%@NL@%
  90.    VLeft = PMAP(WLeft, 0)%@NL@%
  91.    VRight = PMAP(WRight, 0)%@NL@%
  92.    VTop = PMAP(WTop, 1)%@NL@%
  93.    VBottom = PMAP(WBottom, 1)%@NL@%
  94. %@AB@%' Calculate the height and width in pixels%@AE@%%@NL@%
  95. %@AB@%   ' of the enclosing rectangle:%@AE@%%@NL@%
  96.    RectHeight = ABS(VBottom - VTop) + 1%@NL@%
  97.    RectWidth = ABS(VRight - VLeft) + 1%@NL@%
  98. %@NL@%
  99. %@AB@%   ' Calculate size in bytes of array:%@AE@%%@NL@%
  100.    ByteSize = 4 + RectHeight * INT((RectWidth + 7) / 8)%@NL@%
  101. %@NL@%
  102. %@AB@%   ' Array is integer, so divide bytes by two:%@AE@%%@NL@%
  103.    GetArraySize = ByteSize \ 2 + 1%@NL@%
  104. END FUNCTION%@NL@%
  105. %@NL@%
  106. %@NL@%
  107. %@NL@%
  108. %@2@%%@AH@%BALLXOR.BAS%@AE@%%@EH@%%@NL@%
  109. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\BALLXOR.BAS%@AE@%%@NL@%
  110. %@NL@%
  111. DECLARE FUNCTION GetArraySize (WLeft, WRight, WTop, WBottom)%@NL@%
  112. %@NL@%
  113. SCREEN 2%@NL@%
  114. %@NL@%
  115. %@AB@%' Define a viewport and draw a border around it:%@AE@%%@NL@%
  116. VIEW (20, 10)-(620, 190), , 1%@NL@%
  117. %@NL@%
  118. CONST PI = 3.141592653589#%@NL@%
  119. %@NL@%
  120. %@AB@%' Redefine the coordinates of the viewport with view%@AE@%%@NL@%
  121. %@AB@%' coordinates:%@AE@%%@NL@%
  122. WINDOW (-3.15, -.14)-(3.56, 1.01)%@NL@%
  123. %@NL@%
  124. %@AB@%' Arrays in program are now dynamic:%@AE@%%@NL@%
  125. %@AB@%' $DYNAMIC%@AE@%%@NL@%
  126. %@NL@%
  127. %@AB@%' Calculate the view coordinates for the top and bottom of a%@AE@%%@NL@%
  128. %@AB@%' rectangle large enough to hold the image that will be%@AE@%%@NL@%
  129. %@AB@%' drawn with CIRCLE and PAINT:%@AE@%%@NL@%
  130. WLeft = -.18%@NL@%
  131. WRight = .18%@NL@%
  132. WTop = .05%@NL@%
  133. WBottom = -.05%@NL@%
  134. %@NL@%
  135. %@AB@%' Call the GetArraySize function,%@AE@%%@NL@%
  136. %@AB@%' passing it the rectangle's view coordinates:%@AE@%%@NL@%
  137. ArraySize% = GetArraySize(WLeft, WRight, WTop, WBottom)%@NL@%
  138. %@NL@%
  139. DIM Array(1 TO ArraySize%)  AS INTEGER%@NL@%
  140. %@NL@%
  141. %@AB@%' Draw and paint the circle:%@AE@%%@NL@%
  142. CIRCLE (0, 0), .18%@NL@%
  143. PAINT (0, 0)%@NL@%
  144. %@NL@%
  145. %@AB@%' Store the rectangle in Array:%@AE@%%@NL@%
  146. GET (WLeft, WTop)-(WRight, WBottom), Array%@NL@%
  147. CLS%@NL@%
  148. %@AB@%' Draw a box and fill it with a pattern:%@AE@%%@NL@%
  149. LINE (-3, .8)-(3.4, .2), , B%@NL@%
  150. Pattern$ = CHR$(126) + CHR$(0) + CHR$(126) + CHR$(126)%@NL@%
  151. PAINT (0, .5), Pattern$%@NL@%
  152. %@NL@%
  153. LOCATE 21, 29%@NL@%
  154. PRINT "Press any key to end."%@NL@%
  155. %@NL@%
  156. %@AB@%' Initialize loop variables:%@AE@%%@NL@%
  157. StepSize = .02%@NL@%
  158. StartLoop = -PI%@NL@%
  159. Decay = 1%@NL@%
  160. %@NL@%
  161. DO%@NL@%
  162.    EndLoop = -StartLoop%@NL@%
  163.    FOR X = StartLoop TO EndLoop STEP StepSize%@NL@%
  164.       Y = ABS(COS(X)) * Decay - .14%@NL@%
  165. %@NL@%
  166. %@AB@%      ' The first PUT statement places the image%@AE@%%@NL@%
  167. %@AB@%      ' on the screen:%@AE@%%@NL@%
  168.       PUT (X, Y), Array, XOR%@NL@%
  169. %@NL@%
  170. %@AB@%      ' Use an empty FOR...NEXT loop to delay%@AE@%%@NL@%
  171. %@AB@%      ' the program and reduce image flicker:%@AE@%%@NL@%
  172.       FOR I = 1 TO 5: NEXT I%@NL@%
  173. %@NL@%
  174.       IF Y < -.13 THEN Decay = Decay * .9%@NL@%
  175.       Esc$ = INKEY$%@NL@%
  176.       IF Esc$ <> "" OR Decay < .01 THEN EXIT FOR%@NL@%
  177. %@NL@%
  178. %@AB@%      ' The second PUT statement erases the image and%@AE@%%@NL@%
  179. %@AB@%      ' restores the background:%@AE@%%@NL@%
  180.       PUT (X, Y), Array, XOR%@NL@%
  181.    NEXT X%@NL@%
  182. %@NL@%
  183.    StepSize = -StepSize%@NL@%
  184.    StartLoop = -StartLoop%@NL@%
  185. LOOP UNTIL Esc$ <> "" OR Decay < .01%@NL@%
  186. %@NL@%
  187. END%@NL@%
  188. %@AB@%'  .%@AE@%%@NL@%
  189. %@AB@%'  .%@AE@%%@NL@%
  190. %@AB@%'  .%@AE@%%@NL@%
  191. %@NL@%
  192. FUNCTION GetArraySize (WLeft, WRight, WTop, WBottom) STATIC%@NL@%
  193. %@NL@%
  194. %@AB@%   ' Map the view coordinates passed to this function to%@AE@%%@NL@%
  195. %@AB@%   ' their physical-coordinate equivalents:%@AE@%%@NL@%
  196.    VLeft = PMAP(WLeft, 0)%@NL@%
  197.    VRight = PMAP(WRight, 0)%@NL@%
  198.    VTop = PMAP(WTop, 1)%@NL@%
  199.    VBottom = PMAP(WBottom, 1)%@NL@%
  200. %@AB@%' Calculate the height and width in pixels%@AE@%%@NL@%
  201. %@AB@%   ' of the enclosing rectangle:%@AE@%%@NL@%
  202.    RectHeight = ABS(VBottom - VTop) + 1%@NL@%
  203.    RectWidth = ABS(VRight - VLeft) + 1%@NL@%
  204. %@NL@%
  205. %@AB@%   ' Calculate size in bytes of array:%@AE@%%@NL@%
  206.    ByteSize = 4 + RectHeight * INT((RectWidth + 7) / 8)%@NL@%
  207. %@NL@%
  208. %@AB@%   ' Array is integer, so divide bytes by two:%@AE@%%@NL@%
  209.    GetArraySize = ByteSize \ 2 + 1%@NL@%
  210. END FUNCTION%@NL@%
  211. %@NL@%
  212. %@NL@%
  213. %@NL@%
  214. %@2@%%@AH@%BAR.BAS%@AE@%%@EH@%%@NL@%
  215. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\BAR.BAS%@AE@%%@NL@%
  216. %@NL@%
  217. %@AB@%' Define type for the titles:%@AE@%%@NL@%
  218. TYPE TitleType%@NL@%
  219.    MainTitle AS STRING * 40%@NL@%
  220.    XTitle AS STRING * 40%@NL@%
  221.    YTitle AS STRING * 18%@NL@%
  222. END TYPE%@NL@%
  223. %@NL@%
  224. DECLARE SUB InputTitles (T AS TitleType)%@NL@%
  225. DECLARE FUNCTION DrawGraph$ (T AS TitleType, Label$(), Value!(), N%)%@NL@%
  226. DECLARE FUNCTION InputData% (Label$(), Value!())%@NL@%
  227. %@NL@%
  228. %@AB@%' Variable declarations for titles and bar data:%@AE@%%@NL@%
  229. DIM Titles AS TitleType, Label$(1 TO 5), Value(1 TO 5)%@NL@%
  230. %@NL@%
  231. CONST FALSE = 0, TRUE = NOT FALSE%@NL@%
  232. %@NL@%
  233. DO%@NL@%
  234.    InputTitles Titles%@NL@%
  235.    N% = InputData%(Label$(), Value())%@NL@%
  236.    IF N% <> FALSE THEN%@NL@%
  237.       NewGraph$ = DrawGraph$(Titles, Label$(), Value(), N%)%@NL@%
  238.    END IF%@NL@%
  239. LOOP WHILE NewGraph$ = "Y"%@NL@%
  240. %@NL@%
  241. END%@NL@%
  242. %@NL@%
  243. %@AB@%' ======================== DRAWGRAPH ======================%@AE@%%@NL@%
  244. %@AB@%'   Draws a bar graph from the data entered in the%@AE@%%@NL@%
  245. %@AB@%'   INPUTTITLES and INPUTDATA procedures.%@AE@%%@NL@%
  246. %@AB@%' =========================================================%@AE@%%@NL@%
  247. %@NL@%
  248. FUNCTION DrawGraph$ (T AS TitleType, Label$(), Value(), N%) STATIC%@NL@%
  249. %@NL@%
  250. %@AB@%   ' Set size of graph:%@AE@%%@NL@%
  251.    CONST GRAPHTOP = 24, GRAPHBOTTOM = 171%@NL@%
  252.    CONST GRAPHLEFT = 48, GRAPHRIGHT = 624%@NL@%
  253.    CONST YLENGTH = GRAPHBOTTOM - GRAPHTOP%@NL@%
  254. %@NL@%
  255. %@AB@%   ' Calculate maximum and minimum values:%@AE@%%@NL@%
  256.    YMax = 0%@NL@%
  257.    YMin = 0%@NL@%
  258.    FOR I% = 1 TO N%%@NL@%
  259.       IF Value(I%) < YMin THEN YMin = Value(I%)%@NL@%
  260.       IF Value(I%) > YMax THEN YMax = Value(I%)%@NL@%
  261.    NEXT I%%@NL@%
  262. %@NL@%
  263. %@AB@%   ' Calculate width of bars and space between them:%@AE@%%@NL@%
  264.    BarWidth = (GRAPHRIGHT - GRAPHLEFT) / N%%@NL@%
  265.    BarSpace = .2 * BarWidth%@NL@%
  266.    BarWidth = BarWidth - BarSpace%@NL@%
  267. %@NL@%
  268.    SCREEN 2%@NL@%
  269.    CLS%@NL@%
  270. %@NL@%
  271. %@AB@%   ' Draw y-axis:%@AE@%%@NL@%
  272.    LINE (GRAPHLEFT, GRAPHTOP)-(GRAPHLEFT, GRAPHBOTTOM), 1%@NL@%
  273. %@NL@%
  274. %@AB@%   ' Draw main graph title:%@AE@%%@NL@%
  275.    Start% = 44 - (LEN(RTRIM$(T.MainTitle)) / 2)%@NL@%
  276.    LOCATE 2, Start%%@NL@%
  277.    PRINT RTRIM$(T.MainTitle);%@NL@%
  278. %@NL@%
  279. %@AB@%   ' Annotate y-axis:%@AE@%%@NL@%
  280.    Start% = CINT(13 - LEN(RTRIM$(T.YTitle)) / 2)%@NL@%
  281.    FOR I% = 1 TO LEN(RTRIM$(T.YTitle))%@NL@%
  282.       LOCATE Start% + I% - 1, 1%@NL@%
  283.       PRINT MID$(T.YTitle, I%, 1);%@NL@%
  284.    NEXT I%%@NL@%
  285. %@NL@%
  286. %@AB@%   ' Calculate scale factor so labels aren't bigger than four digits:%@AE@%%@NL@%
  287.    IF ABS(YMax) > ABS(YMin) THEN%@NL@%
  288.       Power = YMax%@NL@%
  289.    ELSE%@NL@%
  290.       Power = YMin%@NL@%
  291.    END IF%@NL@%
  292.    Power = CINT(LOG(ABS(Power) / 100) / LOG(10))%@NL@%
  293.    IF Power < 0 THEN Power = 0%@NL@%
  294. %@NL@%
  295. %@AB@%   ' Scale minimum and maximum values down:%@AE@%%@NL@%
  296.    ScaleFactor = 10 ^ Power%@NL@%
  297.    YMax = CINT(YMax / ScaleFactor)%@NL@%
  298.    YMin = CINT(YMin / ScaleFactor)%@NL@%
  299. %@AB@%   ' If power isn't zero then put scale factor on chart:%@AE@%%@NL@%
  300.    IF Power <> 0 THEN%@NL@%
  301.       LOCATE 3, 2%@NL@%
  302.       PRINT "x 10^"; LTRIM$(STR$(Power))%@NL@%
  303.    END IF%@NL@%
  304. %@NL@%
  305. %@AB@%   ' Put tic mark and number for Max point on y-axis:%@AE@%%@NL@%
  306.    LINE (GRAPHLEFT - 3, GRAPHTOP) -STEP(3, 0)%@NL@%
  307.    LOCATE 4, 2%@NL@%
  308.    PRINT USING "####"; YMax%@NL@%
  309. %@NL@%
  310. %@AB@%   ' Put tic mark and number for Min point on y-axis:%@AE@%%@NL@%
  311.    LINE (GRAPHLEFT - 3, GRAPHBOTTOM) -STEP(3, 0)%@NL@%
  312.    LOCATE 22, 2%@NL@%
  313.    PRINT USING "####"; YMin%@NL@%
  314. %@NL@%
  315.    YMax = YMax * ScaleFactor ' Scale minimum and maximum back%@NL@%
  316.    YMin = YMin * ScaleFactor ' up for charting calculations.%@NL@%
  317. %@NL@%
  318. %@AB@%   ' Annotate x-axis:%@AE@%%@NL@%
  319.    Start% = 44 - (LEN(RTRIM$(T.XTitle)) / 2)%@NL@%
  320.    LOCATE 25, Start%%@NL@%
  321.    PRINT RTRIM$(T.XTitle);%@NL@%
  322. %@NL@%
  323. %@AB@%   ' Calculate the pixel range for the y-axis:%@AE@%%@NL@%
  324.    YRange = YMax - YMin%@NL@%
  325. %@NL@%
  326. %@AB@%   ' Define a diagonally striped pattern:%@AE@%%@NL@%
  327.    Tile$ = CHR$(1)+CHR$(2)+CHR$(4)+CHR$(8)+CHR$(16)+CHR$(32)+CHR$(64)+CHR$(128)%@NL@%
  328. %@NL@%
  329. %@AB@%   ' Draw a zero line if appropriate:%@AE@%%@NL@%
  330.    IF YMin < 0 THEN%@NL@%
  331.       Bottom = GRAPHBOTTOM - ((-YMin) / YRange * YLENGTH)%@NL@%
  332.       LOCATE INT((Bottom - 1) / 8) + 1, 5%@NL@%
  333.       PRINT "0";%@NL@%
  334.    ELSE%@NL@%
  335.       Bottom = GRAPHBOTTOM%@NL@%
  336.    END IF%@NL@%
  337. %@NL@%
  338. %@AB@%   ' Draw x-axis:%@AE@%%@NL@%
  339.    LINE (GRAPHLEFT - 3, Bottom)-(GRAPHRIGHT, Bottom)%@NL@%
  340. %@AB@%   ' Draw bars and labels:%@AE@%%@NL@%
  341.    Start% = GRAPHLEFT + (BarSpace / 2)%@NL@%
  342.    FOR I% = 1 TO N%%@NL@%
  343. %@NL@%
  344. %@AB@%      ' Draw a bar label:%@AE@%%@NL@%
  345.       BarMid = Start% + (BarWidth / 2)%@NL@%
  346.       CharMid = INT((BarMid - 1) / 8) + 1%@NL@%
  347.       LOCATE 23, CharMid - INT(LEN(RTRIM$(Label$(I%))) / 2)%@NL@%
  348.       PRINT Label$(I%);%@NL@%
  349. %@NL@%
  350. %@AB@%      ' Draw the bar and fill it with the striped pattern:%@AE@%%@NL@%
  351.       BarHeight = (Value(I%) / YRange) * YLENGTH%@NL@%
  352.       LINE (Start%, Bottom) -STEP(BarWidth, -BarHeight), , B%@NL@%
  353.       PAINT (BarMid, Bottom - (BarHeight / 2)), Tile$, 1%@NL@%
  354. %@NL@%
  355.       Start% = Start% + BarWidth + BarSpace%@NL@%
  356.    NEXT I%%@NL@%
  357.    LOCATE 1, 1%@NL@%
  358.    PRINT "New graph? ";%@NL@%
  359.    DrawGraph$ = UCASE$(INPUT$(1))%@NL@%
  360. %@NL@%
  361. END FUNCTION%@NL@%
  362. %@AB@%' ======================== INPUTDATA ======================%@AE@%%@NL@%
  363. %@AB@%'     Gets input for the bar labels and their values%@AE@%%@NL@%
  364. %@AB@%' =========================================================%@AE@%%@NL@%
  365. %@NL@%
  366. FUNCTION InputData% (Label$(), Value()) STATIC%@NL@%
  367. %@NL@%
  368. %@AB@%   ' Initialize the number of data values:%@AE@%%@NL@%
  369.    NumData% = 0%@NL@%
  370. %@NL@%
  371. %@AB@%   ' Print data-entry instructions:%@AE@%%@NL@%
  372.    CLS%@NL@%
  373.    PRINT "Enter data for up to 5 bars:"%@NL@%
  374.    PRINT "   * Enter the label and value for each bar."%@NL@%
  375.    PRINT "   * Values can be negative."%@NL@%
  376.    PRINT "   * Enter a blank label to stop."%@NL@%
  377.    PRINT%@NL@%
  378.    PRINT "After viewing the graph, press any key ";%@NL@%
  379.    PRINT "to end the program."%@NL@%
  380. %@NL@%
  381. %@AB@%   ' Accept data until blank label or 5 entries:%@AE@%%@NL@%
  382.    Done% = FALSE%@NL@%
  383.    DO%@NL@%
  384.       NumData% = NumData% + 1%@NL@%
  385.       PRINT%@NL@%
  386.       PRINT "Bar("; LTRIM$(STR$(NumData%)); "):"%@NL@%
  387.       INPUT ; "        Label? ", Label$(NumData%)%@NL@%
  388. %@NL@%
  389. %@AB@%      ' Only input value if label isn't blank:%@AE@%%@NL@%
  390.       IF Label$(NumData%) <> "" THEN%@NL@%
  391.          LOCATE , 35%@NL@%
  392.          INPUT "Value? ", Value(NumData%)%@NL@%
  393. %@NL@%
  394. %@AB@%      ' If label is blank, decrement data counter%@AE@%%@NL@%
  395. %@AB@%      ' and set Done flag equal to TRUE:%@AE@%%@NL@%
  396.       ELSE%@NL@%
  397.          NumData% = NumData% - 1%@NL@%
  398.          Done% = TRUE%@NL@%
  399.       END IF%@NL@%
  400.    LOOP UNTIL (NumData% = 5) OR Done%%@NL@%
  401. %@NL@%
  402. %@AB@%   ' Return the number of data values input:%@AE@%%@NL@%
  403.    InputData% = NumData%%@NL@%
  404. %@NL@%
  405. END FUNCTION%@NL@%
  406. %@AB@%' ====================== INPUTTITLES ======================%@AE@%%@NL@%
  407. %@AB@%'     Accepts input for the three different graph titles%@AE@%%@NL@%
  408. %@AB@%' =========================================================%@AE@%%@NL@%
  409. %@NL@%
  410. SUB InputTitles (T AS TitleType) STATIC%@NL@%
  411.    SCREEN 0, 0                ' Set text screen.%@NL@%
  412.    DO                        ' Input titles.%@NL@%
  413.       CLS%@NL@%
  414.       INPUT "Enter main graph title: ", T.MainTitle%@NL@%
  415.       INPUT "Enter x-axis title    : ", T.XTitle%@NL@%
  416.       INPUT "Enter y-axis title    : ", T.YTitle%@NL@%
  417. %@NL@%
  418. %@AB@%      ' Check to see if titles are OK:%@AE@%%@NL@%
  419.       LOCATE 7, 1%@NL@%
  420.       PRINT "OK (Y to continue, N to change)? ";%@NL@%
  421.       LOCATE , , 1%@NL@%
  422.       OK$ = UCASE$(INPUT$(1))%@NL@%
  423.    LOOP UNTIL OK$ = "Y"%@NL@%
  424. END SUB%@NL@%
  425. %@NL@%
  426. %@NL@%
  427. %@NL@%
  428. %@2@%%@AH@%BIGSTRIN.BAS%@AE@%%@EH@%%@NL@%
  429. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\BIGSTRIN.BAS%@AE@%%@NL@%
  430. %@NL@%
  431. %@AB@%'Define arrays which will be passed to each new level%@AE@%%@NL@%
  432. %@AB@%'       of recursion.%@AE@%%@NL@%
  433. DECLARE SUB BigStrings (n%, s1$(), s2$(), s3$(), s4$())%@NL@%
  434. DEFINT A-Z%@NL@%
  435. DIM s1$(1 TO 2), s2$(1 TO 2), s3$(1 TO 2), s4$(1 TO 2)%@NL@%
  436. %@AB@%' Compute the # of 64K blocks available in far memory.%@AE@%%@NL@%
  437. n = FRE(-1) \ 65536%@NL@%
  438. CLS%@NL@%
  439. %@AB@%'Quit if not enough memory.%@AE@%%@NL@%
  440. IF n < 1 THEN%@NL@%
  441.              PRINT "Not enough memory for operation."%@NL@%
  442.              END%@NL@%
  443. END IF%@NL@%
  444. %@NL@%
  445. %@AB@%' Start the recursion.%@AE@%%@NL@%
  446. CALL BigStrings(n, s1$(), s2$(), s3$(), s4$())%@NL@%
  447. %@NL@%
  448. SUB BigStrings (n, s1$(), s2$(), s3$(), s4$())%@NL@%
  449. %@AB@%' Create a new array (up to 64K) for each level of recursion.%@AE@%%@NL@%
  450. DIM a$(1 TO 2)%@NL@%
  451. %@AB@%' Have n keep track of recursion level.%@AE@%%@NL@%
  452. SELECT CASE n%@NL@%
  453. %@AB@%' When at highest recusion level, process the strings.%@AE@%%@NL@%
  454.         CASE 0%@NL@%
  455.                 PRINT s1$(1); s1$(2); s2$(1); s2$(2); s3$(1); s3$(2); s4$(1); s4$(2)%@NL@%
  456.         CASE 1%@NL@%
  457.                 a$(1) = "Each "%@NL@%
  458.                 a$(2) = "word "%@NL@%
  459.                 s1$(1) = a$(1)%@NL@%
  460.                 s1$(2) = a$(2)%@NL@%
  461.         CASE 2%@NL@%
  462.                 a$(1) = "pair "%@NL@%
  463.                 a$(2) = "comes "%@NL@%
  464.                 s2$(1) = a$(1)%@NL@%
  465.                 s2$(2) = a$(2)%@NL@%
  466.         CASE 3%@NL@%
  467.                 a$(1) = "from "%@NL@%
  468.                 a$(2) = "separate "%@NL@%
  469.                 s3$(1) = a$(1)%@NL@%
  470.                 s3$(2) = a$(2)%@NL@%
  471.         CASE 4%@NL@%
  472.                 a$(1) = "recursive "%@NL@%
  473.                 a$(2) = "procedures."%@NL@%
  474.                 s4$(1) = a$(1)%@NL@%
  475.                 s4$(2) = a$(2)%@NL@%
  476. END SELECT%@NL@%
  477. %@NL@%
  478. %@AB@%' Keep going until we're out of memory.%@AE@%%@NL@%
  479. IF n > 0 THEN%@NL@%
  480.                 n = n - 1%@NL@%
  481. %@AB@%' For each recursion, pass in previously created arrays.%@AE@%%@NL@%
  482.                 CALL BigStrings(n, s1$(), s2$(), s3$(), s4$())%@NL@%
  483. END IF%@NL@%
  484. %@NL@%
  485. END SUB%@NL@%
  486. %@NL@%
  487. %@NL@%
  488. %@NL@%
  489. %@NL@%
  490. %@2@%%@AH@%BOOKLOOK.BAS%@AE@%%@EH@%%@NL@%
  491. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\BOOKLOOK.BAS%@AE@%%@NL@%
  492. %@NL@%
  493. %@AB@%'****************************** Main  Module *******************************%@AE@%%@NL@%
  494. %@AB@%'* This window contains the module-level code of BOOKLOOK.BAS, a program   *%@AE@%%@NL@%
  495. %@AB@%'* used to manage the database of a hypothethical library (BOOKS.MDB). The *%@AE@%%@NL@%
  496. %@AB@%'* program requires the following additional modules: BOOKMOD1.BAS,        *%@AE@%%@NL@%
  497. %@AB@%'* BOOKMOD2.BAS, and BOOKMOD3.BAS, all named in the file BOOKLOOK.MAK. The *%@AE@%%@NL@%
  498. %@AB@%'* include file BOOKLOOK.BI and the database file BOOKS.MDB must also be   *%@AE@%%@NL@%
  499. %@AB@%'* accessible. The program is discussed in Chapter 10, Database Programming*%@AE@%%@NL@%
  500. %@AB@%'* with ISAM in the BASIC 7.0 Programmer's Guide.                          *%@AE@%%@NL@%
  501. %@AB@%'*                                                                         *%@AE@%%@NL@%
  502. %@AB@%'* If you do NOT have expanded memory available, you should have invoked   *%@AE@%%@NL@%
  503. %@AB@%'* the PROISAM.EXE TSR as PROISAM /Ib:n, where n can be between 10-20.     *%@AE@%%@NL@%
  504. %@AB@%'* The /Ib: option specifies the number of buffers ISAM needs. Higher n    *%@AE@%%@NL@%
  505. %@AB@%'* values improve performance. Too few buffers, and the program will fail  *%@AE@%%@NL@%
  506. %@AB@%'* with an "Out of Memory" error. However if /Ib: is set too high, there   *%@AE@%%@NL@%
  507. %@AB@%'* may not be enough memory to load and run the program. If you do HAVE    *%@AE@%%@NL@%
  508. %@AB@%'* expanded memory, ISAM automatically uses up to 1.2 megabytes, even if   *%@AE@%%@NL@%
  509. %@AB@%'* you set Ib: to a low value. With a program the size of BOOKLOOK, use the*%@AE@%%@NL@%
  510. %@AB@%'* /Ie: option to reserve some expanded memory for QBX. This indirectly    *%@AE@%%@NL@%
  511. %@AB@%'* limits the amount of expanded memory ISAM uses, but make sure ISAM gets *%@AE@%%@NL@%
  512. %@AB@%'* enough EMS for at least 15 buffers (each buffer = 2K). As a last resort,*%@AE@%%@NL@%
  513. %@AB@%'* you can start QBX with the /NOF switch to make more memory available.   *%@AE@%%@NL@%
  514. %@AB@%'*                                                                         *%@AE@%%@NL@%
  515. %@AB@%'* BOOKLOOK manages 3 tables, BookStock, CardHolders, and BooksOut. The    *%@AE@%%@NL@%
  516. %@AB@%'* data in the BookStock and CardHolders tables is displayed as forms on   *%@AE@%%@NL@%
  517. %@AB@%'* screen. The user can switch between table displays by pressing "V" (for *%@AE@%%@NL@%
  518. %@AB@%'* View Other Table). Each table is defined as a separate structure. The   *%@AE@%%@NL@%
  519. %@AB@%'* structure for BookStock is Books, for CardHolders it is Borrowers, and  *%@AE@%%@NL@%
  520. %@AB@%'* for BooksOut it is BookStatus. Each of these is incorporated as an      *%@AE@%%@NL@%
  521. %@AB@%'* element of the structure RecStruct. RecStruct also has an element of    *%@AE@%%@NL@%
  522. %@AB@%'* INTEGER type called TableNum (to keep track of which table is being     *%@AE@%%@NL@%
  523. %@AB@%'* displayed), and a STRING element called WhichIndex that holds the name  *%@AE@%%@NL@%
  524. %@AB@%'* of the index by which the user chooses to order presentation of records.*%@AE@%%@NL@%
  525. %@AB@%'* Press F2 to see a list of procedures called by the program.             *%@AE@%%@NL@%
  526. %@AB@%'***************************************************************************%@AE@%%@NL@%
  527. %@NL@%
  528. DEFINT A-Z%@NL@%
  529. %@AB@%'$INCLUDE: 'BOOKLOOK.BI'%@AE@%%@NL@%
  530. SCREEN 0%@NL@%
  531. CLS                         ' TempRec is for editing and adding records%@NL@%
  532. DIM TempRec AS RecStruct    ' Used only to blank out a TempRec%@NL@%
  533. DIM EmptyRec AS RecStruct   ' See BOOKLOOK.BI for declaration of%@NL@%
  534. DIM BigRec AS RecStruct     ' this structure and its elements%@NL@%
  535. DIM Marker(25) AS INTEGER   ' Array to hold SAVEPOINT returns%@NL@%
  536. %@NL@%
  537. %@AB@%' Open the database and the BookStock, CardHolders, and BooksOut tables%@AE@%%@NL@%
  538. %@NL@%
  539. ON ERROR GOTO MainHandler%@NL@%
  540. OPEN "BOOKS.MDB" FOR ISAM Books "BookStock" AS cBookStockTableNum%@NL@%
  541. OPEN "BOOKS.MDB" FOR ISAM Borrowers "CardHolders" AS cCardHoldersTableNum%@NL@%
  542. OPEN "BOOKS.MDB" FOR ISAM BookStatus "BooksOut" AS cBooksOutTableNum%@NL@%
  543. ON ERROR GOTO 0%@NL@%
  544. %@NL@%
  545. BigRec.TableNum = cBookStockTableNum   ' Decide which table to show first%@NL@%
  546. %@NL@%
  547. %@AB@%   ' Since the database has multiple tables, this outer DO loop is used to%@AE@%%@NL@%
  548. %@AB@%   ' reset the number associated with the table the user wants to%@AE@%%@NL@%
  549. %@AB@%   ' to access, then draw the screen appropriate to that table, etc.%@AE@%%@NL@%
  550. DO%@NL@%
  551.   EraseMessage                          ' Show the interface%@NL@%
  552.   CALL DrawScreen(BigRec.TableNum)%@NL@%
  553.   Checked = CheckIndex%(BigRec, TRUE)   ' Show current index%@NL@%
  554.   CALL Retriever(BigRec, DimN, DimP, Answer) ' Retrieve and show a record%@NL@%
  555.   CALL ShowMessage(" Press V to View other table", 0)%@NL@%
  556.   CALL ShowStatus(" Total records in table: ", CDBL(LOF(BigRec.TableNum)))%@NL@%
  557. %@NL@%
  558. %@AB@%  ' This loop lets the user traverse BigRec.TableNum and insert, delete,%@AE@%%@NL@%
  559. %@AB@%  ' or modify records.%@AE@%%@NL@%
  560.   DO                                           ' At start of each loop, show%@NL@%
  561. %@AB@%                                               ' the user valid operations%@AE@%%@NL@%
  562.     CALL Retriever(BigRec, DimN, DimP, Answer) ' and display current record%@NL@%
  563. %@NL@%
  564.     STACK 4000                          ' Set large stack for recursions-it%@NL@%
  565. %@AB@%                                        ' also resets FRE(-2) to stack 4000.%@AE@%%@NL@%
  566. %@NL@%
  567.     Answer% = GetInput%(BigRec)         ' Find out what the user wants to do%@NL@%
  568. %@NL@%
  569.     IF Answer < UNDO THEN               ' Excludes UNDOALL & INVALIDKEY too%@NL@%
  570.       CALL EditCheck(PendingFlag, Answer, BigRec)%@NL@%
  571.     END IF%@NL@%
  572. %@NL@%
  573.     SELECT CASE Answer         ' Process valid user requests%@NL@%
  574.       CASE QUIT%@NL@%
  575.         CALL ShowMessage(" You chose Quit. So long! ", 0)%@NL@%
  576.         END%@NL@%
  577. %@NL@%
  578. %@AB@%                               ' If user picks "N" (Next Record), MOVENEXT.%@AE@%%@NL@%
  579. %@AB@%                               ' CheckPosition handles end-of-file (i.e. the%@AE@%%@NL@%
  580.       CASE GOAHEAD, ENDK       ' position just past the last record). If EOF%@NL@%
  581. %@AB@%                               ' or BOF = TRUE, CheckPosition holds position%@AE@%%@NL@%
  582.         MOVENEXT BigRec.TableNum%@NL@%
  583.         CALL CheckPosition(BigRec, Answer, DimN, DimP)%@NL@%
  584. %@NL@%
  585. %@AB@%                               ' Same logic as GOAHEAD, but reversed%@AE@%%@NL@%
  586.       CASE GOBACK, HOME%@NL@%
  587. %@NL@%
  588.         MOVEPREVIOUS BigRec.TableNum%@NL@%
  589.         CALL CheckPosition(BigRec, Answer, DimN, DimP)%@NL@%
  590. %@NL@%
  591. %@AB@%                               ' If user chooses "E", let him edit a field.%@AE@%%@NL@%
  592. %@AB@%                               ' Assign the value returned by SAVEPOINT to%@AE@%%@NL@%
  593. %@AB@%                               ' an array element, then update the table and%@AE@%%@NL@%
  594. %@AB@%                               ' show the changed field. Trap any "duplicate%@AE@%%@NL@%
  595.       CASE EDITRECORD          ' value for unique index" (error 86) and%@NL@%
  596. %@AB@%                               ' handle it. The value returned by SAVEPOINT%@AE@%%@NL@%
  597. %@AB@%                               ' allows rollbacks so the user can undo edits%@AE@%%@NL@%
  598. %@NL@%
  599.         IF LOF(BigRec.TableNum) THEN%@NL@%
  600.           IF EditField(Argument%, BigRec, Letter$, EDITRECORD, Answer%) THEN%@NL@%
  601. %@NL@%
  602. %@AB@%              ' You save a sequence of savepoint identifiers in an array so%@AE@%%@NL@%
  603. %@AB@%              ' you can let the user roll the state of the file back to a%@AE@%%@NL@%
  604. %@AB@%              ' specific point. The returns from SAVEPOINT aren't guaranteed%@AE@%%@NL@%
  605. %@AB@%              ' to be sequential.%@AE@%%@NL@%
  606.             n = n + 1              ' Increment counter first so savepoint%@NL@%
  607.             Marker(n) = SAVEPOINT  ' is synced with array-element subscript%@NL@%
  608. %@NL@%
  609.             Alert$ = "Setting Savepoint number " + STR$(Marker(n))%@NL@%
  610.             CALL ShowMessage(Alert$, 0)%@NL@%
  611.             ON ERROR GOTO MainHandler%@NL@%
  612.             SELECT CASE BigRec.TableNum   ' Update the table being displayed%@NL@%
  613.               CASE cBookStockTableNum%@NL@%
  614.                 UPDATE BigRec.TableNum, BigRec.Inventory%@NL@%
  615.               CASE cCardHoldersTableNum%@NL@%
  616.                 UPDATE BigRec.TableNum, BigRec.Lendee%@NL@%
  617.             END SELECT%@NL@%
  618.             ON ERROR GOTO 0%@NL@%
  619.           ELSE%@NL@%
  620.             COMMITTRANS               ' Use COMMITTRANS abort transaction if%@NL@%
  621.             PendingFlag = FALSE       ' the user presses ESC%@NL@%
  622.             n = 0                     ' Reset array counter%@NL@%
  623.           END IF%@NL@%
  624.         ELSE%@NL@%
  625.           CALL ShowMessage("Sorry, no records in this table to edit", 0): SLEEP%@NL@%
  626.         END IF%@NL@%
  627. %@AB@%                          ' If choice is "A", get the values the user wants%@AE@%%@NL@%
  628. %@AB@%                          ' in each of the fields (with AddOne). If there%@AE@%%@NL@%
  629. %@AB@%                          ' is no ESCAPE from the edit, INSERT the record.%@AE@%%@NL@%
  630. %@AB@%                          ' Trap "Duplicate value for unique index" errors%@AE@%%@NL@%
  631. %@AB@%                          ' and handle them in MainHandler (error 86).%@AE@%%@NL@%
  632.       CASE ADDRECORD%@NL@%
  633.         added = AddOne(BigRec, EmptyRec, TempRec, Answer%)%@NL@%
  634.         IF added THEN%@NL@%
  635.           Alert$ = "A new record assumes proper place in current index"%@NL@%
  636.           CALL ShowMessage(Alert$, 0)%@NL@%
  637.           ON ERROR GOTO MainHandler%@NL@%
  638.           SELECT CASE BigRec.TableNum     ' Insert into table being shown%@NL@%
  639.             CASE cBookStockTableNum%@NL@%
  640.               INSERT BigRec.TableNum, TempRec.Inventory%@NL@%
  641.             CASE cCardHoldersTableNum%@NL@%
  642.               INSERT BigRec.TableNum, TempRec.Lendee%@NL@%
  643.           END SELECT%@NL@%
  644.           ON ERROR GOTO 0%@NL@%
  645.         END IF%@NL@%
  646.         TempRec = EmptyRec%@NL@%
  647. %@NL@%
  648. %@AB@%                              ' If choice is "D" --- prompt for confirmation.%@AE@%%@NL@%
  649. %@AB@%                              ' If so, delete it and show new current record.%@AE@%%@NL@%
  650.       CASE TOSSRECORD%@NL@%
  651.         AnyRecords = LOF(BigRec.TableNum)%@NL@%
  652.         IF BigRec.TableNum = cBookStockTableNum THEN CheckedOut = GetStatus(BigRec, 0#)%@NL@%
  653.         IF BigRec.TableNum = cCardHoldersTableNum THEN%@NL@%
  654.           SETINDEX cBooksOutTableNum, "CardNumIndexBO"%@NL@%
  655.           SEEKEQ cBooksOutTableNum, BigRec.Lendee.CardNum%@NL@%
  656.           IF NOT EOF(cBooksOutTableNum) THEN CheckedOut = TRUE%@NL@%
  657.         END IF%@NL@%
  658.         IF AnyRecords AND CheckedOut = FALSE THEN%@NL@%
  659.           Alert$ = "Press D again to Delete this record, ESC to escape"%@NL@%
  660.           CALL ShowMessage(Alert$, 0)%@NL@%
  661.           DeleteIt% = GetInput%(BigRec)%@NL@%
  662.           IF DeleteIt% = TOSSRECORD THEN   ' Delete currently-displayed record%@NL@%
  663.             DELETE BigRec.TableNum%@NL@%
  664.             CALL ShowMessage("Record deleted...Press a key to continue", 0)%@NL@%
  665.           ELSE%@NL@%
  666.             CALL ShowMessage("Record not deleted. Press a key to continue", 0)%@NL@%
  667.             CALL ShowRecord(BigRec)%@NL@%
  668.           END IF%@NL@%
  669. %@AB@%          ' The following code checks whether the record deleted was the last%@AE@%%@NL@%
  670. %@AB@%          ' record in the index, then makes the new last record current%@AE@%%@NL@%
  671.           IF EOF(BigRec.TableNum) THEN%@NL@%
  672.             MOVELAST BigRec.TableNum%@NL@%
  673.           END IF%@NL@%
  674.         ELSE%@NL@%
  675.           IF BigRec.TableNum = cBookStockTableNum THEN%@NL@%
  676.             IF AnyRecords = 0 THEN Alert$ = "Sorry, no records in this table to delete"%@NL@%
  677.             IF CheckedOut THEN Alert$ = "Can't delete --- this book currently checked out!"%@NL@%
  678.           ELSEIF BigRec.TableNum = cCardHoldersTableNum THEN%@NL@%
  679.             IF AnyRecords = 0 THEN Alert$ = "Sorry, no records in this table to delete"%@NL@%
  680.             IF CheckedOut THEN Alert$ = "Can't delete --- this cardholder still has books out!"%@NL@%
  681.           END IF%@NL@%
  682.           CALL ShowMessage(Alert$, 0): SLEEP%@NL@%
  683.         END IF%@NL@%
  684.         CheckedOut = FALSE%@NL@%
  685. %@NL@%
  686. %@AB@%                               ' If user chooses "R", walk the fields so he%@AE@%%@NL@%
  687. %@AB@%                               ' can choose new index to order presentation%@AE@%%@NL@%
  688.       CASE REORDER%@NL@%
  689.         Letter$ = CHR$(TABKEY)%@NL@%
  690.         GotOne = ChooseOrder(BigRec, EmptyRec, TempRec, Letter$, REORDER)%@NL@%
  691. %@NL@%
  692. %@AB@%                               ' If a choice of indexes was made, retrieve%@AE@%%@NL@%
  693. %@AB@%                               ' the index name, set an error trap, and try%@AE@%%@NL@%
  694. %@AB@%                               ' to set the index, then display new index.%@AE@%%@NL@%
  695.         IF GotOne THEN%@NL@%
  696.           IndexName$ = LTRIM$(RTRIM$(TempRec.WhichIndex))%@NL@%
  697.           ON ERROR GOTO MainHandler%@NL@%
  698.           IF IndexName$ <> "NULL" THEN            ' This string is placed in%@NL@%
  699.             SETINDEX BigRec.TableNum, IndexName$  ' TempRec.WhichIndex if%@NL@%
  700.           ELSE                                    ' user chooses "Default."%@NL@%
  701.             SETINDEX BigRec.TableNum, ""          ' "" is valid index name%@NL@%
  702.           END IF                                  'representing NULL index%@NL@%
  703.           ON ERROR GOTO 0                         '(i.e. the default order)%@NL@%
  704.           CALL AdjustIndex(BigRec)%@NL@%
  705.           LSET TempRec = EmptyRec%@NL@%
  706.         END IF%@NL@%
  707. %@NL@%
  708. %@AB@%                          ' If choice is "F", first set current index%@AE@%%@NL@%
  709.       CASE SEEKFIELD      ' using same procedure as REORDER. Then do seek.%@NL@%
  710. %@NL@%
  711.         Letter$ = CHR$(TABKEY)        ' Pass TABKEY for PlaceCursor%@NL@%
  712.         GotOne = ChooseOrder(BigRec, EmptyRec, TempRec, Letter$, SEEKFIELD)%@NL@%
  713. %@NL@%
  714.         IF GotOne AND TEXTCOMP(TempRec.WhichIndex, "NULL") THEN%@NL@%
  715.           CALL SeekRecord(BigRec, TempRec, Letter$)%@NL@%
  716.           FirstLetter$ = ""%@NL@%
  717.           DimN = EOF(BigRec.TableNum): DimP = BOF(BigRec.TableNum)%@NL@%
  718.         END IF%@NL@%
  719. %@NL@%
  720. %@AB@%                          ' STATUS gets the due date of a book & displays it%@AE@%%@NL@%
  721.       CASE STATUS%@NL@%
  722.         IF BigRec.TableNum = cBookStockTableNum THEN%@NL@%
  723.           CALL ShowStatus("", 0#)                  ' Explicitly type the 0%@NL@%
  724.           GotIt = GetStatus(BigRec, DateToShow#)   ' to avoid type mismatch%@NL@%
  725.           IF GotIt THEN%@NL@%
  726.             Alert$ = "Press B for information on Borrower of this book"%@NL@%
  727.             CALL ShowMessage(Alert$, 0)%@NL@%
  728.             CALL ShowStatus("Due Date: ", DateToShow#)%@NL@%
  729.           END IF%@NL@%
  730.         END IF%@NL@%
  731. %@NL@%
  732. %@AB@%                         ' LendeeProfile displays borrower of displayed book%@AE@%%@NL@%
  733.       CASE BORROWER%@NL@%
  734.         CALL LendeeProfile(BigRec)%@NL@%
  735. %@NL@%
  736. %@AB@%                         ' BooksBorrowed shows books borrowed by CardHolder%@AE@%%@NL@%
  737.       CASE WHICHBOOKS%@NL@%
  738.         IF Borrowed THEN CALL BooksBorrowed(BigRec)%@NL@%
  739. %@NL@%
  740. %@AB@%                         ' If user hits "V" cycle through displayable tables%@AE@%%@NL@%
  741.       CASE OTHERTABLE%@NL@%
  742.         IF BigRec.TableNum < cDisplayedTables THEN%@NL@%
  743.           BigRec.TableNum = BigRec.TableNum + 1%@NL@%
  744.         ELSE%@NL@%
  745.           BigRec.TableNum = 1%@NL@%
  746.         END IF%@NL@%
  747.         EXIT DO%@NL@%
  748. %@AB@%                         ' If user picks "I" to check current book back in,%@AE@%%@NL@%
  749. %@AB@%                         ' make sure it is out, then check it back in%@AE@%%@NL@%
  750.       CASE CHECKIN%@NL@%
  751.         IF Borrowed THEN%@NL@%
  752.           GotIt = GetStatus(BigRec, DateToShow#)%@NL@%
  753.           IF DateToShow# THEN%@NL@%
  754.             CALL ReturnBook(BigRec, DateToShow#)%@NL@%
  755.           END IF%@NL@%
  756.         END IF%@NL@%
  757. %@AB@%                         ' If user picks "O" to check current book out,%@AE@%%@NL@%
  758. %@AB@%                         ' make sure it is available, then check it out%@AE@%%@NL@%
  759.       CASE CHECKOUT%@NL@%
  760.         GotIt = GetStatus(BigRec, DateToShow#)%@NL@%
  761.           IF DateToShow# = 0# THEN%@NL@%
  762.              CALL BorrowBook(BigRec)%@NL@%
  763.           ELSE%@NL@%
  764.              CALL ShowMessage("Sorry, this book is already checked out...", 0)%@NL@%
  765.           END IF%@NL@%
  766. %@NL@%
  767. %@AB@%                        ' If user wants to Undo all or some of a series of%@AE@%%@NL@%
  768. %@AB@%                        ' uncommitted edits, make sure there is a pending%@AE@%%@NL@%
  769. %@AB@%                        ' transaction to undo, then restore the state of the%@AE@%%@NL@%
  770. %@AB@%                        ' file one step at a time, or altogether, depending%@AE@%%@NL@%
  771. %@AB@%                        ' on whether U or ^U was entered.%@AE@%%@NL@%
  772.       CASE UNDO, UNDOALL%@NL@%
  773.         IF PendingFlag = TRUE THEN%@NL@%
  774.           IF n < 1 THEN%@NL@%
  775.             CALL ShowMessage("No pending edits left to Undo...", 0)%@NL@%
  776.           ELSE%@NL@%
  777.             IF Answer = UNDO THEN%@NL@%
  778.               Alert$ = "Restoring back to Savepoint # " + STR$(Marker(n))%@NL@%
  779.               CALL ShowMessage(Alert$, 0)%@NL@%
  780.               ROLLBACK Marker(n)%@NL@%
  781.               n = n - 1%@NL@%
  782.             ELSE                    ' If it's not UNDO, it must be UNDOALL%@NL@%
  783.               CALL ShowMessage("Undoing the whole last series of edits", 0)%@NL@%
  784.               ROLLBACK ALL%@NL@%
  785.               n = 0%@NL@%
  786.             END IF%@NL@%
  787.          END IF%@NL@%
  788.        ELSE%@NL@%
  789.          CALL ShowMessage("There are no pending edits left to Undo...", 0)%@NL@%
  790.        END IF%@NL@%
  791. %@NL@%
  792.       CASE INVALIDKEY              ' Alert user if wrong key is pressed%@NL@%
  793.         CALL ShowMessage(KEYSMESSAGE, 0)%@NL@%
  794.         IF PendingFlag = TRUE THEN CALL DrawIndexBox(BigRec.TableNum, EDITRECORD)%@NL@%
  795.     END SELECT%@NL@%
  796.     CALL DrawHelpKeys(BigRec.TableNum)%@NL@%
  797.     CALL ShowKeys(BigRec, BRIGHT + FOREGROUND, DimN, DimP)%@NL@%
  798.   LOOP%@NL@%
  799. LOOP%@NL@%
  800. CLOSE%@NL@%
  801. END%@NL@%
  802. %@NL@%
  803. %@AB@%' This error handler takes care of the most common ISAM errors%@AE@%%@NL@%
  804. %@NL@%
  805. MainHandler:%@NL@%
  806. %@NL@%
  807. IF ERR = 73 THEN        ' 73 = Feature unavailable%@NL@%
  808.   CALL ShowMessage("You forgot to load the ISAM TSR program", 0)%@NL@%
  809.   END%@NL@%
  810. ELSEIF ERR = 88 THEN        ' 88 = Database inconsistent%@NL@%
  811. %@AB@%  ' If you have text files corresponding to each of the tables, then%@AE@%%@NL@%
  812. %@AB@%  ' MakeOver prompts for their names and creates an ISAM file from them.%@AE@%%@NL@%
  813.   CALL MakeOver(BigRec)%@NL@%
  814.   RESUME NEXT%@NL@%
  815. %@NL@%
  816. ELSEIF ERR = 83 THEN        ' 83 = Index not found%@NL@%
  817.     CALL DrawScreen(BigRec.TableNum)%@NL@%
  818.     CALL ShowMessage("Unable to set the index. Need more buffers?", 0)%@NL@%
  819.     RESUME NEXT%@NL@%
  820. ELSEIF ERR = 86 THEN        ' 86 = Duplicate value for unique index%@NL@%
  821. %@AB@%    ' Trap errors when a user tries to enter a value for the Card Number or%@AE@%%@NL@%
  822. %@AB@%    ' ID fields that duplicates a value already in the table%@AE@%%@NL@%
  823.     CALL DupeFixer(BigRec)%@NL@%
  824.     RESUME%@NL@%
  825. ELSE%@NL@%
  826.   Alert$ = "Sorry, not able to handle this error in BOOKLOOK: " + STR$(ERR)%@NL@%
  827.   CALL ShowMessage(Alert$, 0)%@NL@%
  828.   END%@NL@%
  829. END IF%@NL@%
  830. %@NL@%
  831. %@AB@%'***************************************************************************%@AE@%%@NL@%
  832. %@AB@%'*  The AddOne FUNCTION is called once for each field when the user wants  *%@AE@%%@NL@%
  833. %@AB@%'*  to add a record to the displayed table.                                *%@AE@%%@NL@%
  834. %@AB@%'*                                Parameters                               *%@AE@%%@NL@%
  835. %@AB@%'*  BigRec    RecStruct variable containing information on all tables      *%@AE@%%@NL@%
  836. %@AB@%'*  EmptyRec  Empty record of same type as BigRec                          *%@AE@%%@NL@%
  837. %@AB@%'*  TempRec   Temporary record record of same type as BigRec               *%@AE@%%@NL@%
  838. %@AB@%'*  Answer    Integer passed through to EditField; tells task to perform   *%@AE@%%@NL@%
  839. %@AB@%'***************************************************************************%@AE@%%@NL@%
  840. FUNCTION AddOne (BigRec AS RecStruct, EmptyRec AS RecStruct, TempRec AS RecStruct, Answer%)%@NL@%
  841.   CALL ClearEm(BigRec.TableNum, 1, 1, 1, 1, 1, 1)%@NL@%
  842.   LSET TempRec = EmptyRec%@NL@%
  843.   CALL ShowMessage("Enter the first field of the new record", 0)%@NL@%
  844.   TempRec.TableNum = BigRec.TableNum%@NL@%
  845.   Edited = EditField(Argument%, TempRec, FirstLetter$, ADDRECORD, Answer%)%@NL@%
  846.   IF Edited THEN%@NL@%
  847.     AddOne = -1%@NL@%
  848.   ELSE%@NL@%
  849.     AddOne = 0%@NL@%
  850.   END IF%@NL@%
  851.   COLOR FOREGROUND, BACKGROUND%@NL@%
  852. END FUNCTION%@NL@%
  853. %@NL@%
  854. %@AB@%'***************************************************************************%@AE@%%@NL@%
  855. %@AB@%'* The CheckPosition SUB checks the table position after the requested user*%@AE@%%@NL@%
  856. %@AB@%'* action is completed. If EOF follows a MOVENEXT or the user has chosen   *%@AE@%%@NL@%
  857. %@AB@%'* MOVELAST, the Keys for Database Viewing/Editing box is updated to say   *%@AE@%%@NL@%
  858. %@AB@%'* "No Next Record." If BOF  follows a MOVEPREVIOUS or user has chosen a   *%@AE@%%@NL@%
  859. %@AB@%'* MOVEFIRST, "No Previous Record" is displayed.                           *%@AE@%%@NL@%
  860. %@AB@%'* In either case, the position is held by executing MOVELAST or MOVEFIRST.*%@AE@%%@NL@%
  861. %@AB@%'*                            Parameters:                                  *%@AE@%%@NL@%
  862. %@AB@%'*   Big Rec      User-defined type containing all table information       *%@AE@%%@NL@%
  863. %@AB@%'*   Answer       Tells what operation retrieve results from               *%@AE@%%@NL@%
  864. %@AB@%'*   DimN & DimP  Flags telling which menu items should be dimmed/changed  *%@AE@%%@NL@%
  865. %@AB@%'***************************************************************************%@AE@%%@NL@%
  866. SUB CheckPosition (BigRec AS RecStruct, Answer, DimN%, DimP%)%@NL@%
  867.   SELECT CASE Answer%@NL@%
  868.     CASE GOAHEAD, ENDK%@NL@%
  869.       IF EOF(BigRec.TableNum) OR (Answer = ENDK) THEN%@NL@%
  870.         CALL ShowMessage("This is the last record in this index", 0)%@NL@%
  871.         DimN = TRUE: DimP = FALSE%@NL@%
  872.         MOVELAST BigRec.TableNum%@NL@%
  873.       ELSE                    ' If not EOF, turn on N%@NL@%
  874.         DimN = FALSE: DimP = FALSE%@NL@%
  875.         CALL EraseMessage%@NL@%
  876.       END IF%@NL@%
  877.     CASE GOBACK, HOME%@NL@%
  878.       IF BOF(BigRec.TableNum) OR (Answer = HOME) THEN%@NL@%
  879.         CALL ShowMessage("This is the first record in this index", 0)%@NL@%
  880.         DimP = TRUE: DimN = FALSE%@NL@%
  881.         MOVEFIRST BigRec.TableNum%@NL@%
  882.       ELSE%@NL@%
  883.         DimP = FALSE: DimN = FALSE%@NL@%
  884.         CALL EraseMessage%@NL@%
  885.       END IF%@NL@%
  886.   END SELECT%@NL@%
  887. END SUB%@NL@%
  888. %@NL@%
  889. %@AB@%'***************************************************************************%@AE@%%@NL@%
  890. %@AB@%'* The ChooseOrder FUNCTION calls PlaceCursor so the user can move around  *%@AE@%%@NL@%
  891. %@AB@%'* the form to pick the index to set.                                      *%@AE@%%@NL@%
  892. %@AB@%'*                                  Parameters                             *%@AE@%%@NL@%
  893. %@AB@%'*  BigRec       BigRec has all the table information in updated form      *%@AE@%%@NL@%
  894. %@AB@%'*  EmptyRec     EmptyRec is same template as BigRec, but fields are empty *%@AE@%%@NL@%
  895. %@AB@%'*  TempRec      Holds intermediate and temporary data                     *%@AE@%%@NL@%
  896. %@AB@%'*  FirstLetter  Catches letter if user starts typing during SEEKFIELD     *%@AE@%%@NL@%
  897. %@AB@%'*  Task         Either REORDER or SEEKFIELD - passed on to PlaceCursor    *%@AE@%%@NL@%
  898. %@AB@%'***************************************************************************%@AE@%%@NL@%
  899. FUNCTION ChooseOrder (BigRec AS RecStruct, EmptyRec AS RecStruct, TempRec AS RecStruct, FirstLetter$, Task%)%@NL@%
  900.   CALL DrawTable(BigRec.TableNum)%@NL@%
  901.   CALL DrawIndexBox(BigRec.TableNum, Task)%@NL@%
  902.   Argument = TITLEFIELD                    ' Always start with first field%@NL@%
  903.   TempRec = EmptyRec: TempRec.TableNum = BigRec.TableNum%@NL@%
  904. %@NL@%
  905. %@AB@%  ' Pass temporary RecStruct variable so user can't trash BigRec%@AE@%%@NL@%
  906.   value = PlaceCursor(Argument, TempRec, FirstLetter$, 1, Task)%@NL@%
  907. %@NL@%
  908. %@AB@%  ' If the user chooses ESC, redraw everything, then exit to module level%@AE@%%@NL@%
  909.   IF ASC(TempRec.WhichIndex) = 0 THEN%@NL@%
  910.     CALL DrawIndexBox(BigRec.TableNum, Task)%@NL@%
  911.     CALL ShowRecord(BigRec)%@NL@%
  912.     CALL ShowMessage(KEYSMESSAGE, 0)%@NL@%
  913.     ChooseOrder = 0%@NL@%
  914.     EXIT FUNCTION%@NL@%
  915.   ELSE                                ' Otherwise, if user makes a choice%@NL@%
  916.     ChooseOrder = -1                  ' of Indexes, signal success to the%@NL@%
  917.   END IF                              ' module-level code%@NL@%
  918. END FUNCTION%@NL@%
  919. %@NL@%
  920. %@AB@%'***************************************************************************%@AE@%%@NL@%
  921. %@AB@%'*                                                                         *%@AE@%%@NL@%
  922. %@AB@%'*  The DupeFixer SUB is called when the tries to enter a duplicate value  *%@AE@%%@NL@%
  923. %@AB@%'*  for the BookStock table's IDnum column or the the CardHolders table's  *%@AE@%%@NL@%
  924. %@AB@%'*  CardNum column, because their indexes are Unique. The procedure prompts*%@AE@%%@NL@%
  925. %@AB@%'*  the user to enter a new value.                                         *%@AE@%%@NL@%
  926. %@AB@%'***************************************************************************%@AE@%%@NL@%
  927. SUB DupeFixer (BigRec AS RecStruct)%@NL@%
  928.     IF BigRec.TableNum = cBookStockTableNum THEN%@NL@%
  929.       DO%@NL@%
  930.         Alert$ = STR$(BigRec.Inventory.IDnum) + " is not unique. "%@NL@%
  931.         CALL ShowMessage(Alert$, 1)%@NL@%
  932.         COLOR YELLOW + BRIGHT, BACKGROUND%@NL@%
  933.         INPUT "Try another number: ", TempString$%@NL@%
  934.         BigRec.Inventory.IDnum = VAL(TempString$)%@NL@%
  935.       LOOP UNTIL BigRec.Inventory.IDnum%@NL@%
  936.     ELSEIF BigRec.TableNum = cCardHoldersTableNum THEN%@NL@%
  937.       DO%@NL@%
  938.         Alert$ = STR$(BigRec.Lendee.CardNum) + " is not unique. "%@NL@%
  939.         CALL ShowMessage(Alert$, 1)%@NL@%
  940.         COLOR YELLOW + BRIGHT, BACKGROUND%@NL@%
  941.         INPUT "Try another number: ", TempString$%@NL@%
  942.         BigRec.Lendee.CardNum = VAL(TempString$)%@NL@%
  943.       LOOP UNTIL BigRec.Lendee.CardNum%@NL@%
  944.     END IF%@NL@%
  945.     COLOR FOREGROUND, BACKGROUND%@NL@%
  946. END SUB%@NL@%
  947. %@NL@%
  948. %@AB@%'********************************* EditCheck SUB ***************************%@AE@%%@NL@%
  949. %@AB@%'*                                                                         *%@AE@%%@NL@%
  950. %@AB@%'* The EditCheck procedure monitors what the user wants to do, and if the  *%@AE@%%@NL@%
  951. %@AB@%'* choice is EDITRECORD, makes sure that a transaction is begun, or if it  *%@AE@%%@NL@%
  952. %@AB@%'* already has begun, continues it. If a transaction has been pending, and *%@AE@%%@NL@%
  953. %@AB@%'* the user chooses anything except EDITRECORD, then the transaction is    *%@AE@%%@NL@%
  954. %@AB@%'* committed.                                                              *%@AE@%%@NL@%
  955. %@AB@%'*                                                                         *%@AE@%%@NL@%
  956. %@AB@%'*                            Parameters:                                  *%@AE@%%@NL@%
  957. %@AB@%'*   Pending      A flag that indicates whether transaction is pending     *%@AE@%%@NL@%
  958. %@AB@%'*   Task         Tells what operation the user wants to perform now       *%@AE@%%@NL@%
  959. %@AB@%'*   TablesRec    Structure containing information about the tables        *%@AE@%%@NL@%
  960. %@AB@%'*                                                                         *%@AE@%%@NL@%
  961. %@AB@%'***************************************************************************%@AE@%%@NL@%
  962. SUB EditCheck (Pending, Task, TablesRec AS RecStruct)%@NL@%
  963. %@AB@%  ' First, decide if this is a new or pending transaction, or not one at all%@AE@%%@NL@%
  964. %@AB@%  ' The only transaction in this program keeps edits to the current record%@AE@%%@NL@%
  965. %@AB@%  ' pending until the user moves on to a new record or a new operation%@AE@%%@NL@%
  966. %@AB@%  ' (for example a Reorder).%@AE@%%@NL@%
  967. SHARED n                          ' n is index to array of savepoint ids%@NL@%
  968. %@NL@%
  969.       IF Task = EDITRECORD THEN%@NL@%
  970.         IF Pending = FALSE THEN%@NL@%
  971.           BEGINTRANS%@NL@%
  972.           Pending = TRUE%@NL@%
  973.         END IF%@NL@%
  974.       ELSEIF Pending = TRUE THEN  ' Equivalent to Task<>EDITRECORD AND%@NL@%
  975.         COMMITTRANS               ' Pending=TRUE%@NL@%
  976.         Pending = FALSE%@NL@%
  977.         n = 0                     ' Reset array index for savepoint ids%@NL@%
  978.         CALL DrawIndexBox(TablesRec.TableNum, 0)%@NL@%
  979.       END IF%@NL@%
  980. END SUB%@NL@%
  981. %@NL@%
  982. %@AB@%'***************************************************************************%@AE@%%@NL@%
  983. %@AB@%'*  The GetInput FUNCTION takes the keystroke input by the user and returns*%@AE@%%@NL@%
  984. %@AB@%'*  a constant indicating what the user wants to do. If the keystroke rep- *%@AE@%%@NL@%
  985. %@AB@%'*  resents a valid operation, the choice is echoed to the screen.         *%@AE@%%@NL@%
  986. %@AB@%'***************************************************************************%@AE@%%@NL@%
  987. FUNCTION GetInput% (BigRec AS RecStruct)%@NL@%
  988. DO%@NL@%
  989.   Answer$ = INKEY$%@NL@%
  990. LOOP WHILE Answer$ = EMPTYSTRING%@NL@%
  991.   IF LEN(Answer$) > 1 THEN%@NL@%
  992.     RightSide = HighKeys%(Answer$)%@NL@%
  993.     GetInput = RightSide%@NL@%
  994.   ELSE%@NL@%
  995.     SELECT CASE Answer$%@NL@%
  996.       CASE "A", "a"%@NL@%
  997.         CALL UserChoice(BigRec, ALINE, 7, "Add Record")%@NL@%
  998.         GetInput% = ADDRECORD%@NL@%
  999.       CASE "B", "b"%@NL@%
  1000.         IF BigRec.TableNum = cBookStockTableNum THEN%@NL@%
  1001.           CALL UserChoice(BigRec, WLINE, 28, "Borrower")%@NL@%
  1002.           GetInput% = BORROWER%@NL@%
  1003.         ELSE%@NL@%
  1004.           CALL UserChoice(BigRec, WLINE, 13, "Books Outstanding")%@NL@%
  1005.           GetInput% = WHICHBOOKS%@NL@%
  1006.         END IF%@NL@%
  1007.       CASE "O", "o"%@NL@%
  1008.         CALL UserChoice(BigRec, CLINE, 7, "Check Book Out")%@NL@%
  1009.         GetInput% = CHECKOUT%@NL@%
  1010.       CASE "I", "i"%@NL@%
  1011.         CALL UserChoice(BigRec, CLINE, 28, "Check In")%@NL@%
  1012.         GetInput% = CHECKIN%@NL@%
  1013.       CASE "D", "d"%@NL@%
  1014.         CALL UserChoice(BigRec, ALINE, 28, "Drop Record")%@NL@%
  1015.         GetInput% = TOSSRECORD%@NL@%
  1016.       CASE "N", "n"%@NL@%
  1017.         GetInput% = GOAHEAD%@NL@%
  1018.       CASE "P", "p"%@NL@%
  1019.         GetInput% = GOBACK%@NL@%
  1020.       CASE "Q", "q"%@NL@%
  1021.         CALL UserChoice(BigRec, ELINE, 28, "Quit")%@NL@%
  1022.         GetInput% = QUIT%@NL@%
  1023.       CASE "E", "e"%@NL@%
  1024.         CALL UserChoice(BigRec, ELINE, 7, "Edit Record")%@NL@%
  1025.         GetInput% = EDITRECORD%@NL@%
  1026.       CASE "F", "f"%@NL@%
  1027.         CALL UserChoice(BigRec, RLINE, 28, "Find Record")%@NL@%
  1028.         GetInput% = SEEKFIELD%@NL@%
  1029.       CASE "R", "r"%@NL@%
  1030.         CALL UserChoice(BigRec, RLINE, 7, "Reorder Records")%@NL@%
  1031.         GetInput% = REORDER%@NL@%
  1032.       CASE "V", "v"%@NL@%
  1033.         GetInput% = OTHERTABLE%@NL@%
  1034.       CASE "W", "w"%@NL@%
  1035.         CALL UserChoice(BigRec, WLINE, 7, "When Due Back")%@NL@%
  1036.         GetInput% = STATUS%@NL@%
  1037.       CASE CHR$(ESCAPE)%@NL@%
  1038.         GetInput% = ESCAPE%@NL@%
  1039.       CASE "U", "u"%@NL@%
  1040.         GetInput = UNDO       ' U signals rollback request after editing%@NL@%
  1041.       CASE CHR$(CTRLU)        ' ^U = rollback a whole series of edits%@NL@%
  1042.         GetInput = UNDOALL%@NL@%
  1043.       CASE ELSE%@NL@%
  1044.         GetInput% = INVALIDKEY%@NL@%
  1045.         BEEP%@NL@%
  1046.     END SELECT%@NL@%
  1047.   END IF%@NL@%
  1048. END FUNCTION%@NL@%
  1049. %@NL@%
  1050. %@AB@%'**************************************************************************%@AE@%%@NL@%
  1051. %@AB@%'*  The HighKeys FUNCTION handles common two-byte keys input by the user. *%@AE@%%@NL@%
  1052. %@AB@%'*  The Answer parameter is the keystroke entered by the user.            *                                                          *%@AE@%%@NL@%
  1053. %@AB@%'**************************************************************************%@AE@%%@NL@%
  1054. FUNCTION HighKeys (Answer AS STRING)%@NL@%
  1055.   SELECT CASE ASC(RIGHT$(Answer$, 1))     ' Look at code for right byte%@NL@%
  1056.     CASE UP%@NL@%
  1057.       HighKeys = GOBACK                   ' UP is the up-arrow key%@NL@%
  1058.     CASE DOWN%@NL@%
  1059.       HighKeys = GOAHEAD                  ' DOWN is the down-arrow key%@NL@%
  1060.     CASE HOME%@NL@%
  1061.       HighKeys = HOME                     ' etc.%@NL@%
  1062.     CASE ENDK%@NL@%
  1063.       HighKeys = ENDK%@NL@%
  1064.       CASE LEFT%@NL@%
  1065.       HighKeys = OTHERTABLE%@NL@%
  1066.     CASE RIGHT%@NL@%
  1067.       HighKeys = OTHERTABLE%@NL@%
  1068.     CASE PGUP%@NL@%
  1069.       CALL ShowMessage("You could program so PGUP moves back n records", 0): SLEEP%@NL@%
  1070.       HighKeys = INVALIDKEY%@NL@%
  1071.     CASE PGDN%@NL@%
  1072.       CALL ShowMessage("You could program so PGDN moves forward n records", 0): SLEEP%@NL@%
  1073.       HighKeys = INVALIDKEY%@NL@%
  1074.     CASE ELSE%@NL@%
  1075.       CALL ShowMessage("Sorry, that key isn't handled yet.", 0): SLEEP%@NL@%
  1076.       HighKeys = INVALIDKEY%@NL@%
  1077.   END SELECT%@NL@%
  1078. END FUNCTION%@NL@%
  1079. %@NL@%
  1080. %@AB@%'****************************** Retriever SUB ******************************%@AE@%%@NL@%
  1081. %@AB@%'* The Retriever SUB retrieves records from the database file and puts     *%@AE@%%@NL@%
  1082. %@AB@%'* them into the appropriate recordvariable for the table being displayed. *%@AE@%%@NL@%
  1083. %@AB@%'* An error trap is set in case the retrieve fails, in which case a message*%@AE@%%@NL@%
  1084. %@AB@%'* is displayed. Note that if a preceding SEEKoperand fails, EOF is TRUE.  *%@AE@%%@NL@%
  1085. %@AB@%'* In that case, position is set to the last record, which is retrieved.   *%@AE@%%@NL@%
  1086. %@AB@%'*                            Parameters:                                  *%@AE@%%@NL@%
  1087. %@AB@%'*   Big Rec      User-defined type containing all table information       *%@AE@%%@NL@%
  1088. %@AB@%'*   DimN & DimP  Flags telling which menu items should be dimmed/changed  *%@AE@%%@NL@%
  1089. %@AB@%'*   Task         Tells what operation retrieve results from               *%@AE@%%@NL@%
  1090. %@AB@%'***************************************************************************%@AE@%%@NL@%
  1091. SUB Retriever (BigRec AS RecStruct, DimN, DimP, Task)%@NL@%
  1092.   STATIC PeekFlag         ' Set this if user is just peeking at other table%@NL@%
  1093.   LOCATE , , 0            ' Turn off the cursor%@NL@%
  1094. %@AB@%  ' Show the user which choice was made, and whether EOF or BOF%@AE@%%@NL@%
  1095.   CALL ShowKeys(BigRec, FOREGROUND + BRIGHT, DimN, DimP)%@NL@%
  1096. %@AB@%  ' If table is empty, don't try to retrieve anything%@AE@%%@NL@%
  1097.   IF LOF(BigRec.TableNum) = 0 THEN%@NL@%
  1098.     DrawTable (BigRec.TableNum)%@NL@%
  1099.     CALL ShowMessage("There are no records in this table", 0): EXIT SUB%@NL@%
  1100.   END IF%@NL@%
  1101. %@NL@%
  1102.   IF Task <> ENDK AND Task <> HOME THEN%@NL@%
  1103.     IF Task < EDITRECORD THEN                         ' Edit needs its%@NL@%
  1104.       CALL Indexbox(BigRec, CheckIndex%(BigRec, 0))   ' own prompts. Show%@NL@%
  1105.     ELSEIF Task > INVALIDKEY THEN                     ' indexbox otherwise%@NL@%
  1106.       IF Task <> ESC THEN CALL DrawIndexBox(BigRec.TableNum, 0)%@NL@%
  1107.       CALL Indexbox(BigRec, CheckIndex%(BigRec, 0))%@NL@%
  1108.     END IF%@NL@%
  1109.   END IF%@NL@%
  1110.   IF BOF(BigRec.TableNum) THEN MOVEFIRST (BigRec.TableNum)%@NL@%
  1111.   ON LOCAL ERROR GOTO LocalHandler           ' Trap errors on the retrieve.%@NL@%
  1112.   IF NOT EOF(BigRec.TableNum) THEN           ' Retrieve current record%@NL@%
  1113.     SELECT CASE BigRec.TableNum              ' from table being displayed%@NL@%
  1114.       CASE cBookStockTableNum                ' if EOF is not true%@NL@%
  1115.         RETRIEVE BigRec.TableNum, BigRec.Inventory%@NL@%
  1116.       CASE cCardHoldersTableNum%@NL@%
  1117.         RETRIEVE BigRec.TableNum, BigRec.Lendee%@NL@%
  1118.     END SELECT%@NL@%
  1119.   ELSE                                       ' If EOF is true, set position%@NL@%
  1120.     MOVELAST BigRec.TableNum                 ' to the last record in table,%@NL@%
  1121.     SELECT CASE BigRec.TableNum              ' then retrieve the record%@NL@%
  1122.       CASE cBookStockTableNum%@NL@%
  1123.         RETRIEVE BigRec.TableNum, BigRec.Inventory%@NL@%
  1124.       CASE cCardHoldersTableNum%@NL@%
  1125.         RETRIEVE BigRec.TableNum, BigRec.Lendee%@NL@%
  1126.     END SELECT%@NL@%
  1127.     DimN = TRUE%@NL@%
  1128.   END IF%@NL@%
  1129.   ON LOCAL ERROR GOTO 0                             ' Turn off error trap%@NL@%
  1130.   CALL ClearEm(BigRec.TableNum, 1, 1, 1, 1, 1, 1)%@NL@%
  1131.   CALL ShowRecord(BigRec)%@NL@%
  1132.   IF Task = OTHERTABLE THEN   ' If user is just peeking at the other table%@NL@%
  1133.     IF PeekFlag = 0 THEN      ' remind him how to get back to first table%@NL@%
  1134.       CALL ShowMessage("Press V to return to the other table", 0)%@NL@%
  1135.       PeekFlag = 1%@NL@%
  1136.     END IF%@NL@%
  1137.   ELSE%@NL@%
  1138.     PeekFlag = 0%@NL@%
  1139.   END IF%@NL@%
  1140. EXIT SUB%@NL@%
  1141. %@NL@%
  1142. LocalHandler:%@NL@%
  1143.   IF ERR = 85 THEN%@NL@%
  1144.     CALL ShowMessage("Unable to retrieve your record...", 0)%@NL@%
  1145.   END IF%@NL@%
  1146.   RESUME NEXT%@NL@%
  1147. END SUB%@NL@%
  1148. %@NL@%
  1149. %@AB@%'********************************* SeekRecord SUB *************************%@AE@%%@NL@%
  1150. %@AB@%'*  SeekRecord takes the name of the user's chosen index, sets it as the  *%@AE@%%@NL@%
  1151. %@AB@%'*  current index, then prompts the user to enter the value to seek. A    *%@AE@%%@NL@%
  1152. %@AB@%'*  minimal editor, MakeString, gets user input. If the SEEK is on a com- *%@AE@%%@NL@%
  1153. %@AB@%'*  bined index, GetKeyVals is called to get the input. Input is checked  *%@AE@%%@NL@%
  1154. %@AB@%'*  for minimal acceptability by ValuesOK. If it is OK, GetOperand is     *%@AE@%%@NL@%
  1155. %@AB@%'*  called to let the user specify how to conduct the SEEK.               *%@AE@%%@NL@%
  1156. %@AB@%'*                              Parameters:                               *%@AE@%%@NL@%
  1157. %@AB@%'*      TablesRec  Contains current record information for all tables     *%@AE@%%@NL@%
  1158. %@AB@%'*      TempRec    Contains the name of the index on which to seek (in    *%@AE@%%@NL@%
  1159. %@AB@%'*                 TempRec.WhichIndex element)                            *%@AE@%%@NL@%
  1160. %@AB@%'*      Letter$    If the user starts typing instead of pressing ENTER    *%@AE@%%@NL@%
  1161. %@AB@%'*                 Letter$ catches the keystroke, passes it to MakeString *%@AE@%%@NL@%
  1162. %@AB@%'**************************************************************************%@AE@%%@NL@%
  1163. SUB SeekRecord (TablesRec AS RecStruct, TempRec AS RecStruct, Letter$)%@NL@%
  1164.   DIM EmptyRec AS RecStruct             ' Make an empty record.%@NL@%
  1165.   IF LEFT$(Letter$, 1) < " " THEN       ' Exit if value is not a valid%@NL@%
  1166. %@AB@%                                        ' character, then redraw%@AE@%%@NL@%
  1167.     CALL DrawIndexBox(TablesRec.TableNum, SEEKFIELD)%@NL@%
  1168.     CALL Indexbox(TablesRec, CheckIndex%(TablesRec, TRUE))%@NL@%
  1169.     CALL ShowMessage("You must enter a valid string or numeric value", 0)%@NL@%
  1170.     EXIT SUB%@NL@%
  1171.   END IF%@NL@%
  1172.   TheTable = TablesRec.TableNum%@NL@%
  1173.   IndexName$ = RTRIM$(TempRec.WhichIndex)%@NL@%
  1174.   IF GETINDEX$(TheTable) <> IndexName$ THEN  ' If index to seek on is not%@NL@%
  1175.     ON LOCAL ERROR GOTO SeekHandler          ' current, set it now. Trap%@NL@%
  1176.     SETINDEX TheTable, IndexName$            ' possible failure of SETINDEX%@NL@%
  1177.     ON LOCAL ERROR GOTO 0                    ' then turn off error trap.%@NL@%
  1178.   END IF%@NL@%
  1179.   CALL AdjustIndex(TablesRec)                ' Show the current index%@NL@%
  1180.   TablesRec.WhichIndex = TempRec.WhichIndex%@NL@%
  1181.   TempRec = EmptyRec                         ' Clear TempRec for data%@NL@%
  1182.   TempRec.TableNum = TablesRec.TableNum%@NL@%
  1183. %@AB@%  ' Get the value to SEEK for from the user. The data type you assign the%@AE@%%@NL@%
  1184. %@AB@%  ' input to must be the same as the data in the database, so get it as a%@AE@%%@NL@%
  1185. %@AB@%  ' string with MakeString, then convert it to proper type for index. If%@AE@%%@NL@%
  1186. %@AB@%  ' the index is the combined index BigIndex, use GetKeyVals for input...%@AE@%%@NL@%
  1187. %@NL@%
  1188.  SELECT CASE RTRIM$(LTRIM$(IndexName$))%@NL@%
  1189.    CASE "TitleIndexBS", "AuthorIndexBS", "PubIndexBS", "NameIndexCH", "StateIndexCH"%@NL@%
  1190.     Prompt$ = "Value To Seek: "%@NL@%
  1191.     Key1$ = MakeString$(ASC(Letter$), Prompt$): IF Key1$ = "" THEN EXIT SUB%@NL@%
  1192.    CASE "IDIndex", "CardNumIndexCH", "ZipIndexCH"%@NL@%
  1193.     ValueToSeek$ = MakeString$(ASC(Letter$), Prompt$)%@NL@%
  1194.     IF ValueToSeek$ = "" THEN EXIT SUB%@NL@%
  1195.     IF IndexName$ = "IDIndex" THEN%@NL@%
  1196.       NumberToSeek# = VAL(ValueToSeek$)%@NL@%
  1197.       Key1$ = ValueToSeek$%@NL@%
  1198.     ELSE%@NL@%
  1199.       NumberToSeek& = VAL(ValueToSeek$)%@NL@%
  1200.       Key1$ = ValueToSeek$%@NL@%
  1201.     END IF%@NL@%
  1202.    CASE "BigIndex"%@NL@%
  1203.     CALL GetKeyVals(TempRec, Key1$, Key2$, Key3#, Letter$)%@NL@%
  1204.     ValueToSeek$ = STR$(Key3#)%@NL@%
  1205.    CASE ""%@NL@%
  1206.      Alert$ = "Sorry, can't search for field values on the default index"%@NL@%
  1207.      CALL ShowMessage(Alert$, 0)%@NL@%
  1208.    CASE ELSE%@NL@%
  1209.   END SELECT%@NL@%
  1210. %@NL@%
  1211. %@AB@%  ' Make sure the input values are minimally acceptable%@AE@%%@NL@%
  1212. %@NL@%
  1213.   IF NOT ValuesOK(TablesRec, Key1$, Key2$, ValueToSeek$) THEN%@NL@%
  1214.     CALL ShowMessage("Sorry, problem with your entry. Try again!", 0)%@NL@%
  1215.     EXIT SUB%@NL@%
  1216.   END IF%@NL@%
  1217. %@NL@%
  1218. %@AB@%  ' Show the user the values he entered in their appropriate fields%@AE@%%@NL@%
  1219.   CALL ClearEm(TablesRec.TableNum, 1, 1, 1, 1, 1, 1)%@NL@%
  1220.   CALL ShowIt(TempRec, IndexName$, TheTable, Key1$)%@NL@%
  1221. %@NL@%
  1222. %@AB@%  ' GetOperand lets user specify the way the SEEK is to be conducted ---%@AE@%%@NL@%
  1223. %@AB@%  ' either  =, >, >=, <, or <= the value that was entered above%@AE@%%@NL@%
  1224. %@NL@%
  1225.   DidIt = GetOperand%(Operand$)%@NL@%
  1226. %@NL@%
  1227. %@AB@%  ' The actual SEEK has to be done according to two factors, the Index on%@AE@%%@NL@%
  1228. %@AB@%  ' which it is conducted, and the condition chosen in GetOperand. In the%@AE@%%@NL@%
  1229. %@AB@%  ' next section, case on the Operand returned, then IF and ELSEIF on the%@AE@%%@NL@%
  1230. %@AB@%  ' basis of the index on which the search is being conducted%@AE@%%@NL@%
  1231. %@NL@%
  1232.   IF Operand$ <> "<>" THEN                ' "<>" represents user ESC choice%@NL@%
  1233. %@NL@%
  1234.    SELECT CASE Operand$%@NL@%
  1235.     CASE "", "="                        ' If operand ="" or "=", use =%@NL@%
  1236.       IF IndexName$ = "BigIndex" THEN%@NL@%
  1237.         IF INSTR(Key2$, ",") = 0 THEN Key2$ = TransposeName(Key2$) ' a name%@NL@%
  1238.         SEEKEQ TheTable, Key1$, Key2$, Key3#%@NL@%
  1239.       ELSEIF IndexName$ = "NameIndexCH" OR IndexName$ = "AuthorIndexBS" THEN%@NL@%
  1240.         IF INSTR(Key1$, ",") = 0 THEN Key1$ = TransposeName(Key1$) ' a name%@NL@%
  1241.         SEEKEQ TheTable, LTRIM$(RTRIM$(Key1$))%@NL@%
  1242.       ELSEIF IndexName$ = "IDIndex" THEN%@NL@%
  1243.         SEEKEQ TheTable, NumberToSeek#%@NL@%
  1244.       ELSEIF IndexName$ = "CardNumIndexCH" OR IndexName$ = "ZipIndexCH" THEN%@NL@%
  1245.         SEEKEQ TheTable, NumberToSeek&%@NL@%
  1246.       ELSE%@NL@%
  1247.         SEEKEQ TheTable, Key1$%@NL@%
  1248.       END IF%@NL@%
  1249.     CASE ">="                      ' at least gets them close%@NL@%
  1250.       IF IndexName$ = "BigIndex" THEN%@NL@%
  1251.         IF INSTR(Key2$, ",") = 0 THEN Key2$ = TransposeName(Key2$) ' a name%@NL@%
  1252.         SEEKGE TheTable, Key1$, Key2$, Key3#%@NL@%
  1253.       ELSEIF IndexName$ = "NameIndexCH" OR IndexName$ = "AuthorIndexBS" THEN%@NL@%
  1254.         IF INSTR(Key1$, ",") = 0 THEN Key1$ = TransposeName(Key1$)%@NL@%
  1255.         SEEKGE TheTable, Key1$%@NL@%
  1256.       ELSEIF IndexName$ = "IDIndex" THEN%@NL@%
  1257.         SEEKGE TheTable, NumberToSeek#%@NL@%
  1258.       ELSEIF IndexName$ = "CardNumIndexCH" OR IndexName$ = "ZipIndexCH" THEN%@NL@%
  1259.         SEEKGE TheTable, NumberToSeek&%@NL@%
  1260.       ELSE%@NL@%
  1261.         SEEKGE TheTable, Key1$%@NL@%
  1262.       END IF%@NL@%
  1263.     CASE ">"%@NL@%
  1264.       IF IndexName$ = "BigIndex" THEN%@NL@%
  1265.         IF INSTR(Key2$, ",") = 0 THEN Key2$ = TransposeName(Key2$)%@NL@%
  1266.         SEEKGT TheTable, Key1$, Key2$, Key3#%@NL@%
  1267.       ELSEIF IndexName$ = "NameIndexCH" OR IndexName$ = "AuthorIndexBS" THEN%@NL@%
  1268.         IF INSTR(Key1$, ",") = 0 THEN Key1$ = TransposeName(Key1$)%@NL@%
  1269.         SEEKGT TheTable, Key1$%@NL@%
  1270.       ELSEIF IndexName$ = "IDIndex" THEN%@NL@%
  1271.         SEEKGT TheTable, NumberToSeek#%@NL@%
  1272.       ELSEIF IndexName$ = "CardNumIndexCH" OR IndexName$ = "ZipIndexCH" THEN%@NL@%
  1273.         SEEKGT TheTable, NumberToSeek&%@NL@%
  1274.       ELSE%@NL@%
  1275.         SEEKGT TheTable, Key1$%@NL@%
  1276.       END IF%@NL@%
  1277.     CASE "<="%@NL@%
  1278.       IF IndexName$ = "BigIndex" THEN%@NL@%
  1279.         IF INSTR(Key2$, ",") = 0 THEN Key2$ = TransposeName(Key2$)%@NL@%
  1280.         SEEKGT TheTable, Key1$, Key2$, Key3#%@NL@%
  1281.         MOVEPREVIOUS TheTable%@NL@%
  1282.       ELSEIF IndexName$ = "NameIndexCH" OR IndexName$ = "AuthorIndexBS" THEN%@NL@%
  1283.         IF INSTR(Key1$, ",") = 0 THEN Key1$ = TransposeName(Key1$)%@NL@%
  1284.         SEEKGT TheTable, Key1$%@NL@%
  1285.         MOVEPREVIOUS TheTable%@NL@%
  1286.       ELSEIF IndexName$ = "IDIndex" THEN%@NL@%
  1287.         SEEKGT TheTable, NumberToSeek#%@NL@%
  1288.         MOVEPREVIOUS TheTable%@NL@%
  1289.       ELSEIF IndexName$ = "CardNumIndexCH" OR IndexName$ = "ZipIndexCH" THEN%@NL@%
  1290.         SEEKGT TheTable, NumberToSeek&%@NL@%
  1291.         MOVEPREVIOUS TheTable%@NL@%
  1292.       ELSE%@NL@%
  1293.         SEEKGT TheTable, Key1$%@NL@%
  1294.         MOVEPREVIOUS TheTable%@NL@%
  1295.       END IF%@NL@%
  1296.     CASE "<"%@NL@%
  1297.       IF IndexName$ = "BigIndex" THEN%@NL@%
  1298.         IF INSTR(Key2$, ",") = 0 THEN Key2$ = TransposeName(Key2$)%@NL@%
  1299.         SEEKGE TheTable, Key1$, Key2$, Key3#%@NL@%
  1300.         MOVEPREVIOUS TheTable%@NL@%
  1301.       ELSEIF IndexName$ = "NameIndexCH" OR IndexName$ = "AuthorIndexBS" THEN%@NL@%
  1302.         IF INSTR(Key1$, ",") = 0 THEN Key1$ = TransposeName(Key1$)%@NL@%
  1303.         SEEKGE TheTable, Key1$%@NL@%
  1304.         MOVEPREVIOUS TheTable%@NL@%
  1305.       ELSEIF IndexName$ = "IDIndex" THEN%@NL@%
  1306.         SEEKGE TheTable, NumberToSeek#%@NL@%
  1307.         MOVEPREVIOUS TheTable%@NL@%
  1308.       ELSEIF IndexName$ = "CardNumIndexCH" OR IndexName$ = "ZipIndexCH" THEN%@NL@%
  1309.         SEEKGE TheTable, NumberToSeek&%@NL@%
  1310.         MOVEPREVIOUS TheTable%@NL@%
  1311.       ELSE%@NL@%
  1312.         SEEKGE TheTable, Key1$%@NL@%
  1313.         MOVEPREVIOUS TheTable%@NL@%
  1314.       END IF%@NL@%
  1315.     CASE ELSE%@NL@%
  1316.       Alert$ = "The returned operand was " + Operand$%@NL@%
  1317.       CALL ShowMessage(Alert$, 0)%@NL@%
  1318.       SLEEP%@NL@%
  1319.   END SELECT%@NL@%
  1320.  ELSE                        ' If they choose ESC, go back to module level%@NL@%
  1321.    CALL DrawScreen(TheTable)%@NL@%
  1322.    CALL ShowRecord(TablesRec)%@NL@%
  1323.    Alert$ = "You've escaped. " + KEYSMESSAGE%@NL@%
  1324.    CALL ShowMessage(Alert$, 0)%@NL@%
  1325.    SLEEP%@NL@%
  1326.    Operand$ = ""%@NL@%
  1327.  END IF%@NL@%
  1328.   CALL EraseMessage%@NL@%
  1329.   CALL DrawScreen(TheTable)%@NL@%
  1330.   CALL Indexbox(TablesRec, CheckIndex%(TablesRec, FALSE))%@NL@%
  1331.  IF EOF(TablesRec.TableNum) THEN%@NL@%
  1332.   Alert$ = "Sorry,  unable to match value you entered with any field value"%@NL@%
  1333.   CALL ShowMessage(Alert$, 0):  ' SLEEP: EraseMessage%@NL@%
  1334.  END IF%@NL@%
  1335. %@NL@%
  1336. EXIT SUB%@NL@%
  1337. %@NL@%
  1338. SeekHandler:%@NL@%
  1339.  IF ERR = 83 THEN                          ' 83 = Index not found%@NL@%
  1340.     CALL DrawScreen(TablesRec.TableNum)%@NL@%
  1341.     Alert$ = "SETINDEX for " + IndexName$ + " failed. Need more buffers?"%@NL@%
  1342.     CALL ShowMessage(Alert$, 0)%@NL@%
  1343.     EXIT SUB%@NL@%
  1344.  END IF%@NL@%
  1345. %@NL@%
  1346. END SUB   ' End of SeekRecord procedure%@NL@%
  1347. %@NL@%
  1348. %@NL@%
  1349. %@NL@%
  1350. %@2@%%@AH@%BOOKMOD1.BAS%@AE@%%@EH@%%@NL@%
  1351. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\BOOKMOD1.BAS%@AE@%%@NL@%
  1352. %@NL@%
  1353. %@AB@%'***********************************************************************%@AE@%%@NL@%
  1354. %@AB@%'*      This is module level code for BOOKMOD2.BAS, and contains screen*%@AE@%%@NL@%
  1355. %@AB@%'*      drawing and user interface maintenance routines. This module   *%@AE@%%@NL@%
  1356. %@AB@%'*      doesn't contain ISAM statements.                               *%@AE@%%@NL@%
  1357. %@AB@%'***********************************************************************%@AE@%%@NL@%
  1358. %@NL@%
  1359. DEFINT A-Z%@NL@%
  1360. %@AB@%'$INCLUDE: 'booklook.bi'%@AE@%%@NL@%
  1361. KeysBox:%@NL@%
  1362.   DATA "╔══════════════════════════════════════╗"%@NL@%
  1363.   DATA "║                                      ║"%@NL@%
  1364.   DATA "║                                      ║"%@NL@%
  1365.   DATA "║                                      ║"%@NL@%
  1366.   DATA "║                                      ║"%@NL@%
  1367.   DATA "║                                      ║"%@NL@%
  1368.   DATA "║                                      ║"%@NL@%
  1369.   DATA "║                                      ║"%@NL@%
  1370.   DATA "╚═╡ Keys for Database Viewing/Editing ╞╝"%@NL@%
  1371. %@NL@%
  1372. HelpKeys1:%@NL@%
  1373.   DATA ""%@NL@%
  1374.   DATA "N = Next Record      P = Previous   "%@NL@%
  1375.   DATA "R = Reorder Records  F = Find Record"%@NL@%
  1376.   DATA "W = When Due Back    B = Borrower   "%@NL@%
  1377.   DATA "      V = View Other Table          "%@NL@%
  1378.   DATA "A = Add Record       D = Drop Record"%@NL@%
  1379.   DATA "E = Edit Record      Q = Quit       "%@NL@%
  1380.   DATA "O = Check Book Out   I = Check In   "%@NL@%
  1381.   DATA ""%@NL@%
  1382. %@NL@%
  1383. HelpKeys2:%@NL@%
  1384.   DATA ""%@NL@%
  1385.   DATA "N = Next Record      P = Previous   "%@NL@%
  1386.   DATA "R = Reorder Records  F = Find Record"%@NL@%
  1387.   DATA "      B = Books Outstanding         "%@NL@%
  1388.   DATA "      V = View Other Table          "%@NL@%
  1389.   DATA "A = Add Record       D = Drop Record"%@NL@%
  1390.   DATA "E = Edit Record      Q = Quit       "%@NL@%
  1391.   DATA "                                    "%@NL@%
  1392.   DATA ""%@NL@%
  1393. %@NL@%
  1394. Indexbox1:%@NL@%
  1395.   DATA "╔═══════════════════════════╗"%@NL@%
  1396.   DATA "║ By Titles                 ║"%@NL@%
  1397.   DATA "║ By Authors                ║"%@NL@%
  1398.   DATA "║ By Publishers             ║"%@NL@%
  1399.   DATA "║ By ID numbers             ║"%@NL@%
  1400.   DATA "║ By Title + Author + ID    ║"%@NL@%
  1401.   DATA "║ Default = Insertion order ║"%@NL@%
  1402.   DATA "║                           ║"%@NL@%
  1403.   DATA "╚═╡ Current Sorting Order ╞═╝"%@NL@%
  1404. Indexbox2:%@NL@%
  1405.   DATA "╔═══════════════════════════╗"%@NL@%
  1406.   DATA "║ By Name                   ║"%@NL@%
  1407.   DATA "║ By State                  ║"%@NL@%
  1408.   DATA "║ By Zip code               ║"%@NL@%
  1409.   DATA "║ By Card number            ║"%@NL@%
  1410.   DATA "║                           ║"%@NL@%
  1411.   DATA "║ Default = Insertion order ║"%@NL@%
  1412.   DATA "║                           ║"%@NL@%
  1413.   DATA "╚═╡ Current Sorting Order ╞═╝"%@NL@%
  1414. %@NL@%
  1415. %@NL@%
  1416. BooksTable:%@NL@%
  1417. DATA "╔════════════════════════════════════════════════════════════════════╗"%@NL@%
  1418. DATA "║                                                                    ║"%@NL@%
  1419. DATA "║    Title:                                                          ║"%@NL@%
  1420. DATA "║                                                                    ║"%@NL@%
  1421. DATA "║    Author:                                                         ║"%@NL@%
  1422. DATA "║                                                                    ║"%@NL@%
  1423. DATA "║    Publisher:                                                      ║"%@NL@%
  1424. DATA "║                                                                    ║"%@NL@%
  1425. DATA "║    Edition:                                                        ║"%@NL@%
  1426. DATA "║                                                                    ║"%@NL@%
  1427. DATA "║    Price:                                                          ║"%@NL@%
  1428. DATA "║                                                                    ║"%@NL@%
  1429. DATA "║    ID number:                                                      ║"%@NL@%
  1430. DATA "╚════════════════════════════════════════════════════════════════════╝"%@NL@%
  1431. %@NL@%
  1432. %@NL@%
  1433. LendeesTable:%@NL@%
  1434. DATA "╔════════════════════════════════════════════════════════════════════╗"%@NL@%
  1435. DATA "║                                                                    ║"%@NL@%
  1436. DATA "║   Name:                                                            ║"%@NL@%
  1437. DATA "║                                                                    ║"%@NL@%
  1438. DATA "║   Street:                                                          ║"%@NL@%
  1439. DATA "║                                                                    ║"%@NL@%
  1440. DATA "║   City:                                                            ║"%@NL@%
  1441. DATA "║                                                                    ║"%@NL@%
  1442. DATA "║   State:                                                           ║"%@NL@%
  1443. DATA "║                                                                    ║"%@NL@%
  1444. DATA "║   Zipcode:                                                         ║"%@NL@%
  1445. DATA "║                                                                    ║"%@NL@%
  1446. DATA "║   Card number:                                                     ║"%@NL@%
  1447. DATA "╚════════════════════════════════════════════════════════════════════╝"%@NL@%
  1448. %@NL@%
  1449. OperandBox:%@NL@%
  1450. DATA "╔═══════════════════════════╗"%@NL@%
  1451. DATA "║                           ║"%@NL@%
  1452. DATA "║ Greater Than              ║"%@NL@%
  1453. DATA "║ or                        ║"%@NL@%
  1454. DATA "║ Equal To     Value Entered║"%@NL@%
  1455. DATA "║ or                        ║"%@NL@%
  1456. DATA "║ Less Than                 ║"%@NL@%
  1457. DATA "║                           ║"%@NL@%
  1458. DATA "╚══╡ Relationship to Key ╞══╝"%@NL@%
  1459. %@NL@%
  1460. EditMessage:%@NL@%
  1461. DATA "╔═══════════════════════════╗"%@NL@%
  1462. DATA "║ A log is being kept while ║"%@NL@%
  1463. DATA "║ you edit fields in this   ║"%@NL@%
  1464. DATA "║ record. Press U to undo   ║"%@NL@%
  1465. DATA "║ each preceding edit, or   ║"%@NL@%
  1466. DATA "║ CTRL+U to undo all of the ║"%@NL@%
  1467. DATA "║ pending edits as a group. ║"%@NL@%
  1468. DATA "║                           ║"%@NL@%
  1469. DATA "╚═════╡ To Undo Edits ╞═════╝"%@NL@%
  1470. %@NL@%
  1471. %@AB@%'***************************************************************************%@AE@%%@NL@%
  1472. %@AB@%'*  The ClearEm SUB erases the parts of the screen where table record col- *%@AE@%%@NL@%
  1473. %@AB@%'*  umn information is displayed, depending on which fields are specified. *%@AE@%%@NL@%
  1474. %@AB@%'*                                Parameters                               *%@AE@%%@NL@%
  1475. %@AB@%'*  TableNum    Integer specifying the table being displayed               *%@AE@%%@NL@%
  1476. %@AB@%'*  Field?      Boolean values specifying which fields to erase            *%@AE@%%@NL@%
  1477. %@AB@%'***************************************************************************%@AE@%%@NL@%
  1478. SUB ClearEm (TableNum%, Field1%, Field2%, Field3%, Field4%, Field5%, Field6%)%@NL@%
  1479. %@NL@%
  1480.   DIM ToClear(10) AS INTEGER%@NL@%
  1481. %@NL@%
  1482.   ToClear(0) = Field1: ToClear(1) = Field2: ToClear(2) = Field3%@NL@%
  1483.   ToClear(3) = Field4: ToClear(4) = Field5: ToClear(5) = Field6%@NL@%
  1484. %@NL@%
  1485.   COLOR FOREGROUND, BACKGROUND%@NL@%
  1486. %@NL@%
  1487.       FOR Index = 0 TO 5%@NL@%
  1488.         IF ToClear(Index) THEN%@NL@%
  1489.           SELECT CASE Index%@NL@%
  1490.             CASE 0%@NL@%
  1491.               LOCATE TITLEFIELD, 18%@NL@%
  1492.               PRINT "                                                    "%@NL@%
  1493.             CASE 1%@NL@%
  1494.               LOCATE AUTHORFIELD, 18%@NL@%
  1495.               PRINT "                                                    "%@NL@%
  1496.             CASE 2%@NL@%
  1497.               LOCATE PUBFIELD, 18%@NL@%
  1498.               PRINT "                                                    "%@NL@%
  1499.             CASE 3%@NL@%
  1500.               LOCATE EDFIELD, 18%@NL@%
  1501.               PRINT "                                                    "%@NL@%
  1502.             CASE 4%@NL@%
  1503.               IF TableNum% = cCardHoldersTableNum THEN%@NL@%
  1504.                 LOCATE PRICEFIELD, 18%@NL@%
  1505.                 PRINT "                                                    "%@NL@%
  1506.               ELSE%@NL@%
  1507.                 LOCATE PRICEFIELD, 19%@NL@%
  1508.                 PRINT "                                                   "%@NL@%
  1509.               END IF%@NL@%
  1510.             CASE 5%@NL@%
  1511.               LOCATE IDFIELD, 18%@NL@%
  1512.               PRINT "                                                    "%@NL@%
  1513.           END SELECT%@NL@%
  1514.         END IF%@NL@%
  1515.       NEXT Index%@NL@%
  1516. END SUB%@NL@%
  1517. %@NL@%
  1518. %@AB@%'**************************************************************************%@AE@%%@NL@%
  1519. %@AB@%'*  The ConfirmEntry FUNCTION echoes the user's input and processes his   *%@AE@%%@NL@%
  1520. %@AB@%'*  response to make sure the proper action is taken.                     *%@AE@%%@NL@%
  1521. %@AB@%'*                                 Parameters                             *%@AE@%%@NL@%
  1522. %@AB@%'*  Letter$   Contains the input that the user has just entered.          *%@AE@%%@NL@%
  1523. %@AB@%'**************************************************************************%@AE@%%@NL@%
  1524. FUNCTION ConfirmEntry% (Letter$)%@NL@%
  1525.   Alert$ = "Press ENTER to confirm choice, type value, or TAB to move on"%@NL@%
  1526.   CALL ShowMessage(Alert$, 1)%@NL@%
  1527.   DO%@NL@%
  1528.   Answer$ = INKEY$%@NL@%
  1529.   LOOP WHILE Answer$ = EMPTYSTRING%@NL@%
  1530.   Reply% = ASC(Answer$)%@NL@%
  1531. %@NL@%
  1532.   SELECT CASE Reply%%@NL@%
  1533.     CASE ENTER%@NL@%
  1534.       ConfirmEntry% = -1%@NL@%
  1535.       Letter$ = ""%@NL@%
  1536.     CASE TABKEY%@NL@%
  1537.       ConfirmEntry% = 0%@NL@%
  1538.       Letter$ = Answer$%@NL@%
  1539.     CASE ASC(" ") TO ASC("~")%@NL@%
  1540.       Letter$ = Answer$%@NL@%
  1541.       ConfirmEntry = -1%@NL@%
  1542.     CASE ELSE%@NL@%
  1543.       ConfirmEntry% = 0%@NL@%
  1544.       Letter$ = "eScApE"%@NL@%
  1545.       CALL ShowMessage("Invalid key --- Try again", 0)%@NL@%
  1546.    END SELECT%@NL@%
  1547. END FUNCTION%@NL@%
  1548. %@NL@%
  1549. %@AB@%'***************************************************************************%@AE@%%@NL@%
  1550. %@AB@%'*    The DrawHelpBoox SUB draws the menu box that links a key to a task.  *%@AE@%%@NL@%
  1551. %@AB@%'***************************************************************************%@AE@%%@NL@%
  1552. SUB DrawHelpBox%@NL@%
  1553.   COLOR FOREGROUND, BACKGROUND%@NL@%
  1554.   RESTORE KeysBox%@NL@%
  1555.     FOR Row = BOXTOP TO BOXEND%@NL@%
  1556.       LOCATE Row, 1%@NL@%
  1557.       READ Temp$%@NL@%
  1558.       PRINT Temp$%@NL@%
  1559.       IF Row = BOXEND THEN%@NL@%
  1560.         COLOR BACKGROUND, FOREGROUND + BRIGHT%@NL@%
  1561.         LOCATE Row, HELPCOL + 3%@NL@%
  1562.         PRINT " Keys for Database Viewing/Editing "%@NL@%
  1563.         COLOR FOREGROUND, BACKGROUND%@NL@%
  1564.       END IF%@NL@%
  1565.     NEXT Row%@NL@%
  1566.   COLOR FOREGROUND, BACKGROUND%@NL@%
  1567. END SUB%@NL@%
  1568. %@NL@%
  1569. %@AB@%'***************************************************************************%@AE@%%@NL@%
  1570. %@AB@%'*    The DrawHelpKeys SUB refills the menu box that links a key to a task.*%@AE@%%@NL@%
  1571. %@AB@%'*                                Parameters                               *%@AE@%%@NL@%
  1572. %@AB@%'*    TableNum    Integer identifying the table being displayed            *%@AE@%%@NL@%
  1573. %@AB@%'***************************************************************************%@AE@%%@NL@%
  1574. SUB DrawHelpKeys (TableNum AS INTEGER)%@NL@%
  1575. %@NL@%
  1576. COLOR FOREGROUND, BACKGROUND%@NL@%
  1577. IF TableNum = cBookStockTableNum THEN RESTORE HelpKeys1 ELSE RESTORE HelpKeys2%@NL@%
  1578. FOR Row = BOXTOP TO BOXEND%@NL@%
  1579.   LOCATE Row, HELPCOL + 2%@NL@%
  1580.   READ Temp$%@NL@%
  1581.   PRINT Temp$%@NL@%
  1582.   IF Row = BOXEND THEN%@NL@%
  1583.     COLOR BACKGROUND, FOREGROUND + BRIGHT%@NL@%
  1584.     LOCATE Row, HELPCOL + 3%@NL@%
  1585.     PRINT " Keys for Database Viewing/Editing "%@NL@%
  1586.     COLOR FOREGROUND, BACKGROUND%@NL@%
  1587.     END IF%@NL@%
  1588. NEXT Row%@NL@%
  1589. COLOR FOREGROUND, BACKGROUND%@NL@%
  1590. %@NL@%
  1591. END SUB%@NL@%
  1592. %@NL@%
  1593. %@AB@%'***************************************************************************%@AE@%%@NL@%
  1594. %@AB@%'*  The DrawIndexBox procedure draws the appropriate index box, depending  *%@AE@%%@NL@%
  1595. %@AB@%'*  the table being displayed. If the task is EDITRECORD, the index box    *%@AE@%%@NL@%
  1596. %@AB@%'*  information is replaced with information about Undo and Undo All       *%@AE@%%@NL@%
  1597. %@AB@%'*                               Parameters                                *%@AE@%%@NL@%
  1598. %@AB@%'*  TableNum    Integer identifying the table being displayed              *%@AE@%%@NL@%
  1599. %@AB@%'*  Task        Integer identifying the task the user is involved in       *%@AE@%%@NL@%
  1600. %@AB@%'***************************************************************************%@AE@%%@NL@%
  1601. SUB DrawIndexBox (TableNum AS INTEGER, Task%)%@NL@%
  1602. %@NL@%
  1603. COLOR FOREGROUND, BACKGROUND%@NL@%
  1604. %@NL@%
  1605. IF Task = EDITRECORD THEN%@NL@%
  1606.   RESTORE EditMessage%@NL@%
  1607. ELSE%@NL@%
  1608.   IF TableNum = 1 THEN RESTORE Indexbox1 ELSE RESTORE Indexbox2%@NL@%
  1609. END IF%@NL@%
  1610. %@NL@%
  1611. FOR Row = BOXTOP TO BOXEND%@NL@%
  1612.   LOCATE Row, 42%@NL@%
  1613.   READ Temp$%@NL@%
  1614.   PRINT Temp$%@NL@%
  1615.   IF Row = BOXEND THEN%@NL@%
  1616.     IF Task = EDITRECORD THEN%@NL@%
  1617.       COLOR FOREGROUND + BRIGHT, BACKGROUND%@NL@%
  1618.       LOCATE 19, INDBOX + 16%@NL@%
  1619.       PRINT "U"%@NL@%
  1620.       LOCATE 21, INDBOX + 2%@NL@%
  1621.       PRINT "CTRL+U"%@NL@%
  1622.       LOCATE Row, INDBOX + 7%@NL@%
  1623.       PRINT " To Undo Edits "%@NL@%
  1624.       COLOR FOREGROUND, BACKGROUND%@NL@%
  1625.     ELSE%@NL@%
  1626.       COLOR BACKGROUND, FOREGROUND + BRIGHT%@NL@%
  1627.       LOCATE Row, INDBOX + 3%@NL@%
  1628.       PRINT " Current Sorting Order "%@NL@%
  1629.       COLOR FOREGROUND, BACKGROUND%@NL@%
  1630.     END IF%@NL@%
  1631.   END IF%@NL@%
  1632. NEXT Row%@NL@%
  1633. COLOR FOREGROUND, BACKGROUND%@NL@%
  1634. %@NL@%
  1635. END SUB%@NL@%
  1636. %@NL@%
  1637. %@AB@%'***************************************************************************%@AE@%%@NL@%
  1638. %@AB@%'*  The DrawScreen SUB calls other procedures to draw the appropriate parts*%@AE@%%@NL@%
  1639. %@AB@%'*  of the screen for the table to be displayed.                           *%@AE@%%@NL@%
  1640. %@AB@%'*                                Parameters                               *%@AE@%%@NL@%
  1641. %@AB@%'*  TableNum    Integer telling which table is to be shown                 *%@AE@%%@NL@%
  1642. %@AB@%'***************************************************************************%@AE@%%@NL@%
  1643. SUB DrawScreen (TableNum AS INTEGER)%@NL@%
  1644.   CALL DrawTable(TableNum)%@NL@%
  1645.   CALL DrawHelpBox%@NL@%
  1646.   CALL DrawHelpKeys(TableNum)%@NL@%
  1647.   CALL DrawIndexBox(TableNum, Task)%@NL@%
  1648.   CALL ShowMessage("", 0)%@NL@%
  1649.   COLOR FOREGROUND, BACKGROUND%@NL@%
  1650. END SUB%@NL@%
  1651. %@NL@%
  1652. %@AB@%'***************************************************************************%@AE@%%@NL@%
  1653. %@AB@%'*  The DrawTable SUB draws and lables the table being displayed.          *%@AE@%%@NL@%
  1654. %@AB@%'*                                Parameters                               *%@AE@%%@NL@%
  1655. %@AB@%'*  TableNum    The number of the table currently being displayed          *%@AE@%%@NL@%
  1656. %@AB@%'***************************************************************************%@AE@%%@NL@%
  1657. SUB DrawTable (TableNum AS INTEGER)%@NL@%
  1658. CALL ClearEm(TableNum, 1, 1, 1, 1, 1, 1)%@NL@%
  1659. VIEW PRINT%@NL@%
  1660. COLOR FOREGROUND, BACKGROUND%@NL@%
  1661. SELECT CASE TableNum%@NL@%
  1662.   CASE 1%@NL@%
  1663.     TableName$ = " Book Stock Table "%@NL@%
  1664.   CASE 2%@NL@%
  1665.     TableName$ = " Card Holders Table "%@NL@%
  1666. END SELECT%@NL@%
  1667. %@NL@%
  1668. HowLong = LEN(TableName$)%@NL@%
  1669. NameSpace$ = "╡" + STRING$(HowLong, 32) + "╞"%@NL@%
  1670. PlaceName = (72 \ 2) - (HowLong \ 2)%@NL@%
  1671. %@NL@%
  1672. IF TableNum = 1 THEN RESTORE BooksTable ELSE RESTORE LendeesTable%@NL@%
  1673. %@NL@%
  1674. COLOR FOREGROUND, BACKGROUND%@NL@%
  1675. %@NL@%
  1676. FOR Row = TABLETOP TO TABLEEND%@NL@%
  1677.   LOCATE Row, 1%@NL@%
  1678.   READ Temp$%@NL@%
  1679.   PRINT Temp$%@NL@%
  1680.   IF Row = TABLETOP THEN%@NL@%
  1681.     LOCATE TABLETOP, PlaceName%@NL@%
  1682.     PRINT NameSpace$%@NL@%
  1683.     COLOR BACKGROUND, BRIGHT + FOREGROUND%@NL@%
  1684.     LOCATE 1, PlaceName + 1%@NL@%
  1685.     PRINT TableName$%@NL@%
  1686.     COLOR FOREGROUND, BACKGROUND%@NL@%
  1687.   END IF%@NL@%
  1688. NEXT Row%@NL@%
  1689. COLOR FOREGROUND, BACKGROUND%@NL@%
  1690. %@NL@%
  1691. END SUB%@NL@%
  1692. %@NL@%
  1693. %@AB@%'***************************************************************************%@AE@%%@NL@%
  1694. %@AB@%'*  The EraseMessage SUB erases the message in the message box between the *%@AE@%%@NL@%
  1695. %@AB@%'*  displayed table and the menus at the bottom of the screen. It replaces *%@AE@%%@NL@%
  1696. %@AB@%'*  the corners of the table and menus that may have been overwritten      *%@AE@%%@NL@%
  1697. %@AB@%'***************************************************************************%@AE@%%@NL@%
  1698. SUB EraseMessage%@NL@%
  1699.   COLOR FOREGROUND, BACKGROUND%@NL@%
  1700.        LOCATE MESBOXTOP, 1%@NL@%
  1701.        PRINT "╚"; STRING$(68, CHR$(205)); "╝"%@NL@%
  1702.        LOCATE MESFIELD, 1%@NL@%
  1703.        PRINT SPACE$(70)%@NL@%
  1704.        LOCATE MESBOXEND, 1%@NL@%
  1705.        PRINT "╔"; STRING$(38, CHR$(205)); "╗ ╔"; STRING$(27, CHR$(205)); "╗"%@NL@%
  1706. %@NL@%
  1707. END SUB%@NL@%
  1708. %@NL@%
  1709. %@AB@%'**************************** MakeString FUNCTION **************************%@AE@%%@NL@%
  1710. %@AB@%'*                                                                         *%@AE@%%@NL@%
  1711. %@AB@%'* The MakeString FUNCTION provides a minimal editor to operate in the     *%@AE@%%@NL@%
  1712. %@AB@%'* BOOKLOOK message box. A prompt is shown. The user can enter numbers,    *%@AE@%%@NL@%
  1713. %@AB@%'* letters, punctuation, the ENTER, BACKSPACE and ESC keys.                *%@AE@%%@NL@%
  1714. %@AB@%'*                                                                         *%@AE@%%@NL@%
  1715. %@AB@%'*                            Parameters:                                  *%@AE@%%@NL@%
  1716. %@AB@%'*   FilterTrap   Brings in a keystroke or letter by ASCII value           *%@AE@%%@NL@%
  1717. %@AB@%'*   ThisString   Prompt passed in depends on calling function             *%@AE@%%@NL@%
  1718. %@AB@%'*                                                                         *%@AE@%%@NL@%
  1719. %@AB@%'***************************************************************************%@AE@%%@NL@%
  1720. FUNCTION MakeString$ (FilterTrap AS INTEGER, ThisString$)%@NL@%
  1721. %@NL@%
  1722. MessageLen = LEN(ThisString$)                   ' Save length of the prompt%@NL@%
  1723. IF FilterTrap THEN                              ' then, if a letter was%@NL@%
  1724.   ThisString$ = ThisString$ + CHR$(FilterTrap)  ' passed in, add it to the%@NL@%
  1725.   NewString$ = CHR$(FilterTrap)                 ' prompt and use it to start%@NL@%
  1726. END IF                                          ' string to be returned.%@NL@%
  1727. CALL ShowMessage(ThisString$, 1)                ' Show the string and turn%@NL@%
  1728. DO                                              ' on cursor at end.%@NL@%
  1729.   DO%@NL@%
  1730.   Answer$ = INKEY$%@NL@%
  1731.   LOOP WHILE Answer$ = EMPTYSTRING%@NL@%
  1732.       SELECT CASE Answer$%@NL@%
  1733.         CASE CHR$(ESCAPE)%@NL@%
  1734.           FilterTrap = ESCAPE%@NL@%
  1735.           CALL ShowMessage(KEYSMESSAGE, 0)%@NL@%
  1736.           EXIT FUNCTION%@NL@%
  1737.         CASE " " TO "~"%@NL@%
  1738.           NewString$ = NewString$ + Answer$%@NL@%
  1739.           ThisString$ = ThisString$ + Answer$%@NL@%
  1740.           CALL ShowMessage(ThisString$, 1)%@NL@%
  1741.         CASE CHR$(BACKSPACE)%@NL@%
  1742.           ShortLen = LEN(ThisString$) - 1%@NL@%
  1743.           ThisString$ = MID$(ThisString$, 1, ShortLen)%@NL@%
  1744.           NewString$ = MID$(ThisString$, MessageLen + 1)%@NL@%
  1745.           CALL ShowMessage(ThisString$, 1)%@NL@%
  1746.         CASE CHR$(ENTER)%@NL@%
  1747.           LOCATE , , 0%@NL@%
  1748.           MakeString$ = LTRIM$(RTRIM$(NewString$))%@NL@%
  1749.           EXIT FUNCTION%@NL@%
  1750.         CASE ELSE%@NL@%
  1751.           BEEP%@NL@%
  1752.           CALL ShowMessage("Not a valid key --- press Space bar", 0)%@NL@%
  1753.       END SELECT%@NL@%
  1754. LOOP%@NL@%
  1755. END FUNCTION%@NL@%
  1756. %@NL@%
  1757. %@AB@%'***************************************************************************%@AE@%%@NL@%
  1758. %@AB@%'*  The ReturnKey$ FUNCTION gets a key from the user and returns its value *%@AE@%%@NL@%
  1759. %@AB@%'***************************************************************************%@AE@%%@NL@%
  1760. FUNCTION ReturnKey$%@NL@%
  1761.   DO%@NL@%
  1762.     Answer$ = INKEY$%@NL@%
  1763.   LOOP WHILE Answer$ = EMPTYSTRING%@NL@%
  1764.   ReturnKey$ = Answer$%@NL@%
  1765. END FUNCTION%@NL@%
  1766. %@NL@%
  1767. %@AB@%'******************************** ShowIt SUB ******************************%@AE@%%@NL@%
  1768. %@AB@%'*                                                                        *%@AE@%%@NL@%
  1769. %@AB@%'*    After the user enters a value to search for in a specific index,    *%@AE@%%@NL@%
  1770. %@AB@%'*    this SUB places the value in the proper element of the temporary    *%@AE@%%@NL@%
  1771. %@AB@%'*    record variable, then displays the value in the field. Finally,     *%@AE@%%@NL@%
  1772. %@AB@%'*    the user is prompted to choose the relationship the indexed value   *%@AE@%%@NL@%
  1773. %@AB@%'*    should have to the key that has been entered.                       *%@AE@%%@NL@%
  1774. %@AB@%'*                            Parameters:                                 *%@AE@%%@NL@%
  1775. %@AB@%'*    TabesRec:       A temporary recordvariable - same as BigRec         *%@AE@%%@NL@%
  1776. %@AB@%'*    WhichIndex:     Tells name of Index on which key should be sought   *%@AE@%%@NL@%
  1777. %@AB@%'*    WhichTable:     The number of the table currently being displayed   *%@AE@%%@NL@%
  1778. %@AB@%'*    StringTo Show:  Value user wants to search for in index             *%@AE@%%@NL@%
  1779. %@AB@%'*                                                                        *%@AE@%%@NL@%
  1780. %@AB@%'**************************************************************************%@AE@%%@NL@%
  1781. SUB ShowIt (TablesRec AS RecStruct, WhichIndex$, WhichTable%, StringToShow$)%@NL@%
  1782.   TablesRec.TableNum = WhichTable%@NL@%
  1783.   TablesRec.WhichIndex = WhichIndex$%@NL@%
  1784.   COLOR BRIGHT + FOREGROUND, BACKGROUND%@NL@%
  1785.       SELECT CASE WhichIndex$%@NL@%
  1786.         CASE "TitleIndexBS"%@NL@%
  1787.           TablesRec.Inventory.Title = StringToShow$%@NL@%
  1788.         CASE "AuthorIndexBS"%@NL@%
  1789.           TablesRec.Inventory.Author = StringToShow$%@NL@%
  1790.         CASE "PubIndexBS"%@NL@%
  1791.           TablesRec.Inventory.Publisher = StringToShow$%@NL@%
  1792.         CASE "IDIndex"%@NL@%
  1793.           TablesRec.Inventory.IDnum = VAL(StringToShow$)%@NL@%
  1794.         CASE "NameIndexCH"%@NL@%
  1795.           TablesRec.Lendee.TheName = StringToShow$%@NL@%
  1796.         CASE "StateIndexCH"%@NL@%
  1797.           TablesRec.Lendee.State = StringToShow$%@NL@%
  1798.         CASE "ZipIndexCH"%@NL@%
  1799.           TablesRec.Lendee.Zip = VAL(StringToShow$)%@NL@%
  1800.         CASE "CardNumIndexCH"%@NL@%
  1801.           TablesRec.Lendee.CardNum = VAL(StringToShow$)%@NL@%
  1802.       END SELECT%@NL@%
  1803.     CALL ShowRecord(TablesRec)%@NL@%
  1804.   COLOR FOREGROUND, BACKGROUND%@NL@%
  1805. END SUB%@NL@%
  1806. %@NL@%
  1807. %@AB@%'***************************************************************************%@AE@%%@NL@%
  1808. %@AB@%'*  The ShowKeys SUB presents the key the user should press for a desired  *%@AE@%%@NL@%
  1809. %@AB@%'*  operation associated with a description of the task.                   *%@AE@%%@NL@%
  1810. %@AB@%'*                               Parameters                                *%@AE@%%@NL@%
  1811. %@AB@%'*  TablesRec   RecStruct type variable containing table information       *%@AE@%%@NL@%
  1812. %@AB@%'*  ForeGrnd    Integer indicating whether key is highlighted or not       *%@AE@%%@NL@%
  1813. %@AB@%'*  TableDone   1 for No Next Record, 0 otherwise (usually DimN)           *%@AE@%%@NL@%
  1814. %@AB@%'*  TableStart  1 for No Previous Record, 0 otherwise (usually DimP)       *%@AE@%%@NL@%
  1815. %@AB@%'***************************************************************************%@AE@%%@NL@%
  1816. SUB ShowKeys (TablesRec AS RecStruct, ForeGrnd%, TableDone%, TableStart%)%@NL@%
  1817.   COLOR ForeGrnd, BACKGROUND                    'foreground bright%@NL@%
  1818.   LOCATE NLINE, 3%@NL@%
  1819.   PRINT "N"%@NL@%
  1820.   LOCATE NLINE, 24%@NL@%
  1821.   PRINT "P"%@NL@%
  1822.   LOCATE RLINE, 3%@NL@%
  1823.   PRINT "R"%@NL@%
  1824.   LOCATE RLINE, 24%@NL@%
  1825.   PRINT "F"%@NL@%
  1826.   IF TablesRec.TableNum = cBookStockTableNum THEN%@NL@%
  1827.     LOCATE WLINE, 3%@NL@%
  1828.     PRINT "W"%@NL@%
  1829.     LOCATE WLINE, 24%@NL@%
  1830.     PRINT "B"%@NL@%
  1831.   ELSE%@NL@%
  1832.     LOCATE WLINE, 9%@NL@%
  1833.     PRINT "B"%@NL@%
  1834.   END IF%@NL@%
  1835.   LOCATE VLINE, 9%@NL@%
  1836.   PRINT "V"%@NL@%
  1837.   LOCATE ALINE, 3%@NL@%
  1838.   PRINT "A"%@NL@%
  1839.   LOCATE ALINE, 24%@NL@%
  1840.   PRINT "D"%@NL@%
  1841.   LOCATE ELINE, 3%@NL@%
  1842.   PRINT "E"%@NL@%
  1843.   LOCATE ELINE, 24%@NL@%
  1844.   PRINT "Q"%@NL@%
  1845.   IF TablesRec.TableNum = cBookStockTableNum THEN%@NL@%
  1846.     LOCATE CLINE, 3%@NL@%
  1847.     PRINT "O"%@NL@%
  1848.     LOCATE CLINE, 24%@NL@%
  1849.     PRINT "I"%@NL@%
  1850.   END IF%@NL@%
  1851.   IF TableDone = TRUE THEN%@NL@%
  1852. %@NL@%
  1853.     LOCATE NLINE, 3%@NL@%
  1854.     PRINT " No Next Record"%@NL@%
  1855.   ELSE%@NL@%
  1856.     LOCATE NLINE, 3%@NL@%
  1857.     PRINT "N "%@NL@%
  1858.     COLOR FOREGROUND, BACKGROUND%@NL@%
  1859.     LOCATE NLINE, 5%@NL@%
  1860.     PRINT "= "%@NL@%
  1861.     LOCATE NLINE, 6%@NL@%
  1862.     PRINT " Next Record"%@NL@%
  1863.   END IF%@NL@%
  1864.   IF TableStart = TRUE THEN%@NL@%
  1865.     COLOR ForeGrnd, BACKGROUND%@NL@%
  1866.     LOCATE NLINE, 20%@NL@%
  1867.     PRINT " No Previous Record"%@NL@%
  1868.   ELSE%@NL@%
  1869.     COLOR ForeGrnd, BACKGROUND%@NL@%
  1870.     LOCATE NLINE, 20%@NL@%
  1871.     PRINT "    P "%@NL@%
  1872.     COLOR FOREGROUND, BACKGROUND%@NL@%
  1873.     LOCATE NLINE, 26%@NL@%
  1874.     PRINT "= "%@NL@%
  1875.     LOCATE NLINE, 27%@NL@%
  1876.     PRINT " Previous   "%@NL@%
  1877.     END IF%@NL@%
  1878.   COLOR FOREGROUND, BACKGROUND%@NL@%
  1879. END SUB%@NL@%
  1880. %@NL@%
  1881. %@AB@%'**************************************************************************%@AE@%%@NL@%
  1882. %@AB@%'*  The ShowMessage SUB displays the message string passed in the message *%@AE@%%@NL@%
  1883. %@AB@%'*  box between the displayed table and the menus. If the Cursor parameter*%@AE@%%@NL@%
  1884. %@AB@%'*  is 0, no cursor appears in the box; if it is 1, a cursor is displaed. *%@AE@%%@NL@%
  1885. %@AB@%'*                                 Parameters                             *%@AE@%%@NL@%
  1886. %@AB@%'*  Message$    Prompt or message to display                              *%@AE@%%@NL@%
  1887. %@AB@%'*  Cursor      Boolean value telling whether or not to show a cursor     *%@AE@%%@NL@%
  1888. %@AB@%'**************************************************************************%@AE@%%@NL@%
  1889. SUB ShowMessage (Message$, Cursor)%@NL@%
  1890.   CALL EraseMessage%@NL@%
  1891.   IF (LEN(Message$) MOD 2) THEN%@NL@%
  1892.         Borderlen = 1%@NL@%
  1893.   END IF%@NL@%
  1894.   MesLen = LEN(Message$)%@NL@%
  1895.   SELECT CASE Cursor                          ' No cursor request means to%@NL@%
  1896.   CASE FALSE                                  ' center the message in box%@NL@%
  1897.     HalfMes = (MesLen \ 2) + 1                ' and display without cursor%@NL@%
  1898.     Start = (SCREENWIDTH \ 2) - HalfMes%@NL@%
  1899.   CASE ELSE%@NL@%
  1900.     Start = 4                                 ' Message is part of an edit%@NL@%
  1901.   END SELECT                                  ' so display flush left, and%@NL@%
  1902.     LOCATE MESBOXTOP, 2                       ' keep cursor visible%@NL@%
  1903.     PRINT "╔"; STRING$(66, CHR$(205)); "╗"%@NL@%
  1904.     LOCATE MESFIELD, 2%@NL@%
  1905.     PRINT "║"; SPACE$(66); "║"%@NL@%
  1906.     LOCATE MESBOXEND, 2%@NL@%
  1907.     PRINT "╚"; STRING$(37, CHR$(205)); "╦"; "═╦"; STRING$(26, CHR$(205)); "╝"%@NL@%
  1908.     COLOR BRIGHT + FOREGROUND, BACKGROUND%@NL@%
  1909.     LOCATE MESFIELD, Start, Cursor%@NL@%
  1910.     PRINT Message$;%@NL@%
  1911.     LOCATE MESFIELD, Start + MesLen, Cursor%@NL@%
  1912.     PRINT "";%@NL@%
  1913.     COLOR FOREGROUND, BACKGROUND%@NL@%
  1914. END SUB%@NL@%
  1915. %@NL@%
  1916. %@AB@%'**************************************************************************%@AE@%%@NL@%
  1917. %@AB@%'*  The ShowRecord SUB displays the columns of the current record of the  *%@AE@%%@NL@%
  1918. %@AB@%'*  table being displayed. Numerics are only displayed if they are <> 0.  *%@AE@%%@NL@%
  1919. %@AB@%'*                                Parameters                              *%@AE@%%@NL@%
  1920. %@AB@%'*  TablesRec   RecStruct type variable containing table information      *%@AE@%%@NL@%
  1921. %@AB@%'**************************************************************************%@AE@%%@NL@%
  1922. SUB ShowRecord (TablesRec AS RecStruct)%@NL@%
  1923. COLOR FOREGROUND, BACKGROUND%@NL@%
  1924.   SELECT CASE TablesRec.TableNum%@NL@%
  1925.     CASE cBookStockTableNum%@NL@%
  1926.       LOCATE TITLEFIELD, 18: PRINT TablesRec.Inventory.Title%@NL@%
  1927.       LOCATE AUTHORFIELD, 18: PRINT TablesRec.Inventory.Author%@NL@%
  1928.       LOCATE PUBFIELD, 18: PRINT TablesRec.Inventory.Publisher%@NL@%
  1929.       IF TablesRec.Inventory.Edition <> 0 THEN LOCATE EDFIELD, 17: PRINT STR$(TablesRec.Inventory.Edition)%@NL@%
  1930.       IF TablesRec.Inventory.Price <> 0 THEN LOCATE PRICEFIELD, 17: PRINT " $"; STR$(TablesRec.Inventory.Price)%@NL@%
  1931.       IF TablesRec.Inventory.IDnum <> 0 THEN LOCATE IDFIELD, 17: PRINT STR$(TablesRec.Inventory.IDnum)%@NL@%
  1932.     CASE cCardHoldersTableNum%@NL@%
  1933.       LOCATE NAMEFIELD, 18: PRINT TablesRec.Lendee.TheName%@NL@%
  1934.       LOCATE STREETFIELD, 18: PRINT TablesRec.Lendee.Street%@NL@%
  1935.       LOCATE CITYFIELD, 18: PRINT TablesRec.Lendee.City%@NL@%
  1936.       LOCATE STATEFIELD, 18: PRINT TablesRec.Lendee.State%@NL@%
  1937.       IF TablesRec.Lendee.Zip <> 0 THEN LOCATE ZIPFIELD, 17: PRINT STR$(TablesRec.Lendee.Zip)%@NL@%
  1938.       IF TablesRec.Lendee.CardNum <> 0 THEN LOCATE CARDNUMFIELD, 17: PRINT STR$(TablesRec.Lendee.CardNum)%@NL@%
  1939.     CASE ELSE%@NL@%
  1940.        CALL ShowMessage("There are no other forms defined", 0)%@NL@%
  1941.   END SELECT%@NL@%
  1942. END SUB%@NL@%
  1943. %@NL@%
  1944. %@AB@%'**************************************************************************%@AE@%%@NL@%
  1945. %@AB@%'*  The UserChoice SUB is used to echo back to the user the most recent   *%@AE@%%@NL@%
  1946. %@AB@%'*  menu selection he has made. Not all menu choices are echoed back.     *%@AE@%%@NL@%
  1947. %@AB@%'*                                Parameters                              *%@AE@%%@NL@%
  1948. %@AB@%'*  BigRec    RecStruct type variable containing table information        *%@AE@%%@NL@%
  1949. %@AB@%'*  Row       Row on which to put the Feedback$                           *%@AE@%%@NL@%
  1950. %@AB@%'*  Column    Column at which to start the Feedback$                      *%@AE@%%@NL@%
  1951. %@AB@%'*  Feedback$ Menu-choice string to highlight                             *%@AE@%%@NL@%
  1952. %@AB@%'**************************************************************************%@AE@%%@NL@%
  1953. SUB UserChoice (BigRec AS RecStruct, Row, Column, Feedback$)%@NL@%
  1954.     CALL DrawHelpKeys(BigRec.TableNum)%@NL@%
  1955.     CALL ShowKeys(BigRec, BRIGHT + FOREGROUND, DimN, DimP)%@NL@%
  1956.     COLOR FOREGROUND + BRIGHT, BACKGROUND%@NL@%
  1957.     LOCATE Row, Column%@NL@%
  1958.     PRINT Feedback$%@NL@%
  1959.     COLOR FOREGROUND, BACKGROUND%@NL@%
  1960. END SUB%@NL@%
  1961. %@NL@%
  1962. %@NL@%
  1963. %@NL@%
  1964. %@2@%%@AH@%BOOKMOD2.BAS%@AE@%%@EH@%%@NL@%
  1965. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\BOOKMOD2.BAS%@AE@%%@NL@%
  1966. %@NL@%
  1967. %@AB@%'***********************************************************************%@AE@%%@NL@%
  1968. %@AB@%'*  This is module level code for BOOKMOD2.BAS. It contains procedures *%@AE@%%@NL@%
  1969. %@AB@%'*  that use ISAM statements as well as procedures that support them.  *%@AE@%%@NL@%
  1970. %@AB@%'*  It is the third module of the BOOKLOOK program.                    *%@AE@%%@NL@%
  1971. %@AB@%'***********************************************************************%@AE@%%@NL@%
  1972. DEFINT A-Z%@NL@%
  1973. %@AB@%'$INCLUDE: 'booklook.bi'%@AE@%%@NL@%
  1974. %@NL@%
  1975. EditMessage:%@NL@%
  1976. DATA "╔═══════════════════════════╗"%@NL@%
  1977. DATA "║ A log is being kept while ║"%@NL@%
  1978. DATA "║ you edit fields in this   ║"%@NL@%
  1979. DATA "║ record. Press U to undo   ║"%@NL@%
  1980. DATA "║ each preceding edit, or   ║"%@NL@%
  1981. DATA "║ CTRL+U to undo all of the ║"%@NL@%
  1982. DATA "║ pending edits as a group. ║"%@NL@%
  1983. DATA "║                           ║"%@NL@%
  1984. DATA "╚═════╡ To Undo Edits ╞═════╝"%@NL@%
  1985. %@NL@%
  1986. OperandBox:%@NL@%
  1987. DATA "╔═══════════════════════════╗"%@NL@%
  1988. DATA "║                           ║"%@NL@%
  1989. DATA "║ Greater Than              ║"%@NL@%
  1990. DATA "║ or                        ║"%@NL@%
  1991. DATA "║ Equal To     Value Entered║"%@NL@%
  1992. DATA "║ or                        ║"%@NL@%
  1993. DATA "║ Less Than                 ║"%@NL@%
  1994. DATA "║                           ║"%@NL@%
  1995. DATA "╚══╡ Relationship to Key ╞══╝"%@NL@%
  1996. %@NL@%
  1997. %@AB@%'************************************************************************%@AE@%%@NL@%
  1998. %@AB@%'*                                                                      *%@AE@%%@NL@%
  1999. %@AB@%'*  This SUB checks the real current index after a try to set an index. *%@AE@%%@NL@%
  2000. %@AB@%'*  If the index was successfully set, it's name is displayed, other-   *%@AE@%%@NL@%
  2001. %@AB@%'*  wise the current index is displayed. IndexBox is called to update   *%@AE@%%@NL@%
  2002. %@AB@%'*  Current Sorting Order box on the screen.                            *%@AE@%%@NL@%
  2003. %@AB@%'*                                                                      *%@AE@%%@NL@%
  2004. %@AB@%'************************************************************************%@AE@%%@NL@%
  2005. SUB AdjustIndex (TablesRec AS RecStruct)%@NL@%
  2006.   RealIndexName$ = GETINDEX$(TablesRec.TableNum)%@NL@%
  2007.   CALL Indexbox(TablesRec, CheckIndex%(TablesRec, 0))%@NL@%
  2008.   IF RealIndexName$ <> EMPTYSTRING THEN%@NL@%
  2009.     Alert$ = "Records are now ordered by the index called " + RealIndexName$%@NL@%
  2010.   ELSE%@NL@%
  2011.     Alert$ = "Records now ordered by the default (NULL) index"%@NL@%
  2012.   END IF%@NL@%
  2013.   CALL ShowMessage(Alert$, 0)%@NL@%
  2014. END SUB%@NL@%
  2015. %@NL@%
  2016. %@AB@%'***************************************************************************%@AE@%%@NL@%
  2017. %@AB@%'*  The ChangeRecord FUNCTION gets the new field value with MakeString. It *%@AE@%%@NL@%
  2018. %@AB@%'*  then assigns the value (converted if necessary) to its proper element  *%@AE@%%@NL@%
  2019. %@AB@%'*  in the recordvariable (TablesRec) used to update the table.            *%@AE@%%@NL@%
  2020. %@AB@%'*                                Parameters                               *%@AE@%%@NL@%
  2021. %@AB@%'*  FirstLetter   If the user has started typing, this contains a letter   *%@AE@%%@NL@%
  2022. %@AB@%'*  Argument      Tells what field the cursor is currently in              *%@AE@%%@NL@%
  2023. %@AB@%'*  TablesRec     RecStruct type variable holding all table information    *%@AE@%%@NL@%
  2024. %@AB@%'*  Task          Tells which operation is being performed                 *%@AE@%%@NL@%
  2025. %@AB@%'***************************************************************************%@AE@%%@NL@%
  2026. FUNCTION ChangeRecord (FirstLetter$, Argument, TablesRec AS RecStruct, Task AS INTEGER)%@NL@%
  2027.   STATIC SaveTitle AS STRING%@NL@%
  2028.   Prompt$ = "New Field Value: "%@NL@%
  2029. %@NL@%
  2030.   IF Task <> SEEKFIELD THEN            ' Adjust the Argument --- It is in-%@NL@%
  2031.     IF Argument = TITLEFIELD THEN      ' cremented as part of PlaceCursor.%@NL@%
  2032.       Argument = IDFIELD               ' But it needs the user's original%@NL@%
  2033.     ELSE                               ' choice in this function.%@NL@%
  2034.        Argument = Argument - 2%@NL@%
  2035.     END IF%@NL@%
  2036.   END IF%@NL@%
  2037. %@NL@%
  2038.   Filter% = ASC(FirstLetter$)                ' Convert FirstLetter$ to ascii%@NL@%
  2039.   Remainder$ = MakeString$(Filter%, Prompt$) ' number to pass to MakeString.%@NL@%
  2040.   IF Filter% = ESCAPE THEN                   ' This lets the user press ESC%@NL@%
  2041.     ChangeRecord = 0                         ' to abandon function.%@NL@%
  2042.     CALL ShowRecord(TablesRec)%@NL@%
  2043.     EXIT FUNCTION%@NL@%
  2044.   END IF%@NL@%
  2045. %@AB@%                                           ' Select for proper assignment of%@AE@%%@NL@%
  2046.   SELECT CASE Argument                     ' string user makes with MakeString%@NL@%
  2047.     CASE TITLEFIELD, NAMEFIELD%@NL@%
  2048.       IF Task = EDITRECORD OR Task = ADDRECORD OR Task = SEEKFIELD THEN%@NL@%
  2049.         IF TablesRec.TableNum = cBookStockTableNum THEN%@NL@%
  2050.           TablesRec.Inventory.Title = Remainder$%@NL@%
  2051.         ELSE%@NL@%
  2052.           TablesRec.Lendee.TheName = Remainder$%@NL@%
  2053.         END IF%@NL@%
  2054.       END IF%@NL@%
  2055.       COLOR FOREGROUND, BACKGROUND%@NL@%
  2056.     CASE AUTHORFIELD, STREETFIELD%@NL@%
  2057.       IF Task = EDITRECORD OR Task = ADDRECORD THEN%@NL@%
  2058.         IF TablesRec.TableNum = cBookStockTableNum THEN%@NL@%
  2059.           TablesRec.Inventory.Author = Remainder$%@NL@%
  2060.         ELSE%@NL@%
  2061.           TablesRec.Lendee.Street = Remainder$%@NL@%
  2062.         END IF%@NL@%
  2063.       END IF%@NL@%
  2064.       COLOR FOREGROUND, BACKGROUND%@NL@%
  2065.     CASE PUBFIELD, CITYFIELD%@NL@%
  2066.       IF Task = EDITRECORD OR Task = ADDRECORD THEN%@NL@%
  2067.         IF TablesRec.TableNum = cBookStockTableNum THEN%@NL@%
  2068.           TablesRec.Inventory.Publisher = Remainder$%@NL@%
  2069.         ELSE%@NL@%
  2070.           TablesRec.Lendee.City = Remainder$%@NL@%
  2071.         END IF%@NL@%
  2072.       END IF%@NL@%
  2073.       COLOR FOREGROUND, BACKGROUND%@NL@%
  2074.     CASE EDFIELD, STATEFIELD%@NL@%
  2075.       IF Task = EDITRECORD OR Task = ADDRECORD THEN%@NL@%
  2076.         IF TablesRec.TableNum = cBookStockTableNum THEN%@NL@%
  2077.           TablesRec.Inventory.Edition = VAL(Remainder$)%@NL@%
  2078.         ELSE%@NL@%
  2079.           TablesRec.Lendee.State = Remainder$%@NL@%
  2080.         END IF%@NL@%
  2081.       END IF%@NL@%
  2082.       COLOR FOREGROUND, BACKGROUND%@NL@%
  2083.     CASE PRICEFIELD, ZIPFIELD%@NL@%
  2084.       IF Task = EDITRECORD OR Task = ADDRECORD THEN%@NL@%
  2085.         IF TablesRec.TableNum = cBookStockTableNum THEN%@NL@%
  2086.           TablesRec.Inventory.Price = VAL(Remainder$)%@NL@%
  2087.         ELSE%@NL@%
  2088.           TablesRec.Lendee.Zip = VAL(Remainder$)%@NL@%
  2089.         END IF%@NL@%
  2090.       END IF%@NL@%
  2091.       COLOR FOREGROUND, BACKGROUND%@NL@%
  2092.     CASE IDFIELD, CARDNUMFIELD%@NL@%
  2093.       IF Task = EDITRECORD OR Task = ADDRECORD THEN%@NL@%
  2094.         IF TablesRec.TableNum = cBookStockTableNum THEN%@NL@%
  2095.           size = LEN(Remainder$)%@NL@%
  2096.           FOR counter = 1 TO size%@NL@%
  2097.             IF ASC(MID$(Remainder$, counter, 1)) = 0 THEN%@NL@%
  2098.               Remainder$ = MID$(Remainder$, (counter + 1), size)%@NL@%
  2099.             END IF%@NL@%
  2100.           NEXT counter%@NL@%
  2101.           TablesRec.Inventory.IDnum = VAL(LTRIM$(RTRIM$(Remainder$)))%@NL@%
  2102.         ELSE%@NL@%
  2103.           TablesRec.Lendee.CardNum = VAL(Remainder$)%@NL@%
  2104.         END IF%@NL@%
  2105.       END IF%@NL@%
  2106.       COLOR FOREGROUND, BACKGROUND%@NL@%
  2107.     CASE ELSE%@NL@%
  2108.         CALL ShowMessage("  Can't change that field ", 0)%@NL@%
  2109.         BEEP%@NL@%
  2110.         SLEEP 1%@NL@%
  2111. END SELECT%@NL@%
  2112.  ChangeRecord = 1%@NL@%
  2113. END FUNCTION%@NL@%
  2114. %@NL@%
  2115. %@AB@%'***************************************************************************%@AE@%%@NL@%
  2116. %@AB@%'*  The CheckIndex uses the GETINDEX function to find the current index.   *%@AE@%%@NL@%
  2117. %@AB@%'*  Since only some displayed fields correspond to indexes, the number     *%@AE@%%@NL@%
  2118. %@AB@%'*  returned is a code indicating what to do, not the index name           *%@AE@%%@NL@%
  2119. %@AB@%'*                                Parameters                               *%@AE@%%@NL@%
  2120. %@AB@%'*  TablesRec   RecStuct type variable holding all table information       *%@AE@%%@NL@%
  2121. %@AB@%'*  FirstTime   If first time is TRUE, Index is NULL index                 *%@AE@%%@NL@%
  2122. %@AB@%'***************************************************************************%@AE@%%@NL@%
  2123. FUNCTION CheckIndex% (TablesRec AS RecStruct, FirstTime)%@NL@%
  2124.   Check$ = GETINDEX$(TablesRec.TableNum)%@NL@%
  2125.   SELECT CASE Check$%@NL@%
  2126.     CASE "TitleIndexBS", "NameIndexCH"%@NL@%
  2127.       CheckIndex% = 0%@NL@%
  2128.     CASE "AuthorIndexBS"%@NL@%
  2129.       CheckIndex% = 1%@NL@%
  2130.     CASE "PubIndexBS"%@NL@%
  2131.       CheckIndex% = 2%@NL@%
  2132.     CASE "StateIndexCH"%@NL@%
  2133.       CheckIndex% = 3%@NL@%
  2134.     CASE "ZipIndexCH"%@NL@%
  2135.       CheckIndex% = 4%@NL@%
  2136.     CASE "IDIndex", "CardNumIndexCH"%@NL@%
  2137.       CheckIndex% = 5%@NL@%
  2138.     CASE "BigIndex"                 ' There's no combined index on%@NL@%
  2139.       CheckIndex% = 6               ' CardHolders table%@NL@%
  2140.     CASE ""%@NL@%
  2141.       CheckIndex% = 7               ' This is a special case for the%@NL@%
  2142. %@AB@%                                    ' Blank line in CardHolders table%@AE@%%@NL@%
  2143.     IF FirstTime% THEN%@NL@%
  2144.       CALL Indexbox(TablesRec, 7)%@NL@%
  2145.     END IF%@NL@%
  2146.   END SELECT%@NL@%
  2147. END FUNCTION%@NL@%
  2148. %@NL@%
  2149. %@AB@%'***************************************************************************%@AE@%%@NL@%
  2150. %@AB@%'*  The EdAddCursor function is used to place the cursor in the proper     *%@AE@%%@NL@%
  2151. %@AB@%'*  when the task is to Edit or Add a record.  Note when printing numeric  *%@AE@%%@NL@%
  2152. %@AB@%'*  fields LOCATE 1 column left to compensate  for the implicit "+" sign.  *%@AE@%%@NL@%
  2153. %@AB@%'*                                Parameters                               *%@AE@%%@NL@%
  2154. %@AB@%'*  NextField   Tells which field is to be highlighted next                *%@AE@%%@NL@%
  2155. %@AB@%'*  Job         Tells operation user wants to engage in                    *%@AE@%%@NL@%
  2156. %@AB@%'*  TablesRec   RecStruct type variable holding all table information      *%@AE@%%@NL@%
  2157. %@AB@%'*  FirstShot   Nonzero value indicates this is first time through         *%@AE@%%@NL@%
  2158. %@AB@%'***************************************************************************%@AE@%%@NL@%
  2159. FUNCTION EdAddCursor (NextField%, Job%, TablesRec AS RecStruct, FirstShot%)%@NL@%
  2160.   SELECT CASE TablesRec.TableNum%@NL@%
  2161.     CASE cBookStockTableNum                       ' BookStock table is 1%@NL@%
  2162.       SELECT CASE NextField%@NL@%
  2163.         CASE TITLEFIELD, NAMEFIELD%@NL@%
  2164.           LOCATE IDFIELD, 17%@NL@%
  2165.           IF FirstShot THEN COLOR FOREGROUND, BACKGROUND%@NL@%
  2166.           PRINT TablesRec.Inventory.IDnum%@NL@%
  2167.           COLOR BACKGROUND, BRIGHT + FOREGROUND%@NL@%
  2168.           LOCATE TITLEFIELD, 18%@NL@%
  2169.           PRINT TablesRec.Inventory.Title%@NL@%
  2170.           NextField% = AUTHORFIELD%@NL@%
  2171.         CASE AUTHORFIELD, STREETFIELD%@NL@%
  2172.           LOCATE TITLEFIELD, 18%@NL@%
  2173.           PRINT TablesRec.Inventory.Title%@NL@%
  2174.           COLOR BACKGROUND, BRIGHT + FOREGROUND%@NL@%
  2175.           LOCATE AUTHORFIELD, 18%@NL@%
  2176.           PRINT TablesRec.Inventory.Author%@NL@%
  2177.           NextField% = PUBFIELD%@NL@%
  2178.         CASE PUBFIELD, CITYFIELD%@NL@%
  2179.           LOCATE AUTHORFIELD, 18%@NL@%
  2180.           PRINT TablesRec.Inventory.Author%@NL@%
  2181.           COLOR BACKGROUND, BRIGHT + FOREGROUND%@NL@%
  2182.           LOCATE PUBFIELD, 18%@NL@%
  2183.             PRINT TablesRec.Inventory.Publisher%@NL@%
  2184.             NextField% = EDFIELD%@NL@%
  2185.         CASE EDFIELD, STATEFIELD%@NL@%
  2186.           LOCATE PUBFIELD, 18%@NL@%
  2187.           PRINT TablesRec.Inventory.Publisher%@NL@%
  2188.           COLOR BACKGROUND, BRIGHT + FOREGROUND%@NL@%
  2189.           LOCATE EDFIELD, 17%@NL@%
  2190.           PRINT TablesRec.Inventory.Edition%@NL@%
  2191.           NextField% = PRICEFIELD%@NL@%
  2192.         CASE PRICEFIELD, ZIPFIELD%@NL@%
  2193.           LOCATE EDFIELD, 17%@NL@%
  2194.           PRINT TablesRec.Inventory.Edition%@NL@%
  2195.           COLOR BACKGROUND, BRIGHT + FOREGROUND%@NL@%
  2196.           LOCATE PRICEFIELD, 19%@NL@%
  2197.           PRINT ; TablesRec.Inventory.Price%@NL@%
  2198.           NextField% = IDFIELD%@NL@%
  2199.         CASE IDFIELD, CARDNUMFIELD%@NL@%
  2200.           LOCATE PRICEFIELD, 18%@NL@%
  2201.           PRINT "$"; TablesRec.Inventory.Price%@NL@%
  2202.           COLOR BACKGROUND, BRIGHT + FOREGROUND%@NL@%
  2203.           LOCATE IDFIELD, 17%@NL@%
  2204.           PRINT TablesRec.Inventory.IDnum%@NL@%
  2205.           NextField% = TITLEFIELD%@NL@%
  2206.       END SELECT%@NL@%
  2207.     CASE cCardHoldersTableNum                       ' CardHolders table is 2%@NL@%
  2208.       SELECT CASE NextField%@NL@%
  2209.         CASE NAMEFIELD%@NL@%
  2210.           LOCATE CARDNUMFIELD, 17%@NL@%
  2211.           IF FirstShot THEN COLOR FOREGROUND, BACKGROUND%@NL@%
  2212.           PRINT TablesRec.Lendee.CardNum%@NL@%
  2213.           COLOR BACKGROUND, BRIGHT + FOREGROUND%@NL@%
  2214.           LOCATE NAMEFIELD, 18%@NL@%
  2215.           PRINT TablesRec.Lendee.TheName%@NL@%
  2216.           NextField% = STREETFIELD%@NL@%
  2217.         CASE STREETFIELD%@NL@%
  2218.           LOCATE NAMEFIELD, 18%@NL@%
  2219.           PRINT TablesRec.Lendee.TheName%@NL@%
  2220.           COLOR BACKGROUND, BRIGHT + FOREGROUND%@NL@%
  2221.           LOCATE STREETFIELD, 18%@NL@%
  2222.           PRINT TablesRec.Lendee.Street%@NL@%
  2223.           NextField% = CITYFIELD%@NL@%
  2224.         CASE CITYFIELD%@NL@%
  2225.           LOCATE STREETFIELD, 18%@NL@%
  2226.           PRINT TablesRec.Lendee.Street%@NL@%
  2227.           COLOR BACKGROUND, BRIGHT + FOREGROUND%@NL@%
  2228.           LOCATE CITYFIELD, 18%@NL@%
  2229.           PRINT TablesRec.Lendee.City%@NL@%
  2230.           NextField% = STATEFIELD%@NL@%
  2231.         CASE STATEFIELD%@NL@%
  2232.           LOCATE CITYFIELD, 18%@NL@%
  2233.           PRINT TablesRec.Lendee.City%@NL@%
  2234.           COLOR BACKGROUND, BRIGHT + FOREGROUND%@NL@%
  2235.           LOCATE STATEFIELD, 18%@NL@%
  2236.           PRINT TablesRec.Lendee.State%@NL@%
  2237.           NextField% = PRICEFIELD%@NL@%
  2238.         CASE ZIPFIELD%@NL@%
  2239.           LOCATE STATEFIELD, 18%@NL@%
  2240.           PRINT TablesRec.Lendee.State%@NL@%
  2241.           COLOR BACKGROUND, BRIGHT + FOREGROUND%@NL@%
  2242.           LOCATE ZIPFIELD, 17%@NL@%
  2243.           PRINT TablesRec.Lendee.Zip%@NL@%
  2244.           NextField% = IDFIELD%@NL@%
  2245.         CASE CARDNUMFIELD%@NL@%
  2246.           LOCATE ZIPFIELD, 17%@NL@%
  2247.           PRINT TablesRec.Lendee.Zip%@NL@%
  2248.           COLOR BACKGROUND, BRIGHT + FOREGROUND%@NL@%
  2249.           LOCATE CARDNUMFIELD, 17%@NL@%
  2250.           PRINT TablesRec.Lendee.CardNum%@NL@%
  2251.           NextField% = TITLEFIELD%@NL@%
  2252.       END SELECT%@NL@%
  2253.   END SELECT%@NL@%
  2254.   COLOR FOREGROUND, BACKGROUND%@NL@%
  2255. END FUNCTION%@NL@%
  2256. %@NL@%
  2257. %@AB@%'***************************************************************************%@AE@%%@NL@%
  2258. %@AB@%'*  The EditField function lets the user choose whether or not to actually *%@AE@%%@NL@%
  2259. %@AB@%'*  change the current field (by calling ChangeRecord) or move on to the   *%@AE@%%@NL@%
  2260. %@AB@%'*  next field. It also displays a message telling how to Undo edits. If   *%@AE@%%@NL@%
  2261. %@AB@%'*  EditField returns TRUE, a SAVEPOINT is set at module level. If the task*%@AE@%%@NL@%
  2262. %@AB@%'*  is ADDRECORD, the user is taken through the fields one at a time until *%@AE@%%@NL@%
  2263. %@AB@%'*  they have all been entered.                                            *%@AE@%%@NL@%
  2264. %@AB@%'*                              Parameters                                 *%@AE@%%@NL@%
  2265. %@AB@%'*  Argument    Tells which field is currently being dealt with            *%@AE@%%@NL@%
  2266. %@AB@%'*  TablesRec   RecStruct type variable holding current table information  *%@AE@%%@NL@%
  2267. %@AB@%'*  FirstLetter If the user has started typing, the letter is passed in    *%@AE@%%@NL@%
  2268. %@AB@%'*  Task        Tells what type of operation the user is performing        *%@AE@%%@NL@%
  2269. %@AB@%'*  Answer      Same as Task, but passed to ChangeRecord%@AE@%%@NL@%
  2270. %@AB@%'***************************************************************************%@AE@%%@NL@%
  2271. FUNCTION EditField (Argument%, TablesRec AS RecStruct, FirstLetter$, Task%, Answer%)%@NL@%
  2272. %@AB@%  ' Show the transaction block message dealing with undoing edits:%@AE@%%@NL@%
  2273.   IF Task = EDITRECORD THEN CALL DrawIndexBox(1, Task)%@NL@%
  2274. %@NL@%
  2275.   STATIC NextField%@NL@%
  2276.   FirstLetter$ = ""%@NL@%
  2277.   IF Task = EDITRECORD THEN CALL ShowMessage("Edit this field or TAB to another", 0)%@NL@%
  2278.   Argument = TITLEFIELD%@NL@%
  2279.   Value = PlaceCursor(Argument, TablesRec, FirstLetter$, 1, Task%)%@NL@%
  2280.   IF Argument THEN%@NL@%
  2281.     IF Task = EDITRECORD THEN CALL ShowMessage("Edit this field or TAB to another", 0)%@NL@%
  2282.     COLOR FOREGROUND, BACKGROUND%@NL@%
  2283.     WasFieldChanged = ChangeRecord(FirstLetter$, Argument, TablesRec, Answer)%@NL@%
  2284. %@NL@%
  2285.     IF Task = EDITRECORD AND WasFieldChanged <> 0 THEN%@NL@%
  2286.       CALL ShowMessage("Press E to Edit another field ", 0)%@NL@%
  2287.       EditField = TRUE            ' If True is returned, a SAVEPOINT is set%@NL@%
  2288.     ELSEIF Task = EDITRECORD AND WasFieldChanged = 0 THEN%@NL@%
  2289.       CALL ShowRecord(TablesRec)%@NL@%
  2290.       CALL ShowMessage("Please try again...", 0)%@NL@%
  2291.       EditField = FALSE     'Don't set SAVEPOINT if user escapes from edit%@NL@%
  2292.     ELSEIF Task = SEEKFIELD THEN%@NL@%
  2293.       EditField = FALSE: EXIT FUNCTION%@NL@%
  2294.     END IF%@NL@%
  2295.     IF Task = ADDRECORD THEN%@NL@%
  2296.       NextField = 1%@NL@%
  2297.       DO WHILE NextField <> 0 AND Argument <> 0%@NL@%
  2298.         CALL ShowMessage("Enter value for field or ESC to abandon addition ", 0)%@NL@%
  2299.         SELECT CASE NextField%@NL@%
  2300.           CASE 1%@NL@%
  2301.             Argument = AUTHORFIELD%@NL@%
  2302.             FieldsDone = FieldsDone + 1%@NL@%
  2303.           CASE 2%@NL@%
  2304.             Argument = PUBFIELD%@NL@%
  2305.             FieldsDone = FieldsDone + 1%@NL@%
  2306.           CASE 3%@NL@%
  2307.             Argument = EDFIELD%@NL@%
  2308.             FieldsDone = FieldsDone + 1%@NL@%
  2309.           CASE 4%@NL@%
  2310.             Argument = PRICEFIELD%@NL@%
  2311.             FieldsDone = FieldsDone + 1%@NL@%
  2312.           CASE 5%@NL@%
  2313.             Argument = IDFIELD%@NL@%
  2314.             FieldsDone = FieldsDone + 1%@NL@%
  2315.             NextField = 0%@NL@%
  2316.           CASE ELSE%@NL@%
  2317.             CALL ShowMessage("Problem in the CASE assignments to Argument", 0): SLEEP%@NL@%
  2318.         END SELECT%@NL@%
  2319.         FirstLetter$ = ""%@NL@%
  2320.         Value = PlaceCursor(Argument, TablesRec, FirstLetter$, 1, Task%)%@NL@%
  2321.         IF Argument THEN%@NL@%
  2322.           COLOR FOREGROUND, BACKGROUND%@NL@%
  2323.           WasFieldChanged = ChangeRecord(FirstLetter$, Argument, TablesRec, Answer)%@NL@%
  2324.           NextField = NextField + 1%@NL@%
  2325.           IF FieldsDone = 5 THEN EditField% = 1: EXIT FUNCTION%@NL@%
  2326.         END IF%@NL@%
  2327.       LOOP%@NL@%
  2328.       EditField = FALSE 'No need for SAVEPOINT with ADDRECORD%@NL@%
  2329.     END IF%@NL@%
  2330.   ELSE%@NL@%
  2331.   CALL ShowRecord(TablesRec)%@NL@%
  2332.   CALL ShowMessage("Please try again...", 0)%@NL@%
  2333.   SLEEP: CALL EraseMessage%@NL@%
  2334.   CALL DrawIndexBox(TablesRec.TableNum, 0)' Replace Edit stuff with Index stuff%@NL@%
  2335.   EditField = FALSE     'Don't set SAVEPOINT if user escapes from edit%@NL@%
  2336.   END IF%@NL@%
  2337. %@NL@%
  2338. END FUNCTION%@NL@%
  2339. %@NL@%
  2340. %@AB@%'***************************************************************************%@AE@%%@NL@%
  2341. %@AB@%'*  The GetKeyVals SUB gathers the Keys for searching on a combined index. *%@AE@%%@NL@%
  2342. %@AB@%'*  It shows the fields as they are entered.                               *%@AE@%%@NL@%
  2343. %@AB@%'*                                Parameters                               *%@AE@%%@NL@%
  2344. %@AB@%'*  TablesRec   Contains all the information for the tables                *%@AE@%%@NL@%
  2345. %@AB@%'*  Key1        Represents the Title field of BookStock table              *%@AE@%%@NL@%
  2346. %@AB@%'*  Key2        Represents the Author field of BookStock table             *%@AE@%%@NL@%
  2347. %@AB@%'*  Key3        Represents the IDnum field of BookStock table              *%@AE@%%@NL@%
  2348. %@AB@%'*  Letter      Holds the first letter the user tries to enter at prompt   *%@AE@%%@NL@%
  2349. %@AB@%'***************************************************************************%@AE@%%@NL@%
  2350. SUB GetKeyVals (TablesRec AS RecStruct, Key1$, Key2$, Key3#, Letter$)%@NL@%
  2351.   WhichTable = TablesRec.TableNum%@NL@%
  2352.   Prompt$ = "Value to Seek: "%@NL@%
  2353. %@NL@%
  2354.   CALL DrawScreen(WhichTable)%@NL@%
  2355.   DO%@NL@%
  2356. %@AB@%    ' Have the user ENTER the Title value to search for%@AE@%%@NL@%
  2357.     COLOR BACKGROUND, FOREGROUND%@NL@%
  2358.     LOCATE TITLEFIELD, 18%@NL@%
  2359.     PRINT "Please enter the Title to find"%@NL@%
  2360.     Key1$ = MakeString$(ASC(Letter$), Prompt$)%@NL@%
  2361.     CALL ShowIt(TablesRec, "TitleIndexBS", WhichTable, Key1$)%@NL@%
  2362.   LOOP UNTIL Key1$ <> ""%@NL@%
  2363. %@NL@%
  2364.   Letter$ = " "    ' Set it to a blank space for typing%@NL@%
  2365. %@NL@%
  2366. %@AB@%    ' Have the user ENTER the Author value to search for%@AE@%%@NL@%
  2367.   DO%@NL@%
  2368.     COLOR BACKGROUND, FOREGROUND%@NL@%
  2369.     LOCATE AUTHORFIELD, 18%@NL@%
  2370.     PRINT "Please enter the Author name to find"%@NL@%
  2371.     Key2$ = MakeString$(ASC(Letter$), Prompt$)%@NL@%
  2372. %@AB@%    ' Show it just shows the input user has entered, not a record from file%@AE@%%@NL@%
  2373.     CALL ShowIt(TablesRec, "AuthorIndexBS", WhichTable, Key2$)%@NL@%
  2374.   LOOP UNTIL Key2$ <> ""%@NL@%
  2375. %@NL@%
  2376.   Letter$ = " "    ' Set it to a blank space for typing%@NL@%
  2377. %@AB@%    ' Have the user ENTER the ID number value to search for%@AE@%%@NL@%
  2378.   DO%@NL@%
  2379.     COLOR BACKGROUND, FOREGROUND%@NL@%
  2380.     LOCATE IDFIELD, 18%@NL@%
  2381.     PRINT "Please enter the ID number to find"%@NL@%
  2382.     ValueToSeek$ = MakeString$(ASC(Letter$), Prompt$)%@NL@%
  2383.     Key3# = CDBL(VAL(ValueToSeek$))       ' CURRENCY field%@NL@%
  2384.     CALL ShowIt(TablesRec, "IDIndex", WhichTable, ValueToSeek$)%@NL@%
  2385. LOOP UNTIL Key3# <> 0%@NL@%
  2386. END SUB%@NL@%
  2387. %@NL@%
  2388. %@AB@%'****************************** GetOperand FUNCTION ************************%@AE@%%@NL@%
  2389. %@AB@%'* The GetOperand FUNCTION displays a choice of operators to allow user a  *%@AE@%%@NL@%
  2390. %@AB@%'* choice in how a SEEKoperand search will be conducted. If the user makes *%@AE@%%@NL@%
  2391. %@AB@%'* a valid choice, it is assigned to HoldOperand. An invalid choice or a   *%@AE@%%@NL@%
  2392. %@AB@%'* choice of ESC results in "<>" being passed back. This permits an exit   *%@AE@%%@NL@%
  2393. %@AB@%'* from the function (which is recursive). Otherwise, the user's choice is *%@AE@%%@NL@%
  2394. %@AB@%'* trapped in HoldOperand when ENTER is pressed.                           *%@AE@%%@NL@%
  2395. %@AB@%'* Note that this function is recursive so use the calls menu to keep      *%@AE@%%@NL@%
  2396. %@AB@%'* track of the nesting depth when stepping through it. Unlike PlaceCursor *%@AE@%%@NL@%
  2397. %@AB@%'* GetOperand doesn't keep track of the stack - the stack set should be OK.*%@AE@%%@NL@%
  2398. %@AB@%'*                              Parameters                                 *%@AE@%%@NL@%
  2399. %@AB@%'*   HoldOperand    Contains operand to check each time function calls     *%@AE@%%@NL@%
  2400. %@AB@%'*                  itself; Let's user ESC from function if desired.       *%@AE@%%@NL@%
  2401. %@AB@%'***************************************************************************%@AE@%%@NL@%
  2402. FUNCTION GetOperand% (HoldOperand$)%@NL@%
  2403.   STATIC WhichOne     ' Keep track of which case from call to call%@NL@%
  2404. %@NL@%
  2405. %@AB@%  ' If user has chose ESC then exit back to caller%@AE@%%@NL@%
  2406.   IF HoldOperand$ = "<>" THEN WhichOne = 0: EXIT FUNCTION%@NL@%
  2407. %@NL@%
  2408. %@AB@%  ' if this is the first time through the function then%@AE@%%@NL@%
  2409. %@AB@%  ' Replace the Sort Order box with box of operand choices%@AE@%%@NL@%
  2410.   IF WhichOne = 0 THEN%@NL@%
  2411.     RESTORE OperandBox%@NL@%
  2412.     FOR Row = BOXTOP TO BOXEND%@NL@%
  2413.       LOCATE Row, 42%@NL@%
  2414.       READ Temp$%@NL@%
  2415.       PRINT Temp$%@NL@%
  2416.       IF Row = BOXEND THEN%@NL@%
  2417.         COLOR FOREGROUND + BRIGHT, BACKGROUND%@NL@%
  2418.         LOCATE Row, INDBOX + 5%@NL@%
  2419.         PRINT "Relationship to Key"%@NL@%
  2420.       END IF%@NL@%
  2421.     NEXT Row%@NL@%
  2422.     LOCATE VLINE, 44%@NL@%
  2423.     PRINT "Equal To     Value Entered"     ' This is default --- if user%@NL@%
  2424.     COLOR FOREGROUND, BACKGROUND           ' presses ENTER without tabbing,%@NL@%
  2425.   END IF                                   ' SeekRecord sets the operand%@NL@%
  2426. %@AB@%                                           ' to =    Note: a more flexible%@AE@%%@NL@%
  2427. %@AB@%                                           ' default choice might be >=%@AE@%%@NL@%
  2428. %@NL@%
  2429.   Alert$ = "Now press TAB to select how search should be conducted"%@NL@%
  2430.   CALL ShowMessage(Alert$, 0)%@NL@%
  2431.   DO%@NL@%
  2432.   Answer$ = INKEY$%@NL@%
  2433.   LOOP WHILE Answer$ <> CHR$(TABKEY) AND Answer$ <> CHR$(ENTER) AND Answer$ <> CHR$(ESCAPE)%@NL@%
  2434. %@NL@%
  2435.   IF LEN(Answer$) = 1 THEN%@NL@%
  2436.     SELECT CASE ASC(Answer$)%@NL@%
  2437.       CASE TABKEY%@NL@%
  2438.         SELECT CASE WhichOne%@NL@%
  2439.           CASE 0%@NL@%
  2440.             COLOR FOREGROUND, BACKGROUND%@NL@%
  2441.             LOCATE VLINE, 44%@NL@%
  2442.             PRINT "Equal To"%@NL@%
  2443.             COLOR BRIGHT + FOREGROUND, BACKGROUND%@NL@%
  2444.             LOCATE RLINE, 44%@NL@%
  2445.             PRINT "Greater Than"%@NL@%
  2446.             WhichOne = WhichOne + 1%@NL@%
  2447.             HoldOperand$ = ">"%@NL@%
  2448.           CASE 1%@NL@%
  2449.             COLOR BRIGHT + FOREGROUND, BACKGROUND%@NL@%
  2450.             LOCATE VLINE, 44%@NL@%
  2451.             PRINT "Equal To"%@NL@%
  2452.             LOCATE WLINE, 44%@NL@%
  2453.             PRINT "or"%@NL@%
  2454.             WhichOne = WhichOne + 1%@NL@%
  2455.             HoldOperand$ = ">="%@NL@%
  2456.           CASE 2%@NL@%
  2457.             COLOR FOREGROUND, BACKGROUND%@NL@%
  2458.             LOCATE RLINE, 44%@NL@%
  2459.             PRINT "Greater Than"%@NL@%
  2460.             LOCATE WLINE, 44%@NL@%
  2461.             PRINT "or"%@NL@%
  2462.             COLOR BRIGHT + FOREGROUND, BACKGROUND%@NL@%
  2463.             LOCATE ALINE, 44%@NL@%
  2464.             PRINT "or"%@NL@%
  2465.             LOCATE ELINE, 44%@NL@%
  2466.             PRINT "Less Than"%@NL@%
  2467.             WhichOne = WhichOne + 1%@NL@%
  2468.             HoldOperand$ = "<="%@NL@%
  2469.           CASE 3%@NL@%
  2470.             COLOR FOREGROUND, BACKGROUND%@NL@%
  2471.             LOCATE VLINE, 44%@NL@%
  2472.             PRINT "Equal To"%@NL@%
  2473.             LOCATE ALINE, 44%@NL@%
  2474.             PRINT "or"%@NL@%
  2475.             WhichOne = WhichOne + 1%@NL@%
  2476.             HoldOperand$ = "<"%@NL@%
  2477.             SLEEP%@NL@%
  2478.           CASE 4%@NL@%
  2479.             COLOR FOREGROUND, BACKGROUND%@NL@%
  2480.             LOCATE ELINE, 44%@NL@%
  2481.             PRINT "Less Than"%@NL@%
  2482.             COLOR BRIGHT + FOREGROUND, BACKGROUND%@NL@%
  2483.             LOCATE VLINE, 44%@NL@%
  2484.             PRINT "Equal To     Value Entered"%@NL@%
  2485.             WhichOne = WhichOne + 1%@NL@%
  2486.             HoldOperand$ = "="%@NL@%
  2487.           CASE ELSE%@NL@%
  2488.         END SELECT                          ' If no choice was made, call%@NL@%
  2489.         IF WhichOne > 4 THEN WhichOne = 0   ' GetOperand again%@NL@%
  2490.         COLOR FOREGROUND, BACKGROUND%@NL@%
  2491.         OK = GetOperand%(HoldOperand$)%@NL@%
  2492.       CASE ENTER%@NL@%
  2493.         WhichOne = 0%@NL@%
  2494.         EXIT FUNCTION%@NL@%
  2495.     CASE ESCAPE                 ' If user chooses ESC, signal the function%@NL@%
  2496.       HoldOperand$ = "<>"       ' to exit and keep exiting back through%@NL@%
  2497.       GetOperand% = 0           ' all levels of recursion%@NL@%
  2498.       WhichOne = 0%@NL@%
  2499.     CASE ELSE                   ' If user chooses invalid key, try again%@NL@%
  2500.       BEEP%@NL@%
  2501.       CALL ShowMessage("Use TAB to select relationship to search for...", 0)%@NL@%
  2502.       COLOR white, BACKGROUND%@NL@%
  2503.       OK = GetOperand%(HoldOperand$)%@NL@%
  2504.   END SELECT%@NL@%
  2505. ELSE%@NL@%
  2506. END IF%@NL@%
  2507. %@NL@%
  2508. END FUNCTION%@NL@%
  2509. %@NL@%
  2510. %@AB@%'***************************************************************************%@AE@%%@NL@%
  2511. %@AB@%'*  The IndexBox SUB highlights the proper index name in the Current Index *%@AE@%%@NL@%
  2512. %@AB@%'*  box at the bottom right section of the screen.                         *%@AE@%%@NL@%
  2513. %@AB@%'                                                                          *%@AE@%%@NL@%
  2514. %@AB@%'*  TablesRec   RecStruct type variable containing all table information   *%@AE@%%@NL@%
  2515. %@AB@%'*  MoveDown    Integer representing line on which index name resides      *%@AE@%%@NL@%
  2516. %@AB@%'***************************************************************************%@AE@%%@NL@%
  2517. SUB Indexbox (TablesRec AS RecStruct, MoveDown)%@NL@%
  2518.    Table = TablesRec.TableNum%@NL@%
  2519.    COLOR BRIGHT + FOREGROUND, BACKGROUND%@NL@%
  2520.    LOCATE 17 + MoveDown, 44%@NL@%
  2521.    SELECT CASE MoveDown%@NL@%
  2522.      CASE 0%@NL@%
  2523.       IF Table = cBookStockTableNum THEN PRINT "By Titles   " ELSE PRINT "By Name    "%@NL@%
  2524.       COLOR FOREGROUND, BACKGROUND%@NL@%
  2525.       LOCATE ELINE, 44%@NL@%
  2526.       PRINT "Default = Insertion Order"%@NL@%
  2527.      CASE 1%@NL@%
  2528.       IF Table = cBookStockTableNum THEN PRINT "By Authors   "%@NL@%
  2529.       COLOR FOREGROUND, BACKGROUND%@NL@%
  2530.       LOCATE NLINE, 44%@NL@%
  2531.       IF Table = cBookStockTableNum THEN PRINT "By Titles   " ELSE PRINT "By Name     "%@NL@%
  2532.      CASE 2%@NL@%
  2533.       IF Table = cBookStockTableNum THEN PRINT "By Publishers   "%@NL@%
  2534.       COLOR FOREGROUND, BACKGROUND%@NL@%
  2535.       LOCATE RLINE, 44%@NL@%
  2536.       IF Table = cBookStockTableNum THEN PRINT "By Authors    "%@NL@%
  2537.      CASE 3%@NL@%
  2538.       IF Table = cCardHoldersTableNum THEN%@NL@%
  2539.         LOCATE RLINE, 44%@NL@%
  2540.         PRINT "By States     "%@NL@%
  2541.         COLOR FOREGROUND, BACKGROUND%@NL@%
  2542.         LOCATE NLINE, 44%@NL@%
  2543.         PRINT "By Names     "%@NL@%
  2544.       ELSE%@NL@%
  2545.         COLOR FOREGROUND, BACKGROUND%@NL@%
  2546.         LOCATE WLINE, 44%@NL@%
  2547.         PRINT "By Publishers"%@NL@%
  2548.       END IF%@NL@%
  2549.      CASE 4%@NL@%
  2550.       IF Table = cCardHoldersTableNum THEN%@NL@%
  2551.         LOCATE WLINE, 44%@NL@%
  2552.         PRINT "By Zipcodes   "%@NL@%
  2553.         COLOR FOREGROUND, BACKGROUND%@NL@%
  2554.         LOCATE RLINE, 44%@NL@%
  2555.         PRINT "By States     "%@NL@%
  2556.       END IF%@NL@%
  2557.      CASE 5%@NL@%
  2558.       LOCATE VLINE, 44%@NL@%
  2559.       IF Table = cBookStockTableNum THEN%@NL@%
  2560.         PRINT "By ID Numbers   "%@NL@%
  2561.         COLOR FOREGROUND, BACKGROUND%@NL@%
  2562.       ELSE%@NL@%
  2563.         PRINT "By Card numbers   "%@NL@%
  2564.         COLOR FOREGROUND, BACKGROUND%@NL@%
  2565.         LOCATE WLINE, 44%@NL@%
  2566.         PRINT "By Zipcodes    "%@NL@%
  2567.       END IF%@NL@%
  2568.      CASE 6%@NL@%
  2569.       IF Table = cBookStockTableNum THEN%@NL@%
  2570.         LOCATE ALINE, 44%@NL@%
  2571.         PRINT "By Title + Author + ID"%@NL@%
  2572.         COLOR FOREGROUND, BACKGROUND%@NL@%
  2573.         LOCATE VLINE, 44%@NL@%
  2574.         PRINT "By ID Numbers"%@NL@%
  2575.       ELSE%@NL@%
  2576.         LOCATE VLINE, 44%@NL@%
  2577.         COLOR FOREGROUND, BACKGROUND%@NL@%
  2578.         PRINT "By Card numbers   "%@NL@%
  2579.       END IF%@NL@%
  2580.      COLOR FOREGROUND, BACKGROUND%@NL@%
  2581.      CASE 7%@NL@%
  2582.       LOCATE ELINE, 44%@NL@%
  2583.       PRINT "Default = Insertion Order"%@NL@%
  2584.       COLOR FOREGROUND, BACKGROUND%@NL@%
  2585.       IF Table = cBookStockTableNum THEN%@NL@%
  2586.         LOCATE ALINE, 44%@NL@%
  2587.         PRINT "By Title + Author + ID"%@NL@%
  2588.       ELSE%@NL@%
  2589.         LOCATE VLINE, 44%@NL@%
  2590.         PRINT "By Card numbers"%@NL@%
  2591.       END IF%@NL@%
  2592.     END SELECT%@NL@%
  2593.    IF MoveDown < 7 THEN%@NL@%
  2594.     MoveDown = MoveDown + 1%@NL@%
  2595.    ELSE%@NL@%
  2596.     MoveDown = 0%@NL@%
  2597.    END IF%@NL@%
  2598. COLOR FOREGROUND, BACKGROUND%@NL@%
  2599. END SUB%@NL@%
  2600. %@NL@%
  2601. %@AB@%'***************************************************************************%@AE@%%@NL@%
  2602. %@AB@%'* The OrderCursor FUNCTION returns TRUE or FALSE for user index choice.   *%@AE@%%@NL@%
  2603. %@AB@%'* Each time the user places the cursor on an Index to sort on, this       *%@AE@%%@NL@%
  2604. %@AB@%'* function displays an instruction message in the field(s) corresponding  *%@AE@%%@NL@%
  2605. %@AB@%'* to the Index, It then associates the highlighted index name (in the     *%@AE@%%@NL@%
  2606. %@AB@%'* Sorting Order box) with the name it is known by in the program, and     *%@AE@%%@NL@%
  2607. %@AB@%'* places that name in the .WhichIndex element of a structured variable of *%@AE@%%@NL@%
  2608. %@AB@%'* RecStruct type.                                                         *%@AE@%%@NL@%
  2609. %@AB@%'*                                   Parameters:                           *%@AE@%%@NL@%
  2610. %@AB@%'* Index       Integer telling which index user has highlighted            *%@AE@%%@NL@%
  2611. %@AB@%'* NextField   Manifest Constant telling big cursor field position         *%@AE@%%@NL@%
  2612. %@AB@%'* Job         Manifest Constant indicating task being performed           *%@AE@%%@NL@%
  2613. %@AB@%'* TablesRec   Variable of RecStruct type, whose .WhichInded element is    *%@AE@%%@NL@%
  2614. %@AB@%'*             used to return the index name to be used by SETINDEX.       *%@AE@%%@NL@%
  2615. %@AB@%'***************************************************************************%@AE@%%@NL@%
  2616. FUNCTION OrderCursor (Index%, NextField%, Job%, TablesRec AS RecStruct, Letter$)%@NL@%
  2617.   OrderCursor = FALSE%@NL@%
  2618.   CALL Indexbox(TablesRec, Index)         ' Light up the new index%@NL@%
  2619.   COLOR BACKGROUND, BRIGHT + FOREGROUND   ' in Sorting Order box%@NL@%
  2620.   LOCATE NextField, 18%@NL@%
  2621.   IF Job = REORDER THEN         ' Tell the user what is expected of him%@NL@%
  2622. %@NL@%
  2623.     IF TablesRec.TableNum = cBookStockTableNum THEN%@NL@%
  2624.       IF NextField <> PRICEFIELD AND NextField <> EDFIELD THEN%@NL@%
  2625.         PRINT "Press enter to resort, or TAB to move on"%@NL@%
  2626.       ELSE%@NL@%
  2627.         LOCATE NextField, 20 '19%@NL@%
  2628.         PRINT "Sorry, cannot sort on an unindexed field"%@NL@%
  2629.       END IF%@NL@%
  2630.     ELSE%@NL@%
  2631.       IF NextField <> STREETFIELD AND NextField <> CITYFIELD THEN%@NL@%
  2632.         PRINT "Press enter to resort, or TAB to move on"%@NL@%
  2633.       ELSE%@NL@%
  2634.         PRINT "Sorry, cannot sort on an unindexed field"%@NL@%
  2635.       END IF%@NL@%
  2636.     END IF%@NL@%
  2637.    END IF%@NL@%
  2638. %@NL@%
  2639. %@AB@%        ' The following places the name of the index to sort on in the%@AE@%%@NL@%
  2640. %@AB@%        ' WhichIndex element of the structured variable TablesRec --- it%@AE@%%@NL@%
  2641. %@AB@%        ' retrieved at the module-level code%@AE@%%@NL@%
  2642. %@NL@%
  2643.         LOCATE NextField, 18%@NL@%
  2644.         SELECT CASE NextField%@NL@%
  2645.           CASE TITLEFIELD, NAMEFIELD%@NL@%
  2646.             IF Job = SEEKFIELD THEN%@NL@%
  2647.               IF TablesRec.TableNum = cBookStockTableNum THEN%@NL@%
  2648.                 PRINT "Type Title to search for, or press TAB to move on"%@NL@%
  2649.               ELSE%@NL@%
  2650.                 PRINT "Type Name to search for, or press TAB to move on"%@NL@%
  2651.               END IF%@NL@%
  2652.             END IF%@NL@%
  2653.             IF ConfirmEntry%(Letter$) THEN%@NL@%
  2654.               IF TablesRec.TableNum = cBookStockTableNum THEN%@NL@%
  2655.                 TablesRec.WhichIndex = "TitleIndexBS"%@NL@%
  2656.               ELSE%@NL@%
  2657.                 TablesRec.WhichIndex = "NameIndexCH"%@NL@%
  2658.               END IF%@NL@%
  2659.               OrderCursor = TRUE%@NL@%
  2660.               EXIT FUNCTION%@NL@%
  2661.             ELSE%@NL@%
  2662.               OrderCursor = FALSE%@NL@%
  2663.               NextField% = AUTHORFIELD%@NL@%
  2664.             END IF%@NL@%
  2665.           CASE AUTHORFIELD, STREETFIELD%@NL@%
  2666.             IF Job = SEEKFIELD THEN%@NL@%
  2667.               IF TablesRec.TableNum = cBookStockTableNum THEN%@NL@%
  2668.                 PRINT "Type Author name to search for, or TAB to move on"%@NL@%
  2669.               ELSE%@NL@%
  2670.                 PRINT "Sorry, can't search on an unindexed field"%@NL@%
  2671.               END IF%@NL@%
  2672.             END IF%@NL@%
  2673.             IF ConfirmEntry%(Letter$) THEN%@NL@%
  2674.               IF TablesRec.TableNum = cBookStockTableNum THEN%@NL@%
  2675.                 TablesRec.WhichIndex = "AuthorIndexBS"%@NL@%
  2676.               END IF%@NL@%
  2677.               OrderCursor = TRUE%@NL@%
  2678.               EXIT FUNCTION%@NL@%
  2679.             ELSE%@NL@%
  2680.               OrderCursor = FALSE%@NL@%
  2681.               NextField% = PUBFIELD%@NL@%
  2682.             END IF%@NL@%
  2683.           CASE PUBFIELD, CITYFIELD%@NL@%
  2684.             IF Job = SEEKFIELD THEN%@NL@%
  2685.               IF TablesRec.TableNum = cBookStockTableNum THEN%@NL@%
  2686.                 PRINT "Type Publisher name to search for, or TAB to move on"%@NL@%
  2687.               ELSE%@NL@%
  2688.                 PRINT "Sorry, can't search on an unindexed field"%@NL@%
  2689.               END IF%@NL@%
  2690.             END IF%@NL@%
  2691.             IF ConfirmEntry%(Letter$) THEN%@NL@%
  2692.               IF TablesRec.TableNum = cBookStockTableNum THEN%@NL@%
  2693.                 TablesRec.WhichIndex = "PubIndexBS"%@NL@%
  2694.               END IF%@NL@%
  2695.               OrderCursor = TRUE%@NL@%
  2696.               EXIT FUNCTION%@NL@%
  2697.             ELSE%@NL@%
  2698.               OrderCursor = FALSE%@NL@%
  2699.               NextField% = EDFIELD%@NL@%
  2700.             END IF%@NL@%
  2701.           CASE EDFIELD, STATEFIELD%@NL@%
  2702.             IF Job = SEEKFIELD THEN%@NL@%
  2703.               IF TablesRec.TableNum = cCardHoldersTableNum THEN%@NL@%
  2704.                 PRINT "Type State (2 letters), or TAB to move on"%@NL@%
  2705.               ELSE%@NL@%
  2706.                 PRINT "Sorry, can't search on an unindexed field"%@NL@%
  2707.               END IF%@NL@%
  2708.             END IF%@NL@%
  2709.             IF ConfirmEntry%(Letter$) THEN%@NL@%
  2710.               IF TablesRec.TableNum = cCardHoldersTableNum THEN%@NL@%
  2711.                 TablesRec.WhichIndex = "StateIndexCH"%@NL@%
  2712.               END IF%@NL@%
  2713.               OrderCursor = TRUE%@NL@%
  2714.               EXIT FUNCTION%@NL@%
  2715.             ELSE%@NL@%
  2716.               OrderCursor = FALSE%@NL@%
  2717.               NextField% = PRICEFIELD%@NL@%
  2718.             END IF%@NL@%
  2719.           CASE PRICEFIELD, ZIPFIELD%@NL@%
  2720.             IF Job = SEEKFIELD THEN%@NL@%
  2721.               IF TablesRec.TableNum = cCardHoldersTableNum THEN%@NL@%
  2722.                 PRINT "Type Zipcode to search for, or TAB to move on"%@NL@%
  2723.               ELSE%@NL@%
  2724.                 LOCATE PRICEFIELD, 20%@NL@%
  2725.                 PRINT "Sorry, can't search on an unindexed field"%@NL@%
  2726.               END IF%@NL@%
  2727.             END IF%@NL@%
  2728.             IF ConfirmEntry%(Letter$) THEN%@NL@%
  2729.               IF TablesRec.TableNum = cCardHoldersTableNum THEN%@NL@%
  2730.                 TablesRec.WhichIndex = "ZipIndexCH"%@NL@%
  2731.               END IF%@NL@%
  2732.               OrderCursor = TRUE%@NL@%
  2733.               EXIT FUNCTION%@NL@%
  2734.             ELSE%@NL@%
  2735.               OrderCursor = FALSE%@NL@%
  2736.               NextField% = IDFIELD%@NL@%
  2737.             END IF%@NL@%
  2738.           CASE IDFIELD, CARDNUMFIELD%@NL@%
  2739.             IF Job = SEEKFIELD THEN%@NL@%
  2740.               IF TablesRec.TableNum = cBookStockTableNum THEN%@NL@%
  2741.                 PRINT "Type ID number to search for, or TAB to move on"%@NL@%
  2742.               ELSE%@NL@%
  2743.                 PRINT "Type Card number to seek, or press TAB to move on"%@NL@%
  2744.               END IF%@NL@%
  2745.             END IF%@NL@%
  2746. %@AB@%            ' Setting Letter$ to "" may be unnecessary now%@AE@%%@NL@%
  2747.             Letter$ = ""%@NL@%
  2748.             IF ConfirmEntry%(Letter$) THEN%@NL@%
  2749.               IF TablesRec.TableNum = cBookStockTableNum THEN%@NL@%
  2750.                 TablesRec.WhichIndex = "IDIndex"%@NL@%
  2751.               ELSE%@NL@%
  2752.                 TablesRec.WhichIndex = "CardNumIndexCH"%@NL@%
  2753.               END IF%@NL@%
  2754.               OrderCursor = TRUE%@NL@%
  2755.               EXIT FUNCTION%@NL@%
  2756.             ELSE%@NL@%
  2757.               OrderCursor = FALSE%@NL@%
  2758.               NextField% = BIGINDEX%@NL@%
  2759.             END IF%@NL@%
  2760.         END SELECT%@NL@%
  2761.  IF Letter$ = "eScApE" THEN OrderCursor = 3: FirstLetter$ = ""%@NL@%
  2762. END FUNCTION%@NL@%
  2763. %@NL@%
  2764. %@AB@%'***************************************************************************%@AE@%%@NL@%
  2765. %@AB@%'*  The PlaceCursor FUNCTION lets the user tab around on the displayed form*%@AE@%%@NL@%
  2766. %@AB@%'*  when performing field-specific operations on the table. Since this     *%@AE@%%@NL@%
  2767. %@AB@%'*  function is recursive it keeps track of available stack space. The two *%@AE@%%@NL@%
  2768. %@AB@%'*  major possibilities are SEEKs/REORDERs (for which OrderCursor is then  *%@AE@%%@NL@%
  2769. %@AB@%'*  called) and EDIT/ADD records (for which EdAddCursor is called. Note    *%@AE@%%@NL@%
  2770. %@AB@%'*  the combined index (BigIndex) and the default index are handled as     *%@AE@%%@NL@%
  2771. %@AB@%'*  special cases, since they don't correspond to a single field.Recursive *%@AE@%%@NL@%
  2772. %@AB@%'*  construction lets the user cycle through the fields as long as         *%@AE@%%@NL@%
  2773. %@AB@%'*  sufficient stack remains to keep calling PlaceCursor. Note that since  *%@AE@%%@NL@%
  2774. %@AB@%'*  it is recursive, it may take while to step out while stepping with F8. *%@AE@%%@NL@%
  2775. %@AB@%'*                                Parameters                               *%@AE@%%@NL@%
  2776. %@AB@%'*  WhichField    Integer identifier specifying current field on form      *%@AE@%%@NL@%
  2777. %@AB@%'*  TablesRec     Variable of type RecStruct holding all table information *%@AE@%%@NL@%
  2778. %@AB@%'*  FirstLetter$  Carries user response to initial prompt shown            *%@AE@%%@NL@%
  2779. %@AB@%'*  FirstTime     Boolean telling whether this is first cal or recursion   *%@AE@%%@NL@%
  2780. %@AB@%'*  Task          Tells operation being performed                          *%@AE@%%@NL@%
  2781. %@AB@%'***************************************************************************%@AE@%%@NL@%
  2782. %@AB@%'%@AE@%%@NL@%
  2783. FUNCTION PlaceCursor% (WhichField, TablesRec AS RecStruct, FirstLetter$, FirstTime AS INTEGER, Task AS INTEGER)%@NL@%
  2784. STATIC ReturnValue, InitialLetter$, GetOut, counter, WhichOne%@NL@%
  2785. WhichTable = TablesRec.TableNum%@NL@%
  2786. IF ExitFlag THEN EXIT FUNCTION%@NL@%
  2787. %@NL@%
  2788. ReturnValue = WhichField%@NL@%
  2789. %@AB@%' Keep tabs on the stack and exit and reset it if it gets too low%@AE@%%@NL@%
  2790. IF FRE(-2) < 400 THEN%@NL@%
  2791.   WhichField = 0%@NL@%
  2792.   PlaceCursor = 0%@NL@%
  2793.   GetOut = -1%@NL@%
  2794.   EXIT FUNCTION%@NL@%
  2795. END IF%@NL@%
  2796. %@NL@%
  2797. %@AB@%' Set up for each of the possible operations that use PlaceCursor%@AE@%%@NL@%
  2798. IF Task = REORDER THEN%@NL@%
  2799.    COLOR FOREGROUND, BACKGROUND%@NL@%
  2800.    CALL ShowMessage("Press TAB to choose field to sort on, ESC to escape", 0)%@NL@%
  2801.    IF WhichField = TITLEFIELD THEN WhichOne = 0%@NL@%
  2802. ELSEIF Task = SEEKFIELD THEN%@NL@%
  2803.    CALL ShowMessage("TAB to a field, then enter a value to search", 0)%@NL@%
  2804. ELSEIF Task = ADDRECORD THEN%@NL@%
  2805.   IF FirstTime THEN FirstLetter$ = CHR$(TABKEY) ELSE FirstLetter$ = ""%@NL@%
  2806. END IF%@NL@%
  2807. %@NL@%
  2808. %@AB@%' The following IF... lets function handle either an entered letter or TAB%@AE@%%@NL@%
  2809. IF FirstLetter$ <> "" THEN%@NL@%
  2810.     Answer$ = FirstLetter$%@NL@%
  2811. ELSEIF FirstTime THEN%@NL@%
  2812.   IF Task = EDITRECORD THEN%@NL@%
  2813.     Answer$ = CHR$(TABKEY)%@NL@%
  2814.   END IF%@NL@%
  2815. ELSE%@NL@%
  2816.   DO%@NL@%
  2817.   Answer$ = INKEY$%@NL@%
  2818.   LOOP WHILE Answer$ = EMPTYSTRING%@NL@%
  2819. END IF%@NL@%
  2820. %@NL@%
  2821. IF LEN(Answer$) = 1 THEN%@NL@%
  2822. %@NL@%
  2823. %@AB@%' Clear the fields for the appropriate messages%@AE@%%@NL@%
  2824. IF Task <> EDITRECORD AND Task <> ADDRECORD THEN%@NL@%
  2825. CALL ClearEm(TablesRec.TableNum, 1, 1, 1, 1, 1, 1)%@NL@%
  2826. END IF%@NL@%
  2827. %@NL@%
  2828.    SELECT CASE ASC(Answer$)%@NL@%
  2829.     CASE IS = TABKEY, ENTER%@NL@%
  2830.            SELECT CASE WhichField%@NL@%
  2831.             CASE TITLEFIELD, AUTHORFIELD, PUBFIELD, EDFIELD, PRICEFIELD, IDFIELD%@NL@%
  2832.               IF Task = REORDER OR Task = SEEKFIELD THEN%@NL@%
  2833.                 RetVal = OrderCursor(WhichOne, WhichField, Task, TablesRec, FirstLetter$)%@NL@%
  2834.                 IF RetVal THEN%@NL@%
  2835. %@AB@%                  ' trap a magic value for an escape here then call the Draw stuff%@AE@%%@NL@%
  2836.                   IF RetVal <> 3 THEN%@NL@%
  2837.                     WhichOne = 0: EXIT FUNCTION%@NL@%
  2838.                   ELSE%@NL@%
  2839.                     WhichOne = 0%@NL@%
  2840.                     WhichField = 0%@NL@%
  2841.                     PlaceCursor = 0%@NL@%
  2842.                     CALL ShowRecord(TablesRec)%@NL@%
  2843.                     CALL ShowMessage("You've escaped! Try again", 0)%@NL@%
  2844.                     CALL DrawTable(WhichTable)%@NL@%
  2845.                     CALL DrawHelpKeys(WhichTable)%@NL@%
  2846.                     CALL ShowKeys(TablesRec, FOREGROUND + BRIGHT, 0, 0)%@NL@%
  2847.                     EXIT FUNCTION%@NL@%
  2848.                   END IF%@NL@%
  2849.                 END IF%@NL@%
  2850.               ELSEIF Task = EDITRECORD OR Task = ADDRECORD THEN%@NL@%
  2851.                 Placed = EdAddCursor(WhichField, Task, TablesRec, FirstTime)%@NL@%
  2852.               END IF%@NL@%
  2853. %@NL@%
  2854.             CASE BIGINDEX%@NL@%
  2855.                 CALL Indexbox(TablesRec, WhichOne)%@NL@%
  2856.                 IF WhichTable = cBookStockTableNum THEN%@NL@%
  2857.                   COLOR BACKGROUND, BRIGHT + FOREGROUND%@NL@%
  2858.                   IF Task = REORDER THEN%@NL@%
  2859.                     LOCATE TITLEFIELD, 18%@NL@%
  2860.                     PRINT "Press ENTER to sort first by Title..."%@NL@%
  2861.                     LOCATE AUTHORFIELD, 18%@NL@%
  2862.                     PRINT "... then subsort by Author..."%@NL@%
  2863.                     LOCATE IDFIELD, 18%@NL@%
  2864.                     PRINT "... then subsort again by ID "%@NL@%
  2865.                     SLEEP%@NL@%
  2866.                   ELSEIF Task = SEEKFIELD THEN%@NL@%
  2867.                     LOCATE TITLEFIELD, 18%@NL@%
  2868.                     PRINT "First, type in the Title to search for,"%@NL@%
  2869.                     LOCATE AUTHORFIELD, 18%@NL@%
  2870.                     PRINT "... then type in the Author's name"%@NL@%
  2871.                     LOCATE IDFIELD, 18%@NL@%
  2872.                     PRINT "... then type in the ID number "%@NL@%
  2873.                     CALL ShowMessage("Typing in a value for a combined index is tricky...", 0)%@NL@%
  2874.                     SLEEP%@NL@%
  2875.                   END IF%@NL@%
  2876.                   COLOR FOREGROUND, BACKGROUND%@NL@%
  2877.                   IF ConfirmEntry%(FirstLetter$) THEN%@NL@%
  2878.                     TablesRec.WhichIndex = "BigIndex"%@NL@%
  2879.                     IF Task = SEEKFIELD THEN%@NL@%
  2880.                       WhichOne = 0%@NL@%
  2881.                       WhichField = TITLEFIELD%@NL@%
  2882.                     END IF%@NL@%
  2883.                     EXIT FUNCTION%@NL@%
  2884.                   END IF%@NL@%
  2885.                 END IF%@NL@%
  2886.                 CALL ClearEm(TablesRec.TableNum, 1, 1, 0, 0, 1, 0)%@NL@%
  2887.                 WhichField = NULLINDEX   ' TITLEFIELD%@NL@%
  2888. %@NL@%
  2889.             CASE NULLINDEX%@NL@%
  2890.                 CALL Indexbox(TablesRec, WhichOne)%@NL@%
  2891.                 IF Task = SEEKFIELD THEN%@NL@%
  2892.                   CALL ShowMessage("Can't SEEK on the default index", 0)%@NL@%
  2893.                   DO%@NL@%
  2894.                     KeyIn$ = INKEY$%@NL@%
  2895.                     IF KeyIn$ <> "" THEN%@NL@%
  2896.                       IF ASC(KeyIn$) = ESCAPE THEN EXIT FUNCTION%@NL@%
  2897.                     END IF%@NL@%
  2898.                   LOOP WHILE KeyIn$ = ""%@NL@%
  2899. %@AB@%                  'SLEEP%@AE@%%@NL@%
  2900. %@AB@%                '  EXIT FUNCTION%@AE@%%@NL@%
  2901. %@AB@%                'END IF%@AE@%%@NL@%
  2902.                 ELSEIF ConfirmEntry%(FirstLetter$) THEN%@NL@%
  2903.                   TablesRec.WhichIndex = "NULL"%@NL@%
  2904.                   EXIT FUNCTION%@NL@%
  2905.                 END IF%@NL@%
  2906.                 WhichField = TITLEFIELD%@NL@%
  2907. %@NL@%
  2908.             CASE ELSE%@NL@%
  2909.                 EraseMessage%@NL@%
  2910.                  CALL ShowMessage("Not a valid key --- press Space bar", 0)%@NL@%
  2911.                 EXIT FUNCTION%@NL@%
  2912.           END SELECT%@NL@%
  2913. %@AB@%        ' Placecursor calls itself for next user response%@AE@%%@NL@%
  2914.         Value = PlaceCursor(WhichField, TablesRec, FirstLetter$, 0, Task)%@NL@%
  2915. %@NL@%
  2916.     CASE ESCAPE%@NL@%
  2917.       WhichOne = 0%@NL@%
  2918.       WhichField = 0%@NL@%
  2919.       PlaceCursor = 0%@NL@%
  2920.       CALL ShowRecord(TablesRec)%@NL@%
  2921.       CALL ShowMessage("You've escaped! Try again", 0)%@NL@%
  2922.       CALL DrawTable(WhichTable)%@NL@%
  2923.       CALL DrawHelpKeys(WhichTable)%@NL@%
  2924.       CALL ShowKeys(TablesRec, FOREGROUND + BRIGHT, 0, 0)%@NL@%
  2925.       EXIT FUNCTION%@NL@%
  2926.     CASE 32 TO 127                        ' Acceptable ASCII characters%@NL@%
  2927.      InitialLetter$ = Answer$%@NL@%
  2928.      FirstLetter$ = InitialLetter$%@NL@%
  2929.      EXIT FUNCTION%@NL@%
  2930.     CASE ELSE%@NL@%
  2931.         BEEP%@NL@%
  2932.         EraseMessage%@NL@%
  2933.          CALL ShowMessage("Not a valid key --- press Space bar", 0)%@NL@%
  2934.         WhichField = 0%@NL@%
  2935.         PlaceCursor = 0%@NL@%
  2936.         EXIT FUNCTION%@NL@%
  2937.     END SELECT%@NL@%
  2938. ELSEIF Answer$ <> CHR$(9) THEN%@NL@%
  2939.   EraseMessage%@NL@%
  2940.   CALL ShowMessage("Not a valid key --- press Space bar", 0)%@NL@%
  2941.   WhichField = 0%@NL@%
  2942.   EXIT FUNCTION%@NL@%
  2943. ELSE%@NL@%
  2944.      CALL ShowMessage("  Press TAB key or ENTER  ", 0)%@NL@%
  2945. END IF%@NL@%
  2946. %@NL@%
  2947. IF GetOut THEN%@NL@%
  2948.   counter = counter + 1%@NL@%
  2949.   IF counter < 15 THEN%@NL@%
  2950.     WhichField = 0%@NL@%
  2951.     WhichOne = 0%@NL@%
  2952.     EXIT FUNCTION%@NL@%
  2953.   ELSE%@NL@%
  2954.     GetOut = 0%@NL@%
  2955.     counter = 0%@NL@%
  2956.  END IF%@NL@%
  2957. END IF%@NL@%
  2958. %@NL@%
  2959. END FUNCTION%@NL@%
  2960. %@NL@%
  2961. %@AB@%'***************************************************************************%@AE@%%@NL@%
  2962. %@AB@%'*  The TransposeName FUNCTION takes a  string and decideds whether it is  *%@AE@%%@NL@%
  2963. %@AB@%'*  a comma-delimited, last-name-first name, a first-name-first name or a  *%@AE@%%@NL@%
  2964. %@AB@%'*  single word name. In the last case, the string is returned unchanged.  *%@AE@%%@NL@%
  2965. %@AB@%'*  In either of the other cases, the string is translated to the comple-  *%@AE@%%@NL@%
  2966. %@AB@%'*  mentary format.                                                        *%@AE@%%@NL@%
  2967. %@AB@%'*                              Parameters                                 *%@AE@%%@NL@%
  2968. %@AB@%'*  TheName   A string representing a CardHolders table TheName element,   *%@AE@%%@NL@%
  2969. %@AB@%'*            or a BookStock table Author Element                          *%@AE@%%@NL@%
  2970. %@AB@%'***************************************************************************%@AE@%%@NL@%
  2971. FUNCTION TransposeName$ (TheName AS STRING)%@NL@%
  2972. SubStrLen = (INSTR(TheName, ","))%@NL@%
  2973. IF SubStrLen = 0 THEN%@NL@%
  2974.   SubStrLen = INSTR(TheName, " ")%@NL@%
  2975.   IF SubStrLen = 0 THEN TransposeName$ = TheName: EXIT FUNCTION%@NL@%
  2976. END IF%@NL@%
  2977. TheName = LTRIM$(RTRIM$(TheName))%@NL@%
  2978.   IF INSTR(TheName, ",") THEN%@NL@%
  2979.     LastNameLen = INSTR(TheName, ",")%@NL@%
  2980.     LastName$ = LTRIM$(RTRIM$(LEFT$(TheName, LastNameLen - 1)))%@NL@%
  2981.     FirstName$ = LTRIM$(RTRIM$(MID$(TheName, LastNameLen + 1)))%@NL@%
  2982.     TransposeName$ = LTRIM$(RTRIM$(FirstName$ + " " + LastName$))%@NL@%
  2983.   ELSE%@NL@%
  2984.     FirstNameLen = INSTR(TheName, " ")%@NL@%
  2985.     IF FirstNameLen THEN%@NL@%
  2986.       FirstName$ = LTRIM$(RTRIM$(LEFT$(TheName, FirstNameLen - 1)))%@NL@%
  2987.       LastName$ = LTRIM$(RTRIM$(MID$(TheName, FirstNameLen + 1)))%@NL@%
  2988.     ELSE%@NL@%
  2989.       LastName$ = LTRIM$(RTRIM$(TheName))%@NL@%
  2990.     END IF%@NL@%
  2991.     TransposeName$ = LTRIM$(RTRIM$(LastName$ + ", " + FirstName$))%@NL@%
  2992.   END IF%@NL@%
  2993. END FUNCTION%@NL@%
  2994. %@NL@%
  2995. %@AB@%'****************************** ValuesOK FUNCTION **************************%@AE@%%@NL@%
  2996. %@AB@%'* The ValuesOK FUNCTION checks the values input by the user for various   *%@AE@%%@NL@%
  2997. %@AB@%'* purposes. The checking is very minimal and checks the format of what is *%@AE@%%@NL@%
  2998. %@AB@%'* entered. For example, the IDnum field needs a double value, but the form*%@AE@%%@NL@%
  2999. %@AB@%'* (5 digits, followed by a decimal point, followed by 4 digits) is more   *%@AE@%%@NL@%
  3000. %@AB@%'* important than the data type.                                           *%@AE@%%@NL@%
  3001. %@AB@%'*                                Parameters:                              *%@AE@%%@NL@%
  3002. %@AB@%'*   Big Rec      User-defined type containing all table information       *%@AE@%%@NL@%
  3003. %@AB@%'*   Key1, Key2   Represent strings to check                               *%@AE@%%@NL@%
  3004. %@AB@%'*   ValueToSeek  Represents the final value of a combined index           *%@AE@%%@NL@%
  3005. %@AB@%'***************************************************************************%@AE@%%@NL@%
  3006. FUNCTION ValuesOK (BigRec AS RecStruct, Key1$, Key2$, ValueToSeek$)%@NL@%
  3007.   IndexName$ = BigRec.WhichIndex%@NL@%
  3008.   ValueToSeek$ = LTRIM$(RTRIM$(ValueToSeek$))%@NL@%
  3009.   SELECT CASE RTRIM$(LTRIM$(IndexName$))%@NL@%
  3010.     CASE "TitleIndexBS", "PubIndexBS"       ' LEN <= 50%@NL@%
  3011.       IF LEN(Key1$) > 50 THEN ValuesOK = FALSE: EXIT FUNCTION%@NL@%
  3012. %@NL@%
  3013.     CASE "AuthorIndexBS", "NameIndexCH"     ' LEN <= 36%@NL@%
  3014.       IF LEN(Key1$) > 36 THEN ValuesOK = FALSE: EXIT FUNCTION%@NL@%
  3015. %@NL@%
  3016.     CASE "StateIndexCH"                     ' LEN = 2%@NL@%
  3017.       IF LEN(Key1$) > 2 THEN ValuesOK = FALSE: EXIT FUNCTION%@NL@%
  3018. %@NL@%
  3019.     CASE "IDIndex", "IDIndexBO"             ' 5 digits befor d.p., 4 after%@NL@%
  3020.       IF LEN(ValueToSeek$) <> 10 THEN ValuesOK = FALSE: EXIT FUNCTION%@NL@%
  3021.       IF MID$(ValueToSeek$, 6, 1) <> "." THEN%@NL@%
  3022.         ValuesOK = FALSE: EXIT FUNCTION%@NL@%
  3023.       END IF%@NL@%
  3024.     CASE "CardNumIndexCH", "CardNumIndexBO" ' 5 digits, value <= LONG%@NL@%
  3025.       IF LEN(ValueToSeek$) <> 5 THEN ValuesOK = FALSE: EXIT FUNCTION%@NL@%
  3026. %@NL@%
  3027.     CASE "ZipIndexCH"                       ' 5 digits, value <= LONG%@NL@%
  3028.       IF LEN(ValueToSeek$) <> 5 THEN ValuesOK = FALSE: EXIT FUNCTION%@NL@%
  3029. %@NL@%
  3030.     CASE "BigIndex"                         ' Key1$ <= 50, Key2$ <= 36%@NL@%
  3031.       IF LEN(Key1$) > 50 THEN ValuesOK = FALSE: EXIT FUNCTION%@NL@%
  3032.       IF LEN(Key2$) > 36 THEN ValuesOK = FALSE: EXIT FUNCTION%@NL@%
  3033.       IF MID$(ValueToSeek$, 6, 1) <> "." THEN%@NL@%
  3034.         ValuesOK = FALSE: EXIT FUNCTION%@NL@%
  3035.       END IF%@NL@%
  3036.   END SELECT%@NL@%
  3037.   ValuesOK = TRUE%@NL@%
  3038. END FUNCTION%@NL@%
  3039. %@NL@%
  3040. %@NL@%
  3041. %@NL@%
  3042. %@2@%%@AH@%BOOKMOD3.BAS%@AE@%%@EH@%%@NL@%
  3043. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\BOOKMOD3.BAS%@AE@%%@NL@%
  3044. %@NL@%
  3045. %@AB@%'***************************************************************************%@AE@%%@NL@%
  3046. %@AB@%'* This is module level code for BOOKMOD3.BAS, the fourth                  *%@AE@%%@NL@%
  3047. %@AB@%'* module of BOOKLOOK.BAS.                                                 *%@AE@%%@NL@%
  3048. %@AB@%'*                                                                         *%@AE@%%@NL@%
  3049. %@AB@%'* The module contains a procedure, MakeOver, you can use to convert text  *%@AE@%%@NL@%
  3050. %@AB@%'* files containing the right format and type of information for the tables*%@AE@%%@NL@%
  3051. %@AB@%'* used by the BOOKLOOK program to a .MDB file. However, you need to call  *%@AE@%%@NL@%
  3052. %@AB@%'* MakeOver from the Immediate Window, and in order for it to work, you    *%@AE@%%@NL@%
  3053. %@AB@%'* must use the PROISAMD version of the TSR, because MakeOver needs the    *%@AE@%%@NL@%
  3054. %@AB@%'* data dictionary functionality for creating indexes, etc.                *%@AE@%%@NL@%
  3055. %@AB@%'* If you use the DTFMTER.QLB library functions you must include the files *%@AE@%%@NL@%
  3056. %@AB@%'* DATIM.BI and FORMAT.BI at this level, using syntax as shown below.      *%@AE@%%@NL@%
  3057. %@AB@%'***************************************************************************%@AE@%%@NL@%
  3058. DEFINT A-Z%@NL@%
  3059. %@AB@%'$INCLUDE: 'booklook.bi'%@AE@%%@NL@%
  3060. %@NL@%
  3061. %@AB@%'***************************************************************************%@AE@%%@NL@%
  3062. %@AB@%'*  The BooksBorrowed SUB takes the CardNum in BooksOut associated with the*%@AE@%%@NL@%
  3063. %@AB@%'*  currently displayed CardHolder, then looks up each book in BooksOut    *%@AE@%%@NL@%
  3064. %@AB@%'*  assigned to that CardNum. Note that you can use SEEKoperand to find the*%@AE@%%@NL@%
  3065. %@AB@%'*  first matching record, but thereafter you need to MOVENEXT and check   *%@AE@%%@NL@%
  3066. %@AB@%'*  each succeeding record to see if the CardNum matches. When a match is  *%@AE@%%@NL@%
  3067. %@AB@%'*  made, look up the IDnum in the BooksOut table and retrieve the title.  *%@AE@%%@NL@%
  3068. %@AB@%'*  Put all the titles in the Titles array, then display with PeekWindow.  *%@AE@%%@NL@%
  3069. %@AB@%'*                                   Parameters                            *%@AE@%%@NL@%
  3070. %@AB@%'*  TablesRec   Structure containing information on all database tables    *%@AE@%%@NL@%
  3071. %@AB@%'***************************************************************************%@AE@%%@NL@%
  3072. SUB BooksBorrowed (TablesRec AS RecStruct)%@NL@%
  3073.         DIM Titles(50) AS STRING%@NL@%
  3074. %@AB@%        ' First, get the card number of the current record in Bookstock - then%@AE@%%@NL@%
  3075. %@AB@%        ' at the end of this procedure, restore that book%@AE@%%@NL@%
  3076.         IF LOF(cBooksOutTableNum) = 0 THEN EXIT SUB%@NL@%
  3077.         IF GETINDEX$(cBooksOutTableNum) <> "CardNumIndexBO" THEN%@NL@%
  3078.                 SETINDEX cBooksOutTableNum, "CardNumIndexBO"%@NL@%
  3079.         END IF%@NL@%
  3080.         RevName$ = TransposeName$(TablesRec.Lendee.TheName)%@NL@%
  3081.         SEEKEQ cBooksOutTableNum, TablesRec.Lendee.CardNum%@NL@%
  3082.          IF NOT EOF(cBooksOutTableNum) THEN%@NL@%
  3083.                 DO%@NL@%
  3084.                         RETRIEVE cBooksOutTableNum, TablesRec.OutBooks%@NL@%
  3085.                          IF TablesRec.OutBooks.CardNum = TablesRec.Lendee.CardNum THEN%@NL@%
  3086.                                         IF GETINDEX$(cBookStockTableNum) <> "IDIndex" THEN%@NL@%
  3087.                                                 SETINDEX cBookStockTableNum, "IDIndex"%@NL@%
  3088.                                         END IF%@NL@%
  3089.                                         SEEKEQ cBookStockTableNum, TablesRec.OutBooks.IDnum%@NL@%
  3090.                                         IF NOT EOF(cBookStockTableNum) THEN%@NL@%
  3091.                                                 RETRIEVE cBookStockTableNum, TablesRec.Inventory%@NL@%
  3092.                                                 Titles(Index) = RTRIM$(TablesRec.Inventory.Title)%@NL@%
  3093.                                                 ThisSize = LEN(RTRIM$(Titles(Index)))%@NL@%
  3094.                                                         IF ThisSize > Biggest THEN%@NL@%
  3095.                                                                 Biggest = ThisSize%@NL@%
  3096.                                                         END IF%@NL@%
  3097.                                          Index = Index + 1%@NL@%
  3098.                                         END IF%@NL@%
  3099.                                 END IF%@NL@%
  3100.                 MOVENEXT cBooksOutTableNum%@NL@%
  3101.                 LOOP UNTIL EOF(cBooksOutTableNum)%@NL@%
  3102.         ELSE%@NL@%
  3103.                 Alert$ = RevName$ + " currently has no books checked out"%@NL@%
  3104.                 CALL ShowMessage(Alert$, 0)%@NL@%
  3105.         END IF%@NL@%
  3106.         IF Index <> 0 THEN%@NL@%
  3107.                 HeadMessage$ = " Books borrowed by " + RevName$ + " "%@NL@%
  3108.                 FootMessage$ = " Press a key to continue "%@NL@%
  3109.                 CALL PeekWindow(Titles(), HeadMessage$, FootMessage$, Biggest)%@NL@%
  3110.                 CALL DrawTable(TablesRec.TableNum)%@NL@%
  3111.                 CALL ShowMessage(KEYSMESSAGE, 0)%@NL@%
  3112.         END IF%@NL@%
  3113. END SUB%@NL@%
  3114. %@NL@%
  3115. %@AB@%'***************************************************************************%@AE@%%@NL@%
  3116. %@AB@%'*  The BorrowBook SUB prompts the user to enter the name of the Cardholder*%@AE@%%@NL@%
  3117. %@AB@%'*  who wants to borrow the book, then updates all the other tables accord-*%@AE@%%@NL@%
  3118. %@AB@%'*  ingly. The name or cardnumber can be entered --- if conversion to a    *%@AE@%%@NL@%
  3119. %@AB@%'*  number fails, the user entered a name. If the name isn't of the right  *%@AE@%%@NL@%
  3120. %@AB@%'*  format, it is transposed to last-first, comma delimited. If no exact   *%@AE@%%@NL@%
  3121. %@AB@%'*  match is found, the next best match is attempted and presented for the *%@AE@%%@NL@%
  3122. %@AB@%'*  approval of the user.%@AE@%%@NL@%
  3123. %@AB@%'*                                  Parameter                              *%@AE@%%@NL@%
  3124. %@AB@%'*  TablesRec   RecStruct type variable holding current table information  *%@AE@%%@NL@%
  3125. %@AB@%'***************************************************************************%@AE@%%@NL@%
  3126. SUB BorrowBook (TablesRec AS RecStruct)%@NL@%
  3127. %@NL@%
  3128. DIM SaveBook AS RecStruct%@NL@%
  3129. DIM PeekString(10) AS STRING%@NL@%
  3130. %@NL@%
  3131. Prompt$ = "Name or Card Number to Seek: "%@NL@%
  3132. SaveBook = TablesRec                          ' Save book information%@NL@%
  3133. %@AB@%        ' Prompt user and catch keystroke%@AE@%%@NL@%
  3134. CALL ShowMessage("Enter borrower cardnumber or name: ", 1)%@NL@%
  3135. FirstChar = ASC(ReturnKey$)                   ' ReturnKey$ is a function%@NL@%
  3136. IF FirstChar = ESCAPE THEN CALL ShowMessage("", 0): EXIT SUB%@NL@%
  3137. Answer$ = MakeString$(FirstChar, Prompt$)%@NL@%
  3138. IF FirstChar = ESCAPE THEN CALL ShowMessage("", 0): EXIT SUB%@NL@%
  3139. NumToCheck& = VAL(Answer$)%@NL@%
  3140. IF NumToCheck& = 0 THEN%@NL@%
  3141.         IF INSTR(Answer$, ",") = 0 THEN%@NL@%
  3142.                 StraightName$ = Answer$%@NL@%
  3143.                 Answer$ = TransposeName$(Answer$)%@NL@%
  3144.         ELSE%@NL@%
  3145.                 StraightName$ = TransposeName$(Answer$)%@NL@%
  3146.         END IF%@NL@%
  3147. %@NL@%
  3148.         SETINDEX cCardHoldersTableNum, "NameIndexCH"%@NL@%
  3149.         SEEKEQ cCardHoldersTableNum, Answer$%@NL@%
  3150.         IF EOF(cCardHoldersTableNum) THEN%@NL@%
  3151.                 MOVEFIRST cCardHoldersTableNum%@NL@%
  3152.                 SEEKGE cCardHoldersTableNum, Answer$     ' If EQ fails, try GE%@NL@%
  3153.                 IF EOF(cCardHoldersTableNum) THEN%@NL@%
  3154.                         Alert$ = "Sorry, couldn't find " + StraightName$ + " in CardHolders table..."%@NL@%
  3155.                         CALL ShowMessage(Alert$, 0)%@NL@%
  3156.                         EXIT SUB%@NL@%
  3157.                 END IF%@NL@%
  3158.         END IF%@NL@%
  3159.         IF NOT EOF(cCardHoldersTableNum) THEN%@NL@%
  3160.                 RETRIEVE cCardHoldersTableNum, SaveBook.Lendee%@NL@%
  3161.                 IF TEXTCOMP(LEFT$(SaveBook.Lendee.TheName, 2), LEFT$(Answer$, 2)) = 0 THEN%@NL@%
  3162.                         NumToCheck& = SaveBook.Lendee.CardNum%@NL@%
  3163.                 ELSE%@NL@%
  3164.                         Alert$ = "Sorry, couldn't match " + StraightName$ + " in CardHolders table..."%@NL@%
  3165.                         CALL ShowMessage(Alert$, 0): ' SLEEP: EraseMessage%@NL@%
  3166.                         EXIT SUB%@NL@%
  3167.                 END IF%@NL@%
  3168.         END IF%@NL@%
  3169. ELSE%@NL@%
  3170.         SETINDEX cCardHoldersTableNum, "CardNumIndexCH"%@NL@%
  3171.         SEEKEQ cCardHoldersTableNum, NumToCheck&%@NL@%
  3172.         IF EOF(cCardHoldersTableNum) THEN%@NL@%
  3173.                 Alert$ = "Sorry, could not match " + Answer$%@NL@%
  3174.                 CALL ShowMessage(Alert$, 0):  ' SLEEP: EraseMessage%@NL@%
  3175.                 EXIT SUB%@NL@%
  3176.         ELSE%@NL@%
  3177.                 RETRIEVE cCardHoldersTableNum, SaveBook.Lendee%@NL@%
  3178.                 NumToCheck& = SaveBook.Lendee.CardNum%@NL@%
  3179.         END IF%@NL@%
  3180. END IF%@NL@%
  3181. %@AB@%                                                                                                ' You can replace this phoney date with a call to%@AE@%%@NL@%
  3182. DateDue# = 32950#     ' the Date/Time library as shown on these 2 lines:%@NL@%
  3183. %@AB@%'DateDue# = Now# + 30#%@AE@%%@NL@%
  3184. %@AB@%'DateDue$ = STR$(Month&(DateDue#)) + "/" + LTRIM$(STR$(Day&(DateDue#))) + "/" + LTRIM$(STR$(Year&(DateDue#)))%@AE@%%@NL@%
  3185. %@NL@%
  3186. %@AB@%' Show the information on the Cardholder you found...%@AE@%%@NL@%
  3187. DO%@NL@%
  3188.         PeekString(0) = " This book will be checked out to: "%@NL@%
  3189.         PeekString(1) = ""%@NL@%
  3190.         PeekString(2) = RTRIM$(SaveBook.Lendee.TheName)%@NL@%
  3191.         PeekString(3) = RTRIM$(SaveBook.Lendee.Street)%@NL@%
  3192.         PeekString(4) = RTRIM$(SaveBook.Lendee.City) + ", " + RTRIM$(SaveBook.Lendee.State)%@NL@%
  3193.         PeekString(5) = "Card number: " + STR$(SaveBook.Lendee.CardNum)%@NL@%
  3194.         PeekString(6) = ""%@NL@%
  3195.         PeekString(7) = "The Due Date will be " + STR$(DateDue# + 30)%@NL@%
  3196.         IF LEN(DateDue$) THEN PeekString(7) = "The Due Date will be " + DateDue$%@NL@%
  3197.         FOR Index = 0 TO 8%@NL@%
  3198.                 ThisSize = LEN(RTRIM$(PeekString(Index)))%@NL@%
  3199.                 IF ThisSize > Biggest THEN%@NL@%
  3200.                         Biggest = ThisSize%@NL@%
  3201.                 END IF%@NL@%
  3202.         NEXT Index%@NL@%
  3203. %@NL@%
  3204.         HeadMessage$ = " Cardholder checking out this book "%@NL@%
  3205.         FootMessage$ = " Press ENTER to confirm this checkout "%@NL@%
  3206.         Alert$ = "Press N seek next similar match, ESC to abort checkout"%@NL@%
  3207.         CALL ShowMessage(Alert$, 0)%@NL@%
  3208.         CALL PeekWindow(PeekString(), HeadMessage$, FootMessage$, Biggest)%@NL@%
  3209. %@NL@%
  3210. %@AB@%        ' Let the user press "N" to see the next best match, ESC to abort checkout%@AE@%%@NL@%
  3211. %@AB@%        ' anything else to confirm this as person to whom to check book out to%@AE@%%@NL@%
  3212. %@NL@%
  3213.         Reply$ = ReturnKey$%@NL@%
  3214.         SELECT CASE Reply$%@NL@%
  3215.                 CASE CHR$(ESCAPE)%@NL@%
  3216.                         DoneFlag = TRUE%@NL@%
  3217.                 CASE "N", "n"%@NL@%
  3218.                         MOVENEXT cCardHoldersTableNum%@NL@%
  3219.                         IF EOF(cCardHoldersTableNum) THEN%@NL@%
  3220.                                 DoneFlag = TRUE%@NL@%
  3221.                         ELSE%@NL@%
  3222.                                 RETRIEVE cCardHoldersTableNum, SaveBook.Lendee%@NL@%
  3223.                                 NumToCheck& = SaveBook.Lendee.CardNum%@NL@%
  3224.                                 IF LEFT$(SaveBook.Lendee.TheName, 2) <> LEFT$(Answer$, 2) THEN%@NL@%
  3225.                                         DoneFlag = TRUE%@NL@%
  3226.                                 END IF%@NL@%
  3227.                         END IF%@NL@%
  3228.                 CASE ELSE%@NL@%
  3229.                                 TablesRec.OutBooks.CardNum = NumToCheck&%@NL@%
  3230.                                 TablesRec.OutBooks.IDnum = SaveBook.Inventory.IDnum%@NL@%
  3231.                                 TablesRec.OutBooks.DueDate = DateDue#%@NL@%
  3232.                                 DoneFlag = TRUE%@NL@%
  3233.                                 MOVEFIRST (cBooksOutTableNum)%@NL@%
  3234.                                 INSERT cBooksOutTableNum, TablesRec.OutBooks%@NL@%
  3235.                                 CALL ShowMessage("", 0)%@NL@%
  3236.         END SELECT%@NL@%
  3237. LOOP UNTIL DoneFlag%@NL@%
  3238. %@NL@%
  3239. CALL DrawTable(TablesRec.TableNum)%@NL@%
  3240. CALL ShowMessage(KEYSMESSAGE, 0)%@NL@%
  3241. %@NL@%
  3242. END SUB%@NL@%
  3243. %@NL@%
  3244. %@AB@%'**************************************************************************%@AE@%%@NL@%
  3245. %@AB@%'*  The Borrowed FUNCTION simply makes sure there are records in the      *%@AE@%%@NL@%
  3246. %@AB@%'*  BooksOut table. If there are none, a message is displayed             *%@AE@%%@NL@%
  3247. %@AB@%'**************************************************************************%@AE@%%@NL@%
  3248. FUNCTION Borrowed%@NL@%
  3249.         IF LOF(cBooksOutTableNum) = 0 THEN%@NL@%
  3250.                 CALL ShowMessage("Sorry, no records in the BooksOut table", 0): SLEEP%@NL@%
  3251.                 Borrowed = FALSE%@NL@%
  3252.         ELSE%@NL@%
  3253.                 Borrowed = TRUE%@NL@%
  3254.         END IF%@NL@%
  3255. END FUNCTION%@NL@%
  3256. %@NL@%
  3257. %@AB@%'***************************************************************************%@AE@%%@NL@%
  3258. %@AB@%'* The CatchKey function gets a keystroke and returns TRUE if it was ENTER,*%@AE@%%@NL@%
  3259. %@AB@%'* otherwise it returns FALSE.                                             *%@AE@%%@NL@%
  3260. %@AB@%'***************************************************************************%@AE@%%@NL@%
  3261. FUNCTION CatchKey%%@NL@%
  3262.         DO%@NL@%
  3263.         Answer$ = INKEY$%@NL@%
  3264.         LOOP WHILE Answer$ = ""%@NL@%
  3265.         SELECT CASE ASC(Answer$)%@NL@%
  3266.                 CASE ENTER%@NL@%
  3267.                         CatchKey% = -1%@NL@%
  3268.                 CASE ELSE%@NL@%
  3269.                         CatchKey% = 0%@NL@%
  3270.         END SELECT%@NL@%
  3271. END FUNCTION%@NL@%
  3272. %@NL@%
  3273. %@AB@%'***************************************************************************%@AE@%%@NL@%
  3274. %@AB@%'*  The GetStatus FUNCTION looks up the status of a book in the BooksOut   *%@AE@%%@NL@%
  3275. %@AB@%'*  table. If the SEEK fails it means the book isn't checked out, and that *%@AE@%%@NL@%
  3276. %@AB@%'*  message is displayed. Otherwise, it is placed in DateToShow parameter. *%@AE@%%@NL@%
  3277. %@AB@%'*  The final message about retrieving borrow info relates to LendeeProfile*%@AE@%%@NL@%
  3278. %@AB@%'*                                   Parameters                            *%@AE@%%@NL@%
  3279. %@AB@%'*  TablesRec     Structure containing the information about all the tables*%@AE@%%@NL@%
  3280. %@AB@%'*  DateToShow    The due date to show in the ShowStatus SUB               *%@AE@%%@NL@%
  3281. %@AB@%'***************************************************************************%@AE@%%@NL@%
  3282. FUNCTION GetStatus (TablesRec AS RecStruct, DateToShow#)%@NL@%
  3283.                 IF GETINDEX$(cBooksOutTableNum) <> "IDIndexBO" THEN%@NL@%
  3284.                         SETINDEX cBooksOutTableNum, "IDIndexBO"%@NL@%
  3285.                 END IF%@NL@%
  3286.                 SEEKEQ cBooksOutTableNum, TablesRec.Inventory.IDnum%@NL@%
  3287.                 IF NOT EOF(cBooksOutTableNum) THEN%@NL@%
  3288.                         RETRIEVE cBooksOutTableNum, TablesRec.OutBooks%@NL@%
  3289.                 ELSE%@NL@%
  3290.                         Alert$ = "This book is not checked out"   ' the book wasn't in BooksOut%@NL@%
  3291.                         CALL ShowMessage(Alert$, 0)               ' table, so it wasn't out%@NL@%
  3292.                         DateToShow# = 0: GetStatus = FALSE%@NL@%
  3293.                         EXIT FUNCTION%@NL@%
  3294.                 END IF%@NL@%
  3295.                 DateToShow# = TablesRec.OutBooks.DueDate#%@NL@%
  3296.                 GetStatus = TRUE%@NL@%
  3297. END FUNCTION%@NL@%
  3298. %@NL@%
  3299. %@AB@%'***************************************************************************%@AE@%%@NL@%
  3300. %@AB@%'*  The LendeeProfile takes the IDnum of the currently displayed book, then*%@AE@%%@NL@%
  3301. %@AB@%'*  looks that up in the BooksOut table and fetches the CardHolder record  *%@AE@%%@NL@%
  3302. %@AB@%'*  that corresponds to the CardNum entry in BooksOut. Then the CardNum is *%@AE@%%@NL@%
  3303. %@AB@%'*  looked up in the CardHolders table and the borrower information shown. *%@AE@%%@NL@%
  3304. %@AB@%'*                                Parameters                               *%@AE@%%@NL@%
  3305. %@AB@%'*  TablesRec   Contains information on all the tables in the database     *%@AE@%%@NL@%
  3306. %@AB@%'***************************************************************************%@AE@%%@NL@%
  3307. SUB LendeeProfile (TablesRec AS RecStruct)%@NL@%
  3308. %@AB@%        ' Make sure the CardHolders table actually has records%@AE@%%@NL@%
  3309.         IF LOF(cCardHoldersTableNum) = 0 THEN%@NL@%
  3310.                 CALL ShowMessage("Sorry, there are no cardholder records", 0): SLEEP%@NL@%
  3311.                 EXIT SUB%@NL@%
  3312.         END IF%@NL@%
  3313. %@AB@%        ' Create an array to hold information from CardHolders table%@AE@%%@NL@%
  3314.         DIM LendeeInfo(10)  AS STRING%@NL@%
  3315. %@AB@%        ' Set the index if it is not the one you want%@AE@%%@NL@%
  3316.         IF GETINDEX$(cBooksOutTableNum) <> "IDIndexBO" THEN%@NL@%
  3317.                 SETINDEX cBooksOutTableNum, "IDIndexBO"%@NL@%
  3318.         END IF%@NL@%
  3319.         SEEKEQ cBooksOutTableNum, TablesRec.Inventory.IDnum    ' Seek the record.%@NL@%
  3320.         IF EOF(cBooksOutTableNum) THEN                         ' If you find it,%@NL@%
  3321.                 CALL ShowMessage("This book is not checked out", 0)  ' the book is out,%@NL@%
  3322.                 EXIT SUB                                             ' otherwise not.%@NL@%
  3323.         ELSE                                                   ' If it's there,%@NL@%
  3324.                 RETRIEVE cBooksOutTableNum, TablesRec.OutBooks       ' fetch it.%@NL@%
  3325. %@NL@%
  3326. %@AB@%                ' If the CardNum exists, set an index in CardHolders and SEEK the%@AE@%%@NL@%
  3327. %@AB@%                ' CardNum. If SEEK fails, print a warning; if it succeeds, get the%@AE@%%@NL@%
  3328. %@AB@%                ' information about the borrower, and display it using PeekWindow%@AE@%%@NL@%
  3329. %@NL@%
  3330.                 IF TablesRec.OutBooks.CardNum <> 0 THEN%@NL@%
  3331.                         IF GETINDEX$(cCardHoldersTableNum) <> "CardNumIndexCH" THEN%@NL@%
  3332.                                 SETINDEX cCardHoldersTableNum, "CardNumIndexCH"%@NL@%
  3333.                         END IF%@NL@%
  3334.                         SEEKEQ cCardHoldersTableNum, TablesRec.OutBooks.CardNum%@NL@%
  3335.                         IF EOF(cBooksOutTableNum) THEN%@NL@%
  3336.                                 Alert$ = "Cardholder number associated with book ID is not valid"%@NL@%
  3337.                                 CALL ShowMessage(Alert$, 0)%@NL@%
  3338.                                 EXIT SUB%@NL@%
  3339.                         ELSE%@NL@%
  3340.                                 RETRIEVE cCardHoldersTableNum, TablesRec.Lendee%@NL@%
  3341.                                 LendeeInfo(0) = RTRIM$(TablesRec.Lendee.TheName)%@NL@%
  3342.                                 LendeeInfo(1) = ""%@NL@%
  3343.                                 LendeeInfo(2) = RTRIM$(TablesRec.Lendee.Street)%@NL@%
  3344.                                 LendeeInfo(3) = RTRIM$(TablesRec.Lendee.City)%@NL@%
  3345.                                 LendeeInfo(4) = RTRIM$(TablesRec.Lendee.State)%@NL@%
  3346.                                 LendeeInfo(5) = LTRIM$(STR$(TablesRec.Lendee.Zip))%@NL@%
  3347.                                 LendeeInfo(7) = STR$(TablesRec.Lendee.CardNum)%@NL@%
  3348.                                 LendeeInfo(6) = ""%@NL@%
  3349.                                 LendeeInfo(7) = "Card number: " + LendeeInfo(7)%@NL@%
  3350.                                 LendeeInfo(8) = ""%@NL@%
  3351.                                 FOR Index = 1 TO 6%@NL@%
  3352.                                         ThisBig = LEN(LendeeInfo(Index))%@NL@%
  3353.                                         IF ThisBig > BiggestYet THEN%@NL@%
  3354.                                                 BiggestYet = ThisBig%@NL@%
  3355.                                         END IF%@NL@%
  3356.                                 NEXT Index%@NL@%
  3357.                                 Alert$ = "Press V to access the record for this cardholder"%@NL@%
  3358.                                 CALL ShowMessage(Alert$, 0)%@NL@%
  3359.                                 HeadMessage$ = "Borrower of this Book"%@NL@%
  3360.                                 FootMessage$ = "Press a key to clear box"%@NL@%
  3361.                                 CALL ClearEm(TablesRec.TableNum, 1, 1, 1, 1, 1, 1)%@NL@%
  3362.                                 CALL PeekWindow(LendeeInfo(), HeadMessage$, FootMessage$, BiggestYet)%@NL@%
  3363.                                 CALL DrawTable(TablesRec.TableNum)%@NL@%
  3364.                                 CALL ShowMessage(KEYSMESSAGE, 0)%@NL@%
  3365.                         END IF%@NL@%
  3366.                 END IF%@NL@%
  3367.         END IF%@NL@%
  3368. END SUB%@NL@%
  3369. %@NL@%
  3370. %@AB@%'***************************************************************************%@AE@%%@NL@%
  3371. %@AB@%'* The MakeOver SUB lets the user input the names of properly formatted    *%@AE@%%@NL@%
  3372. %@AB@%'* text files, then creates a database file of the same type as BOOKS.MDB. *%@AE@%%@NL@%
  3373. %@AB@%'* There is also a prompt for the new database name. The text files must   *%@AE@%%@NL@%
  3374. %@AB@%'* contain comma-delimited fields, with strings within double quote marks. *%@AE@%%@NL@%
  3375. %@AB@%'* The last part of this SUB demonstrates how indexes are created. You need*%@AE@%%@NL@%
  3376. %@AB@%'* to have loaded PROISAMD.EXE to run this procedure.                      *%@AE@%%@NL@%
  3377. %@AB@%'*                            Parameters:                                  *%@AE@%%@NL@%
  3378. %@AB@%'*   Big Rec      User-defined type containing all table information       *%@AE@%%@NL@%
  3379. %@AB@%'***************************************************************************%@AE@%%@NL@%
  3380. %@AB@%'%@AE@%%@NL@%
  3381. SUB MakeOver (BigRec AS RecStruct)%@NL@%
  3382.         CLOSE%@NL@%
  3383.         Alert$ = "Type name of file containing Cardholders table data: "%@NL@%
  3384.         CALL ShowMessage(Alert$, 1)%@NL@%
  3385.         INPUT "", CardFile$%@NL@%
  3386.         Alert$ = "Type name of file containing BooksOut table data: "%@NL@%
  3387.         CALL ShowMessage(Alert$, 1)%@NL@%
  3388.         INPUT "", OutBooks$%@NL@%
  3389.         Alert$ = "Type name of file containing BookStock table data: "%@NL@%
  3390.         CALL ShowMessage(Alert$, 1)%@NL@%
  3391.         INPUT "", BookFile$%@NL@%
  3392.         Alert$ = "Type name of ISAM file to create: "%@NL@%
  3393.         CALL ShowMessage(Alert$, 1)%@NL@%
  3394.         INPUT "", IsamFile$%@NL@%
  3395.         IF UCASE$(IsamFile$) = "BOOKS.MDB" THEN KILL "BOOKS.MDB"%@NL@%
  3396.         CALL ShowMessage("Loading database...", 0)%@NL@%
  3397. %@NL@%
  3398.         CLOSE%@NL@%
  3399.         ON LOCAL ERROR GOTO FileHandler%@NL@%
  3400.         LenFileNo% = 10%@NL@%
  3401.         OPEN CardFile$ FOR INPUT AS LenFileNo%%@NL@%
  3402.         OutFileNo% = 11%@NL@%
  3403.         OPEN OutBooks$ FOR INPUT AS OutFileNo%%@NL@%
  3404.         RecFileNo% = 12%@NL@%
  3405.         OPEN BookFile$ FOR INPUT AS RecFileNo%%@NL@%
  3406.         ON ERROR GOTO 0%@NL@%
  3407. %@NL@%
  3408. %@AB@%        ' Open the database and the BookStock table%@AE@%%@NL@%
  3409.         OPEN IsamFile$ FOR ISAM Books "BookStock" AS cBookStockTableNum%@NL@%
  3410.         OPEN IsamFile$ FOR ISAM Borrowers "CardHolders" AS cCardHoldersTableNum%@NL@%
  3411.         OPEN IsamFile$ FOR ISAM BookStatus "BooksOut" AS cBooksOutTableNum%@NL@%
  3412.         CALL ShowMessage(" Opened all isam tables", 0)%@NL@%
  3413. %@NL@%
  3414.         SeqFile% = LenFileNo%@NL@%
  3415.         DO WHILE (Reader%(BigRec, SeqFile%))%@NL@%
  3416.          INSERT cCardHoldersTableNum, BigRec.Lendee%@NL@%
  3417.         LOOP%@NL@%
  3418.         SeqFile% = OutFileNo%@NL@%
  3419.         DO WHILE (Reader%(BigRec, SeqFile))%@NL@%
  3420.          INSERT cBooksOutTableNum, BigRec.OutBooks%@NL@%
  3421.         LOOP%@NL@%
  3422.         SeqFile = RecFileNo%@NL@%
  3423.         DO WHILE (Reader%(BigRec, SeqFile))%@NL@%
  3424.          INSERT cBookStockTableNum, BigRec.Inventory%@NL@%
  3425.         LOOP%@NL@%
  3426.         CALL ShowMessage("Finished reading in records---Indexes next", 0)%@NL@%
  3427. %@AB@%' These indexes are already in the BOOKS.MDB database --- the following%@AE@%%@NL@%
  3428. %@AB@%' is the syntax that was used to create them%@AE@%%@NL@%
  3429. %@NL@%
  3430.         ON LOCAL ERROR GOTO FileHandler%@NL@%
  3431.         CREATEINDEX cBookStockTableNum, "TitleIndexBS", 0, "Title"%@NL@%
  3432.         CREATEINDEX cBookStockTableNum, "AuthorIndexBS", 0, "Author"%@NL@%
  3433.         CREATEINDEX cBookStockTableNum, "PubIndexBS", 0, "Publisher"%@NL@%
  3434.         CREATEINDEX cBookStockTableNum, "IDIndex", 1, "IDnum"     ' Note unique index%@NL@%
  3435.         CREATEINDEX cBookStockTableNum, "BigIndex", 0, "Title", "Author", "IDnum"%@NL@%
  3436. %@NL@%
  3437.         CREATEINDEX cBooksOutTableNum, "IDIndexBO", 0, "IDnum"%@NL@%
  3438.         CREATEINDEX cBooksOutTableNum, "CardNumIndexBO", 0, "CardNum"%@NL@%
  3439. %@NL@%
  3440.         CREATEINDEX cCardHoldersTableNum, "NameIndexCH", 0, "TheName"%@NL@%
  3441.         CREATEINDEX cCardHoldersTableNum, "StateIndexCH", 0, "State"%@NL@%
  3442.         CREATEINDEX cCardHoldersTableNum, "ZipIndexCH", 0, "Zip"%@NL@%
  3443.         CREATEINDEX cCardHoldersTableNum, "CardNumIndexCH", 1, "CardNum"  ' Unique index%@NL@%
  3444.         ON ERROR GOTO 0%@NL@%
  3445.         CALL ShowMessage(" All done with indexes...", 0)%@NL@%
  3446. %@AB@%        'CLOSE%@AE@%%@NL@%
  3447. %@NL@%
  3448.         EXIT SUB%@NL@%
  3449. %@NL@%
  3450. FileHandler:%@NL@%
  3451.         IF ERR = 73 THEN%@NL@%
  3452.                 CALL ShowMessage("You need to Exit QBX and load PROISAMD /Ib:24 /Ii:16", 0)%@NL@%
  3453.         ELSEIF ERR = 10 THEN%@NL@%
  3454.                 Alert$ = "Finished appending the records to " + IsamFile$%@NL@%
  3455.                 CALL ShowMessage(Alert$, 0)%@NL@%
  3456.                 END%@NL@%
  3457.         ELSEIF ERR = 86 THEN%@NL@%
  3458.                 Alert$ = "Tried to add record with duplicate value on a unique index"%@NL@%
  3459.                 CALL ShowMessage(Alert$, 0)%@NL@%
  3460.                 ELSE%@NL@%
  3461.                 CALL ShowMessage("Can't find textfiles needed to make the database", 0)%@NL@%
  3462.         END IF%@NL@%
  3463.         END%@NL@%
  3464. END SUB%@NL@%
  3465. %@NL@%
  3466. %@AB@%'***************************************************************************%@AE@%%@NL@%
  3467. %@AB@%'*  The PeekWindow SUB displays the elements of the OutBookNames array in  *%@AE@%%@NL@%
  3468. %@AB@%'*  a window on top of the currently displayed table.                      *%@AE@%%@NL@%
  3469. %@AB@%'*                                Parameters                               *%@AE@%%@NL@%
  3470. %@AB@%'*  OutBookNames    Array of strings containing lines displayed in window  *%@AE@%%@NL@%
  3471. %@AB@%'*  Header$         String to show at top of window                        *%@AE@%%@NL@%
  3472. %@AB@%'*  Footer$         String to show at bottom of window                     *%@AE@%%@NL@%
  3473. %@AB@%'*  BiggestYet      Length of the longest string to be shown               *%@AE@%%@NL@%
  3474. %@AB@%'***************************************************************************%@AE@%%@NL@%
  3475. SUB PeekWindow (OutBookNames() AS STRING, Header$, Footer$, BiggestYet%)%@NL@%
  3476. HeadLen = LEN(Header$)        ' + 4%@NL@%
  3477. FootLen = LEN(Footer$)        ' + 4%@NL@%
  3478. IF HeadLen > FootLen THEN Bigger = HeadLen ELSE Bigger = FootLen%@NL@%
  3479. IF Bigger > BiggestYet THEN BiggestYet = Bigger%@NL@%
  3480. %@NL@%
  3481. InnerBox = 9          ' InnerBox is total number of lines allowed inside box%@NL@%
  3482. first = 0: last = 8%@NL@%
  3483. DO%@NL@%
  3484. %@NL@%
  3485. %@AB@%        ' Calculate header and footer placement%@AE@%%@NL@%
  3486. %@NL@%
  3487.                 IF (HeadLen MOD 2) THEN%@NL@%
  3488.                         HeadStart = ((BiggestYet - HeadLen) \ 2) + 13%@NL@%
  3489.                 ELSE%@NL@%
  3490.                         HeadStart = ((BiggestYet - HeadLen) \ 2) + 12%@NL@%
  3491.                 END IF%@NL@%
  3492.                 IF (FootLen MOD 2) THEN%@NL@%
  3493.                         FootStart = ((BiggestYet - FootLen) \ 2) + 13%@NL@%
  3494.                 ELSE%@NL@%
  3495.                         FootStart = ((BiggestYet - FootLen) \ 2) + 12%@NL@%
  3496.                 END IF%@NL@%
  3497. %@NL@%
  3498. %@AB@%                ' Print a box and fill it with titles%@AE@%%@NL@%
  3499.                 Inset = TABLETOP + 2%@NL@%
  3500. %@NL@%
  3501.                 Lines = Inset + 1%@NL@%
  3502.                 IF MoreBoxes = FALSE THEN%@NL@%
  3503.                         LOCATE Inset, 3%@NL@%
  3504.                         PRINT "       ╔"; STRING$(BiggestYet + 2, CHR$(205)); "╗"%@NL@%
  3505.                 END IF%@NL@%
  3506.                 FOR PrintEm = first TO last%@NL@%
  3507.                         LOCATE Lines + NextSpace, 3%@NL@%
  3508.                         PRINT "       ║ "; OutBookNames(Total); SPACE$(BiggestYet - LEN((OutBookNames(Total)))); " ║"%@NL@%
  3509.                         Total = Total + 1: NextSpace = NextSpace + 1%@NL@%
  3510.                 NEXT PrintEm%@NL@%
  3511.                 IF MoreBoxes = FALSE THEN                       ' Means first group%@NL@%
  3512.                         LOCATE Lines + NextSpace, 3%@NL@%
  3513.                         PRINT "       ╚"; STRING$(BiggestYet + 2, CHR$(205)); "╝"%@NL@%
  3514.                         COLOR BACKGROUND, FOREGROUND + BRIGHT%@NL@%
  3515.                         LOCATE Inset, HeadStart%@NL@%
  3516.                         PRINT Header$;                          '"╡ "; Header$; " ╞"%@NL@%
  3517.                         LOCATE Lines + NextSpace, FootStart%@NL@%
  3518.                         PRINT Footer$                           '"╡ "; Footer$; " ╞"%@NL@%
  3519.                         COLOR FOREGROUND, BACKGROUND%@NL@%
  3520.                 END IF%@NL@%
  3521.                 SLEEP%@NL@%
  3522.         first = first + InnerBox: last = last + InnerBox%@NL@%
  3523.         NextSpace = 0: HowMany = 0%@NL@%
  3524. %@NL@%
  3525.         MoreBoxes = TRUE%@NL@%
  3526. %@NL@%
  3527. LOOP UNTIL LEN(RTRIM$(OutBookNames(Total))) = 0%@NL@%
  3528. %@NL@%
  3529. END SUB%@NL@%
  3530. %@NL@%
  3531. %@AB@%'***************************************************************************%@AE@%%@NL@%
  3532. %@AB@%'*  The Reader FUNCTION reads specified text files and returns each line   *%@AE@%%@NL@%
  3533. %@AB@%'*  as a separate record for the corresponding table.                      *%@AE@%%@NL@%
  3534. %@AB@%'*                               Parameters                                *%@AE@%%@NL@%
  3535. %@AB@%'*  BigRec    RecStruct variable containing information on tables          *%@AE@%%@NL@%
  3536. %@AB@%'*  SeqFile   File number used to open the text file to be read%@AE@%%@NL@%
  3537. %@AB@%'***************************************************************************%@AE@%%@NL@%
  3538. FUNCTION Reader% (BigRec AS RecStruct, SeqFile%)%@NL@%
  3539.         SELECT CASE SeqFile%@NL@%
  3540.                 CASE 10%@NL@%
  3541.                         IF NOT EOF(SeqFile) THEN%@NL@%
  3542.                          INPUT #SeqFile, BigRec.Lendee.CardNum, BigRec.Lendee.Zip, BigRec.Lendee.TheName, BigRec.Lendee.City, BigRec.Lendee.Street, BigRec.Lendee.State%@NL@%
  3543.                          Reader = -1%@NL@%
  3544.                         ELSE%@NL@%
  3545.                                 Reader = 0%@NL@%
  3546.                         END IF%@NL@%
  3547.                 CASE 11%@NL@%
  3548.                         IF NOT EOF(SeqFile) THEN%@NL@%
  3549.                          INPUT #SeqFile, BigRec.OutBooks.IDnum, BigRec.OutBooks.CardNum, BigRec.OutBooks.DueDate%@NL@%
  3550.                          Reader = -1%@NL@%
  3551.                         ELSE%@NL@%
  3552.                          Reader = 0%@NL@%
  3553.                         END IF%@NL@%
  3554.                 CASE 12%@NL@%
  3555.                         IF NOT EOF(SeqFile) THEN%@NL@%
  3556.                                 INPUT #SeqFile, BigRec.Inventory.IDnum, BigRec.Inventory.Price, BigRec.Inventory.Edition, BigRec.Inventory.Title, BigRec.Inventory.Author, BigRec.Inventory.Publisher%@NL@%
  3557.                                 Reader = -1%@NL@%
  3558.                          ELSE%@NL@%
  3559.                                 Reader = 0%@NL@%
  3560.                          END IF%@NL@%
  3561.         END SELECT%@NL@%
  3562. END FUNCTION%@NL@%
  3563. %@NL@%
  3564. %@AB@%'***************************************************************************%@AE@%%@NL@%
  3565. %@AB@%'*  The ReturnBook SUB checks the book currently being displayed back into *%@AE@%%@NL@%
  3566. %@AB@%'*  the library --- that is, it eliminates the appropriate entry from the  *%@AE@%%@NL@%
  3567. %@AB@%'*  BooksOut table. It checks to see if the book is overdue, and if so, it *%@AE@%%@NL@%
  3568. %@AB@%'*  displays the amount of the fine to be paid.                            *%@AE@%%@NL@%
  3569. %@AB@%'*                                Parameters                               *%@AE@%%@NL@%
  3570. %@AB@%'*  TablesRec   RecStruct type variable holding current table information  *%@AE@%%@NL@%
  3571. %@AB@%'***************************************************************************%@AE@%%@NL@%
  3572. SUB ReturnBook (TablesRec AS RecStruct, DueDate#)%@NL@%
  3573. %@NL@%
  3574. DIM ReturnLines(10) AS STRING%@NL@%
  3575. %@NL@%
  3576. Alert$ = "Press ENTER to check current book in, N to abort checkin..."%@NL@%
  3577. CALL ShowMessage(Alert$, 0)%@NL@%
  3578. %@NL@%
  3579. SETINDEX cBooksOutTableNum, "IDIndexBO"%@NL@%
  3580. SEEKEQ cBooksOutTableNum, TablesRec.Inventory.IDnum%@NL@%
  3581. IF NOT EOF(cBooksOutTableNum) THEN%@NL@%
  3582.         RETRIEVE cBooksOutTableNum, TablesRec.OutBooks%@NL@%
  3583. END IF%@NL@%
  3584. SETINDEX cCardHoldersTableNum, "CardNumIndexCH"%@NL@%
  3585. SEEKEQ cCardHoldersTableNum, TablesRec.OutBooks.CardNum%@NL@%
  3586. %@NL@%
  3587. IF NOT EOF(cBooksOutTableNum) THEN%@NL@%
  3588.         IF LOF(cCardHoldersTableNum) THEN%@NL@%
  3589.                 RETRIEVE cCardHoldersTableNum, TablesRec.Lendee%@NL@%
  3590.         END IF%@NL@%
  3591. END IF%@NL@%
  3592. %@NL@%
  3593. Today# = 32000    'Replace this with call to DTFMTER.QLB library routine%@NL@%
  3594. %@AB@%                                                                        'as shown on the next 2 lines%@AE@%%@NL@%
  3595. %@AB@%'Today# = Now#%@AE@%%@NL@%
  3596. %@AB@%'ShowDate$ = STR$(Month&(Today#)) + "/" + LTRIM$(STR$(Day&(Today#))) + "/" + LTRIM$(STR$(Year&(Today#)))%@AE@%%@NL@%
  3597. IF Today# > TablesRec.OutBooks.DueDate THEN%@NL@%
  3598.         Fine = Today# - TablesRec.OutBooks.DueDate%@NL@%
  3599. END IF%@NL@%
  3600. %@NL@%
  3601. DateDue# = (TablesRec.OutBooks.DueDate)%@NL@%
  3602. %@AB@%' If you have DTFMTER.QLB loaded, use in to get date to display%@AE@%%@NL@%
  3603. %@AB@%' DateDue$ = STR$(Month&(DateDue#)) + "/" + LTRIM$(STR$(Day&(DateDue#))) + "/" + LTRIM$(STR$(Year&(DateDue#)))%@AE@%%@NL@%
  3604. ReturnLines(0) = ""%@NL@%
  3605. ReturnLines(1) = RTRIM$(TablesRec.Inventory.Title)%@NL@%
  3606. ReturnLines(2) = "is checked out to card number: " + STR$(TablesRec.OutBooks.CardNum)%@NL@%
  3607. ReturnLines(3) = RTRIM$(TablesRec.Lendee.TheName)%@NL@%
  3608. ReturnLines(4) = ""%@NL@%
  3609. ReturnLines(5) = "Today's Date:     " + STR$(Today#) + " - A phoney date"%@NL@%
  3610. IF LEN(ShowDate$) THEN ReturnLines(5) = "Today's Date:     " + ShowDate$%@NL@%
  3611. ReturnLines(6) = "Due Date of Book: " + STR$(TablesRec.OutBooks.DueDate)%@NL@%
  3612. IF LEN(DateDue$) THEN ReturnLines(6) = "Due Date of Book: " + DateDue$%@NL@%
  3613. ReturnLines(7) = "Fine Payable:     $" + STR$(ABS(Fine / 100))%@NL@%
  3614. ReturnLines(8) = ""%@NL@%
  3615. ReturnLines(9) = ""%@NL@%
  3616. FOR Index = 0 TO 10%@NL@%
  3617.         ThisOne = LEN(ReturnLines(Index))%@NL@%
  3618.         IF ThisOne > BiggestYet THEN BiggestYet = ThisOne%@NL@%
  3619. NEXT Index%@NL@%
  3620. Header$ = "Press ENTER to check book in..."%@NL@%
  3621. Footer$ = "Press N or n to abort checkin..."%@NL@%
  3622. CALL PeekWindow(ReturnLines(), Header$, Footer$, BiggestYet%)%@NL@%
  3623. %@NL@%
  3624. IF CatchKey THEN                              ' If user confirms, delete%@NL@%
  3625.         IF LOF(cBooksOutTableNum) <> 0 THEN         ' the entry to BooksOut table%@NL@%
  3626.                 DELETE cBooksOutTableNum%@NL@%
  3627.         END IF%@NL@%
  3628. END IF%@NL@%
  3629. CALL DrawTable(TablesRec.TableNum)%@NL@%
  3630. CALL EraseMessage%@NL@%
  3631. %@NL@%
  3632. END SUB%@NL@%
  3633. %@NL@%
  3634. %@AB@%'***************************************************************************%@AE@%%@NL@%
  3635. %@AB@%'* The ShowStatus SUB uses the due date associated with the book IDnum from*%@AE@%%@NL@%
  3636. %@AB@%'* of the BooksOut table. This date is in serial form which is not decoded *%@AE@%%@NL@%
  3637. %@AB@%'* here, but can be decoded with the date/time function library supplied   *%@AE@%%@NL@%
  3638. %@AB@%'* with BASIC 7.0. The due date is displayed centered on the top line of   *%@AE@%%@NL@%
  3639. %@AB@%'* the ShowMessage box.                                                    *%@AE@%%@NL@%
  3640. %@AB@%'*                                Parameters                               *%@AE@%%@NL@%
  3641. %@AB@%'*  Stat$       Message introducing the due date when displayed in its box *%@AE@%%@NL@%
  3642. %@AB@%'*  ValueToShow The due date of the book from the BooksOut table           *%@AE@%%@NL@%
  3643. %@AB@%'***************************************************************************%@AE@%%@NL@%
  3644. SUB ShowStatus (Stat$, ValueToShow AS DOUBLE)%@NL@%
  3645. %@NL@%
  3646. COLOR FOREGROUND, BACKGROUND%@NL@%
  3647. DataEndLine$ = STRING$(60, 205)       'redraw the bottom line%@NL@%
  3648. %@NL@%
  3649. StringToShow$ = Stat$       ' Figure out where to locate the text%@NL@%
  3650. IF ValueToShow = 0 THEN%@NL@%
  3651.         LOCATE TABLEEND, 4%@NL@%
  3652.         PRINT DataEndLine$%@NL@%
  3653.         EXIT SUB%@NL@%
  3654. ELSE%@NL@%
  3655. %@AB@%        ' The dates in the file are in serial form. Use the DTFMTER.QLB library%@AE@%%@NL@%
  3656. %@AB@%        ' to decode serial dates for normal display. In the code below, the%@AE@%%@NL@%
  3657. %@AB@%        ' calls to the library are commented out.%@AE@%%@NL@%
  3658. %@NL@%
  3659. %@AB@%        'TheDate$ = STR$(Month&(ValueToShow)) + "/" + LTRIM$(STR$(Day&(ValueToShow))) + "/" + LTRIM$(STR$(Year&(ValueToShow)))%@AE@%%@NL@%
  3660.         IF Stat$ = " Total records in table: " OR LEN(TheDate$) = 0 THEN%@NL@%
  3661.                 StringToShow$ = StringToShow$ + " " + STR$(ValueToShow)%@NL@%
  3662.         ELSE%@NL@%
  3663.                 StringToShow$ = StringToShow$ + " " + TheDate$%@NL@%
  3664.         END IF%@NL@%
  3665.         HowLong = LEN(StringToShow$)%@NL@%
  3666.         PlaceStatus = (73 \ 2) - (HowLong \ 2)%@NL@%
  3667.         StatusSpace$ = CHR$(181) + STRING$(HowLong, 32) + CHR$(198)%@NL@%
  3668. END IF%@NL@%
  3669. LOCATE TABLEEND, PlaceStatus%@NL@%
  3670. PRINT StatusSpace$%@NL@%
  3671. COLOR BACKGROUND, BRIGHT + FOREGROUND%@NL@%
  3672. LOCATE TABLEEND, PlaceStatus + 1%@NL@%
  3673. PRINT StringToShow$%@NL@%
  3674. COLOR FOREGROUND, BACKGROUND%@NL@%
  3675. %@NL@%
  3676. END SUB%@NL@%
  3677. %@NL@%
  3678. %@NL@%
  3679. %@NL@%
  3680. %@2@%%@AH@%CAL.BAS%@AE@%%@EH@%%@NL@%
  3681. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\CAL.BAS%@AE@%%@NL@%
  3682. %@NL@%
  3683. DEFINT A-Z      ' Default variable type is integer.%@NL@%
  3684. %@NL@%
  3685. %@AB@%' Define a data type for the names of the months and the%@AE@%%@NL@%
  3686. %@AB@%' number of days in each:%@AE@%%@NL@%
  3687. TYPE MonthType%@NL@%
  3688.         Number AS INTEGER  ' Number of days in the month%@NL@%
  3689.         MName AS STRING * 9   ' Name  of the month%@NL@%
  3690. END TYPE%@NL@%
  3691. %@NL@%
  3692. %@AB@%' Declare procedures used:%@AE@%%@NL@%
  3693. DECLARE FUNCTION IsLeapYear% (N%)%@NL@%
  3694. DECLARE FUNCTION GetInput% (Prompt$, Row%, LowVal%, HighVal%)%@NL@%
  3695. %@NL@%
  3696. DECLARE SUB PrintCalendar (Year%, Month%)%@NL@%
  3697. DECLARE SUB ComputeMonth (Year%, Month%, StartDay%, TotalDays%)%@NL@%
  3698. %@NL@%
  3699. DIM MonthData(1 TO 12)   AS MonthType%@NL@%
  3700. %@NL@%
  3701. %@AB@%' Initialize month definitions from DATA statements below:%@AE@%%@NL@%
  3702. FOR I = 1 TO 12%@NL@%
  3703.         READ MonthData(I).MName, MonthData(I).Number%@NL@%
  3704. NEXT%@NL@%
  3705. %@NL@%
  3706. %@AB@%' Main loop, repeat for as many months as desired:%@AE@%%@NL@%
  3707. DO%@NL@%
  3708.         CLS%@NL@%
  3709. %@NL@%
  3710. %@AB@%        ' Get year and month as input:%@AE@%%@NL@%
  3711.         Year = GetInput("Year (1899 to 2099): ", 1, 1899, 2099)%@NL@%
  3712.         Month = GetInput("Month (1 to 12): ", 2, 1, 12)%@NL@%
  3713. %@NL@%
  3714. %@AB@%        ' Print the calendar:%@AE@%%@NL@%
  3715.         PrintCalendar Year, Month%@NL@%
  3716. %@AB@%' Another Date?%@AE@%%@NL@%
  3717.         LOCATE 13, 1      ' Locate in 13th row, 1st column.%@NL@%
  3718.         PRINT "New Date? ";  ' Keep cursor on same line.%@NL@%
  3719.         LOCATE , , 1, 0, 13  ' Turn cursor on and make it one%@NL@%
  3720. %@AB@%                        ' character high.%@AE@%%@NL@%
  3721.         Resp$ = INPUT$(1) ' Wait for a key press.%@NL@%
  3722.         PRINT Resp$    ' Print  the key  pressed.%@NL@%
  3723. %@NL@%
  3724. LOOP WHILE UCASE$(Resp$) = "Y"%@NL@%
  3725. END%@NL@%
  3726. %@NL@%
  3727. %@AB@%' Data for the months of a year:%@AE@%%@NL@%
  3728. DATA January, 31, February, 28,  March, 31%@NL@%
  3729. DATA April, 30,   May, 31, June, 30, July, 31, August, 31%@NL@%
  3730. DATA September,   30, October, 31, November, 30, December, 31%@NL@%
  3731. %@NL@%
  3732. %@AB@%' ====================== COMPUTEMONTH =====================%@AE@%%@NL@%
  3733. %@AB@%'  Computes the first day and the total days in a month%@AE@%%@NL@%
  3734. %@AB@%' =========================================================%@AE@%%@NL@%
  3735. %@AB@%'%@AE@%%@NL@%
  3736. SUB ComputeMonth (Year, Month, StartDay, TotalDays) STATIC%@NL@%
  3737.         SHARED MonthData() AS MonthType%@NL@%
  3738. %@NL@%
  3739.         CONST LEAP = 366 MOD 7%@NL@%
  3740.         CONST NORMAL = 365 MOD 7%@NL@%
  3741. %@NL@%
  3742. %@AB@%        ' Calculate total number of days (NumDays) since 1/1/1899:%@AE@%%@NL@%
  3743. %@NL@%
  3744. %@AB@%        ' Start with whole years:%@AE@%%@NL@%
  3745.         NumDays = 0%@NL@%
  3746.         FOR I = 1899 TO Year - 1%@NL@%
  3747.                 IF IsLeapYear(I) THEN              ' If leap year,%@NL@%
  3748.                         NumDays = NumDays + LEAP   ' add 366 MOD 7.%@NL@%
  3749.                 ELSE                               ' If normal year,%@NL@%
  3750.                         NumDays = NumDays + NORMAL ' add 365 MOD 7.%@NL@%
  3751.                 END IF%@NL@%
  3752.         NEXT%@NL@%
  3753. %@NL@%
  3754. %@AB@%        ' Next, add in days from whole months:%@AE@%%@NL@%
  3755.         FOR I = 1 TO Month - 1%@NL@%
  3756.                 NumDays = NumDays + MonthData(I).Number%@NL@%
  3757.         NEXT%@NL@%
  3758. %@NL@%
  3759. %@AB@%        ' Set the number of days in the requested month:%@AE@%%@NL@%
  3760.         TotalDays = MonthData(Month).Number%@NL@%
  3761. %@NL@%
  3762. %@AB@%        ' Compensate if requested year is a leap year:%@AE@%%@NL@%
  3763.         IF IsLeapYear(Year) THEN%@NL@%
  3764. %@NL@%
  3765. %@AB@%                ' If after February, add one to total days:%@AE@%%@NL@%
  3766.                 IF Month > 2 THEN%@NL@%
  3767.                         NumDays = NumDays + 1%@NL@%
  3768. %@NL@%
  3769. %@AB@%                ' If February, add one to the month's days:%@AE@%%@NL@%
  3770.                 ELSEIF Month = 2 THEN%@NL@%
  3771.                         TotalDays = TotalDays + 1%@NL@%
  3772.                 END IF%@NL@%
  3773.         END IF%@NL@%
  3774. %@NL@%
  3775. %@AB@%        ' 1/1/1899 was a Sunday, so calculating "NumDays MOD 7"%@AE@%%@NL@%
  3776. %@AB@%        ' gives the day of week (Sunday = 0, Monday = 1, Tuesday%@AE@%%@NL@%
  3777. %@AB@%        ' = 2, and so on) for the first day of the input month:%@AE@%%@NL@%
  3778.         StartDay = NumDays MOD 7%@NL@%
  3779. END SUB%@NL@%
  3780. %@NL@%
  3781. %@AB@%' ======================== GETINPUT =======================%@AE@%%@NL@%
  3782. %@AB@%'  Prompts for input, then tests for a valid range%@AE@%%@NL@%
  3783. %@AB@%' =========================================================%@AE@%%@NL@%
  3784. %@AB@%'%@AE@%%@NL@%
  3785. FUNCTION GetInput (Prompt$, Row, LowVal, HighVal) STATIC%@NL@%
  3786. %@NL@%
  3787. %@AB@%        ' Locate prompt at specified row, turn cursor on and%@AE@%%@NL@%
  3788. %@AB@%        ' make it one character high:%@AE@%%@NL@%
  3789.         LOCATE Row, 1, 1, 0, 13%@NL@%
  3790.         PRINT Prompt$;%@NL@%
  3791. %@NL@%
  3792. %@AB@%        ' Save column position:%@AE@%%@NL@%
  3793.         Column = POS(0)%@NL@%
  3794. %@NL@%
  3795. %@AB@%        ' Input value until it's within range:%@AE@%%@NL@%
  3796.         DO%@NL@%
  3797.                 LOCATE Row, Column   ' Locate cursor at end of prompt.%@NL@%
  3798.                 PRINT SPACE$(10)     ' Erase anything already there.%@NL@%
  3799.                 LOCATE Row, Column   ' Relocate cursor at end of prompt.%@NL@%
  3800.                 INPUT "", Value      ' Input value with no prompt.%@NL@%
  3801.         LOOP WHILE (Value < LowVal OR Value > HighVal)%@NL@%
  3802. %@NL@%
  3803. %@AB@%        ' Return valid input as value of function:%@AE@%%@NL@%
  3804.         GetInput = Value%@NL@%
  3805. %@NL@%
  3806. END FUNCTION%@NL@%
  3807. %@NL@%
  3808. %@AB@%' ====================== ISLEAPYEAR =======================%@AE@%%@NL@%
  3809. %@AB@%'   Determines if a year is a leap year or not%@AE@%%@NL@%
  3810. %@AB@%' =========================================================%@AE@%%@NL@%
  3811. %@AB@%'%@AE@%%@NL@%
  3812. FUNCTION IsLeapYear (N) STATIC%@NL@%
  3813. %@NL@%
  3814. %@AB@%        ' If the year is evenly divisible by 4 and not divisible%@AE@%%@NL@%
  3815. %@AB@%        ' by 100, or if the year is evenly divisible by 400,%@AE@%%@NL@%
  3816. %@AB@%        ' then it's a leap year:%@AE@%%@NL@%
  3817.         IsLeapYear = (N MOD 4 = 0 AND N MOD 100 <> 0) OR (N MOD 400 = 0)%@NL@%
  3818. END FUNCTION%@NL@%
  3819. %@NL@%
  3820. %@AB@%' ===================== PRINTCALENDAR =====================%@AE@%%@NL@%
  3821. %@AB@%'   Prints a formatted calendar given the year and month%@AE@%%@NL@%
  3822. %@AB@%' =========================================================%@AE@%%@NL@%
  3823. %@AB@%'%@AE@%%@NL@%
  3824. SUB PrintCalendar (Year, Month) STATIC%@NL@%
  3825. SHARED MonthData() AS MonthType%@NL@%
  3826. %@NL@%
  3827. %@AB@%        ' Compute starting day (Su M Tu ...)%@AE@%%@NL@%
  3828. %@AB@%        ' and total days for the month:%@AE@%%@NL@%
  3829.         ComputeMonth Year, Month, StartDay, TotalDays%@NL@%
  3830.         CLS%@NL@%
  3831.         Header$ = RTRIM$(MonthData(Month).MName) + "," + STR$(Year)%@NL@%
  3832. %@NL@%
  3833. %@AB@%        ' Calculate location for centering month and year:%@AE@%%@NL@%
  3834.         LeftMargin = (35 - LEN(Header$)) \ 2%@NL@%
  3835. %@AB@%' Print header:%@AE@%%@NL@%
  3836.         PRINT TAB(LeftMargin); Header$%@NL@%
  3837.         PRINT%@NL@%
  3838.         PRINT "Su    M   Tu    W   Th    F   Sa"%@NL@%
  3839.         PRINT%@NL@%
  3840. %@NL@%
  3841. %@AB@%        ' Recalculate and print tab%@AE@%%@NL@%
  3842. %@AB@%        ' to the first day of the month (Su M Tu ...):%@AE@%%@NL@%
  3843.         LeftMargin = 5 * StartDay + 1%@NL@%
  3844.         PRINT TAB(LeftMargin);%@NL@%
  3845. %@NL@%
  3846. %@AB@%        ' Print out the days of the month:%@AE@%%@NL@%
  3847.         FOR I = 1 TO TotalDays%@NL@%
  3848.                 PRINT USING "##_   "; I;%@NL@%
  3849. %@NL@%
  3850. %@AB@%                ' Advance to the next line%@AE@%%@NL@%
  3851. %@AB@%                ' when the cursor is past column 32:%@AE@%%@NL@%
  3852.                 IF POS(0) > 32 THEN PRINT%@NL@%
  3853.         NEXT%@NL@%
  3854. %@NL@%
  3855. END SUB%@NL@%
  3856. %@NL@%
  3857. %@NL@%
  3858. %@NL@%
  3859. %@2@%%@AH@%CHECK.BAS%@AE@%%@EH@%%@NL@%
  3860. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\CHECK.BAS%@AE@%%@NL@%
  3861. %@NL@%
  3862. DIM Amount(1 TO 100) AS CURRENCY, Balance AS CURRENCY%@NL@%
  3863. CONST FALSE = 0, TRUE = NOT FALSE%@NL@%
  3864. CLS%@NL@%
  3865. %@AB@%' Get account's starting balance:%@AE@%%@NL@%
  3866. INPUT "Type starting balance, then press <ENTER>: ", Balance%@NL@%
  3867. %@AB@%' Get transactions. Continue accepting input%@AE@%%@NL@%
  3868. %@AB@%' until the input is zero for a transaction,%@AE@%%@NL@%
  3869. %@AB@%' or until 100 transactions have been entered:%@AE@%%@NL@%
  3870. FOR TransacNum% = 1 TO 100%@NL@%
  3871.    PRINT TransacNum%;%@NL@%
  3872.    PRINT ") Enter transaction amount (0 to end): ";%@NL@%
  3873.    INPUT "", Amount(TransacNum%)%@NL@%
  3874.    IF Amount(TransacNum%) = 0 THEN%@NL@%
  3875.       TransacNum% = TransacNum% - 1%@NL@%
  3876.       EXIT FOR%@NL@%
  3877.    END IF%@NL@%
  3878. NEXT%@NL@%
  3879. %@NL@%
  3880. %@AB@%' Sort transactions in ascending order,%@AE@%%@NL@%
  3881. %@AB@%' using a "bubble sort":%@AE@%%@NL@%
  3882. Limit% = TransacNum%%@NL@%
  3883. DO%@NL@%
  3884.    Swaps% = FALSE%@NL@%
  3885.    FOR I% = 1 TO (Limit% - 1)%@NL@%
  3886. %@AB@%      ' If two adjacent elements are out of order,%@AE@%%@NL@%
  3887. %@AB@%      ' switch those elements:%@AE@%%@NL@%
  3888.       IF Amount(I%) < Amount(I% + 1) THEN%@NL@%
  3889.          SWAP Amount(I%), Amount(I% + 1)%@NL@%
  3890.          Swaps% = I%%@NL@%
  3891.       END IF%@NL@%
  3892.    NEXT I%%@NL@%
  3893. %@AB@%  ' Sort on next pass only to where last switch was made:%@AE@%%@NL@%
  3894.   Limit% = Swaps%%@NL@%
  3895. %@NL@%
  3896. %@AB@%' Sort until no elements are exchanged:%@AE@%%@NL@%
  3897. LOOP WHILE Swaps%%@NL@%
  3898. %@AB@%' Print the sorted transaction array. If a transaction%@AE@%%@NL@%
  3899. %@AB@%' is greater than zero, print it as a "CREDIT"; if a%@AE@%%@NL@%
  3900. %@AB@%' transaction is less than zero, print it as a "DEBIT":%@AE@%%@NL@%
  3901. FOR I% = 1 TO TransacNum%%@NL@%
  3902.    IF Amount(I%) > 0 THEN%@NL@%
  3903.       PRINT USING "CREDIT: $$#####.##"; Amount(I%)%@NL@%
  3904.    ELSEIF Amount(I%) < 0 THEN%@NL@%
  3905.       PRINT USING "DEBIT: $$#####.##"; Amount(I%)%@NL@%
  3906.    END IF%@NL@%
  3907. %@AB@%   ' Update balance:%@AE@%%@NL@%
  3908.    Balance = Balance + Amount(I%)%@NL@%
  3909. NEXT I%%@NL@%
  3910. %@AB@%' Print the final balance:%@AE@%%@NL@%
  3911. PRINT%@NL@%
  3912. PRINT "--------------------------"%@NL@%
  3913. PRINT USING "Final Balance: $$######.##"; Balance%@NL@%
  3914. END%@NL@%
  3915. %@NL@%
  3916. %@NL@%
  3917. %@NL@%
  3918. %@2@%%@AH@%CHRTASM.ASM%@AE@%%@EH@%%@NL@%
  3919. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\CHRTASM.ASM%@AE@%%@NL@%
  3920. %@NL@%
  3921. .MODEL medium%@NL@%
  3922. %@AB@%;********************************************************%@AE@%%@NL@%
  3923. %@AB@%;CHRTASM.ASM - assembly routines for the BASIC chart toolbox%@AE@%%@NL@%
  3924. %@AB@%;%@AE@%%@NL@%
  3925. %@AB@%;  Copyright (C) 1989 Microsoft Corporation, All Rights Reserved%@AE@%%@NL@%
  3926. %@AB@%;%@AE@%%@NL@%
  3927. %@AB@%;   DefaultFont - provides the segment:offset address for%@AE@%%@NL@%
  3928. %@AB@%;                  the default font%@AE@%%@NL@%
  3929. %@AB@%;%@AE@%%@NL@%
  3930. %@AB@%;********************************************************%@AE@%%@NL@%
  3931. %@NL@%
  3932. .FARDATA%@NL@%
  3933. _IBM8_def label byte%@NL@%
  3934. %@NL@%
  3935.       db   000h,000h,07Eh,00Ch,000h,000h,000h,000h%@NL@%
  3936.       db   000h,000h,000h,000h,000h,000h,000h,000h%@NL@%
  3937.       db   000h,000h,000h,000h,000h,000h,000h,000h%@NL@%
  3938.       db   000h,000h,000h,000h,000h,000h,000h,000h%@NL@%
  3939.       db   000h,000h,000h,000h,000h,000h,000h,000h%@NL@%
  3940.       db   000h,000h,000h,000h,000h,000h,000h,000h%@NL@%
  3941.       db   000h,000h,000h,000h,000h,000h,000h,000h%@NL@%
  3942.       db   000h,000h,000h,000h,000h,000h,000h,000h%@NL@%
  3943.       db   000h,000h,000h,000h,008h,000h,030h,000h%@NL@%
  3944.       db   060h,000h,007h,000h,000h,000h,000h,000h%@NL@%
  3945.       db   000h,000h,000h,090h,001h,000h,008h,000h%@NL@%
  3946.       db   008h,000h,000h,008h,000h,008h,000h,000h%@NL@%
  3947.       db   0FFh,02Eh,020h,0FFh,000h,000h,000h,000h%@NL@%
  3948.       db   000h,07Ah,004h,000h,000h,000h,000h,000h%@NL@%
  3949.       db   000h,07Eh,004h,000h,000h,000h,008h,000h%@NL@%
  3950.       db   07Eh,004h,008h,000h,086h,004h,008h,000h%@NL@%
  3951.       db   08Eh,004h,008h,000h,096h,004h,008h,000h%@NL@%
  3952.       db   09Eh,004h,008h,000h,0A6h,004h,008h,000h%@NL@%
  3953.       db   0AEh,004h,008h,000h,0B6h,004h,008h,000h%@NL@%
  3954.       db   0BEh,004h,008h,000h,0C6h,004h,008h,000h%@NL@%
  3955.       db   0CEh,004h,008h,000h,0D6h,004h,008h,000h%@NL@%
  3956.       db   0DEh,004h,008h,000h,0E6h,004h,008h,000h%@NL@%
  3957.       db   0EEh,004h,008h,000h,0F6h,004h,008h,000h%@NL@%
  3958.       db   0FEh,004h,008h,000h,006h,005h,008h,000h%@NL@%
  3959.       db   00Eh,005h,008h,000h,016h,005h,008h,000h%@NL@%
  3960.       db   01Eh,005h,008h,000h,026h,005h,008h,000h%@NL@%
  3961.       db   02Eh,005h,008h,000h,036h,005h,008h,000h%@NL@%
  3962.       db   03Eh,005h,008h,000h,046h,005h,008h,000h%@NL@%
  3963.       db   04Eh,005h,008h,000h,056h,005h,008h,000h%@NL@%
  3964.       db   05Eh,005h,008h,000h,066h,005h,008h,000h%@NL@%
  3965.       db   06Eh,005h,008h,000h,076h,005h,008h,000h%@NL@%
  3966.       db   07Eh,005h,008h,000h,086h,005h,008h,000h%@NL@%
  3967.       db   08Eh,005h,008h,000h,096h,005h,008h,000h%@NL@%
  3968.       db   09Eh,005h,008h,000h,0A6h,005h,008h,000h%@NL@%
  3969.       db   0AEh,005h,008h,000h,0B6h,005h,008h,000h%@NL@%
  3970.       db   0BEh,005h,008h,000h,0C6h,005h,008h,000h%@NL@%
  3971.       db   0CEh,005h,008h,000h,0D6h,005h,008h,000h%@NL@%
  3972.       db   0DEh,005h,008h,000h,0E6h,005h,008h,000h%@NL@%
  3973.       db   0EEh,005h,008h,000h,0F6h,005h,008h,000h%@NL@%
  3974.       db   0FEh,005h,008h,000h,006h,006h,008h,000h%@NL@%
  3975.       db   00Eh,006h,008h,000h,016h,006h,008h,000h%@NL@%
  3976.       db   01Eh,006h,008h,000h,026h,006h,008h,000h%@NL@%
  3977.       db   02Eh,006h,008h,000h,036h,006h,008h,000h%@NL@%
  3978.       db   03Eh,006h,008h,000h,046h,006h,008h,000h%@NL@%
  3979.       db   04Eh,006h,008h,000h,056h,006h,008h,000h%@NL@%
  3980.       db   05Eh,006h,008h,000h,066h,006h,008h,000h%@NL@%
  3981.       db   06Eh,006h,008h,000h,076h,006h,008h,000h%@NL@%
  3982.       db   07Eh,006h,008h,000h,086h,006h,008h,000h%@NL@%
  3983.       db   08Eh,006h,008h,000h,096h,006h,008h,000h%@NL@%
  3984.       db   09Eh,006h,008h,000h,0A6h,006h,008h,000h%@NL@%
  3985.       db   0AEh,006h,008h,000h,0B6h,006h,008h,000h%@NL@%
  3986.       db   0BEh,006h,008h,000h,0C6h,006h,008h,000h%@NL@%
  3987.       db   0CEh,006h,008h,000h,0D6h,006h,008h,000h%@NL@%
  3988.       db   0DEh,006h,008h,000h,0E6h,006h,008h,000h%@NL@%
  3989.       db   0EEh,006h,008h,000h,0F6h,006h,008h,000h%@NL@%
  3990.       db   0FEh,006h,008h,000h,006h,007h,008h,000h%@NL@%
  3991.       db   00Eh,007h,008h,000h,016h,007h,008h,000h%@NL@%
  3992.       db   01Eh,007h,008h,000h,026h,007h,008h,000h%@NL@%
  3993.       db   02Eh,007h,008h,000h,036h,007h,008h,000h%@NL@%
  3994.       db   03Eh,007h,008h,000h,046h,007h,008h,000h%@NL@%
  3995.       db   04Eh,007h,008h,000h,056h,007h,008h,000h%@NL@%
  3996.       db   05Eh,007h,008h,000h,066h,007h,008h,000h%@NL@%
  3997.       db   06Eh,007h,008h,000h,076h,007h,008h,000h%@NL@%
  3998.       db   07Eh,007h,008h,000h,086h,007h,008h,000h%@NL@%
  3999.       db   08Eh,007h,008h,000h,096h,007h,008h,000h%@NL@%
  4000.       db   09Eh,007h,008h,000h,0A6h,007h,008h,000h%@NL@%
  4001.       db   0AEh,007h,008h,000h,0B6h,007h,008h,000h%@NL@%
  4002.       db   0BEh,007h,008h,000h,0C6h,007h,008h,000h%@NL@%
  4003.       db   0CEh,007h,008h,000h,0D6h,007h,008h,000h%@NL@%
  4004.       db   0DEh,007h,008h,000h,0E6h,007h,008h,000h%@NL@%
  4005.       db   0EEh,007h,008h,000h,0F6h,007h,008h,000h%@NL@%
  4006.       db   0FEh,007h,008h,000h,006h,008h,008h,000h%@NL@%
  4007.       db   00Eh,008h,008h,000h,016h,008h,008h,000h%@NL@%
  4008.       db   01Eh,008h,008h,000h,026h,008h,008h,000h%@NL@%
  4009.       db   02Eh,008h,008h,000h,036h,008h,008h,000h%@NL@%
  4010.       db   03Eh,008h,008h,000h,046h,008h,008h,000h%@NL@%
  4011.       db   04Eh,008h,008h,000h,056h,008h,008h,000h%@NL@%
  4012.       db   05Eh,008h,008h,000h,066h,008h,008h,000h%@NL@%
  4013.       db   06Eh,008h,008h,000h,076h,008h,008h,000h%@NL@%
  4014.       db   07Eh,008h,008h,000h,086h,008h,008h,000h%@NL@%
  4015.       db   08Eh,008h,008h,000h,096h,008h,008h,000h%@NL@%
  4016.       db   09Eh,008h,008h,000h,0A6h,008h,008h,000h%@NL@%
  4017.       db   0AEh,008h,008h,000h,0B6h,008h,008h,000h%@NL@%
  4018.       db   0BEh,008h,008h,000h,0C6h,008h,008h,000h%@NL@%
  4019.       db   0CEh,008h,008h,000h,0D6h,008h,008h,000h%@NL@%
  4020.       db   0DEh,008h,008h,000h,0E6h,008h,008h,000h%@NL@%
  4021.       db   0EEh,008h,008h,000h,0F6h,008h,008h,000h%@NL@%
  4022.       db   0FEh,008h,008h,000h,006h,009h,008h,000h%@NL@%
  4023.       db   00Eh,009h,008h,000h,016h,009h,008h,000h%@NL@%
  4024.       db   01Eh,009h,008h,000h,026h,009h,008h,000h%@NL@%
  4025.       db   02Eh,009h,008h,000h,036h,009h,008h,000h%@NL@%
  4026.       db   03Eh,009h,008h,000h,046h,009h,008h,000h%@NL@%
  4027.       db   04Eh,009h,008h,000h,056h,009h,008h,000h%@NL@%
  4028.       db   05Eh,009h,008h,000h,066h,009h,008h,000h%@NL@%
  4029.       db   06Eh,009h,008h,000h,076h,009h,008h,000h%@NL@%
  4030.       db   07Eh,009h,008h,000h,086h,009h,008h,000h%@NL@%
  4031.       db   08Eh,009h,008h,000h,096h,009h,008h,000h%@NL@%
  4032.       db   09Eh,009h,008h,000h,0A6h,009h,008h,000h%@NL@%
  4033.       db   0AEh,009h,008h,000h,0B6h,009h,008h,000h%@NL@%
  4034.       db   0BEh,009h,008h,000h,0C6h,009h,008h,000h%@NL@%
  4035.       db   0CEh,009h,008h,000h,0D6h,009h,008h,000h%@NL@%
  4036.       db   0DEh,009h,008h,000h,0E6h,009h,008h,000h%@NL@%
  4037.       db   0EEh,009h,008h,000h,0F6h,009h,008h,000h%@NL@%
  4038.       db   0FEh,009h,008h,000h,006h,00Ah,008h,000h%@NL@%
  4039.       db   00Eh,00Ah,008h,000h,016h,00Ah,008h,000h%@NL@%
  4040.       db   01Eh,00Ah,008h,000h,026h,00Ah,008h,000h%@NL@%
  4041.       db   02Eh,00Ah,008h,000h,036h,00Ah,008h,000h%@NL@%
  4042.       db   03Eh,00Ah,008h,000h,046h,00Ah,008h,000h%@NL@%
  4043.       db   04Eh,00Ah,008h,000h,056h,00Ah,008h,000h%@NL@%
  4044.       db   05Eh,00Ah,008h,000h,066h,00Ah,008h,000h%@NL@%
  4045.       db   06Eh,00Ah,008h,000h,076h,00Ah,008h,000h%@NL@%
  4046.       db   07Eh,00Ah,008h,000h,086h,00Ah,008h,000h%@NL@%
  4047.       db   08Eh,00Ah,008h,000h,096h,00Ah,008h,000h%@NL@%
  4048.       db   09Eh,00Ah,008h,000h,0A6h,00Ah,008h,000h%@NL@%
  4049.       db   0AEh,00Ah,008h,000h,0B6h,00Ah,008h,000h%@NL@%
  4050.       db   0BEh,00Ah,008h,000h,0C6h,00Ah,008h,000h%@NL@%
  4051.       db   0CEh,00Ah,008h,000h,0D6h,00Ah,008h,000h%@NL@%
  4052.       db   0DEh,00Ah,008h,000h,0E6h,00Ah,008h,000h%@NL@%
  4053.       db   0EEh,00Ah,008h,000h,0F6h,00Ah,008h,000h%@NL@%
  4054.       db   0FEh,00Ah,008h,000h,006h,00Bh,008h,000h%@NL@%
  4055.       db   00Eh,00Bh,008h,000h,016h,00Bh,008h,000h%@NL@%
  4056.       db   01Eh,00Bh,008h,000h,026h,00Bh,008h,000h%@NL@%
  4057.       db   02Eh,00Bh,008h,000h,036h,00Bh,008h,000h%@NL@%
  4058.       db   03Eh,00Bh,008h,000h,046h,00Bh,008h,000h%@NL@%
  4059.       db   04Eh,00Bh,008h,000h,056h,00Bh,008h,000h%@NL@%
  4060.       db   05Eh,00Bh,008h,000h,066h,00Bh,008h,000h%@NL@%
  4061.       db   06Eh,00Bh,008h,000h,076h,00Bh,008h,000h%@NL@%
  4062.       db   07Eh,00Bh,008h,000h,086h,00Bh,008h,000h%@NL@%
  4063.       db   08Eh,00Bh,008h,000h,096h,00Bh,008h,000h%@NL@%
  4064.       db   09Eh,00Bh,008h,000h,0A6h,00Bh,008h,000h%@NL@%
  4065.       db   0AEh,00Bh,008h,000h,0B6h,00Bh,008h,000h%@NL@%
  4066.       db   0BEh,00Bh,008h,000h,0C6h,00Bh,008h,000h%@NL@%
  4067.       db   0CEh,00Bh,008h,000h,0D6h,00Bh,008h,000h%@NL@%
  4068.       db   0DEh,00Bh,008h,000h,0E6h,00Bh,008h,000h%@NL@%
  4069.       db   0EEh,00Bh,008h,000h,0F6h,00Bh,008h,000h%@NL@%
  4070.       db   0FEh,00Bh,008h,000h,006h,00Ch,008h,000h%@NL@%
  4071.       db   00Eh,00Ch,008h,000h,016h,00Ch,008h,000h%@NL@%
  4072.       db   01Eh,00Ch,008h,000h,026h,00Ch,008h,000h%@NL@%
  4073.       db   02Eh,00Ch,008h,000h,036h,00Ch,008h,000h%@NL@%
  4074.       db   03Eh,00Ch,008h,000h,046h,00Ch,008h,000h%@NL@%
  4075.       db   04Eh,00Ch,008h,000h,056h,00Ch,008h,000h%@NL@%
  4076.       db   05Eh,00Ch,008h,000h,066h,00Ch,008h,000h%@NL@%
  4077.       db   06Eh,00Ch,008h,000h,076h,00Ch,008h,000h%@NL@%
  4078.       db   07Eh,005h,049h,042h,04Dh,000h,000h,000h%@NL@%
  4079.       db   000h,000h,000h,000h,000h,000h,07Eh,081h%@NL@%
  4080.       db   0A5h,081h,0BDh,099h,081h,07Eh,07Eh,0FFh%@NL@%
  4081.       db   0DBh,0FFh,0C3h,0E7h,0FFh,07Eh,06Ch,0FEh%@NL@%
  4082.       db   0FEh,0FEh,07Ch,038h,010h,000h,010h,038h%@NL@%
  4083.       db   07Ch,0FEh,07Ch,038h,010h,000h,038h,07Ch%@NL@%
  4084.       db   038h,0FEh,0FEh,07Ch,038h,07Ch,010h,010h%@NL@%
  4085.       db   038h,07Ch,0FEh,07Ch,038h,07Ch,010h,010h%@NL@%
  4086.       db   038h,07Ch,0FEh,07Ch,038h,07Ch,0FFh,0FFh%@NL@%
  4087.       db   0E7h,0C3h,0C3h,0E7h,0FFh,0FFh,000h,000h%@NL@%
  4088.       db   000h,000h,000h,000h,000h,000h,000h,000h%@NL@%
  4089.       db   000h,000h,000h,000h,000h,000h,000h,000h%@NL@%
  4090.       db   000h,000h,000h,000h,000h,000h,000h,000h%@NL@%
  4091.       db   000h,000h,000h,000h,000h,000h,000h,000h%@NL@%
  4092.       db   000h,000h,000h,000h,000h,000h,07Fh,063h%@NL@%
  4093.       db   07Fh,063h,063h,067h,0E6h,0C0h,099h,05Ah%@NL@%
  4094.       db   03Ch,0E7h,0E7h,03Ch,05Ah,099h,080h,0E0h%@NL@%
  4095.       db   0F8h,0FEh,0F8h,0E0h,080h,000h,002h,00Eh%@NL@%
  4096.       db   03Eh,0FEh,03Eh,00Eh,002h,000h,018h,03Ch%@NL@%
  4097.       db   07Eh,018h,018h,07Eh,03Ch,018h,066h,066h%@NL@%
  4098.       db   066h,066h,066h,000h,066h,000h,07Fh,0DBh%@NL@%
  4099.       db   0DBh,07Bh,01Bh,01Bh,01Bh,000h,03Eh,063h%@NL@%
  4100.       db   038h,06Ch,06Ch,038h,0CCh,078h,000h,000h%@NL@%
  4101.       db   000h,000h,07Eh,07Eh,07Eh,000h,018h,03Ch%@NL@%
  4102.       db   07Eh,018h,07Eh,03Ch,018h,0FFh,018h,03Ch%@NL@%
  4103.       db   07Eh,018h,018h,018h,018h,000h,018h,018h%@NL@%
  4104.       db   018h,018h,07Eh,03Ch,018h,000h,000h,018h%@NL@%
  4105.       db   00Ch,0FEh,00Ch,018h,000h,000h,000h,030h%@NL@%
  4106.       db   060h,0FEh,060h,030h,000h,000h,000h,030h%@NL@%
  4107.       db   060h,0FEh,060h,030h,000h,000h,000h,030h%@NL@%
  4108.       db   060h,0FEh,060h,030h,000h,000h,000h,030h%@NL@%
  4109.       db   060h,0FEh,060h,030h,000h,000h,000h,030h%@NL@%
  4110.       db   060h,0FEh,060h,030h,000h,000h,000h,000h%@NL@%
  4111.       db   000h,000h,000h,000h,000h,000h,030h,078h%@NL@%
  4112.       db   078h,030h,030h,000h,030h,000h,06Ch,06Ch%@NL@%
  4113.       db   06Ch,000h,000h,000h,000h,000h,06Ch,06Ch%@NL@%
  4114.       db   0FEh,06Ch,0FEh,06Ch,06Ch,000h,030h,07Ch%@NL@%
  4115.       db   0C0h,078h,00Ch,0F8h,030h,000h,000h,0C6h%@NL@%
  4116.       db   0CCh,018h,030h,066h,0C6h,000h,038h,06Ch%@NL@%
  4117.       db   038h,076h,0DCh,0CCh,076h,000h,060h,060h%@NL@%
  4118.       db   0C0h,000h,000h,000h,000h,000h,018h,030h%@NL@%
  4119.       db   060h,060h,060h,030h,018h,000h,060h,030h%@NL@%
  4120.       db   018h,018h,018h,030h,060h,000h,000h,066h%@NL@%
  4121.       db   03Ch,0FFh,03Ch,066h,000h,000h,000h,030h%@NL@%
  4122.       db   030h,0FCh,030h,030h,000h,000h,000h,000h%@NL@%
  4123.       db   000h,000h,000h,030h,030h,060h,000h,000h%@NL@%
  4124.       db   000h,0FCh,000h,000h,000h,000h,000h,000h%@NL@%
  4125.       db   000h,000h,000h,030h,030h,000h,006h,00Ch%@NL@%
  4126.       db   018h,030h,060h,0C0h,080h,000h,07Ch,0C6h%@NL@%
  4127.       db   0CEh,0DEh,0F6h,0E6h,07Ch,000h,030h,070h%@NL@%
  4128.       db   030h,030h,030h,030h,0FCh,000h,078h,0CCh%@NL@%
  4129.       db   00Ch,038h,060h,0CCh,0FCh,000h,078h,0CCh%@NL@%
  4130.       db   00Ch,038h,00Ch,0CCh,078h,000h,01Ch,03Ch%@NL@%
  4131.       db   06Ch,0CCh,0FEh,00Ch,01Eh,000h,0FCh,0C0h%@NL@%
  4132.       db   0F8h,00Ch,00Ch,0CCh,078h,000h,038h,060h%@NL@%
  4133.       db   0C0h,0F8h,0CCh,0CCh,078h,000h,0FCh,0CCh%@NL@%
  4134.       db   00Ch,018h,030h,030h,030h,000h,078h,0CCh%@NL@%
  4135.       db   0CCh,078h,0CCh,0CCh,078h,000h,078h,0CCh%@NL@%
  4136.       db   0CCh,07Ch,00Ch,018h,070h,000h,000h,030h%@NL@%
  4137.       db   030h,000h,000h,030h,030h,000h,000h,030h%@NL@%
  4138.       db   030h,000h,000h,030h,030h,060h,018h,030h%@NL@%
  4139.       db   060h,0C0h,060h,030h,018h,000h,000h,000h%@NL@%
  4140.       db   0FCh,000h,000h,0FCh,000h,000h,060h,030h%@NL@%
  4141.       db   018h,00Ch,018h,030h,060h,000h,078h,0CCh%@NL@%
  4142.       db   00Ch,018h,030h,000h,030h,000h,07Ch,0C6h%@NL@%
  4143.       db   0DEh,0DEh,0DEh,0C0h,078h,000h,030h,078h%@NL@%
  4144.       db   0CCh,0CCh,0FCh,0CCh,0CCh,000h,0FCh,066h%@NL@%
  4145.       db   066h,07Ch,066h,066h,0FCh,000h,03Ch,066h%@NL@%
  4146.       db   0C0h,0C0h,0C0h,066h,03Ch,000h,0F8h,06Ch%@NL@%
  4147.       db   066h,066h,066h,06Ch,0F8h,000h,0FEh,062h%@NL@%
  4148.       db   068h,078h,068h,062h,0FEh,000h,0FEh,062h%@NL@%
  4149.       db   068h,078h,068h,060h,0F0h,000h,03Ch,066h%@NL@%
  4150.       db   0C0h,0C0h,0CEh,066h,03Eh,000h,0CCh,0CCh%@NL@%
  4151.       db   0CCh,0FCh,0CCh,0CCh,0CCh,000h,078h,030h%@NL@%
  4152.       db   030h,030h,030h,030h,078h,000h,01Eh,00Ch%@NL@%
  4153.       db   00Ch,00Ch,0CCh,0CCh,078h,000h,0E6h,066h%@NL@%
  4154.       db   06Ch,078h,06Ch,066h,0E6h,000h,0F0h,060h%@NL@%
  4155.       db   060h,060h,062h,066h,0FEh,000h,0C6h,0EEh%@NL@%
  4156.       db   0FEh,0FEh,0D6h,0C6h,0C6h,000h,0C6h,0E6h%@NL@%
  4157.       db   0F6h,0DEh,0CEh,0C6h,0C6h,000h,038h,06Ch%@NL@%
  4158.       db   0C6h,0C6h,0C6h,06Ch,038h,000h,0FCh,066h%@NL@%
  4159.       db   066h,07Ch,060h,060h,0F0h,000h,078h,0CCh%@NL@%
  4160.       db   0CCh,0CCh,0DCh,078h,01Ch,000h,0FCh,066h%@NL@%
  4161.       db   066h,07Ch,06Ch,066h,0E6h,000h,078h,0CCh%@NL@%
  4162.       db   0E0h,070h,01Ch,0CCh,078h,000h,0FCh,0B4h%@NL@%
  4163.       db   030h,030h,030h,030h,078h,000h,0CCh,0CCh%@NL@%
  4164.       db   0CCh,0CCh,0CCh,0CCh,0FCh,000h,0CCh,0CCh%@NL@%
  4165.       db   0CCh,0CCh,0CCh,078h,030h,000h,0C6h,0C6h%@NL@%
  4166.       db   0C6h,0D6h,0FEh,0EEh,0C6h,000h,0C6h,0C6h%@NL@%
  4167.       db   06Ch,038h,038h,06Ch,0C6h,000h,0CCh,0CCh%@NL@%
  4168.       db   0CCh,078h,030h,030h,078h,000h,0FEh,0C6h%@NL@%
  4169.       db   08Ch,018h,032h,066h,0FEh,000h,078h,060h%@NL@%
  4170.       db   060h,060h,060h,060h,078h,000h,0C0h,060h%@NL@%
  4171.       db   030h,018h,00Ch,006h,002h,000h,078h,018h%@NL@%
  4172.       db   018h,018h,018h,018h,078h,000h,010h,038h%@NL@%
  4173.       db   06Ch,0C6h,000h,000h,000h,000h,000h,000h%@NL@%
  4174.       db   000h,000h,000h,000h,000h,0FFh,030h,030h%@NL@%
  4175.       db   018h,000h,000h,000h,000h,000h,000h,000h%@NL@%
  4176.       db   078h,00Ch,07Ch,0CCh,076h,000h,0E0h,060h%@NL@%
  4177.       db   060h,07Ch,066h,066h,0DCh,000h,000h,000h%@NL@%
  4178.       db   078h,0CCh,0C0h,0CCh,078h,000h,01Ch,00Ch%@NL@%
  4179.       db   00Ch,07Ch,0CCh,0CCh,076h,000h,000h,000h%@NL@%
  4180.       db   078h,0CCh,0FCh,0C0h,078h,000h,038h,06Ch%@NL@%
  4181.       db   060h,0F0h,060h,060h,0F0h,000h,000h,000h%@NL@%
  4182.       db   076h,0CCh,0CCh,07Ch,00Ch,0F8h,0E0h,060h%@NL@%
  4183.       db   06Ch,076h,066h,066h,0E6h,000h,030h,000h%@NL@%
  4184.       db   070h,030h,030h,030h,078h,000h,00Ch,000h%@NL@%
  4185.       db   00Ch,00Ch,00Ch,0CCh,0CCh,078h,0E0h,060h%@NL@%
  4186.       db   066h,06Ch,078h,06Ch,0E6h,000h,070h,030h%@NL@%
  4187.       db   030h,030h,030h,030h,078h,000h,000h,000h%@NL@%
  4188.       db   0CCh,0FEh,0FEh,0D6h,0C6h,000h,000h,000h%@NL@%
  4189.       db   0F8h,0CCh,0CCh,0CCh,0CCh,000h,000h,000h%@NL@%
  4190.       db   078h,0CCh,0CCh,0CCh,078h,000h,000h,000h%@NL@%
  4191.       db   0DCh,066h,066h,07Ch,060h,0F0h,000h,000h%@NL@%
  4192.       db   076h,0CCh,0CCh,07Ch,00Ch,01Eh,000h,000h%@NL@%
  4193.       db   0DCh,076h,066h,060h,0F0h,000h,000h,000h%@NL@%
  4194.       db   07Ch,0C0h,078h,00Ch,0F8h,000h,010h,030h%@NL@%
  4195.       db   07Ch,030h,030h,034h,018h,000h,000h,000h%@NL@%
  4196.       db   0CCh,0CCh,0CCh,0CCh,076h,000h,000h,000h%@NL@%
  4197.       db   0CCh,0CCh,0CCh,078h,030h,000h,000h,000h%@NL@%
  4198.       db   0C6h,0D6h,0FEh,0FEh,06Ch,000h,000h,000h%@NL@%
  4199.       db   0C6h,06Ch,038h,06Ch,0C6h,000h,000h,000h%@NL@%
  4200.       db   0CCh,0CCh,0CCh,07Ch,00Ch,0F8h,000h,000h%@NL@%
  4201.       db   0FCh,098h,030h,064h,0FCh,000h,01Ch,030h%@NL@%
  4202.       db   030h,0E0h,030h,030h,01Ch,000h,018h,018h%@NL@%
  4203.       db   018h,000h,018h,018h,018h,000h,0E0h,030h%@NL@%
  4204.       db   030h,01Ch,030h,030h,0E0h,000h,076h,0DCh%@NL@%
  4205.       db   000h,000h,000h,000h,000h,000h,000h,010h%@NL@%
  4206.       db   038h,06Ch,0C6h,0C6h,0FEh,000h,078h,0CCh%@NL@%
  4207.       db   0C0h,0CCh,078h,018h,00Ch,078h,000h,0CCh%@NL@%
  4208.       db   000h,0CCh,0CCh,0CCh,07Eh,000h,01Ch,000h%@NL@%
  4209.       db   078h,0CCh,0FCh,0C0h,078h,000h,07Eh,0C3h%@NL@%
  4210.       db   03Ch,006h,03Eh,066h,03Fh,000h,0CCh,000h%@NL@%
  4211.       db   078h,00Ch,07Ch,0CCh,07Eh,000h,0E0h,000h%@NL@%
  4212.       db   078h,00Ch,07Ch,0CCh,07Eh,000h,030h,030h%@NL@%
  4213.       db   078h,00Ch,07Ch,0CCh,07Eh,000h,000h,000h%@NL@%
  4214.       db   078h,0C0h,0C0h,078h,00Ch,038h,07Eh,0C3h%@NL@%
  4215.       db   03Ch,066h,07Eh,060h,03Ch,000h,0CCh,000h%@NL@%
  4216.       db   078h,0CCh,0FCh,0C0h,078h,000h,0E0h,000h%@NL@%
  4217.       db   078h,0CCh,0FCh,0C0h,078h,000h,0CCh,000h%@NL@%
  4218.       db   070h,030h,030h,030h,078h,000h,07Ch,0C6h%@NL@%
  4219.       db   038h,018h,018h,018h,03Ch,000h,0E0h,000h%@NL@%
  4220.       db   070h,030h,030h,030h,078h,000h,0C6h,038h%@NL@%
  4221.       db   06Ch,0C6h,0FEh,0C6h,0C6h,000h,030h,030h%@NL@%
  4222.       db   000h,078h,0CCh,0FCh,0CCh,000h,01Ch,000h%@NL@%
  4223.       db   0FCh,060h,078h,060h,0FCh,000h,000h,000h%@NL@%
  4224.       db   07Fh,00Ch,07Fh,0CCh,07Fh,000h,03Eh,06Ch%@NL@%
  4225.       db   0CCh,0FEh,0CCh,0CCh,0CEh,000h,078h,0CCh%@NL@%
  4226.       db   000h,078h,0CCh,0CCh,078h,000h,000h,0CCh%@NL@%
  4227.       db   000h,078h,0CCh,0CCh,078h,000h,000h,0E0h%@NL@%
  4228.       db   000h,078h,0CCh,0CCh,078h,000h,078h,0CCh%@NL@%
  4229.       db   000h,0CCh,0CCh,0CCh,07Eh,000h,000h,0E0h%@NL@%
  4230.       db   000h,0CCh,0CCh,0CCh,07Eh,000h,000h,0CCh%@NL@%
  4231.       db   000h,0CCh,0CCh,07Ch,00Ch,0F8h,0C3h,018h%@NL@%
  4232.       db   03Ch,066h,066h,03Ch,018h,000h,0CCh,000h%@NL@%
  4233.       db   0CCh,0CCh,0CCh,0CCh,078h,000h,018h,018h%@NL@%
  4234.       db   07Eh,0C0h,0C0h,07Eh,018h,018h,038h,06Ch%@NL@%
  4235.       db   064h,0F0h,060h,0E6h,0FCh,000h,0CCh,0CCh%@NL@%
  4236.       db   078h,0FCh,030h,0FCh,030h,030h,0F8h,0CCh%@NL@%
  4237.       db   0CCh,0FAh,0C6h,0CFh,0C6h,0C7h,00Eh,01Bh%@NL@%
  4238.       db   018h,03Ch,018h,018h,0D8h,070h,01Ch,000h%@NL@%
  4239.       db   078h,00Ch,07Ch,0CCh,07Eh,000h,038h,000h%@NL@%
  4240.       db   070h,030h,030h,030h,078h,000h,000h,01Ch%@NL@%
  4241.       db   000h,078h,0CCh,0CCh,078h,000h,000h,01Ch%@NL@%
  4242.       db   000h,0CCh,0CCh,0CCh,07Eh,000h,000h,0F8h%@NL@%
  4243.       db   000h,0F8h,0CCh,0CCh,0CCh,000h,0FCh,000h%@NL@%
  4244.       db   0CCh,0ECh,0FCh,0DCh,0CCh,000h,03Ch,06Ch%@NL@%
  4245.       db   06Ch,03Eh,000h,07Eh,000h,000h,038h,06Ch%@NL@%
  4246.       db   06Ch,038h,000h,07Ch,000h,000h,030h,000h%@NL@%
  4247.       db   030h,060h,0C0h,0CCh,078h,000h,000h,000h%@NL@%
  4248.       db   000h,0FCh,0C0h,0C0h,000h,000h,000h,000h%@NL@%
  4249.       db   000h,0FCh,00Ch,00Ch,000h,000h,0C3h,0C6h%@NL@%
  4250.       db   0CCh,0DEh,033h,066h,0CCh,00Fh,0C3h,0C6h%@NL@%
  4251.       db   0CCh,0DBh,037h,06Fh,0CFh,003h,018h,018h%@NL@%
  4252.       db   000h,018h,018h,018h,018h,000h,000h,033h%@NL@%
  4253.       db   066h,0CCh,066h,033h,000h,000h,000h,0CCh%@NL@%
  4254.       db   066h,033h,066h,0CCh,000h,000h,022h,088h%@NL@%
  4255.       db   022h,088h,022h,088h,022h,088h,055h,0AAh%@NL@%
  4256.       db   055h,0AAh,055h,0AAh,055h,0AAh,0DBh,077h%@NL@%
  4257.       db   0DBh,0EEh,0DBh,077h,0DBh,0EEh,018h,018h%@NL@%
  4258.       db   018h,018h,018h,018h,018h,018h,018h,018h%@NL@%
  4259.       db   018h,018h,0F8h,018h,018h,018h,018h,018h%@NL@%
  4260.       db   0F8h,018h,0F8h,018h,018h,018h,036h,036h%@NL@%
  4261.       db   036h,036h,0F6h,036h,036h,036h,000h,000h%@NL@%
  4262.       db   000h,000h,0FEh,036h,036h,036h,000h,000h%@NL@%
  4263.       db   0F8h,018h,0F8h,018h,018h,018h,036h,036h%@NL@%
  4264.       db   0F6h,006h,0F6h,036h,036h,036h,036h,036h%@NL@%
  4265.       db   036h,036h,036h,036h,036h,036h,000h,000h%@NL@%
  4266.       db   0FEh,006h,0F6h,036h,036h,036h,036h,036h%@NL@%
  4267.       db   0F6h,006h,0FEh,000h,000h,000h,036h,036h%@NL@%
  4268.       db   036h,036h,0FEh,000h,000h,000h,018h,018h%@NL@%
  4269.       db   0F8h,018h,0F8h,000h,000h,000h,000h,000h%@NL@%
  4270.       db   000h,000h,0F8h,018h,018h,018h,018h,018h%@NL@%
  4271.       db   018h,018h,01Fh,000h,000h,000h,018h,018h%@NL@%
  4272.       db   018h,018h,0FFh,000h,000h,000h,000h,000h%@NL@%
  4273.       db   000h,000h,0FFh,018h,018h,018h,018h,018h%@NL@%
  4274.       db   018h,018h,01Fh,018h,018h,018h,000h,000h%@NL@%
  4275.       db   000h,000h,0FFh,000h,000h,000h,018h,018h%@NL@%
  4276.       db   018h,018h,0FFh,018h,018h,018h,018h,018h%@NL@%
  4277.       db   01Fh,018h,01Fh,018h,018h,018h,036h,036h%@NL@%
  4278.       db   036h,036h,037h,036h,036h,036h,036h,036h%@NL@%
  4279.       db   037h,030h,03Fh,000h,000h,000h,000h,000h%@NL@%
  4280.       db   03Fh,030h,037h,036h,036h,036h,036h,036h%@NL@%
  4281.       db   0F7h,000h,0FFh,000h,000h,000h,000h,000h%@NL@%
  4282.       db   0FFh,000h,0F7h,036h,036h,036h,036h,036h%@NL@%
  4283.       db   037h,030h,037h,036h,036h,036h,000h,000h%@NL@%
  4284.       db   0FFh,000h,0FFh,000h,000h,000h,036h,036h%@NL@%
  4285.       db   0F7h,000h,0F7h,036h,036h,036h,018h,018h%@NL@%
  4286.       db   0FFh,000h,0FFh,000h,000h,000h,036h,036h%@NL@%
  4287.       db   036h,036h,0FFh,000h,000h,000h,000h,000h%@NL@%
  4288.       db   0FFh,000h,0FFh,018h,018h,018h,000h,000h%@NL@%
  4289.       db   000h,000h,0FFh,036h,036h,036h,036h,036h%@NL@%
  4290.       db   036h,036h,03Fh,000h,000h,000h,018h,018h%@NL@%
  4291.       db   01Fh,018h,01Fh,000h,000h,000h,000h,000h%@NL@%
  4292.       db   01Fh,018h,01Fh,018h,018h,018h,000h,000h%@NL@%
  4293.       db   000h,000h,03Fh,036h,036h,036h,036h,036h%@NL@%
  4294.       db   036h,036h,0FFh,036h,036h,036h,018h,018h%@NL@%
  4295.       db   0FFh,018h,0FFh,018h,018h,018h,018h,018h%@NL@%
  4296.       db   018h,018h,0F8h,000h,000h,000h,000h,000h%@NL@%
  4297.       db   000h,000h,01Fh,018h,018h,018h,0FFh,0FFh%@NL@%
  4298.       db   0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,000h,000h%@NL@%
  4299.       db   000h,000h,0FFh,0FFh,0FFh,0FFh,0F0h,0F0h%@NL@%
  4300.       db   0F0h,0F0h,0F0h,0F0h,0F0h,0F0h,00Fh,00Fh%@NL@%
  4301.       db   00Fh,00Fh,00Fh,00Fh,00Fh,00Fh,0FFh,0FFh%@NL@%
  4302.       db   0FFh,0FFh,000h,000h,000h,000h,000h,000h%@NL@%
  4303.       db   076h,0DCh,0C8h,0DCh,076h,000h,000h,078h%@NL@%
  4304.       db   0CCh,0F8h,0CCh,0F8h,0C0h,0C0h,000h,0FCh%@NL@%
  4305.       db   0CCh,0C0h,0C0h,0C0h,0C0h,000h,000h,0FEh%@NL@%
  4306.       db   06Ch,06Ch,06Ch,06Ch,06Ch,000h,0FCh,0CCh%@NL@%
  4307.       db   060h,030h,060h,0CCh,0FCh,000h,000h,000h%@NL@%
  4308.       db   07Eh,0D8h,0D8h,0D8h,070h,000h,000h,066h%@NL@%
  4309.       db   066h,066h,066h,07Ch,060h,0C0h,000h,076h%@NL@%
  4310.       db   0DCh,018h,018h,018h,018h,000h,0FCh,030h%@NL@%
  4311.       db   078h,0CCh,0CCh,078h,030h,0FCh,038h,06Ch%@NL@%
  4312.       db   0C6h,0FEh,0C6h,06Ch,038h,000h,038h,06Ch%@NL@%
  4313.       db   0C6h,0C6h,06Ch,06Ch,0EEh,000h,01Ch,030h%@NL@%
  4314.       db   018h,07Ch,0CCh,0CCh,078h,000h,000h,000h%@NL@%
  4315.       db   07Eh,0DBh,0DBh,07Eh,000h,000h,006h,00Ch%@NL@%
  4316.       db   07Eh,0DBh,0DBh,07Eh,060h,0C0h,038h,060h%@NL@%
  4317.       db   0C0h,0F8h,0C0h,060h,038h,000h,078h,0CCh%@NL@%
  4318.       db   0CCh,0CCh,0CCh,0CCh,0CCh,000h,000h,0FCh%@NL@%
  4319.       db   000h,0FCh,000h,0FCh,000h,000h,030h,030h%@NL@%
  4320.       db   0FCh,030h,030h,000h,0FCh,000h,060h,030h%@NL@%
  4321.       db   018h,030h,060h,000h,0FCh,000h,018h,030h%@NL@%
  4322.       db   060h,030h,018h,000h,0FCh,000h,00Eh,01Bh%@NL@%
  4323.       db   01Bh,018h,018h,018h,018h,018h,018h,018h%@NL@%
  4324.       db   018h,018h,018h,0D8h,0D8h,070h,030h,030h%@NL@%
  4325.       db   000h,0FCh,000h,030h,030h,000h,000h,076h%@NL@%
  4326.       db   0DCh,000h,076h,0DCh,000h,000h,038h,06Ch%@NL@%
  4327.       db   06Ch,038h,000h,000h,000h,000h,000h,000h%@NL@%
  4328.       db   000h,018h,018h,000h,000h,000h,000h,000h%@NL@%
  4329.       db   000h,000h,018h,000h,000h,000h,00Fh,00Ch%@NL@%
  4330.       db   00Ch,00Ch,0ECh,06Ch,03Ch,01Ch,078h,06Ch%@NL@%
  4331.       db   06Ch,06Ch,06Ch,000h,000h,000h,070h,018h%@NL@%
  4332.       db   030h,060h,078h,000h,000h,000h,000h,000h%@NL@%
  4333.       db   03Ch,03Ch,03Ch,03Ch,000h,000h,000h,000h%@NL@%
  4334.       db   000h,000h,000h,000h,000h,000h%@NL@%
  4335. %@NL@%
  4336. %@AB@%;=====End of Font%@AE@%%@NL@%
  4337. %@NL@%
  4338. .CODE%@NL@%
  4339. %@NL@%
  4340. %@AB@%;********************************************************%@AE@%%@NL@%
  4341. %@AB@%;DefaultFont - Returns the Segment:Offset address of the%@AE@%%@NL@%
  4342. %@AB@%;               default font%@AE@%%@NL@%
  4343. %@AB@%;%@AE@%%@NL@%
  4344. %@AB@%; DefaultFont Segment%, Offset%%@AE@%%@NL@%
  4345. %@NL@%
  4346. PUBLIC DefaultFont%@NL@%
  4347. DefaultFont PROC%@NL@%
  4348.    push  bp%@NL@%
  4349.    mov   bp,sp%@NL@%
  4350. %@NL@%
  4351.    les         bx,[bp+10]                %@AB@%;put address of first arg in es:si%@AE@%%@NL@%
  4352.    mov         es:[bx],SEG _IBM8_def        %@AB@%;move segment address to first arg of call%@AE@%%@NL@%
  4353. %@NL@%
  4354.    les         bx,[bp+6]                %@AB@%;repeat above for offset address of font%@AE@%%@NL@%
  4355.    mov         word ptr es:[bx],OFFSET _IBM8_def%@NL@%
  4356. %@NL@%
  4357.    pop   bp%@NL@%
  4358.    ret   8%@NL@%
  4359. DefaultFont ENDP%@NL@%
  4360. %@NL@%
  4361.       END%@NL@%
  4362. %@NL@%
  4363. %@NL@%
  4364. %@2@%%@AH@%CHRTB.BAS%@AE@%%@EH@%%@NL@%
  4365. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\CHRTB.BAS%@AE@%%@NL@%
  4366. %@NL@%
  4367. %@AB@%'*** CHRTB.BAS - Chart Routines for the Presentation Graphics Toolbox in%@AE@%%@NL@%
  4368. %@AB@%'           Microsoft BASIC 7.0, Professional Development System%@AE@%%@NL@%
  4369. %@AB@%'              Copyright (C) 1987-1989, Microsoft Corporation%@AE@%%@NL@%
  4370. %@AB@%'%@AE@%%@NL@%
  4371. %@AB@%'  NOTE:  This sample source code toolbox is intended to demonstrate some%@AE@%%@NL@%
  4372. %@AB@%'  of the extended capabilities of Microsoft BASIC 7.0 Professional Development%@AE@%%@NL@%
  4373. %@AB@%'  system that can help to leverage the professional developer's time more%@AE@%%@NL@%
  4374. %@AB@%'  effectively.  While you are free to use, modify, or distribute the routines%@AE@%%@NL@%
  4375. %@AB@%'  in this module in any way you find useful, it should be noted that these are%@AE@%%@NL@%
  4376. %@AB@%'  examples only and should not be relied upon as a fully-tested "add-on"%@AE@%%@NL@%
  4377. %@AB@%'  library.%@AE@%%@NL@%
  4378. %@AB@%'%@AE@%%@NL@%
  4379. %@AB@%'  PURPOSE: This file contains the BASIC source code for the Presentation%@AE@%%@NL@%
  4380. %@AB@%'           Graphics Toolbox Chart Routines.%@AE@%%@NL@%
  4381. %@AB@%'%@AE@%%@NL@%
  4382. %@AB@%'  To create a library and QuickLib containing the charting routines found%@AE@%%@NL@%
  4383. %@AB@%'  in this file, follow these steps:%@AE@%%@NL@%
  4384. %@AB@%'       BC /X/FS chrtb.bas%@AE@%%@NL@%
  4385. %@AB@%'       LIB chrtb.lib + chrtb + chrtasm + qbx.lib;%@AE@%%@NL@%
  4386. %@AB@%'       LINK /Q chrtb.lib, chrtb.qlb,,qbxqlb.lib;%@AE@%%@NL@%
  4387. %@AB@%'  If you are going to use this CHRTB.QLB QuickLib in conjunction with%@AE@%%@NL@%
  4388. %@AB@%'  the font source code (FONTB.BAS) or the UI toobox source code%@AE@%%@NL@%
  4389. %@AB@%'  (GENERAL.BAS, WINDOW.BAS, MENU.BAS and MOUSE.BAS), you need to%@AE@%%@NL@%
  4390. %@AB@%'  include the assembly code routines referenced in these files.  For the%@AE@%%@NL@%
  4391. %@AB@%'  font routines, create CHRTB.LIB as follows before you create the%@AE@%%@NL@%
  4392. %@AB@%'  QuickLib:%@AE@%%@NL@%
  4393. %@AB@%'       LIB chrtb.lib + chrtb + chrtasm + fontasm + qbx.lib;%@AE@%%@NL@%
  4394. %@AB@%'  For the UI toolbox routines, create the library as follows:%@AE@%%@NL@%
  4395. %@AB@%'       LIB chrtb.lib + chrtb + chrtasm + uiasm + qbx.lib;%@AE@%%@NL@%
  4396. %@AB@%'**************************************************************************%@AE@%%@NL@%
  4397. %@NL@%
  4398. %@AB@%' Constants:%@AE@%%@NL@%
  4399. %@NL@%
  4400. CONST cTicSize = .02            ' Percent of axis length to use for tic length%@NL@%
  4401. CONST cMaxChars = 255           ' Maximum ASCII value allowed for character%@NL@%
  4402. CONST cBarWid = .8              ' Percent of category width to use for bar%@NL@%
  4403. CONST cPiVal = 3.141592         ' A value for PI%@NL@%
  4404. CONST cFalse = 0                ' Logical false%@NL@%
  4405. CONST cTrue = NOT cFalse        ' Logical true%@NL@%
  4406. %@NL@%
  4407. %@AB@%' CHRTB.BI contains all of the TYPE definitions and SUB declarations%@AE@%%@NL@%
  4408. %@AB@%' that are accessible to the library user as well as CONST definitions for%@AE@%%@NL@%
  4409. %@AB@%' some routine parameters and error messages:%@AE@%%@NL@%
  4410. %@NL@%
  4411. %@AB@%'$INCLUDE: 'CHRTB.BI'%@AE@%%@NL@%
  4412. %@NL@%
  4413. %@AB@%' FONTB.BI contains all of the TYPE definitions and SUB declarations%@AE@%%@NL@%
  4414. %@AB@%' required for graphics text:%@AE@%%@NL@%
  4415. %@NL@%
  4416. %@AB@%'$INCLUDE: 'FONTB.BI'%@AE@%%@NL@%
  4417. %@NL@%
  4418. %@AB@%' Below are TYPE definitions local to this module:%@AE@%%@NL@%
  4419. %@NL@%
  4420. %@AB@%' TYPE for recording information on title spacing:%@AE@%%@NL@%
  4421. TYPE TitleLayout%@NL@%
  4422.         Top         AS INTEGER        ' Space above first title%@NL@%
  4423.         TitleOne    AS INTEGER        ' Height of first title%@NL@%
  4424.         Middle      AS INTEGER        ' Space between first and second titles%@NL@%
  4425.         TitleTwo    AS INTEGER        ' Height of second title%@NL@%
  4426.         Bottom      AS INTEGER        ' Space below second title%@NL@%
  4427.         TotalSize   AS INTEGER        ' Sum of all the above%@NL@%
  4428. END TYPE%@NL@%
  4429. %@NL@%
  4430. %@AB@%' TYPE for recording information on the legend layout:%@AE@%%@NL@%
  4431. TYPE LegendLayout%@NL@%
  4432.         NumCol      AS INTEGER        ' Number of columns in legend%@NL@%
  4433.         NumRow      AS INTEGER        ' Number of rows in legend%@NL@%
  4434.         SymbolSize  AS INTEGER        ' Height of symbol%@NL@%
  4435.         LabelOffset AS INTEGER        ' Space between start of symbol and label%@NL@%
  4436.         RowSpacing  AS INTEGER        ' Space between tops of rows%@NL@%
  4437.         ColSpacing  AS INTEGER        ' Spacing between beginnings of columns%@NL@%
  4438.         HorizBorder AS INTEGER        ' Top and bottom border%@NL@%
  4439.         VertBorder  AS INTEGER        ' Left and right border%@NL@%
  4440. END TYPE%@NL@%
  4441. %@NL@%
  4442. %@AB@%' TYPE for a group of global parameters:%@AE@%%@NL@%
  4443. TYPE GlobalParams%@NL@%
  4444.         SysFlag     AS INTEGER        ' cYes means Analyze call is from system%@NL@%
  4445.         Initialized AS INTEGER        ' cYes means clInitChart has been called%@NL@%
  4446. %@NL@%
  4447.         PaletteScrn AS INTEGER        ' Screen mode for which palette is set%@NL@%
  4448.         PaletteBits AS INTEGER        ' Bits per pixel for current screen mode%@NL@%
  4449.         PaletteSet  AS INTEGER        ' cYes means palette has been initialized%@NL@%
  4450.         White       AS INTEGER        ' White attribute in current screen mode%@NL@%
  4451. %@NL@%
  4452.         Aspect      AS SINGLE         ' Current screen aspect%@NL@%
  4453.         MaxXPix     AS INTEGER        ' Screen size along X axis%@NL@%
  4454.         MaxYPix     AS INTEGER        ' Screen size along Y axis%@NL@%
  4455.         MaxColor    AS INTEGER        ' Maximum color number for current screen%@NL@%
  4456. %@NL@%
  4457.         ChartWid    AS INTEGER        ' Width of chart window%@NL@%
  4458.         ChartHgt    AS INTEGER        ' Height of chart window%@NL@%
  4459.         CwX1        AS INTEGER        ' Left side of chart window%@NL@%
  4460.         CwY1        AS INTEGER        ' Top edge of chart window%@NL@%
  4461.         CwX2        AS INTEGER        ' Right side of chart window%@NL@%
  4462.         CwY2        AS INTEGER        ' Bottom edge of chart window%@NL@%
  4463. %@NL@%
  4464.         XStagger    AS INTEGER        ' Boolean, true if category labels overflow%@NL@%
  4465.         ValLenX     AS INTEGER        ' Maximum length of value labels on X-axis%@NL@%
  4466.         ValLenY     AS INTEGER        ' Maximum length of value labels on Y-axis%@NL@%
  4467. %@NL@%
  4468.         NVals       AS INTEGER        ' Number of data values in data series%@NL@%
  4469.         NSeries     AS INTEGER        ' Number of series of data%@NL@%
  4470.         MSeries     AS INTEGER        ' If multiple-series chart then cYes, else%@NL@%
  4471. %@AB@%                                                                                        ' cNo%@AE@%%@NL@%
  4472.         XMode       AS INTEGER        ' Axis mode of x axis%@NL@%
  4473.         YMode       AS INTEGER        ' Axis mode of y axis%@NL@%
  4474. END TYPE%@NL@%
  4475. %@NL@%
  4476. %@AB@%' FUNCTION and SUB declarations for procedures local to this module:%@AE@%%@NL@%
  4477. %@NL@%
  4478. DECLARE FUNCTION clBuildBitP$ (Bits%, C%, InP$)%@NL@%
  4479. DECLARE FUNCTION clBuildPlaneP$ (Bits%, C%, InP$)%@NL@%
  4480. DECLARE FUNCTION clColorMaskL% (Bits%, Colr%)%@NL@%
  4481. DECLARE FUNCTION clGetStyle% (StyleNum%)%@NL@%
  4482. DECLARE FUNCTION clMaxVal (A, B)%@NL@%
  4483. DECLARE FUNCTION clMap2Pal% (N%)%@NL@%
  4484. DECLARE FUNCTION clMap2Attrib% (N%)%@NL@%
  4485. DECLARE FUNCTION clMaxStrLen% (Txt$(), First%, Last%)%@NL@%
  4486. DECLARE FUNCTION clVal2Str$ (X, Places%, Format%)%@NL@%
  4487. %@NL@%
  4488. DECLARE SUB clAdjustScale (Axis AS AxisType)%@NL@%
  4489. DECLARE SUB clAnalyzeC (Cat$(), N%, SLabels$(), First%, Last%)%@NL@%
  4490. DECLARE SUB clAnalyzeS (N%, SLabels$(), First%, Last%)%@NL@%
  4491. DECLARE SUB clBuildPalette (ScrnMode%, Bits%)%@NL@%
  4492. DECLARE SUB clChkInit ()%@NL@%
  4493. DECLARE SUB clChkFonts ()%@NL@%
  4494. DECLARE SUB clChkForErrors (Env AS ChartEnvironment, TypeMin%, TypeMax%, N%, First%, Last%)%@NL@%
  4495. DECLARE SUB clChkChartWindow (Env AS ChartEnvironment)%@NL@%
  4496. DECLARE SUB clChkPalettes (C%(), s%(), P$(), Char%(), B%())%@NL@%
  4497. DECLARE SUB clClearError ()%@NL@%
  4498. DECLARE SUB clColorMaskH (Bits%, Colr%, CMask%())%@NL@%
  4499. DECLARE SUB clDrawAxes (Cat$())%@NL@%
  4500. DECLARE SUB clDrawDataWindow ()%@NL@%
  4501. DECLARE SUB clDrawChartWindow ()%@NL@%
  4502. DECLARE SUB clDrawTitles ()%@NL@%
  4503. DECLARE SUB clDrawLegend (SeriesLabel$(), First AS INTEGER, Last AS INTEGER)%@NL@%
  4504. DECLARE SUB clDrawBarData ()%@NL@%
  4505. DECLARE SUB clDrawColumnData ()%@NL@%
  4506. DECLARE SUB clDrawLineData ()%@NL@%
  4507. DECLARE SUB clDrawPieData (value(), Expl%(), N%)%@NL@%
  4508. DECLARE SUB clDrawScatterData ()%@NL@%
  4509. DECLARE SUB clFilter (A AS AxisType, AxisMode%, D1(), D2(), N%)%@NL@%
  4510. DECLARE SUB clFilterMS (A AS AxisType, AxisMode%, D1(), D2(), N%, First%, Last%)%@NL@%
  4511. DECLARE SUB clFlagSystem ()%@NL@%
  4512. DECLARE SUB clFormatTics (A AS AxisType)%@NL@%
  4513. DECLARE SUB clHPrint (X%, Y%, Txt$)%@NL@%
  4514. DECLARE SUB clInitChart ()%@NL@%
  4515. DECLARE SUB clInitStdStruc ()%@NL@%
  4516. DECLARE SUB clLabelXTics (Axis AS AxisType, Cat$(), TicX, TicTotX%, TicY, YBoundry%)%@NL@%
  4517. DECLARE SUB clLabelYTics (Axis AS AxisType, Cat$(), TicX, TicY, TicTotY%)%@NL@%
  4518. DECLARE SUB clLayoutTitle (TL AS ANY, T1 AS ANY, T2 AS ANY)%@NL@%
  4519. DECLARE SUB clPrintTitle (TitleVar AS TitleType, Y%)%@NL@%
  4520. DECLARE SUB clRenderBar (X1, Y1, X2, Y2, C%)%@NL@%
  4521. DECLARE SUB clRenderWindow (W AS RegionType)%@NL@%
  4522. DECLARE SUB clScaleAxis (A AS AxisType, AxisMode%, D1())%@NL@%
  4523. DECLARE SUB clSelectChartWindow ()%@NL@%
  4524. DECLARE SUB clSelectRelWindow (W AS RegionType)%@NL@%
  4525. DECLARE SUB clSetAxisModes ()%@NL@%
  4526. DECLARE SUB clSetChartFont (N AS INTEGER)%@NL@%
  4527. DECLARE SUB clSetError (ErrNo AS INTEGER)%@NL@%
  4528. DECLARE SUB clSetCharColor (N%)%@NL@%
  4529. DECLARE SUB clSetGlobalParams ()%@NL@%
  4530. DECLARE SUB clSizeDataWindow (Cat$())%@NL@%
  4531. DECLARE SUB clLayoutLegend (SeriesLabel$(), First%, Last%)%@NL@%
  4532. DECLARE SUB clSpaceTics ()%@NL@%
  4533. DECLARE SUB clSpaceTicsA (A AS AxisType, AxisMode%, AxisLen%, TicWid%)%@NL@%
  4534. DECLARE SUB clTitleXAxis (A AS AxisType, X1%, X2%, YBoundry%)%@NL@%
  4535. DECLARE SUB clTitleYAxis (A AS AxisType, Y1%, Y2%)%@NL@%
  4536. DECLARE SUB clUnFlagSystem ()%@NL@%
  4537. DECLARE SUB clVPrint (X%, Y%, Txt$)%@NL@%
  4538. %@NL@%
  4539. %@NL@%
  4540. %@AB@%' Variable definitions local to this module:%@AE@%%@NL@%
  4541. %@NL@%
  4542. DIM PaletteC%(0 TO cPalLen)            ' List of colors     for drawing data%@NL@%
  4543. DIM PaletteS%(0 TO cPalLen)            ' List of styles     for drawing data%@NL@%
  4544. DIM PaletteP$(0 TO cPalLen)            ' List of patterns   for drawing data%@NL@%
  4545. DIM PaletteCh%(0 TO cPalLen)           ' List of plot chars for drawing data%@NL@%
  4546. DIM PaletteB%(0 TO cPalLen)            ' List of patterns   for borders%@NL@%
  4547. %@NL@%
  4548. DIM StdChars%(0 TO cPalLen)            ' Holds default plot characters%@NL@%
  4549. %@NL@%
  4550. DIM DAxis         AS AxisType          ' Default axis settings%@NL@%
  4551. DIM DWindow       AS RegionType        ' Default window settings%@NL@%
  4552. DIM DLegend       AS LegendType        ' Default legend settings%@NL@%
  4553. DIM DTitle        AS TitleType         ' Default title settings%@NL@%
  4554. %@NL@%
  4555. DIM XTitleLayout  AS TitleLayout       ' X-axis layout information%@NL@%
  4556. DIM YTitleLayout  AS TitleLayout       ' Y-axis layout information%@NL@%
  4557. DIM TTitleLayout  AS TitleLayout       ' Main/Sub layout information%@NL@%
  4558. %@NL@%
  4559. DIM LLayout       AS LegendLayout      ' Legend layout information%@NL@%
  4560. %@NL@%
  4561. DIM GFI           AS FontInfo          ' Global font information%@NL@%
  4562. DIM GE            AS ChartEnvironment  ' An internal global chart environment%@NL@%
  4563. DIM GP            AS GlobalParams      ' Holds a number of global parameters%@NL@%
  4564. %@AB@%                                                                                                        ' used in the charting routines.  See%@AE@%%@NL@%
  4565. %@AB@%                                                                                                        ' TYPE definition for details.%@AE@%%@NL@%
  4566. %@NL@%
  4567. %@AB@%'$DYNAMIC%@AE@%%@NL@%
  4568. DIM V1(1, 1), V2(1, 1)                 ' Internal dynamic data arrays.%@NL@%
  4569. %@AB@%'$STATIC%@AE@%%@NL@%
  4570. %@NL@%
  4571. %@AB@%'============================================================%@AE@%%@NL@%
  4572. %@AB@%'==============      Main Level Code     ====================%@AE@%%@NL@%
  4573. %@AB@%'============================================================%@AE@%%@NL@%
  4574. %@NL@%
  4575. %@AB@%' This error trap is set in the ChartScreen routine and will%@AE@%%@NL@%
  4576. %@AB@%' be evoked if an invalid screen mode is used:%@AE@%%@NL@%
  4577. ScreenErr:%@NL@%
  4578.         clSetError cBadScreen%@NL@%
  4579.         RESUME NEXT%@NL@%
  4580. %@NL@%
  4581. %@AB@%' This error trap should catch all errors that arise in using%@AE@%%@NL@%
  4582. %@AB@%' the charting library that are not expected:%@AE@%%@NL@%
  4583. UnexpectedErr:%@NL@%
  4584.         clSetError cCLUnexpectedOff + ERR%@NL@%
  4585.         RESUME NEXT%@NL@%
  4586. %@NL@%
  4587. %@AB@%'=== AnalyzeChart - Sets up scales and data window sizes%@AE@%%@NL@%
  4588. %@AB@%'%@AE@%%@NL@%
  4589. %@AB@%'  Arguments:%@AE@%%@NL@%
  4590. %@AB@%'     Env        - A ChartEnvironment variable%@AE@%%@NL@%
  4591. %@AB@%'%@AE@%%@NL@%
  4592. %@AB@%'     Cat$(1)    - One-dimensional array of category labels%@AE@%%@NL@%
  4593. %@AB@%'%@AE@%%@NL@%
  4594. %@AB@%'     Value(1)   - One-dimensional array of values to chart%@AE@%%@NL@%
  4595. %@AB@%'%@AE@%%@NL@%
  4596. %@AB@%'     N%         - The number of data values in data series%@AE@%%@NL@%
  4597. %@AB@%'%@AE@%%@NL@%
  4598. %@AB@%'  Return Values:%@AE@%%@NL@%
  4599. %@AB@%'     Scale and Data-Window values are changed as appropriate.%@AE@%%@NL@%
  4600. %@AB@%'%@AE@%%@NL@%
  4601. %@AB@%'=================================================================%@AE@%%@NL@%
  4602. SUB AnalyzeChart (Env AS ChartEnvironment, Cat$(), value(), N AS INTEGER)%@NL@%
  4603. %@NL@%
  4604. SHARED GE AS ChartEnvironment, GP AS GlobalParams%@NL@%
  4605. SHARED V1()%@NL@%
  4606. REDIM V1(1 TO N%, 1 TO 1)%@NL@%
  4607. DIM Dum$(1 TO 1)%@NL@%
  4608. %@NL@%
  4609. %@AB@%        ' Check initialization and fonts:%@AE@%%@NL@%
  4610.         clClearError%@NL@%
  4611.         clChkInit%@NL@%
  4612.         clChkFonts%@NL@%
  4613.         IF ChartErr >= 100 THEN EXIT SUB%@NL@%
  4614. %@NL@%
  4615. %@AB@%        ' Set a global flag to indicate that this isn't a multiple-series chart:%@AE@%%@NL@%
  4616.         GP.MSeries = cNo%@NL@%
  4617. %@NL@%
  4618. %@AB@%        ' Check for obvious parameter and ChartEnvironment errors:%@AE@%%@NL@%
  4619.         clChkForErrors Env, 1, 3, N, 0, 0%@NL@%
  4620.         IF ChartErr > 100 THEN EXIT SUB%@NL@%
  4621. %@NL@%
  4622. %@AB@%        ' Make a copy of the user's ChartEnvironment variable to the library's%@AE@%%@NL@%
  4623. %@AB@%        ' global environment variable:%@AE@%%@NL@%
  4624.         GE = Env%@NL@%
  4625. %@NL@%
  4626. %@AB@%        ' Set the correct axis modes for the type of chart specified in the%@AE@%%@NL@%
  4627. %@AB@%        ' chart environment:%@AE@%%@NL@%
  4628.         clSetAxisModes%@NL@%
  4629. %@NL@%
  4630. %@AB@%        ' Transfer the input data to the dynamic working data array.  Do this%@AE@%%@NL@%
  4631. %@AB@%        ' for each axis because, depending on the chart type, either one may be%@AE@%%@NL@%
  4632. %@AB@%        ' the value axis.  The Filter routine automatically ignores the call if%@AE@%%@NL@%
  4633. %@AB@%        ' the axis is a category axis:%@AE@%%@NL@%
  4634.         clFilter GE.XAxis, GP.XMode, value(), V1(), N%@NL@%
  4635.         clFilter GE.YAxis, GP.YMode, value(), V1(), N%@NL@%
  4636. %@NL@%
  4637. %@AB@%        ' Analyze the data for scale-maximum and -minimum and set the scale-%@AE@%%@NL@%
  4638. %@AB@%        ' factor, etc. depending on the options set in the chart environment:%@AE@%%@NL@%
  4639.         clAnalyzeC Cat$(), N, Dum$(), 1, 1%@NL@%
  4640. %@NL@%
  4641. %@AB@%        ' Copy the global chart environment back to the user's ChartEnvironment%@AE@%%@NL@%
  4642. %@AB@%        ' variable so that the settings that were calculated by the library are%@AE@%%@NL@%
  4643. %@AB@%        ' accessible.  Then, if this routine wasn't called by the library itself,%@AE@%%@NL@%
  4644. %@AB@%        ' in the course of drawing a bar, column or line chart, deallocate the%@AE@%%@NL@%
  4645. %@AB@%        ' working data array:%@AE@%%@NL@%
  4646.         Env = GE%@NL@%
  4647.         IF GP.SysFlag = cNo THEN ERASE V1%@NL@%
  4648. %@NL@%
  4649. END SUB%@NL@%
  4650. %@NL@%
  4651. %@AB@%'=== AnalyzeChartMS - Analyzes multiple-series data for scale/window size.%@AE@%%@NL@%
  4652. %@AB@%'%@AE@%%@NL@%
  4653. %@AB@%'  Arguments:%@AE@%%@NL@%
  4654. %@AB@%'     Env             - ChartEnvironment variable%@AE@%%@NL@%
  4655. %@AB@%'%@AE@%%@NL@%
  4656. %@AB@%'     Cat$(1)         - One-dimensional array of category labels%@AE@%%@NL@%
  4657. %@AB@%'%@AE@%%@NL@%
  4658. %@AB@%'     Value(2)        - Two-dimensional array of values to chart.  First%@AE@%%@NL@%
  4659. %@AB@%'                       dimension (rows) represents different values within%@AE@%%@NL@%
  4660. %@AB@%'                       a series.  Second dimension (columns) represents%@AE@%%@NL@%
  4661. %@AB@%'                       different series.%@AE@%%@NL@%
  4662. %@AB@%'%@AE@%%@NL@%
  4663. %@AB@%'     N%              - Number of values (beginning with 1) to chart per%@AE@%%@NL@%
  4664. %@AB@%'                       series.%@AE@%%@NL@%
  4665. %@AB@%'%@AE@%%@NL@%
  4666. %@AB@%'     First%          - First series to analyze%@AE@%%@NL@%
  4667. %@AB@%'%@AE@%%@NL@%
  4668. %@AB@%'     Last%           - Last series to analyze%@AE@%%@NL@%
  4669. %@AB@%'%@AE@%%@NL@%
  4670. %@AB@%'     SeriesLabel$(1) - Labels for the different series%@AE@%%@NL@%
  4671. %@AB@%'%@AE@%%@NL@%
  4672. %@AB@%'  Return Values:%@AE@%%@NL@%
  4673. %@AB@%'     Various settings in the Env variable are altered in accordance with%@AE@%%@NL@%
  4674. %@AB@%'     the analysis.%@AE@%%@NL@%
  4675. %@AB@%'%@AE@%%@NL@%
  4676. %@AB@%'=================================================================%@AE@%%@NL@%
  4677. SUB AnalyzeChartMS (Env AS ChartEnvironment, Cat$(), value() AS SINGLE, N AS INTEGER, First AS INTEGER, Last AS INTEGER, SeriesLabel$())%@NL@%
  4678. %@NL@%
  4679. SHARED GE AS ChartEnvironment, GP AS GlobalParams%@NL@%
  4680. SHARED V1()%@NL@%
  4681. REDIM V1(1 TO N, 1 TO Last - First + 1)%@NL@%
  4682. %@NL@%
  4683. %@AB@%        ' Check initialization and fonts:%@AE@%%@NL@%
  4684.         clClearError%@NL@%
  4685.         clChkInit%@NL@%
  4686.         clChkFonts%@NL@%
  4687.         IF ChartErr >= 100 THEN EXIT SUB%@NL@%
  4688. %@NL@%
  4689. %@AB@%        ' Set a global flag to indicate that this is a multiple-series chart:%@AE@%%@NL@%
  4690.         GP.MSeries = cYes%@NL@%
  4691. %@NL@%
  4692. %@AB@%        ' Check for obvious parameter and ChartEnvironment errors:%@AE@%%@NL@%
  4693.         clChkForErrors Env, 1, 3, N, 0, 0%@NL@%
  4694.         IF ChartErr > 100 THEN EXIT SUB%@NL@%
  4695. %@NL@%
  4696. %@AB@%        ' Make a copy of the user's ChartEnvironment variable to the library's%@AE@%%@NL@%
  4697. %@AB@%        ' global environment variable:%@AE@%%@NL@%
  4698.         GE = Env%@NL@%
  4699. %@NL@%
  4700. %@AB@%        ' Set the correct axis modes for the type of chart specified in the%@AE@%%@NL@%
  4701. %@AB@%        ' chart environment:%@AE@%%@NL@%
  4702.         clSetAxisModes%@NL@%
  4703. %@NL@%
  4704. %@AB@%        ' Transfer the input data to the dynamic working data array.  Do this%@AE@%%@NL@%
  4705. %@AB@%        ' for each axis because, depending on the chart type, either one may be%@AE@%%@NL@%
  4706. %@AB@%        ' the value axis.  The Filter routine automatically ignores the call if%@AE@%%@NL@%
  4707. %@AB@%        ' the axis is a category axis:%@AE@%%@NL@%
  4708.         clFilterMS GE.XAxis, GP.XMode, value(), V1(), N, First, Last%@NL@%
  4709.         clFilterMS GE.YAxis, GP.YMode, value(), V1(), N, First, Last%@NL@%
  4710. %@NL@%
  4711. %@AB@%        ' Analyze the data for scale maximums and minimums and set the scale%@AE@%%@NL@%
  4712. %@AB@%        ' factor, etc. depending on the options set in the chart environment:%@AE@%%@NL@%
  4713.         clAnalyzeC Cat$(), N, SeriesLabel$(), First, Last%@NL@%
  4714. %@NL@%
  4715. %@AB@%        ' Copy the global chart environment back to the user's ChartEnvironment%@AE@%%@NL@%
  4716. %@AB@%        ' variable so that the settings that were calculated by the library are%@AE@%%@NL@%
  4717. %@AB@%        ' accessible.  Then, if this routine wasn't called by the library itself,%@AE@%%@NL@%
  4718. %@AB@%        ' in the course of drawing a bar, column or line chart, deallocate the%@AE@%%@NL@%
  4719. %@AB@%        ' working data array:%@AE@%%@NL@%
  4720.         Env = GE%@NL@%
  4721.         IF GP.SysFlag = cNo THEN ERASE V1%@NL@%
  4722. %@NL@%
  4723. END SUB%@NL@%
  4724. %@NL@%
  4725. %@AB@%'=== AnalyzePie - Analyzes data for a pie chart%@AE@%%@NL@%
  4726. %@AB@%'%@AE@%%@NL@%
  4727. %@AB@%'  Arguments:%@AE@%%@NL@%
  4728. %@AB@%'     Env      - A ChartEnvironment variable%@AE@%%@NL@%
  4729. %@AB@%'%@AE@%%@NL@%
  4730. %@AB@%'     Cat$()   - One-dimensional array of category names%@AE@%%@NL@%
  4731. %@AB@%'%@AE@%%@NL@%
  4732. %@AB@%'     Value()  - One-dimensional array of values to chart%@AE@%%@NL@%
  4733. %@AB@%'%@AE@%%@NL@%
  4734. %@AB@%'     Expl()   - One dimensional array of flags indicating whether slices%@AE@%%@NL@%
  4735. %@AB@%'                are to be "exploded" (0 means no, 1 means yes).%@AE@%%@NL@%
  4736. %@AB@%'                Ignored if Env.ChartStyle <> 1.%@AE@%%@NL@%
  4737. %@AB@%'%@AE@%%@NL@%
  4738. %@AB@%'     N        - The number of values to chart%@AE@%%@NL@%
  4739. %@AB@%'%@AE@%%@NL@%
  4740. %@AB@%'  Return Values:%@AE@%%@NL@%
  4741. %@AB@%'     None.%@AE@%%@NL@%
  4742. %@AB@%'%@AE@%%@NL@%
  4743. %@AB@%'=================================================================%@AE@%%@NL@%
  4744. SUB AnalyzePie (Env AS ChartEnvironment, Cat$(), value() AS SINGLE, Expl() AS INTEGER, N AS INTEGER)%@NL@%
  4745. SHARED GE AS ChartEnvironment%@NL@%
  4746. SHARED GP AS GlobalParams%@NL@%
  4747. SHARED TTitleLayout AS TitleLayout%@NL@%
  4748. SHARED XTitleLayout AS TitleLayout%@NL@%
  4749. SHARED YTitleLayout AS TitleLayout%@NL@%
  4750. SHARED V1()%@NL@%
  4751. DIM EmptyTitle AS TitleType%@NL@%
  4752. %@NL@%
  4753. %@AB@%        ' Check initialization and fonts:%@AE@%%@NL@%
  4754.         clClearError%@NL@%
  4755.         clChkInit%@NL@%
  4756.         clChkFonts%@NL@%
  4757.         IF ChartErr >= 100 THEN EXIT SUB%@NL@%
  4758. %@NL@%
  4759. %@AB@%        ' This is a multiple series chart (a pie chart is treated as a%@AE@%%@NL@%
  4760. %@AB@%        ' multiple series chart with each series having one value):%@AE@%%@NL@%
  4761.         GP.MSeries = cYes%@NL@%
  4762.         GP.NSeries = N%@NL@%
  4763. %@NL@%
  4764. %@AB@%        ' Check for obvious parameter and ChartEnvironment errors:%@AE@%%@NL@%
  4765.         clChkForErrors Env, cPie, cPie, 2, 1, N%@NL@%
  4766.         IF ChartErr > 100 THEN EXIT SUB%@NL@%
  4767. %@NL@%
  4768. %@AB@%        ' Make a copy of the user's ChartEnvironment variable to the library's%@AE@%%@NL@%
  4769. %@AB@%        ' global environment variable:%@AE@%%@NL@%
  4770.         GE = Env%@NL@%
  4771. %@NL@%
  4772. %@AB@%        ' Set the correct axis modes for the type of chart specified in the%@AE@%%@NL@%
  4773. %@AB@%        ' chart environment:%@AE@%%@NL@%
  4774.         clSetAxisModes%@NL@%
  4775. %@NL@%
  4776. %@AB@%        ' Set global parameters and layout main title:%@AE@%%@NL@%
  4777.         clSetGlobalParams%@NL@%
  4778. %@NL@%
  4779. %@AB@%        ' Layout titles (ignore X and Y axis titles):%@AE@%%@NL@%
  4780.         clLayoutTitle TTitleLayout, GE.MainTitle, GE.SubTitle%@NL@%
  4781.         EmptyTitle.Title = ""%@NL@%
  4782.         clLayoutTitle XTitleLayout, EmptyTitle, EmptyTitle%@NL@%
  4783.         clLayoutTitle YTitleLayout, EmptyTitle, EmptyTitle%@NL@%
  4784. %@NL@%
  4785. %@AB@%        ' Calculate the size for LegendWindow and DataWindow:%@AE@%%@NL@%
  4786.         clLayoutLegend Cat$(), 1, N%@NL@%
  4787.         IF ChartErr > 100 THEN EXIT SUB%@NL@%
  4788.         clSizeDataWindow Cat$()%@NL@%
  4789.         IF ChartErr > 100 THEN EXIT SUB%@NL@%
  4790. %@NL@%
  4791. %@AB@%        ' Copy the global chart environment back to the user's ChartEnvironment%@AE@%%@NL@%
  4792. %@AB@%        ' variable so that the settings that were calculated by the library are%@AE@%%@NL@%
  4793. %@AB@%        ' accessible.  Then, if this routine wasn't called by the library itself,%@AE@%%@NL@%
  4794. %@AB@%        ' in the course of drawing a pie chart, deallocate the working data array:%@AE@%%@NL@%
  4795.         Env = GE%@NL@%
  4796. %@NL@%
  4797. END SUB%@NL@%
  4798. %@NL@%
  4799. %@AB@%'=== AnalyzeScatter - Sets up scales and data-window sizes for scatter chart%@AE@%%@NL@%
  4800. %@AB@%'%@AE@%%@NL@%
  4801. %@AB@%'  Arguments:%@AE@%%@NL@%
  4802. %@AB@%'     Env        - A ChartEnvironment variable%@AE@%%@NL@%
  4803. %@AB@%'%@AE@%%@NL@%
  4804. %@AB@%'     ValX(1)    - One-dimensional array of values for X axis%@AE@%%@NL@%
  4805. %@AB@%'%@AE@%%@NL@%
  4806. %@AB@%'     ValY(1)    - One-dimensional array of values for Y axis%@AE@%%@NL@%
  4807. %@AB@%'%@AE@%%@NL@%
  4808. %@AB@%'     N%         - The number of data values in data series%@AE@%%@NL@%
  4809. %@AB@%'%@AE@%%@NL@%
  4810. %@AB@%'  Return Values:%@AE@%%@NL@%
  4811. %@AB@%'     Scale and data-window values are changed as appropriate.%@AE@%%@NL@%
  4812. %@AB@%'%@AE@%%@NL@%
  4813. %@AB@%'=================================================================%@AE@%%@NL@%
  4814. SUB AnalyzeScatter (Env AS ChartEnvironment, ValX() AS SINGLE, ValY() AS SINGLE, N AS INTEGER)%@NL@%
  4815. %@NL@%
  4816. SHARED GE AS ChartEnvironment, GP AS GlobalParams%@NL@%
  4817. SHARED V1(), V2()%@NL@%
  4818. REDIM V1(1 TO N, 1 TO 1), V2(1 TO N, 1 TO 1)%@NL@%
  4819. DIM Dum$(1 TO 1)%@NL@%
  4820. %@NL@%
  4821. %@AB@%        ' Check initialization and fonts:%@AE@%%@NL@%
  4822.         clClearError%@NL@%
  4823.         clChkInit%@NL@%
  4824.         clChkFonts%@NL@%
  4825.         IF ChartErr >= 100 THEN EXIT SUB%@NL@%
  4826. %@NL@%
  4827. %@AB@%        ' Set a global flag to indicate that this isn't a multiple-series chart:%@AE@%%@NL@%
  4828.         GP.MSeries = cNo%@NL@%
  4829. %@NL@%
  4830. %@AB@%        ' Check for obvious parameter and ChartEnvironment errors:%@AE@%%@NL@%
  4831.         clChkForErrors Env, 4, 4, N%, 0, 0%@NL@%
  4832.         IF ChartErr > 100 THEN EXIT SUB%@NL@%
  4833. %@NL@%
  4834. %@AB@%        ' Make a copy of the user's ChartEnvironment variable to the library's%@AE@%%@NL@%
  4835. %@AB@%        ' global environment variable:%@AE@%%@NL@%
  4836.         GE = Env%@NL@%
  4837. %@NL@%
  4838. %@AB@%        ' Set the correct axis modes for the type of chart specified in the%@AE@%%@NL@%
  4839. %@AB@%        ' chart environment:%@AE@%%@NL@%
  4840.         clSetAxisModes%@NL@%
  4841. %@NL@%
  4842. %@AB@%        ' Transfer the input data to the dynamic working data arrays (one%@AE@%%@NL@%
  4843. %@AB@%        ' for each axis):%@AE@%%@NL@%
  4844.         clFilter GE.XAxis, GP.XMode, ValX(), V1(), N%@NL@%
  4845.         clFilter GE.YAxis, GP.YMode, ValY(), V2(), N%@NL@%
  4846. %@NL@%
  4847. %@AB@%        ' Analyze the data for scale-maximum and -minimum and set the scale-%@AE@%%@NL@%
  4848. %@AB@%        ' factor, etc. depending on the options set in the chart environment:%@AE@%%@NL@%
  4849.         clAnalyzeS N, Dum$(), 1, 1%@NL@%
  4850. %@NL@%
  4851. %@AB@%        ' Copy the global chart environment back to the user's ChartEnvironment%@AE@%%@NL@%
  4852. %@AB@%        ' variable so that the settings that were calculated by the library are%@AE@%%@NL@%
  4853. %@AB@%        ' accessible.  Then, if this routine wasn't called by the library itself,%@AE@%%@NL@%
  4854. %@AB@%        ' in the course of drawing a scatter chart, deallocate the working%@AE@%%@NL@%
  4855. %@AB@%        ' data arrays:%@AE@%%@NL@%
  4856.         Env = GE%@NL@%
  4857.         IF GP.SysFlag = cNo THEN ERASE V1, V2%@NL@%
  4858. %@NL@%
  4859. END SUB%@NL@%
  4860. %@NL@%
  4861. %@AB@%'=== AnalyzeScatterMS - Analyzes multiple-series data for scale/window size%@AE@%%@NL@%
  4862. %@AB@%'%@AE@%%@NL@%
  4863. %@AB@%'  Arguments:%@AE@%%@NL@%
  4864. %@AB@%'     Env             - A ChartEnvironment variable%@AE@%%@NL@%
  4865. %@AB@%'%@AE@%%@NL@%
  4866. %@AB@%'     ValX(2)         - Two-dimensional array of values for X axis.  First%@AE@%%@NL@%
  4867. %@AB@%'                       dimension (rows) represents different values within%@AE@%%@NL@%
  4868. %@AB@%'                       a series.  Second dimension (columns) represents%@AE@%%@NL@%
  4869. %@AB@%'                       different series.%@AE@%%@NL@%
  4870. %@AB@%'%@AE@%%@NL@%
  4871. %@AB@%'     ValY(2)         - Two-dimensional array of values for Y axis.  Above%@AE@%%@NL@%
  4872. %@AB@%'                       comments apply%@AE@%%@NL@%
  4873. %@AB@%'%@AE@%%@NL@%
  4874. %@AB@%'     N%              - Number of values (beginning with 1) to chart per%@AE@%%@NL@%
  4875. %@AB@%'                       series%@AE@%%@NL@%
  4876. %@AB@%'%@AE@%%@NL@%
  4877. %@AB@%'     First%          - First series to analyze%@AE@%%@NL@%
  4878. %@AB@%'%@AE@%%@NL@%
  4879. %@AB@%'     Last%           - Last series to analyze%@AE@%%@NL@%
  4880. %@AB@%'%@AE@%%@NL@%
  4881. %@AB@%'     SeriesLabel$(1) - Labels for the different series%@AE@%%@NL@%
  4882. %@AB@%'%@AE@%%@NL@%
  4883. %@AB@%'  Return Values:%@AE@%%@NL@%
  4884. %@AB@%'     Various settings in the Env variable are altered in accordance with%@AE@%%@NL@%
  4885. %@AB@%'     the analysis.%@AE@%%@NL@%
  4886. %@AB@%'%@AE@%%@NL@%
  4887. %@AB@%'=================================================================%@AE@%%@NL@%
  4888. SUB AnalyzeScatterMS (Env AS ChartEnvironment, ValX() AS SINGLE, ValY() AS SINGLE, N AS INTEGER, First AS INTEGER, Last AS INTEGER, SeriesLabel$())%@NL@%
  4889. %@NL@%
  4890. SHARED GE AS ChartEnvironment, GP AS GlobalParams%@NL@%
  4891. SHARED V1(), V2()%@NL@%
  4892. REDIM V1(1 TO N, 1 TO Last - First + 1), V2(1 TO N, 1 TO Last - First + 1)%@NL@%
  4893. DIM Dum$(1 TO 1)%@NL@%
  4894. %@NL@%
  4895. %@AB@%        ' Check initialization and fonts:%@AE@%%@NL@%
  4896.         clClearError%@NL@%
  4897.         clChkInit%@NL@%
  4898.         clChkFonts%@NL@%
  4899.         IF ChartErr >= 100 THEN EXIT SUB%@NL@%
  4900. %@NL@%
  4901. %@AB@%        ' Set a global flag to indicate that this is a multiple-series chart:%@AE@%%@NL@%
  4902.         GP.MSeries = cYes%@NL@%
  4903. %@NL@%
  4904. %@AB@%        ' Check for obvious parameter and ChartEnvironment errors:%@AE@%%@NL@%
  4905.         clChkForErrors Env, 4, 4, N%, 0, 0%@NL@%
  4906.         IF ChartErr > 100 THEN EXIT SUB%@NL@%
  4907. %@NL@%
  4908. %@AB@%        ' Make a copy of the user's ChartEnvironment variable to the library's%@AE@%%@NL@%
  4909. %@AB@%        ' global environment variable:%@AE@%%@NL@%
  4910.         GE = Env%@NL@%
  4911. %@NL@%
  4912. %@AB@%        ' Set the correct axis modes for the type of chart specified in the%@AE@%%@NL@%
  4913. %@AB@%        ' chart environment:%@AE@%%@NL@%
  4914.         clSetAxisModes%@NL@%
  4915. %@NL@%
  4916. %@AB@%        ' Transfer the input data to the dynamic working data arrays (one%@AE@%%@NL@%
  4917. %@AB@%        ' for each axis):%@AE@%%@NL@%
  4918.         clFilterMS GE.XAxis, GP.XMode, ValX(), V1(), N, First, Last%@NL@%
  4919.         clFilterMS GE.YAxis, GP.YMode, ValY(), V2(), N, First, Last%@NL@%
  4920. %@NL@%
  4921. %@AB@%        ' Analyze the data for scale-maximum and -minimum and set the scale-%@AE@%%@NL@%
  4922. %@AB@%        ' factor, etc. depending on the options set in the chart environment:%@AE@%%@NL@%
  4923.         clAnalyzeS N, SeriesLabel$(), First%, Last%%@NL@%
  4924. %@NL@%
  4925. %@AB@%        ' Copy the global chart environment back to the user's ChartEnvironment%@AE@%%@NL@%
  4926. %@AB@%        ' variable so that the settings that were calculated by the library are%@AE@%%@NL@%
  4927. %@AB@%        ' accessible.  Then, if this routine wasn't called by the library itself,%@AE@%%@NL@%
  4928. %@AB@%        ' in the course of drawing a scatter chart, deallocate the working%@AE@%%@NL@%
  4929. %@AB@%        ' data arrays:%@AE@%%@NL@%
  4930.         Env = GE%@NL@%
  4931.         IF GP.SysFlag = cNo THEN ERASE V1, V2%@NL@%
  4932. %@NL@%
  4933. END SUB%@NL@%
  4934. %@NL@%
  4935. %@AB@%'=== Chart - Draws a single-series category/value chart%@AE@%%@NL@%
  4936. %@AB@%'%@AE@%%@NL@%
  4937. %@AB@%'  Arguments:%@AE@%%@NL@%
  4938. %@AB@%'     Env        - A ChartEnvironment variable%@AE@%%@NL@%
  4939. %@AB@%'%@AE@%%@NL@%
  4940. %@AB@%'     Cat$(1)    - One-dimensional array of category labels%@AE@%%@NL@%
  4941. %@AB@%'%@AE@%%@NL@%
  4942. %@AB@%'     Value(1)   - One-dimensional array of values to plot%@AE@%%@NL@%
  4943. %@AB@%'%@AE@%%@NL@%
  4944. %@AB@%'     N          - The number of data values in data series%@AE@%%@NL@%
  4945. %@AB@%'%@AE@%%@NL@%
  4946. %@AB@%'  Return Values:%@AE@%%@NL@%
  4947. %@AB@%'     Some elements of the Env variable are altered by plotting routines%@AE@%%@NL@%
  4948. %@AB@%'%@AE@%%@NL@%
  4949. %@AB@%'  Remarks:%@AE@%%@NL@%
  4950. %@AB@%'     This routine takes all of the parameters set in the Env variable%@AE@%%@NL@%
  4951. %@AB@%'     and draws a single-series chart of type Bar, Column, or Line%@AE@%%@NL@%
  4952. %@AB@%'     depending on the chart type specified in the Env variable.%@AE@%%@NL@%
  4953. %@AB@%'%@AE@%%@NL@%
  4954. %@AB@%'=================================================================%@AE@%%@NL@%
  4955. SUB Chart (Env AS ChartEnvironment, Cat$(), value() AS SINGLE, N AS INTEGER)%@NL@%
  4956. %@NL@%
  4957. SHARED V1()%@NL@%
  4958. %@NL@%
  4959. %@AB@%        ' Analyze data for scale and window settings:%@AE@%%@NL@%
  4960.         clFlagSystem%@NL@%
  4961.         AnalyzeChart Env, Cat$(), value(), N%@NL@%
  4962.         clUnFlagSystem%@NL@%
  4963.         IF ChartErr < 100 THEN%@NL@%
  4964. %@NL@%
  4965. %@AB@%                ' Draw the different elements of the chart:%@AE@%%@NL@%
  4966.                 clDrawChartWindow%@NL@%
  4967.                 clDrawTitles%@NL@%
  4968.                 clDrawDataWindow%@NL@%
  4969.                 clDrawAxes Cat$()%@NL@%
  4970. %@NL@%
  4971. %@AB@%                ' Call appropriate Draw...Data routine for chart type:%@AE@%%@NL@%
  4972.                 SELECT CASE Env.ChartType%@NL@%
  4973.                         CASE 1: clDrawBarData%@NL@%
  4974.                         CASE 2: clDrawColumnData%@NL@%
  4975.                         CASE 3: clDrawLineData%@NL@%
  4976.                 END SELECT%@NL@%
  4977. %@NL@%
  4978.         END IF%@NL@%
  4979. %@NL@%
  4980. %@AB@%        ' Deallocate the data array:%@AE@%%@NL@%
  4981.         ERASE V1%@NL@%
  4982. %@NL@%
  4983. END SUB%@NL@%
  4984. %@NL@%
  4985. %@AB@%'=== ChartMS - Draws a multiple-series category/value chart%@AE@%%@NL@%
  4986. %@AB@%'%@AE@%%@NL@%
  4987. %@AB@%'  Arguments:%@AE@%%@NL@%
  4988. %@AB@%'     Env               - A ChartEnvironment variable%@AE@%%@NL@%
  4989. %@AB@%'%@AE@%%@NL@%
  4990. %@AB@%'     Cat$(1)           - A one-dimensional array of category names for the%@AE@%%@NL@%
  4991. %@AB@%'                         different data values%@AE@%%@NL@%
  4992. %@AB@%'%@AE@%%@NL@%
  4993. %@AB@%'     Value(2)          - A two-dimensional array of values--one column for%@AE@%%@NL@%
  4994. %@AB@%'                         each series of data%@AE@%%@NL@%
  4995. %@AB@%'%@AE@%%@NL@%
  4996. %@AB@%'     N%                - The number of data points in each series of data%@AE@%%@NL@%
  4997. %@AB@%'%@AE@%%@NL@%
  4998. %@AB@%'     First%            - The first series to be plotted%@AE@%%@NL@%
  4999. %@AB@%'%@AE@%%@NL@%
  5000. %@AB@%'     Last%             - The last series to be plotted%@AE@%%@NL@%
  5001. %@AB@%'%@AE@%%@NL@%
  5002. %@AB@%'     SeriesLabel$(1)   - Labels used for each series in the legend%@AE@%%@NL@%
  5003. %@AB@%'%@AE@%%@NL@%
  5004. %@AB@%'  Return Values:%@AE@%%@NL@%
  5005. %@AB@%'     Some elements of the Env variable are altered by plotting routines%@AE@%%@NL@%
  5006. %@AB@%'%@AE@%%@NL@%
  5007. %@AB@%'  Remarks:%@AE@%%@NL@%
  5008. %@AB@%'     This routine takes all of the parameters set in the Env variable%@AE@%%@NL@%
  5009. %@AB@%'     and draws a multiple-series chart of type Bar, Column, or Line%@AE@%%@NL@%
  5010. %@AB@%'     depending on the chart type specified in the Env variable.%@AE@%%@NL@%
  5011. %@AB@%'%@AE@%%@NL@%
  5012. %@AB@%'=================================================================%@AE@%%@NL@%
  5013. SUB ChartMS (Env AS ChartEnvironment, Cat$(), value() AS SINGLE, N AS INTEGER, First AS INTEGER, Last AS INTEGER, SeriesLabel$())%@NL@%
  5014. %@NL@%
  5015. SHARED V1()%@NL@%
  5016. %@NL@%
  5017. %@AB@%        ' Analyze data for scale settings:%@AE@%%@NL@%
  5018.         clFlagSystem%@NL@%
  5019.         AnalyzeChartMS Env, Cat$(), value(), N, First, Last, SeriesLabel$()%@NL@%
  5020.         clUnFlagSystem%@NL@%
  5021.         IF ChartErr < 100 THEN%@NL@%
  5022. %@NL@%
  5023. %@AB@%                ' Draw the different elements of the chart:%@AE@%%@NL@%
  5024.                 clDrawChartWindow%@NL@%
  5025.                 clDrawTitles%@NL@%
  5026.                 clDrawDataWindow%@NL@%
  5027.                 clDrawAxes Cat$()%@NL@%
  5028. %@NL@%
  5029. %@AB@%                ' Call appropriate Draw...DataMS routine for chart type:%@AE@%%@NL@%
  5030.                 SELECT CASE Env.ChartType%@NL@%
  5031.                         CASE 1: clDrawBarData%@NL@%
  5032.                         CASE 2: clDrawColumnData%@NL@%
  5033.                         CASE 3: clDrawLineData%@NL@%
  5034.                 END SELECT%@NL@%
  5035. %@NL@%
  5036. %@AB@%                ' Lastly, add the legend:%@AE@%%@NL@%
  5037.                 clDrawLegend SeriesLabel$(), First, Last%@NL@%
  5038. %@NL@%
  5039.         END IF%@NL@%
  5040. %@NL@%
  5041. %@AB@%        ' Deallocate the data array:%@AE@%%@NL@%
  5042.         ERASE V1%@NL@%
  5043. %@NL@%
  5044. END SUB%@NL@%
  5045. %@NL@%
  5046. %@AB@%'=== ChartPie - Draws a pie chart%@AE@%%@NL@%
  5047. %@AB@%'%@AE@%%@NL@%
  5048. %@AB@%'  Arguments:%@AE@%%@NL@%
  5049. %@AB@%'     Env      - A ChartEnvironment variable%@AE@%%@NL@%
  5050. %@AB@%'%@AE@%%@NL@%
  5051. %@AB@%'     Cat$()   - One-dimensional array of category names%@AE@%%@NL@%
  5052. %@AB@%'%@AE@%%@NL@%
  5053. %@AB@%'     Value()  - One-dimensional array of values to chart%@AE@%%@NL@%
  5054. %@AB@%'%@AE@%%@NL@%
  5055. %@AB@%'     Expl%()  - One-dimensional array of flags indicating whether slices%@AE@%%@NL@%
  5056. %@AB@%'                are to be "exploded" or not (0 means no, 1 means yes),%@AE@%%@NL@%
  5057. %@AB@%'                ignored if ChartStyle <> 1%@AE@%%@NL@%
  5058. %@AB@%'%@AE@%%@NL@%
  5059. %@AB@%'     N%       - The number of values to chart%@AE@%%@NL@%
  5060. %@AB@%'%@AE@%%@NL@%
  5061. %@AB@%'  Return Values:%@AE@%%@NL@%
  5062. %@AB@%'     No return values%@AE@%%@NL@%
  5063. %@AB@%'%@AE@%%@NL@%
  5064. %@AB@%'=================================================================%@AE@%%@NL@%
  5065. SUB ChartPie (Env AS ChartEnvironment, Cat$(), value() AS SINGLE, Expl() AS INTEGER, N AS INTEGER)%@NL@%
  5066. SHARED GP AS GlobalParams%@NL@%
  5067. %@AB@%        ' Set the global system flag to tell the AnalyzePie routine that it%@AE@%%@NL@%
  5068. %@AB@%        ' is being called by the system and not the user:%@AE@%%@NL@%
  5069.         clFlagSystem%@NL@%
  5070. %@NL@%
  5071. %@AB@%        ' Calculate the size of the Data- and Legend-window:%@AE@%%@NL@%
  5072.         AnalyzePie Env, Cat$(), value(), Expl(), N%@NL@%
  5073. %@NL@%
  5074. %@AB@%        ' Remove the system flag:%@AE@%%@NL@%
  5075.         clUnFlagSystem%@NL@%
  5076. %@NL@%
  5077. %@AB@%        ' If there were no errors during analysis draw the chart:%@AE@%%@NL@%
  5078.         IF ChartErr < 100 THEN%@NL@%
  5079. %@NL@%
  5080. %@AB@%                ' Draw the different chart elements:%@AE@%%@NL@%
  5081.                 clDrawChartWindow%@NL@%
  5082.                 clDrawTitles%@NL@%
  5083.                 clDrawDataWindow%@NL@%
  5084.                 clDrawPieData value(), Expl(), N%@NL@%
  5085.                 IF ChartErr <> 0 THEN EXIT SUB%@NL@%
  5086.                 clDrawLegend Cat$(), 1, N%@NL@%
  5087. %@NL@%
  5088.         END IF%@NL@%
  5089. %@NL@%
  5090. END SUB%@NL@%
  5091. %@NL@%
  5092. %@AB@%'=== ChartScatter - Draws a single-series scatter chart%@AE@%%@NL@%
  5093. %@AB@%'%@AE@%%@NL@%
  5094. %@AB@%'  Arguments:%@AE@%%@NL@%
  5095. %@AB@%'     Env      - A ChartEnvironment variable%@AE@%%@NL@%
  5096. %@AB@%'%@AE@%%@NL@%
  5097. %@AB@%'     ValX(1)  - One-dimensional array of values for X axis%@AE@%%@NL@%
  5098. %@AB@%'%@AE@%%@NL@%
  5099. %@AB@%'     ValY(1)  - One-dimensional array of values for Y axis%@AE@%%@NL@%
  5100. %@AB@%'%@AE@%%@NL@%
  5101. %@AB@%'     N%       - The number of values to chart%@AE@%%@NL@%
  5102. %@AB@%'%@AE@%%@NL@%
  5103. %@AB@%'%@AE@%%@NL@%
  5104. %@AB@%'  Return Values:%@AE@%%@NL@%
  5105. %@AB@%'     Some elements of Env variable may be changed by drawing routines%@AE@%%@NL@%
  5106. %@AB@%'%@AE@%%@NL@%
  5107. %@AB@%'  Remarks:%@AE@%%@NL@%
  5108. %@AB@%'     ChartScatter should be called when a chart with two value axes is%@AE@%%@NL@%
  5109. %@AB@%'     desired%@AE@%%@NL@%
  5110. %@AB@%'%@AE@%%@NL@%
  5111. %@AB@%'=================================================================%@AE@%%@NL@%
  5112. SUB ChartScatter (Env AS ChartEnvironment, ValX() AS SINGLE, ValY() AS SINGLE, N AS INTEGER)%@NL@%
  5113. DIM Dum$(1 TO 1)%@NL@%
  5114. SHARED V1(), V2()%@NL@%
  5115. %@NL@%
  5116. %@AB@%        ' Set the global system flag to tell the AnalyzeScatter routine that it%@AE@%%@NL@%
  5117. %@AB@%        ' is being called by the system and not the user:%@AE@%%@NL@%
  5118.         clFlagSystem%@NL@%
  5119. %@NL@%
  5120. %@AB@%        ' Calculate the scale maximums and minimums and scale factor. Also%@AE@%%@NL@%
  5121. %@AB@%        ' calculate the sizes for the Data- and Legend-windows:%@AE@%%@NL@%
  5122.         AnalyzeScatter Env, ValX(), ValY(), N%@NL@%
  5123. %@NL@%
  5124. %@AB@%        ' Remove the system flag:%@AE@%%@NL@%
  5125.         clUnFlagSystem%@NL@%
  5126. %@NL@%
  5127. %@AB@%        ' If there were no errors during analysis draw the chart:%@AE@%%@NL@%
  5128.         IF ChartErr < 100 THEN%@NL@%
  5129. %@NL@%
  5130. %@AB@%                ' Draw the different elements of the chart:%@AE@%%@NL@%
  5131.                 clDrawChartWindow%@NL@%
  5132.                 clDrawTitles%@NL@%
  5133.                 clDrawDataWindow%@NL@%
  5134.                 clDrawAxes Dum$()%@NL@%
  5135.                 clDrawScatterData%@NL@%
  5136. %@NL@%
  5137.         END IF%@NL@%
  5138. %@NL@%
  5139. %@AB@%        ' Deallocate the dynamic working data arrays:%@AE@%%@NL@%
  5140.         ERASE V1, V2%@NL@%
  5141. %@NL@%
  5142. END SUB%@NL@%
  5143. %@NL@%
  5144. %@AB@%'=== ChartScatterMS - Draws a multiple-series scatter chart%@AE@%%@NL@%
  5145. %@AB@%'%@AE@%%@NL@%
  5146. %@AB@%'  Arguments:%@AE@%%@NL@%
  5147. %@AB@%'     Env            - A ChartEnvironment variable%@AE@%%@NL@%
  5148. %@AB@%'%@AE@%%@NL@%
  5149. %@AB@%'     ValX(2)        - Two-dimensional array of values for X axis%@AE@%%@NL@%
  5150. %@AB@%'%@AE@%%@NL@%
  5151. %@AB@%'     ValY(2)        - Two-dimensional array of values for Y axis%@AE@%%@NL@%
  5152. %@AB@%'%@AE@%%@NL@%
  5153. %@AB@%'     N%             - The number of values in each series%@AE@%%@NL@%
  5154. %@AB@%'%@AE@%%@NL@%
  5155. %@AB@%'     First%         - First series to chart (first column)%@AE@%%@NL@%
  5156. %@AB@%'%@AE@%%@NL@%
  5157. %@AB@%'     Last%          - Last series to chart (last column)%@AE@%%@NL@%
  5158. %@AB@%'%@AE@%%@NL@%
  5159. %@AB@%'     SeriesLabel$() - Label used for each series in legend%@AE@%%@NL@%
  5160. %@AB@%'%@AE@%%@NL@%
  5161. %@AB@%'%@AE@%%@NL@%
  5162. %@AB@%'  Return Values:%@AE@%%@NL@%
  5163. %@AB@%'     Some elements in Env variable may be changed by drawing routines%@AE@%%@NL@%
  5164. %@AB@%'%@AE@%%@NL@%
  5165. %@AB@%'  Remarks:%@AE@%%@NL@%
  5166. %@AB@%'     A scatter chart uses two value axes so it must have values for both%@AE@%%@NL@%
  5167. %@AB@%'     the X and Y axes (ValX(), ValY()).  The first dimension denotes%@AE@%%@NL@%
  5168. %@AB@%'     the different values within a series.  The second dimension specifies%@AE@%%@NL@%
  5169. %@AB@%'     different data series (e.g. ValX(4,3) would represent the fourth value%@AE@%%@NL@%
  5170. %@AB@%'     in the third series of data).%@AE@%%@NL@%
  5171. %@AB@%'%@AE@%%@NL@%
  5172. %@AB@%'=================================================================%@AE@%%@NL@%
  5173. SUB ChartScatterMS (Env AS ChartEnvironment, ValX() AS SINGLE, ValY() AS SINGLE, N AS INTEGER, First AS INTEGER, Last AS INTEGER, SeriesLabel$())%@NL@%
  5174. DIM Dum$(1 TO 1)%@NL@%
  5175. SHARED V1(), V2()%@NL@%
  5176. %@NL@%
  5177. %@AB@%        ' Set the global system flag to tell the AnalyzeScatterMS routine that it%@AE@%%@NL@%
  5178. %@AB@%        ' is being called by the system and not the user:%@AE@%%@NL@%
  5179.         clFlagSystem%@NL@%
  5180. %@NL@%
  5181. %@AB@%        ' Calculate the scale maximums and minimums and scale factor. Also%@AE@%%@NL@%
  5182. %@AB@%        ' calculate the sizes for the Data- and Legend-windows:%@AE@%%@NL@%
  5183.         AnalyzeScatterMS Env, ValX(), ValY(), N, First, Last, SeriesLabel$()%@NL@%
  5184. %@NL@%
  5185. %@AB@%        ' Remove the system flag:%@AE@%%@NL@%
  5186.         clUnFlagSystem%@NL@%
  5187. %@NL@%
  5188. %@AB@%        ' If there were no errors during analysis draw the chart:%@AE@%%@NL@%
  5189.         IF ChartErr < 100 THEN%@NL@%
  5190. %@NL@%
  5191. %@AB@%                ' Draw the different elements of the chart:%@AE@%%@NL@%
  5192.                 clDrawChartWindow%@NL@%
  5193.                 clDrawTitles%@NL@%
  5194.                 clDrawDataWindow%@NL@%
  5195.                 clDrawAxes Dum$()%@NL@%
  5196.                 clDrawScatterData%@NL@%
  5197.                 clDrawLegend SeriesLabel$(), First, Last%@NL@%
  5198. %@NL@%
  5199.         END IF%@NL@%
  5200. %@NL@%
  5201. %@AB@%        ' Deallocate the dynamic working data arrays:%@AE@%%@NL@%
  5202.         ERASE V1, V2%@NL@%
  5203. %@NL@%
  5204. END SUB%@NL@%
  5205. %@NL@%
  5206. %@AB@%'=== ChartScreen - Sets the SCREEN mode and default palettes%@AE@%%@NL@%
  5207. %@AB@%'%@AE@%%@NL@%
  5208. %@AB@%'  Arguments:%@AE@%%@NL@%
  5209. %@AB@%'     N%    - A valid BASIC graphic mode, or mode 0%@AE@%%@NL@%
  5210. %@AB@%'%@AE@%%@NL@%
  5211. %@AB@%'  Return Values:%@AE@%%@NL@%
  5212. %@AB@%'     All palettes may be altered%@AE@%%@NL@%
  5213. %@AB@%'%@AE@%%@NL@%
  5214. %@AB@%'=================================================================%@AE@%%@NL@%
  5215. SUB ChartScreen (N AS INTEGER)%@NL@%
  5216. SHARED GP AS GlobalParams%@NL@%
  5217. %@NL@%
  5218. %@AB@%        ' Check initialization and fonts:%@AE@%%@NL@%
  5219.         clClearError%@NL@%
  5220.         clChkInit%@NL@%
  5221. %@NL@%
  5222. %@AB@%        ' Set up branch to error processor and attempt to set the specified%@AE@%%@NL@%
  5223. %@AB@%        ' screen mode and draw to it:%@AE@%%@NL@%
  5224.         ON ERROR GOTO ScreenErr%@NL@%
  5225.         SCREEN N%@NL@%
  5226.         IF N <> 0 THEN PRESET (0, 0)%@NL@%
  5227.         ON ERROR GOTO UnexpectedErr%@NL@%
  5228. %@NL@%
  5229. %@AB@%        ' If the above PRESET failed, then the TestScreen error processor will%@AE@%%@NL@%
  5230. %@AB@%        ' have set the ChartErr error variable to a nonzero value.  If the last%@AE@%%@NL@%
  5231. %@AB@%        ' call to ChartScreen used the same mode, GP.PaletteScrn will equal N; and%@AE@%%@NL@%
  5232. %@AB@%        ' there is no need to rebuild palettes.  In either case there is no need%@AE@%%@NL@%
  5233. %@AB@%        ' to do anything else, so exit:%@AE@%%@NL@%
  5234.         IF ChartErr <> 0 OR (GP.PaletteScrn = N AND GP.PaletteSet) THEN EXIT SUB%@NL@%
  5235. %@NL@%
  5236. %@AB@%        ' This is a new screen mode so use the SELECT CASE statement below%@AE@%%@NL@%
  5237. %@AB@%        ' to handle it.  It sets the number of bits per pixel for a screen%@AE@%%@NL@%
  5238. %@AB@%        ' mode so that the palettes can be built properly:%@AE@%%@NL@%
  5239.         SELECT CASE N%@NL@%
  5240. %@NL@%
  5241. %@AB@%                ' Screen mode 0 is not a graphics mode and is included mainly for%@AE@%%@NL@%
  5242. %@AB@%                ' completeness.  The actual screen mode has been set above, so exit:%@AE@%%@NL@%
  5243.                 CASE 0:%@NL@%
  5244.                         EXIT SUB%@NL@%
  5245. %@NL@%
  5246.                 CASE 1:  Bits% = 2%@NL@%
  5247.                 CASE 2:  Bits% = 1%@NL@%
  5248.                 CASE 3:  Bits% = 1%@NL@%
  5249.                 CASE 4:  Bits% = 1%@NL@%
  5250.                 CASE 7:  Bits% = 4%@NL@%
  5251.                 CASE 8:  Bits% = 4%@NL@%
  5252.                 CASE 9:%@NL@%
  5253. %@AB@%                                        ' For screen mode 9, assume a 256K EGA and try setting%@AE@%%@NL@%
  5254. %@AB@%                                        ' a color to 63.  If that fails, assume it is a 64K EGA%@AE@%%@NL@%
  5255. %@AB@%                                        ' (the number of bit planes is four for 256K and two for%@AE@%%@NL@%
  5256. %@AB@%                                        ' 64K):%@AE@%%@NL@%
  5257.                                         Bits% = 4%@NL@%
  5258.                                         ON ERROR GOTO ScreenErr%@NL@%
  5259.                                         clClearError%@NL@%
  5260.                                         COLOR 15%@NL@%
  5261.                                         IF ChartErr <> 0 THEN Bits% = 2%@NL@%
  5262.                                         clClearError%@NL@%
  5263.                                         ON ERROR GOTO UnexpectedErr%@NL@%
  5264. %@NL@%
  5265.                 CASE 10: Bits% = 2%@NL@%
  5266.                 CASE 11: Bits% = 1%@NL@%
  5267.                 CASE 12: Bits% = 4%@NL@%
  5268.                 CASE 13: Bits% = 8%@NL@%
  5269. %@NL@%
  5270. %@AB@%                ' If none of the above match then a valid screen mode was specified;%@AE@%%@NL@%
  5271. %@AB@%                ' however the mode is un-supported so set error and exit:%@AE@%%@NL@%
  5272.                 CASE ELSE: clSetError cBadScreen%@NL@%
  5273.                                           EXIT SUB%@NL@%
  5274.         END SELECT%@NL@%
  5275. %@NL@%
  5276. %@AB@%        ' The screen aspect is 4/3 * MaxY/MaxX:%@AE@%%@NL@%
  5277.         VIEW%@NL@%
  5278.         WINDOW (0, 0)-(1, 1)%@NL@%
  5279.         GP.MaxXPix% = PMAP(1, 0) + 1%@NL@%
  5280.         GP.MaxYPix% = PMAP(0, 1) + 1%@NL@%
  5281.         GP.Aspect = 1.33333 * (GP.MaxYPix% - 1) / (GP.MaxXPix% - 1)%@NL@%
  5282.         WINDOW%@NL@%
  5283. %@NL@%
  5284. %@AB@%        ' The number of colors available:%@AE@%%@NL@%
  5285.         GP.MaxColor = 2 ^ Bits% - 1%@NL@%
  5286. %@NL@%
  5287. %@AB@%        ' Specify which color to use for white:%@AE@%%@NL@%
  5288.         SELECT CASE N%@NL@%
  5289.                 CASE 13: GP.White = 15%@NL@%
  5290.                 CASE ELSE: GP.White = GP.MaxColor%@NL@%
  5291.         END SELECT%@NL@%
  5292. %@NL@%
  5293. %@AB@%        ' Build palette for this screen mode:%@AE@%%@NL@%
  5294.         clBuildPalette N, Bits%%@NL@%
  5295. %@NL@%
  5296. END SUB%@NL@%
  5297. %@NL@%
  5298. %@AB@%'=== clAdjustScale - Calculates scaling factor for an axis and adjusts max-min%@AE@%%@NL@%
  5299. %@AB@%'                  as appropriate for scale factor and log base if log axis:%@AE@%%@NL@%
  5300. %@AB@%'%@AE@%%@NL@%
  5301. %@AB@%'  Arguments:%@AE@%%@NL@%
  5302. %@AB@%'     Axis  -  AxisType variable describing axis to be scaled.%@AE@%%@NL@%
  5303. %@AB@%'%@AE@%%@NL@%
  5304. %@AB@%'  Return Values:%@AE@%%@NL@%
  5305. %@AB@%'     May set the ScaleFactor and ScaleTitle elements and alter%@AE@%%@NL@%
  5306. %@AB@%'     ScaleMin and ScaleMax elements of the Axis variable.%@AE@%%@NL@%
  5307. %@AB@%'%@AE@%%@NL@%
  5308. %@AB@%'=================================================================%@AE@%%@NL@%
  5309. SUB clAdjustScale (Axis AS AxisType)%@NL@%
  5310. %@NL@%
  5311. %@AB@%        ' Don't try to scale a log axis:%@AE@%%@NL@%
  5312.         IF Axis.RangeType = cLog THEN%@NL@%
  5313. %@NL@%
  5314.                 Axis.ScaleFactor = 1%@NL@%
  5315.                 Axis.ScaleTitle.Title = "Log" + STR$(Axis.LogBase)%@NL@%
  5316. %@NL@%
  5317. %@AB@%        ' For a linear axis, choose a scale factor up to Trillions depending%@AE@%%@NL@%
  5318. %@AB@%        ' on the size of the axis limits:%@AE@%%@NL@%
  5319.         ELSE%@NL@%
  5320. %@NL@%
  5321. %@AB@%                ' Choose the largest ABS from Max and Min for the axis:%@AE@%%@NL@%
  5322.                 IF ABS(Axis.ScaleMax) > ABS(Axis.ScaleMin) THEN%@NL@%
  5323.                         Max = ABS(Axis.ScaleMax)%@NL@%
  5324.                 ELSE%@NL@%
  5325.                         Max = ABS(Axis.ScaleMin)%@NL@%
  5326.                 END IF%@NL@%
  5327. %@NL@%
  5328. %@AB@%                ' Find out power of three by which to scale:%@AE@%%@NL@%
  5329.                 Power% = INT((LOG(Max) / LOG(10)) / 3)%@NL@%
  5330. %@NL@%
  5331. %@AB@%                ' And, choose the correct title to go with it:%@AE@%%@NL@%
  5332.                 SELECT CASE Power%%@NL@%
  5333.                         CASE -4:     Axis.ScaleTitle.Title = "Trillionths"%@NL@%
  5334.                         CASE -3:     Axis.ScaleTitle.Title = "Billionths"%@NL@%
  5335.                         CASE -2:     Axis.ScaleTitle.Title = "Millionths"%@NL@%
  5336.                         CASE -1:     Axis.ScaleTitle.Title = "Thousandths"%@NL@%
  5337.                         CASE 0:     Axis.ScaleTitle.Title = ""%@NL@%
  5338.                         CASE 1:     Axis.ScaleTitle.Title = "Thousands"%@NL@%
  5339.                         CASE 2:     Axis.ScaleTitle.Title = "Millions"%@NL@%
  5340.                         CASE 3:     Axis.ScaleTitle.Title = "Billions"%@NL@%
  5341.                         CASE 4:     Axis.ScaleTitle.Title = "Trillions"%@NL@%
  5342.                         CASE ELSE:  Axis.ScaleTitle.Title = "10^" + LTRIM$(STR$(Power% * 3))%@NL@%
  5343.                 END SELECT%@NL@%
  5344. %@NL@%
  5345. %@AB@%                ' Calculate the actual scale factor:%@AE@%%@NL@%
  5346.                 Axis.ScaleFactor = 10 ^ (3 * Power%)%@NL@%
  5347. %@NL@%
  5348. %@AB@%                ' Finally, scale Max and Min by ScaleFactor:%@AE@%%@NL@%
  5349.                 Axis.ScaleMin = Axis.ScaleMin / Axis.ScaleFactor%@NL@%
  5350.                 Axis.ScaleMax = Axis.ScaleMax / Axis.ScaleFactor%@NL@%
  5351. %@NL@%
  5352.         END IF%@NL@%
  5353. %@NL@%
  5354. END SUB%@NL@%
  5355. %@NL@%
  5356. %@AB@%'=== clAnalyzeC - Does analysis of category/value data%@AE@%%@NL@%
  5357. %@AB@%'%@AE@%%@NL@%
  5358. %@AB@%'  Arguments:%@AE@%%@NL@%
  5359. %@AB@%'     Cat$(1)     -  List of category names%@AE@%%@NL@%
  5360. %@AB@%'%@AE@%%@NL@%
  5361. %@AB@%'     N%          -  Number of data values per series%@AE@%%@NL@%
  5362. %@AB@%'%@AE@%%@NL@%
  5363. %@AB@%'     SLabels$    -  Labels for the different data series%@AE@%%@NL@%
  5364. %@AB@%'%@AE@%%@NL@%
  5365. %@AB@%'     First%      -  First series to chart%@AE@%%@NL@%
  5366. %@AB@%'%@AE@%%@NL@%
  5367. %@AB@%'     Last%       -  Last series to chart%@AE@%%@NL@%
  5368. %@AB@%'%@AE@%%@NL@%
  5369. %@AB@%'  Return Values:%@AE@%%@NL@%
  5370. %@AB@%'     Some values in GE are altered.%@AE@%%@NL@%
  5371. %@AB@%'%@AE@%%@NL@%
  5372. %@AB@%'=================================================================%@AE@%%@NL@%
  5373. SUB clAnalyzeC (Cat$(), N%, SLabels$(), First%, Last%)%@NL@%
  5374. SHARED GE AS ChartEnvironment, GP AS GlobalParams%@NL@%
  5375. SHARED TTitleLayout AS TitleLayout%@NL@%
  5376. SHARED XTitleLayout AS TitleLayout%@NL@%
  5377. SHARED YTitleLayout AS TitleLayout%@NL@%
  5378. SHARED V1()%@NL@%
  5379. %@NL@%
  5380. %@AB@%        ' Save the number of values and the number of series in the chart in%@AE@%%@NL@%
  5381. %@AB@%        ' the global parameter variables:%@AE@%%@NL@%
  5382.         GP.NVals = N%%@NL@%
  5383.         GP.NSeries = Last% - First% + 1%@NL@%
  5384. %@NL@%
  5385. %@AB@%        ' Analyze data for scale-maximim and -minimum and scale-factor:%@AE@%%@NL@%
  5386.         clScaleAxis GE.XAxis, GP.XMode, V1()%@NL@%
  5387.         IF ChartErr > 100 THEN EXIT SUB%@NL@%
  5388. %@NL@%
  5389.         clScaleAxis GE.YAxis, GP.YMode, V1()%@NL@%
  5390.         IF ChartErr > 100 THEN EXIT SUB%@NL@%
  5391. %@NL@%
  5392. %@AB@%        ' Format tic labels (needed for sizing routines) and set global%@AE@%%@NL@%
  5393. %@AB@%        ' parameters (again used by sizing and other routines):%@AE@%%@NL@%
  5394.         clFormatTics GE.XAxis%@NL@%
  5395.         clFormatTics GE.YAxis%@NL@%
  5396.         clSetGlobalParams%@NL@%
  5397. %@NL@%
  5398. %@AB@%        ' Layout Titles%@AE@%%@NL@%
  5399.         clLayoutTitle TTitleLayout, GE.MainTitle, GE.SubTitle%@NL@%
  5400.         clLayoutTitle YTitleLayout, GE.YAxis.AxisTitle, GE.YAxis.ScaleTitle%@NL@%
  5401.         clLayoutTitle XTitleLayout, GE.XAxis.AxisTitle, GE.XAxis.ScaleTitle%@NL@%
  5402. %@NL@%
  5403. %@AB@%        ' If this is a multiple-series chart, calculate the legend size:%@AE@%%@NL@%
  5404.         IF GP.MSeries = cYes THEN clLayoutLegend SLabels$(), First%, Last%%@NL@%
  5405.         IF ChartErr > 100 THEN EXIT SUB%@NL@%
  5406. %@NL@%
  5407. %@AB@%        ' Calculate the data-window size:%@AE@%%@NL@%
  5408.         clSizeDataWindow Cat$()%@NL@%
  5409.         IF ChartErr > 100 THEN EXIT SUB%@NL@%
  5410. %@NL@%
  5411. %@AB@%        ' Finally, figure out the distance between tic marks:%@AE@%%@NL@%
  5412.         clSpaceTics%@NL@%
  5413. %@NL@%
  5414. END SUB%@NL@%
  5415. %@NL@%
  5416. %@AB@%'=== clAnalyzeS - Does actual analysis of scatter data%@AE@%%@NL@%
  5417. %@AB@%'%@AE@%%@NL@%
  5418. %@AB@%'  Arguments:%@AE@%%@NL@%
  5419. %@AB@%'     N%          -  Number of values per data series%@AE@%%@NL@%
  5420. %@AB@%'%@AE@%%@NL@%
  5421. %@AB@%'     SLabels$(1) -  Labels for the data series%@AE@%%@NL@%
  5422. %@AB@%'%@AE@%%@NL@%
  5423. %@AB@%'     First%      -  First series to analyze%@AE@%%@NL@%
  5424. %@AB@%'%@AE@%%@NL@%
  5425. %@AB@%'     Last%       -  Last series to analyze%@AE@%%@NL@%
  5426. %@AB@%'%@AE@%%@NL@%
  5427. %@AB@%'  Return Values:%@AE@%%@NL@%
  5428. %@AB@%'     Values in GE are altered.%@AE@%%@NL@%
  5429. %@AB@%'%@AE@%%@NL@%
  5430. %@AB@%'=================================================================%@AE@%%@NL@%
  5431. SUB clAnalyzeS (N%, SLabels$(), First%, Last%)%@NL@%
  5432. SHARED GE AS ChartEnvironment, GP AS GlobalParams%@NL@%
  5433. SHARED TTitleLayout AS TitleLayout%@NL@%
  5434. SHARED XTitleLayout AS TitleLayout%@NL@%
  5435. SHARED YTitleLayout AS TitleLayout%@NL@%
  5436. SHARED V1(), V2()%@NL@%
  5437. DIM Dum$(1 TO 1)%@NL@%
  5438. %@NL@%
  5439. %@AB@%        ' Save the number of values and the number of series in the chart in%@AE@%%@NL@%
  5440. %@AB@%        ' the global parameter variables:%@AE@%%@NL@%
  5441.         GP.NVals = N%%@NL@%
  5442.         GP.NSeries = Last% - First% + 1%@NL@%
  5443. %@NL@%
  5444. %@AB@%        ' Analyze data for scale-maximim and -minimum and scale-factor:%@AE@%%@NL@%
  5445.         clScaleAxis GE.XAxis, GP.XMode, V1()%@NL@%
  5446.         IF ChartErr > 100 THEN EXIT SUB%@NL@%
  5447. %@NL@%
  5448.         clScaleAxis GE.YAxis, GP.YMode, V2()%@NL@%
  5449.         IF ChartErr > 100 THEN EXIT SUB%@NL@%
  5450. %@NL@%
  5451. %@AB@%        ' Format tic labels (needed for sizing routines) and set global%@AE@%%@NL@%
  5452. %@AB@%        ' parameters (again used by sizing and other routines):%@AE@%%@NL@%
  5453.         clFormatTics GE.XAxis%@NL@%
  5454.         clFormatTics GE.YAxis%@NL@%
  5455.         clSetGlobalParams%@NL@%
  5456. %@NL@%
  5457. %@AB@%        ' Layout Titles%@AE@%%@NL@%
  5458.         clLayoutTitle TTitleLayout, GE.MainTitle, GE.SubTitle%@NL@%
  5459.         clLayoutTitle YTitleLayout, GE.YAxis.AxisTitle, GE.YAxis.ScaleTitle%@NL@%
  5460.         clLayoutTitle XTitleLayout, GE.XAxis.AxisTitle, GE.XAxis.ScaleTitle%@NL@%
  5461. %@NL@%
  5462. %@AB@%        ' If this is a multiple-series chart, calculate the legend size:%@AE@%%@NL@%
  5463.         IF GP.MSeries = cYes THEN clLayoutLegend SLabels$(), First%, Last%%@NL@%
  5464.         IF ChartErr > 100 THEN EXIT SUB%@NL@%
  5465. %@NL@%
  5466. %@AB@%        ' Calculate the data window size:%@AE@%%@NL@%
  5467.         clSizeDataWindow Dum$()%@NL@%
  5468.         IF ChartErr > 100 THEN EXIT SUB%@NL@%
  5469. %@NL@%
  5470. %@AB@%        ' Finally, figure out the distance between tic marks:%@AE@%%@NL@%
  5471.         clSpaceTics%@NL@%
  5472. %@NL@%
  5473. END SUB%@NL@%
  5474. %@NL@%
  5475. %@AB@%'=== clBuildBitP$ - Builds a pattern tile for a one bit-plane screen mode%@AE@%%@NL@%
  5476. %@AB@%'%@AE@%%@NL@%
  5477. %@AB@%'  Arguments:%@AE@%%@NL@%
  5478. %@AB@%'     Bits%    =  Number of bits per pixel in this screen mode%@AE@%%@NL@%
  5479. %@AB@%'%@AE@%%@NL@%
  5480. %@AB@%'     C%       =  The color used to make the pattern.%@AE@%%@NL@%
  5481. %@AB@%'%@AE@%%@NL@%
  5482. %@AB@%'     InP$     =  Reference pattern%@AE@%%@NL@%
  5483. %@AB@%'%@AE@%%@NL@%
  5484. %@AB@%'  Return Values:%@AE@%%@NL@%
  5485. %@AB@%'     Returns the specified pattern in specified color.%@AE@%%@NL@%
  5486. %@AB@%'%@AE@%%@NL@%
  5487. %@AB@%'  Remarks:%@AE@%%@NL@%
  5488. %@AB@%'     In screen modes where a pixel on the screen is represented by 1 or%@AE@%%@NL@%
  5489. %@AB@%'     more bits that are adjacent in memory, a byte of memory represents%@AE@%%@NL@%
  5490. %@AB@%'     one or more pixels depending on the number of bits per pixel the%@AE@%%@NL@%
  5491. %@AB@%'     mode uses (e.g. screen mode 1 uses 2 bits per pixel so each byte%@AE@%%@NL@%
  5492. %@AB@%'     contains 4 pixels).  To make a pattern tile in a specific color%@AE@%%@NL@%
  5493. %@AB@%'     you first decide which pixels should be on and which ones off.%@AE@%%@NL@%
  5494. %@AB@%'     Then, you set the corresponding two-bit pixels in the tile bytes%@AE@%%@NL@%
  5495. %@AB@%'     to the value of the color you want the pattern to be.  This routine%@AE@%%@NL@%
  5496. %@AB@%'     does this semi-automatically.  First it inputs a reference pattern that%@AE@%%@NL@%
  5497. %@AB@%'     contains the pattern defined in the highest color available for a%@AE@%%@NL@%
  5498. %@AB@%'     screen mode (all bits in a pixel set to one).  Then a color mask byte%@AE@%%@NL@%
  5499. %@AB@%'     is prepared with each pixel set to the color that was specified as%@AE@%%@NL@%
  5500. %@AB@%'     input to the routine.  When these two components (reference pattern%@AE@%%@NL@%
  5501. %@AB@%'     and color mask) are combined using a logical "AND" any pixel in the%@AE@%%@NL@%
  5502. %@AB@%'     reference pattern that was black (all zero) will remain black and any%@AE@%%@NL@%
  5503. %@AB@%'     pixel that was white will be of the input color.  The nice feature of%@AE@%%@NL@%
  5504. %@AB@%'     this scheme is that you can use one pattern set for any color%@AE@%%@NL@%
  5505. %@AB@%'     available for the screen mode.%@AE@%%@NL@%
  5506. %@AB@%'%@AE@%%@NL@%
  5507. %@AB@%'     Example: Screen mode 1; 2 bits per pixel; to build a pattern%@AE@%%@NL@%
  5508. %@AB@%'              with pixels alternating on and off in color 2:%@AE@%%@NL@%
  5509. %@AB@%'%@AE@%%@NL@%
  5510. %@AB@%'     Reference pattern:   11 00 11 00    (8 bits = 1 byte)%@AE@%%@NL@%
  5511. %@AB@%'     Color mask:          10 10 10 10    (each pixel set to color 2)%@AE@%%@NL@%
  5512. %@AB@%'                         -------------%@AE@%%@NL@%
  5513. %@AB@%'     Result of "AND"      10 00 10 00    (pattern in color 2)%@AE@%%@NL@%
  5514. %@AB@%'%@AE@%%@NL@%
  5515. %@AB@%'=================================================================%@AE@%%@NL@%
  5516. FUNCTION clBuildBitP$ (Bits%, C%, InP$)%@NL@%
  5517. %@NL@%
  5518. %@AB@%        ' First get color mask to match this color and pixel size (bits per pixel):%@AE@%%@NL@%
  5519.         CMask% = clColorMaskL%(Bits%, C%)%@NL@%
  5520. %@NL@%
  5521. %@AB@%        ' Initialize the output pattern to empty then combine the color%@AE@%%@NL@%
  5522. %@AB@%        ' mask with each byte in the input tile using a logical "AND":%@AE@%%@NL@%
  5523.         OutP$ = ""%@NL@%
  5524.         FOR i% = 1 TO LEN(InP$)%@NL@%
  5525.                 NxtCH% = CMask% AND ASC(MID$(InP$, i%, 1))%@NL@%
  5526.                 OutP$ = OutP$ + CHR$(NxtCH%)%@NL@%
  5527.         NEXT i%%@NL@%
  5528. %@NL@%
  5529. %@AB@%        ' Return the completed pattern:%@AE@%%@NL@%
  5530.         clBuildBitP$ = OutP$%@NL@%
  5531. %@NL@%
  5532. END FUNCTION%@NL@%
  5533. %@NL@%
  5534. %@AB@%'=== clBuildPalette - Builds the five chart palettes%@AE@%%@NL@%
  5535. %@AB@%'%@AE@%%@NL@%
  5536. %@AB@%'  Arguments:%@AE@%%@NL@%
  5537. %@AB@%'     N           -  Screen mode for which to build palettes%@AE@%%@NL@%
  5538. %@AB@%'%@AE@%%@NL@%
  5539. %@AB@%'  Return Values:%@AE@%%@NL@%
  5540. %@AB@%'     Values in chart palettes set to standard ones for this mode%@AE@%%@NL@%
  5541. %@AB@%'%@AE@%%@NL@%
  5542. %@AB@%'  Remarks:%@AE@%%@NL@%
  5543. %@AB@%'     The following code sets up the palettes that are referenced when the%@AE@%%@NL@%
  5544. %@AB@%'     different chart elements are drawn.  See the charting library%@AE@%%@NL@%
  5545. %@AB@%'     documentation for a complete description of how these palettes are%@AE@%%@NL@%
  5546. %@AB@%'     used in drawing different portions of a chart.%@AE@%%@NL@%
  5547. %@AB@%'%@AE@%%@NL@%
  5548. %@AB@%'=================================================================%@AE@%%@NL@%
  5549. SUB clBuildPalette (ScrnMode AS INTEGER, Bits AS INTEGER)%@NL@%
  5550. SHARED PaletteC%(), PaletteS%(), PaletteP$(), PaletteCh%(), PaletteB%()%@NL@%
  5551. SHARED StdChars%()%@NL@%
  5552. SHARED GP AS GlobalParams%@NL@%
  5553. %@NL@%
  5554. %@AB@%        ' Flag palette set and record the screen mode:%@AE@%%@NL@%
  5555.         GP.PaletteSet = cYes%@NL@%
  5556.         GP.PaletteScrn = ScrnMode%@NL@%
  5557.         GP.PaletteBits = Bits%@NL@%
  5558. %@NL@%
  5559. %@AB@%        ' The first palettes to set are the character palette and the border%@AE@%%@NL@%
  5560. %@AB@%        ' style palette:%@AE@%%@NL@%
  5561.         PaletteCh%(0) = 0%@NL@%
  5562.         PaletteB%(0) = &HFFFF%@NL@%
  5563.         FOR i% = 1 TO cPalLen%@NL@%
  5564.                 PaletteCh%(i%) = StdChars%(i%)%@NL@%
  5565.                 PaletteB%(i%) = clGetStyle(i%)%@NL@%
  5566.         NEXT i%%@NL@%
  5567. %@NL@%
  5568. %@AB@%        ' The next palette to set is the color palette, which is made up of%@AE@%%@NL@%
  5569. %@AB@%        ' a list of 10 (maybe repeating) colors.  Begin by setting the first%@AE@%%@NL@%
  5570. %@AB@%        ' two colors.  The first color (position 0) is always black and the%@AE@%%@NL@%
  5571. %@AB@%        ' second color is always white (or whatever the maximum color number%@AE@%%@NL@%
  5572. %@AB@%        ' is mapped to in the graphics-card palette).  Cycle through setting%@AE@%%@NL@%
  5573. %@AB@%        ' other colors.  They will be entered in order starting with color 1%@AE@%%@NL@%
  5574. %@AB@%        ' until the maximum number of colors is reached or the palette is filled%@AE@%%@NL@%
  5575. %@AB@%        ' (size governed by the cPalLen CONST).  If the maximum color is reached%@AE@%%@NL@%
  5576. %@AB@%        ' before the palette is filled then repeat the cycle again excluding%@AE@%%@NL@%
  5577. %@AB@%        ' color 0, and so on, until the color palette is filled:%@AE@%%@NL@%
  5578. %@NL@%
  5579.         PaletteC%(0) = 0        ' Black%@NL@%
  5580.         PaletteC%(1) = GP.White ' White%@NL@%
  5581. %@NL@%
  5582.         FOR i% = 2 TO cPalLen%@NL@%
  5583.                 MappedI% = ((i% - 2) MOD GP.MaxColor) + 1%@NL@%
  5584.                 PaletteC%(i%) = MappedI%%@NL@%
  5585.         NEXT i%%@NL@%
  5586. %@NL@%
  5587. %@AB@%        ' Setting the line styles is almost the inverse of setting the colors%@AE@%%@NL@%
  5588. %@AB@%        ' in that each color within a cycle has the same line style.  When a%@AE@%%@NL@%
  5589. %@AB@%        ' new cycle of colors begins, though, the line style changes to%@AE@%%@NL@%
  5590. %@AB@%        ' differentiate the new cycle from previous ones.  The line style%@AE@%%@NL@%
  5591. %@AB@%        ' begins as &HFFFF or a solid line:%@AE@%%@NL@%
  5592. %@NL@%
  5593. %@AB@%        ' The pattern component of the palette contains fill patterns for use in%@AE@%%@NL@%
  5594. %@AB@%        ' filling bars and pie slices.  Fill patterns are "bit" oriented whereas%@AE@%%@NL@%
  5595. %@AB@%        ' line styles are "pixel" oriented.  What this means is that a fill%@AE@%%@NL@%
  5596. %@AB@%        ' pattern of CHR$(&HFF) will be white regardless of what the current%@AE@%%@NL@%
  5597. %@AB@%        ' color is.  If you know that each pixel on the screen is represented by%@AE@%%@NL@%
  5598. %@AB@%        ' 2 bits in RAM and you want a solid fill with color 2, the corresponding%@AE@%%@NL@%
  5599. %@AB@%        ' definition would be CHR$(&HAA) (in binary 10 10 10 10 -- notice, four%@AE@%%@NL@%
  5600. %@AB@%        ' pixels of two bits each set to 2).  The following code automatically%@AE@%%@NL@%
  5601. %@AB@%        ' takes a fill pattern defined in terms of pixels, and by masking it%@AE@%%@NL@%
  5602. %@AB@%        ' with the current color generates the same fill pattern in the%@AE@%%@NL@%
  5603. %@AB@%        ' specified color.  Start with solid black (color 0):%@AE@%%@NL@%
  5604. %@NL@%
  5605.         PaletteS%(0) = &HFFFF%@NL@%
  5606.         PaletteP$(0) = CHR$(0)%@NL@%
  5607. %@NL@%
  5608.         FOR i% = 1 TO cPalLen%@NL@%
  5609. %@NL@%
  5610. %@AB@%                ' The cycle number starts at one and is incremented each time%@AE@%%@NL@%
  5611. %@AB@%                ' the maximum number of colors for the current screen mode is reached:%@AE@%%@NL@%
  5612.                 Cycle% = ((i% - 1) \ GP.MaxColor) + 1%@NL@%
  5613. %@NL@%
  5614. %@AB@%                ' Set the style palette from the standard styles (which have%@AE@%%@NL@%
  5615. %@AB@%                ' previously been placed in the border palette):%@AE@%%@NL@%
  5616.                 PaletteS%(i%) = PaletteB%(Cycle%)%@NL@%
  5617. %@NL@%
  5618. %@AB@%                ' Get the default pattern and put it into the palette:%@AE@%%@NL@%
  5619.                 SELECT CASE ScrnMode%@NL@%
  5620. %@NL@%
  5621. %@AB@%                        ' One bit plane modes:%@AE@%%@NL@%
  5622.                         CASE 1, 2, 11, 13: RefPattern$ = GetPattern$(Bits, Cycle%)%@NL@%
  5623. %@NL@%
  5624. %@AB@%                        ' Multiple bit plane modes:%@AE@%%@NL@%
  5625.                         CASE ELSE: RefPattern$ = GetPattern$(1, Cycle%)%@NL@%
  5626. %@NL@%
  5627.                 END SELECT%@NL@%
  5628.                 PaletteP$(i%) = MakeChartPattern$(RefPattern$, PaletteC%(i%), 0)%@NL@%
  5629. %@NL@%
  5630.         NEXT i%%@NL@%
  5631. %@NL@%
  5632. END SUB%@NL@%
  5633. %@NL@%
  5634. %@AB@%'=== clBuildPlaneP$ - Builds a pattern tile for multiple bit-plane screen modes%@AE@%%@NL@%
  5635. %@AB@%'%@AE@%%@NL@%
  5636. %@AB@%'  Arguments:%@AE@%%@NL@%
  5637. %@AB@%'     Bits%    =  Number of planes in this screen mode%@AE@%%@NL@%
  5638. %@AB@%'%@AE@%%@NL@%
  5639. %@AB@%'     C%       =  The color used to make the pattern%@AE@%%@NL@%
  5640. %@AB@%'%@AE@%%@NL@%
  5641. %@AB@%'     InP$     =  Reference pattern%@AE@%%@NL@%
  5642. %@AB@%'%@AE@%%@NL@%
  5643. %@AB@%'  Return Values:%@AE@%%@NL@%
  5644. %@AB@%'     Returns the specified pattern in specified color%@AE@%%@NL@%
  5645. %@AB@%'%@AE@%%@NL@%
  5646. %@AB@%'  Remarks:%@AE@%%@NL@%
  5647. %@AB@%'     PAINT tiles are different for screen modes that use 2 or more%@AE@%%@NL@%
  5648. %@AB@%'     bit-planes than for the modes that use only one (see remarks for%@AE@%%@NL@%
  5649. %@AB@%'     clBuildBitP$()).  When bit-planes are used each pixel requires only%@AE@%%@NL@%
  5650. %@AB@%'     one bit per byte, but, there needs to be one byte for each bit-%@AE@%%@NL@%
  5651. %@AB@%'     plane.  The process for building a pattern from a reference pattern%@AE@%%@NL@%
  5652. %@AB@%'     and color mask are logically the same as in the one bit-plane modes%@AE@%%@NL@%
  5653. %@AB@%'     the only difference is that a color mask requires several bytes%@AE@%%@NL@%
  5654. %@AB@%'     (one for each bit-plane) rather than one.%@AE@%%@NL@%
  5655. %@AB@%'%@AE@%%@NL@%
  5656. %@AB@%'  Example: Screen mode 9 with 2 bit planes; pattern with alternating%@AE@%%@NL@%
  5657. %@AB@%'           pixels on and off; color 2:%@AE@%%@NL@%
  5658. %@AB@%'%@AE@%%@NL@%
  5659. %@AB@%'           Reference pattern:   1 0 1 0 1 0 1 0%@AE@%%@NL@%
  5660. %@AB@%'           Color mask:          0 0 0 0 0 0 0 0   (plane 1)%@AE@%%@NL@%
  5661. %@AB@%'                                1 1 1 1 1 1 1 1   (plane 2)%@AE@%%@NL@%
  5662. %@AB@%'                               -----------------%@AE@%%@NL@%
  5663. %@AB@%'           Result of "AND"      0 0 0 0 0 0 0 0   (plane 1)%@AE@%%@NL@%
  5664. %@AB@%'                                1 0 1 0 1 0 1 0   (plane 2)%@AE@%%@NL@%
  5665. %@AB@%'%@AE@%%@NL@%
  5666. %@AB@%'%@AE@%%@NL@%
  5667. %@AB@%'=================================================================%@AE@%%@NL@%
  5668. FUNCTION clBuildPlaneP$ (Bits%, C%, InP$)%@NL@%
  5669. DIM CMask%(1 TO 4)%@NL@%
  5670. %@NL@%
  5671. %@AB@%        ' First get color mask to match this color and pixel size (bits per pixel):%@AE@%%@NL@%
  5672.         clColorMaskH Bits%, C%, CMask%()%@NL@%
  5673. %@NL@%
  5674. %@AB@%        ' Initialize the output pattern to empty then combine the color%@AE@%%@NL@%
  5675. %@AB@%        ' mask with each byte in the input tile using a logical "AND":%@AE@%%@NL@%
  5676.         OutP$ = ""%@NL@%
  5677.         FOR TileByte% = 1 TO LEN(InP$)%@NL@%
  5678.                 RefTile% = ASC(MID$(InP$, TileByte%, 1))%@NL@%
  5679. %@NL@%
  5680. %@AB@%                ' Combine each bit-plane in the color mask with the pattern byte:%@AE@%%@NL@%
  5681.                 FOR Plane% = 1 TO Bits%%@NL@%
  5682.                         OutP$ = OutP$ + CHR$(RefTile% AND CMask%(Plane%))%@NL@%
  5683.                 NEXT Plane%%@NL@%
  5684.         NEXT TileByte%%@NL@%
  5685. %@NL@%
  5686. %@AB@%        ' Return the completed pattern:%@AE@%%@NL@%
  5687.         clBuildPlaneP$ = OutP$%@NL@%
  5688. %@NL@%
  5689. END FUNCTION%@NL@%
  5690. %@NL@%
  5691. %@AB@%'=== clChkChartWindow - Makes sure the chart window is valid%@AE@%%@NL@%
  5692. %@AB@%'%@AE@%%@NL@%
  5693. %@AB@%'  Arguments:%@AE@%%@NL@%
  5694. %@AB@%'     Env   -  A ChartEnvironment variable%@AE@%%@NL@%
  5695. %@AB@%'%@AE@%%@NL@%
  5696. %@AB@%'  Return Values:%@AE@%%@NL@%
  5697. %@AB@%'     Changes global parameters for chart window%@AE@%%@NL@%
  5698. %@AB@%'%@AE@%%@NL@%
  5699. %@AB@%'  Remarks:%@AE@%%@NL@%
  5700. %@AB@%'     This routine forces the chart window to be valid.  If the input%@AE@%%@NL@%
  5701. %@AB@%'     values are invalid a full screen is chosen.  The valid chart window%@AE@%%@NL@%
  5702. %@AB@%'     is stored in the global parameter set and used by other charting%@AE@%%@NL@%
  5703. %@AB@%'     routines.  The last valid screen set by ChartScreen is used as%@AE@%%@NL@%
  5704. %@AB@%'     reference.%@AE@%%@NL@%
  5705. %@AB@%'%@AE@%%@NL@%
  5706. %@AB@%'=================================================================%@AE@%%@NL@%
  5707. SUB clChkChartWindow (Env AS ChartEnvironment)%@NL@%
  5708. SHARED GP AS GlobalParams%@NL@%
  5709. %@NL@%
  5710. %@AB@%        ' Make sure X1 < X2:%@AE@%%@NL@%
  5711.         IF Env.ChartWindow.X1 < Env.ChartWindow.X2 THEN%@NL@%
  5712.                 GP.CwX1 = Env.ChartWindow.X1%@NL@%
  5713.                 GP.CwX2 = Env.ChartWindow.X2%@NL@%
  5714.         ELSE%@NL@%
  5715.                 GP.CwX1 = Env.ChartWindow.X2%@NL@%
  5716.                 GP.CwX2 = Env.ChartWindow.X1%@NL@%
  5717.         END IF%@NL@%
  5718. %@NL@%
  5719. %@AB@%        ' Make sure Y1 < Y2:%@AE@%%@NL@%
  5720.         IF Env.ChartWindow.Y1 < Env.ChartWindow.Y2 THEN%@NL@%
  5721.                 GP.CwY1 = Env.ChartWindow.Y1%@NL@%
  5722.                 GP.CwY2 = Env.ChartWindow.Y2%@NL@%
  5723.         ELSE%@NL@%
  5724.                 GP.CwY1 = Env.ChartWindow.Y2%@NL@%
  5725.                 GP.CwY2 = Env.ChartWindow.Y1%@NL@%
  5726.         END IF%@NL@%
  5727. %@NL@%
  5728. %@AB@%        ' If the X coordinates of the chart window are invalid,%@AE@%%@NL@%
  5729. %@AB@%        ' set them to full screen:%@AE@%%@NL@%
  5730.         IF GP.CwX1 < 0 OR GP.CwX2 >= GP.MaxXPix OR GP.CwX1 = GP.CwX2 THEN%@NL@%
  5731.                 GP.CwX1 = 0%@NL@%
  5732.                 GP.CwX2 = GP.MaxXPix - 1%@NL@%
  5733.         END IF%@NL@%
  5734. %@NL@%
  5735. %@AB@%        ' If the Y coordinates of the chart window are invalid,%@AE@%%@NL@%
  5736. %@AB@%        ' set them to full screen:%@AE@%%@NL@%
  5737.         IF GP.CwY1 < 0 OR GP.CwY2 >= GP.MaxYPix OR GP.CwY1 = GP.CwY2 THEN%@NL@%
  5738.                 GP.CwY1 = 0%@NL@%
  5739.                 GP.CwY2 = GP.MaxYPix - 1%@NL@%
  5740.         END IF%@NL@%
  5741. %@NL@%
  5742. %@AB@%        ' Set chart height and width for use later:%@AE@%%@NL@%
  5743.         GP.ChartWid = GP.CwX2 - GP.CwX1 + 1%@NL@%
  5744.         GP.ChartHgt = GP.CwY2 - GP.CwY1 + 1%@NL@%
  5745. %@NL@%
  5746. %@AB@%        ' Put the valid coordinates in Env:%@AE@%%@NL@%
  5747.         Env.ChartWindow.X1 = GP.CwX1%@NL@%
  5748.         Env.ChartWindow.Y1 = GP.CwY1%@NL@%
  5749.         Env.ChartWindow.X2 = GP.CwX2%@NL@%
  5750.         Env.ChartWindow.Y2 = GP.CwY2%@NL@%
  5751. %@NL@%
  5752. END SUB%@NL@%
  5753. %@NL@%
  5754. %@AB@%'=== clChkFonts - Checks that there is at least one loaded font%@AE@%%@NL@%
  5755. %@AB@%'%@AE@%%@NL@%
  5756. %@AB@%'  Arguments:%@AE@%%@NL@%
  5757. %@AB@%'     none%@AE@%%@NL@%
  5758. %@AB@%'%@AE@%%@NL@%
  5759. %@AB@%'  Return Values:%@AE@%%@NL@%
  5760. %@AB@%'     Chart error set if no room for a font%@AE@%%@NL@%
  5761. %@AB@%'%@AE@%%@NL@%
  5762. %@AB@%'=================================================================%@AE@%%@NL@%
  5763. SUB clChkFonts%@NL@%
  5764. %@NL@%
  5765. %@AB@%        ' See if a font is loaded:%@AE@%%@NL@%
  5766.         GetTotalFonts Reg%, Load%%@NL@%
  5767. %@NL@%
  5768. %@AB@%        ' If not then find out the maximum number of fonts allowed and if%@AE@%%@NL@%
  5769. %@AB@%        ' there's room, then load the default font:%@AE@%%@NL@%
  5770.         IF Load% <= 0 THEN%@NL@%
  5771.                 GetMaxFonts MReg%, MLoad%%@NL@%
  5772.                 IF Reg% < MReg% AND Load% < MLoad% THEN%@NL@%
  5773.                         DefaultFont Segment%, Offset%%@NL@%
  5774.                         FontNum% = RegisterMemFont(Segment%, Offset%)%@NL@%
  5775.                         FontNum% = LoadFont("N" + STR$(Load% + 1))%@NL@%
  5776. %@NL@%
  5777. %@AB@%                ' If there's no room, then set an error:%@AE@%%@NL@%
  5778.                 ELSE%@NL@%
  5779.                         clSetError cNoFontSpace%@NL@%
  5780.                 END IF%@NL@%
  5781.         END IF%@NL@%
  5782. END SUB%@NL@%
  5783. %@NL@%
  5784. %@AB@%'=== CheckForErrors - Checks for and tries to fix a variety of errors%@AE@%%@NL@%
  5785. %@AB@%'%@AE@%%@NL@%
  5786. %@AB@%'  Arguments:%@AE@%%@NL@%
  5787. %@AB@%'     Env      -  ChartEnvironment variable%@AE@%%@NL@%
  5788. %@AB@%'%@AE@%%@NL@%
  5789. %@AB@%'     TypeMin% -  Minimum allowable ChartType%@AE@%%@NL@%
  5790. %@AB@%'%@AE@%%@NL@%
  5791. %@AB@%'     TypeMax% -  Maximum allowable ChartType%@AE@%%@NL@%
  5792. %@AB@%'%@AE@%%@NL@%
  5793. %@AB@%'     N%       -  Number of data values per series%@AE@%%@NL@%
  5794. %@AB@%'%@AE@%%@NL@%
  5795. %@AB@%'     First%   -  Column of data representing first series%@AE@%%@NL@%
  5796. %@AB@%'%@AE@%%@NL@%
  5797. %@AB@%'     Last%    -  Column of data representing last series%@AE@%%@NL@%
  5798. %@AB@%'%@AE@%%@NL@%
  5799. %@AB@%'  Return Values:%@AE@%%@NL@%
  5800. %@AB@%'     This routine is the main one that checks for errors of input in%@AE@%%@NL@%
  5801. %@AB@%'     the ChartEnvironment variable and routine parameters.%@AE@%%@NL@%
  5802. %@AB@%'%@AE@%%@NL@%
  5803. %@AB@%'=================================================================%@AE@%%@NL@%
  5804. SUB clChkForErrors (Env AS ChartEnvironment, TypeMin%, TypeMax%, N%, First%, Last%)%@NL@%
  5805. %@NL@%
  5806. %@AB@%        ' Clear any previous error:%@AE@%%@NL@%
  5807.         clClearError%@NL@%
  5808. %@NL@%
  5809. %@AB@%        ' Check for correct chart type:%@AE@%%@NL@%
  5810.         IF Env.ChartType < TypeMin% OR Env.ChartType > TypeMax% THEN%@NL@%
  5811.                 clSetError cBadType%@NL@%
  5812.                 EXIT SUB%@NL@%
  5813.         END IF%@NL@%
  5814. %@NL@%
  5815. %@AB@%        ' Check for valid chart style:%@AE@%%@NL@%
  5816.         IF Env.ChartStyle < 1 OR Env.ChartStyle > 2 THEN%@NL@%
  5817.                 clSetError cBadStyle%@NL@%
  5818.                 Env.ChartStyle = 1%@NL@%
  5819.         END IF%@NL@%
  5820. %@NL@%
  5821. %@AB@%        ' The following things are not relevant for pie charts:%@AE@%%@NL@%
  5822.         IF Env.ChartType <> cPie THEN%@NL@%
  5823. %@NL@%
  5824. %@AB@%                ' Check LogBase for the X axis (default to 10):%@AE@%%@NL@%
  5825.                 IF Env.XAxis.RangeType = cLog AND Env.XAxis.LogBase <= 0 THEN%@NL@%
  5826.                         clSetError cBadLogBase%@NL@%
  5827.                         Env.XAxis.LogBase = 10%@NL@%
  5828.                 END IF%@NL@%
  5829. %@NL@%
  5830. %@AB@%                ' Check LogBase for the Y axis (default to 10):%@AE@%%@NL@%
  5831.                 IF Env.YAxis.RangeType = cLog AND Env.YAxis.LogBase <= 0 THEN%@NL@%
  5832.                         clSetError cBadLogBase%@NL@%
  5833.                         Env.YAxis.LogBase = 10%@NL@%
  5834.                 END IF%@NL@%
  5835. %@NL@%
  5836. %@AB@%                ' Check X axis ScaleFactor:%@AE@%%@NL@%
  5837.                 IF Env.XAxis.AutoScale <> cYes AND Env.XAxis.ScaleFactor = 0 THEN%@NL@%
  5838.                         clSetError cBadScaleFactor%@NL@%
  5839.                         Env.XAxis.ScaleFactor = 1%@NL@%
  5840.                 END IF%@NL@%
  5841. %@NL@%
  5842. %@AB@%                ' Check Y axis ScaleFactor:%@AE@%%@NL@%
  5843.                 IF Env.YAxis.AutoScale <> cYes AND Env.YAxis.ScaleFactor = 0 THEN%@NL@%
  5844.                         clSetError cBadScaleFactor%@NL@%
  5845.                         Env.YAxis.ScaleFactor = 1%@NL@%
  5846.                 END IF%@NL@%
  5847.         END IF%@NL@%
  5848. %@NL@%
  5849. %@AB@%        ' Make sure N > 0:%@AE@%%@NL@%
  5850.         IF N% <= 0 THEN%@NL@%
  5851.                 clSetError cTooSmallN%@NL@%
  5852.                 EXIT SUB%@NL@%
  5853.         END IF%@NL@%
  5854. %@NL@%
  5855. %@AB@%        ' Check that First series <= Last one:%@AE@%%@NL@%
  5856.         IF First% > Last% THEN%@NL@%
  5857.                 clSetError cTooFewSeries%@NL@%
  5858.                 EXIT SUB%@NL@%
  5859.         END IF%@NL@%
  5860. %@NL@%
  5861. %@AB@%        ' Force ChartWindow to be valid:%@AE@%%@NL@%
  5862.         clChkChartWindow Env%@NL@%
  5863. %@NL@%
  5864. END SUB%@NL@%
  5865. %@NL@%
  5866. %@AB@%'=== clChkInit - Check that chartlib has been initialized%@AE@%%@NL@%
  5867. %@AB@%'%@AE@%%@NL@%
  5868. %@AB@%'  Arguments:%@AE@%%@NL@%
  5869. %@AB@%'     none%@AE@%%@NL@%
  5870. %@AB@%'%@AE@%%@NL@%
  5871. %@AB@%'  Return Values:%@AE@%%@NL@%
  5872. %@AB@%'     none%@AE@%%@NL@%
  5873. %@AB@%'%@AE@%%@NL@%
  5874. %@AB@%'=================================================================%@AE@%%@NL@%
  5875. SUB clChkInit%@NL@%
  5876. SHARED GP AS GlobalParams%@NL@%
  5877. %@NL@%
  5878.         IF NOT GP.Initialized THEN clInitChart%@NL@%
  5879. %@NL@%
  5880. END SUB%@NL@%
  5881. %@NL@%
  5882. %@AB@%'=== clChkPalettes - Makes sure that palettes are dimensioned correctly%@AE@%%@NL@%
  5883. %@AB@%'%@AE@%%@NL@%
  5884. %@AB@%'  Arguments:%@AE@%%@NL@%
  5885. %@AB@%'     C%()     -  Color palette array%@AE@%%@NL@%
  5886. %@AB@%'%@AE@%%@NL@%
  5887. %@AB@%'     S%()     -  Style palette array%@AE@%%@NL@%
  5888. %@AB@%'%@AE@%%@NL@%
  5889. %@AB@%'     P$()     -  Pattern palette array%@AE@%%@NL@%
  5890. %@AB@%'%@AE@%%@NL@%
  5891. %@AB@%'     Char%()  -  Plot character palette array%@AE@%%@NL@%
  5892. %@AB@%'%@AE@%%@NL@%
  5893. %@AB@%'     B%()     -  Border pattern palette array%@AE@%%@NL@%
  5894. %@AB@%'%@AE@%%@NL@%
  5895. %@AB@%'  Return Values:%@AE@%%@NL@%
  5896. %@AB@%'     Chart error may be set to cBadPalette%@AE@%%@NL@%
  5897. %@AB@%'%@AE@%%@NL@%
  5898. %@AB@%'=================================================================%@AE@%%@NL@%
  5899. SUB clChkPalettes (C() AS INTEGER, s() AS INTEGER, P$(), Char() AS INTEGER, B() AS INTEGER)%@NL@%
  5900. %@NL@%
  5901. %@AB@%        ' Check each palette array to be sure it is dimensioned from 0%@AE@%%@NL@%
  5902. %@AB@%        ' to cPalLen:%@AE@%%@NL@%
  5903.         FOR i% = 1 TO 5%@NL@%
  5904.                 SELECT CASE i%%@NL@%
  5905.                         CASE 1:  L% = LBOUND(C, 1): U% = UBOUND(C, 1)%@NL@%
  5906.                         CASE 2:  L% = LBOUND(s, 1): U% = UBOUND(s, 1)%@NL@%
  5907.                         CASE 3:  L% = LBOUND(P$, 1): U% = UBOUND(P$, 1)%@NL@%
  5908.                         CASE 4:  L% = LBOUND(Char, 1): U% = UBOUND(Char, 1)%@NL@%
  5909.                         CASE 5:  L% = LBOUND(B, 1): U% = UBOUND(B, 1)%@NL@%
  5910.                 END SELECT%@NL@%
  5911. %@NL@%
  5912. %@AB@%                ' If incorrectly dimensioned then set error:%@AE@%%@NL@%
  5913.                 IF (L% <> 0) OR (U% <> cPalLen) THEN%@NL@%
  5914.                         clSetError cBadPalette%@NL@%
  5915.                         EXIT SUB%@NL@%
  5916.                 END IF%@NL@%
  5917.         NEXT i%%@NL@%
  5918. %@NL@%
  5919. END SUB%@NL@%
  5920. %@NL@%
  5921. %@AB@%'=== clClearError - Clears ChartErr, the ChartLib error variable%@AE@%%@NL@%
  5922. %@AB@%'%@AE@%%@NL@%
  5923. %@AB@%'  Arguments:%@AE@%%@NL@%
  5924. %@AB@%'     None%@AE@%%@NL@%
  5925. %@AB@%'%@AE@%%@NL@%
  5926. %@AB@%'  Return Values:%@AE@%%@NL@%
  5927. %@AB@%'     Sets ChartErr to 0%@AE@%%@NL@%
  5928. %@AB@%'%@AE@%%@NL@%
  5929. %@AB@%'=================================================================%@AE@%%@NL@%
  5930. SUB clClearError%@NL@%
  5931. %@NL@%
  5932.         ChartErr = 0%@NL@%
  5933. %@NL@%
  5934. END SUB%@NL@%
  5935. %@NL@%
  5936. %@AB@%'=== clColorMaskH% - Function to generate a byte with each pixel set to%@AE@%%@NL@%
  5937. %@AB@%'                  some color - for high-res modes (7,8,9,10)%@AE@%%@NL@%
  5938. %@AB@%'%@AE@%%@NL@%
  5939. %@AB@%'  Arguments:%@AE@%%@NL@%
  5940. %@AB@%'     Bits%    -  Number of bits per pixel in current screen mode%@AE@%%@NL@%
  5941. %@AB@%'%@AE@%%@NL@%
  5942. %@AB@%'     Colr%    -  Color to make the mask%@AE@%%@NL@%
  5943. %@AB@%'%@AE@%%@NL@%
  5944. %@AB@%'     CMask%() -  One dimensional array to place mask values in%@AE@%%@NL@%
  5945. %@AB@%'%@AE@%%@NL@%
  5946. %@AB@%'  Return Values:%@AE@%%@NL@%
  5947. %@AB@%'     Screen modes 7, 8, 9 and 10 use bit planes.  Rather than using%@AE@%%@NL@%
  5948. %@AB@%'     adjacent bits in one byte to determine a color, they use bits%@AE@%%@NL@%
  5949. %@AB@%'     "stacked" on top of each other in different bytes.  This routine%@AE@%%@NL@%
  5950. %@AB@%'     generates one byte of a particular color by setting the different%@AE@%%@NL@%
  5951. %@AB@%'     levels of the stack to &H00 and &HFF to represent eight pixels%@AE@%%@NL@%
  5952. %@AB@%'     of a particular color.%@AE@%%@NL@%
  5953. %@AB@%'%@AE@%%@NL@%
  5954. %@AB@%'=================================================================%@AE@%%@NL@%
  5955. SUB clColorMaskH (Bits%, Colr%, CMask%())%@NL@%
  5956. %@NL@%
  5957. %@AB@%        ' Copy the color to a local variable:%@AE@%%@NL@%
  5958.         RefColor% = Colr%%@NL@%
  5959. %@NL@%
  5960. %@AB@%        ' Bits% is the number of bit planes, set a mask for each one:%@AE@%%@NL@%
  5961.         FOR i% = 1 TO Bits%%@NL@%
  5962. %@NL@%
  5963. %@AB@%                ' Check rightmost bit in color, if it is set to 1 then this plane is%@AE@%%@NL@%
  5964. %@AB@%                ' "on" (it equals &HFF):%@AE@%%@NL@%
  5965.                 IF RefColor% MOD 2 <> 0 THEN%@NL@%
  5966.                         CMask%(i%) = &HFF%@NL@%
  5967. %@NL@%
  5968. %@AB@%                ' If the bit is 0, the plane is off (it equals &H0):%@AE@%%@NL@%
  5969.                 ELSE%@NL@%
  5970.                         CMask%(i%) = &H0%@NL@%
  5971.                 END IF%@NL@%
  5972. %@NL@%
  5973. %@AB@%                ' Shift the reference color right by one bit:%@AE@%%@NL@%
  5974.                 RefColor% = RefColor% \ 2%@NL@%
  5975.         NEXT i%%@NL@%
  5976. %@NL@%
  5977. END SUB%@NL@%
  5978. %@NL@%
  5979. %@AB@%'=== clColorMaskL% - Function to generate a byte with each pixel set to%@AE@%%@NL@%
  5980. %@AB@%'                 some color.%@AE@%%@NL@%
  5981. %@AB@%'%@AE@%%@NL@%
  5982. %@AB@%'  Arguments:%@AE@%%@NL@%
  5983. %@AB@%'     Bits%    -  Number of bits per pixel in current screen mode%@AE@%%@NL@%
  5984. %@AB@%'%@AE@%%@NL@%
  5985. %@AB@%'     Colr%    -  Color to make the mask%@AE@%%@NL@%
  5986. %@AB@%'%@AE@%%@NL@%
  5987. %@AB@%'  Return Values:%@AE@%%@NL@%
  5988. %@AB@%'     Returns integer with low byte that contains definitions for%@AE@%%@NL@%
  5989. %@AB@%'     pixels of specified color.%@AE@%%@NL@%
  5990. %@AB@%'%@AE@%%@NL@%
  5991. %@AB@%'=================================================================%@AE@%%@NL@%
  5992. FUNCTION clColorMaskL% (Bits%, Colr%)%@NL@%
  5993. %@NL@%
  5994. %@AB@%        ' Initialize the mask to zero:%@AE@%%@NL@%
  5995.         M% = 0%@NL@%
  5996. %@NL@%
  5997. %@AB@%        ' Multiplying a number by (2 ^ Bits%) will shift it left by "Bits%" bits:%@AE@%%@NL@%
  5998.         LShift% = 2 ^ Bits%%@NL@%
  5999. %@NL@%
  6000. %@AB@%        ' Create a byte in which each pixel (of "Bits%" bits) is set to%@AE@%%@NL@%
  6001. %@AB@%        ' Colr%.  This is done by setting the mask to "Colr%" then shifting%@AE@%%@NL@%
  6002. %@AB@%        ' it left by "Bits%" and repeating until the byte is full:%@AE@%%@NL@%
  6003.         FOR i% = 0 TO 7 \ Bits%%@NL@%
  6004.                 M% = M% * LShift% + Colr%%@NL@%
  6005.         NEXT i%%@NL@%
  6006. %@NL@%
  6007. %@AB@%        ' Return the mask as the value of the function:%@AE@%%@NL@%
  6008.         clColorMaskL% = M% MOD 256%@NL@%
  6009. %@NL@%
  6010. END FUNCTION%@NL@%
  6011. %@NL@%
  6012. %@AB@%'=== clDrawAxes - Draws the axes for a chart%@AE@%%@NL@%
  6013. %@AB@%'%@AE@%%@NL@%
  6014. %@AB@%'  Arguments:%@AE@%%@NL@%
  6015. %@AB@%'     Cat$(1)  -  One-dimensional array or category names for use in%@AE@%%@NL@%
  6016. %@AB@%'                 labeling the category axis (ignored if category%@AE@%%@NL@%
  6017. %@AB@%'                 axis not used)%@AE@%%@NL@%
  6018. %@AB@%'%@AE@%%@NL@%
  6019. %@AB@%'  Return Values:%@AE@%%@NL@%
  6020. %@AB@%'     No return values%@AE@%%@NL@%
  6021. %@AB@%'%@AE@%%@NL@%
  6022. %@AB@%'=================================================================%@AE@%%@NL@%
  6023. SUB clDrawAxes (Cat$())%@NL@%
  6024. SHARED GE AS ChartEnvironment, GP AS GlobalParams%@NL@%
  6025. SHARED GFI AS FontInfo%@NL@%
  6026. SHARED PaletteC%(), PaletteB%()%@NL@%
  6027. %@NL@%
  6028. %@AB@%        ' Use temporary variables to refer to axis limits:%@AE@%%@NL@%
  6029.         X1 = GE.XAxis.ScaleMin%@NL@%
  6030.         X2 = GE.XAxis.ScaleMax%@NL@%
  6031.         Y1 = GE.YAxis.ScaleMin%@NL@%
  6032.         Y2 = GE.YAxis.ScaleMax%@NL@%
  6033. %@NL@%
  6034. %@AB@%        ' To draw the tic/grid lines it is necessary to know where the line%@AE@%%@NL@%
  6035. %@AB@%        ' starts and ends.  If tic marks are specified (by setting%@AE@%%@NL@%
  6036. %@AB@%        ' the "labeled" flag in the axis definition) then the%@AE@%%@NL@%
  6037. %@AB@%        ' tic lines start "ticwidth" below or to the left of the X and%@AE@%%@NL@%
  6038. %@AB@%        ' Y axis respectively.  If grid lines are specified then the%@AE@%%@NL@%
  6039. %@AB@%        ' tic/grid line ends at ScaleMax for the respective axis.  The%@AE@%%@NL@%
  6040. %@AB@%        ' case statements below calculate where the tic/grid lines start%@AE@%%@NL@%
  6041. %@AB@%        ' based on the above criteria.%@AE@%%@NL@%
  6042. %@NL@%
  6043. %@AB@%        ' Check for tic marks first (X Axis):%@AE@%%@NL@%
  6044.         SELECT CASE GE.XAxis.Labeled%@NL@%
  6045.                 CASE cNo:  XTicMinY = Y1%@NL@%
  6046.                 CASE ELSE%@NL@%
  6047.                         XTicMinY = Y1 - cTicSize * (Y2 - Y1)%@NL@%
  6048.                         IF GP.XStagger = cYes THEN%@NL@%
  6049.                                 clSetChartFont GE.XAxis.TicFont%@NL@%
  6050.                                 XTicDropY = GFI.PixHeight * (Y2 - Y1) / (GE.DataWindow.Y2 - GE.DataWindow.Y1)%@NL@%
  6051.                         ELSE%@NL@%
  6052.                                 XTicDropY = 0%@NL@%
  6053.                         END IF%@NL@%
  6054.         END SELECT%@NL@%
  6055. %@NL@%
  6056. %@AB@%        ' (Y Axis):%@AE@%%@NL@%
  6057.         SELECT CASE GE.YAxis.Labeled%@NL@%
  6058.                 CASE cNo:  YTicMinX = X1%@NL@%
  6059.                 CASE ELSE: YTicMinX = X1 - cTicSize * (X2 - X1)%@NL@%
  6060.         END SELECT%@NL@%
  6061. %@NL@%
  6062. %@AB@%        ' Now for the other end of the tic/grid lines check for%@AE@%%@NL@%
  6063. %@AB@%        ' the grid flag (X axis):%@AE@%%@NL@%
  6064.         SELECT CASE GE.XAxis.grid%@NL@%
  6065.                 CASE cNo:  XTicMaxY = Y1%@NL@%
  6066.                 CASE ELSE: XTicMaxY = Y2%@NL@%
  6067.         END SELECT%@NL@%
  6068. %@NL@%
  6069. %@AB@%        ' (Y Axis):%@AE@%%@NL@%
  6070.         SELECT CASE GE.YAxis.grid%@NL@%
  6071.                 CASE cNo:  YTicMaxX = X1%@NL@%
  6072.                 CASE ELSE: YTicMaxX = X2%@NL@%
  6073.         END SELECT%@NL@%
  6074. %@NL@%
  6075. %@AB@%        ' Now that the beginning and end of the tic/grid lines has been%@AE@%%@NL@%
  6076. %@AB@%        ' calculated, it is necessary to figure out where they fall along the%@AE@%%@NL@%
  6077. %@AB@%        ' axes.  This depends on the type of axis: category or value.  On a%@AE@%%@NL@%
  6078. %@AB@%        ' category axis the tic/grid lines should fall in the middle of each%@AE@%%@NL@%
  6079. %@AB@%        ' bar set.  This is calculated by adding 1/2 of TicInterval to%@AE@%%@NL@%
  6080. %@AB@%        ' the beginning of the axis.  On a value axis the tic/grid line%@AE@%%@NL@%
  6081. %@AB@%        ' falls at the beginning of the axis.  It is also necessary to know%@AE@%%@NL@%
  6082. %@AB@%        ' the total number of tics per axis.  The following CASE statements%@AE@%%@NL@%
  6083. %@AB@%        ' calculate this.  Once the first tic/grid location on an axis is%@AE@%%@NL@%
  6084. %@AB@%        ' calculated the others can be calculated as they are drawn by adding%@AE@%%@NL@%
  6085. %@AB@%        ' TicInterval each time to the position of the previous tic mark:%@AE@%%@NL@%
  6086. %@NL@%
  6087. %@AB@%        ' Location of the first (leftmost) tic/grid line on the X axis:%@AE@%%@NL@%
  6088.         TicTotX% = CINT((X2 - X1) / GE.XAxis.TicInterval)%@NL@%
  6089.         SELECT CASE GP.XMode%@NL@%
  6090.                 CASE cCategory: TicX = X1 + GE.XAxis.TicInterval / 2%@NL@%
  6091.                 CASE ELSE%@NL@%
  6092.                         TicX = X1%@NL@%
  6093.                         TicTotX% = TicTotX% + 1%@NL@%
  6094.         END SELECT%@NL@%
  6095. %@NL@%
  6096. %@AB@%        ' Location of the first (top) tic/grid line on the Y axis:%@AE@%%@NL@%
  6097.         TicTotY% = CINT((Y2 - Y1) / GE.YAxis.TicInterval)%@NL@%
  6098.         SELECT CASE GP.YMode%@NL@%
  6099.                 CASE cCategory: TicY = Y1 + GE.YAxis.TicInterval / 2%@NL@%
  6100.                 CASE ELSE%@NL@%
  6101.                         TicY = Y1%@NL@%
  6102.                         TicTotY% = TicTotY% + 1%@NL@%
  6103.         END SELECT%@NL@%
  6104. %@NL@%
  6105. %@AB@%        ' Now it's time to draw the axes; first the X then the Y axis.%@AE@%%@NL@%
  6106. %@AB@%        ' There's a small complexity that has to be dealt with first, though.%@AE@%%@NL@%
  6107. %@AB@%        ' The tic/grid lines are specified in "world" coordinates since that%@AE@%%@NL@%
  6108. %@AB@%        ' is easier to calculate but the current VIEW (the DataWindow) would%@AE@%%@NL@%
  6109. %@AB@%        ' clip them since tic marks (and also labels) lie outside of that%@AE@%%@NL@%
  6110. %@AB@%        ' region.  The solution is to extrapolate the DataWindow "world" to the%@AE@%%@NL@%
  6111. %@AB@%        ' ChartWindow region and set our VIEW to the ChartWindow.  This will%@AE@%%@NL@%
  6112. %@AB@%        ' clip labels if they are too long and try to go outside the Chart%@AE@%%@NL@%
  6113. %@AB@%        ' Window but still allow use of world coordinates for specifying%@AE@%%@NL@%
  6114. %@AB@%        ' locations.  To extrapolate the world coordinates to the ChartWindow,%@AE@%%@NL@%
  6115. %@AB@%        ' PMAP can be used.  This works since PMAP can take pixel coordinates%@AE@%%@NL@%
  6116. %@AB@%        ' outside of the current VIEW and map them to the appropriate world%@AE@%%@NL@%
  6117. %@AB@%        ' coordinates.  The DataWindow coordinates (calculated in the routine%@AE@%%@NL@%
  6118. %@AB@%        ' clSizeDataWindow) are expressed relative to the ChartWindow so%@AE@%%@NL@%
  6119. %@AB@%        ' it can be somewhat complicated trying to understand what to use with%@AE@%%@NL@%
  6120. %@AB@%        ' PMAP.  If you draw a picture of it things will appear more straight%@AE@%%@NL@%
  6121. %@AB@%        ' forward.%@AE@%%@NL@%
  6122. %@NL@%
  6123. %@AB@%        ' To make sure that bars and columns aren't drawn over the axis lines%@AE@%%@NL@%
  6124. %@AB@%        ' temporarily move the left DataWindow border left by one and the bottom%@AE@%%@NL@%
  6125. %@AB@%        ' border down by one pixel:%@AE@%%@NL@%
  6126.         GE.DataWindow.X1 = GE.DataWindow.X1 - 1%@NL@%
  6127.         GE.DataWindow.Y2 = GE.DataWindow.Y2 + 1%@NL@%
  6128. %@NL@%
  6129. %@AB@%        ' Select the DataWindow view and assign the "world" to it:%@AE@%%@NL@%
  6130.         clSelectRelWindow GE.DataWindow%@NL@%
  6131.         WINDOW (X1, Y1)-(X2, Y2)%@NL@%
  6132.         GTextWindow X1, Y1, X2, Y2, cFalse%@NL@%
  6133. %@NL@%
  6134. %@AB@%        ' Next, use PMAP to extrapolate to ChartWindow:%@AE@%%@NL@%
  6135.         WorldX1 = PMAP(-GE.DataWindow.X1, 2)%@NL@%
  6136.         WorldX2 = PMAP(GP.ChartWid - 1 - GE.DataWindow.X1, 2)%@NL@%
  6137. %@NL@%
  6138.         WorldY1 = PMAP(GP.ChartHgt - 1 - GE.DataWindow.Y1, 3)%@NL@%
  6139.         WorldY2 = PMAP(-GE.DataWindow.Y1, 3)%@NL@%
  6140. %@NL@%
  6141. %@AB@%        ' Reset the DataWindow borders back to their original settings:%@AE@%%@NL@%
  6142.         GE.DataWindow.X1 = GE.DataWindow.X1 + 1%@NL@%
  6143.         GE.DataWindow.Y2 = GE.DataWindow.Y2 - 1%@NL@%
  6144. %@NL@%
  6145. %@AB@%        ' Finally, select the ChartWindow VIEW and apply the extrapolated%@AE@%%@NL@%
  6146. %@AB@%        ' window to it:%@AE@%%@NL@%
  6147.         clSelectChartWindow%@NL@%
  6148.         WINDOW (WorldX1, WorldY1)-(WorldX2, WorldY2)%@NL@%
  6149.         GTextWindow WorldX1, WorldY1, WorldX2, WorldY2, cFalse%@NL@%
  6150. %@NL@%
  6151. %@AB@%         ' Draw the X and Y axes (one pixel to left and bottom of window):%@AE@%%@NL@%
  6152.         CX% = PaletteC%(clMap2Pal%(GE.XAxis.AxisColor))  ' Color of X axis%@NL@%
  6153.         CY% = PaletteC%(clMap2Pal%(GE.YAxis.AxisColor))  ' Color of Y axis%@NL@%
  6154. %@NL@%
  6155.         SX% = PaletteB%(clMap2Pal%(GE.XAxis.GridStyle)) ' Line styles; X grid%@NL@%
  6156.         SY% = PaletteB%(clMap2Pal%(GE.YAxis.GridStyle)) ' Line styles; Y grid%@NL@%
  6157. %@NL@%
  6158.         LINE (X1, Y1)-(X2, Y1), CX%%@NL@%
  6159.         LINE (X1, Y1)-(X1, Y2), CY%%@NL@%
  6160. %@NL@%
  6161. %@AB@%        ' X-Axis...Draw styled grid line then solid tic mark:%@AE@%%@NL@%
  6162.         TicLoc = TicX%@NL@%
  6163.         Stagger% = cFalse%@NL@%
  6164.         FOR i% = 1 TO TicTotX%%@NL@%
  6165.                 LINE (TicLoc, Y1)-(TicLoc, XTicMaxY), CY%, , SX%%@NL@%
  6166.                 IF Stagger% THEN%@NL@%
  6167.                         LINE (TicLoc, XTicMinY - XTicDropY)-(TicLoc, Y1), CX%%@NL@%
  6168.                         Stagger% = cFalse%@NL@%
  6169.                 ELSE%@NL@%
  6170.                         LINE (TicLoc, XTicMinY)-(TicLoc, Y1), CX%%@NL@%
  6171.                         Stagger% = cTrue%@NL@%
  6172.                 END IF%@NL@%
  6173.                 TicLoc = TicLoc + GE.XAxis.TicInterval%@NL@%
  6174.         NEXT i%%@NL@%
  6175. %@NL@%
  6176. %@AB@%        ' Y-Axis...Draw styled grid line then solid tic mark:%@AE@%%@NL@%
  6177.         TicLoc = TicY%@NL@%
  6178.         FOR i% = 1 TO TicTotY%%@NL@%
  6179.                 LINE (X1, TicLoc)-(YTicMaxX, TicLoc), CX%, , SY%%@NL@%
  6180.                 LINE (YTicMinX, TicLoc)-(X1, TicLoc), CY%%@NL@%
  6181.                 TicLoc = TicLoc + GE.YAxis.TicInterval%@NL@%
  6182.         NEXT i%%@NL@%
  6183. %@NL@%
  6184. %@AB@%        ' Label X tic marks and print titles:%@AE@%%@NL@%
  6185.         clLabelXTics GE.XAxis, Cat$(), TicX, TicTotX%, XTicMinY, YBoundry%%@NL@%
  6186.         clTitleXAxis GE.XAxis, GE.DataWindow.X1, GE.DataWindow.X2, YBoundry%%@NL@%
  6187. %@NL@%
  6188. %@AB@%        ' Label Y tic marks and print titles:%@AE@%%@NL@%
  6189.         clLabelYTics GE.YAxis, Cat$(), YTicMinX, TicY, TicTotY%%@NL@%
  6190.         clTitleYAxis GE.YAxis, GE.DataWindow.Y1, GE.DataWindow.Y2%@NL@%
  6191. %@NL@%
  6192. END SUB%@NL@%
  6193. %@NL@%
  6194. %@AB@%'=== clDrawBarData - Draws data portion of multi-series bar chart%@AE@%%@NL@%
  6195. %@AB@%'%@AE@%%@NL@%
  6196. %@AB@%'  Arguments:%@AE@%%@NL@%
  6197. %@AB@%'     None%@AE@%%@NL@%
  6198. %@AB@%'%@AE@%%@NL@%
  6199. %@AB@%'  Return Values:%@AE@%%@NL@%
  6200. %@AB@%'     None%@AE@%%@NL@%
  6201. %@AB@%'%@AE@%%@NL@%
  6202. %@AB@%'=================================================================%@AE@%%@NL@%
  6203. SUB clDrawBarData%@NL@%
  6204. SHARED GE AS ChartEnvironment, GP AS GlobalParams%@NL@%
  6205. SHARED PaletteC%()%@NL@%
  6206. SHARED V1()%@NL@%
  6207. %@NL@%
  6208. %@AB@%        ' Set the VIEW to the DataWindow:%@AE@%%@NL@%
  6209.         clSelectRelWindow GE.DataWindow%@NL@%
  6210. %@NL@%
  6211. %@AB@%        ' Set the WINDOW to match:%@AE@%%@NL@%
  6212.         WINDOW (GE.XAxis.ScaleMin, GE.YAxis.ScaleMin)-(GE.XAxis.ScaleMax, GE.YAxis.ScaleMax)%@NL@%
  6213.         GTextWindow GE.XAxis.ScaleMin, GE.YAxis.ScaleMin, GE.XAxis.ScaleMax, GE.YAxis.ScaleMax, cFalse%@NL@%
  6214. %@NL@%
  6215. %@AB@%        ' If this is a linear axis then determine where the bars should grow from:%@AE@%%@NL@%
  6216.         IF GE.XAxis.RangeType = cLinear THEN%@NL@%
  6217. %@NL@%
  6218. %@AB@%                ' If the scale minimum and maximum are on opposite sides of zero%@AE@%%@NL@%
  6219. %@AB@%                ' set the bar starting point to zero:%@AE@%%@NL@%
  6220.                 IF GE.XAxis.ScaleMin < 0 AND GE.XAxis.ScaleMax > 0 THEN%@NL@%
  6221.                         BarMin = 0%@NL@%
  6222. %@NL@%
  6223. %@AB@%                ' If the axis range is all negative the the bars should grow from%@AE@%%@NL@%
  6224. %@AB@%                ' the right to the left so make the bar starting point the scale%@AE@%%@NL@%
  6225. %@AB@%                ' maximum:%@AE@%%@NL@%
  6226.                 ELSEIF GE.XAxis.ScaleMin < 0 THEN%@NL@%
  6227.                         BarMin = GE.XAxis.ScaleMax%@NL@%
  6228. %@NL@%
  6229. %@AB@%                ' The axis range is all positive so the bar starting point is the%@AE@%%@NL@%
  6230. %@AB@%                ' scale minimum:%@AE@%%@NL@%
  6231.                 ELSE%@NL@%
  6232.                         BarMin = GE.XAxis.ScaleMin%@NL@%
  6233.                 END IF%@NL@%
  6234. %@NL@%
  6235. %@AB@%        ' The bar starting point for log axes should always be the scale minimum%@AE@%%@NL@%
  6236. %@AB@%        ' since only positive numbers are represented on a log axis (even though%@AE@%%@NL@%
  6237. %@AB@%        ' the log of small numbers is negative):%@AE@%%@NL@%
  6238.         ELSE%@NL@%
  6239.                 BarMin = GE.XAxis.ScaleMin%@NL@%
  6240.         END IF%@NL@%
  6241. %@NL@%
  6242. %@AB@%        ' Calculate the width of a bar.  Divide by the number of%@AE@%%@NL@%
  6243. %@AB@%        ' series if it's a plain (not stacked) chart:%@AE@%%@NL@%
  6244.         BarWid = GE.YAxis.TicInterval * cBarWid%@NL@%
  6245.         IF GE.ChartStyle = cPlain THEN BarWid = BarWid / GP.NSeries%@NL@%
  6246. %@NL@%
  6247. %@AB@%        ' Calculate the beginning Y value of first bar then loop drawing%@AE@%%@NL@%
  6248. %@AB@%        ' all the bars:%@AE@%%@NL@%
  6249.         SpaceWid = GE.YAxis.TicInterval * (1 - cBarWid)%@NL@%
  6250.         StartLoc = GE.YAxis.ScaleMax - SpaceWid / 2%@NL@%
  6251. %@NL@%
  6252.         FOR i% = 1 TO GP.NVals%@NL@%
  6253. %@NL@%
  6254. %@AB@%                ' Reset sum variables for positive and negative stacked bars:%@AE@%%@NL@%
  6255.                 RSumPos = 0%@NL@%
  6256.                 RSumNeg = 0%@NL@%
  6257. %@NL@%
  6258. %@AB@%                ' Reset the bar starting points:%@AE@%%@NL@%
  6259.                 BarStartPos = BarMin%@NL@%
  6260.                 BarStartNeg = BarMin%@NL@%
  6261. %@NL@%
  6262. %@AB@%                ' Reset starting Y location of this bar set:%@AE@%%@NL@%
  6263.                 BarLoc = StartLoc%@NL@%
  6264. %@NL@%
  6265. %@AB@%                ' Now, chart the different series for this category:%@AE@%%@NL@%
  6266.                 FOR J% = 1 TO GP.NSeries%@NL@%
  6267. %@NL@%
  6268. %@AB@%                        ' Get the value to chart from the data array:%@AE@%%@NL@%
  6269.                         V = V1(i%, J%)%@NL@%
  6270. %@NL@%
  6271. %@AB@%                        ' If the value isn't a missing one then try to chart it:%@AE@%%@NL@%
  6272.                         IF V <> cMissingValue THEN%@NL@%
  6273. %@NL@%
  6274. %@AB@%                                ' If the X-axis has the AutoScale flag set then divide%@AE@%%@NL@%
  6275. %@AB@%                                ' the value by the axis' ScaleFactor variable:%@AE@%%@NL@%
  6276.                                 IF GE.XAxis.AutoScale = cYes THEN V = V / GE.XAxis.ScaleFactor%@NL@%
  6277. %@NL@%
  6278. %@AB@%                                ' If this is a plain chart then calculate the bar's location%@AE@%%@NL@%
  6279. %@AB@%                                ' and draw it:%@AE@%%@NL@%
  6280.                                 IF GE.ChartStyle = cPlain THEN%@NL@%
  6281. %@NL@%
  6282.                                         BarLoc = StartLoc - (J% - 1) * BarWid%@NL@%
  6283.                                         clRenderBar BarMin, BarLoc, V, BarLoc - BarWid, J%%@NL@%
  6284. %@NL@%
  6285. %@AB@%                                ' If the bars should be stacked then draw either a positive or%@AE@%%@NL@%
  6286. %@AB@%                                ' negative portion of a bar depending on whether the data value%@AE@%%@NL@%
  6287. %@AB@%                                ' is positive or negative:%@AE@%%@NL@%
  6288.                                 ELSE%@NL@%
  6289. %@NL@%
  6290. %@AB@%                                        ' If the value is positive:%@AE@%%@NL@%
  6291.                                         IF V > 0 THEN%@NL@%
  6292. %@NL@%
  6293. %@AB@%                                                ' Add the value to the current sum for the bar and draw%@AE@%%@NL@%
  6294. %@AB@%                                                ' the bar from the top of the last portion:%@AE@%%@NL@%
  6295.                                                 RSumPos = RSumPos + V%@NL@%
  6296.                                                 clRenderBar BarStartPos, BarLoc, RSumPos, BarLoc - BarWid, J%%@NL@%
  6297.                                                 BarStartPos = RSumPos%@NL@%
  6298. %@NL@%
  6299. %@AB@%                                        ' If the value is negative:%@AE@%%@NL@%
  6300.                                         ELSE%@NL@%
  6301. %@NL@%
  6302. %@AB@%                                                ' Add the value to the current sum for the bar and draw%@AE@%%@NL@%
  6303. %@AB@%                                                ' the bar from the bottom of the last portion:%@AE@%%@NL@%
  6304.                                                 RSumNeg = RSumNeg + V%@NL@%
  6305.                                                 clRenderBar BarStartNeg, BarLoc, RSumNeg, BarLoc - BarWid, J%%@NL@%
  6306.                                                 BarStartNeg = RSumNeg%@NL@%
  6307. %@NL@%
  6308.                                         END IF%@NL@%
  6309.                                 END IF%@NL@%
  6310.                         END IF%@NL@%
  6311. %@NL@%
  6312.                 NEXT J%%@NL@%
  6313. %@NL@%
  6314. %@AB@%                ' Update the bar cluster's starting location:%@AE@%%@NL@%
  6315.                 StartLoc = StartLoc - GE.YAxis.TicInterval%@NL@%
  6316. %@NL@%
  6317.         NEXT i%%@NL@%
  6318. %@NL@%
  6319. %@AB@%        ' If BarMin isn't the axis minimum then draw a reference line:%@AE@%%@NL@%
  6320.         IF BarMin <> GE.XAxis.ScaleMin THEN%@NL@%
  6321.                 LINE (BarMin, GE.YAxis.ScaleMin)-(BarMin, GE.YAxis.ScaleMax), PaletteC%(clMap2Pal%(GE.YAxis.AxisColor))%@NL@%
  6322.         END IF%@NL@%
  6323. %@NL@%
  6324. END SUB%@NL@%
  6325. %@NL@%
  6326. %@AB@%'=== clDrawChartWindow - Draws the Chart window%@AE@%%@NL@%
  6327. %@AB@%'%@AE@%%@NL@%
  6328. %@AB@%'  Arguments:%@AE@%%@NL@%
  6329. %@AB@%'     None%@AE@%%@NL@%
  6330. %@AB@%'%@AE@%%@NL@%
  6331. %@AB@%'  Return Values:%@AE@%%@NL@%
  6332. %@AB@%'     None%@AE@%%@NL@%
  6333. %@AB@%'%@AE@%%@NL@%
  6334. %@AB@%'  Remarks:%@AE@%%@NL@%
  6335. %@AB@%'     This routine erases any previous viewport%@AE@%%@NL@%
  6336. %@AB@%'%@AE@%%@NL@%
  6337. %@AB@%'=================================================================%@AE@%%@NL@%
  6338. SUB clDrawChartWindow%@NL@%
  6339. SHARED GE AS ChartEnvironment%@NL@%
  6340. %@NL@%
  6341. %@AB@%        ' Define viewport then render window:%@AE@%%@NL@%
  6342.         clSelectChartWindow%@NL@%
  6343.         clRenderWindow GE.ChartWindow%@NL@%
  6344. %@NL@%
  6345. END SUB%@NL@%
  6346. %@NL@%
  6347. %@AB@%'=== clDrawColumnData - Draws data portion of MS Column chart%@AE@%%@NL@%
  6348. %@AB@%'%@AE@%%@NL@%
  6349. %@AB@%'  Arguments:%@AE@%%@NL@%
  6350. %@AB@%'     None%@AE@%%@NL@%
  6351. %@AB@%'%@AE@%%@NL@%
  6352. %@AB@%'  Return Values:%@AE@%%@NL@%
  6353. %@AB@%'     None%@AE@%%@NL@%
  6354. %@AB@%'%@AE@%%@NL@%
  6355. %@AB@%'=================================================================%@AE@%%@NL@%
  6356. SUB clDrawColumnData%@NL@%
  6357. SHARED GP AS GlobalParams, GE AS ChartEnvironment%@NL@%
  6358. SHARED PaletteC%(), V1()%@NL@%
  6359. %@NL@%
  6360. %@AB@%        ' First, set the VIEW to DataWindow:%@AE@%%@NL@%
  6361.         clSelectRelWindow GE.DataWindow%@NL@%
  6362. %@NL@%
  6363. %@AB@%        ' Set the WINDOW to match:%@AE@%%@NL@%
  6364.         WINDOW (GE.XAxis.ScaleMin, GE.YAxis.ScaleMin)-(GE.XAxis.ScaleMax, GE.YAxis.ScaleMax)%@NL@%
  6365.         GTextWindow GE.XAxis.ScaleMin, GE.YAxis.ScaleMin, GE.XAxis.ScaleMax, GE.YAxis.ScaleMax, cFalse%@NL@%
  6366. %@NL@%
  6367. %@AB@%        ' If this is a linear axis then determine where the bars should grow from:%@AE@%%@NL@%
  6368.         IF GE.YAxis.RangeType = cLinear THEN%@NL@%
  6369. %@NL@%
  6370. %@AB@%                ' Draw 0 reference line if the scale minimum and maximum are on%@AE@%%@NL@%
  6371. %@AB@%                ' opposite sides of zero.  Also set the bar starting point to zero%@AE@%%@NL@%
  6372. %@AB@%                ' so that bars grow from the zero line:%@AE@%%@NL@%
  6373.                 IF GE.YAxis.ScaleMin < 0 AND GE.YAxis.ScaleMax > 0 THEN%@NL@%
  6374.                         BarMin = 0%@NL@%
  6375. %@NL@%
  6376. %@AB@%                ' If the axis range is all negative the the bars should grow from%@AE@%%@NL@%
  6377. %@AB@%                ' the right to the left so make the bar starting point the scale%@AE@%%@NL@%
  6378. %@AB@%                ' maximum:%@AE@%%@NL@%
  6379.                 ELSEIF GE.YAxis.ScaleMin < 0 THEN%@NL@%
  6380.                         BarMin = GE.YAxis.ScaleMax%@NL@%
  6381. %@NL@%
  6382. %@AB@%                ' The axis range is all positive so the bar starting point is the%@AE@%%@NL@%
  6383. %@AB@%                ' scale minimum:%@AE@%%@NL@%
  6384.                 ELSE%@NL@%
  6385.                         BarMin = GE.YAxis.ScaleMin%@NL@%
  6386.                 END IF%@NL@%
  6387. %@NL@%
  6388. %@AB@%        ' The bar starting point for log axes should always be the scale minimum%@AE@%%@NL@%
  6389. %@AB@%        ' since only positive numbers are represented on a log axis (even though%@AE@%%@NL@%
  6390. %@AB@%        ' the log of small numbers is negative):%@AE@%%@NL@%
  6391.         ELSE%@NL@%
  6392.                 BarMin = GE.YAxis.ScaleMin%@NL@%
  6393.         END IF%@NL@%
  6394. %@NL@%
  6395. %@AB@%        ' Calculate the width of a bar.  Divide by the number of%@AE@%%@NL@%
  6396. %@AB@%        ' series if it's a plain (not stacked) chart:%@AE@%%@NL@%
  6397.         BarWid = GE.XAxis.TicInterval * cBarWid%@NL@%
  6398.         IF GE.ChartStyle = cPlain THEN BarWid = BarWid / GP.NSeries%@NL@%
  6399. %@NL@%
  6400. %@AB@%        ' calculate the beginning X value of first bar and loop, drawing all%@AE@%%@NL@%
  6401. %@AB@%        ' the bars:%@AE@%%@NL@%
  6402.         SpaceWid = GE.XAxis.TicInterval * (1 - cBarWid)%@NL@%
  6403.         StartLoc = GE.XAxis.ScaleMin + SpaceWid / 2%@NL@%
  6404. %@NL@%
  6405.         FOR i% = 1 TO GP.NVals%@NL@%
  6406. %@NL@%
  6407. %@AB@%                ' Reset sum variables for positive and negative stacked bars:%@AE@%%@NL@%
  6408.                 RSumPos = 0%@NL@%
  6409.                 RSumNeg = 0%@NL@%
  6410. %@NL@%
  6411.                 BarStartPos = BarMin%@NL@%
  6412.                 BarStartNeg = BarMin%@NL@%
  6413. %@NL@%
  6414. %@AB@%                ' Reset starting Y location of this bar set:%@AE@%%@NL@%
  6415.                 BarLoc = StartLoc%@NL@%
  6416. %@NL@%
  6417. %@AB@%                ' Now, go across the rows charting the different series for%@AE@%%@NL@%
  6418. %@AB@%                ' this category:%@AE@%%@NL@%
  6419.                 FOR J% = 1 TO GP.NSeries%@NL@%
  6420. %@NL@%
  6421. %@AB@%                        ' Get the value to chart from the data array:%@AE@%%@NL@%
  6422.                         V = V1(i%, J%)%@NL@%
  6423. %@NL@%
  6424. %@AB@%                        ' If the value isn't a missing one then try to chart it:%@AE@%%@NL@%
  6425.                         IF V <> cMissingValue THEN%@NL@%
  6426. %@NL@%
  6427. %@AB@%                                ' If the Y-axis has the AutoScale flag set then divide%@AE@%%@NL@%
  6428. %@AB@%                                ' the value by the axis' ScaleFactor variable:%@AE@%%@NL@%
  6429.                                 IF GE.YAxis.AutoScale = cYes THEN V = V / GE.YAxis.ScaleFactor%@NL@%
  6430. %@NL@%
  6431. %@AB@%                                ' If this is a plain chart then calculate the bar's location%@AE@%%@NL@%
  6432. %@AB@%                                ' and draw it:%@AE@%%@NL@%
  6433.                                 IF GE.ChartStyle = cPlain THEN%@NL@%
  6434. %@NL@%
  6435.                                         BarLoc = StartLoc + (J% - 1) * BarWid%@NL@%
  6436.                                         clRenderBar BarLoc, BarMin, BarLoc + BarWid, V, J%%@NL@%
  6437. %@NL@%
  6438. %@AB@%                                ' If the bars should be stacked then draw either a positive or%@AE@%%@NL@%
  6439. %@AB@%                                ' negative portion of a bar depending on whether the data value%@AE@%%@NL@%
  6440. %@AB@%                                ' is positive or negative:%@AE@%%@NL@%
  6441.                                 ELSE%@NL@%
  6442. %@NL@%
  6443. %@AB@%                                        ' If the value is positive:%@AE@%%@NL@%
  6444.                                         IF V > 0 THEN%@NL@%
  6445. %@NL@%
  6446. %@AB@%                                                ' Add the value to the current sum for the bar and draw%@AE@%%@NL@%
  6447. %@AB@%                                                ' the bar from the top of the last portion:%@AE@%%@NL@%
  6448.                                                 RSumPos = RSumPos + V%@NL@%
  6449.                                                 clRenderBar BarLoc, BarStartPos, BarLoc + BarWid, RSumPos, J%%@NL@%
  6450.                                                 BarStartPos = RSumPos%@NL@%
  6451. %@NL@%
  6452. %@AB@%                                        ' If the value is negative:%@AE@%%@NL@%
  6453.                                         ELSE%@NL@%
  6454. %@NL@%
  6455. %@AB@%                                                ' Add the value to the current sum for the bar and draw%@AE@%%@NL@%
  6456. %@AB@%                                                ' the bar from the bottom of the last portion:%@AE@%%@NL@%
  6457.                                                 RSumNeg = RSumNeg + V%@NL@%
  6458.                                                 clRenderBar BarLoc, BarStartNeg, BarLoc + BarWid, RSumNeg, J%%@NL@%
  6459.                                                 BarStartNeg = RSumNeg%@NL@%
  6460. %@NL@%
  6461.                                         END IF%@NL@%
  6462.                                 END IF%@NL@%
  6463.                         END IF%@NL@%
  6464. %@NL@%
  6465.                 NEXT J%%@NL@%
  6466. %@NL@%
  6467. %@AB@%                ' Update the bar cluster's starting location:%@AE@%%@NL@%
  6468.                 StartLoc = StartLoc + GE.XAxis.TicInterval%@NL@%
  6469. %@NL@%
  6470.         NEXT i%%@NL@%
  6471. %@NL@%
  6472. %@AB@%        ' If BarMin isn't the axis minimum then draw a reference line:%@AE@%%@NL@%
  6473.         IF BarMin <> GE.YAxis.ScaleMin THEN%@NL@%
  6474.                 LINE (GE.XAxis.ScaleMin, BarMin)-(GE.XAxis.ScaleMax, BarMin), PaletteC%(clMap2Pal%(GE.XAxis.AxisColor))%@NL@%
  6475.         END IF%@NL@%
  6476. %@NL@%
  6477. END SUB%@NL@%
  6478. %@NL@%
  6479. %@AB@%'=== clDrawDataWindow - Draws the Data window%@AE@%%@NL@%
  6480. %@AB@%'%@AE@%%@NL@%
  6481. %@AB@%'  Arguments:%@AE@%%@NL@%
  6482. %@AB@%'     None%@AE@%%@NL@%
  6483. %@AB@%'%@AE@%%@NL@%
  6484. %@AB@%'  Return Values:%@AE@%%@NL@%
  6485. %@AB@%'     None%@AE@%%@NL@%
  6486. %@AB@%'%@AE@%%@NL@%
  6487. %@AB@%'  Remarks:%@AE@%%@NL@%
  6488. %@AB@%'     This routine erases any previous viewport or window specification.%@AE@%%@NL@%
  6489. %@AB@%'%@AE@%%@NL@%
  6490. %@AB@%'=================================================================%@AE@%%@NL@%
  6491. SUB clDrawDataWindow%@NL@%
  6492. SHARED GE AS ChartEnvironment%@NL@%
  6493. %@NL@%
  6494. %@AB@%        ' Define viewport then render window:%@AE@%%@NL@%
  6495.         clSelectRelWindow GE.DataWindow%@NL@%
  6496.         clRenderWindow GE.DataWindow%@NL@%
  6497. %@NL@%
  6498. END SUB%@NL@%
  6499. %@NL@%
  6500. %@AB@%'=== clDrawLegend - Draws a legend%@AE@%%@NL@%
  6501. %@AB@%'%@AE@%%@NL@%
  6502. %@AB@%'  Arguments:%@AE@%%@NL@%
  6503. %@AB@%'     SeriesLabel$(1)   - Array of labels for the legend%@AE@%%@NL@%
  6504. %@AB@%'%@AE@%%@NL@%
  6505. %@AB@%'     First%            - Label number corresponding to first series%@AE@%%@NL@%
  6506. %@AB@%'%@AE@%%@NL@%
  6507. %@AB@%'     Last%             - Label number corresponding to last series%@AE@%%@NL@%
  6508. %@AB@%'%@AE@%%@NL@%
  6509. %@AB@%'  Return Values:%@AE@%%@NL@%
  6510. %@AB@%'     None.%@AE@%%@NL@%
  6511. %@AB@%'%@AE@%%@NL@%
  6512. %@AB@%'=================================================================%@AE@%%@NL@%
  6513. SUB clDrawLegend (SeriesLabel$(), First AS INTEGER, Last AS INTEGER)%@NL@%
  6514. %@NL@%
  6515. SHARED GE AS ChartEnvironment, GP AS GlobalParams%@NL@%
  6516. SHARED PaletteC%(), PaletteP$(), PaletteCh%()%@NL@%
  6517. SHARED GFI AS FontInfo%@NL@%
  6518. SHARED LLayout AS LegendLayout%@NL@%
  6519. %@NL@%
  6520. %@AB@%        ' If legend flag is No then exit:%@AE@%%@NL@%
  6521.         IF GE.Legend.Legend = cNo THEN EXIT SUB%@NL@%
  6522. %@NL@%
  6523. %@AB@%        ' Select and render the legend window:%@AE@%%@NL@%
  6524.         clSelectRelWindow GE.Legend.LegendWindow%@NL@%
  6525.         clRenderWindow GE.Legend.LegendWindow%@NL@%
  6526.         WINDOW%@NL@%
  6527.         GTextWindow 0, 0, 0, 0, cFalse%@NL@%
  6528. %@NL@%
  6529. %@AB@%        ' Start with the first label, set the Y position of the first line%@AE@%%@NL@%
  6530. %@AB@%        ' of labels and loop through all the rows in the legend:%@AE@%%@NL@%
  6531.         clSetChartFont GE.Legend.TextFont%@NL@%
  6532.         LabelNum% = First%@NL@%
  6533.         YPos% = LLayout.HorizBorder%@NL@%
  6534.         FOR i% = 1 TO LLayout.NumRow%@NL@%
  6535. %@NL@%
  6536. %@AB@%                ' Set position of beginning of row:%@AE@%%@NL@%
  6537.                 XPos% = LLayout.VertBorder%@NL@%
  6538. %@NL@%
  6539.                 FOR J% = 1 TO LLayout.NumCol%@NL@%
  6540. %@NL@%
  6541. %@AB@%                        ' Map the label number to a valid palette reference:%@AE@%%@NL@%
  6542.                         MJ% = clMap2Pal%(LabelNum% - First + 1)%@NL@%
  6543. %@NL@%
  6544. %@AB@%                        ' Depending on ChartType draw either a filled box or the%@AE@%%@NL@%
  6545. %@AB@%                        ' plot character used for plotting:%@AE@%%@NL@%
  6546.                         XStep% = LLayout.SymbolSize / GP.Aspect%@NL@%
  6547.                         SELECT CASE GE.ChartType%@NL@%
  6548. %@NL@%
  6549.                                 CASE cBar, cColumn, cPie:%@NL@%
  6550.                                         LINE (XPos%, YPos%)-STEP(XStep%, LLayout.SymbolSize), 0, BF%@NL@%
  6551.                                         LINE (XPos%, YPos%)-STEP(XStep%, LLayout.SymbolSize), 1, B%@NL@%
  6552.                                         PAINT (XPos% + 1, YPos% + 1), PaletteP$(MJ%), 1%@NL@%
  6553.                                         LINE (XPos%, YPos%)-STEP(XStep%, LLayout.SymbolSize), PaletteC%(MJ%), B%@NL@%
  6554. %@NL@%
  6555.                                 CASE cLine, cScatter:%@NL@%
  6556.                                         clSetCharColor MJ%%@NL@%
  6557.                                         PlotChr$ = CHR$(PaletteCh%(MJ%))%@NL@%
  6558.                                         clHPrint XPos% + XStep% - GFI.AvgWidth, YPos% - GFI.Leading, PlotChr$%@NL@%
  6559. %@NL@%
  6560.                         END SELECT%@NL@%
  6561. %@NL@%
  6562. %@AB@%                        ' Print the label for this entry in the legend:%@AE@%%@NL@%
  6563.                         clSetCharColor GE.Legend.TextColor%@NL@%
  6564.                         clHPrint XPos% + LLayout.LabelOffset, YPos% - GFI.Leading, SeriesLabel$(LabelNum%)%@NL@%
  6565. %@NL@%
  6566. %@AB@%                        ' Increment the label count and check count has finished:%@AE@%%@NL@%
  6567.                         LabelNum% = LabelNum% + 1%@NL@%
  6568.                         IF LabelNum% > Last THEN EXIT SUB%@NL@%
  6569. %@NL@%
  6570. %@AB@%                        ' Move over to the next column:%@AE@%%@NL@%
  6571.                         XPos% = XPos% + LLayout.ColSpacing%@NL@%
  6572. %@NL@%
  6573.                 NEXT J%%@NL@%
  6574. %@NL@%
  6575. %@AB@%                ' Move position to the next row:%@AE@%%@NL@%
  6576.                 YPos% = YPos% + LLayout.RowSpacing%@NL@%
  6577. %@NL@%
  6578.         NEXT i%%@NL@%
  6579. %@NL@%
  6580. END SUB%@NL@%
  6581. %@NL@%
  6582. %@AB@%'=== clDrawLineData - Draws data portion line chart%@AE@%%@NL@%
  6583. %@AB@%'%@AE@%%@NL@%
  6584. %@AB@%'  Arguments:%@AE@%%@NL@%
  6585. %@AB@%'     None%@AE@%%@NL@%
  6586. %@AB@%'%@AE@%%@NL@%
  6587. %@AB@%'  Return Values:%@AE@%%@NL@%
  6588. %@AB@%'     None%@AE@%%@NL@%
  6589. %@AB@%'%@AE@%%@NL@%
  6590. %@AB@%'=================================================================%@AE@%%@NL@%
  6591. SUB clDrawLineData%@NL@%
  6592. SHARED GE AS ChartEnvironment, GP AS GlobalParams%@NL@%
  6593. SHARED PaletteC%(), PaletteS%(), PaletteCh%()%@NL@%
  6594. SHARED GFI AS FontInfo%@NL@%
  6595. SHARED V1()%@NL@%
  6596. %@NL@%
  6597. %@AB@%        ' First, set the appropriate font and make text horizontal:%@AE@%%@NL@%
  6598.         clSetChartFont GE.DataFont%@NL@%
  6599.         SetGTextDir 0%@NL@%
  6600. %@NL@%
  6601. %@AB@%        ' Then, set the view to DataWindow:%@AE@%%@NL@%
  6602.         clSelectRelWindow GE.DataWindow%@NL@%
  6603. %@NL@%
  6604. %@AB@%        ' Set the window to match:%@AE@%%@NL@%
  6605.         WINDOW (GE.XAxis.ScaleMin, GE.YAxis.ScaleMin)-(GE.XAxis.ScaleMax, GE.YAxis.ScaleMax)%@NL@%
  6606.         GTextWindow GE.XAxis.ScaleMin, GE.YAxis.ScaleMin, GE.XAxis.ScaleMax, GE.YAxis.ScaleMax, cFalse%@NL@%
  6607. %@NL@%
  6608. %@AB@%        ' Loop through the series:%@AE@%%@NL@%
  6609.         FOR J% = 1 TO GP.NSeries%@NL@%
  6610. %@NL@%
  6611. %@AB@%                ' Map the series number into a valid palette reference:%@AE@%%@NL@%
  6612.                 MJ% = clMap2Pal%(J%)%@NL@%
  6613. %@NL@%
  6614. %@AB@%                ' Calculate starting X location of first point and set%@AE@%%@NL@%
  6615. %@AB@%                ' last value to missing (since this is the first value in the%@AE@%%@NL@%
  6616. %@AB@%                ' series the last value wasn't there):%@AE@%%@NL@%
  6617.                 StartLoc = GE.XAxis.ScaleMin + GE.XAxis.TicInterval / 2%@NL@%
  6618.                 LastMissing% = cYes%@NL@%
  6619. %@NL@%
  6620.                 FOR i% = 1 TO GP.NVals%@NL@%
  6621. %@NL@%
  6622. %@AB@%                        ' Get a value from the data array:%@AE@%%@NL@%
  6623.                         V = V1(i%, J%)%@NL@%
  6624. %@NL@%
  6625. %@AB@%                        ' If the value is missing, set the LastMissing flag to Yes and%@AE@%%@NL@%
  6626. %@AB@%                        ' go to the next value:%@AE@%%@NL@%
  6627.                         IF V = cMissingValue THEN%@NL@%
  6628.                                 LastMissing% = cYes%@NL@%
  6629. %@NL@%
  6630. %@AB@%                        ' If the value is not missing then try to chart it:%@AE@%%@NL@%
  6631.                         ELSE%@NL@%
  6632. %@NL@%
  6633. %@AB@%                                ' Scale the value (and convert it to a log if this is a%@AE@%%@NL@%
  6634. %@AB@%                                ' Log axis):%@AE@%%@NL@%
  6635.                                 IF GE.YAxis.AutoScale = cYes THEN V = V / GE.YAxis.ScaleFactor%@NL@%
  6636. %@NL@%
  6637. %@AB@%                                ' If the style dictates lines and the last point wasn't%@AE@%%@NL@%
  6638. %@AB@%                                ' missing then draw a line between the last point and this one:%@AE@%%@NL@%
  6639.                                 IF GE.ChartStyle = cLines AND LastMissing% <> cYes THEN%@NL@%
  6640.                                         LINE -(StartLoc, V), PaletteC%(MJ%), , PaletteS%(MJ%)%@NL@%
  6641.                                 END IF%@NL@%
  6642. %@NL@%
  6643. %@AB@%                                ' Position and print character:%@AE@%%@NL@%
  6644.                                 CX% = PMAP(StartLoc, 0) - GetGTextLen(CHR$(PaletteCh%(MJ%))) / 2%@NL@%
  6645.                                 CY% = PMAP(V, 1) - GFI.Ascent / 2%@NL@%
  6646.                                 clSetCharColor MJ%%@NL@%
  6647.                                 clHPrint CX%, CY%, CHR$(PaletteCh%(MJ%))%@NL@%
  6648. %@NL@%
  6649.                                 PSET (StartLoc, V), POINT(StartLoc, V)%@NL@%
  6650. %@NL@%
  6651.                                 LastMissing% = cNo%@NL@%
  6652.                         END IF%@NL@%
  6653. %@NL@%
  6654. %@AB@%                        ' Move to next category position:%@AE@%%@NL@%
  6655.                         StartLoc = StartLoc + GE.XAxis.TicInterval%@NL@%
  6656.                 NEXT i%%@NL@%
  6657.         NEXT J%%@NL@%
  6658. %@NL@%
  6659. END SUB%@NL@%
  6660. %@NL@%
  6661. %@AB@%'=== clDrawPieData - Draws data part of a pie chart%@AE@%%@NL@%
  6662. %@AB@%'%@AE@%%@NL@%
  6663. %@AB@%'  Arguments:%@AE@%%@NL@%
  6664. %@AB@%'     Value(1)    -  One-dimensional array of data values%@AE@%%@NL@%
  6665. %@AB@%'%@AE@%%@NL@%
  6666. %@AB@%'     Expl(1)     -  One-dimensional array of explode flags (1=explode, 0=no)%@AE@%%@NL@%
  6667. %@AB@%'%@AE@%%@NL@%
  6668. %@AB@%'     N%          -  The number of data values to plot%@AE@%%@NL@%
  6669. %@AB@%'  Return Values:%@AE@%%@NL@%
  6670. %@AB@%'     None%@AE@%%@NL@%
  6671. %@AB@%'%@AE@%%@NL@%
  6672. %@AB@%'=================================================================%@AE@%%@NL@%
  6673. SUB clDrawPieData (value() AS SINGLE, Expl() AS INTEGER, N AS INTEGER)%@NL@%
  6674. SHARED GE AS ChartEnvironment%@NL@%
  6675. SHARED GP AS GlobalParams%@NL@%
  6676. SHARED GFI AS FontInfo%@NL@%
  6677. SHARED PaletteC%(), PaletteP$()%@NL@%
  6678. %@NL@%
  6679. %@AB@%        ' Set the font to use for percent labels:%@AE@%%@NL@%
  6680.         clSetChartFont GE.DataFont%@NL@%
  6681. %@NL@%
  6682. %@AB@%        ' Set up some reference variables:%@AE@%%@NL@%
  6683.         Pi2 = 2 * cPiVal                  ' 2*PI for radians conversions%@NL@%
  6684.         MinAngle = Pi2 / 120              ' Smallest wedge to try to paint%@NL@%
  6685.         A1 = -.0000001                    ' Starting and ending angle (set%@NL@%
  6686.         A2 = A1                           ' to very small negative to get%@NL@%
  6687. %@AB@%                                                                                                 ' radius line for first wedge)%@AE@%%@NL@%
  6688. %@NL@%
  6689. %@AB@%        ' Size the pie.%@AE@%%@NL@%
  6690. %@AB@%        ' Choose the point in the middle of the data window for the pie center:%@AE@%%@NL@%
  6691.         WINDOW (0, 0)-(1, 1)%@NL@%
  6692.         X = PMAP(.5, 0)                  ' Distance: left to center%@NL@%
  6693.         Y = PMAP(.5, 1)                  ' Distance: bottom to center%@NL@%
  6694.         WINDOW                           ' Now, use physical coordinates (pixels)%@NL@%
  6695.         GTextWindow 0, 0, 0, 0, cFalse%@NL@%
  6696. %@NL@%
  6697. %@AB@%        ' Adjust radii for percent labels if required:%@AE@%%@NL@%
  6698.         clSetChartFont GE.DataFont%@NL@%
  6699.         IF GE.ChartStyle = cPercent THEN%@NL@%
  6700.                 RadiusX = (X - 6 * GFI.AvgWidth) * GP.Aspect%@NL@%
  6701.                 RadiusY = Y - 2 * GFI.PixHeight%@NL@%
  6702.         ELSE%@NL@%
  6703.                 RadiusX = X * GP.Aspect%@NL@%
  6704.                 RadiusY = Y%@NL@%
  6705.         END IF%@NL@%
  6706. %@NL@%
  6707. %@AB@%        ' Pick the smallest radius (adjusted for screen aspect) then reduce%@AE@%%@NL@%
  6708. %@AB@%        ' it by 10% so the pie isn't too close to the window border:%@AE@%%@NL@%
  6709.         IF RadiusX < RadiusY THEN%@NL@%
  6710.                 Radius = RadiusX%@NL@%
  6711.         ELSE%@NL@%
  6712.                 Radius = RadiusY%@NL@%
  6713.         END IF%@NL@%
  6714.         Radius = (.9 * Radius) / GP.Aspect%@NL@%
  6715. %@NL@%
  6716. %@AB@%        ' If radius is too small then error:%@AE@%%@NL@%
  6717.         IF Radius <= 0 THEN%@NL@%
  6718.                 clSetError cBadDataWindow%@NL@%
  6719.                 EXIT SUB%@NL@%
  6720.         END IF%@NL@%
  6721. %@NL@%
  6722. %@AB@%        ' Find the sum of the data values (use double precision Sum variable to%@AE@%%@NL@%
  6723. %@AB@%        ' protect against overflow if summing large data values):%@AE@%%@NL@%
  6724.         Sum# = 0%@NL@%
  6725.         FOR i% = 1 TO GP.NSeries%@NL@%
  6726.                 IF value(i%) > 0 THEN Sum# = Sum# + value(i%)%@NL@%
  6727.         NEXT i%%@NL@%
  6728. %@NL@%
  6729. %@AB@%        ' Loop through drawing and painting the wedges:%@AE@%%@NL@%
  6730.         FOR i% = 1 TO N%@NL@%
  6731. %@NL@%
  6732. %@AB@%                ' Map I% to a valid palette reference:%@AE@%%@NL@%
  6733.                 MappedI% = clMap2Pal(i%)%@NL@%
  6734. %@NL@%
  6735. %@AB@%                ' Draw wedges for positive values only:%@AE@%%@NL@%
  6736.                 IF value(i%) > 0 THEN%@NL@%
  6737. %@NL@%
  6738. %@AB@%                        ' Calculate wedge percent and wedge ending angle:%@AE@%%@NL@%
  6739.                         Percent = value(i%) / Sum#%@NL@%
  6740.                         A2 = A1 - Percent * Pi2%@NL@%
  6741. %@NL@%
  6742. %@AB@%                        ' This locates the angle through the center of the pie wedge and%@AE@%%@NL@%
  6743. %@AB@%                        ' calculates X and Y components of the vector headed in that%@AE@%%@NL@%
  6744. %@AB@%                        ' direction:%@AE@%%@NL@%
  6745.                         Bisect = (A1 + A2) / 2%@NL@%
  6746.                         BisectX = Radius * COS(Bisect)%@NL@%
  6747.                         BisectY = Radius * SIN(Bisect) * GP.Aspect%@NL@%
  6748. %@NL@%
  6749. %@AB@%                        ' If the piece is exploded then offset it 1/10th of a radius%@AE@%%@NL@%
  6750. %@AB@%                        ' along the bisecting angle calculated above:%@AE@%%@NL@%
  6751.                         IF Expl(i%) <> 0 THEN%@NL@%
  6752.                                 CX = X + .1 * BisectX%@NL@%
  6753.                                 CY = Y + .1 * BisectY%@NL@%
  6754.                         ELSE%@NL@%
  6755.                                 CX = X%@NL@%
  6756.                                 CY = Y%@NL@%
  6757.                         END IF%@NL@%
  6758. %@NL@%
  6759. %@AB@%                        ' If the angle is large enough, paint the wedge (if wedges of%@AE@%%@NL@%
  6760. %@AB@%                        ' smaller angles are painted, the "paint" will sometimes spill out):%@AE@%%@NL@%
  6761.                         IF (A1 - A2) > MinAngle THEN%@NL@%
  6762.                                 PX = CX + .8 * BisectX%@NL@%
  6763.                                 PY = CY + .8 * BisectY%@NL@%
  6764. %@NL@%
  6765. %@AB@%                                ' Outline the wedge in color 1 and paint it black.%@AE@%%@NL@%
  6766.                                 CIRCLE (CX, CY), Radius, 1, A1, A2, GP.Aspect%@NL@%
  6767.                                 PAINT (PX, PY), 0, 1%@NL@%
  6768. %@AB@%                                ' Paint with the appropriate pattern:%@AE@%%@NL@%
  6769.                                 PAINT (PX, PY), PaletteP$(MappedI%), 1%@NL@%
  6770.                         END IF%@NL@%
  6771. %@AB@%                        ' draw the wedge in the correct color:%@AE@%%@NL@%
  6772.                         CIRCLE (CX, CY), Radius, PaletteC%(MappedI%), A1, A2, GP.Aspect%@NL@%
  6773. %@NL@%
  6774. %@AB@%                        ' Label pie wedge with percent if appropriate:%@AE@%%@NL@%
  6775.                         IF GE.ChartStyle = cPercent THEN%@NL@%
  6776.                                 Label$ = clVal2Str$(Percent * 100, 1, 1) + "%"%@NL@%
  6777.                                 LabelX% = CX + BisectX + (GFI.AvgWidth * COS(Bisect))%@NL@%
  6778.                                 LabelY% = CY + BisectY + (GFI.AvgWidth * SIN(Bisect)) * GP.Aspect%@NL@%
  6779. %@NL@%
  6780. %@AB@%                                ' Adjust label location for the quadrant:%@AE@%%@NL@%
  6781.                                 Quadrant% = FIX((ABS(Bisect / Pi2)) * 4)%@NL@%
  6782.                                 IF Quadrant% = 0 OR Quadrant% = 1 THEN%@NL@%
  6783.                                         LabelY% = LabelY% - GFI.Ascent%@NL@%
  6784.                                 END IF%@NL@%
  6785.                                 IF Quadrant% = 1 OR Quadrant% = 2 THEN%@NL@%
  6786.                                         LabelX% = LabelX% - GetGTextLen(Label$)%@NL@%
  6787.                                 END IF%@NL@%
  6788. %@NL@%
  6789.                                 clSetCharColor GE.Legend.TextColor%@NL@%
  6790.                                 clHPrint LabelX%, LabelY%, Label$%@NL@%
  6791.                         END IF%@NL@%
  6792.                 END IF%@NL@%
  6793. %@NL@%
  6794. %@AB@%                ' Set the beginning of next wedge to the end of this one:%@AE@%%@NL@%
  6795.                 A1 = A2%@NL@%
  6796. %@NL@%
  6797.         NEXT i%%@NL@%
  6798. %@NL@%
  6799. END SUB%@NL@%
  6800. %@NL@%
  6801. %@AB@%'=== clDrawScatterData - Draws data portion of Scatter chart%@AE@%%@NL@%
  6802. %@AB@%'%@AE@%%@NL@%
  6803. %@AB@%'  Arguments:%@AE@%%@NL@%
  6804. %@AB@%'     None%@AE@%%@NL@%
  6805. %@AB@%'%@AE@%%@NL@%
  6806. %@AB@%'  Return Values:%@AE@%%@NL@%
  6807. %@AB@%'     None%@AE@%%@NL@%
  6808. %@AB@%'%@AE@%%@NL@%
  6809. %@AB@%'=================================================================%@AE@%%@NL@%
  6810. SUB clDrawScatterData%@NL@%
  6811. SHARED GE AS ChartEnvironment, GP AS GlobalParams%@NL@%
  6812. SHARED PaletteC%(), PaletteS%(), PaletteCh%()%@NL@%
  6813. SHARED GFI AS FontInfo%@NL@%
  6814. SHARED V1(), V2()%@NL@%
  6815. %@NL@%
  6816. %@AB@%        ' Select the chart font and make text output horizontal:%@AE@%%@NL@%
  6817.         clSetChartFont GE.DataFont%@NL@%
  6818.         SetGTextDir 0%@NL@%
  6819. %@NL@%
  6820. %@AB@%        ' Now, loop through all the points charting them:%@AE@%%@NL@%
  6821.         FOR Series% = 1 TO GP.NSeries%@NL@%
  6822. %@NL@%
  6823. %@AB@%                ' Set LastMissing flag to Yes for first point in series:%@AE@%%@NL@%
  6824.                 LastMissing% = cYes%@NL@%
  6825.                 MS% = clMap2Pal%(Series%)%@NL@%
  6826. %@NL@%
  6827. %@AB@%                ' Loop through all the points, charting them:%@AE@%%@NL@%
  6828.                 FOR DataPoint% = 1 TO GP.NVals%@NL@%
  6829. %@NL@%
  6830. %@AB@%                        ' Get the X-value and Y-values from the data arrays:%@AE@%%@NL@%
  6831.                         VX = V1(DataPoint%, Series%)%@NL@%
  6832.                         VY = V2(DataPoint%, Series%)%@NL@%
  6833. %@NL@%
  6834. %@AB@%                        ' If either of the values to chart is missing set LastMissing%@AE@%%@NL@%
  6835. %@AB@%                        ' flag to Yes to indicate a missing point and go to the next point:%@AE@%%@NL@%
  6836.                         IF VX = cMissingValue OR VY = cMissingValue THEN%@NL@%
  6837.                                 LastMissing% = cYes%@NL@%
  6838. %@NL@%
  6839.                         ELSE%@NL@%
  6840. %@NL@%
  6841. %@AB@%                                ' Otherwise, scale the X and Y values if AutoScale is set for%@AE@%%@NL@%
  6842. %@AB@%                                ' their respective axes:%@AE@%%@NL@%
  6843.                                 IF GE.XAxis.AutoScale = cYes THEN VX = VX / GE.XAxis.ScaleFactor%@NL@%
  6844.                                 IF GE.YAxis.AutoScale = cYes THEN VY = VY / GE.YAxis.ScaleFactor%@NL@%
  6845. %@NL@%
  6846. %@AB@%                                ' If this is a lined chart and the last point wasn't missing,%@AE@%%@NL@%
  6847. %@AB@%                                ' then draw a line from last point to the current point:%@AE@%%@NL@%
  6848.                                 IF GE.ChartStyle = cLines AND LastMissing% <> cYes THEN%@NL@%
  6849.                                         LINE -(VX, VY), PaletteC%(MS%), , PaletteS%(MS%)%@NL@%
  6850.                                 END IF%@NL@%
  6851. %@NL@%
  6852. %@AB@%                                ' In any case draw the plot character.  Start by getting the%@AE@%%@NL@%
  6853. %@AB@%                                ' screen coordinates of the character relative to the point%@AE@%%@NL@%
  6854. %@AB@%                                ' just charted:%@AE@%%@NL@%
  6855.                                 CX% = PMAP(VX, 0) - GetGTextLen(CHR$(PaletteCh%(MS%))) / 2%@NL@%
  6856.                                 CY% = PMAP(VY, 1) - GFI.Ascent / 2%@NL@%
  6857. %@NL@%
  6858. %@AB@%                                ' Now, set the character color and print it:%@AE@%%@NL@%
  6859.                                 clSetCharColor MS%%@NL@%
  6860.                                 clHPrint CX%, CY%, CHR$(PaletteCh%(MS%))%@NL@%
  6861. %@NL@%
  6862. %@AB@%                                ' Finally, reset the graphics cursor, since printing the%@AE@%%@NL@%
  6863. %@AB@%                                ' character changed it:%@AE@%%@NL@%
  6864.                                 PSET (VX, VY), POINT(VX, VY)%@NL@%
  6865. %@NL@%
  6866.                                 LastMissing% = cNo%@NL@%
  6867.                         END IF%@NL@%
  6868. %@NL@%
  6869.                 NEXT DataPoint%%@NL@%
  6870.         NEXT Series%%@NL@%
  6871. END SUB%@NL@%
  6872. %@NL@%
  6873. %@AB@%'=== clDrawTitles - Draws the main and subtitles on a chart%@AE@%%@NL@%
  6874. %@AB@%'%@AE@%%@NL@%
  6875. %@AB@%'  Arguments:%@AE@%%@NL@%
  6876. %@AB@%'     None%@AE@%%@NL@%
  6877. %@AB@%'%@AE@%%@NL@%
  6878. %@AB@%'  Return Values:%@AE@%%@NL@%
  6879. %@AB@%'     None%@AE@%%@NL@%
  6880. %@AB@%'%@AE@%%@NL@%
  6881. %@AB@%'=================================================================%@AE@%%@NL@%
  6882. SUB clDrawTitles%@NL@%
  6883. SHARED GE AS ChartEnvironment%@NL@%
  6884. SHARED TTitleLayout AS TitleLayout%@NL@%
  6885. %@NL@%
  6886. %@AB@%        ' Bottom of main title line is 1-1/2 character heights from the%@AE@%%@NL@%
  6887. %@AB@%        ' top of the chart window:%@AE@%%@NL@%
  6888.         YPos% = TTitleLayout.Top%@NL@%
  6889.         clPrintTitle GE.MainTitle, YPos%%@NL@%
  6890. %@NL@%
  6891. %@AB@%        ' Add 1.5 * character height to y position for subtitle line position:%@AE@%%@NL@%
  6892.         YPos% = YPos% + TTitleLayout.TitleOne + TTitleLayout.Middle%@NL@%
  6893.         clPrintTitle GE.SubTitle, YPos%%@NL@%
  6894. %@NL@%
  6895. END SUB%@NL@%
  6896. %@NL@%
  6897. %@AB@%'=== clFilter - Filters input data into dynamic working data array%@AE@%%@NL@%
  6898. %@AB@%'%@AE@%%@NL@%
  6899. %@AB@%'  Arguments:%@AE@%%@NL@%
  6900. %@AB@%'     Axis     -  An AxisType variable%@AE@%%@NL@%
  6901. %@AB@%'%@AE@%%@NL@%
  6902. %@AB@%'     AxisMode%-  Mode for this axis%@AE@%%@NL@%
  6903. %@AB@%'%@AE@%%@NL@%
  6904. %@AB@%'     D1(1)    -  One-dimensional array of input data%@AE@%%@NL@%
  6905. %@AB@%'%@AE@%%@NL@%
  6906. %@AB@%'     D2(2)    -  Two-dimensional array for filtered data%@AE@%%@NL@%
  6907. %@AB@%'%@AE@%%@NL@%
  6908. %@AB@%'     N%       -  The number of values to transfer%@AE@%%@NL@%
  6909. %@AB@%'%@AE@%%@NL@%
  6910. %@AB@%'  Return Values:%@AE@%%@NL@%
  6911. %@AB@%'     Alters values in D2()%@AE@%%@NL@%
  6912. %@AB@%'%@AE@%%@NL@%
  6913. %@AB@%'=================================================================%@AE@%%@NL@%
  6914. SUB clFilter (Axis AS AxisType, AxisMode%, D1(), D2(), N%)%@NL@%
  6915. %@NL@%
  6916. %@AB@%        ' If the axis is a category one then exit:%@AE@%%@NL@%
  6917.         IF AxisMode% = cCategory THEN EXIT SUB%@NL@%
  6918. %@NL@%
  6919. %@AB@%        ' Transfer the data from the input data array to the working data%@AE@%%@NL@%
  6920. %@AB@%        ' array:%@AE@%%@NL@%
  6921.         FOR i% = 1 TO N%%@NL@%
  6922.                 D2(i%, 1) = D1(i%)%@NL@%
  6923.         NEXT i%%@NL@%
  6924. %@NL@%
  6925. %@AB@%        ' Call FilterMS to go through the data again scaling it and taking%@AE@%%@NL@%
  6926. %@AB@%        ' logs depending on the settings for this axis:%@AE@%%@NL@%
  6927.         clFilterMS Axis, AxisMode%, D2(), D2(), N%, 1, 1%@NL@%
  6928. %@NL@%
  6929. END SUB%@NL@%
  6930. %@NL@%
  6931. %@AB@%'=== clFilterMS - Filters two-dimensional input data into the dynamic working%@AE@%%@NL@%
  6932. %@AB@%'               data array%@AE@%%@NL@%
  6933. %@AB@%'%@AE@%%@NL@%
  6934. %@AB@%'  Arguments:%@AE@%%@NL@%
  6935. %@AB@%'     Axis     -  An AxisType variable%@AE@%%@NL@%
  6936. %@AB@%'%@AE@%%@NL@%
  6937. %@AB@%'     AxisMode%-  Axis mode for the axis%@AE@%%@NL@%
  6938. %@AB@%'%@AE@%%@NL@%
  6939. %@AB@%'     D1(2)    -  Two-dimensional array of input data%@AE@%%@NL@%
  6940. %@AB@%'%@AE@%%@NL@%
  6941. %@AB@%'     D2(2)    -  Two-dimensional array for filtered data%@AE@%%@NL@%
  6942. %@AB@%'%@AE@%%@NL@%
  6943. %@AB@%'     N%       -  The number of values to transfer%@AE@%%@NL@%
  6944. %@AB@%'%@AE@%%@NL@%
  6945. %@AB@%'     First%   -  First data series to filter%@AE@%%@NL@%
  6946. %@AB@%'%@AE@%%@NL@%
  6947. %@AB@%'     Last%    -  Last data series to filter%@AE@%%@NL@%
  6948. %@AB@%'%@AE@%%@NL@%
  6949. %@AB@%'  Return Values:%@AE@%%@NL@%
  6950. %@AB@%'     Alters values in D2()%@AE@%%@NL@%
  6951. %@AB@%'%@AE@%%@NL@%
  6952. %@AB@%'=================================================================%@AE@%%@NL@%
  6953. SUB clFilterMS (Axis AS AxisType, AxisMode%, D1(), D2(), N%, First%, Last%)%@NL@%
  6954. %@NL@%
  6955. %@AB@%        ' If the axis is a category axis then exit:%@AE@%%@NL@%
  6956.         IF AxisMode% = cCategory THEN EXIT SUB%@NL@%
  6957. %@NL@%
  6958. %@AB@%        ' If this isn't an autoscale axis, use the scale factor from the%@AE@%%@NL@%
  6959. %@AB@%        ' environment.  If it is an autoscale axis don't scale at all now%@AE@%%@NL@%
  6960. %@AB@%        ' it will be done when the data is drawn on the screen:%@AE@%%@NL@%
  6961.         IF Axis.AutoScale = cNo THEN%@NL@%
  6962.                 ScaleFactor = Axis.ScaleFactor%@NL@%
  6963.         ELSE%@NL@%
  6964.                 ScaleFactor = 1%@NL@%
  6965.         END IF%@NL@%
  6966. %@NL@%
  6967. %@AB@%        ' If this a log axis calculate the log base:%@AE@%%@NL@%
  6968.         IF AxisMode% = cLog THEN LogRef = LOG(Axis.LogBase)%@NL@%
  6969. %@NL@%
  6970. %@AB@%        ' Loop through the data series:%@AE@%%@NL@%
  6971.         FOR J% = First% TO Last%%@NL@%
  6972. %@NL@%
  6973. %@AB@%                ' Loop through the values within the series:%@AE@%%@NL@%
  6974.                 FOR i% = 1 TO N%%@NL@%
  6975. %@NL@%
  6976. %@AB@%                        ' Get a data value and if it isn't missing, then scale it:%@AE@%%@NL@%
  6977.                         V = D1(i%, J%)%@NL@%
  6978.                         IF V <> cMissingValue THEN V = V / ScaleFactor%@NL@%
  6979. %@NL@%
  6980. %@AB@%                        ' If the axis is a log axis, then if the value is greater than%@AE@%%@NL@%
  6981. %@AB@%                        ' it is safe to take it's log.  Otherwise, set the data value to%@AE@%%@NL@%
  6982. %@AB@%                        ' missing:%@AE@%%@NL@%
  6983.                         IF Axis.RangeType = cLog THEN%@NL@%
  6984.                                  IF V > 0 THEN%@NL@%
  6985.                                         V = LOG(V) / LogRef%@NL@%
  6986.                                 ELSE%@NL@%
  6987.                                         V = cMissingValue%@NL@%
  6988.                                 END IF%@NL@%
  6989.                         END IF%@NL@%
  6990. %@NL@%
  6991. %@AB@%                        ' Place the value in the output data array:%@AE@%%@NL@%
  6992.                         D2(i%, J% - First% + 1) = V%@NL@%
  6993. %@NL@%
  6994.                 NEXT i%%@NL@%
  6995. %@NL@%
  6996.         NEXT J%%@NL@%
  6997. %@NL@%
  6998. END SUB%@NL@%
  6999. %@NL@%
  7000. %@AB@%'=== clFlagSystem - Sets GP.SysFlag to cYes%@AE@%%@NL@%
  7001. %@AB@%'%@AE@%%@NL@%
  7002. %@AB@%'  Arguments:%@AE@%%@NL@%
  7003. %@AB@%'     None%@AE@%%@NL@%
  7004. %@AB@%'%@AE@%%@NL@%
  7005. %@AB@%'  Return Values:%@AE@%%@NL@%
  7006. %@AB@%'     Alters the value of GP.SysFlag%@AE@%%@NL@%
  7007. %@AB@%'%@AE@%%@NL@%
  7008. %@AB@%'=================================================================%@AE@%%@NL@%
  7009. SUB clFlagSystem%@NL@%
  7010. SHARED GP AS GlobalParams%@NL@%
  7011. %@NL@%
  7012.         GP.SysFlag = cYes%@NL@%
  7013. %@NL@%
  7014. END SUB%@NL@%
  7015. %@NL@%
  7016. %@AB@%'=== clFormatTics - Figures out tic label format and TicDecimals.%@AE@%%@NL@%
  7017. %@AB@%'%@AE@%%@NL@%
  7018. %@AB@%'  Arguments:%@AE@%%@NL@%
  7019. %@AB@%'     Axis     -  AxisType variable for which to format tics.%@AE@%%@NL@%
  7020. %@AB@%'%@AE@%%@NL@%
  7021. %@AB@%'  Return Values:%@AE@%%@NL@%
  7022. %@AB@%'     The TicFormat and Decimals elements may be changed for an axis%@AE@%%@NL@%
  7023. %@AB@%'     if AutoTic is cYes.%@AE@%%@NL@%
  7024. %@AB@%'%@AE@%%@NL@%
  7025. %@AB@%'=================================================================%@AE@%%@NL@%
  7026. SUB clFormatTics (Axis AS AxisType)%@NL@%
  7027. %@NL@%
  7028. %@AB@%        ' If AutoScale isn't Yes then exit%@AE@%%@NL@%
  7029.         IF Axis.AutoScale <> cYes THEN EXIT SUB%@NL@%
  7030. %@NL@%
  7031. %@AB@%        ' If the size of the largest value is bigger than seven decimal%@AE@%%@NL@%
  7032. %@AB@%        ' places then set TicFormat to exponential.  Otherwise, set it%@AE@%%@NL@%
  7033. %@AB@%        ' to normal:%@AE@%%@NL@%
  7034.         IF ABS(Axis.ScaleMin) >= 10 ^ 8 OR ABS(Axis.ScaleMax) >= 10 ^ 8 THEN%@NL@%
  7035.                 Axis.TicFormat = cExpFormat%@NL@%
  7036.         ELSE%@NL@%
  7037.                 Axis.TicFormat = cNormFormat%@NL@%
  7038.         END IF%@NL@%
  7039. %@NL@%
  7040. %@AB@%        ' Pick the largest of the scale max and min (in absolute value) and%@AE@%%@NL@%
  7041. %@AB@%        ' use that to decide how many decimals to use when displaying the tic%@AE@%%@NL@%
  7042. %@AB@%        ' labels:%@AE@%%@NL@%
  7043.         Range = ABS(Axis.ScaleMax)%@NL@%
  7044.         IF ABS(Axis.ScaleMin) > Range THEN Range = ABS(Axis.ScaleMin)%@NL@%
  7045.         IF Range < 10 THEN%@NL@%
  7046.                 TicResolution = -INT(-ABS(LOG(Range) / LOG(10!))) + 1%@NL@%
  7047.                 IF TicResolution > 9 THEN TicResolution = 9%@NL@%
  7048.                 Axis.TicDecimals = TicResolution%@NL@%
  7049.         ELSE%@NL@%
  7050.                 Axis.TicDecimals = 0%@NL@%
  7051.         END IF%@NL@%
  7052. %@NL@%
  7053. END SUB%@NL@%
  7054. %@NL@%
  7055. %@AB@%'=== clGetStyle - Returns a predefined line-style definition%@AE@%%@NL@%
  7056. %@AB@%'%@AE@%%@NL@%
  7057. %@AB@%'  Arguments:%@AE@%%@NL@%
  7058. %@AB@%'     StyleNum%   -  A number identifying the entry to return%@AE@%%@NL@%
  7059. %@AB@%'%@AE@%%@NL@%
  7060. %@AB@%'  Return Values:%@AE@%%@NL@%
  7061. %@AB@%'     Returns the line-style for the specified style number%@AE@%%@NL@%
  7062. %@AB@%'%@AE@%%@NL@%
  7063. %@AB@%'=================================================================%@AE@%%@NL@%
  7064. FUNCTION clGetStyle% (StyleNum%)%@NL@%
  7065. %@NL@%
  7066.         SELECT CASE StyleNum%%@NL@%
  7067.                 CASE 1: Style% = &HFFFF%@NL@%
  7068.                 CASE 2: Style% = &HF0F0%@NL@%
  7069.                 CASE 3: Style% = &HF060%@NL@%
  7070.                 CASE 4: Style% = &HCCCC%@NL@%
  7071.                 CASE 5: Style% = &HC8C8%@NL@%
  7072.                 CASE 6: Style% = &HEEEE%@NL@%
  7073.                 CASE 7: Style% = &HEAEA%@NL@%
  7074.                 CASE 8: Style% = &HF6DE%@NL@%
  7075.                 CASE 9: Style% = &HF6F6%@NL@%
  7076.                 CASE 10: Style% = &HF56A%@NL@%
  7077.                 CASE 11: Style% = &HCECE%@NL@%
  7078.                 CASE 12: Style% = &HA8A8%@NL@%
  7079.                 CASE 13: Style% = &HAAAA%@NL@%
  7080.                 CASE 14: Style% = &HE4E4%@NL@%
  7081.                 CASE 15: Style% = &HC88C%@NL@%
  7082.         END SELECT%@NL@%
  7083.         clGetStyle% = Style%%@NL@%
  7084. %@NL@%
  7085. END FUNCTION%@NL@%
  7086. %@NL@%
  7087. %@AB@%'=== clHPrint - Prints text Horizontally on the screen%@AE@%%@NL@%
  7088. %@AB@%'%@AE@%%@NL@%
  7089. %@AB@%'  Arguments:%@AE@%%@NL@%
  7090. %@AB@%'     X     -  X position for the lower left of the first character to be%@AE@%%@NL@%
  7091. %@AB@%'              printed (in absolute screen coordinates)%@AE@%%@NL@%
  7092. %@AB@%'%@AE@%%@NL@%
  7093. %@AB@%'     Y     -  Y position for the lower left of the first character to be%@AE@%%@NL@%
  7094. %@AB@%'              printed (in absolute screen coordinates)%@AE@%%@NL@%
  7095. %@AB@%'%@AE@%%@NL@%
  7096. %@AB@%'     Txt$  -  Text to print%@AE@%%@NL@%
  7097. %@AB@%'%@AE@%%@NL@%
  7098. %@AB@%'  Return Values:%@AE@%%@NL@%
  7099. %@AB@%'     None%@AE@%%@NL@%
  7100. %@AB@%'%@AE@%%@NL@%
  7101. %@AB@%'=================================================================%@AE@%%@NL@%
  7102. SUB clHPrint (X%, Y%, Txt$)%@NL@%
  7103. %@NL@%
  7104. %@AB@%        ' Map the input coordinates relative to the current viewport:%@AE@%%@NL@%
  7105.         X = PMAP(X%, 2)%@NL@%
  7106.         Y = PMAP(Y%, 3)%@NL@%
  7107. %@NL@%
  7108. %@AB@%        ' Output the text horizontally:%@AE@%%@NL@%
  7109.         SetGTextDir 0%@NL@%
  7110.         TextLen% = OutGText(X, Y, Txt$)%@NL@%
  7111. %@NL@%
  7112. END SUB%@NL@%
  7113. %@NL@%
  7114. %@AB@%'=== clInitChart - Initializes the charting library.%@AE@%%@NL@%
  7115. %@AB@%'%@AE@%%@NL@%
  7116. %@AB@%'  Arguments:%@AE@%%@NL@%
  7117. %@AB@%'     None%@AE@%%@NL@%
  7118. %@AB@%'%@AE@%%@NL@%
  7119. %@AB@%'  Return Values:%@AE@%%@NL@%
  7120. %@AB@%'     None%@AE@%%@NL@%
  7121. %@AB@%'%@AE@%%@NL@%
  7122. %@AB@%'  Remarks:%@AE@%%@NL@%
  7123. %@AB@%'     This routine initializes some default data structures and is%@AE@%%@NL@%
  7124. %@AB@%'     called automatically by charting routines if the variable%@AE@%%@NL@%
  7125. %@AB@%'     GP.Initialized is cNo (or zero).%@AE@%%@NL@%
  7126. %@AB@%'%@AE@%%@NL@%
  7127. %@AB@%'=================================================================%@AE@%%@NL@%
  7128. SUB clInitChart%@NL@%
  7129. SHARED StdChars%(), GP AS GlobalParams%@NL@%
  7130. %@NL@%
  7131. %@AB@%        ' Clear any previous errors%@AE@%%@NL@%
  7132.         clClearError%@NL@%
  7133. %@NL@%
  7134.         ON ERROR GOTO UnexpectedErr%@NL@%
  7135. %@NL@%
  7136. %@AB@%        ' Initialize PaletteSet to no so palettes will be initialized properly%@AE@%%@NL@%
  7137. %@AB@%        ' when ChartScreen is called:%@AE@%%@NL@%
  7138.         GP.PaletteSet = cNo%@NL@%
  7139. %@NL@%
  7140. %@AB@%        ' Set up the list of plotting characters:%@AE@%%@NL@%
  7141.         PlotChars$ = "*ox=+/:&#@%![$^"%@NL@%
  7142.         StdChars%(0) = 0%@NL@%
  7143.         FOR i% = 1 TO cPalLen%@NL@%
  7144.                 StdChars%(i%) = ASC(MID$(PlotChars$, i%, 1))%@NL@%
  7145.         NEXT i%%@NL@%
  7146. %@NL@%
  7147. %@AB@%        ' Initialize standard structures for title, axis, window and legend:%@AE@%%@NL@%
  7148.         clInitStdStruc%@NL@%
  7149. %@NL@%
  7150.         GP.Initialized = cYes%@NL@%
  7151. %@NL@%
  7152. END SUB%@NL@%
  7153. %@NL@%
  7154. %@AB@%'=== clInitStdStruc - Initializes structures for standard titles, axes, etc.%@AE@%%@NL@%
  7155. %@AB@%'%@AE@%%@NL@%
  7156. %@AB@%'  Arguments:%@AE@%%@NL@%
  7157. %@AB@%'     None%@AE@%%@NL@%
  7158. %@AB@%'%@AE@%%@NL@%
  7159. %@AB@%'  Return Values:%@AE@%%@NL@%
  7160. %@AB@%'     None%@AE@%%@NL@%
  7161. %@AB@%'%@AE@%%@NL@%
  7162. %@AB@%'=================================================================%@AE@%%@NL@%
  7163. SUB clInitStdStruc%@NL@%
  7164. SHARED DAxis AS AxisType, DWindow AS RegionType%@NL@%
  7165. SHARED DLegend AS LegendType, DTitle AS TitleType%@NL@%
  7166. %@NL@%
  7167. %@AB@%' Set up default components of the default chart%@AE@%%@NL@%
  7168. %@AB@%' environment; start with default title:%@AE@%%@NL@%
  7169. %@NL@%
  7170. %@AB@%' Default title definition:%@AE@%%@NL@%
  7171. DTitle.Title = ""                ' Title text is blank%@NL@%
  7172. DTitle.TitleFont = 1             ' Title font is first one%@NL@%
  7173. DTitle.TitleColor = 1            ' Title color is white%@NL@%
  7174. DTitle.Justify = cCenter         ' Center justified%@NL@%
  7175. %@NL@%
  7176. %@AB@%' Default axis definition:%@AE@%%@NL@%
  7177. DAxis.grid = cNo                 ' No grid%@NL@%
  7178. DAxis.GridStyle = 1              ' Solid lines for grid%@NL@%
  7179. DAxis.AxisTitle = DTitle         ' Use above to initialize axis title%@NL@%
  7180. DAxis.AxisColor = 1              ' Axis color is white%@NL@%
  7181. DAxis.Labeled = cYes             ' Label and tic axis%@NL@%
  7182. DAxis.RangeType = cLinear        ' Linear axis%@NL@%
  7183. DAxis.LogBase = 10               ' Logs to base 10%@NL@%
  7184. DAxis.AutoScale = cYes           ' Automatically scale numbers if needed%@NL@%
  7185. DAxis.ScaleTitle = DTitle        ' Scale title%@NL@%
  7186. DAxis.TicFont = 1                ' Tic font is first one%@NL@%
  7187. DAxis.TicDecimals = 0            ' No decimals%@NL@%
  7188. %@NL@%
  7189. %@AB@%' Default window definition:%@AE@%%@NL@%
  7190. DWindow.Background = 0           ' Black background%@NL@%
  7191. DWindow.Border = cNo             ' Window will have no border%@NL@%
  7192. DWindow.BorderColor = 1          ' Make the borders white%@NL@%
  7193. DWindow.BorderStyle = 1          ' Solid-line borders%@NL@%
  7194. %@NL@%
  7195. %@AB@%' Default legend definition:%@AE@%%@NL@%
  7196. DLegend.Legend = cYes            ' Draw a legend if multi-series chart%@NL@%
  7197. DLegend.Place = cRight           ' On the right side%@NL@%
  7198. DLegend.TextColor = 1            ' Legend text is white on black%@NL@%
  7199. DLegend.TextFont = 1             ' Legend text font is first one%@NL@%
  7200. DLegend.AutoSize = cYes          ' Figure out size automatically%@NL@%
  7201. DLegend.LegendWindow = DWindow   ' Use the default window specification%@NL@%
  7202. %@NL@%
  7203. END SUB%@NL@%
  7204. %@NL@%
  7205. %@AB@%'=== clLabelXTics - Labels tic marks for X axis%@AE@%%@NL@%
  7206. %@AB@%'%@AE@%%@NL@%
  7207. %@AB@%'  Arguments:%@AE@%%@NL@%
  7208. %@AB@%'     Axis     -  An AxisType variable containing axis specification%@AE@%%@NL@%
  7209. %@AB@%'%@AE@%%@NL@%
  7210. %@AB@%'     Cat$(1)  -  One-dimensional array of category labels.  Ignored%@AE@%%@NL@%
  7211. %@AB@%'                 if axis not category axis%@AE@%%@NL@%
  7212. %@AB@%'%@AE@%%@NL@%
  7213. %@AB@%'     TicX     -  X coordinate of first tic mark%@AE@%%@NL@%
  7214. %@AB@%'%@AE@%%@NL@%
  7215. %@AB@%'     TicY     -  Y coordinate of tic tip (portion away from axis)%@AE@%%@NL@%
  7216. %@AB@%'%@AE@%%@NL@%
  7217. %@AB@%'     YBoundry% -  Y coordinate of bottom of tic labels%@AE@%%@NL@%
  7218. %@AB@%'%@AE@%%@NL@%
  7219. %@AB@%'  Return Values:%@AE@%%@NL@%
  7220. %@AB@%'     None%@AE@%%@NL@%
  7221. %@AB@%'%@AE@%%@NL@%
  7222. %@AB@%'=================================================================%@AE@%%@NL@%
  7223. SUB clLabelXTics (Axis AS AxisType, Cat$(), TicX, TicTotX%, TicY, YBoundry%)%@NL@%
  7224. SHARED GFI AS FontInfo%@NL@%
  7225. SHARED GP AS GlobalParams%@NL@%
  7226. SHARED GE AS ChartEnvironment%@NL@%
  7227. %@NL@%
  7228. %@AB@%        ' If this axis isn't supposed to be labeled then exit:%@AE@%%@NL@%
  7229.         IF Axis.Labeled <> cYes THEN EXIT SUB%@NL@%
  7230. %@NL@%
  7231. %@AB@%        ' Set the appropriate color, font, and orientation for tic labels:%@AE@%%@NL@%
  7232.         clSetCharColor Axis.AxisColor%@NL@%
  7233.         clSetChartFont Axis.TicFont%@NL@%
  7234.         SetGTextDir 0%@NL@%
  7235. %@NL@%
  7236. %@AB@%        ' The Y coordinate of the labels will be a constant .5 character%@AE@%%@NL@%
  7237. %@AB@%        ' heights below the end of the tic marks (TicY):%@AE@%%@NL@%
  7238.         Y% = PMAP(TicY, 1) + (GFI.Ascent - GFI.Leading) / 2%@NL@%
  7239.         IF GP.XStagger = cYes THEN%@NL@%
  7240.                 YDrop% = (3 * GFI.Ascent - GFI.Leading) / 2%@NL@%
  7241.         ELSE%@NL@%
  7242.                 YDrop% = 0%@NL@%
  7243.         END IF%@NL@%
  7244.         YBoundry% = Y% + YDrop% + GFI.PixHeight%@NL@%
  7245. %@NL@%
  7246. %@AB@%        ' Loop through and write labels%@AE@%%@NL@%
  7247.         TX = TicX%@NL@%
  7248.         CatNum% = 1%@NL@%
  7249.         Stagger% = cFalse%@NL@%
  7250.         FOR i% = 1 TO TicTotX%%@NL@%
  7251. %@NL@%
  7252. %@AB@%                ' The label depends on axis mode (category, value):%@AE@%%@NL@%
  7253.                 SELECT CASE GP.XMode%@NL@%
  7254.                         CASE cCategory: Txt$ = Cat$(CatNum%)%@NL@%
  7255.                         CASE ELSE:      Txt$ = clVal2Str$(TX, Axis.TicDecimals, Axis.TicFormat)%@NL@%
  7256.                 END SELECT%@NL@%
  7257.                 TxtLen% = GetGTextLen(Txt$)%@NL@%
  7258.                 IF GP.XMode = cCategory THEN%@NL@%
  7259.                         MaxLen% = 2 * (GE.DataWindow.X2 - GE.DataWindow.X1) / GP.NVals - GFI.AvgWidth%@NL@%
  7260.                         IF MaxLen% < 0 THEN MaxLen% = 0%@NL@%
  7261.                         DO UNTIL TxtLen% <= MaxLen%%@NL@%
  7262.                                 Txt$ = LEFT$(Txt$, LEN(Txt$) - 1)%@NL@%
  7263.                                 TxtLen% = GetGTextLen(Txt$)%@NL@%
  7264.                         LOOP%@NL@%
  7265.                 END IF%@NL@%
  7266. %@NL@%
  7267. %@AB@%                ' Center the label under the tic mark and print it:%@AE@%%@NL@%
  7268.                 X% = PMAP(TX, 0) - (TxtLen%) / 2%@NL@%
  7269. %@NL@%
  7270.                 IF Stagger% THEN%@NL@%
  7271.                         clHPrint X%, Y% + YDrop%, Txt$%@NL@%
  7272.                         Stagger% = cFalse%@NL@%
  7273.                 ELSE%@NL@%
  7274.                         clHPrint X%, Y%, Txt$%@NL@%
  7275.                         Stagger% = cTrue%@NL@%
  7276.                 END IF%@NL@%
  7277. %@NL@%
  7278. %@AB@%                ' Move to the next tic mark:%@AE@%%@NL@%
  7279.                 TX = TX + Axis.TicInterval%@NL@%
  7280.                 CatNum% = CatNum% + 1%@NL@%
  7281.         NEXT i%%@NL@%
  7282. %@NL@%
  7283. END SUB%@NL@%
  7284. %@NL@%
  7285. %@AB@%'=== clLabelYTics - Labels tic marks and draws Y axis title%@AE@%%@NL@%
  7286. %@AB@%'%@AE@%%@NL@%
  7287. %@AB@%'  Arguments:%@AE@%%@NL@%
  7288. %@AB@%'     Axis     -  An AxisType variable containing axis specification%@AE@%%@NL@%
  7289. %@AB@%'%@AE@%%@NL@%
  7290. %@AB@%'     Cat$(1)  -  One-dimensional array of category labels.  Ignored%@AE@%%@NL@%
  7291. %@AB@%'                 if axis not category axis%@AE@%%@NL@%
  7292. %@AB@%'%@AE@%%@NL@%
  7293. %@AB@%'     TicX     -  X coordinate of first tic's tip (away from axis)%@AE@%%@NL@%
  7294. %@AB@%'%@AE@%%@NL@%
  7295. %@AB@%'     TicY     -  Y coordinate of first tic%@AE@%%@NL@%
  7296. %@AB@%'%@AE@%%@NL@%
  7297. %@AB@%'  Return Values:%@AE@%%@NL@%
  7298. %@AB@%'     None%@AE@%%@NL@%
  7299. %@AB@%'%@AE@%%@NL@%
  7300. %@AB@%'=================================================================%@AE@%%@NL@%
  7301. SUB clLabelYTics (Axis AS AxisType, Cat$(), TicX, TicY, TicTotY%)%@NL@%
  7302. SHARED GFI AS FontInfo%@NL@%
  7303. SHARED GP AS GlobalParams%@NL@%
  7304. %@NL@%
  7305. %@AB@%        ' If axis isn't supposed to be labeled then exit:%@AE@%%@NL@%
  7306.         IF Axis.Labeled <> cYes THEN EXIT SUB%@NL@%
  7307. %@NL@%
  7308. %@AB@%        ' Set the appropriate color, font, and orientation for tic labels:%@AE@%%@NL@%
  7309.         clSetCharColor Axis.AxisColor%@NL@%
  7310.         clSetChartFont Axis.TicFont%@NL@%
  7311.         SetGTextDir 0%@NL@%
  7312. %@NL@%
  7313. %@AB@%        ' Loop through and write labels%@AE@%%@NL@%
  7314.         TY = TicY%@NL@%
  7315.         CatNum% = 1%@NL@%
  7316.         FOR i% = 1 TO TicTotY%%@NL@%
  7317. %@NL@%
  7318. %@AB@%                ' The label depends on axis mode (category, value):%@AE@%%@NL@%
  7319.                 SELECT CASE GP.YMode%@NL@%
  7320.                         CASE cCategory: Txt$ = Cat$(GP.NVals - CatNum% + 1)%@NL@%
  7321.                         CASE ELSE:      Txt$ = clVal2Str$(TY, Axis.TicDecimals, Axis.TicFormat)%@NL@%
  7322.                 END SELECT%@NL@%
  7323.                 TxtLen% = GetGTextLen(Txt$)%@NL@%
  7324. %@NL@%
  7325. %@AB@%                ' Space the label 1/2 character width to the left of the tic%@AE@%%@NL@%
  7326. %@AB@%                ' mark and center it vertically on the tic mark (round vertical%@AE@%%@NL@%
  7327. %@AB@%                ' location to the next highest integer):%@AE@%%@NL@%
  7328.                 X% = PMAP(TicX, 0) - TxtLen% - (.5 * GFI.MaxWidth)%@NL@%
  7329.                 Y% = -INT(-(PMAP(TY, 1) - (GFI.Ascent + GFI.Leading) / 2))%@NL@%
  7330. %@NL@%
  7331. %@AB@%                ' Print the label:%@AE@%%@NL@%
  7332.                 clHPrint X%, Y%, Txt$%@NL@%
  7333. %@NL@%
  7334. %@AB@%                ' Go to the next tic mark:%@AE@%%@NL@%
  7335.                 TY = TY + Axis.TicInterval%@NL@%
  7336.                 CatNum% = CatNum% + 1%@NL@%
  7337.         NEXT i%%@NL@%
  7338. %@NL@%
  7339. END SUB%@NL@%
  7340. %@NL@%
  7341. %@AB@%'=== clLayoutLegend - Calculates size of the legend%@AE@%%@NL@%
  7342. %@AB@%'%@AE@%%@NL@%
  7343. %@AB@%'  Arguments:%@AE@%%@NL@%
  7344. %@AB@%'     SeriesLabel$(1) - The labels used in the legend%@AE@%%@NL@%
  7345. %@AB@%'%@AE@%%@NL@%
  7346. %@AB@%'     First%   - The first series (label) to process%@AE@%%@NL@%
  7347. %@AB@%'%@AE@%%@NL@%
  7348. %@AB@%'     Last%    - The last series (label) to process%@AE@%%@NL@%
  7349. %@AB@%'%@AE@%%@NL@%
  7350. %@AB@%'  Return Values:%@AE@%%@NL@%
  7351. %@AB@%'     The coordinates in the legend window portion of Env are altered%@AE@%%@NL@%
  7352. %@AB@%'%@AE@%%@NL@%
  7353. %@AB@%'  Remarks:%@AE@%%@NL@%
  7354. %@AB@%'     Sizing the legend window requires finding out where it goes (right%@AE@%%@NL@%
  7355. %@AB@%'     or bottom) and determining how big the labels are and how big%@AE@%%@NL@%
  7356. %@AB@%'     the legend needs to be to hold them.%@AE@%%@NL@%
  7357. %@AB@%'%@AE@%%@NL@%
  7358. %@AB@%'=================================================================%@AE@%%@NL@%
  7359. SUB clLayoutLegend (SeriesLabel$(), First%, Last%)%@NL@%
  7360. SHARED GE AS ChartEnvironment, GP AS GlobalParams%@NL@%
  7361. SHARED GFI AS FontInfo%@NL@%
  7362. SHARED LLayout AS LegendLayout%@NL@%
  7363. SHARED TTitleLayout AS TitleLayout%@NL@%
  7364. DIM W AS RegionType%@NL@%
  7365. %@NL@%
  7366. %@AB@%        ' If "no legend" is specified, then exit:%@AE@%%@NL@%
  7367.         IF GE.Legend.Legend = cNo THEN EXIT SUB%@NL@%
  7368. %@NL@%
  7369. %@AB@%        ' This may be an auto legend or not, but, in either case we're%@AE@%%@NL@%
  7370. %@AB@%        ' going to need the following information:%@AE@%%@NL@%
  7371.         clSetChartFont GE.Legend.TextFont%@NL@%
  7372. %@NL@%
  7373.         LLayout.SymbolSize = GFI.Ascent - GFI.Leading - 1%@NL@%
  7374.         LLayout.HorizBorder = GFI.Ascent%@NL@%
  7375.         LLayout.VertBorder = GFI.AvgWidth%@NL@%
  7376.         LLayout.RowSpacing = 1.75 * (LLayout.SymbolSize + 1)%@NL@%
  7377.         LLayout.LabelOffset = LLayout.SymbolSize / GP.Aspect + GFI.AvgWidth%@NL@%
  7378. %@NL@%
  7379. %@AB@%        'RowLeading% = LLayout.RowSpacing - LLayout.SymbolSize%@AE@%%@NL@%
  7380.         RowLeading% = .75 * LLayout.SymbolSize + 1.75%@NL@%
  7381. %@NL@%
  7382.         ColWid% = clMaxStrLen(SeriesLabel$(), First%, Last%) + LLayout.LabelOffset%@NL@%
  7383.         LLayout.ColSpacing = ColWid% + GFI.AvgWidth%@NL@%
  7384. %@NL@%
  7385. %@AB@%        ' If this isn't an autosize legend:%@AE@%%@NL@%
  7386.         IF GE.Legend.AutoSize = cNo THEN%@NL@%
  7387. %@NL@%
  7388. %@AB@%                ' Check the legend coordinates supplied by the user to make%@AE@%%@NL@%
  7389. %@AB@%                ' sure that they are valid.  If they are, exit:%@AE@%%@NL@%
  7390.                 W = GE.Legend.LegendWindow%@NL@%
  7391.                 LWid% = W.X2 - W.X1%@NL@%
  7392.                 LHgt% = W.Y2 - W.Y1%@NL@%
  7393.                 IF LWid% > 0 AND LHgt% > 0 THEN%@NL@%
  7394. %@NL@%
  7395. %@AB@%                        ' Calculate the number of columns and rows of labels that will%@AE@%%@NL@%
  7396. %@AB@%                        ' fit in the legend:%@AE@%%@NL@%
  7397.                         NumCol% = INT((LWid% - LLayout.VertBorder) / (LLayout.ColSpacing))%@NL@%
  7398.                         IF NumCol% <= 0 THEN NumCol% = 1%@NL@%
  7399.                         IF NumCol% > GP.NSeries THEN NumCol% = GP.NSeries%@NL@%
  7400.                         NumRow% = -INT(-GP.NSeries / NumCol%)%@NL@%
  7401.                         LLayout.NumRow = NumRow%%@NL@%
  7402.                         LLayout.NumCol = NumCol%%@NL@%
  7403. %@NL@%
  7404. %@AB@%                        ' Re-calculate the column and row spacing:%@AE@%%@NL@%
  7405.                         LLayout.ColSpacing = INT((LWid% - LLayout.VertBorder) / NumCol%)%@NL@%
  7406.                         LLayout.RowSpacing = INT((LHgt% - 2 * LLayout.HorizBorder + RowLeading%) / NumRow%)%@NL@%
  7407. %@NL@%
  7408.                         EXIT SUB%@NL@%
  7409. %@NL@%
  7410. %@AB@%                ' If invalid legend coordinates are discovered set an error and%@AE@%%@NL@%
  7411. %@AB@%                ' go on to calculate new ones:%@AE@%%@NL@%
  7412.                 ELSE%@NL@%
  7413. %@NL@%
  7414.                   clSetError cBadLegendWindow%@NL@%
  7415. %@NL@%
  7416.                 END IF%@NL@%
  7417.         END IF%@NL@%
  7418. %@NL@%
  7419. %@AB@%        ' Do remaining calculations according to the legend placement specified%@AE@%%@NL@%
  7420. %@AB@%        ' (right, bottom, overlay):%@AE@%%@NL@%
  7421.         SELECT CASE GE.Legend.Place%@NL@%
  7422. %@NL@%
  7423.                 CASE cRight, cOverlay:%@NL@%
  7424. %@NL@%
  7425. %@AB@%                        ' Leave room at top for chart titles:%@AE@%%@NL@%
  7426.                         Top% = TTitleLayout.TotalSize%@NL@%
  7427. %@NL@%
  7428. %@AB@%                        ' Figure out the maximum number of legend rows that will%@AE@%%@NL@%
  7429. %@AB@%                        ' fit in the amount of space you have left for the legend%@AE@%%@NL@%
  7430. %@AB@%                        ' height.  Then, see how many columns are needed.  Once%@AE@%%@NL@%
  7431. %@AB@%                        ' the number of columns is set refigure how many rows are%@AE@%%@NL@%
  7432. %@AB@%                        ' required:%@AE@%%@NL@%
  7433.                         NumRow% = INT((GP.ChartHgt - Top% - 2 * LLayout.HorizBorder) / LLayout.RowSpacing)%@NL@%
  7434.                         IF NumRow% > GP.NSeries THEN NumRow% = GP.NSeries%@NL@%
  7435.                         NumCol% = -INT(-GP.NSeries / NumRow%)%@NL@%
  7436.                         NumRow% = -INT(-GP.NSeries / NumCol%)%@NL@%
  7437. %@NL@%
  7438. %@AB@%                        ' Set the width and height:%@AE@%%@NL@%
  7439.                         LWid% = NumCol% * LLayout.ColSpacing - GFI.AvgWidth + 2 * LLayout.VertBorder%@NL@%
  7440.                         LHgt% = (NumRow% * LLayout.RowSpacing - RowLeading% + 2 * LLayout.HorizBorder)%@NL@%
  7441. %@NL@%
  7442. %@AB@%                        ' Place the legend one character width from right and even with%@AE@%%@NL@%
  7443. %@AB@%                        ' what will be the top of the data window:%@AE@%%@NL@%
  7444.                         LLft% = GP.ChartWid - 1 - LWid% - GFI.AvgWidth%@NL@%
  7445.                         LTop% = Top%%@NL@%
  7446. %@NL@%
  7447.                 CASE cBottom:%@NL@%
  7448. %@NL@%
  7449. %@AB@%                        ' The number of label columns that will fit (using the same%@AE@%%@NL@%
  7450. %@AB@%                        ' procedure as above except figure columns first):%@AE@%%@NL@%
  7451.                         NumCol% = INT((GP.ChartWid - 2 * LLayout.HorizBorder) / LLayout.ColSpacing)%@NL@%
  7452.                         IF NumCol% > GP.NSeries THEN NumCol% = GP.NSeries%@NL@%
  7453.                         NumRow% = -INT(-GP.NSeries / NumCol%)%@NL@%
  7454.                         NumCol% = -INT(-GP.NSeries / NumRow%)%@NL@%
  7455. %@NL@%
  7456. %@AB@%                        ' Set the width and height:%@AE@%%@NL@%
  7457.                         LWid% = NumCol% * LLayout.ColSpacing - GFI.AvgWidth + 2 * LLayout.VertBorder%@NL@%
  7458.                         LHgt% = (NumRow% * LLayout.RowSpacing - RowLeading% + 2 * LLayout.HorizBorder)%@NL@%
  7459. %@NL@%
  7460. %@AB@%                        ' Center the legend horizontally one character from the bottom:%@AE@%%@NL@%
  7461.                         LLft% = (GP.ChartWid - 1 - LWid%) / 2%@NL@%
  7462.                         LTop% = GP.ChartHgt - 1 - LHgt% - GFI.Ascent%@NL@%
  7463. %@NL@%
  7464.         END SELECT%@NL@%
  7465. %@NL@%
  7466. %@AB@%        ' Record legend columns and rows:%@AE@%%@NL@%
  7467.         LLayout.NumRow = NumRow%%@NL@%
  7468.         LLayout.NumCol = NumCol%%@NL@%
  7469. %@NL@%
  7470. %@AB@%        ' Finally, place the legend coordinates in GE:%@AE@%%@NL@%
  7471.         GE.Legend.LegendWindow.X1 = LLft%%@NL@%
  7472.         GE.Legend.LegendWindow.Y1 = LTop%%@NL@%
  7473.         GE.Legend.LegendWindow.X2 = LLft% + LWid%%@NL@%
  7474.         GE.Legend.LegendWindow.Y2 = LTop% + LHgt%%@NL@%
  7475. %@NL@%
  7476. %@AB@%        ' If, after all this, the legend window is invalid, set error:%@AE@%%@NL@%
  7477.         IF LLft% < 0 OR LTop% < 0 OR LWid% <= 0 OR LHgt% <= 0 THEN%@NL@%
  7478.                 clSetError cBadLegendWindow%@NL@%
  7479.         END IF%@NL@%
  7480. %@NL@%
  7481. END SUB%@NL@%
  7482. %@NL@%
  7483. %@AB@%'=== clLayoutTitle - Figures out title layouts for Top, X-axis and%@AE@%%@NL@%
  7484. %@AB@%'                      Y-axis titles%@AE@%%@NL@%
  7485. %@AB@%'%@AE@%%@NL@%
  7486. %@AB@%'  Arguments:%@AE@%%@NL@%
  7487. %@AB@%'     TL    -  Layout variable into which to place titles%@AE@%%@NL@%
  7488. %@AB@%'%@AE@%%@NL@%
  7489. %@AB@%'     T1    -  First title%@AE@%%@NL@%
  7490. %@AB@%'%@AE@%%@NL@%
  7491. %@AB@%'     T2    -  Second Title%@AE@%%@NL@%
  7492. %@AB@%'%@AE@%%@NL@%
  7493. %@AB@%'  Return Values:%@AE@%%@NL@%
  7494. %@AB@%'     none%@AE@%%@NL@%
  7495. %@AB@%'%@AE@%%@NL@%
  7496. %@AB@%'=================================================================%@AE@%%@NL@%
  7497. SUB clLayoutTitle (TL AS TitleLayout, T1 AS TitleType, T2 AS TitleType)%@NL@%
  7498. SHARED GFI AS FontInfo%@NL@%
  7499. %@NL@%
  7500. %@AB@%        ' Set the title heights initially to 0:%@AE@%%@NL@%
  7501.         TL.TitleOne = 0%@NL@%
  7502.         TL.TitleTwo = 0%@NL@%
  7503. %@NL@%
  7504. %@AB@%        ' If the first title is set then get its height:%@AE@%%@NL@%
  7505.         Total% = 0%@NL@%
  7506.         IF LTRIM$(T1.Title) <> "" THEN%@NL@%
  7507.                 clSetChartFont T1.TitleFont%@NL@%
  7508.                 TL.TitleOne = GFI.PixHeight%@NL@%
  7509.                 Total% = Total% + 1%@NL@%
  7510.         END IF%@NL@%
  7511. %@NL@%
  7512. %@AB@%        ' If the second title is set then get it's height:%@AE@%%@NL@%
  7513.         IF LTRIM$(T2.Title) <> "" THEN%@NL@%
  7514.                 clSetChartFont T2.TitleFont%@NL@%
  7515.                 TL.TitleTwo = GFI.PixHeight%@NL@%
  7516.                 Lead2% = GFI.Leading%@NL@%
  7517.                 Total% = Total% + 1%@NL@%
  7518.         END IF%@NL@%
  7519. %@NL@%
  7520. %@AB@%        ' Set the "leading" values for label spacing depending on how many%@AE@%%@NL@%
  7521. %@AB@%        ' of the titles were non-blank:%@AE@%%@NL@%
  7522.         TotalHeight% = TL.TitleOne + TL.TitleTwo%@NL@%
  7523.         SELECT CASE Total%%@NL@%
  7524.                 CASE 0:%@NL@%
  7525.                         TL.Top = 8%@NL@%
  7526.                         TL.Middle = 0%@NL@%
  7527.                         TL.Bottom = 4%@NL@%
  7528. %@NL@%
  7529.                 CASE 1:%@NL@%
  7530.                         TL.Top = 8 + TotalHeight% / 8%@NL@%
  7531.                         TL.Middle = 0%@NL@%
  7532.                         TL.Bottom = TL.Top%@NL@%
  7533. %@NL@%
  7534.                 CASE 2:%@NL@%
  7535.                         TL.Top = 8 + TotalHeight% / 8%@NL@%
  7536.                         TL.Middle = 0: IF Lead2% = 0 THEN TL.Middle = TL.TitleOne / 2%@NL@%
  7537.                         TL.Bottom = TL.Top%@NL@%
  7538.         END SELECT%@NL@%
  7539. %@NL@%
  7540.         TL.TotalSize = TL.Top + TL.TitleOne + TL.Middle + TL.TitleTwo + TL.Bottom%@NL@%
  7541. %@NL@%
  7542. END SUB%@NL@%
  7543. %@NL@%
  7544. %@AB@%'=== clMap2Attrib% - Maps an integer to a screen attribute for current%@AE@%%@NL@%
  7545. %@AB@%'                    screen mode%@AE@%%@NL@%
  7546. %@AB@%'%@AE@%%@NL@%
  7547. %@AB@%'  Arguments:%@AE@%%@NL@%
  7548. %@AB@%'     N% - The number to map%@AE@%%@NL@%
  7549. %@AB@%'%@AE@%%@NL@%
  7550. %@AB@%'  Return Values:%@AE@%%@NL@%
  7551. %@AB@%'     The function returns:%@AE@%%@NL@%
  7552. %@AB@%'        0 is mapped to 0, all other numbers are mapped to the range%@AE@%%@NL@%
  7553. %@AB@%'        1 to GP.MaxColor%@AE@%%@NL@%
  7554. %@AB@%'%@AE@%%@NL@%
  7555. %@AB@%'=================================================================%@AE@%%@NL@%
  7556. FUNCTION clMap2Attrib% (N%)%@NL@%
  7557. SHARED GP AS GlobalParams%@NL@%
  7558. %@NL@%
  7559.         AbsN% = ABS(N%)%@NL@%
  7560.         IF AbsN% = 0 THEN%@NL@%
  7561.                 clMap2Attrib% = AbsN%%@NL@%
  7562.         ELSE%@NL@%
  7563.                 clMap2Attrib% = (AbsN% - 1) MOD GP.MaxColor + 1%@NL@%
  7564.         END IF%@NL@%
  7565. %@NL@%
  7566. END FUNCTION%@NL@%
  7567. %@NL@%
  7568. %@AB@%'=== clMap2Pal% - Maps an integer into a palette reference%@AE@%%@NL@%
  7569. %@AB@%'%@AE@%%@NL@%
  7570. %@AB@%'  Arguments:%@AE@%%@NL@%
  7571. %@AB@%'     N% - The number to map%@AE@%%@NL@%
  7572. %@AB@%'%@AE@%%@NL@%
  7573. %@AB@%'  Return Values:%@AE@%%@NL@%
  7574. %@AB@%'     The function returns (N%-1) MOD cPalLen + 1%@AE@%%@NL@%
  7575. %@AB@%'%@AE@%%@NL@%
  7576. %@AB@%'  Remarks:%@AE@%%@NL@%
  7577. %@AB@%'     This FUNCTION is used in almost every reference to a palette to ensure%@AE@%%@NL@%
  7578. %@AB@%'     that an invalid number doesn't cause a reference outside of a palette%@AE@%%@NL@%
  7579. %@AB@%'     array (and thus crash the library).  This FUNCTION maps the first%@AE@%%@NL@%
  7580. %@AB@%'     cPalLen values to themselves. Numbers above cPalLen are mapped to%@AE@%%@NL@%
  7581. %@AB@%'     the values 2..cPalLen.%@AE@%%@NL@%
  7582. %@AB@%'%@AE@%%@NL@%
  7583. %@AB@%'=================================================================%@AE@%%@NL@%
  7584. FUNCTION clMap2Pal% (N%)%@NL@%
  7585. %@NL@%
  7586.         AbsN% = ABS(N%)%@NL@%
  7587.         IF AbsN% > cPalLen THEN%@NL@%
  7588.                 clMap2Pal% = (AbsN% - 2) MOD (cPalLen - 1) + 2%@NL@%
  7589.         ELSE%@NL@%
  7590.                 clMap2Pal% = AbsN%%@NL@%
  7591.         END IF%@NL@%
  7592. %@NL@%
  7593. END FUNCTION%@NL@%
  7594. %@NL@%
  7595. %@AB@%'=== clMaxStrLen% - Finds the length of the longest string in a list%@AE@%%@NL@%
  7596. %@AB@%'%@AE@%%@NL@%
  7597. %@AB@%'  Arguments:%@AE@%%@NL@%
  7598. %@AB@%'     Txt$(1)  -  One-dimensional array of strings to search%@AE@%%@NL@%
  7599. %@AB@%'%@AE@%%@NL@%
  7600. %@AB@%'     First%   -  First string to consider%@AE@%%@NL@%
  7601. %@AB@%'%@AE@%%@NL@%
  7602. %@AB@%'     Last%    -  Last string to consider%@AE@%%@NL@%
  7603. %@AB@%'%@AE@%%@NL@%
  7604. %@AB@%'  Return Values:%@AE@%%@NL@%
  7605. %@AB@%'     This FUNCTION returns the length of the longest string%@AE@%%@NL@%
  7606. %@AB@%'%@AE@%%@NL@%
  7607. %@AB@%'=================================================================%@AE@%%@NL@%
  7608. FUNCTION clMaxStrLen% (Txt$(), First%, Last%)%@NL@%
  7609. %@NL@%
  7610. %@AB@%        ' Set Max to 0 then loop through each label updating Max if the%@AE@%%@NL@%
  7611. %@AB@%        ' label is longer:%@AE@%%@NL@%
  7612.         Max% = 0%@NL@%
  7613.         FOR Row% = First% TO Last%%@NL@%
  7614.                 L% = GetGTextLen(Txt$(Row%))%@NL@%
  7615.                 IF L% > Max% THEN Max% = L%%@NL@%
  7616.         NEXT Row%%@NL@%
  7617. %@NL@%
  7618. %@AB@%        ' Return Max as the value of the FUNCTION:%@AE@%%@NL@%
  7619.         clMaxStrLen% = Max%%@NL@%
  7620. %@NL@%
  7621. END FUNCTION%@NL@%
  7622. %@NL@%
  7623. %@AB@%'=== clMaxVal - Returns the maximum of two numbers%@AE@%%@NL@%
  7624. %@AB@%'%@AE@%%@NL@%
  7625. %@AB@%'  Arguments:%@AE@%%@NL@%
  7626. %@AB@%'     A  -  The first number%@AE@%%@NL@%
  7627. %@AB@%'%@AE@%%@NL@%
  7628. %@AB@%'     B  -  The second number%@AE@%%@NL@%
  7629. %@AB@%'%@AE@%%@NL@%
  7630. %@AB@%'  Return Values:%@AE@%%@NL@%
  7631. %@AB@%'     The function returns the maximum of the two values%@AE@%%@NL@%
  7632. %@AB@%'%@AE@%%@NL@%
  7633. %@AB@%'=================================================================%@AE@%%@NL@%
  7634. FUNCTION clMaxVal (A, B)%@NL@%
  7635. %@NL@%
  7636.         IF A > B THEN clMaxVal = A ELSE clMaxVal = B%@NL@%
  7637. %@NL@%
  7638. END FUNCTION%@NL@%
  7639. %@NL@%
  7640. %@AB@%'=== clPrintTitle - Prints title correctly justified and colored%@AE@%%@NL@%
  7641. %@AB@%'%@AE@%%@NL@%
  7642. %@AB@%'  Arguments:%@AE@%%@NL@%
  7643. %@AB@%'     TitleVar - A TitleType variable containing specifications for the%@AE@%%@NL@%
  7644. %@AB@%'                title to be printed%@AE@%%@NL@%
  7645. %@AB@%'%@AE@%%@NL@%
  7646. %@AB@%'     Y%       - Vertical position in window for bottom of line%@AE@%%@NL@%
  7647. %@AB@%'%@AE@%%@NL@%
  7648. %@AB@%'  Return Values:%@AE@%%@NL@%
  7649. %@AB@%'     None%@AE@%%@NL@%
  7650. %@AB@%'%@AE@%%@NL@%
  7651. %@AB@%'=================================================================%@AE@%%@NL@%
  7652. SUB clPrintTitle (TitleVar AS TitleType, Y%)%@NL@%
  7653. SHARED GFI AS FontInfo, GP AS GlobalParams%@NL@%
  7654. %@NL@%
  7655. %@AB@%        ' Calculate width of the title text:%@AE@%%@NL@%
  7656.         clSetChartFont TitleVar.TitleFont%@NL@%
  7657. %@NL@%
  7658.         Txt$ = RTRIM$(TitleVar.Title)%@NL@%
  7659.         TxtLen% = GetGTextLen(Txt$)%@NL@%
  7660.         IF TxtLen% = 0 THEN EXIT SUB%@NL@%
  7661. %@NL@%
  7662. %@AB@%        ' Calculate horizontal position depending on justification style%@AE@%%@NL@%
  7663.         SELECT CASE TitleVar.Justify%@NL@%
  7664. %@NL@%
  7665.                 CASE cCenter: X% = (GP.ChartWid - 1 - (TxtLen%)) / 2%@NL@%
  7666.                 CASE cRight:  X% = GP.ChartWid - 1 - TxtLen% - GFI.AvgWidth%@NL@%
  7667.                 CASE ELSE:    X% = GFI.AvgWidth%@NL@%
  7668. %@NL@%
  7669.         END SELECT%@NL@%
  7670. %@NL@%
  7671. %@AB@%        ' Set color of text and print it:%@AE@%%@NL@%
  7672.         clSetCharColor TitleVar.TitleColor%@NL@%
  7673.         clHPrint X%, Y%, Txt$%@NL@%
  7674. %@NL@%
  7675. END SUB%@NL@%
  7676. %@NL@%
  7677. %@AB@%'=== clRenderBar - Renders a bar for a bar or column chart%@AE@%%@NL@%
  7678. %@AB@%'%@AE@%%@NL@%
  7679. %@AB@%'  Arguments:%@AE@%%@NL@%
  7680. %@AB@%'     X1    -  Left side of bar (in data world coordinates)%@AE@%%@NL@%
  7681. %@AB@%'%@AE@%%@NL@%
  7682. %@AB@%'     Y1    -  Top of bar (in data world coordinates)%@AE@%%@NL@%
  7683. %@AB@%'%@AE@%%@NL@%
  7684. %@AB@%'     X2    -  Right side of bar (in data world coordinates)%@AE@%%@NL@%
  7685. %@AB@%'%@AE@%%@NL@%
  7686. %@AB@%'     Y2    -  Bottom of bar (in data world coordinates)%@AE@%%@NL@%
  7687. %@AB@%'%@AE@%%@NL@%
  7688. %@AB@%'     C%    -  Palette entry number to use for border color and fill pattern%@AE@%%@NL@%
  7689. %@AB@%'%@AE@%%@NL@%
  7690. %@AB@%'  Return Values:%@AE@%%@NL@%
  7691. %@AB@%'     None%@AE@%%@NL@%
  7692. %@AB@%'%@AE@%%@NL@%
  7693. %@AB@%'=================================================================%@AE@%%@NL@%
  7694. SUB clRenderBar (X1, Y1, X2, Y2, C%)%@NL@%
  7695. SHARED PaletteC%(), PaletteP$()%@NL@%
  7696. %@NL@%
  7697. %@AB@%        ' First clear out space for the bar by drawing a bar in black:%@AE@%%@NL@%
  7698.         LINE (X1, Y1)-(X2, Y2), 0, BF%@NL@%
  7699. %@NL@%
  7700. %@AB@%        ' Put a border around the bar and fill with pattern:%@AE@%%@NL@%
  7701.         MC% = clMap2Pal%(C%)%@NL@%
  7702. %@NL@%
  7703.         LINE (X1, Y1)-(X2, Y2), 1, B%@NL@%
  7704.         PAINT ((X1 + X2) / 2, (Y1 + Y2) / 2), PaletteP$(MC%), 1%@NL@%
  7705.         LINE (X1, Y1)-(X2, Y2), PaletteC%(MC%), B%@NL@%
  7706. %@NL@%
  7707. END SUB%@NL@%
  7708. %@NL@%
  7709. %@AB@%'=== clRenderWindow - Renders a window on the screen%@AE@%%@NL@%
  7710. %@AB@%'%@AE@%%@NL@%
  7711. %@AB@%'  Arguments:%@AE@%%@NL@%
  7712. %@AB@%'     W - A RegionType variable%@AE@%%@NL@%
  7713. %@AB@%'%@AE@%%@NL@%
  7714. %@AB@%'  Return Values:%@AE@%%@NL@%
  7715. %@AB@%'     None%@AE@%%@NL@%
  7716. %@AB@%'%@AE@%%@NL@%
  7717. %@AB@%'  Remarks:%@AE@%%@NL@%
  7718. %@AB@%'     This routine assumes that the viewport is set to the borders of%@AE@%%@NL@%
  7719. %@AB@%'     the window to be rendered%@AE@%%@NL@%
  7720. %@AB@%'%@AE@%%@NL@%
  7721. %@AB@%'=================================================================%@AE@%%@NL@%
  7722. SUB clRenderWindow (W AS RegionType)%@NL@%
  7723. SHARED PaletteC%(), PaletteB%()%@NL@%
  7724. %@NL@%
  7725. %@AB@%        ' Set window since the size of the viewport is unknown and draw%@AE@%%@NL@%
  7726. %@AB@%        ' a filled box of the background color specified by the window%@AE@%%@NL@%
  7727. %@AB@%        ' definition:%@AE@%%@NL@%
  7728.         WINDOW (0, 0)-(1, 1)%@NL@%
  7729.         LINE (0, 0)-(1, 1), PaletteC%(clMap2Pal%(W.Background)), BF%@NL@%
  7730. %@NL@%
  7731. %@AB@%        ' Draw a border if specified:%@AE@%%@NL@%
  7732.         IF W.Border = cYes THEN%@NL@%
  7733.                 LINE (0, 0)-(1, 1), PaletteC%(clMap2Pal%(W.BorderColor)), B, PaletteB%(clMap2Pal%(W.BorderStyle))%@NL@%
  7734.         END IF%@NL@%
  7735. %@NL@%
  7736. END SUB%@NL@%
  7737. %@NL@%
  7738. %@AB@%'=== clScaleAxis - Calculates minimum, maximum and scale factor for an axis%@AE@%%@NL@%
  7739. %@AB@%'%@AE@%%@NL@%
  7740. %@AB@%'  Arguments:%@AE@%%@NL@%
  7741. %@AB@%'     A        - An AxisType variable%@AE@%%@NL@%
  7742. %@AB@%'%@AE@%%@NL@%
  7743. %@AB@%'     AxisMode%- cCategory or cValue%@AE@%%@NL@%
  7744. %@AB@%'%@AE@%%@NL@%
  7745. %@AB@%'     D1(2)    - Two-dimensional array of values to be scaled%@AE@%%@NL@%
  7746. %@AB@%'%@AE@%%@NL@%
  7747. %@AB@%'  Return Values:%@AE@%%@NL@%
  7748. %@AB@%'     ScaleMin, ScaleMax, ScaleFactor, and ScaleTitle elements in%@AE@%%@NL@%
  7749. %@AB@%'     axis variable will be altered if it is a category axis or%@AE@%%@NL@%
  7750. %@AB@%'     AutoScale is Yes.%@AE@%%@NL@%
  7751. %@AB@%'%@AE@%%@NL@%
  7752. %@AB@%'=================================================================%@AE@%%@NL@%
  7753. SUB clScaleAxis (Axis AS AxisType, AxisMode%, D1())%@NL@%
  7754. SHARED GE AS ChartEnvironment, GP AS GlobalParams%@NL@%
  7755. %@NL@%
  7756. %@AB@%        ' If this is a category axis then ignore all the flags and force%@AE@%%@NL@%
  7757. %@AB@%        ' scale parameters to those needed by charting routines:%@AE@%%@NL@%
  7758.         IF AxisMode% = cCategory THEN%@NL@%
  7759.                 Axis.ScaleMin = 0%@NL@%
  7760.                 Axis.ScaleMax = 1%@NL@%
  7761.                 Axis.ScaleFactor = 1%@NL@%
  7762.                 Axis.ScaleTitle.Title = ""%@NL@%
  7763.                 EXIT SUB%@NL@%
  7764.         END IF%@NL@%
  7765. %@NL@%
  7766. %@AB@%        ' If AutoScale isn't Yes then exit:%@AE@%%@NL@%
  7767.         IF Axis.AutoScale <> cYes THEN EXIT SUB%@NL@%
  7768. %@NL@%
  7769. %@AB@%        ' AutoScale was specified, calculate the different scale variables%@AE@%%@NL@%
  7770. %@AB@%        ' Set maximum and minimum to defaults.%@AE@%%@NL@%
  7771. %@NL@%
  7772. %@AB@%        ' Initialize the value- and row-minimum and maximum values to zero:%@AE@%%@NL@%
  7773.         VMin = 0%@NL@%
  7774.         VMax = 0%@NL@%
  7775. %@NL@%
  7776.         RMin = 0%@NL@%
  7777.         RMax = 0%@NL@%
  7778. %@NL@%
  7779. %@AB@%        ' Compare data values for minimum and maximum:%@AE@%%@NL@%
  7780.         FOR Row% = 1 TO GP.NVals%@NL@%
  7781. %@NL@%
  7782. %@AB@%                ' Initialize positive and negative sum variables:%@AE@%%@NL@%
  7783.                 RSumPos = 0%@NL@%
  7784.                 RSumNeg = 0%@NL@%
  7785. %@NL@%
  7786. %@AB@%                ' Evaluate the value from this row in each series:%@AE@%%@NL@%
  7787.                 FOR Column% = 1 TO GP.NSeries%@NL@%
  7788. %@NL@%
  7789. %@AB@%                        ' Get the value from the data array:%@AE@%%@NL@%
  7790.                         V = D1(Row%, Column%)%@NL@%
  7791. %@NL@%
  7792. %@AB@%                        ' Process values that aren't missing only:%@AE@%%@NL@%
  7793.                         IF V <> cMissingValue THEN%@NL@%
  7794. %@NL@%
  7795. %@AB@%                                ' Add positive values to positive sum and negative ones to%@AE@%%@NL@%
  7796. %@AB@%                                ' negative sum:%@AE@%%@NL@%
  7797.                                 IF V > 0 THEN RSumPos = RSumPos + V%@NL@%
  7798.                                 IF V < 0 THEN RSumNeg = RSumNeg + V%@NL@%
  7799. %@NL@%
  7800. %@AB@%                                ' Compare the value against current maximum and minimum and%@AE@%%@NL@%
  7801. %@AB@%                                ' replace them if appropriate:%@AE@%%@NL@%
  7802.                                 IF V < VMin THEN VMin = V%@NL@%
  7803.                                 IF V > VMax THEN VMax = V%@NL@%
  7804. %@NL@%
  7805.                         END IF%@NL@%
  7806. %@NL@%
  7807.                 NEXT Column%%@NL@%
  7808. %@NL@%
  7809. %@AB@%                ' Compare the positive and negative sums for this row with the%@AE@%%@NL@%
  7810. %@AB@%                ' current row maximum and minimum and replace them if appropriate:%@AE@%%@NL@%
  7811.                 IF RSumNeg < RMin THEN RMin = RSumNeg%@NL@%
  7812.                 IF RSumPos > RMax THEN RMax = RSumPos%@NL@%
  7813. %@NL@%
  7814.         NEXT Row%%@NL@%
  7815. %@NL@%
  7816. %@AB@%        ' If the chart style is one, meaning that the data isn't stacked for%@AE@%%@NL@%
  7817. %@AB@%        ' bar and column charts, or it is a line or scatter chart then the scale%@AE@%%@NL@%
  7818. %@AB@%        ' minimum and maximum are the minimum and maximum values found.%@AE@%%@NL@%
  7819. %@AB@%        ' Each value is adjusted so the data is not drawn on or beyond the%@AE@%%@NL@%
  7820. %@AB@%        ' border of the data window:%@AE@%%@NL@%
  7821.         IF GE.ChartStyle = 1 OR GE.ChartType = cLine OR GE.ChartType = cScatter THEN%@NL@%
  7822.                 IF VMin < 0 THEN%@NL@%
  7823.                         Axis.ScaleMin = VMin - .01 * (VMax - VMin)%@NL@%
  7824.                 END IF%@NL@%
  7825.                 IF VMax > 0 THEN%@NL@%
  7826.                         Axis.ScaleMax = VMax + .01 * (VMax - VMin)%@NL@%
  7827.                 END IF%@NL@%
  7828. %@NL@%
  7829. %@AB@%        ' Otherwise, the scale minimum and maximum are the minimum and maximum%@AE@%%@NL@%
  7830. %@AB@%        ' sums of the data for each row:%@AE@%%@NL@%
  7831.         ELSE%@NL@%
  7832.                 IF RMin < 0 THEN%@NL@%
  7833.                         Axis.ScaleMin = RMin - .01 * (RMax - RMin)%@NL@%
  7834.                 END IF%@NL@%
  7835.                 IF RMax > 0 THEN%@NL@%
  7836.                         Axis.ScaleMax = RMax + .01 * (RMax - RMin)%@NL@%
  7837.                 END IF%@NL@%
  7838.         END IF%@NL@%
  7839. %@NL@%
  7840. %@AB@%        ' If no data then force range to be non-zero:%@AE@%%@NL@%
  7841.         IF Axis.ScaleMin = Axis.ScaleMax THEN Axis.ScaleMax = 1%@NL@%
  7842. %@NL@%
  7843. %@AB@%        ' Adjust the scale limits by ScaleFactor if required:%@AE@%%@NL@%
  7844.         clAdjustScale Axis%@NL@%
  7845. %@NL@%
  7846. END SUB%@NL@%
  7847. %@NL@%
  7848. %@AB@%'=== clSelectChartFont - Selects a font to use and gets info about it%@AE@%%@NL@%
  7849. %@AB@%'%@AE@%%@NL@%
  7850. %@AB@%'  Arguments:%@AE@%%@NL@%
  7851. %@AB@%'     N%    -  Font number to use%@AE@%%@NL@%
  7852. %@AB@%'%@AE@%%@NL@%
  7853. %@AB@%'  Return Values:%@AE@%%@NL@%
  7854. %@AB@%'     none%@AE@%%@NL@%
  7855. %@AB@%'%@AE@%%@NL@%
  7856. %@AB@%'=================================================================%@AE@%%@NL@%
  7857. SUB clSelectChartFont (N%)%@NL@%
  7858. SHARED GFI AS FontInfo%@NL@%
  7859. %@NL@%
  7860. %@AB@%        ' Select the font and get information about it:%@AE@%%@NL@%
  7861.         SelectFont N%%@NL@%
  7862.         GetFontInfo GFI%@NL@%
  7863. END SUB%@NL@%
  7864. %@NL@%
  7865. %@AB@%'=== clSelectChartWindow - Sets viewport to chart window%@AE@%%@NL@%
  7866. %@AB@%'%@AE@%%@NL@%
  7867. %@AB@%'  Arguments:%@AE@%%@NL@%
  7868. %@AB@%'     Env         - A ChartEnvironment variable%@AE@%%@NL@%
  7869. %@AB@%'%@AE@%%@NL@%
  7870. %@AB@%'  Return Values:%@AE@%%@NL@%
  7871. %@AB@%'     None%@AE@%%@NL@%
  7872. %@AB@%'%@AE@%%@NL@%
  7873. %@AB@%'  Remarks:%@AE@%%@NL@%
  7874. %@AB@%'     This routine erases any previous viewport%@AE@%%@NL@%
  7875. %@AB@%'%@AE@%%@NL@%
  7876. %@AB@%'=================================================================%@AE@%%@NL@%
  7877. SUB clSelectChartWindow%@NL@%
  7878. SHARED GP AS GlobalParams%@NL@%
  7879. %@NL@%
  7880. %@AB@%        ' Set viewport to chart window:%@AE@%%@NL@%
  7881.         VIEW (GP.CwX1, GP.CwY1)-(GP.CwX2, GP.CwY2)%@NL@%
  7882. %@NL@%
  7883. END SUB%@NL@%
  7884. %@NL@%
  7885. %@AB@%'=== clSelectRelWindow - Sets viewport to window relative to chart window%@AE@%%@NL@%
  7886. %@AB@%'%@AE@%%@NL@%
  7887. %@AB@%'  Arguments:%@AE@%%@NL@%
  7888. %@AB@%'     Env   - A ChartEnvironment variable%@AE@%%@NL@%
  7889. %@AB@%'%@AE@%%@NL@%
  7890. %@AB@%'     W     - RegionType variable of window to set%@AE@%%@NL@%
  7891. %@AB@%'%@AE@%%@NL@%
  7892. %@AB@%'  Return Values:%@AE@%%@NL@%
  7893. %@AB@%'     None%@AE@%%@NL@%
  7894. %@AB@%'%@AE@%%@NL@%
  7895. %@AB@%'  Remarks:%@AE@%%@NL@%
  7896. %@AB@%'     This routine erases any previous viewport%@AE@%%@NL@%
  7897. %@AB@%'%@AE@%%@NL@%
  7898. %@AB@%'=================================================================%@AE@%%@NL@%
  7899. SUB clSelectRelWindow (W AS RegionType)%@NL@%
  7900. SHARED GP AS GlobalParams%@NL@%
  7901. %@NL@%
  7902. %@AB@%        ' New viewport is defined relative to the current one:%@AE@%%@NL@%
  7903.         VIEW (GP.CwX1 + W.X1, GP.CwY1 + W.Y1)-(GP.CwX1 + W.X2, GP.CwY1 + W.Y2)%@NL@%
  7904. %@NL@%
  7905. END SUB%@NL@%
  7906. %@NL@%
  7907. %@AB@%'=== clSetAxisModes - Sets axis modes for X- and Y-axis according to%@AE@%%@NL@%
  7908. %@AB@%'                   ChartType%@AE@%%@NL@%
  7909. %@AB@%'%@AE@%%@NL@%
  7910. %@AB@%'  Arguments:%@AE@%%@NL@%
  7911. %@AB@%'     None%@AE@%%@NL@%
  7912. %@AB@%'%@AE@%%@NL@%
  7913. %@AB@%'  Return Values:%@AE@%%@NL@%
  7914. %@AB@%'     Alters XAxis and YAxis axis modes%@AE@%%@NL@%
  7915. %@AB@%'%@AE@%%@NL@%
  7916. %@AB@%'=================================================================%@AE@%%@NL@%
  7917. SUB clSetAxisModes%@NL@%
  7918. SHARED GE AS ChartEnvironment%@NL@%
  7919. SHARED GP AS GlobalParams%@NL@%
  7920. %@NL@%
  7921.         SELECT CASE GE.ChartType%@NL@%
  7922. %@NL@%
  7923.                 CASE cBar:%@NL@%
  7924.                         GP.XMode = cValue%@NL@%
  7925.                         GP.YMode = cCategory%@NL@%
  7926. %@NL@%
  7927.                 CASE cColumn, cLine:%@NL@%
  7928.                         GP.XMode = cCategory%@NL@%
  7929.                         GP.YMode = cValue%@NL@%
  7930. %@NL@%
  7931.                 CASE cScatter:%@NL@%
  7932.                         GP.XMode = cValue%@NL@%
  7933.                         GP.YMode = cValue%@NL@%
  7934. %@NL@%
  7935.                 CASE cPie:%@NL@%
  7936.                         GP.XMode = cCategory%@NL@%
  7937.                         GP.YMode = cCategory%@NL@%
  7938. %@NL@%
  7939.         END SELECT%@NL@%
  7940. %@NL@%
  7941. END SUB%@NL@%
  7942. %@NL@%
  7943. %@AB@%'=== clSetCharColor - Sets color for DRAW characters%@AE@%%@NL@%
  7944. %@AB@%'%@AE@%%@NL@%
  7945. %@AB@%'  Arguments:%@AE@%%@NL@%
  7946. %@AB@%'     N%    -  Color number%@AE@%%@NL@%
  7947. %@AB@%'%@AE@%%@NL@%
  7948. %@AB@%'  Return Values:%@AE@%%@NL@%
  7949. %@AB@%'     None%@AE@%%@NL@%
  7950. %@AB@%'%@AE@%%@NL@%
  7951. %@AB@%'=================================================================%@AE@%%@NL@%
  7952. SUB clSetCharColor (N%)%@NL@%
  7953. SHARED PaletteC%()%@NL@%
  7954. %@NL@%
  7955. %@AB@%        ' Check for valid color number then set color if correct:%@AE@%%@NL@%
  7956.         SetGTextColor PaletteC%(clMap2Pal%(N%))%@NL@%
  7957. %@NL@%
  7958. END SUB%@NL@%
  7959. %@NL@%
  7960. %@AB@%'=== clSetChartFont - Selects the specified font%@AE@%%@NL@%
  7961. %@AB@%'%@AE@%%@NL@%
  7962. %@AB@%'  Arguments:%@AE@%%@NL@%
  7963. %@AB@%'     N%    -  Number of loaded font to select%@AE@%%@NL@%
  7964. %@AB@%'%@AE@%%@NL@%
  7965. %@AB@%'  Return Values:%@AE@%%@NL@%
  7966. %@AB@%'     none%@AE@%%@NL@%
  7967. %@AB@%'%@AE@%%@NL@%
  7968. %@AB@%'=================================================================%@AE@%%@NL@%
  7969. SUB clSetChartFont (N AS INTEGER)%@NL@%
  7970. SHARED GFI AS FontInfo%@NL@%
  7971. %@NL@%
  7972. %@AB@%        ' Select font and get information on it:%@AE@%%@NL@%
  7973.         SelectFont N%%@NL@%
  7974.         GetFontInfo GFI%@NL@%
  7975. %@NL@%
  7976. END SUB%@NL@%
  7977. %@NL@%
  7978. %@AB@%'=== clSetError - Sets the ChartLib error variable%@AE@%%@NL@%
  7979. %@AB@%'%@AE@%%@NL@%
  7980. %@AB@%'  Arguments:%@AE@%%@NL@%
  7981. %@AB@%'     ErrNo    - The error number to set%@AE@%%@NL@%
  7982. %@AB@%'%@AE@%%@NL@%
  7983. %@AB@%'  Return Values:%@AE@%%@NL@%
  7984. %@AB@%'     Sets ChartErr to ErrNo%@AE@%%@NL@%
  7985. %@AB@%'%@AE@%%@NL@%
  7986. %@AB@%'=================================================================%@AE@%%@NL@%
  7987. SUB clSetError (ErrNo AS INTEGER)%@NL@%
  7988. %@NL@%
  7989.         ChartErr = ErrNo%@NL@%
  7990. %@NL@%
  7991. END SUB%@NL@%
  7992. %@NL@%
  7993. %@AB@%'=== clSetGlobalParams - Sets some global parameters that other routines use%@AE@%%@NL@%
  7994. %@AB@%'%@AE@%%@NL@%
  7995. %@AB@%'  Arguments:%@AE@%%@NL@%
  7996. %@AB@%'     None%@AE@%%@NL@%
  7997. %@AB@%'%@AE@%%@NL@%
  7998. %@AB@%'  Return Values:%@AE@%%@NL@%
  7999. %@AB@%'     GP.ValLenX and GP.ValLenY are altered%@AE@%%@NL@%
  8000. %@AB@%'%@AE@%%@NL@%
  8001. %@AB@%'=================================================================%@AE@%%@NL@%
  8002. SUB clSetGlobalParams%@NL@%
  8003. SHARED GP AS GlobalParams, GE AS ChartEnvironment%@NL@%
  8004. %@NL@%
  8005. %@AB@%        ' Figure out longest label on X axis:%@AE@%%@NL@%
  8006.         clSetChartFont GE.XAxis.TicFont%@NL@%
  8007.         SF = GE.XAxis.ScaleMin%@NL@%
  8008.         Len1 = GetGTextLen(clVal2Str$(SF, GE.XAxis.TicDecimals, GE.XAxis.TicFormat))%@NL@%
  8009.         SF = GE.XAxis.ScaleMax%@NL@%
  8010.         Len2 = GetGTextLen(clVal2Str$(SF, GE.XAxis.TicDecimals, GE.XAxis.TicFormat))%@NL@%
  8011.         GP.ValLenX = clMaxVal(Len1, Len2)%@NL@%
  8012. %@NL@%
  8013. %@AB@%        ' Figure out longest label on Y axis:%@AE@%%@NL@%
  8014.         clSetChartFont GE.YAxis.TicFont%@NL@%
  8015.         SF = GE.YAxis.ScaleMin%@NL@%
  8016.         Len1 = GetGTextLen(clVal2Str$(SF, GE.YAxis.TicDecimals, GE.YAxis.TicFormat))%@NL@%
  8017.         SF = GE.YAxis.ScaleMax%@NL@%
  8018.         Len2 = GetGTextLen(clVal2Str$(SF, GE.YAxis.TicDecimals, GE.YAxis.TicFormat))%@NL@%
  8019.         GP.ValLenY = clMaxVal(Len1, Len2)%@NL@%
  8020. %@NL@%
  8021. END SUB%@NL@%
  8022. %@NL@%
  8023. %@AB@%'=== clSizeDataWindow - Calculates general data window size%@AE@%%@NL@%
  8024. %@AB@%'%@AE@%%@NL@%
  8025. %@AB@%'  Arguments:%@AE@%%@NL@%
  8026. %@AB@%'     Cat$(1)  - One-dimensional array of category labels (only%@AE@%%@NL@%
  8027. %@AB@%'                used if one of the axes is a category one)%@AE@%%@NL@%
  8028. %@AB@%'%@AE@%%@NL@%
  8029. %@AB@%'  Return Values:%@AE@%%@NL@%
  8030. %@AB@%'     The X1, Y1, X2, Y2 elements of the GE variable will be%@AE@%%@NL@%
  8031. %@AB@%'     set to the data window coordinates%@AE@%%@NL@%
  8032. %@AB@%'%@AE@%%@NL@%
  8033. %@AB@%'=================================================================%@AE@%%@NL@%
  8034. SUB clSizeDataWindow (Cat$())%@NL@%
  8035. SHARED GE AS ChartEnvironment%@NL@%
  8036. SHARED GP AS GlobalParams%@NL@%
  8037. SHARED GFI AS FontInfo%@NL@%
  8038. SHARED TTitleLayout AS TitleLayout%@NL@%
  8039. SHARED XTitleLayout AS TitleLayout%@NL@%
  8040. SHARED YTitleLayout AS TitleLayout%@NL@%
  8041. %@NL@%
  8042. %@AB@%        ' *** TOP%@AE@%%@NL@%
  8043. %@AB@%        ' Adjust the top of the data window:%@AE@%%@NL@%
  8044.         DTop% = TTitleLayout.TotalSize%@NL@%
  8045. %@NL@%
  8046. %@AB@%        ' *** LEFT%@AE@%%@NL@%
  8047. %@AB@%        ' Do left side:%@AE@%%@NL@%
  8048.         DLeft% = YTitleLayout.TotalSize%@NL@%
  8049. %@NL@%
  8050. %@AB@%        ' Add room for axis labels if the axis is labeled and not a pie chart:%@AE@%%@NL@%
  8051.         IF GE.ChartType <> cPie THEN%@NL@%
  8052.                 IF GE.YAxis.Labeled = cYes THEN%@NL@%
  8053. %@NL@%
  8054. %@AB@%                        ' Get the correct font:%@AE@%%@NL@%
  8055.                         clSetChartFont GE.YAxis.TicFont%@NL@%
  8056. %@NL@%
  8057. %@AB@%                        ' If it is a category axis then add longest category label:%@AE@%%@NL@%
  8058.                         IF GP.YMode = cCategory THEN%@NL@%
  8059.                                 DLeft% = DLeft% + clMaxStrLen%(Cat$(), 1, GP.NVals) + .5 * GFI.MaxWidth%@NL@%
  8060. %@NL@%
  8061. %@AB@%                        ' If it a value axis just add characters for label (plus 1/2 for%@AE@%%@NL@%
  8062. %@AB@%                        ' spacing):%@AE@%%@NL@%
  8063.                         ELSE%@NL@%
  8064.                                 DLeft% = DLeft% + GP.ValLenY + (.5 * GFI.MaxWidth)%@NL@%
  8065.                         END IF%@NL@%
  8066. %@NL@%
  8067.                 ELSEIF GP.XMode = cValue AND GE.XAxis.Labeled = cYes THEN%@NL@%
  8068. %@NL@%
  8069. %@AB@%                        ' Then space over 1/2 of the leftmost label on the X Axis if it's%@AE@%%@NL@%
  8070. %@AB@%                        ' a value axis; if it's a category axis assume the label will be%@AE@%%@NL@%
  8071. %@AB@%                        ' correct:%@AE@%%@NL@%
  8072.                         DLeft% = DLeft% + GP.ValLenX \ 2%@NL@%
  8073.                 END IF%@NL@%
  8074.         END IF%@NL@%
  8075. %@NL@%
  8076. %@AB@%        ' *** RIGHT%@AE@%%@NL@%
  8077. %@AB@%        ' For the right, space over 8 pixels from the right:%@AE@%%@NL@%
  8078.         DRight% = 12%@NL@%
  8079. %@NL@%
  8080. %@AB@%        ' Then space over 1/2 of the rightmost label on the X Axis if it's%@AE@%%@NL@%
  8081. %@AB@%        ' a value axis; if it's a category axis assume the label will be%@AE@%%@NL@%
  8082. %@AB@%        ' correct:%@AE@%%@NL@%
  8083.         IF GP.XMode = cValue AND GE.XAxis.Labeled = cYes THEN%@NL@%
  8084.                 DRight% = DRight% + (GP.ValLenX) \ 2%@NL@%
  8085.         END IF%@NL@%
  8086. %@NL@%
  8087.         DRight% = GP.ChartWid - DRight%%@NL@%
  8088. %@NL@%
  8089. %@AB@%        ' *** YTIC MARKS%@AE@%%@NL@%
  8090. %@AB@%        ' Finally, adjust the window coordinates for tic marks (if it's not a%@AE@%%@NL@%
  8091. %@AB@%        ' pie chart):%@AE@%%@NL@%
  8092.         IF GE.ChartType <> cPie THEN%@NL@%
  8093.                 IF GE.YAxis.Labeled = cYes THEN%@NL@%
  8094.                         DLeft% = DRight% - (DRight% - DLeft%) / (1 + cTicSize)%@NL@%
  8095.                 END IF%@NL@%
  8096.         END IF%@NL@%
  8097. %@NL@%
  8098. %@AB@%        ' *** LEGEND%@AE@%%@NL@%
  8099. %@AB@%        ' Account for the legend if its on the right:%@AE@%%@NL@%
  8100.         IF GE.Legend.Legend = cYes AND GP.MSeries = cYes THEN%@NL@%
  8101.                 IF GE.Legend.Place = cRight THEN%@NL@%
  8102.                         A% = GE.Legend.LegendWindow.X1%@NL@%
  8103.                         DRight% = DRight% - ABS(GP.ChartWid - A%)%@NL@%
  8104.                 END IF%@NL@%
  8105.         END IF%@NL@%
  8106. %@NL@%
  8107. %@AB@%        ' Now we have DLeft%, DRight% we can check if the labels fit on the%@AE@%%@NL@%
  8108. %@AB@%        ' X axis or if we need to put them on two rows:%@AE@%%@NL@%
  8109.         GP.XStagger = cFalse%@NL@%
  8110.         IF GP.XMode = cCategory AND GE.ChartType <> cPie THEN%@NL@%
  8111.                 clSetChartFont GE.XAxis.TicFont%@NL@%
  8112.                 TicInterval% = (DRight% - DLeft%) \ GP.NVals%@NL@%
  8113.                 IF clMaxStrLen%(Cat$(), 1, GP.NVals) + .5 * GFI.MaxWidth > TicInterval% THEN%@NL@%
  8114.                         GP.XStagger = cTrue%@NL@%
  8115.                 END IF%@NL@%
  8116.         END IF%@NL@%
  8117. %@NL@%
  8118. %@AB@%        ' If we do have to stagger, check if there is enough space to the%@AE@%%@NL@%
  8119. %@AB@%        ' left and right for long categories.  Make adjustments as necessary:%@AE@%%@NL@%
  8120.         IF GP.XStagger THEN%@NL@%
  8121.                 LenLeft% = GetGTextLen%(Cat$(1)) + GFI.AvgWidth%@NL@%
  8122.                 LenRight% = GetGTextLen%(Cat$(GP.NVals)) + GFI.AvgWidth%@NL@%
  8123.                 SizeRight% = cTrue%@NL@%
  8124.                 SizeLeft% = cTrue%@NL@%
  8125.                 OldRight% = DRight%%@NL@%
  8126.                 OldLeft% = DLeft%%@NL@%
  8127.                 DO WHILE SizeRight% OR SizeLeft%%@NL@%
  8128.                         IF LenRight% - TicInterval% > 2 * (GP.ChartWid - DRight%) AND 2 * (GP.ChartWid - DRight%) < TicInterval% THEN%@NL@%
  8129.                                 SizeRight% = cTrue%@NL@%
  8130.                         ELSE%@NL@%
  8131.                                 SizeRight% = cFalse%@NL@%
  8132.                         END IF%@NL@%
  8133.                         IF SizeRight% THEN%@NL@%
  8134.                                 TicInterval% = (2 * (GP.ChartWid - DLeft%) - LenRight%) \ (2 * GP.NVals - 1)%@NL@%
  8135.                                 IF LenRight% > 2 * TicInterval% THEN%@NL@%
  8136.                                         TicInterval% = (GP.ChartWid - DLeft%) / (GP.NVals + .5)%@NL@%
  8137.                                 END IF%@NL@%
  8138.                                 DRight% = DLeft% + GP.NVals * TicInterval%%@NL@%
  8139.                         END IF%@NL@%
  8140.                         IF LenLeft% - TicInterval% > 2 * DLeft% AND 2 * DLeft% < TicInterval% THEN%@NL@%
  8141.                                 SizeLeft% = cTrue%@NL@%
  8142.                         ELSE%@NL@%
  8143.                                 SizeLeft% = cFalse%@NL@%
  8144.                         END IF%@NL@%
  8145.                         IF SizeLeft% THEN%@NL@%
  8146.                                 TicInterval% = (2 * DRight% - LenLeft%) \ (2 * GP.NVals - 1)%@NL@%
  8147.                                 IF LenLeft% > 2 * TicInterval% THEN%@NL@%
  8148.                                         TicInterval% = DRight% / (GP.NVals + .5)%@NL@%
  8149.                                 END IF%@NL@%
  8150.                                 DLeft% = DRight% - GP.NVals * TicInterval%%@NL@%
  8151.                         END IF%@NL@%
  8152. %@NL@%
  8153. %@AB@%                        ' Make sure we haven't gone too far on either side:%@AE@%%@NL@%
  8154.                         IF DRight% > OldRight% THEN%@NL@%
  8155.                                 DRight% = OldRight%%@NL@%
  8156.                         END IF%@NL@%
  8157.                         IF DLeft% < OldLeft% THEN%@NL@%
  8158.                                 DLeft% = OldLeft%%@NL@%
  8159.                         END IF%@NL@%
  8160. %@NL@%
  8161. %@AB@%                        ' Check if there has been a change, if not, we are done:%@AE@%%@NL@%
  8162.                         IF ABS(ChangeRight% - DRight%) + ABS(ChangeLeft% - DLeft%) > 0 THEN%@NL@%
  8163.                                 EXIT DO%@NL@%
  8164.                         ELSE%@NL@%
  8165.                                 ChangeRight% = DRight%%@NL@%
  8166.                                 ChangeLeft% = DLeft%%@NL@%
  8167.                         END IF%@NL@%
  8168.                 LOOP%@NL@%
  8169.         END IF%@NL@%
  8170. %@NL@%
  8171. %@AB@%        ' *** BOTTOM%@AE@%%@NL@%
  8172.         DBot% = XTitleLayout.TotalSize%@NL@%
  8173. %@NL@%
  8174. %@AB@%        ' If axis is labeled (and not a pie chart), add row for tic%@AE@%%@NL@%
  8175. %@AB@%        ' labels + 1/2 row spacing:%@AE@%%@NL@%
  8176.         IF GE.XAxis.Labeled = cYes AND GE.ChartType <> cPie THEN%@NL@%
  8177.                 IF GP.XStagger = cTrue THEN%@NL@%
  8178.                         DBot% = DBot% + 3 * GFI.PixHeight%@NL@%
  8179.                 ELSE%@NL@%
  8180.                         DBot% = DBot% + 1.5 * GFI.PixHeight%@NL@%
  8181.                 END IF%@NL@%
  8182.         END IF%@NL@%
  8183. %@NL@%
  8184. %@AB@%        ' Make the setting relative to the chart window:%@AE@%%@NL@%
  8185.         DBot% = GP.ChartHgt - 1 - DBot%%@NL@%
  8186. %@NL@%
  8187. %@NL@%
  8188. %@AB@%        ' *** XTIC MARKS%@AE@%%@NL@%
  8189. %@AB@%        ' Finally, adjust the window coordinates for tic marks (if it's not a%@AE@%%@NL@%
  8190. %@AB@%        ' pie chart):%@AE@%%@NL@%
  8191.         IF GE.ChartType <> cPie THEN%@NL@%
  8192.                 IF GE.XAxis.Labeled = cYes THEN%@NL@%
  8193.                         DBot% = DTop% + (DBot% - DTop%) / (1 + cTicSize)%@NL@%
  8194.                 END IF%@NL@%
  8195. %@NL@%
  8196.         END IF%@NL@%
  8197. %@NL@%
  8198. %@AB@%        ' *** LEGEND%@AE@%%@NL@%
  8199. %@AB@%        ' Account for the legend if its on the bottom:%@AE@%%@NL@%
  8200.         IF GE.Legend.Legend = cYes AND GP.MSeries = cYes THEN%@NL@%
  8201.                 IF GE.Legend.Place = cBottom THEN%@NL@%
  8202.                         A% = GE.Legend.LegendWindow.Y1%@NL@%
  8203.                         DBot% = DBot% - ABS(GP.ChartHgt - A%)%@NL@%
  8204.                 END IF%@NL@%
  8205.         END IF%@NL@%
  8206. %@NL@%
  8207. %@AB@%        ' Install values in the DataWindow definition:%@AE@%%@NL@%
  8208.         GE.DataWindow.X1 = DLeft%%@NL@%
  8209.         GE.DataWindow.X2 = DRight%%@NL@%
  8210.         GE.DataWindow.Y1 = DTop%%@NL@%
  8211.         GE.DataWindow.Y2 = DBot%%@NL@%
  8212. %@NL@%
  8213. %@AB@%        ' If the window is invalid then set error:%@AE@%%@NL@%
  8214.         IF DLeft% >= DRight% OR DTop% >= DBot% THEN%@NL@%
  8215.                 clSetError cBadDataWindow%@NL@%
  8216.         END IF%@NL@%
  8217. %@NL@%
  8218. END SUB%@NL@%
  8219. %@NL@%
  8220. %@AB@%'=== clSpaceTics - Calculates TicInterval%@AE@%%@NL@%
  8221. %@AB@%'%@AE@%%@NL@%
  8222. %@AB@%'  Arguments:%@AE@%%@NL@%
  8223. %@AB@%'     None%@AE@%%@NL@%
  8224. %@AB@%'%@AE@%%@NL@%
  8225. %@AB@%'  Return Values:%@AE@%%@NL@%
  8226. %@AB@%'     The TicInterval will be altered%@AE@%%@NL@%
  8227. %@AB@%'%@AE@%%@NL@%
  8228. %@AB@%'  Remarks:%@AE@%%@NL@%
  8229. %@AB@%'     The TicInterval is the distance between tic marks in WORLD%@AE@%%@NL@%
  8230. %@AB@%'     coordinates (i.e. the coordinates your data are in)%@AE@%%@NL@%
  8231. %@AB@%'%@AE@%%@NL@%
  8232. %@AB@%'=================================================================%@AE@%%@NL@%
  8233. SUB clSpaceTics%@NL@%
  8234. SHARED GE AS ChartEnvironment, GP AS GlobalParams%@NL@%
  8235. SHARED GFI AS FontInfo%@NL@%
  8236. %@NL@%
  8237. %@AB@%        ' X-Axis:%@AE@%%@NL@%
  8238. %@AB@%        ' Calculate the length of the axis and of the longest tic label.  Then,%@AE@%%@NL@%
  8239. %@AB@%        ' use that information to calculate the number of tics that will fit:%@AE@%%@NL@%
  8240.         clSetChartFont GE.XAxis.TicFont%@NL@%
  8241.         AxisLen% = GE.DataWindow.X2 - GE.DataWindow.X1 + 1%@NL@%
  8242.         TicWid% = GP.ValLenX + GFI.MaxWidth%@NL@%
  8243.         clSpaceTicsA GE.XAxis, GP.XMode, AxisLen%, TicWid%%@NL@%
  8244. %@NL@%
  8245. %@AB@%        ' Y-Axis:%@AE@%%@NL@%
  8246. %@AB@%        ' Same procedure as above:%@AE@%%@NL@%
  8247.         clSetChartFont GE.YAxis.TicFont%@NL@%
  8248.         AxisLen% = GE.DataWindow.Y2 - GE.DataWindow.Y1 + 1%@NL@%
  8249.         TicWid% = 2 * GFI.Ascent%@NL@%
  8250.         clSpaceTicsA GE.YAxis, GP.YMode, AxisLen%, TicWid%%@NL@%
  8251. %@NL@%
  8252. END SUB%@NL@%
  8253. %@NL@%
  8254. %@AB@%'=== clSpaceTicsA - Figures out TicInterval for an axis%@AE@%%@NL@%
  8255. %@AB@%'%@AE@%%@NL@%
  8256. %@AB@%'  Arguments:%@AE@%%@NL@%
  8257. %@AB@%'     Axis     -  An AxisType variable to space tics for%@AE@%%@NL@%
  8258. %@AB@%'%@AE@%%@NL@%
  8259. %@AB@%'     AxisMode%-  cCategory or cValue%@AE@%%@NL@%
  8260. %@AB@%'%@AE@%%@NL@%
  8261. %@AB@%'     AxisLen% -  Length of the axis in pixels%@AE@%%@NL@%
  8262. %@AB@%'%@AE@%%@NL@%
  8263. %@AB@%'  Return Values:%@AE@%%@NL@%
  8264. %@AB@%'     The TicInterval value may be changed for an axis%@AE@%%@NL@%
  8265. %@AB@%'%@AE@%%@NL@%
  8266. %@AB@%'  Remarks:%@AE@%%@NL@%
  8267. %@AB@%'     The TicInterval is the distance between tic marks in adjusted world%@AE@%%@NL@%
  8268. %@AB@%'     coordinates (i.e. the coordinates your data are in scaled by%@AE@%%@NL@%
  8269. %@AB@%'     ScaleFactor and adjusted by LogBase if it is a log axis).%@AE@%%@NL@%
  8270. %@AB@%'%@AE@%%@NL@%
  8271. %@AB@%'=================================================================%@AE@%%@NL@%
  8272. SUB clSpaceTicsA (Axis AS AxisType, AxisMode%, AxisLen%, TicWid%)%@NL@%
  8273. SHARED GP AS GlobalParams%@NL@%
  8274. %@NL@%
  8275. %@AB@%        ' If this is a category axis the tic interval is 1%@AE@%%@NL@%
  8276. %@AB@%        ' divided by the number-of-categories:%@AE@%%@NL@%
  8277.         IF AxisMode% = cCategory THEN%@NL@%
  8278.                 Axis.TicInterval = 1 / GP.NVals%@NL@%
  8279.                 EXIT SUB%@NL@%
  8280.         END IF%@NL@%
  8281. %@NL@%
  8282. %@AB@%        ' Otherwise, if we're supposed to scale this axis then the tic interval%@AE@%%@NL@%
  8283. %@AB@%        ' depends on how many will fit and some aesthetic considerations:%@AE@%%@NL@%
  8284.         IF Axis.AutoScale = cYes THEN%@NL@%
  8285. %@NL@%
  8286. %@AB@%                ' Figure which is bigger in absolute value between scale maximum%@AE@%%@NL@%
  8287. %@AB@%                ' and minimum:%@AE@%%@NL@%
  8288.                 MaxRange = ABS(Axis.ScaleMax)%@NL@%
  8289.                 IF ABS(Axis.ScaleMin) > MaxRange THEN MaxRange = ABS(Axis.ScaleMin)%@NL@%
  8290. %@NL@%
  8291. %@AB@%                ' Calculate the maximum number of tic marks that will fit:%@AE@%%@NL@%
  8292.                 MaxTics% = INT(AxisLen% / TicWid%)%@NL@%
  8293. %@NL@%
  8294. %@AB@%                ' If the maximum number of tics is one or less set the tic%@AE@%%@NL@%
  8295. %@AB@%                ' interval to the axis range and the number of tics to one:%@AE@%%@NL@%
  8296.                 IF MaxTics% <= 1 THEN%@NL@%
  8297.                         NumTics% = 1%@NL@%
  8298.                         TicInterval = Axis.ScaleMax - Axis.ScaleMin%@NL@%
  8299. %@NL@%
  8300.                 ELSE%@NL@%
  8301. %@AB@%                        ' Guess that the tic interval is equal to 1/10th of the order%@AE@%%@NL@%
  8302. %@AB@%                        ' of magnitude of the largest of the scale max or min:%@AE@%%@NL@%
  8303.                         TicInterval = .1 * 10 ^ INT(LOG(MaxRange) / LOG(10!))%@NL@%
  8304. %@NL@%
  8305. %@AB@%                        ' If this doesn't result in too many tic marks then OK. Otherwise%@AE@%%@NL@%
  8306. %@AB@%                        ' multiply the tic interval by 2 and 5 alternatively until the%@AE@%%@NL@%
  8307. %@AB@%                        ' number of tic marks falls into the acceptable range.%@AE@%%@NL@%
  8308.                         NextStep% = 2%@NL@%
  8309.                         ScaleRange = Axis.ScaleMax - Axis.ScaleMin%@NL@%
  8310.                         DO%@NL@%
  8311.                                 NumTics% = -INT(-ScaleRange / TicInterval)%@NL@%
  8312.                                 IF (NumTics% <= MaxTics%) THEN EXIT DO%@NL@%
  8313.                                 TicInterval = TicInterval * NextStep%%@NL@%
  8314.                                 NextStep% = 7 - NextStep%%@NL@%
  8315.                         LOOP UNTIL NumTics% <= MaxTics%%@NL@%
  8316.                 END IF%@NL@%
  8317. %@NL@%
  8318. %@AB@%                ' Set Axis.TicInterval and adjust scale maximum and minimum:%@AE@%%@NL@%
  8319.                 Axis.TicInterval = TicInterval%@NL@%
  8320.                 IF ABS(TicInterval) < 1 THEN%@NL@%
  8321.                         Axis.TicDecimals = -INT(-ABS(LOG(1.1 * TicInterval) / LOG(10!)))%@NL@%
  8322.                 END IF%@NL@%
  8323. %@NL@%
  8324.                 Axis.ScaleMax = -INT(-Axis.ScaleMax / TicInterval) * TicInterval%@NL@%
  8325.                 Axis.ScaleMin = INT(Axis.ScaleMin / TicInterval) * TicInterval%@NL@%
  8326.         END IF%@NL@%
  8327. %@NL@%
  8328. END SUB%@NL@%
  8329. %@NL@%
  8330. %@AB@%'=== clTitleXAxis - Draws titles on X axis (AxisTitle and ScaleTitle)%@AE@%%@NL@%
  8331. %@AB@%'%@AE@%%@NL@%
  8332. %@AB@%'  Arguments:%@AE@%%@NL@%
  8333. %@AB@%'     Axis  -  AxisType variable describing axis%@AE@%%@NL@%
  8334. %@AB@%'%@AE@%%@NL@%
  8335. %@AB@%'     X1%   -  Left of DataWindow%@AE@%%@NL@%
  8336. %@AB@%'%@AE@%%@NL@%
  8337. %@AB@%'     X2%   -  Right of DataWindow%@AE@%%@NL@%
  8338. %@AB@%'%@AE@%%@NL@%
  8339. %@AB@%'     YBoundry%   -  Top boundry of title block%@AE@%%@NL@%
  8340. %@AB@%'%@AE@%%@NL@%
  8341. %@AB@%'=================================================================%@AE@%%@NL@%
  8342. SUB clTitleXAxis (Axis AS AxisType, X1%, X2%, YBoundry%)%@NL@%
  8343. SHARED GFI AS FontInfo%@NL@%
  8344. SHARED XTitleLayout AS TitleLayout%@NL@%
  8345. %@NL@%
  8346.         CH% = GFI.PixHeight%@NL@%
  8347.         CW% = GFI.MaxWidth%@NL@%
  8348. %@NL@%
  8349. %@AB@%        ' Set position of first title:%@AE@%%@NL@%
  8350.         Y% = YBoundry% + XTitleLayout.Top%@NL@%
  8351. %@NL@%
  8352. %@AB@%        ' Loop through the two titles (AxisTitle and ScaleTitle), printing%@AE@%%@NL@%
  8353. %@AB@%        ' them if they aren't blank:%@AE@%%@NL@%
  8354.         FOR i% = 1 TO 2%@NL@%
  8355. %@NL@%
  8356. %@AB@%                ' Get the test, color, and justification for the title to be printed:%@AE@%%@NL@%
  8357.                 SELECT CASE i%%@NL@%
  8358. %@NL@%
  8359.                         CASE 1:  ' AxisTitle%@NL@%
  8360.                                 Txt$ = Axis.AxisTitle.Title%@NL@%
  8361.                                 C% = Axis.AxisTitle.TitleColor%@NL@%
  8362.                                 J% = Axis.AxisTitle.Justify%@NL@%
  8363.                                 F% = Axis.AxisTitle.TitleFont%@NL@%
  8364.                                 Lead% = XTitleLayout.Middle%@NL@%
  8365. %@NL@%
  8366.                         CASE 2:  ' ScaleTitle%@NL@%
  8367.                                 Txt$ = Axis.ScaleTitle.Title%@NL@%
  8368.                                 C% = Axis.ScaleTitle.TitleColor%@NL@%
  8369.                                 J% = Axis.ScaleTitle.Justify%@NL@%
  8370.                                 F% = Axis.ScaleTitle.TitleFont%@NL@%
  8371.                                 Lead% = XTitleLayout.Bottom%@NL@%
  8372. %@NL@%
  8373.                 END SELECT%@NL@%
  8374.                 clSetChartFont F%%@NL@%
  8375.                 Txt$ = RTRIM$(Txt$)%@NL@%
  8376.                 TxtLen% = GetGTextLen(Txt$)%@NL@%
  8377. %@NL@%
  8378. %@AB@%                ' If the title isn't all blank:%@AE@%%@NL@%
  8379.                 IF TxtLen% <> 0 THEN%@NL@%
  8380. %@NL@%
  8381. %@AB@%                        ' Set the title's color:%@AE@%%@NL@%
  8382.                         clSetCharColor C%%@NL@%
  8383. %@NL@%
  8384. %@AB@%                        ' Calculate x position of title's first character depending on%@AE@%%@NL@%
  8385. %@AB@%                        ' the justification flag:%@AE@%%@NL@%
  8386.                         SELECT CASE J%%@NL@%
  8387.                                 CASE cLeft:   X% = X1%%@NL@%
  8388.                                 CASE cCenter: X% = ((X1% + X2%) - TxtLen%) / 2%@NL@%
  8389.                                 CASE ELSE:    X% = X2% - TxtLen%%@NL@%
  8390.                         END SELECT%@NL@%
  8391. %@NL@%
  8392. %@AB@%                        ' Write out the text:%@AE@%%@NL@%
  8393.                         clHPrint X%, Y%, Txt$%@NL@%
  8394. %@NL@%
  8395. %@AB@%                        ' Move down to the next title position:%@AE@%%@NL@%
  8396.                         Y% = Y% + GFI.PixHeight + XTitleLayout.Middle%@NL@%
  8397. %@NL@%
  8398.                 END IF%@NL@%
  8399. %@NL@%
  8400.         NEXT i%%@NL@%
  8401. %@NL@%
  8402. END SUB%@NL@%
  8403. %@NL@%
  8404. %@AB@%'=== clTitleYAxis - Draws titles on Y axis (AxisTitle and ScaleTitle)%@AE@%%@NL@%
  8405. %@AB@%'%@AE@%%@NL@%
  8406. %@AB@%'  Arguments:%@AE@%%@NL@%
  8407. %@AB@%'     Axis  -  AxisType variable describing axis%@AE@%%@NL@%
  8408. %@AB@%'%@AE@%%@NL@%
  8409. %@AB@%'     Y1%   -  Top of DataWindow%@AE@%%@NL@%
  8410. %@AB@%'%@AE@%%@NL@%
  8411. %@AB@%'     Y2%   -  Bottom of DataWindow%@AE@%%@NL@%
  8412. %@AB@%'%@AE@%%@NL@%
  8413. %@AB@%'  Return Values:%@AE@%%@NL@%
  8414. %@AB@%'%@AE@%%@NL@%
  8415. %@AB@%'=================================================================%@AE@%%@NL@%
  8416. SUB clTitleYAxis (Axis AS AxisType, Y1%, Y2%) STATIC%@NL@%
  8417. SHARED GFI AS FontInfo%@NL@%
  8418. SHARED YTitleLayout AS TitleLayout%@NL@%
  8419. %@NL@%
  8420. %@NL@%
  8421. %@AB@%        ' Set position for first title:%@AE@%%@NL@%
  8422.         X% = YTitleLayout.Top%@NL@%
  8423. %@NL@%
  8424. %@AB@%        ' Loop through the two titles (AxisTitle and ScaleTitle), printing%@AE@%%@NL@%
  8425. %@AB@%        ' them if they aren't blank:%@AE@%%@NL@%
  8426.         FOR i% = 1 TO 2%@NL@%
  8427. %@NL@%
  8428. %@AB@%                ' Get the test, color, and justification for the title to be printed:%@AE@%%@NL@%
  8429.                 SELECT CASE i%%@NL@%
  8430. %@NL@%
  8431.                         CASE 1:  ' AxisTitle%@NL@%
  8432.                                 Txt$ = Axis.AxisTitle.Title%@NL@%
  8433.                                 C% = Axis.AxisTitle.TitleColor%@NL@%
  8434.                                 J% = Axis.AxisTitle.Justify%@NL@%
  8435.                                 F% = Axis.AxisTitle.TitleFont%@NL@%
  8436.                                 Lead% = YTitleLayout.TitleOne + YTitleLayout.Middle%@NL@%
  8437. %@NL@%
  8438.                         CASE 2:  ' ScaleTitle%@NL@%
  8439.                                 Txt$ = Axis.ScaleTitle.Title%@NL@%
  8440.                                 C% = Axis.ScaleTitle.TitleColor%@NL@%
  8441.                                 J% = Axis.ScaleTitle.Justify%@NL@%
  8442.                                 F% = Axis.ScaleTitle.TitleFont%@NL@%
  8443.                                 Lead% = 0%@NL@%
  8444. %@NL@%
  8445.                 END SELECT%@NL@%
  8446.                 clSetChartFont F%%@NL@%
  8447.                 Txt$ = RTRIM$(Txt$)%@NL@%
  8448.                 TxtLen% = GetGTextLen(Txt$)%@NL@%
  8449. %@NL@%
  8450.                 IF TxtLen% <> 0 THEN%@NL@%
  8451. %@NL@%
  8452. %@AB@%                        ' Set title's color:%@AE@%%@NL@%
  8453.                         clSetCharColor C%%@NL@%
  8454. %@NL@%
  8455. %@AB@%                        ' Calculate y position of title's first character depending on%@AE@%%@NL@%
  8456. %@AB@%                        ' the justification flag:%@AE@%%@NL@%
  8457.                         SELECT CASE J%%@NL@%
  8458.                                 CASE cLeft:   Y% = Y2%%@NL@%
  8459.                                 CASE cCenter: Y% = ((Y1% + Y2%) + TxtLen%) / 2%@NL@%
  8460.                                 CASE ELSE:    Y% = Y1% + (TxtLen% - 1)%@NL@%
  8461.                         END SELECT%@NL@%
  8462. %@NL@%
  8463. %@AB@%                        ' Write out the text:%@AE@%%@NL@%
  8464.                         clVPrint X%, Y%, Txt$%@NL@%
  8465. %@NL@%
  8466. %@AB@%                        ' Move to next title position:%@AE@%%@NL@%
  8467.                         X% = X% + Lead%%@NL@%
  8468. %@NL@%
  8469.                 END IF%@NL@%
  8470. %@NL@%
  8471.         NEXT i%%@NL@%
  8472. %@NL@%
  8473. END SUB%@NL@%
  8474. %@NL@%
  8475. %@AB@%'=== clUnFlagSystem - Sets GP.SysFlag to cNo%@AE@%%@NL@%
  8476. %@AB@%'%@AE@%%@NL@%
  8477. %@AB@%'  Arguments:%@AE@%%@NL@%
  8478. %@AB@%'     None%@AE@%%@NL@%
  8479. %@AB@%'%@AE@%%@NL@%
  8480. %@AB@%'  Return Values:%@AE@%%@NL@%
  8481. %@AB@%'     Alters the value of GP.SysFlag%@AE@%%@NL@%
  8482. %@AB@%'%@AE@%%@NL@%
  8483. %@AB@%'=================================================================%@AE@%%@NL@%
  8484. SUB clUnFlagSystem%@NL@%
  8485. SHARED GP AS GlobalParams%@NL@%
  8486. %@NL@%
  8487.         GP.SysFlag = cNo%@NL@%
  8488. %@NL@%
  8489. END SUB%@NL@%
  8490. %@NL@%
  8491. %@AB@%'=== clVal2Str$ - Converts a single precision value to a string%@AE@%%@NL@%
  8492. %@AB@%'%@AE@%%@NL@%
  8493. %@AB@%'  Arguments:%@AE@%%@NL@%
  8494. %@AB@%'     X        -  The value to convert%@AE@%%@NL@%
  8495. %@AB@%'%@AE@%%@NL@%
  8496. %@AB@%'     Places%  -  The number of places after the decimal to produce%@AE@%%@NL@%
  8497. %@AB@%'%@AE@%%@NL@%
  8498. %@AB@%'     Format%  -  1 For normal, other than 1 for exponential%@AE@%%@NL@%
  8499. %@AB@%'%@AE@%%@NL@%
  8500. %@AB@%'  Return Values:%@AE@%%@NL@%
  8501. %@AB@%'     Returns a string representation of the input number%@AE@%%@NL@%
  8502. %@AB@%'%@AE@%%@NL@%
  8503. %@AB@%'=================================================================%@AE@%%@NL@%
  8504. FUNCTION clVal2Str$ (X, Places%, Format%)%@NL@%
  8505. %@NL@%
  8506. %@AB@%        ' Make a local copy of the value:%@AE@%%@NL@%
  8507.         XX = ABS(X)%@NL@%
  8508. %@NL@%
  8509. %@AB@%        ' Force format to exponential if that is specified or number is%@AE@%%@NL@%
  8510. %@AB@%        ' bigger than a long integer will hold (2^31-1):%@AE@%%@NL@%
  8511.         IF Format% <> cNormFormat OR XX >= 2 ^ 31 THEN%@NL@%
  8512. %@NL@%
  8513. %@AB@%                ' For exponential format calculate the exponent that will make%@AE@%%@NL@%
  8514. %@AB@%                ' one decimal to left of decimal place.  This is done by truncating%@AE@%%@NL@%
  8515. %@AB@%                ' the log (base 10) of XX:%@AE@%%@NL@%
  8516.                 IF XX = 0 THEN ExpX = 0 ELSE ExpX = INT(LOG(XX) / LOG(10))%@NL@%
  8517.                 XX = XX / (10 ^ ExpX)%@NL@%
  8518. %@NL@%
  8519. %@AB@%                ' If no decimals are specified then a number of 9.5x will be%@AE@%%@NL@%
  8520. %@AB@%                ' rounded up to 10 leaving two places to left of decimal so check%@AE@%%@NL@%
  8521. %@AB@%                ' for that and if that occurs divide number by 10 and add 1 to exponent:%@AE@%%@NL@%
  8522.                 IF Places% <= 0 AND CLNG(XX) > 9 THEN%@NL@%
  8523.                         XX = XX / 10%@NL@%
  8524.                         ExpX = ExpX + 1%@NL@%
  8525.                 END IF%@NL@%
  8526. %@NL@%
  8527.         END IF%@NL@%
  8528. %@NL@%
  8529. %@AB@%        ' If no decimal places are specified then generate a rounded integer:%@AE@%%@NL@%
  8530.         IF Places% <= 0 THEN%@NL@%
  8531.                 ValStr$ = LTRIM$(STR$(CLNG(XX)))%@NL@%
  8532. %@NL@%
  8533. %@AB@%        ' If decimal places are called for, round number to requisite number of%@AE@%%@NL@%
  8534. %@AB@%        ' decimals and generate string:%@AE@%%@NL@%
  8535.         ELSE%@NL@%
  8536. %@NL@%
  8537. %@AB@%                ' Limit places after decimal to six:%@AE@%%@NL@%
  8538.                 DP% = Places%%@NL@%
  8539.                 IF DP% > 6 THEN DP% = 6%@NL@%
  8540.                 RF% = 10 ^ DP%%@NL@%
  8541. %@NL@%
  8542. %@AB@%                ' Figure out integer portion:%@AE@%%@NL@%
  8543.                 IntX = FIX(XX)%@NL@%
  8544. %@NL@%
  8545. %@AB@%                ' Round the fractional part to correct number of decimals.  If%@AE@%%@NL@%
  8546. %@AB@%                ' the fraction carries to the 1's place in the rounding%@AE@%%@NL@%
  8547. %@AB@%                ' adjust IntX by adding 1:%@AE@%%@NL@%
  8548.                 FracX = CLNG((1 + XX - IntX) * RF%)%@NL@%
  8549.                 IF FracX >= 2 * RF% THEN%@NL@%
  8550.                         IntX = IntX + 1%@NL@%
  8551.                 END IF%@NL@%
  8552. %@NL@%
  8553. %@AB@%                'Finally, generate the output string:%@AE@%%@NL@%
  8554.                 ValStr$ = LTRIM$(STR$(IntX)) + "." + MID$(STR$(FracX), 3)%@NL@%
  8555. %@NL@%
  8556.         END IF%@NL@%
  8557. %@NL@%
  8558. %@AB@%        ' Add exponent ending if format is exponent:%@AE@%%@NL@%
  8559.         IF Format% <> cNormFormat OR ABS(X) > 2 ^ 31 THEN%@NL@%
  8560.                 ValStr$ = ValStr$ + "E"%@NL@%
  8561.                 IF ExpX >= 0 THEN ValStr$ = ValStr$ + "+"%@NL@%
  8562.                 ValStr$ = ValStr$ + LTRIM$(STR$(ExpX))%@NL@%
  8563.         END IF%@NL@%
  8564. %@NL@%
  8565. %@AB@%        ' Add minus sign if appropriate:%@AE@%%@NL@%
  8566.         IF X < 0 AND VAL(ValStr$) <> 0 THEN ValStr$ = "-" + ValStr$%@NL@%
  8567.         clVal2Str$ = ValStr$%@NL@%
  8568. %@NL@%
  8569. END FUNCTION%@NL@%
  8570. %@NL@%
  8571. %@AB@%'=== clVPrint - Prints text vertically on the screen%@AE@%%@NL@%
  8572. %@AB@%'%@AE@%%@NL@%
  8573. %@AB@%'  Arguments:%@AE@%%@NL@%
  8574. %@AB@%'     X     -  X position of lower left of first char (in absolute screen%@AE@%%@NL@%
  8575. %@AB@%'              coordinates)%@AE@%%@NL@%
  8576. %@AB@%'%@AE@%%@NL@%
  8577. %@AB@%'     Y     -  Y position of lower left of first char (in absolute screen%@AE@%%@NL@%
  8578. %@AB@%'              coordinates)%@AE@%%@NL@%
  8579. %@AB@%'%@AE@%%@NL@%
  8580. %@AB@%'     Txt$  -  Text to print%@AE@%%@NL@%
  8581. %@AB@%'%@AE@%%@NL@%
  8582. %@AB@%'  Return Values:%@AE@%%@NL@%
  8583. %@AB@%'     None%@AE@%%@NL@%
  8584. %@AB@%'%@AE@%%@NL@%
  8585. %@AB@%'=================================================================%@AE@%%@NL@%
  8586. SUB clVPrint (X%, Y%, Txt$)%@NL@%
  8587. %@NL@%
  8588. %@AB@%        ' Map the input coordinates relative to the current viewport:%@AE@%%@NL@%
  8589.         X = PMAP(X%, 2)%@NL@%
  8590.         Y = PMAP(Y%, 3)%@NL@%
  8591. %@NL@%
  8592. %@AB@%        ' Print text out vertically:%@AE@%%@NL@%
  8593.         SetGTextDir 1%@NL@%
  8594.         TextLen% = OutGText(X, Y, Txt$)%@NL@%
  8595.         SetGTextDir 0%@NL@%
  8596. %@NL@%
  8597. END SUB%@NL@%
  8598. %@NL@%
  8599. %@AB@%'=== DefaultChart - Sets up the ChartEnvironment variable to generate a%@AE@%%@NL@%
  8600. %@AB@%'                   default chart of the type and style specified%@AE@%%@NL@%
  8601. %@AB@%'%@AE@%%@NL@%
  8602. %@AB@%'  Arguments:%@AE@%%@NL@%
  8603. %@AB@%'     Env        - A ChartEnvironment variable%@AE@%%@NL@%
  8604. %@AB@%'%@AE@%%@NL@%
  8605. %@AB@%'     ChartType  - The chart type desired: 1=Bar, 2=Column, 3=Line,%@AE@%%@NL@%
  8606. %@AB@%'                  4=Scatter, 5=Pie%@AE@%%@NL@%
  8607. %@AB@%'%@AE@%%@NL@%
  8608. %@AB@%'     ChartStyle - The chart style (depends on type, see README file)%@AE@%%@NL@%
  8609. %@AB@%'%@AE@%%@NL@%
  8610. %@AB@%'%@AE@%%@NL@%
  8611. %@AB@%'  Return Values:%@AE@%%@NL@%
  8612. %@AB@%'     Elements of Env variable are set to default values%@AE@%%@NL@%
  8613. %@AB@%'%@AE@%%@NL@%
  8614. %@AB@%'  Remarks:%@AE@%%@NL@%
  8615. %@AB@%'     This subprogram should be called to initialize the ChartEnvironment%@AE@%%@NL@%
  8616. %@AB@%'     variable before a charting routine is called.%@AE@%%@NL@%
  8617. %@AB@%'%@AE@%%@NL@%
  8618. %@AB@%'=================================================================%@AE@%%@NL@%
  8619. SUB DefaultChart (Env AS ChartEnvironment, ChartType AS INTEGER, ChartStyle AS INTEGER)%@NL@%
  8620. %@NL@%
  8621. SHARED DTitle AS TitleType, DWindow AS RegionType%@NL@%
  8622. SHARED DAxis AS AxisType, DLegend AS LegendType%@NL@%
  8623. %@NL@%
  8624. %@AB@%        ' Clear any previous chart errors:%@AE@%%@NL@%
  8625.         clClearError%@NL@%
  8626. %@NL@%
  8627. %@AB@%        ' Check initialization:%@AE@%%@NL@%
  8628.         clChkInit%@NL@%
  8629. %@NL@%
  8630. %@AB@%  ' Put type in environment:%@AE@%%@NL@%
  8631.         IF ChartType < 1 OR ChartType > 5 THEN%@NL@%
  8632.                 clSetError cBadType%@NL@%
  8633.                 EXIT SUB%@NL@%
  8634.         END IF%@NL@%
  8635.         Env.ChartType = ChartType%@NL@%
  8636. %@NL@%
  8637. %@AB@%        ' Put chart style in environment:%@AE@%%@NL@%
  8638.         IF ChartStyle < 1 OR ChartStyle > 2 THEN%@NL@%
  8639.                 clSetError cBadStyle%@NL@%
  8640.                 ChartStyle = 1%@NL@%
  8641.         END IF%@NL@%
  8642.         Env.ChartStyle = ChartStyle%@NL@%
  8643. %@NL@%
  8644. %@AB@%        ' Set elements of chart to default:%@AE@%%@NL@%
  8645.         Env.DataFont = 1%@NL@%
  8646. %@NL@%
  8647.         Env.MainTitle = DTitle%@NL@%
  8648.         Env.SubTitle = DTitle%@NL@%
  8649. %@NL@%
  8650.         Env.ChartWindow = DWindow           ' Chart window is default window%@NL@%
  8651.         Env.ChartWindow.Border = cYes       ' with a border.%@NL@%
  8652. %@NL@%
  8653.         Env.DataWindow = DWindow%@NL@%
  8654. %@NL@%
  8655.         Env.XAxis = DAxis%@NL@%
  8656.         Env.YAxis = DAxis%@NL@%
  8657. %@NL@%
  8658.         Env.Legend = DLegend%@NL@%
  8659. %@NL@%
  8660. END SUB%@NL@%
  8661. %@NL@%
  8662. %@AB@%'=== GetPaletteDef - Changes an entry in the internal palette%@AE@%%@NL@%
  8663. %@AB@%'%@AE@%%@NL@%
  8664. %@AB@%'  Arguments:%@AE@%%@NL@%
  8665. %@AB@%'     C%()     -  Color palette array%@AE@%%@NL@%
  8666. %@AB@%'%@AE@%%@NL@%
  8667. %@AB@%'     S%()     -  Style palette array%@AE@%%@NL@%
  8668. %@AB@%'%@AE@%%@NL@%
  8669. %@AB@%'     P$()     -  Pattern palette array%@AE@%%@NL@%
  8670. %@AB@%'%@AE@%%@NL@%
  8671. %@AB@%'     Char%()  -  Plot character palette array%@AE@%%@NL@%
  8672. %@AB@%'%@AE@%%@NL@%
  8673. %@AB@%'     B%()     -  Border style palette array%@AE@%%@NL@%
  8674. %@AB@%'%@AE@%%@NL@%
  8675. %@AB@%'  Return Values:%@AE@%%@NL@%
  8676. %@AB@%'     Chart error may be set%@AE@%%@NL@%
  8677. %@AB@%'%@AE@%%@NL@%
  8678. %@AB@%'=================================================================%@AE@%%@NL@%
  8679. SUB GetPaletteDef (C() AS INTEGER, s() AS INTEGER, P$(), Char() AS INTEGER, B() AS INTEGER)%@NL@%
  8680. SHARED GP AS GlobalParams%@NL@%
  8681. SHARED PaletteC%(), PaletteS%(), PaletteP$(), PaletteCh%(), PaletteB%()%@NL@%
  8682. %@NL@%
  8683. %@AB@%        ' Reset any outstanding errors:%@AE@%%@NL@%
  8684.         clClearError%@NL@%
  8685. %@NL@%
  8686. %@AB@%        ' Make sure palettes have been initialized:%@AE@%%@NL@%
  8687.         IF NOT GP.PaletteSet THEN%@NL@%
  8688.                 clSetError cPalettesNotSet%@NL@%
  8689.                 EXIT SUB%@NL@%
  8690.         END IF%@NL@%
  8691. %@NL@%
  8692. %@AB@%        ' Make sure the user's palettes are the correct size:%@AE@%%@NL@%
  8693.         clChkPalettes C(), s(), P$(), Char(), B()%@NL@%
  8694.         IF (ChartErr <> 0) THEN EXIT SUB%@NL@%
  8695. %@NL@%
  8696. %@AB@%        ' Replace the palette values with input variables (making sure that%@AE@%%@NL@%
  8697. %@AB@%        ' the color and character numbers are in range):%@AE@%%@NL@%
  8698.         FOR N% = 0 TO cPalLen%@NL@%
  8699.                 C(N%) = PaletteC%(N%)%@NL@%
  8700.                 s(N%) = PaletteS%(N%)%@NL@%
  8701.                 P$(N%) = PaletteP$(N%)%@NL@%
  8702.                 Char(N%) = PaletteCh%(N%)%@NL@%
  8703.                 B(N%) = PaletteB%(N%)%@NL@%
  8704.         NEXT N%%@NL@%
  8705. %@NL@%
  8706. END SUB%@NL@%
  8707. %@NL@%
  8708. %@AB@%'=== GetPattern - Returns a pattern from among 3 pattern palettes%@AE@%%@NL@%
  8709. %@AB@%'%@AE@%%@NL@%
  8710. %@AB@%'  Arguments:%@AE@%%@NL@%
  8711. %@AB@%'     Bits%       -  The number of bits per pixel for the pattern%@AE@%%@NL@%
  8712. %@AB@%'%@AE@%%@NL@%
  8713. %@AB@%'     PatternNum% -  The pattern number to return%@AE@%%@NL@%
  8714. %@AB@%'%@AE@%%@NL@%
  8715. %@AB@%'  Return Values:%@AE@%%@NL@%
  8716. %@AB@%'     Returns a pattern tile from the list below.%@AE@%%@NL@%
  8717. %@AB@%'%@AE@%%@NL@%
  8718. %@AB@%'  Remarks:%@AE@%%@NL@%
  8719. %@AB@%'     Below are three pattern sets.  There is a set of patterns for one, two%@AE@%%@NL@%
  8720. %@AB@%'     and eight bit-per-pixel screens.%@AE@%%@NL@%
  8721. %@AB@%'%@AE@%%@NL@%
  8722. %@AB@%'=================================================================%@AE@%%@NL@%
  8723. FUNCTION GetPattern$ (Bits%, PatternNum%)%@NL@%
  8724. %@NL@%
  8725.         SELECT CASE Bits%%@NL@%
  8726. %@NL@%
  8727. %@AB@%                ' One bit-per-pixel patterns:%@AE@%%@NL@%
  8728.                 CASE 1:%@NL@%
  8729.                         SELECT CASE PatternNum%%@NL@%
  8730.                                 CASE 1: P$ = CHR$(&HFF)%@NL@%
  8731.                                 CASE 2: P$ = CHR$(&H55) + CHR$(&HAA)%@NL@%
  8732.                                 CASE 3: P$ = CHR$(&H33) + CHR$(&HCC)%@NL@%
  8733.                                 CASE 4: P$ = CHR$(&H0) + CHR$(&HE7)%@NL@%
  8734.                                 CASE 5: P$ = CHR$(&H7F) + CHR$(&HBF) + CHR$(&HDF) + CHR$(&HEF) + CHR$(&HF7) + CHR$(&HFB) + CHR$(&HFD) + CHR$(&HFE)%@NL@%
  8735.                                 CASE 6: P$ = CHR$(&H7E) + CHR$(&HBD) + CHR$(&HDB) + CHR$(&HE7) + CHR$(&HE7) + CHR$(&HDB) + CHR$(&HBD) + CHR$(&H7E)%@NL@%
  8736.                                 CASE 7: P$ = CHR$(&HFE) + CHR$(&HFD) + CHR$(&HFB) + CHR$(&HF7) + CHR$(&HEF) + CHR$(&HDF) + CHR$(&HBF) + CHR$(&H7F)%@NL@%
  8737.                                 CASE 8: P$ = CHR$(&H33) + CHR$(&HCC) + CHR$(&HCC) + CHR$(&H33)%@NL@%
  8738.                                 CASE 9: P$ = CHR$(&H0) + CHR$(&HFD) + CHR$(&H0) + CHR$(&HF7) + CHR$(&H0) + CHR$(&HDF) + CHR$(&H0) + CHR$(&H7F)%@NL@%
  8739.                                 CASE 10: P$ = CHR$(&HF) + CHR$(&H87) + CHR$(&HC3) + CHR$(&HE1) + CHR$(&HF0) + CHR$(&H78) + CHR$(&H3C) + CHR$(&H1E)%@NL@%
  8740.                                 CASE 11: P$ = CHR$(&HA8) + CHR$(&H51) + CHR$(&HA2) + CHR$(&H45) + CHR$(&H8A) + CHR$(&H15) + CHR$(&H2A) + CHR$(&H54)%@NL@%
  8741.                                 CASE 12: P$ = CHR$(&HAA) + CHR$(&H55) + CHR$(&H0) + CHR$(&H0) + CHR$(&HAA) + CHR$(&H55) + CHR$(&H0) + CHR$(&H0)%@NL@%
  8742.                                 CASE 13: P$ = CHR$(&H2A) + CHR$(&H15) + CHR$(&H8A) + CHR$(&H45) + CHR$(&HA2) + CHR$(&H51) + CHR$(&HA8) + CHR$(&H54)%@NL@%
  8743.                                 CASE 14: P$ = CHR$(&H88) + CHR$(&H0) + CHR$(&H22) + CHR$(&H0) + CHR$(&H88) + CHR$(&H0) + CHR$(&H22) + CHR$(&H0)%@NL@%
  8744.                                 CASE 15: P$ = CHR$(&HFF) + CHR$(&H0) + CHR$(&HFF) + CHR$(&H0) + CHR$(&HFF) + CHR$(&H0) + CHR$(&HFF) + CHR$(&H0)%@NL@%
  8745.                         END SELECT%@NL@%
  8746. %@NL@%
  8747. %@AB@%                ' Two bit-per-pixel patterns:%@AE@%%@NL@%
  8748.                 CASE 2:%@NL@%
  8749.                         SELECT CASE PatternNum%%@NL@%
  8750.                                 CASE 1: P$ = CHR$(&HFF)%@NL@%
  8751.                                 CASE 2: P$ = CHR$(&HCC) + CHR$(&H33)%@NL@%
  8752.                                 CASE 3: P$ = CHR$(&HF0) + CHR$(&H3C) + CHR$(&HF) + CHR$(&HC3)%@NL@%
  8753.                                 CASE 4: P$ = CHR$(&HF0) + CHR$(&HF)%@NL@%
  8754.                                 CASE 5: P$ = CHR$(&H3) + CHR$(&HC) + CHR$(&H30) + CHR$(&HC0)%@NL@%
  8755.                                 CASE 6: P$ = CHR$(&HFF) + CHR$(&HC)%@NL@%
  8756.                                 CASE 7: P$ = CHR$(&HF0) + CHR$(&HF0) + CHR$(&HF) + CHR$(&HF)%@NL@%
  8757.                                 CASE 8: P$ = CHR$(&HFF) + CHR$(&HC) + CHR$(&H30) + CHR$(&HC0)%@NL@%
  8758.                                 CASE 9: P$ = CHR$(&HC0) + CHR$(&H30) + CHR$(&HC) + CHR$(&H3)%@NL@%
  8759.                                 CASE 10: P$ = CHR$(&HC0) + CHR$(&HC)%@NL@%
  8760.                                 CASE 11: P$ = CHR$(&HCC) + CHR$(&HCC) + CHR$(&H33) + CHR$(&H33)%@NL@%
  8761.                                 CASE 12: P$ = CHR$(&HCC) + CHR$(&HCC) + CHR$(&H0) + CHR$(&H0)%@NL@%
  8762.                                 CASE 13: P$ = CHR$(&HFF) + CHR$(&H33) + CHR$(&H33)%@NL@%
  8763.                                 CASE 14: P$ = CHR$(&HFF) + CHR$(&H0)%@NL@%
  8764.                                 CASE 15: P$ = CHR$(&HCC) + CHR$(&H30) + CHR$(&H0)%@NL@%
  8765.                         END SELECT%@NL@%
  8766. %@NL@%
  8767. %@AB@%                ' Eight bit-per-pixel patterns:%@AE@%%@NL@%
  8768.                 CASE 8:%@NL@%
  8769.                         P$ = CHR$(&HFF)%@NL@%
  8770. %@NL@%
  8771.         END SELECT%@NL@%
  8772. %@NL@%
  8773. %@AB@%        ' Return the pattern as the value of the function:%@AE@%%@NL@%
  8774.         GetPattern$ = P$%@NL@%
  8775. %@NL@%
  8776. END FUNCTION%@NL@%
  8777. %@NL@%
  8778. %@AB@%'=== LabelChartH - Prints horizontal text on a chart%@AE@%%@NL@%
  8779. %@AB@%'%@AE@%%@NL@%
  8780. %@AB@%'  Arguments:%@AE@%%@NL@%
  8781. %@AB@%'     Env        - A ChartEnvironment variable%@AE@%%@NL@%
  8782. %@AB@%'%@AE@%%@NL@%
  8783. %@AB@%'     X          - Horizontal position of text relative to the left of%@AE@%%@NL@%
  8784. %@AB@%'                  the Chart window (in pixels)%@AE@%%@NL@%
  8785. %@AB@%'%@AE@%%@NL@%
  8786. %@AB@%'     Y          - Vertical position of text relative to the top of%@AE@%%@NL@%
  8787. %@AB@%'                  the Chart window (in pixels)%@AE@%%@NL@%
  8788. %@AB@%'%@AE@%%@NL@%
  8789. %@AB@%'     Font%      - Font number to use for the text%@AE@%%@NL@%
  8790. %@AB@%'%@AE@%%@NL@%
  8791. %@AB@%'     TxtColor   - Color number (in internal color palette) for text%@AE@%%@NL@%
  8792. %@AB@%'%@AE@%%@NL@%
  8793. %@AB@%'     TxtString$ - String variable containing text to print%@AE@%%@NL@%
  8794. %@AB@%'%@AE@%%@NL@%
  8795. %@AB@%'  Return Values:%@AE@%%@NL@%
  8796. %@AB@%'     None%@AE@%%@NL@%
  8797. %@AB@%'%@AE@%%@NL@%
  8798. %@AB@%'=================================================================%@AE@%%@NL@%
  8799. SUB LabelChartH (Env AS ChartEnvironment, X AS INTEGER, Y AS INTEGER, Font AS INTEGER, TxtColor AS INTEGER, TxtString$)%@NL@%
  8800. %@NL@%
  8801. %@AB@%        ' Reset any outstanding errors:%@AE@%%@NL@%
  8802.         clClearError%@NL@%
  8803. %@NL@%
  8804. %@AB@%        ' Check initialization and fonts:%@AE@%%@NL@%
  8805.         clChkInit%@NL@%
  8806.         clChkFonts%@NL@%
  8807.         IF ChartErr >= 100 THEN EXIT SUB%@NL@%
  8808. %@NL@%
  8809. %@AB@%        ' Select ChartWindow as reference viewport:%@AE@%%@NL@%
  8810.         clSelectChartWindow%@NL@%
  8811. %@NL@%
  8812. %@AB@%        ' Select font and set color:%@AE@%%@NL@%
  8813.         SelectFont Font%@NL@%
  8814.         clSetCharColor TxtColor%@NL@%
  8815. %@NL@%
  8816. %@AB@%        ' Call internal print routine to print text:%@AE@%%@NL@%
  8817.         clHPrint X, Y, TxtString$%@NL@%
  8818. %@NL@%
  8819. END SUB%@NL@%
  8820. %@NL@%
  8821. %@AB@%'=== LabelChartV - Prints vertical text on a chart%@AE@%%@NL@%
  8822. %@AB@%'%@AE@%%@NL@%
  8823. %@AB@%'  Arguments:%@AE@%%@NL@%
  8824. %@AB@%'     Env        - A ChartEnvironment variable%@AE@%%@NL@%
  8825. %@AB@%'%@AE@%%@NL@%
  8826. %@AB@%'     X          - Horizontal position of text relative to the left of%@AE@%%@NL@%
  8827. %@AB@%'                  the Chart window (in pixels)%@AE@%%@NL@%
  8828. %@AB@%'%@AE@%%@NL@%
  8829. %@AB@%'     Y          - Vertical position of text relative to the top of%@AE@%%@NL@%
  8830. %@AB@%'                  the Chart window (in pixels)%@AE@%%@NL@%
  8831. %@AB@%'%@AE@%%@NL@%
  8832. %@AB@%'     Font%      - Font number to use for the text%@AE@%%@NL@%
  8833. %@AB@%'%@AE@%%@NL@%
  8834. %@AB@%'     TxtColor   - Color number (in internal color palette) for text%@AE@%%@NL@%
  8835. %@AB@%'%@AE@%%@NL@%
  8836. %@AB@%'     TxtString$ - String variable containing text to print%@AE@%%@NL@%
  8837. %@AB@%'%@AE@%%@NL@%
  8838. %@AB@%'  Return Values:%@AE@%%@NL@%
  8839. %@AB@%'     None%@AE@%%@NL@%
  8840. %@AB@%'%@AE@%%@NL@%
  8841. %@AB@%'=================================================================%@AE@%%@NL@%
  8842. SUB LabelChartV (Env AS ChartEnvironment, X AS INTEGER, Y AS INTEGER, Font AS INTEGER, TxtColor AS INTEGER, TxtString$)%@NL@%
  8843. %@NL@%
  8844. %@AB@%        ' Reset any outstanding errors:%@AE@%%@NL@%
  8845.         clClearError%@NL@%
  8846. %@NL@%
  8847. %@AB@%        ' Check initialization and fonts:%@AE@%%@NL@%
  8848.         clChkInit%@NL@%
  8849.         clChkFonts%@NL@%
  8850.         IF ChartErr >= 100 THEN EXIT SUB%@NL@%
  8851. %@NL@%
  8852. %@AB@%        ' Select ChartWindow as reference viewport:%@AE@%%@NL@%
  8853.         clSelectChartWindow%@NL@%
  8854. %@NL@%
  8855. %@AB@%        ' Select font and set color:%@AE@%%@NL@%
  8856.         SelectFont Font%%@NL@%
  8857.         clSetCharColor TxtColor%@NL@%
  8858. %@NL@%
  8859. %@AB@%        ' Call internal print routine to print text:%@AE@%%@NL@%
  8860.         clVPrint X, Y, TxtString$%@NL@%
  8861. %@NL@%
  8862. END SUB%@NL@%
  8863. %@NL@%
  8864. %@AB@%'=== MakeChartPattern$ - Makes a pattern given reference pattern and%@AE@%%@NL@%
  8865. %@AB@%'                        foreground and background colors%@AE@%%@NL@%
  8866. %@AB@%'%@AE@%%@NL@%
  8867. %@AB@%'  Arguments:%@AE@%%@NL@%
  8868. %@AB@%'     RefPattern$ -  Reference pattern%@AE@%%@NL@%
  8869. %@AB@%'%@AE@%%@NL@%
  8870. %@AB@%'     FG%         -  Foreground color%@AE@%%@NL@%
  8871. %@AB@%'%@AE@%%@NL@%
  8872. %@AB@%'     BG%         -  Background color%@AE@%%@NL@%
  8873. %@AB@%'%@AE@%%@NL@%
  8874. %@AB@%'  Return Values:%@AE@%%@NL@%
  8875. %@AB@%'     Returns a pattern in standard PAINT format%@AE@%%@NL@%
  8876. %@AB@%'     Sets error cBadScreen if ChartScreen hasn't been called%@AE@%%@NL@%
  8877. %@AB@%'%@AE@%%@NL@%
  8878. %@AB@%'=================================================================%@AE@%%@NL@%
  8879. FUNCTION MakeChartPattern$ (RefPattern$, FG AS INTEGER, BG AS INTEGER)%@NL@%
  8880. SHARED GP AS GlobalParams%@NL@%
  8881. %@NL@%
  8882. %@AB@%        ' Reset any outstanding errors:%@AE@%%@NL@%
  8883.         clClearError%@NL@%
  8884. %@NL@%
  8885. %@AB@%        ' Check initialization:%@AE@%%@NL@%
  8886.         clChkInit%@NL@%
  8887.         IF ChartErr >= 100 THEN EXIT FUNCTION%@NL@%
  8888.         IF NOT GP.PaletteSet THEN%@NL@%
  8889.                 clSetError cBadScreen%@NL@%
  8890.                 EXIT FUNCTION%@NL@%
  8891.         END IF%@NL@%
  8892. %@NL@%
  8893.         FGColor% = clMap2Attrib%(FG%)%@NL@%
  8894.         BGColor% = clMap2Attrib%(BG%)%@NL@%
  8895. %@NL@%
  8896. %@AB@%        ' Screens 1, 2, 11 and 13 are 1 bit plane modes and require one method%@AE@%%@NL@%
  8897. %@AB@%        ' of generating pattern tiles.  The other modes supported are multiple%@AE@%%@NL@%
  8898. %@AB@%        ' bit plane modes and require another method of generating pattern%@AE@%%@NL@%
  8899. %@AB@%        ' tiles.  Select the appropriate method for this screen mode:%@AE@%%@NL@%
  8900.         SELECT CASE GP.PaletteScrn%@NL@%
  8901. %@NL@%
  8902. %@AB@%                ' One bit plane modes:%@AE@%%@NL@%
  8903.                 CASE 1, 2, 11, 13: SinglePlane% = cTrue%@NL@%
  8904.                 CASE ELSE: SinglePlane% = cFalse%@NL@%
  8905. %@NL@%
  8906.         END SELECT%@NL@%
  8907. %@NL@%
  8908. %@AB@%        ' Do foreground part of pattern:%@AE@%%@NL@%
  8909.         IF SinglePlane% THEN%@NL@%
  8910.                         FGPattern$ = clBuildBitP$(GP.PaletteBits, FGColor%, RefPattern$)%@NL@%
  8911.         ELSE%@NL@%
  8912.                         FGPattern$ = clBuildPlaneP$(GP.PaletteBits, FGColor%, RefPattern$)%@NL@%
  8913.         END IF%@NL@%
  8914. %@NL@%
  8915. %@AB@%        ' Do background part of pattern (if background color is black then%@AE@%%@NL@%
  8916. %@AB@%        ' the pattern is just the foreground pattern):%@AE@%%@NL@%
  8917.         IF BGColor% = 0 THEN%@NL@%
  8918.                 Pattern$ = FGPattern$%@NL@%
  8919. %@NL@%
  8920.         ELSE%@NL@%
  8921. %@AB@%                ' Background reference pattern is inverted foreground pattern:%@AE@%%@NL@%
  8922.                 BGPattern$ = ""%@NL@%
  8923.                 FOR i% = 1 TO LEN(RefPattern$)%@NL@%
  8924.                         BGPattern$ = BGPattern$ + CHR$(ASC(MID$(RefPattern$, i%, 1)) XOR &HFF)%@NL@%
  8925.                 NEXT i%%@NL@%
  8926. %@NL@%
  8927. %@AB@%                ' Build the corresponding PAINT style pattern:%@AE@%%@NL@%
  8928.                 IF SinglePlane% THEN%@NL@%
  8929.                                 BGPattern$ = clBuildBitP$(GP.PaletteBits, BGColor%, BGPattern$)%@NL@%
  8930.                 ELSE%@NL@%
  8931.                                 BGPattern$ = clBuildPlaneP$(GP.PaletteBits, BGColor%, BGPattern$)%@NL@%
  8932.                 END IF%@NL@%
  8933. %@NL@%
  8934. %@AB@%                ' Put foreground and background patterns back together:%@AE@%%@NL@%
  8935.                 Pattern$ = ""%@NL@%
  8936.                 FOR i% = 1 TO LEN(FGPattern$)%@NL@%
  8937.                         Pattern$ = Pattern$ + CHR$(ASC(MID$(FGPattern$, i%, 1)) OR ASC(MID$(BGPattern$, i%, 1)))%@NL@%
  8938.                 NEXT i%%@NL@%
  8939. %@NL@%
  8940.         END IF%@NL@%
  8941. %@NL@%
  8942.         MakeChartPattern$ = Pattern$%@NL@%
  8943. %@NL@%
  8944. END FUNCTION%@NL@%
  8945. %@NL@%
  8946. %@AB@%'=== ResetPaletteDef - Resets charting palettes for last screen%@AE@%%@NL@%
  8947. %@AB@%'                      mode set with ChartScreen.%@AE@%%@NL@%
  8948. %@AB@%'%@AE@%%@NL@%
  8949. %@AB@%'=================================================================%@AE@%%@NL@%
  8950. SUB ResetPaletteDef%@NL@%
  8951. SHARED GP AS GlobalParams%@NL@%
  8952. %@NL@%
  8953. %@AB@%        ' Clear outstanding errors:%@AE@%%@NL@%
  8954.         clClearError%@NL@%
  8955. %@NL@%
  8956. %@AB@%        ' Check initialization:%@AE@%%@NL@%
  8957.         clChkInit%@NL@%
  8958. %@NL@%
  8959. %@AB@%        ' Make sure that ChartScreen has been called at least once:%@AE@%%@NL@%
  8960.         IF NOT GP.PaletteSet THEN%@NL@%
  8961.                 clSetError cBadScreen%@NL@%
  8962.                 EXIT SUB%@NL@%
  8963.         END IF%@NL@%
  8964. %@NL@%
  8965. %@AB@%        ' Now rebuild the palette with the last set screen mode:%@AE@%%@NL@%
  8966.         clBuildPalette GP.PaletteScrn, GP.PaletteBits%@NL@%
  8967. %@NL@%
  8968. END SUB%@NL@%
  8969. %@NL@%
  8970. %@AB@%'=== SetPaletteDef - Changes an entry in the internal palette%@AE@%%@NL@%
  8971. %@AB@%'%@AE@%%@NL@%
  8972. %@AB@%'  Arguments:%@AE@%%@NL@%
  8973. %@AB@%'     C%()     -  Color palette array%@AE@%%@NL@%
  8974. %@AB@%'%@AE@%%@NL@%
  8975. %@AB@%'     S%()     -  Style palette array%@AE@%%@NL@%
  8976. %@AB@%'%@AE@%%@NL@%
  8977. %@AB@%'     P$()     -  Pattern palette array%@AE@%%@NL@%
  8978. %@AB@%'%@AE@%%@NL@%
  8979. %@AB@%'     Char%()  -  Plot character palette array%@AE@%%@NL@%
  8980. %@AB@%'%@AE@%%@NL@%
  8981. %@AB@%'     B%()     -  Border style palette array%@AE@%%@NL@%
  8982. %@AB@%'%@AE@%%@NL@%
  8983. %@AB@%'  Return Values:%@AE@%%@NL@%
  8984. %@AB@%'     Internal chart palettes may be modified or ChartErr set%@AE@%%@NL@%
  8985. %@AB@%'%@AE@%%@NL@%
  8986. %@AB@%'=================================================================%@AE@%%@NL@%
  8987. SUB SetPaletteDef (C() AS INTEGER, s() AS INTEGER, P$(), Char() AS INTEGER, B() AS INTEGER)%@NL@%
  8988. SHARED PaletteC%(), PaletteS%(), PaletteP$(), PaletteCh%(), PaletteB%()%@NL@%
  8989. %@NL@%
  8990. %@AB@%        ' Reset any outstanding errors and check that palettes are dimesioned%@AE@%%@NL@%
  8991. %@AB@%        ' correctly:%@AE@%%@NL@%
  8992.         clClearError%@NL@%
  8993.         clChkPalettes C(), s(), P$(), Char(), B()%@NL@%
  8994.         IF (ChartErr <> 0) THEN EXIT SUB%@NL@%
  8995. %@NL@%
  8996. %@AB@%        ' Check initialization:%@AE@%%@NL@%
  8997.         clChkInit%@NL@%
  8998. %@NL@%
  8999. %@AB@%        ' Replace the palette values with input variables (making sure that%@AE@%%@NL@%
  9000. %@AB@%        ' the color and character numbers are in range):%@AE@%%@NL@%
  9001.         FOR N% = 0 TO cPalLen%@NL@%
  9002.                 PaletteC%(N%) = clMap2Attrib%(C%(N%))%@NL@%
  9003.                 PaletteS%(N%) = s(N%)%@NL@%
  9004.                 PaletteP$(N%) = P$(N%)%@NL@%
  9005.                 PaletteCh%(N%) = ABS(Char(N%)) MOD (cMaxChars + 1)%@NL@%
  9006.                 PaletteB%(N%) = B(N%)%@NL@%
  9007.         NEXT N%%@NL@%
  9008. %@NL@%
  9009. END SUB%@NL@%
  9010. %@NL@%
  9011. %@NL@%
  9012. %@NL@%
  9013. %@2@%%@AH@%CHRTDEM1.BAS%@AE@%%@EH@%%@NL@%
  9014. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\CHRTDEM1.BAS%@AE@%%@NL@%
  9015. %@NL@%
  9016. %@AB@%'       CHRTDEM1.BAS - second module of the CHRTB demonstration program.%@AE@%%@NL@%
  9017. %@AB@%'%@AE@%%@NL@%
  9018. %@AB@%'               Copyright (C) 1989, Microsoft Corporation%@AE@%%@NL@%
  9019. %@AB@%'%@AE@%%@NL@%
  9020. %@AB@%'   Main module - CHRTDEMO.BAS%@AE@%%@NL@%
  9021. %@AB@%'   Include files - CHRTDEMO.BI%@AE@%%@NL@%
  9022. %@AB@%'%@AE@%%@NL@%
  9023. %@AB@%'$INCLUDE: 'chrtdemo.bi'%@AE@%%@NL@%
  9024. %@NL@%
  9025. %@AB@%'local subs%@AE@%%@NL@%
  9026. DECLARE SUB ChangeStyle ()%@NL@%
  9027. %@NL@%
  9028. DEFINT A-Z%@NL@%
  9029. %@AB@%'%@AE@%%@NL@%
  9030. %@AB@%' Sub Name: ChangeAxis%@AE@%%@NL@%
  9031. %@AB@%'%@AE@%%@NL@%
  9032. %@AB@%' Description: Allows user to view and change attributes of either%@AE@%%@NL@%
  9033. %@AB@%'              chart axis.%@AE@%%@NL@%
  9034. %@AB@%'%@AE@%%@NL@%
  9035. %@AB@%' Arguments: title$ - window title%@AE@%%@NL@%
  9036. %@AB@%'            axis - X or Y axis variable%@AE@%%@NL@%
  9037. %@AB@%'%@AE@%%@NL@%
  9038. SUB ChangeAxis (title$, axis AS AxisType)%@NL@%
  9039. %@NL@%
  9040.     DIM colorBox AS ListBox%@NL@%
  9041.     DIM styleBox AS ListBox%@NL@%
  9042.     DIM fontBox AS ListBox%@NL@%
  9043. %@NL@%
  9044. %@AB@%    ' set up color list box%@AE@%%@NL@%
  9045.     colorBox.scrollButton = 2%@NL@%
  9046.     colorBox.areaButton = 3%@NL@%
  9047.     colorBox.listLen = numColors%@NL@%
  9048.     colorBox.topRow = 3%@NL@%
  9049.     colorBox.botRow = 16%@NL@%
  9050.     colorBox.leftCol = 4%@NL@%
  9051.     colorBox.rightCol = 18%@NL@%
  9052.     colorBox.listPos = axis.AxisColor + 1%@NL@%
  9053. %@NL@%
  9054. %@AB@%    ' set up border style list box%@AE@%%@NL@%
  9055.     styleBox.scrollButton = 5%@NL@%
  9056.     styleBox.areaButton = 6%@NL@%
  9057.     styleBox.listLen = MAXSTYLES%@NL@%
  9058.     styleBox.topRow = 5%@NL@%
  9059.     styleBox.botRow = 16%@NL@%
  9060.     styleBox.leftCol = 24%@NL@%
  9061.     styleBox.rightCol = 40%@NL@%
  9062.     styleBox.listPos = axis.GridStyle%@NL@%
  9063. %@NL@%
  9064. %@AB@%    ' set up font list box%@AE@%%@NL@%
  9065.     fontBox.scrollButton = 8%@NL@%
  9066.     fontBox.areaButton = 9%@NL@%
  9067.     fontBox.listLen = numFonts%@NL@%
  9068.     fontBox.topRow = 5%@NL@%
  9069.     fontBox.botRow = 9%@NL@%
  9070.     fontBox.leftCol = 46%@NL@%
  9071.     fontBox.rightCol = 65%@NL@%
  9072.     fontBox.listPos = axis.TicFont%@NL@%
  9073. %@NL@%
  9074. %@AB@%    ' open window for display%@AE@%%@NL@%
  9075.     winRow = 4%@NL@%
  9076.     winCol = 6%@NL@%
  9077.     WindowOpen 1, winRow, winCol, 22, 73, 0, 7, 0, 7, 15, FALSE, FALSE, FALSE, TRUE, 2, title$%@NL@%
  9078.     WindowBox 1, 2, 17, 20%@NL@%
  9079.     WindowLocate 2, 4%@NL@%
  9080.     WindowPrint 2, "Axis Color:"%@NL@%
  9081.     WindowBox 1, 22, 17, 42%@NL@%
  9082.     WindowLocate 4, 24%@NL@%
  9083.     WindowPrint 2, "Grid Style:"%@NL@%
  9084.     WindowBox 1, 44, 17, 67%@NL@%
  9085.     WindowLocate 4, 46%@NL@%
  9086.     WindowPrint 2, "Label Font:"%@NL@%
  9087.     WindowLocate 10, 46%@NL@%
  9088.     WindowPrint 2, "Range Type:"%@NL@%
  9089.     WindowBox 11, 46, 16, 65%@NL@%
  9090.     WindowLocate 14, 48%@NL@%
  9091.     WindowPrint 2, "Log Base:"%@NL@%
  9092.     WindowBox 13, 57, 15, 63%@NL@%
  9093.     WindowLine 18%@NL@%
  9094. %@NL@%
  9095. %@AB@%    ' create list boxes%@AE@%%@NL@%
  9096.     CreateListBox colors$(), colorBox, 0%@NL@%
  9097.     CreateListBox styles$(), styleBox, 0%@NL@%
  9098.     CreateListBox fonts$(), fontBox, 0%@NL@%
  9099. %@NL@%
  9100. %@AB@%    ' open control buttons%@AE@%%@NL@%
  9101.     ButtonOpen 4, 1, "Display Grid", 2, 24, 0, 0, 2%@NL@%
  9102.     ButtonOpen 7, 1, "Display Labels", 2, 46, 0, 0, 2%@NL@%
  9103.     ButtonOpen 10, 1, "Lin", 12, 48, 0, 0, 3%@NL@%
  9104.     ButtonOpen 11, 1, "Log", 12, 57, 0, 0, 3%@NL@%
  9105.     ButtonOpen 12, 2, "OK ", 19, 10, 0, 0, 1%@NL@%
  9106.     ButtonOpen 13, 1, "Cancel ", 19, 26, 0, 0, 1%@NL@%
  9107.     ButtonOpen 14, 1, "Axis Title ", 19, 46, 0, 0, 1%@NL@%
  9108. %@NL@%
  9109. %@AB@%    ' edit field for log base%@AE@%%@NL@%
  9110.     EditFieldOpen 1, LTRIM$(STR$(axis.LogBase)), 14, 58, 0, 7, 5, 20%@NL@%
  9111. %@NL@%
  9112. %@NL@%
  9113.     currButton = 3                                      ' start with cursor on first button (Autoscale)%@NL@%
  9114.     currEditField = 0%@NL@%
  9115. %@NL@%
  9116.     optionButton = axis.RangeType + 9                   ' set proper state for buttons%@NL@%
  9117.     ButtonToggle optionButton%@NL@%
  9118.     IF axis.Labeled THEN ButtonToggle 7%@NL@%
  9119.     IF axis.Grid THEN ButtonToggle 4%@NL@%
  9120. %@NL@%
  9121.     pushButton = 12                                     ' active command button%@NL@%
  9122. %@NL@%
  9123. %@AB@%    ' window control loop%@AE@%%@NL@%
  9124.     finished = FALSE%@NL@%
  9125.     WHILE NOT finished%@NL@%
  9126.         WindowDo currButton, currEditField              ' wait for event%@NL@%
  9127.         SELECT CASE Dialog(0)%@NL@%
  9128.             CASE 1                                      ' button pressed%@NL@%
  9129.                 currButton = Dialog(1)%@NL@%
  9130.                 SELECT CASE currButton%@NL@%
  9131.                     CASE 4, 7%@NL@%
  9132.                         ButtonToggle currButton%@NL@%
  9133.                         currEditField = 0%@NL@%
  9134.                     CASE 10, 11%@NL@%
  9135.                         ButtonToggle optionButton%@NL@%
  9136.                         optionButton = currButton%@NL@%
  9137.                         ButtonToggle optionButton%@NL@%
  9138.                         currEditField = 0%@NL@%
  9139.                     CASE 2, 3%@NL@%
  9140.                         currEditField = 0%@NL@%
  9141.                         ScrollList colors$(), colorBox, currButton, 1, 0, winRow, winCol%@NL@%
  9142.                         currButton = 3%@NL@%
  9143.                     CASE 5, 6%@NL@%
  9144.                         currEditField = 0%@NL@%
  9145.                         ScrollList styles$(), styleBox, currButton, 1, 0, winRow, winCol%@NL@%
  9146.                         currButton = 6%@NL@%
  9147.                     CASE 8, 9%@NL@%
  9148.                         currEditField = 0%@NL@%
  9149.                         ScrollList fonts$(), fontBox, currButton, 1, 0, winRow, winCol%@NL@%
  9150.                         currButton = 9%@NL@%
  9151.                     CASE 12, 13%@NL@%
  9152.                         pushButton = currButton%@NL@%
  9153.                         finished = TRUE%@NL@%
  9154.                     CASE 14%@NL@%
  9155.                         currEditField = 0%@NL@%
  9156.                         ButtonSetState pushButton, 1%@NL@%
  9157.                         ButtonSetState currButton, 2%@NL@%
  9158.                         pushButton = currButton%@NL@%
  9159.                         ChangeTitle 2, title$ + " Title", axis.AxisTitle, 6, 14%@NL@%
  9160.                 END SELECT%@NL@%
  9161.             CASE 2                                      ' edit field%@NL@%
  9162.                 currEditField = 1%@NL@%
  9163.                 currButton = 0%@NL@%
  9164.             CASE 6                                      ' enter%@NL@%
  9165.                 SELECT CASE pushButton%@NL@%
  9166.                     CASE 12, 13: finished = TRUE%@NL@%
  9167.                     CASE 14: ChangeTitle 2, title$ + " Title", axis.AxisTitle, 6, 14%@NL@%
  9168.                 END SELECT%@NL@%
  9169.                 currButton = pushButton%@NL@%
  9170.             CASE 7                                      ' tab%@NL@%
  9171.                 SELECT CASE currButton%@NL@%
  9172.                     CASE 0:%@NL@%
  9173.                         currEditField = 0%@NL@%
  9174.                         currButton = 12%@NL@%
  9175.                         ButtonSetState pushButton, 1%@NL@%
  9176.                         ButtonSetState currButton, 2%@NL@%
  9177.                         pushButton = currButton%@NL@%
  9178.                     CASE 2, 3: currButton = 4%@NL@%
  9179.                     CASE 4: currButton = 6%@NL@%
  9180.                     CASE 5, 6: currButton = 7%@NL@%
  9181.                     CASE 7: currButton = 9%@NL@%
  9182.                     CASE 8, 9: currButton = optionButton%@NL@%
  9183.                     CASE 10, 11:%@NL@%
  9184.                         currButton = 0%@NL@%
  9185.                         currEditField = 1%@NL@%
  9186.                     CASE 12, 13:%@NL@%
  9187.                         currButton = currButton + 1%@NL@%
  9188.                         ButtonSetState pushButton, 1%@NL@%
  9189.                         ButtonSetState currButton, 2%@NL@%
  9190.                         pushButton = currButton%@NL@%
  9191.                     CASE 14:%@NL@%
  9192.                         ButtonSetState currButton, 1%@NL@%
  9193.                         pushButton = 12%@NL@%
  9194.                         ButtonSetState pushButton, 2%@NL@%
  9195.                         currButton = 3%@NL@%
  9196.                 END SELECT%@NL@%
  9197.             CASE 8                                      ' back tab%@NL@%
  9198.                 SELECT CASE currButton%@NL@%
  9199.                     CASE 0:%@NL@%
  9200.                         currEditField = 0%@NL@%
  9201.                         currButton = optionButton%@NL@%
  9202.                     CASE 2, 3:%@NL@%
  9203.                         currButton = 14%@NL@%
  9204.                         ButtonSetState pushButton, 1%@NL@%
  9205.                         ButtonSetState currButton, 2%@NL@%
  9206.                         pushButton = currButton%@NL@%
  9207.                     CASE 4: currButton = 3%@NL@%
  9208.                     CASE 5, 6: currButton = 4%@NL@%
  9209.                     CASE 7: currButton = 6%@NL@%
  9210.                     CASE 8, 9: currButton = 7%@NL@%
  9211.                     CASE 10, 11: currButton = 9%@NL@%
  9212.                     CASE 12:%@NL@%
  9213.                         currButton = 0%@NL@%
  9214.                         currEditField = 1%@NL@%
  9215.                     CASE 13, 14:%@NL@%
  9216.                         currButton = currButton - 1%@NL@%
  9217.                         ButtonSetState pushButton, 1%@NL@%
  9218.                         ButtonSetState currButton, 2%@NL@%
  9219.                         pushButton = currButton%@NL@%
  9220.                 END SELECT%@NL@%
  9221.             CASE 9                                      ' escape%@NL@%
  9222.                 pushButton = 13%@NL@%
  9223.                 finished = TRUE%@NL@%
  9224.             CASE 10, 12                                 ' up, left arrow%@NL@%
  9225.                 SELECT CASE currButton%@NL@%
  9226.                     CASE 4, 7: ButtonSetState currButton, 2%@NL@%
  9227.                     CASE 2, 3: ScrollList colors$(), colorBox, currButton, 2, 0, winRow, winCol%@NL@%
  9228.                     CASE 5, 6: ScrollList styles$(), styleBox, currButton, 2, 0, winRow, winCol%@NL@%
  9229.                     CASE 8, 9: ScrollList fonts$(), fontBox, currButton, 2, 0, winRow, winCol%@NL@%
  9230.                     CASE 10, 11:%@NL@%
  9231.                         ButtonToggle currButton%@NL@%
  9232.                         currButton = 21 - currButton%@NL@%
  9233.                         optionButton = currButton%@NL@%
  9234.                         ButtonToggle optionButton%@NL@%
  9235.                 END SELECT%@NL@%
  9236.             CASE 11, 13                                 ' down, right arrow%@NL@%
  9237.                 SELECT CASE currButton%@NL@%
  9238.                     CASE 1, 4, 7: ButtonSetState currButton, 1%@NL@%
  9239.                     CASE 2, 3: ScrollList colors$(), colorBox, currButton, 3, 0, winRow, winCol%@NL@%
  9240.                     CASE 5, 6: ScrollList styles$(), styleBox, currButton, 3, 0, winRow, winCol%@NL@%
  9241.                     CASE 8, 9: ScrollList fonts$(), fontBox, currButton, 3, 0, winRow, winCol%@NL@%
  9242.                     CASE 10, 11:%@NL@%
  9243.                         ButtonToggle currButton%@NL@%
  9244.                         currButton = 21 - currButton%@NL@%
  9245.                         optionButton = currButton%@NL@%
  9246.                         ButtonToggle optionButton%@NL@%
  9247.                 END SELECT%@NL@%
  9248.             CASE 14                                     ' space bar%@NL@%
  9249.                 SELECT CASE currButton%@NL@%
  9250.                     CASE 1, 4, 7: ButtonToggle currButton%@NL@%
  9251.                     CASE 12, 13: finished = TRUE%@NL@%
  9252.                     CASE 14: ChangeTitle 2, title$ + " Title", axis.AxisTitle, 6, 14%@NL@%
  9253.                 END SELECT%@NL@%
  9254.         END SELECT%@NL@%
  9255. %@NL@%
  9256. %@AB@%        ' error checking on log base before exiting%@AE@%%@NL@%
  9257.         IF finished AND pushButton = 12 THEN%@NL@%
  9258.             IF VAL(EditFieldInquire(1)) <= 0 THEN%@NL@%
  9259.                 PrintError " Log base must be greater than zero."%@NL@%
  9260.                 currEditField = 1%@NL@%
  9261.                 currButton = 0%@NL@%
  9262.                 finished = FALSE%@NL@%
  9263.             ELSEIF VAL(EditFieldInquire(1)) = 1 THEN%@NL@%
  9264.                 PrintError " Log base cannot equal one. Overflow results."%@NL@%
  9265.                 currEditField = 1%@NL@%
  9266.                 currButton = 0%@NL@%
  9267.                 finished = FALSE%@NL@%
  9268.             END IF%@NL@%
  9269.         END IF%@NL@%
  9270.     WEND%@NL@%
  9271. %@NL@%
  9272. %@AB@%    ' if not canceled then assign and return new values%@AE@%%@NL@%
  9273.     IF pushButton = 12 THEN%@NL@%
  9274.         IF setNum > 0 THEN chartChanged = TRUE%@NL@%
  9275. %@NL@%
  9276.         axis.LogBase = VAL(EditFieldInquire(1))%@NL@%
  9277.         axis.Grid = (ButtonInquire(4) = 2)%@NL@%
  9278.         axis.Labeled = (ButtonInquire(7) = 2)%@NL@%
  9279.         axis.RangeType = optionButton - 9%@NL@%
  9280.         axis.AxisColor = colorBox.listPos - 1%@NL@%
  9281.         axis.ScaleTitle.TitleColor = axis.AxisTitle.TitleColor%@NL@%
  9282.         axis.ScaleTitle.Justify = axis.AxisTitle.Justify%@NL@%
  9283.         axis.GridStyle = styleBox.listPos%@NL@%
  9284.         axis.TicFont = fontBox.listPos%@NL@%
  9285.     END IF%@NL@%
  9286. %@NL@%
  9287.     WindowClose 1%@NL@%
  9288. %@NL@%
  9289. END SUB%@NL@%
  9290. %@NL@%
  9291. %@AB@%'%@AE@%%@NL@%
  9292. %@AB@%' Sub Name: ChangeChartType%@AE@%%@NL@%
  9293. %@AB@%'%@AE@%%@NL@%
  9294. %@AB@%' Description: Changes chart type based on menu selection and%@AE@%%@NL@%
  9295. %@AB@%'              allows the user access to changing the chart style.%@AE@%%@NL@%
  9296. %@AB@%'%@AE@%%@NL@%
  9297. %@AB@%' Arguments: ctype - new chart type%@AE@%%@NL@%
  9298. %@AB@%'%@AE@%%@NL@%
  9299. SUB ChangeChartType (ctype)%@NL@%
  9300. %@NL@%
  9301. %@AB@%    'change type if user selected a different type%@AE@%%@NL@%
  9302.     IF CEnv.ChartType <> ctype THEN%@NL@%
  9303.         IF setNum > 0 THEN chartChanged = TRUE%@NL@%
  9304. %@NL@%
  9305. %@AB@%        ' reset chosen type%@AE@%%@NL@%
  9306.         MenuItemToggle GALLERYTITLE, CEnv.ChartType%@NL@%
  9307. %@AB@%        ' reset other affected menu items%@AE@%%@NL@%
  9308.         IF CEnv.ChartType = cPie THEN%@NL@%
  9309.             MenuSetState CHARTTITLE, 4, 1%@NL@%
  9310.             MenuSetState CHARTTITLE, 5, 1%@NL@%
  9311.             MenuSetState TITLETITLE, 3, 1%@NL@%
  9312.             MenuSetState TITLETITLE, 4, 1%@NL@%
  9313.         END IF%@NL@%
  9314. %@NL@%
  9315.         CEnv.ChartType = ctype%@NL@%
  9316. %@NL@%
  9317. %@AB@%        'if new type is pie then turn off some items%@AE@%%@NL@%
  9318.         IF CEnv.ChartType = cPie THEN%@NL@%
  9319.             MenuSetState CHARTTITLE, 4, 0%@NL@%
  9320.             MenuSetState CHARTTITLE, 5, 0%@NL@%
  9321.             MenuSetState TITLETITLE, 3, 0%@NL@%
  9322.             MenuSetState TITLETITLE, 4, 0%@NL@%
  9323.         END IF%@NL@%
  9324. %@NL@%
  9325. %@AB@%        ' set type in menu bar%@AE@%%@NL@%
  9326.         MenuItemToggle GALLERYTITLE, CEnv.ChartType%@NL@%
  9327.     END IF%@NL@%
  9328. %@NL@%
  9329. %@AB@%    ' allow user to change chart style%@AE@%%@NL@%
  9330.     ChangeStyle%@NL@%
  9331. %@NL@%
  9332. END SUB%@NL@%
  9333. %@NL@%
  9334. %@AB@%'%@AE@%%@NL@%
  9335. %@AB@%' Sub Name: ChangeLegend%@AE@%%@NL@%
  9336. %@AB@%'%@AE@%%@NL@%
  9337. %@AB@%' Description: Allows user to view and modify all attributes of the chart%@AE@%%@NL@%
  9338. %@AB@%'              legend%@AE@%%@NL@%
  9339. %@AB@%'%@AE@%%@NL@%
  9340. %@AB@%' Arguments: none%@AE@%%@NL@%
  9341. %@AB@%'%@AE@%%@NL@%
  9342. SUB ChangeLegend%@NL@%
  9343. %@NL@%
  9344.     DIM fgColorBox AS ListBox%@NL@%
  9345.     DIM fontBox AS ListBox%@NL@%
  9346. %@NL@%
  9347. %@AB@%    ' set up foreground color box%@AE@%%@NL@%
  9348.     fgColorBox.scrollButton = 6%@NL@%
  9349.     fgColorBox.areaButton = 7%@NL@%
  9350.     fgColorBox.listLen = numColors%@NL@%
  9351.     fgColorBox.topRow = 3%@NL@%
  9352.     fgColorBox.botRow = 10%@NL@%
  9353.     fgColorBox.leftCol = 27%@NL@%
  9354.     fgColorBox.rightCol = 41%@NL@%
  9355.     fgColorBox.listPos = CEnv.Legend.TextColor + 1%@NL@%
  9356. %@NL@%
  9357. %@AB@%    ' set up font box%@AE@%%@NL@%
  9358.     fontBox.scrollButton = 8%@NL@%
  9359.     fontBox.areaButton = 9%@NL@%
  9360.     fontBox.listLen = numFonts%@NL@%
  9361.     fontBox.topRow = 3%@NL@%
  9362.     fontBox.botRow = 10%@NL@%
  9363.     fontBox.leftCol = 43%@NL@%
  9364.     fontBox.rightCol = 57%@NL@%
  9365.     fontBox.listPos = CEnv.Legend.TextFont%@NL@%
  9366. %@NL@%
  9367. %@AB@%    ' set up display window%@AE@%%@NL@%
  9368.     winRow = 6%@NL@%
  9369.     winCol = 10%@NL@%
  9370.     WindowOpen 1, winRow, winCol, 18, 69, 0, 7, 0, 7, 15, FALSE, FALSE, FALSE, TRUE, 2, "Chart Legend"%@NL@%
  9371.     WindowBox 1, 2, 11, 23%@NL@%
  9372.     WindowLocate 5, 4%@NL@%
  9373.     WindowPrint 2, "Location:"%@NL@%
  9374.     WindowBox 6, 4, 10, 21%@NL@%
  9375.     WindowBox 1, 25, 11, 59%@NL@%
  9376.     WindowLocate 2, 27%@NL@%
  9377.     WindowPrint 2, "Text Color:"%@NL@%
  9378.     WindowLocate 2, 43%@NL@%
  9379.     WindowPrint 2, "Text Font:"%@NL@%
  9380.     WindowLine 12%@NL@%
  9381. %@NL@%
  9382. %@AB@%    ' create list boxes%@AE@%%@NL@%
  9383.     CreateListBox colors$(), fgColorBox, 0%@NL@%
  9384.     CreateListBox fonts$(), fontBox, 0%@NL@%
  9385. %@NL@%
  9386. %@AB@%    ' open command buttons%@AE@%%@NL@%
  9387.     ButtonOpen 1, 1, "Display Legend", 2, 4, 0, 0, 2%@NL@%
  9388.     ButtonOpen 2, 1, "Autosize", 3, 4, 0, 0, 2%@NL@%
  9389.     ButtonOpen 3, 1, "Overlay", 7, 6, 0, 0, 3%@NL@%
  9390.     ButtonOpen 4, 1, "Bottom", 8, 6, 0, 0, 3%@NL@%
  9391.     ButtonOpen 5, 1, "Right", 9, 6, 0, 0, 3%@NL@%
  9392.     ButtonOpen 10, 2, "OK ", 13, 8, 0, 0, 1%@NL@%
  9393.     ButtonOpen 11, 1, "Cancel ", 13, 21, 0, 0, 1%@NL@%
  9394.     ButtonOpen 12, 1, "Legend Window ", 13, 38, 0, 0, 1%@NL@%
  9395. %@NL@%
  9396.     currButton = 1                                      ' start with cursor on first button%@NL@%
  9397. %@NL@%
  9398. %@AB@%    ' set button states based on current values%@AE@%%@NL@%
  9399.     optionButton = CEnv.Legend.Place + 2%@NL@%
  9400.     ButtonToggle optionButton%@NL@%
  9401.     IF CEnv.Legend.Legend THEN ButtonToggle 1%@NL@%
  9402.     IF CEnv.Legend.AutoSize THEN ButtonToggle 2%@NL@%
  9403.     pushButton = 10%@NL@%
  9404. %@NL@%
  9405. %@AB@%    ' window control loop%@AE@%%@NL@%
  9406.     finished = FALSE%@NL@%
  9407.     WHILE NOT finished%@NL@%
  9408.         WindowDo currButton, 0                          ' wait for event%@NL@%
  9409.         SELECT CASE Dialog(0)%@NL@%
  9410.             CASE 1                                      ' button pressed%@NL@%
  9411.                 currButton = Dialog(1)%@NL@%
  9412.                 SELECT CASE currButton%@NL@%
  9413.                     CASE 1, 2: ButtonToggle currButton%@NL@%
  9414.                     CASE 3, 4, 5%@NL@%
  9415.                         ButtonToggle optionButton%@NL@%
  9416.                         optionButton = currButton%@NL@%
  9417.                         ButtonToggle optionButton%@NL@%
  9418.                     CASE 6, 7:%@NL@%
  9419.                         ScrollList colors$(), fgColorBox, currButton, 1, 0, winRow, winCol%@NL@%
  9420.                         currButton = 7%@NL@%
  9421.                     CASE 8, 9:%@NL@%
  9422.                         ScrollList fonts$(), fontBox, currButton, 1, 0, winRow, winCol%@NL@%
  9423.                         currButton = 9%@NL@%
  9424.                     CASE 10, 11%@NL@%
  9425.                         pushButton = currButton%@NL@%
  9426.                         finished = TRUE%@NL@%
  9427.                     CASE 12%@NL@%
  9428.                         ButtonSetState pushButton, 1%@NL@%
  9429.                         ButtonSetState currButton, 2%@NL@%
  9430.                         pushButton = 12%@NL@%
  9431.                         ChangeWindow 2, "Legend Window", CEnv.Legend.LegendWindow%@NL@%
  9432.                 END SELECT%@NL@%
  9433.             CASE 6                                      ' enter%@NL@%
  9434.                 IF pushButton <> 12 THEN%@NL@%
  9435.                     finished = TRUE%@NL@%
  9436.                 ELSE%@NL@%
  9437.                     ChangeWindow 2, "Legend Window", CEnv.Legend.LegendWindow%@NL@%
  9438.                 END IF%@NL@%
  9439.             CASE 7                                      ' tab%@NL@%
  9440.                 SELECT CASE currButton%@NL@%
  9441.                     CASE 1: currButton = 2%@NL@%
  9442.                     CASE 2: currButton = optionButton%@NL@%
  9443.                     CASE 3, 4, 5: currButton = 7%@NL@%
  9444.                     CASE 6, 7: currButton = 9%@NL@%
  9445.                     CASE 8, 9:%@NL@%
  9446.                         currButton = 10%@NL@%
  9447.                         ButtonSetState pushButton, 1%@NL@%
  9448.                         ButtonSetState currButton, 2%@NL@%
  9449.                         pushButton = currButton%@NL@%
  9450.                     CASE 10, 11:%@NL@%
  9451.                         currButton = currButton + 1%@NL@%
  9452.                         ButtonSetState pushButton, 1%@NL@%
  9453.                         ButtonSetState currButton, 2%@NL@%
  9454.                         pushButton = currButton%@NL@%
  9455.                     CASE 12:%@NL@%
  9456.                         ButtonSetState currButton, 1%@NL@%
  9457.                         pushButton = 10%@NL@%
  9458.                         ButtonSetState pushButton, 2%@NL@%
  9459.                         currButton = 1%@NL@%
  9460.                 END SELECT%@NL@%
  9461.             CASE 8                                      ' back tab%@NL@%
  9462.                 SELECT CASE currButton%@NL@%
  9463.                     CASE 1:%@NL@%
  9464.                         currButton = 12%@NL@%
  9465.                         ButtonSetState pushButton, 1%@NL@%
  9466.                         ButtonSetState currButton, 2%@NL@%
  9467.                         pushButton = currButton%@NL@%
  9468.                     CASE 2: currButton = 1%@NL@%
  9469.                     CASE 3, 4, 5: currButton = 2%@NL@%
  9470.                     CASE 6, 7: currButton = optionButton%@NL@%
  9471.                     CASE 8, 9: currButton = 7%@NL@%
  9472.                     CASE 10: currButton = 9%@NL@%
  9473.                     CASE 11, 12:%@NL@%
  9474.                         currButton = currButton - 1%@NL@%
  9475.                         ButtonSetState pushButton, 1%@NL@%
  9476.                         ButtonSetState currButton, 2%@NL@%
  9477.                         pushButton = currButton%@NL@%
  9478.                 END SELECT%@NL@%
  9479.             CASE 9                                      ' escape%@NL@%
  9480.                 pushButton = 11%@NL@%
  9481.                 finished = TRUE%@NL@%
  9482.             CASE 10, 12                                 ' up, left arrow%@NL@%
  9483.                 SELECT CASE currButton%@NL@%
  9484.                     CASE 1, 2: ButtonSetState currButton, 2%@NL@%
  9485.                     CASE 3:%@NL@%
  9486.                         ButtonToggle currButton%@NL@%
  9487.                         currButton = 5%@NL@%
  9488.                         optionButton = currButton%@NL@%
  9489.                         ButtonToggle optionButton%@NL@%
  9490.                     CASE 4, 5:%@NL@%
  9491.                         ButtonToggle currButton%@NL@%
  9492.                         currButton = currButton - 1%@NL@%
  9493.                         optionButton = currButton%@NL@%
  9494.                         ButtonToggle optionButton%@NL@%
  9495.                     CASE 6, 7: ScrollList colors$(), fgColorBox, currButton, 2, 0, winRow, winCol%@NL@%
  9496.                     CASE 8, 9: ScrollList fonts$(), fontBox, currButton, 2, 0, winRow, winCol%@NL@%
  9497.                 END SELECT%@NL@%
  9498.             CASE 11, 13                                 ' down, right arrow%@NL@%
  9499.                 SELECT CASE currButton%@NL@%
  9500.                     CASE 1, 2: ButtonSetState currButton, 1%@NL@%
  9501.                     CASE 3, 4:%@NL@%
  9502.                         ButtonToggle currButton%@NL@%
  9503.                         currButton = currButton + 1%@NL@%
  9504.                         optionButton = currButton%@NL@%
  9505.                         ButtonToggle optionButton%@NL@%
  9506.                     CASE 5:%@NL@%
  9507.                         ButtonToggle currButton%@NL@%
  9508.                         currButton = 3%@NL@%
  9509.                         optionButton = currButton%@NL@%
  9510.                         ButtonToggle optionButton%@NL@%
  9511.                     CASE 6, 7: ScrollList colors$(), fgColorBox, currButton, 3, 0, winRow, winCol%@NL@%
  9512.                     CASE 8, 9: ScrollList fonts$(), fontBox, currButton, 3, 0, winRow, winCol%@NL@%
  9513.                 END SELECT%@NL@%
  9514.             CASE 14                                     ' space bar%@NL@%
  9515.                 SELECT CASE currButton%@NL@%
  9516.                     CASE 1, 2: ButtonToggle currButton%@NL@%
  9517.                     CASE 10, 11: finished = TRUE%@NL@%
  9518.                     CASE 12: ChangeWindow 2, "Legend Window", CEnv.Legend.LegendWindow%@NL@%
  9519.                END SELECT%@NL@%
  9520.         END SELECT%@NL@%
  9521.     WEND%@NL@%
  9522. %@NL@%
  9523. %@AB@%    ' if not canceled then return the new values%@AE@%%@NL@%
  9524.     IF pushButton = 10 THEN%@NL@%
  9525.         IF setNum > 0 THEN chartChanged = TRUE%@NL@%
  9526. %@NL@%
  9527.         CEnv.Legend.TextColor = fgColorBox.listPos - 1%@NL@%
  9528.         CEnv.Legend.TextFont = fontBox.listPos%@NL@%
  9529.         CEnv.Legend.AutoSize = (ButtonInquire(2) = 2)%@NL@%
  9530.         CEnv.Legend.Legend = (ButtonInquire(1) = 2)%@NL@%
  9531.         CEnv.Legend.Place = optionButton - 2%@NL@%
  9532.     END IF%@NL@%
  9533. %@NL@%
  9534.     WindowClose 1%@NL@%
  9535. %@NL@%
  9536. END SUB%@NL@%
  9537. %@NL@%
  9538. %@AB@%'%@AE@%%@NL@%
  9539. %@AB@%' Sub Name: ChangeStyle%@AE@%%@NL@%
  9540. %@AB@%'%@AE@%%@NL@%
  9541. %@AB@%' Description: Allows user to view and modify the chart style%@AE@%%@NL@%
  9542. %@AB@%'%@AE@%%@NL@%
  9543. %@AB@%' Arguments: none%@AE@%%@NL@%
  9544. %@AB@%'%@AE@%%@NL@%
  9545. SUB ChangeStyle%@NL@%
  9546. DIM fontBox AS ListBox%@NL@%
  9547. %@NL@%
  9548. %@AB@%    ' determine button labels based on chart type%@AE@%%@NL@%
  9549.     SELECT CASE CEnv.ChartType%@NL@%
  9550.         CASE cBar, cColumn%@NL@%
  9551.             style1$ = "Adjacent"%@NL@%
  9552.             style2$ = "Stacked"%@NL@%
  9553.         CASE cLine, cScatter%@NL@%
  9554.             style1$ = "Lines"%@NL@%
  9555.             style2$ = "No Lines"%@NL@%
  9556.         CASE cPie%@NL@%
  9557.             style1$ = "Percentages"%@NL@%
  9558.             style2$ = "No Percentages"%@NL@%
  9559.     END SELECT%@NL@%
  9560. %@NL@%
  9561.     topRow = 8%@NL@%
  9562.     leftCol = 26%@NL@%
  9563. %@AB@%    ' if pie, line or scatter chart then add data font%@AE@%%@NL@%
  9564.     IF CEnv.ChartType > 2 THEN%@NL@%
  9565.         WindowOpen 1, topRow, leftCol, 19, 47, 0, 7, 0, 7, 15, FALSE, FALSE, FALSE, TRUE, 2, "Chart Style"%@NL@%
  9566.         okLine = 12%@NL@%
  9567. %@NL@%
  9568.         WindowLocate 5, 3%@NL@%
  9569.         WindowPrint -2, "Data Font:"%@NL@%
  9570. %@AB@%        ' set up list box containing valid fonts%@AE@%%@NL@%
  9571.         fontBox.scrollButton = 3%@NL@%
  9572.         fontBox.areaButton = 4%@NL@%
  9573.         fontBox.listLen = numFonts%@NL@%
  9574.         fontBox.topRow = 6%@NL@%
  9575.         fontBox.botRow = 10%@NL@%
  9576.         fontBox.leftCol = 3%@NL@%
  9577.         fontBox.rightCol = 20%@NL@%
  9578.         fontBox.listPos = CEnv.DataFont%@NL@%
  9579.         CreateListBox fonts$(), fontBox, 0%@NL@%
  9580.     ELSE%@NL@%
  9581.         WindowOpen 1, topRow, leftCol, 13, 47, 0, 7, 0, 7, 15, FALSE, FALSE, FALSE, TRUE, 2, "Chart Style"%@NL@%
  9582.         okLine = 6%@NL@%
  9583.     END IF%@NL@%
  9584. %@NL@%
  9585. %@AB@%    ' open buttons%@AE@%%@NL@%
  9586.     ButtonOpen 1, 1, style1$, 2, 3, 1, 0, 3%@NL@%
  9587.     ButtonOpen 2, 1, style2$, 3, 3, 1, 0, 3%@NL@%
  9588.     WindowLine okLine - 1%@NL@%
  9589.     ButtonOpen 5, 2, "OK", okLine, 3, 1, 0, 1%@NL@%
  9590.     ButtonOpen 6, 1, "Cancel", okLine, 11, 1, 0, 1%@NL@%
  9591. %@NL@%
  9592.     pushButton = 5%@NL@%
  9593.     optionButton = CEnv.ChartStyle                     ' set current style%@NL@%
  9594.     currButton = optionButton%@NL@%
  9595.     ButtonSetState optionButton, 2%@NL@%
  9596. %@NL@%
  9597. %@AB@%    ' window control loop%@AE@%%@NL@%
  9598.     finished = FALSE%@NL@%
  9599.     WHILE NOT finished%@NL@%
  9600.         WindowDo currButton, 0                          ' wait for event%@NL@%
  9601.         SELECT CASE Dialog(0)%@NL@%
  9602.             CASE 1                                      'button pressed%@NL@%
  9603.                 currButton = Dialog(1)%@NL@%
  9604.                 SELECT CASE currButton%@NL@%
  9605.                     CASE 1, 2:%@NL@%
  9606.                         ButtonSetState optionButton, 1%@NL@%
  9607.                         optionButton = currButton%@NL@%
  9608.                         ButtonSetState optionButton, 2%@NL@%
  9609.                     CASE 3, 4:%@NL@%
  9610.                         ScrollList fonts$(), fontBox, currButton, 1, 0, topRow, leftCol%@NL@%
  9611.                         currButton = 4%@NL@%
  9612.                     CASE 5, 6:%@NL@%
  9613.                         finished = TRUE%@NL@%
  9614.                 END SELECT%@NL@%
  9615.             CASE 6                                      'enter%@NL@%
  9616.                 finished = TRUE%@NL@%
  9617.             CASE 7                                      'tab%@NL@%
  9618.                 SELECT CASE currButton%@NL@%
  9619.                     CASE 1, 2:%@NL@%
  9620.                         IF CEnv.ChartType > 2 THEN%@NL@%
  9621.                             currButton = 4%@NL@%
  9622.                         ELSE%@NL@%
  9623.                             currButton = 5%@NL@%
  9624.                             ButtonSetState pushButton, 1%@NL@%
  9625.                             pushButton = currButton%@NL@%
  9626.                             ButtonSetState pushButton, 2%@NL@%
  9627.                         END IF%@NL@%
  9628.                     CASE 3, 4:%@NL@%
  9629.                         currButton = 5%@NL@%
  9630.                         ButtonSetState pushButton, 1%@NL@%
  9631.                         pushButton = currButton%@NL@%
  9632.                         ButtonSetState currButton, 2%@NL@%
  9633.                     CASE 5:%@NL@%
  9634.                         currButton = 6%@NL@%
  9635.                         ButtonSetState pushButton, 1%@NL@%
  9636.                         pushButton = currButton%@NL@%
  9637.                         ButtonSetState currButton, 2%@NL@%
  9638.                     CASE 6:%@NL@%
  9639.                         currButton = optionButton%@NL@%
  9640.                         ButtonSetState pushButton, 1%@NL@%
  9641.                         pushButton = 5%@NL@%
  9642.                         ButtonSetState pushButton, 2%@NL@%
  9643.                 END SELECT%@NL@%
  9644.             CASE 8                                      'back tab%@NL@%
  9645.                 SELECT CASE currButton%@NL@%
  9646.                     CASE 1, 2:%@NL@%
  9647.                         currButton = 6%@NL@%
  9648.                         ButtonSetState pushButton, 1%@NL@%
  9649.                         pushButton = currButton%@NL@%
  9650.                         ButtonSetState pushButton, 2%@NL@%
  9651.                     CASE 3, 4:%@NL@%
  9652.                         currButton = optionButton%@NL@%
  9653.                     CASE 5:%@NL@%
  9654.                         IF CEnv.ChartType > 2 THEN%@NL@%
  9655.                             currButton = 4%@NL@%
  9656.                         ELSE%@NL@%
  9657.                             currButton = optionButton%@NL@%
  9658.                         END IF%@NL@%
  9659.                     CASE 6:%@NL@%
  9660.                         currButton = 5%@NL@%
  9661.                         ButtonSetState pushButton, 1%@NL@%
  9662.                         pushButton = currButton%@NL@%
  9663.                         ButtonSetState currButton, 2%@NL@%
  9664.                 END SELECT%@NL@%
  9665.             CASE 9                                      'escape%@NL@%
  9666.                 finished = TRUE%@NL@%
  9667.                 pushButton = 5%@NL@%
  9668.             CASE 10, 12                                 'up, left arrow%@NL@%
  9669.                 SELECT CASE currButton%@NL@%
  9670.                     CASE 1, 2:%@NL@%
  9671.                         ButtonSetState currButton, 1%@NL@%
  9672.                         currButton = 3 - currButton%@NL@%
  9673.                         optionButton = currButton%@NL@%
  9674.                         ButtonSetState currButton, 2%@NL@%
  9675.                     CASE 3, 4:%@NL@%
  9676.                         ScrollList fonts$(), fontBox, currButton, 2, 0, topRow, leftCol%@NL@%
  9677.                 END SELECT%@NL@%
  9678.             CASE 11, 13                                 'down, right arrow%@NL@%
  9679.                 SELECT CASE currButton%@NL@%
  9680.                     CASE 1, 2:%@NL@%
  9681.                         ButtonSetState currButton, 1%@NL@%
  9682.                         currButton = 3 - currButton%@NL@%
  9683.                         optionButton = currButton%@NL@%
  9684.                         ButtonSetState currButton, 2%@NL@%
  9685.                     CASE 3, 4:%@NL@%
  9686.                         ScrollList fonts$(), fontBox, currButton, 3, 0, topRow, leftCol%@NL@%
  9687.                 END SELECT%@NL@%
  9688.             CASE 14                                     'space bar%@NL@%
  9689.                 IF currButton > 4 THEN finished = TRUE%@NL@%
  9690.         END SELECT%@NL@%
  9691.     WEND%@NL@%
  9692. %@NL@%
  9693. %@AB@%    ' if not canceled then set new chart style%@AE@%%@NL@%
  9694.     IF pushButton = 5 THEN%@NL@%
  9695.         IF setNum > 0 THEN chartChanged = TRUE%@NL@%
  9696.         CEnv.ChartStyle = optionButton%@NL@%
  9697.         IF CEnv.ChartType > 2 THEN CEnv.DataFont = fontBox.listPos%@NL@%
  9698.     END IF%@NL@%
  9699. %@NL@%
  9700.     WindowClose 1%@NL@%
  9701. %@NL@%
  9702. END SUB%@NL@%
  9703. %@NL@%
  9704. %@AB@%'%@AE@%%@NL@%
  9705. %@AB@%' Sub Name: ChangeTitle%@AE@%%@NL@%
  9706. %@AB@%'%@AE@%%@NL@%
  9707. %@AB@%' Description: Allows user to view and modify the chart titles%@AE@%%@NL@%
  9708. %@AB@%'%@AE@%%@NL@%
  9709. %@AB@%' Arguments: handle - window number%@AE@%%@NL@%
  9710. %@AB@%'            wTitle$ - window title%@AE@%%@NL@%
  9711. %@AB@%'            title -  chart title%@AE@%%@NL@%
  9712. %@AB@%'            topRow - top row of window%@AE@%%@NL@%
  9713. %@AB@%'            leftCol - left column of window%@AE@%%@NL@%
  9714. %@AB@%'%@AE@%%@NL@%
  9715. SUB ChangeTitle (handle, wTitle$, title AS TitleType, topRow, leftCol)%@NL@%
  9716. SHARED mode$(), numModes AS INTEGER%@NL@%
  9717. %@NL@%
  9718.     DIM colorBox AS ListBox%@NL@%
  9719.     DIM fontBox AS ListBox%@NL@%
  9720. %@NL@%
  9721. %@AB@%    ' set up foreground color box%@AE@%%@NL@%
  9722.     colorBox.scrollButton = 1%@NL@%
  9723.     colorBox.areaButton = 2%@NL@%
  9724.     colorBox.listLen = numColors%@NL@%
  9725.     colorBox.topRow = 6%@NL@%
  9726.     colorBox.botRow = 10%@NL@%
  9727.     colorBox.leftCol = 2%@NL@%
  9728.     colorBox.rightCol = 16%@NL@%
  9729.     colorBox.listPos = title.TitleColor + 1%@NL@%
  9730. %@NL@%
  9731. %@AB@%    ' set up font box%@AE@%%@NL@%
  9732.     fontBox.scrollButton = 3%@NL@%
  9733.     fontBox.areaButton = 4%@NL@%
  9734.     fontBox.listLen = numFonts%@NL@%
  9735.     fontBox.topRow = 6%@NL@%
  9736.     fontBox.botRow = 10%@NL@%
  9737.     fontBox.leftCol = 18%@NL@%
  9738.     fontBox.rightCol = 36%@NL@%
  9739.     fontBox.listPos = title.TitleFont%@NL@%
  9740. %@NL@%
  9741. %@AB@%    ' set up display window%@AE@%%@NL@%
  9742.     WindowOpen handle, topRow, leftCol, topRow + 11, leftCol + 50, 0, 7, 0, 7, 15, FALSE, FALSE, FALSE, TRUE, 2, wTitle$%@NL@%
  9743.     WindowLocate 2, 2%@NL@%
  9744.     WindowPrint 2, "Title:"%@NL@%
  9745.     WindowBox 1, 8, 3, 50%@NL@%
  9746.     WindowBox 6, 38, 10, 50%@NL@%
  9747.     WindowLine 4%@NL@%
  9748.     WindowLine 11%@NL@%
  9749.     WindowLocate 5, 1%@NL@%
  9750.     WindowPrint -1, " Color:          Font:               Justify:"%@NL@%
  9751. %@NL@%
  9752. %@AB@%    ' set color attribute for title editfield background to that of the chart background%@AE@%%@NL@%
  9753.     IF mode$(1) = "10" OR (mode$(1) = "2" AND mode$(2) <> "1") OR mode$(1) = "3" THEN%@NL@%
  9754.         func = 0%@NL@%
  9755.         EditFieldOpen 1, RTRIM$(title.title), 2, 9, 0, 7, 41, 70%@NL@%
  9756.     ELSE%@NL@%
  9757.         SetAtt 5, CEnv.ChartWindow.Background + 1%@NL@%
  9758.         EditFieldOpen 1, RTRIM$(title.title), 2, 9, 12, 5, 41, 70%@NL@%
  9759.         func = 2%@NL@%
  9760.     END IF%@NL@%
  9761. %@NL@%
  9762. %@AB@%    ' create list boxes%@AE@%%@NL@%
  9763.     CreateListBox colors$(), colorBox, func%@NL@%
  9764.     CreateListBox fonts$(), fontBox, 0%@NL@%
  9765. %@NL@%
  9766. %@AB@%    ' open buttons%@AE@%%@NL@%
  9767.     ButtonOpen 5, 1, "Left", 7, 39, 0, 0, 3%@NL@%
  9768.     ButtonOpen 6, 1, "Center", 8, 39, 0, 0, 3%@NL@%
  9769.     ButtonOpen 7, 1, "Right", 9, 39, 0, 0, 3%@NL@%
  9770.     ButtonOpen 8, 2, "OK ", 12, 10, 0, 0, 1%@NL@%
  9771.     ButtonOpen 9, 1, "Cancel ", 12, 33, 0, 0, 1%@NL@%
  9772. %@NL@%
  9773.     currButton = 0                                      ' start in edit field%@NL@%
  9774.     currEditField = 1%@NL@%
  9775.     optionButton = 4 + title.Justify                    ' set button state%@NL@%
  9776.     ButtonToggle optionButton%@NL@%
  9777.     pushButton = 8%@NL@%
  9778. %@NL@%
  9779. %@AB@%    ' window control loop%@AE@%%@NL@%
  9780.     finished = FALSE%@NL@%
  9781.     WHILE NOT finished%@NL@%
  9782.         WindowDo currButton, currEditField              ' wait for event%@NL@%
  9783.         SELECT CASE Dialog(0)%@NL@%
  9784.             CASE 1                                      ' button pressed%@NL@%
  9785.                 currButton = Dialog(1)%@NL@%
  9786.                 SELECT CASE currButton%@NL@%
  9787.                     CASE 1, 2%@NL@%
  9788.                         currEditField = 0%@NL@%
  9789.                         ScrollList colors$(), colorBox, currButton, 1, func, topRow, leftCol%@NL@%
  9790.                         currButton = 2%@NL@%
  9791.                     CASE 3, 4%@NL@%
  9792.                         currEditField = 0%@NL@%
  9793.                         ScrollList fonts$(), fontBox, currButton, 1, 0, topRow, leftCol%@NL@%
  9794.                         currButton = 4%@NL@%
  9795.                     CASE 5, 6, 7%@NL@%
  9796.                         ButtonToggle optionButton%@NL@%
  9797.                         optionButton = currButton%@NL@%
  9798.                         ButtonToggle optionButton%@NL@%
  9799.                         currEditField = 0%@NL@%
  9800.                     CASE 8, 9%@NL@%
  9801.                         pushButton = currButton%@NL@%
  9802.                         finished = TRUE%@NL@%
  9803.                 END SELECT%@NL@%
  9804.             CASE 2                                      ' edit field%@NL@%
  9805.                 currButton = 0%@NL@%
  9806.                 currEditField = 1%@NL@%
  9807.             CASE 6                                      ' enter%@NL@%
  9808.                 finished = TRUE%@NL@%
  9809.             CASE 7                                      ' tab%@NL@%
  9810.                 SELECT CASE currButton%@NL@%
  9811.                     CASE 0:%@NL@%
  9812.                         currButton = 2%@NL@%
  9813.                         currEditField = 0%@NL@%
  9814.                     CASE 1, 2: currButton = 4%@NL@%
  9815.                     CASE 3, 4: currButton = optionButton%@NL@%
  9816.                     CASE 5, 6, 7:%@NL@%
  9817.                         currButton = 8%@NL@%
  9818.                         ButtonSetState pushButton, 1%@NL@%
  9819.                         ButtonSetState currButton, 2%@NL@%
  9820.                         pushButton = 8%@NL@%
  9821.                     CASE 8:%@NL@%
  9822.                         currButton = currButton + 1%@NL@%
  9823.                         ButtonSetState pushButton, 1%@NL@%
  9824.                         ButtonSetState currButton, 2%@NL@%
  9825.                         pushButton = currButton%@NL@%
  9826.                     CASE 9:%@NL@%
  9827.                         ButtonSetState currButton, 1%@NL@%
  9828.                         pushButton = 8%@NL@%
  9829.                         ButtonSetState pushButton, 2%@NL@%
  9830.                         currButton = 0%@NL@%
  9831.                         currEditField = 1%@NL@%
  9832.                 END SELECT%@NL@%
  9833.             CASE 8                                      ' back tab%@NL@%
  9834.                 SELECT CASE currButton%@NL@%
  9835.                     CASE 0:%@NL@%
  9836.                         currButton = 9%@NL@%
  9837.                         ButtonSetState pushButton, 1%@NL@%
  9838.                         ButtonSetState currButton, 2%@NL@%
  9839.                         pushButton = 9%@NL@%
  9840.                         currEditField = 0%@NL@%
  9841.                     CASE 1, 2:%@NL@%
  9842.                         currButton = 0%@NL@%
  9843.                         currEditField = 1%@NL@%
  9844.                     CASE 3, 4: currButton = 2%@NL@%
  9845.                     CASE 5, 6, 7: currButton = 4%@NL@%
  9846.                     CASE 8: currButton = optionButton%@NL@%
  9847.                     CASE 9:%@NL@%
  9848.                         currButton = currButton - 1%@NL@%
  9849.                         ButtonSetState pushButton, 1%@NL@%
  9850.                         ButtonSetState currButton, 2%@NL@%
  9851.                         pushButton = currButton%@NL@%
  9852.                 END SELECT%@NL@%
  9853.             CASE 9                                      ' escape%@NL@%
  9854.                 pushButton = 9%@NL@%
  9855.                 finished = TRUE%@NL@%
  9856.             CASE 10, 12                                 ' up, left arrow%@NL@%
  9857.                 SELECT CASE currButton%@NL@%
  9858.                     CASE 1, 2: ScrollList colors$(), colorBox, currButton, 2, func, topRow, leftCol%@NL@%
  9859.                     CASE 3, 4: ScrollList fonts$(), fontBox, currButton, 2, 0, topRow, leftCol%@NL@%
  9860.                     CASE 5:%@NL@%
  9861.                         ButtonToggle currButton%@NL@%
  9862.                         currButton = 7%@NL@%
  9863.                         optionButton = 7%@NL@%
  9864.                         ButtonToggle optionButton%@NL@%
  9865.                     CASE 6, 7:%@NL@%
  9866.                         ButtonToggle currButton%@NL@%
  9867.                         currButton = currButton - 1%@NL@%
  9868.                         optionButton = currButton%@NL@%
  9869.                         ButtonToggle optionButton%@NL@%
  9870.                 END SELECT%@NL@%
  9871.             CASE 11, 13                                 ' down, right arrow%@NL@%
  9872.                 SELECT CASE currButton%@NL@%
  9873.                     CASE 1, 2: ScrollList colors$(), colorBox, currButton, 3, func, topRow, leftCol%@NL@%
  9874.                     CASE 3, 4: ScrollList fonts$(), fontBox, currButton, 3, 0, topRow, leftCol%@NL@%
  9875.                     CASE 5, 6:%@NL@%
  9876.                         ButtonToggle currButton%@NL@%
  9877.                         currButton = currButton + 1%@NL@%
  9878.                         optionButton = currButton%@NL@%
  9879.                         ButtonToggle optionButton%@NL@%
  9880.                     CASE 7:%@NL@%
  9881.                         ButtonToggle currButton%@NL@%
  9882.                         currButton = 5%@NL@%
  9883.                         optionButton = 5%@NL@%
  9884.                         ButtonToggle optionButton%@NL@%
  9885.                 END SELECT%@NL@%
  9886.             CASE 14                                     ' space bar%@NL@%
  9887.                 IF currButton > 7 THEN%@NL@%
  9888.                     pushButton = currButton%@NL@%
  9889.                     finished = TRUE%@NL@%
  9890.                 END IF%@NL@%
  9891.         END SELECT%@NL@%
  9892.     WEND%@NL@%
  9893. %@NL@%
  9894. %@AB@%    ' done and not canceled so return new title information%@AE@%%@NL@%
  9895.     IF pushButton = 8 THEN%@NL@%
  9896.         IF setNum > 0 THEN chartChanged = TRUE%@NL@%
  9897. %@NL@%
  9898.         title.title = EditFieldInquire(1)%@NL@%
  9899.         title.TitleFont = fontBox.listPos%@NL@%
  9900.         title.TitleColor = colorBox.listPos - 1%@NL@%
  9901.         title.Justify = optionButton - 4%@NL@%
  9902.     END IF%@NL@%
  9903. %@NL@%
  9904.     WindowClose handle%@NL@%
  9905. %@NL@%
  9906. END SUB%@NL@%
  9907. %@NL@%
  9908. %@AB@%'%@AE@%%@NL@%
  9909. %@AB@%' Sub Name: ChangeWindow%@AE@%%@NL@%
  9910. %@AB@%'%@AE@%%@NL@%
  9911. %@AB@%' Description: Allows user to view and modify any of the chart windows%@AE@%%@NL@%
  9912. %@AB@%'%@AE@%%@NL@%
  9913. %@AB@%' Arguments: handle - window number%@AE@%%@NL@%
  9914. %@AB@%'            wTitle$ - window title%@AE@%%@NL@%
  9915. %@AB@%'            win - chart window%@AE@%%@NL@%
  9916. %@AB@%'%@AE@%%@NL@%
  9917. SUB ChangeWindow (handle, title$, win AS RegionType)%@NL@%
  9918. %@NL@%
  9919.     DIM bgColorBox AS ListBox%@NL@%
  9920.     DIM bdColorBox AS ListBox%@NL@%
  9921.     DIM bdStyleBox AS ListBox%@NL@%
  9922. %@NL@%
  9923. %@AB@%    ' set up background color box%@AE@%%@NL@%
  9924.     bgColorBox.scrollButton = 1%@NL@%
  9925.     bgColorBox.areaButton = 2%@NL@%
  9926.     bgColorBox.listLen = numColors%@NL@%
  9927.     bgColorBox.topRow = 4%@NL@%
  9928.     bgColorBox.botRow = 14%@NL@%
  9929.     bgColorBox.leftCol = 4%@NL@%
  9930.     bgColorBox.rightCol = 18%@NL@%
  9931.     bgColorBox.listPos = win.Background + 1%@NL@%
  9932. %@NL@%
  9933. %@AB@%    ' set up border color box%@AE@%%@NL@%
  9934.     bdColorBox.scrollButton = 3%@NL@%
  9935.     bdColorBox.areaButton = 4%@NL@%
  9936.     bdColorBox.listLen = numColors%@NL@%
  9937.     bdColorBox.topRow = 5%@NL@%
  9938.     bdColorBox.botRow = 14%@NL@%
  9939.     bdColorBox.leftCol = 24%@NL@%
  9940.     bdColorBox.rightCol = 38%@NL@%
  9941.     bdColorBox.listPos = win.BorderColor + 1%@NL@%
  9942. %@NL@%
  9943. %@AB@%    ' set up border style box%@AE@%%@NL@%
  9944.     bdStyleBox.scrollButton = 5%@NL@%
  9945.     bdStyleBox.areaButton = 6%@NL@%
  9946.     bdStyleBox.listLen = MAXSTYLES%@NL@%
  9947.     bdStyleBox.topRow = 5%@NL@%
  9948.     bdStyleBox.botRow = 14%@NL@%
  9949.     bdStyleBox.leftCol = 40%@NL@%
  9950.     bdStyleBox.rightCol = 54%@NL@%
  9951.     bdStyleBox.listPos = win.BorderStyle%@NL@%
  9952. %@NL@%
  9953. %@AB@%    ' set up display window%@AE@%%@NL@%
  9954.     winRow = 5%@NL@%
  9955.     winCol = 3%@NL@%
  9956.     WindowOpen handle, winRow, winCol, 21, 76, 0, 7, 0, 7, 15, FALSE, FALSE, FALSE, TRUE, 2, title$%@NL@%
  9957.     WindowBox 1, 2, 15, 20%@NL@%
  9958.     WindowLocate 2, 5%@NL@%
  9959.     WindowPrint 2, "Background"%@NL@%
  9960.     WindowLocate 3, 5%@NL@%
  9961.     WindowPrint 2, "Color:"%@NL@%
  9962.     WindowBox 1, 22, 15, 56%@NL@%
  9963.     WindowLocate 4, 24%@NL@%
  9964.     WindowPrint 2, "Border Color:"%@NL@%
  9965.     WindowLocate 4, 40%@NL@%
  9966.     WindowPrint 2, "Border Style:"%@NL@%
  9967.     WindowBox 1, 58, 15, 73%@NL@%
  9968.     WindowLocate 2, 60%@NL@%
  9969.     WindowPrint 2, "Coordinates:"%@NL@%
  9970.     WindowBox 3, 63, 5, 71%@NL@%
  9971.     WindowLocate 4, 60%@NL@%
  9972.     WindowPrint 2, "X1:"%@NL@%
  9973.     WindowBox 6, 63, 8, 71%@NL@%
  9974.     WindowLocate 7, 60%@NL@%
  9975.     WindowPrint 2, "Y1:"%@NL@%
  9976.     WindowBox 9, 63, 11, 71%@NL@%
  9977.     WindowLocate 10, 60%@NL@%
  9978.     WindowPrint 2, "X2:"%@NL@%
  9979.     WindowBox 12, 63, 14, 71%@NL@%
  9980.     WindowLocate 13, 60%@NL@%
  9981.     WindowPrint 2, "Y2:"%@NL@%
  9982.     WindowLine 16%@NL@%
  9983. %@NL@%
  9984.     CreateListBox colors$(), bgColorBox, 0%@NL@%
  9985.     CreateListBox colors$(), bdColorBox, 0%@NL@%
  9986.     CreateListBox styles$(), bdStyleBox, 0%@NL@%
  9987. %@NL@%
  9988.     ButtonOpen 7, 1, "Display Border", 2, 24, 0, 0, 2%@NL@%
  9989.     ButtonOpen 8, 2, "OK ", 17, 14, 0, 0, 1%@NL@%
  9990.     ButtonOpen 9, 1, "Cancel ", 17, 51, 0, 0, 1%@NL@%
  9991. %@NL@%
  9992.     EditFieldOpen 1, LTRIM$(STR$(win.X1)), 4, 64, 0, 7, 7, 10%@NL@%
  9993.     EditFieldOpen 2, LTRIM$(STR$(win.Y1)), 7, 64, 0, 7, 7, 10%@NL@%
  9994.     EditFieldOpen 3, LTRIM$(STR$(win.X2)), 10, 64, 0, 7, 7, 10%@NL@%
  9995.     EditFieldOpen 4, LTRIM$(STR$(win.Y2)), 13, 64, 0, 7, 7, 10%@NL@%
  9996. %@NL@%
  9997.     currButton = 2                                      ' start in first list box%@NL@%
  9998.     currEditField = 0%@NL@%
  9999.     IF win.border = TRUE THEN ButtonSetState 7, 2%@NL@%
  10000.     pushButton = 8%@NL@%
  10001. %@NL@%
  10002. %@AB@%    ' window control loop%@AE@%%@NL@%
  10003.     finished = FALSE%@NL@%
  10004.     WHILE NOT finished%@NL@%
  10005.         WindowDo currButton, currEditField              ' wait for event%@NL@%
  10006.         SELECT CASE Dialog(0)%@NL@%
  10007.             CASE 1                                      ' button pressed%@NL@%
  10008.                 currButton = Dialog(1)%@NL@%
  10009.                 SELECT CASE currButton%@NL@%
  10010.                     CASE 1, 2%@NL@%
  10011.                         currEditField = 0%@NL@%
  10012.                         ScrollList colors$(), bgColorBox, currButton, 1, 0, winRow, winCol%@NL@%
  10013.                         currButton = 2%@NL@%
  10014.                     CASE 3, 4%@NL@%
  10015.                         currEditField = 0%@NL@%
  10016.                         ScrollList colors$(), bdColorBox, currButton, 1, 0, winRow, winCol%@NL@%
  10017.                         currButton = 4%@NL@%
  10018.                     CASE 5, 6%@NL@%
  10019.                         currEditField = 0%@NL@%
  10020.                         ScrollList styles$(), bdStyleBox, currButton, 1, 0, winRow, winCol%@NL@%
  10021.                         currButton = 6%@NL@%
  10022.                     CASE 7%@NL@%
  10023.                         ButtonToggle currButton%@NL@%
  10024.                         currEditField = 0%@NL@%
  10025.                     CASE 8, 9%@NL@%
  10026.                         pushButton = currButton%@NL@%
  10027.                         finished = TRUE%@NL@%
  10028.                 END SELECT%@NL@%
  10029.             CASE 2                                      ' edit field%@NL@%
  10030.                 currEditField = Dialog(2)%@NL@%
  10031.                 currButton = 0%@NL@%
  10032.             CASE 6                                      ' enter%@NL@%
  10033.                 finished = TRUE%@NL@%
  10034.             CASE 7                                      ' tab%@NL@%
  10035.                 SELECT CASE currButton%@NL@%
  10036.                     CASE 0:%@NL@%
  10037.                         SELECT CASE currEditField%@NL@%
  10038.                             CASE 1, 2, 3: currEditField = currEditField + 1%@NL@%
  10039.                             CASE 4:%@NL@%
  10040.                                 currEditField = 0%@NL@%
  10041.                                 currButton = 8%@NL@%
  10042.                                 ButtonSetState pushButton, 1%@NL@%
  10043.                                 ButtonSetState currButton, 2%@NL@%
  10044.                                 pushButton = currButton%@NL@%
  10045.                         END SELECT%@NL@%
  10046.                     CASE 1, 2: currButton = 7%@NL@%
  10047.                     CASE 3, 4: currButton = 6%@NL@%
  10048.                     CASE 5, 6:%@NL@%
  10049.                         currButton = 0%@NL@%
  10050.                         currEditField = 1%@NL@%
  10051.                     CASE 7: currButton = 4%@NL@%
  10052.                     CASE 8:%@NL@%
  10053.                         currButton = currButton + 1%@NL@%
  10054.                         ButtonSetState pushButton, 1%@NL@%
  10055.                         ButtonSetState currButton, 2%@NL@%
  10056.                         pushButton = currButton%@NL@%
  10057.                     CASE 9:%@NL@%
  10058.                         ButtonSetState currButton, 1%@NL@%
  10059.                         pushButton = 8%@NL@%
  10060.                         ButtonSetState pushButton, 2%@NL@%
  10061.                         currButton = 2%@NL@%
  10062.                         currEditField = 0%@NL@%
  10063.                 END SELECT%@NL@%
  10064.             CASE 8                                      ' back tab%@NL@%
  10065.                 SELECT CASE currButton%@NL@%
  10066.                     CASE 0:%@NL@%
  10067.                         SELECT CASE currEditField%@NL@%
  10068.                             CASE 1:%@NL@%
  10069.                                 currEditField = 0%@NL@%
  10070.                                 currButton = 6%@NL@%
  10071.                             CASE 2, 3, 4: currEditField = currEditField - 1%@NL@%
  10072.                         END SELECT%@NL@%
  10073.                     CASE 1, 2:%@NL@%
  10074.                         currButton = 9%@NL@%
  10075.                         ButtonSetState pushButton, 1%@NL@%
  10076.                         ButtonSetState currButton, 2%@NL@%
  10077.                         pushButton = currButton%@NL@%
  10078.                     CASE 3, 4: currButton = 7%@NL@%
  10079.                     CASE 5, 6: currButton = 4%@NL@%
  10080.                     CASE 7: currButton = 2%@NL@%
  10081.                     CASE 8:%@NL@%
  10082.                         currButton = 0%@NL@%
  10083.                         currEditField = 4%@NL@%
  10084.                     CASE 9:%@NL@%
  10085.                         currButton = currButton - 1%@NL@%
  10086.                         ButtonSetState pushButton, 1%@NL@%
  10087.                         ButtonSetState currButton, 2%@NL@%
  10088.                         pushButton = currButton%@NL@%
  10089.                 END SELECT%@NL@%
  10090.             CASE 9                                      ' escape%@NL@%
  10091.                 pushButton = 9%@NL@%
  10092.                 finished = TRUE%@NL@%
  10093.             CASE 10, 12                                 ' up, left arrow%@NL@%
  10094.                 SELECT CASE currButton%@NL@%
  10095.                     CASE 1, 2: ScrollList colors$(), bgColorBox, currButton, 2, 0, winRow, winCol%@NL@%
  10096.                     CASE 3, 4: ScrollList colors$(), bdColorBox, currButton, 2, 0, winRow, winCol%@NL@%
  10097.                     CASE 5, 6: ScrollList styles$(), bdStyleBox, currButton, 2, 0, winRow, winCol%@NL@%
  10098.                     CASE 7: ButtonSetState currButton, 2%@NL@%
  10099.                 END SELECT%@NL@%
  10100.             CASE 11, 13                                 ' down, right arrow%@NL@%
  10101.                 SELECT CASE currButton%@NL@%
  10102.                     CASE 1, 2: ScrollList colors$(), bgColorBox, currButton, 3, 0, winRow, winCol%@NL@%
  10103.                     CASE 3, 4: ScrollList colors$(), bdColorBox, currButton, 3, 0, winRow, winCol%@NL@%
  10104.                     CASE 5, 6: ScrollList styles$(), bdStyleBox, currButton, 3, 0, winRow, winCol%@NL@%
  10105.                     CASE 7: ButtonSetState currButton, 1%@NL@%
  10106.                 END SELECT%@NL@%
  10107.             CASE 14                                     ' space bar%@NL@%
  10108.                 SELECT CASE currButton%@NL@%
  10109.                     CASE 7: ButtonToggle currButton%@NL@%
  10110.                     CASE 8, 9: finished = TRUE%@NL@%
  10111.                 END SELECT%@NL@%
  10112.         END SELECT%@NL@%
  10113.     WEND%@NL@%
  10114. %@NL@%
  10115. %@AB@%    ' return new window information%@AE@%%@NL@%
  10116.     IF pushButton = 8 THEN%@NL@%
  10117.         IF setNum > 0 THEN chartChanged = TRUE%@NL@%
  10118. %@NL@%
  10119.         win.X1 = VAL(EditFieldInquire(1))%@NL@%
  10120.         win.Y1 = VAL(EditFieldInquire(2))%@NL@%
  10121.         win.X2 = VAL(EditFieldInquire(3))%@NL@%
  10122.         win.Y2 = VAL(EditFieldInquire(4))%@NL@%
  10123.         win.Background = bgColorBox.listPos - 1%@NL@%
  10124.         win.border = (ButtonInquire(7) = 2)%@NL@%
  10125.         win.BorderColor = bdColorBox.listPos - 1%@NL@%
  10126.         win.BorderStyle = bdStyleBox.listPos%@NL@%
  10127.     END IF%@NL@%
  10128. %@NL@%
  10129.     WindowClose handle%@NL@%
  10130. %@NL@%
  10131. END SUB%@NL@%
  10132. %@NL@%
  10133. %@NL@%
  10134. %@NL@%
  10135. %@2@%%@AH@%CHRTDEM2.BAS%@AE@%%@EH@%%@NL@%
  10136. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\CHRTDEM2.BAS%@AE@%%@NL@%
  10137. %@NL@%
  10138. %@AB@%'       CHRTDEM2.BAS - third module of the CHRTB demonstration program.%@AE@%%@NL@%
  10139. %@AB@%'%@AE@%%@NL@%
  10140. %@AB@%'               Copyright (C) 1989, Microsoft Corporation%@AE@%%@NL@%
  10141. %@AB@%'%@AE@%%@NL@%
  10142. %@AB@%'   Main module - CHRTDEMO.BAS%@AE@%%@NL@%
  10143. %@AB@%'   Include files - CHRTDEMO.BI%@AE@%%@NL@%
  10144. %@AB@%'%@AE@%%@NL@%
  10145. %@AB@%'$INCLUDE: 'chrtdemo.bi'%@AE@%%@NL@%
  10146. %@NL@%
  10147. %@AB@%' local functions%@AE@%%@NL@%
  10148. DECLARE FUNCTION TrueColr% (colr%)%@NL@%
  10149. %@NL@%
  10150. %@AB@%' local subs%@AE@%%@NL@%
  10151. DECLARE SUB OpenChart (newFlag%)%@NL@%
  10152. DECLARE SUB Quit ()%@NL@%
  10153. DECLARE SUB InitFonts ()%@NL@%
  10154. DECLARE SUB InitStyles ()%@NL@%
  10155. DECLARE SUB SetDisplayColor ()%@NL@%
  10156. DECLARE SUB SetUpBackground ()%@NL@%
  10157. DECLARE SUB SetUpMenu ()%@NL@%
  10158. DECLARE SUB ViewChart ()%@NL@%
  10159. DECLARE SUB ViewFont ()%@NL@%
  10160. DECLARE SUB ViewScreenMode ()%@NL@%
  10161. %@NL@%
  10162. DIM colorDisplay            AS INTEGER%@NL@%
  10163. DIM egacolor(0 TO 15)       AS INTEGER%@NL@%
  10164. DIM origPath$%@NL@%
  10165. %@NL@%
  10166. DEFINT A-Z%@NL@%
  10167. %@AB@%'%@AE@%%@NL@%
  10168. %@AB@%' Sub Name: ClearData%@AE@%%@NL@%
  10169. %@AB@%'%@AE@%%@NL@%
  10170. %@AB@%' Description: Clears all chart data%@AE@%%@NL@%
  10171. %@AB@%' Arguments: None%@AE@%%@NL@%
  10172. %@AB@%'%@AE@%%@NL@%
  10173. SUB ClearData%@NL@%
  10174. SHARED Cat$(), catLen AS INTEGER%@NL@%
  10175. SHARED setVal!(), setLen() AS INTEGER, setName$()%@NL@%
  10176. %@NL@%
  10177. %@AB@%    ' Can't view  chart when no data present%@AE@%%@NL@%
  10178.     MenuSetState VIEWTITLE, 2, 0%@NL@%
  10179. %@NL@%
  10180. %@AB@%    ' Clear categories%@AE@%%@NL@%
  10181.     FOR i = 1 TO cMaxValues%@NL@%
  10182.         Cat$(i) = ""%@NL@%
  10183.     NEXT i%@NL@%
  10184.     catLen = 0%@NL@%
  10185. %@NL@%
  10186. %@AB@%    ' Clear set names and values%@AE@%%@NL@%
  10187.     FOR i = 1 TO cMaxSets%@NL@%
  10188.         setName$(i) = ""%@NL@%
  10189.         setLen(i) = 0%@NL@%
  10190.         FOR j = 1 TO cMaxValues%@NL@%
  10191.             setVal!(j, i) = cMissingValue%@NL@%
  10192.         NEXT j%@NL@%
  10193.     NEXT i%@NL@%
  10194.     setNum = 0%@NL@%
  10195. %@NL@%
  10196. %@AB@%    ' chart not changed%@AE@%%@NL@%
  10197.     chartChanged = FALSE%@NL@%
  10198. %@NL@%
  10199. END SUB%@NL@%
  10200. %@NL@%
  10201. %@AB@%'%@AE@%%@NL@%
  10202. %@AB@%' Sub Name: ClearFonts%@AE@%%@NL@%
  10203. %@AB@%'%@AE@%%@NL@%
  10204. %@AB@%' Description: Sets all chart font pointers to 1.  This is called%@AE@%%@NL@%
  10205. %@AB@%'              each time new fonts are loaded to ensure that%@AE@%%@NL@%
  10206. %@AB@%'              all chart fonts specify a meaningful font%@AE@%%@NL@%
  10207. %@AB@%'%@AE@%%@NL@%
  10208. %@AB@%' Arguments: None%@AE@%%@NL@%
  10209. %@AB@%'%@AE@%%@NL@%
  10210. SUB ClearFonts%@NL@%
  10211. %@NL@%
  10212. %@AB@%    ' reset all font pointers if don't map to current fonts%@AE@%%@NL@%
  10213.     IF CEnv.DataFont > numFonts THEN CEnv.DataFont = 1%@NL@%
  10214.     IF CEnv.MainTitle.TitleFont > numFonts THEN CEnv.MainTitle.TitleFont = 1%@NL@%
  10215.     IF CEnv.SubTitle.TitleFont > numFonts THEN CEnv.SubTitle.TitleFont = 1%@NL@%
  10216.     IF CEnv.XAxis.AxisTitle.TitleFont > numFonts THEN CEnv.XAxis.AxisTitle.TitleFont = 1%@NL@%
  10217.     IF CEnv.XAxis.TicFont > numFonts THEN CEnv.XAxis.TicFont = 1%@NL@%
  10218.     IF CEnv.YAxis.AxisTitle.TitleFont > numFonts THEN CEnv.YAxis.AxisTitle.TitleFont = 1%@NL@%
  10219.     IF CEnv.YAxis.TicFont > numFonts THEN CEnv.YAxis.TicFont = 1%@NL@%
  10220.     IF CEnv.Legend.TextFont > numFonts THEN CEnv.Legend.TextFont = 1%@NL@%
  10221. %@NL@%
  10222. END SUB%@NL@%
  10223. %@NL@%
  10224. %@AB@%'%@AE@%%@NL@%
  10225. %@AB@%' Sub Name: CreateListBox%@AE@%%@NL@%
  10226. %@AB@%'%@AE@%%@NL@%
  10227. %@AB@%' Description: Creates a list box within the current window%@AE@%%@NL@%
  10228. %@AB@%' Arguments: text$() - the list%@AE@%%@NL@%
  10229. %@AB@%'            tbox    - the listBox%@AE@%%@NL@%
  10230. %@AB@%'            func    - function flag for DrawList%@AE@%%@NL@%
  10231. %@AB@%'%@AE@%%@NL@%
  10232. SUB CreateListBox (text$(), tbox AS ListBox, func)%@NL@%
  10233. %@NL@%
  10234. %@AB@%    ' get box length%@AE@%%@NL@%
  10235.     tbox.boxLen = tbox.botRow - tbox.topRow - 1%@NL@%
  10236. %@NL@%
  10237. %@AB@%    ' get displayable length%@AE@%%@NL@%
  10238.     IF tbox.listLen < tbox.boxLen THEN%@NL@%
  10239.         tbox.maxLen = tbox.listLen%@NL@%
  10240.     ELSE%@NL@%
  10241.         tbox.maxLen = tbox.boxLen%@NL@%
  10242.     END IF%@NL@%
  10243. %@NL@%
  10244. %@AB@%    ' get box width%@AE@%%@NL@%
  10245.     tbox.boxWid = tbox.rightCol - tbox.leftCol - 1%@NL@%
  10246. %@NL@%
  10247. %@AB@%    ' create box%@AE@%%@NL@%
  10248.     WindowBox tbox.topRow, tbox.leftCol, tbox.botRow, tbox.rightCol%@NL@%
  10249. %@NL@%
  10250. %@AB@%    ' add scroll bar if necessary or if forced (func = 5)%@AE@%%@NL@%
  10251.     IF tbox.listLen <> tbox.maxLen OR func = 5 THEN%@NL@%
  10252.         ButtonOpen tbox.scrollButton, 1, "", tbox.topRow + 1, tbox.rightCol, tbox.botRow - 1, tbox.rightCol, 6%@NL@%
  10253.     ELSE%@NL@%
  10254.         tbox.scrollButton = 0%@NL@%
  10255.     END IF%@NL@%
  10256. %@NL@%
  10257. %@AB@%    ' open area button%@AE@%%@NL@%
  10258.     ButtonOpen tbox.areaButton, 1, "", tbox.topRow + 1, tbox.leftCol + 1, tbox.botRow - 1, tbox.rightCol - 1, 4%@NL@%
  10259. %@NL@%
  10260. %@AB@%    ' set current list element relative to list box top%@AE@%%@NL@%
  10261.     IF tbox.listPos <= tbox.maxLen THEN%@NL@%
  10262.         tbox.currTop = 1%@NL@%
  10263.         tbox.currPos = tbox.listPos%@NL@%
  10264.     ELSEIF tbox.listPos + tbox.maxLen > tbox.listLen + 1 THEN%@NL@%
  10265.         tbox.currTop = tbox.listLen - tbox.maxLen + 1%@NL@%
  10266.         tbox.currPos = tbox.listPos - tbox.currTop + 1%@NL@%
  10267.     ELSE%@NL@%
  10268.         tbox.currTop = tbox.listPos%@NL@%
  10269.         tbox.currPos = 1%@NL@%
  10270.     END IF%@NL@%
  10271. %@NL@%
  10272. %@AB@%    ' Display list within the box%@AE@%%@NL@%
  10273.     DrawList text$(), tbox, func%@NL@%
  10274. %@NL@%
  10275. END SUB%@NL@%
  10276. %@NL@%
  10277. %@AB@%'%@AE@%%@NL@%
  10278. %@AB@%' Sub Name: DrawList%@AE@%%@NL@%
  10279. %@AB@%'%@AE@%%@NL@%
  10280. %@AB@%' Description: Displays a list within the boundaries of a list box%@AE@%%@NL@%
  10281. %@AB@%' Arguments: text$() - the list%@AE@%%@NL@%
  10282. %@AB@%'            tbox    - the listBox%@AE@%%@NL@%
  10283. %@AB@%'            func    - function flag for special operations%@AE@%%@NL@%
  10284. %@AB@%'%@AE@%%@NL@%
  10285. SUB DrawList (text$(), tbox AS ListBox, func)%@NL@%
  10286. %@NL@%
  10287. %@AB@%    ' Draw each element of list that should currently appear in box%@AE@%%@NL@%
  10288.     FOR i% = 1 TO tbox.boxLen%@NL@%
  10289. %@AB@%        ' highlight current list element%@AE@%%@NL@%
  10290.         IF i% = tbox.currPos THEN%@NL@%
  10291.             WindowColor 7, 0%@NL@%
  10292.         ELSE%@NL@%
  10293.             WindowColor 0, 7%@NL@%
  10294.         END IF%@NL@%
  10295. %@NL@%
  10296.         WindowLocate tbox.topRow + i%, tbox.leftCol + 1%@NL@%
  10297.         IF i <= tbox.maxLen THEN%@NL@%
  10298.             WindowPrint -1, LEFT$(text$(tbox.currTop + i% - 1) + STRING$(tbox.boxWid, " "), tbox.boxWid)%@NL@%
  10299.         ELSE%@NL@%
  10300.             WindowPrint -1, STRING$(tbox.boxWid, " ")%@NL@%
  10301.         END IF%@NL@%
  10302.     NEXT i%%@NL@%
  10303. %@NL@%
  10304. %@AB@%    ' update scrollbar position indicator if scrollbar present%@AE@%%@NL@%
  10305.     IF tbox.scrollButton <> 0 THEN%@NL@%
  10306.         IF tbox.listLen <> 0 THEN%@NL@%
  10307.             position = (tbox.currTop + tbox.currPos - 1) * (tbox.maxLen - 2) / tbox.listLen%@NL@%
  10308.             IF position < 1 THEN%@NL@%
  10309.                position = 1%@NL@%
  10310.             ELSEIF position > tbox.maxLen - 2 THEN%@NL@%
  10311.               position = tbox.maxLen - 2%@NL@%
  10312.             END IF%@NL@%
  10313.         ELSE%@NL@%
  10314.             position = 1%@NL@%
  10315.         END IF%@NL@%
  10316.         ButtonSetState tbox.scrollButton, position%@NL@%
  10317.     END IF%@NL@%
  10318. %@NL@%
  10319. %@AB@%    ' Reset color in case current element was last to be drawn%@AE@%%@NL@%
  10320.     WindowColor 0, 7%@NL@%
  10321. %@NL@%
  10322. %@AB@%    ' update current position in case list has been scrolled%@AE@%%@NL@%
  10323.     tbox.listPos = tbox.currTop + tbox.currPos - 1%@NL@%
  10324. %@NL@%
  10325. %@AB@%    ' handle special operation of immediately updating colors$ in title editfield%@AE@%%@NL@%
  10326.     SELECT CASE func%@NL@%
  10327.         CASE 2: SetAtt 12, tbox.listPos          ' update title editfield foreground color%@NL@%
  10328.     END SELECT%@NL@%
  10329. %@NL@%
  10330. END SUB%@NL@%
  10331. %@NL@%
  10332. %@AB@%'%@AE@%%@NL@%
  10333. %@AB@%' Func Name: HandleMenuEvent%@AE@%%@NL@%
  10334. %@AB@%'%@AE@%%@NL@%
  10335. %@AB@%' Description: Determines the action to be performed when user makes%@AE@%%@NL@%
  10336. %@AB@%'              a menu selection.%@AE@%%@NL@%
  10337. %@AB@%'%@AE@%%@NL@%
  10338. %@AB@%' Arguments: none%@AE@%%@NL@%
  10339. %@AB@%'%@AE@%%@NL@%
  10340. SUB HandleMenuEvent%@NL@%
  10341. SHARED saveFile$, colorDisplay AS INTEGER%@NL@%
  10342. %@NL@%
  10343.     menu = MenuCheck(0)%@NL@%
  10344.     item = MenuCheck(1)%@NL@%
  10345. %@NL@%
  10346.     SELECT CASE menu%@NL@%
  10347. %@AB@%        ' file menu title selection%@AE@%%@NL@%
  10348.         CASE FILETITLE%@NL@%
  10349.             SELECT CASE item%@NL@%
  10350. %@AB@%                ' new chart%@AE@%%@NL@%
  10351.                 CASE 1: OpenChart TRUE%@NL@%
  10352. %@AB@%                ' open existing chart%@AE@%%@NL@%
  10353.                 CASE 2: OpenChart FALSE%@NL@%
  10354. %@AB@%                ' save current chart%@AE@%%@NL@%
  10355.                 CASE 3: junk = SaveChart(saveFile$, FALSE)%@NL@%
  10356. %@AB@%                ' save current chart under new name%@AE@%%@NL@%
  10357.                 CASE 4: junk = SaveChart(saveFile$, TRUE)%@NL@%
  10358. %@AB@%                ' exit program%@AE@%%@NL@%
  10359.                 CASE 6: Quit%@NL@%
  10360.             END SELECT%@NL@%
  10361. %@NL@%
  10362. %@AB@%        ' view menu title selection%@AE@%%@NL@%
  10363.         CASE VIEWTITLE%@NL@%
  10364.             SELECT CASE item%@NL@%
  10365. %@AB@%                ' Display and edit existing chart data%@AE@%%@NL@%
  10366.                 CASE 1: ViewData%@NL@%
  10367. %@AB@%                ' Display chart%@AE@%%@NL@%
  10368.                 CASE 2: ViewChart%@NL@%
  10369. %@AB@%                ' Display and load fonts%@AE@%%@NL@%
  10370.                 CASE 3: ViewFont%@NL@%
  10371. %@AB@%                ' Display and edit screen mode%@AE@%%@NL@%
  10372.                 CASE 4: ViewScreenMode%@NL@%
  10373.             END SELECT%@NL@%
  10374. %@NL@%
  10375. %@AB@%        ' Gallery menu title selection%@AE@%%@NL@%
  10376.         CASE GALLERYTITLE%@NL@%
  10377. %@AB@%            ' change chart type%@AE@%%@NL@%
  10378.             ChangeChartType item%@NL@%
  10379. %@NL@%
  10380. %@AB@%        ' Chart menu title selection%@AE@%%@NL@%
  10381.         CASE CHARTTITLE%@NL@%
  10382.             SELECT CASE item%@NL@%
  10383. %@AB@%                ' Change chart window%@AE@%%@NL@%
  10384.                 CASE 1: ChangeWindow 1, "Chart Window", CEnv.ChartWindow%@NL@%
  10385. %@AB@%                ' Change data window%@AE@%%@NL@%
  10386.                 CASE 2: ChangeWindow 1, "Data Window", CEnv.DataWindow%@NL@%
  10387. %@AB@%                ' Change legend%@AE@%%@NL@%
  10388.                 CASE 3: ChangeLegend%@NL@%
  10389. %@AB@%                ' Change X axis%@AE@%%@NL@%
  10390.                 CASE 4: ChangeAxis "X Axis", CEnv.XAxis%@NL@%
  10391. %@AB@%                ' Change Y axis%@AE@%%@NL@%
  10392.                 CASE 5: ChangeAxis "Y Axis", CEnv.YAxis%@NL@%
  10393.             END SELECT%@NL@%
  10394. %@NL@%
  10395. %@AB@%        ' Title menu title selection%@AE@%%@NL@%
  10396.         CASE TITLETITLE%@NL@%
  10397.             SELECT CASE item%@NL@%
  10398. %@AB@%                ' Display and modify main title%@AE@%%@NL@%
  10399.                 CASE 1: ChangeTitle 1, "Main Title", CEnv.MainTitle, 6, 16%@NL@%
  10400. %@AB@%                ' Display and modify sub title%@AE@%%@NL@%
  10401.                 CASE 2: ChangeTitle 1, "Sub Title", CEnv.SubTitle, 6, 16%@NL@%
  10402. %@AB@%                ' Display and modify x axis title%@AE@%%@NL@%
  10403.                 CASE 3:%@NL@%
  10404.                     ChangeTitle 1, "X-axis Title", CEnv.XAxis.AxisTitle, 6, 16%@NL@%
  10405.                     CEnv.XAxis.ScaleTitle.TitleColor = CEnv.XAxis.AxisTitle.TitleColor%@NL@%
  10406.                     CEnv.XAxis.ScaleTitle.Justify = CEnv.XAxis.AxisTitle.Justify%@NL@%
  10407. %@AB@%                ' Display and modify y axis title%@AE@%%@NL@%
  10408.                 CASE 4:%@NL@%
  10409.                     ChangeTitle 1, "Y-axis Title", CEnv.YAxis.AxisTitle, 6, 16%@NL@%
  10410.                     CEnv.YAxis.ScaleTitle.TitleColor = CEnv.YAxis.AxisTitle.TitleColor%@NL@%
  10411.                     CEnv.YAxis.ScaleTitle.Justify = CEnv.YAxis.AxisTitle.Justify%@NL@%
  10412.             END SELECT%@NL@%
  10413. %@NL@%
  10414. %@AB@%        ' Options menu title selection%@AE@%%@NL@%
  10415.         CASE OPTIONSTITLE%@NL@%
  10416.             colorDisplay = item - 2%@NL@%
  10417.             SetDisplayColor%@NL@%
  10418.     END SELECT%@NL@%
  10419. %@NL@%
  10420. END SUB%@NL@%
  10421. %@NL@%
  10422. %@AB@%'%@AE@%%@NL@%
  10423. %@AB@%' Func Name: InitAll%@AE@%%@NL@%
  10424. %@AB@%'%@AE@%%@NL@%
  10425. %@AB@%' Description: Performs all initialization for the program%@AE@%%@NL@%
  10426. %@AB@%'%@AE@%%@NL@%
  10427. %@AB@%' Arguments: none%@AE@%%@NL@%
  10428. %@AB@%'%@AE@%%@NL@%
  10429. SUB InitAll%@NL@%
  10430. SHARED finished AS INTEGER, screenMode AS INTEGER, saveFile$%@NL@%
  10431. SHARED origPath$, colorDisplay  AS INTEGER%@NL@%
  10432. %@NL@%
  10433.     saveFile$ = ""                          ' No save file to begin with%@NL@%
  10434.     origPath$ = CURDIR$                     ' get working path%@NL@%
  10435.     colorDisplay = FALSE                    ' start with mono display%@NL@%
  10436.     GetBestMode screenMode                  ' get initial screen mode%@NL@%
  10437. %@NL@%
  10438.     SCREEN 0                                ' init screen%@NL@%
  10439.     WIDTH 80, 25%@NL@%
  10440.     CLS%@NL@%
  10441. %@NL@%
  10442.     MenuInit                                ' init menu routines%@NL@%
  10443.     WindowInit                              ' init window routines%@NL@%
  10444.     MouseInit                               ' init mouse routines%@NL@%
  10445. %@NL@%
  10446. %@AB@%    ' exit if no graphic mode available%@AE@%%@NL@%
  10447.     IF screenMode = 0 THEN%@NL@%
  10448.         PrintError "No graphic screen modes available for charting. Exiting program."%@NL@%
  10449.         finished = TRUE%@NL@%
  10450.         EXIT SUB%@NL@%
  10451.     ELSE%@NL@%
  10452.         finished = FALSE%@NL@%
  10453.     END IF%@NL@%
  10454. %@NL@%
  10455.     SetUpMenu                               ' Set up menu bar%@NL@%
  10456.     SetUpBackground                         ' Set up screen background%@NL@%
  10457.     InitChart                               ' Initialize chart%@NL@%
  10458.     InitColors                              ' Set up color list%@NL@%
  10459.     InitStyles                              ' Set up border style list%@NL@%
  10460.     InitFonts                               ' Set up font lists%@NL@%
  10461. %@NL@%
  10462.     MenuShow                                ' display menu bar%@NL@%
  10463.     MouseShow                               ' display mouse%@NL@%
  10464. %@NL@%
  10465. %@AB@%    '               display program introduction%@AE@%%@NL@%
  10466.     a$ = "Microsoft QuickChart|"%@NL@%
  10467.     a$ = a$ + "A Presentation Graphics Toolbox Demo|"%@NL@%
  10468.     a$ = a$ + "for|"%@NL@%
  10469.     a$ = a$ + "Microsoft BASIC 7.0 Professional Development System|"%@NL@%
  10470.     a$ = a$ + "Copyright (c) 1989 Microsoft Corporation|"%@NL@%
  10471. %@NL@%
  10472.     temp = Alert(4, a$, 9, 12, 15, 68, "Color", "Monochrome", "")%@NL@%
  10473. %@NL@%
  10474. %@AB@%    ' set display to color or monochrome depending on colorDislay%@AE@%%@NL@%
  10475.     IF temp = 1 THEN colorDisplay = TRUE%@NL@%
  10476. %@NL@%
  10477.     SetDisplayColor%@NL@%
  10478. %@NL@%
  10479. END SUB%@NL@%
  10480. %@NL@%
  10481. %@AB@%'%@AE@%%@NL@%
  10482. %@AB@%' Sub Name: InitChart%@AE@%%@NL@%
  10483. %@AB@%'%@AE@%%@NL@%
  10484. %@AB@%' Description: Initializes chart environment variables and other%@AE@%%@NL@%
  10485. %@AB@%'              related information.%@AE@%%@NL@%
  10486. %@AB@%'%@AE@%%@NL@%
  10487. %@AB@%' Arguments: None%@AE@%%@NL@%
  10488. %@AB@%'%@AE@%%@NL@%
  10489. SUB InitChart%@NL@%
  10490. %@NL@%
  10491.     MenuItemToggle GALLERYTITLE, cBar       ' default chart type is BAR so%@NL@%
  10492. %@AB@%                                            ' set up menu that way%@AE@%%@NL@%
  10493. %@NL@%
  10494.     DefaultChart CEnv, cBar, cPlain         ' Get defaults for chart variable%@NL@%
  10495. %@NL@%
  10496.     ClearData                               ' Clear all chart data%@NL@%
  10497. %@NL@%
  10498. END SUB%@NL@%
  10499. %@NL@%
  10500. %@AB@%'%@AE@%%@NL@%
  10501. %@AB@%' Sub Name: Initcolors%@AE@%%@NL@%
  10502. %@AB@%'%@AE@%%@NL@%
  10503. %@AB@%' Description: Creates color list based on screen mode%@AE@%%@NL@%
  10504. %@AB@%'%@AE@%%@NL@%
  10505. %@AB@%' Arguments: None%@AE@%%@NL@%
  10506. %@AB@%'%@AE@%%@NL@%
  10507. SUB InitColors%@NL@%
  10508. SHARED screenMode AS INTEGER%@NL@%
  10509. SHARED egacolor() AS INTEGER%@NL@%
  10510. %@NL@%
  10511. %@AB@%    ' init EGA colors$ for SetAtt%@AE@%%@NL@%
  10512.     egacolor(0) = 0%@NL@%
  10513.     egacolor(1) = 1%@NL@%
  10514.     egacolor(2) = 2%@NL@%
  10515.     egacolor(3) = 3%@NL@%
  10516.     egacolor(4) = 4%@NL@%
  10517.     egacolor(5) = 5%@NL@%
  10518.     egacolor(6) = 20%@NL@%
  10519.     egacolor(7) = 7%@NL@%
  10520.     egacolor(8) = 56%@NL@%
  10521.     egacolor(9) = 57%@NL@%
  10522.     egacolor(10) = 58%@NL@%
  10523.     egacolor(11) = 59%@NL@%
  10524.     egacolor(12) = 60%@NL@%
  10525.     egacolor(13) = 61%@NL@%
  10526.     egacolor(14) = 62%@NL@%
  10527.     egacolor(15) = 63%@NL@%
  10528. %@NL@%
  10529. %@AB@%    ' create list of displayable colors$ based on screen mode%@AE@%%@NL@%
  10530.     SELECT CASE screenMode%@NL@%
  10531.         CASE 1%@NL@%
  10532.             numColors = 4%@NL@%
  10533.             REDIM color$(numColors)%@NL@%
  10534.             colors$(1) = "Black"%@NL@%
  10535.             colors$(2) = "White"%@NL@%
  10536.             colors$(3) = "Bright Cyan"%@NL@%
  10537.             colors$(4) = "Bright Magenta"%@NL@%
  10538.         CASE 2, 3, 4, 11%@NL@%
  10539.             numColors = 2%@NL@%
  10540.             REDIM color$(numColors)%@NL@%
  10541.             colors$(1) = "Black"%@NL@%
  10542.             colors$(2) = "White"%@NL@%
  10543.         CASE 7, 8, 9, 12, 13%@NL@%
  10544.             numColors = 16%@NL@%
  10545.             REDIM color$(numColors)%@NL@%
  10546.             colors$(1) = "Black"%@NL@%
  10547.             colors$(2) = "High White"%@NL@%
  10548.             colors$(3) = "Blue"%@NL@%
  10549.             colors$(4) = "Green"%@NL@%
  10550.             colors$(5) = "Cyan"%@NL@%
  10551.             colors$(6) = "Red"%@NL@%
  10552.             colors$(7) = "Magenta"%@NL@%
  10553.             colors$(8) = "Brown"%@NL@%
  10554.             colors$(9) = "White"%@NL@%
  10555.             colors$(10) = "Gray"%@NL@%
  10556.             colors$(11) = "Bright Blue"%@NL@%
  10557.             colors$(12) = "Bright Green"%@NL@%
  10558.             colors$(13) = "Bright Cyan"%@NL@%
  10559.             colors$(14) = "Bright Red"%@NL@%
  10560.             colors$(15) = "Bright Magenta"%@NL@%
  10561.             colors$(16) = "Yellow"%@NL@%
  10562.         CASE 10%@NL@%
  10563.             numColors = 4%@NL@%
  10564.             REDIM color$(numColors)%@NL@%
  10565.             colors$(1) = "Off"%@NL@%
  10566.             colors$(2) = "On High"%@NL@%
  10567.             colors$(3) = "On Normal"%@NL@%
  10568.             colors$(4) = "Blink"%@NL@%
  10569.     END SELECT%@NL@%
  10570. %@NL@%
  10571. %@AB@%    ' reset chart color pointers to default values%@AE@%%@NL@%
  10572.     IF numColors < 16 THEN%@NL@%
  10573.         CEnv.ChartWindow.Background = 0%@NL@%
  10574.         CEnv.ChartWindow.BorderColor = 1%@NL@%
  10575.         CEnv.DataWindow.Background = 0%@NL@%
  10576.         CEnv.DataWindow.BorderColor = 1%@NL@%
  10577.         CEnv.MainTitle.TitleColor = 1%@NL@%
  10578.         CEnv.SubTitle.TitleColor = 1%@NL@%
  10579.         CEnv.XAxis.AxisColor = 1%@NL@%
  10580.         CEnv.XAxis.AxisTitle.TitleColor = 1%@NL@%
  10581.         CEnv.YAxis.AxisColor = 1%@NL@%
  10582.         CEnv.YAxis.AxisTitle.TitleColor = 1%@NL@%
  10583.         CEnv.Legend.TextColor = 1%@NL@%
  10584.         CEnv.Legend.LegendWindow.Background = 0%@NL@%
  10585.         CEnv.Legend.LegendWindow.BorderColor = 1%@NL@%
  10586.     END IF%@NL@%
  10587. END SUB%@NL@%
  10588. %@NL@%
  10589. %@AB@%'%@AE@%%@NL@%
  10590. %@AB@%' Sub Name: InitFonts%@AE@%%@NL@%
  10591. %@AB@%'%@AE@%%@NL@%
  10592. %@AB@%' Description: sets up default font and initializes font list%@AE@%%@NL@%
  10593. %@AB@%'%@AE@%%@NL@%
  10594. %@AB@%' Arguments: None%@AE@%%@NL@%
  10595. %@AB@%'%@AE@%%@NL@%
  10596. SUB InitFonts%@NL@%
  10597. DIM FI AS FontInfo%@NL@%
  10598. %@NL@%
  10599. %@AB@%    ' reset%@AE@%%@NL@%
  10600.     UnRegisterFonts%@NL@%
  10601.     SetMaxFonts 1, 1%@NL@%
  10602. %@NL@%
  10603. %@AB@%    ' get default font%@AE@%%@NL@%
  10604.     DefaultFont Segment%, Offset%%@NL@%
  10605.     reg% = RegisterMemFont%(Segment%, Offset%)%@NL@%
  10606. %@NL@%
  10607. %@AB@%    ' load default font%@AE@%%@NL@%
  10608.     numFonts = LoadFont("n1")%@NL@%
  10609. %@NL@%
  10610.     IF numFonts = 0 THEN numFonts = 1%@NL@%
  10611. %@NL@%
  10612.     fonts$(numFonts) = "IBM 8 Point"%@NL@%
  10613. %@NL@%
  10614.     UnRegisterFonts%@NL@%
  10615. END SUB%@NL@%
  10616. %@NL@%
  10617. %@AB@%'%@AE@%%@NL@%
  10618. %@AB@%' Sub Name: InitStyles%@AE@%%@NL@%
  10619. %@AB@%'%@AE@%%@NL@%
  10620. %@AB@%' Description: Initializes border styles list%@AE@%%@NL@%
  10621. %@AB@%'%@AE@%%@NL@%
  10622. %@AB@%' Arguments: None%@AE@%%@NL@%
  10623. %@AB@%'%@AE@%%@NL@%
  10624. SUB InitStyles%@NL@%
  10625. %@NL@%
  10626. %@AB@%    ' create list of border styles%@AE@%%@NL@%
  10627.     styles$(1) = "────────────────"%@NL@%
  10628.     styles$(2) = "────    ────        "%@NL@%
  10629.     styles$(3) = "────         ──      "%@NL@%
  10630.     styles$(4) = "──  ──  ──      ──  "%@NL@%
  10631.     styles$(5) = "──  ─   ──  ─       "%@NL@%
  10632.     styles$(6) = "─── ─── ─── ──    ─ "%@NL@%
  10633.     styles$(7) = "─── ─ ─ ─── ─     ─ "%@NL@%
  10634.     styles$(8) = "──── ── ── ──── "%@NL@%
  10635.     styles$(9) = "──── ── ──── ── "%@NL@%
  10636.     styles$(10) = "──── ─ ─ ── ─     ─ "%@NL@%
  10637.     styles$(11) = "──  ─── ─    ─  ─── "%@NL@%
  10638.     styles$(12) = "─ ─ ─   ─ ─ ─       "%@NL@%
  10639.     styles$(13) = "─ ─ ─ ─ ─ ─ ─     ─ "%@NL@%
  10640.     styles$(14) = "───  ─  ───  ─      "%@NL@%
  10641.     styles$(15) = "──  ─   ─   ─    ─  "%@NL@%
  10642. %@NL@%
  10643. END SUB%@NL@%
  10644. %@NL@%
  10645. %@AB@%'%@AE@%%@NL@%
  10646. %@AB@%' Func Name: Min%@AE@%%@NL@%
  10647. %@AB@%'%@AE@%%@NL@%
  10648. %@AB@%' Description: Compares two numbers and returns the smallest%@AE@%%@NL@%
  10649. %@AB@%'%@AE@%%@NL@%
  10650. %@AB@%' Arguments: num1, num2 - numbers to compare%@AE@%%@NL@%
  10651. %@AB@%'%@AE@%%@NL@%
  10652. FUNCTION Min% (num1, num2)%@NL@%
  10653. %@NL@%
  10654.     IF num1 <= num2 THEN%@NL@%
  10655.         Min% = num1%@NL@%
  10656.     ELSE%@NL@%
  10657.         Min% = num2%@NL@%
  10658.     END IF%@NL@%
  10659. %@NL@%
  10660. END FUNCTION%@NL@%
  10661. %@NL@%
  10662. %@AB@%'%@AE@%%@NL@%
  10663. %@AB@%' Sub Name: Quit%@AE@%%@NL@%
  10664. %@AB@%'%@AE@%%@NL@%
  10665. %@AB@%' Description: Exits the program after allowing the user a chance to%@AE@%%@NL@%
  10666. %@AB@%'              save the current chart%@AE@%%@NL@%
  10667. %@AB@%'%@AE@%%@NL@%
  10668. %@AB@%' Arguments: None%@AE@%%@NL@%
  10669. %@AB@%'%@AE@%%@NL@%
  10670. SUB Quit%@NL@%
  10671. SHARED finished AS INTEGER, saveFile$, origPath$%@NL@%
  10672. %@NL@%
  10673. %@AB@%    ' Allow user to save chart if necessary%@AE@%%@NL@%
  10674.     IF chartChanged THEN%@NL@%
  10675.         a$ = "| " + "Current chart has not been saved.  Save now?"%@NL@%
  10676. %@NL@%
  10677.         status = Alert(4, a$, 8, 15, 12, 65, "Yes", "No", "Cancel")%@NL@%
  10678. %@NL@%
  10679. %@AB@%        ' save chart%@AE@%%@NL@%
  10680.         IF status = OK THEN%@NL@%
  10681.             status = SaveChart(saveFile$, FALSE)%@NL@%
  10682.         END IF%@NL@%
  10683.     ELSE%@NL@%
  10684.         status = OK%@NL@%
  10685.     END IF%@NL@%
  10686. %@NL@%
  10687. %@AB@%    ' quit if operation has not been canceled.%@AE@%%@NL@%
  10688.     IF status <> CANCEL THEN%@NL@%
  10689.         CHDRIVE MID$(origPath$, 1, 2)%@NL@%
  10690.         CHDIR MID$(origPath$, 3, LEN(origPath$))%@NL@%
  10691.         finished = TRUE%@NL@%
  10692.         MouseHide%@NL@%
  10693.         COLOR 15, 0%@NL@%
  10694.         CLS%@NL@%
  10695.     END IF%@NL@%
  10696. %@NL@%
  10697. END SUB%@NL@%
  10698. %@NL@%
  10699. %@AB@%'%@AE@%%@NL@%
  10700. %@AB@%' Sub Name: ScrollList%@AE@%%@NL@%
  10701. %@AB@%'%@AE@%%@NL@%
  10702. %@AB@%' Description: Handles scrolling for a list box.%@AE@%%@NL@%
  10703. %@AB@%'%@AE@%%@NL@%
  10704. %@AB@%' Arguments: text$() - list%@AE@%%@NL@%
  10705. %@AB@%'            tbox - list box%@AE@%%@NL@%
  10706. %@AB@%'            currButton - current button%@AE@%%@NL@%
  10707. %@AB@%'            status - to determine if button was pressed, or up or down arrow%@AE@%%@NL@%
  10708. %@AB@%'                     keys were used%@AE@%%@NL@%
  10709. %@AB@%'            func - for special operations (passed to DrawList)%@AE@%%@NL@%
  10710. %@AB@%'            winRow - top row of current window%@AE@%%@NL@%
  10711. %@AB@%'            winCol - left column of current window%@AE@%%@NL@%
  10712. %@AB@%'%@AE@%%@NL@%
  10713. SUB ScrollList (text$(), tbox AS ListBox, currButton, status, func, winRow, winCol)%@NL@%
  10714. %@NL@%
  10715. %@AB@%    ' scroll using scroll buttons%@AE@%%@NL@%
  10716.     IF currButton = tbox.scrollButton AND status = 1 THEN%@NL@%
  10717.         SELECT CASE Dialog(19)%@NL@%
  10718. %@AB@%            ' scroll up%@AE@%%@NL@%
  10719.             CASE -1:%@NL@%
  10720.                 IF tbox.currTop > 1 THEN%@NL@%
  10721.                     tbox.currTop = tbox.currTop - 1%@NL@%
  10722.                     tbox.currPos = tbox.currPos + 1%@NL@%
  10723.                     IF tbox.currPos > tbox.maxLen THEN tbox.currPos = tbox.maxLen%@NL@%
  10724.                 END IF%@NL@%
  10725. %@AB@%            ' scroll down%@AE@%%@NL@%
  10726.             CASE -2:%@NL@%
  10727.                 IF tbox.currTop + tbox.maxLen <= tbox.listLen THEN%@NL@%
  10728.                     tbox.currTop = tbox.currTop + 1%@NL@%
  10729.                     tbox.currPos = tbox.currPos - 1%@NL@%
  10730.                     IF tbox.currPos < 1 THEN tbox.currPos = 1%@NL@%
  10731.                 END IF%@NL@%
  10732. %@AB@%            ' scroll to position%@AE@%%@NL@%
  10733.             CASE ELSE:%@NL@%
  10734.                 position = Dialog(19)%@NL@%
  10735.                 IF position > 1 THEN%@NL@%
  10736.                     position = position * (tbox.listLen) / (tbox.boxLen - 2)%@NL@%
  10737.                     IF position < 1 THEN%@NL@%
  10738.                         positon = 1%@NL@%
  10739.                     ELSEIF position > tbox.listLen THEN%@NL@%
  10740.                         position = tbox.listLen%@NL@%
  10741.                     END IF%@NL@%
  10742.                 END IF%@NL@%
  10743. %@NL@%
  10744.                 IF tbox.currTop <= position AND tbox.currTop + tbox.maxLen > position THEN%@NL@%
  10745.                     tbox.currPos = position - tbox.currTop + 1%@NL@%
  10746.                 ELSEIF position <= tbox.maxLen THEN%@NL@%
  10747.                     tbox.currTop = 1%@NL@%
  10748.                     tbox.currPos = position%@NL@%
  10749.                 ELSE%@NL@%
  10750.                     tbox.currTop = position - tbox.maxLen + 1%@NL@%
  10751.                     tbox.currPos = position - tbox.currTop + 1%@NL@%
  10752.                 END IF%@NL@%
  10753.         END SELECT%@NL@%
  10754. %@NL@%
  10755. %@AB@%    ' area button chosen%@AE@%%@NL@%
  10756.     ELSEIF status = 1 THEN%@NL@%
  10757. %@AB@%        ' make selected position the current position%@AE@%%@NL@%
  10758.         IF Dialog(17) <= tbox.maxLen THEN%@NL@%
  10759.             tbox.currPos = Dialog(17)%@NL@%
  10760.             DrawList text$(), tbox, func%@NL@%
  10761.         END IF%@NL@%
  10762. %@NL@%
  10763. %@AB@%        ' poll for repeated scrolling while mouse button is down%@AE@%%@NL@%
  10764.         DO%@NL@%
  10765.             X! = TIMER%@NL@%
  10766.             MousePoll r, c, lb, rb              ' poll mouse%@NL@%
  10767.             IF lb = TRUE THEN%@NL@%
  10768. %@AB@%                ' if below list box then scroll down%@AE@%%@NL@%
  10769.                 IF r > tbox.botRow + winRow - 2 THEN%@NL@%
  10770.                     GOSUB Down1%@NL@%
  10771. %@AB@%                ' if above list box then scroll up%@AE@%%@NL@%
  10772.                 ELSEIF r < tbox.topRow + winRow THEN%@NL@%
  10773.                     GOSUB Up1%@NL@%
  10774. %@AB@%                ' if to right of list box then scroll down%@AE@%%@NL@%
  10775.                 ELSEIF c > tbox.rightCol + winCol - 2 THEN%@NL@%
  10776.                     GOSUB Down1%@NL@%
  10777. %@AB@%                ' if to left of list box then scroll up%@AE@%%@NL@%
  10778.                 ELSEIF c < tbox.leftCol + winCol THEN%@NL@%
  10779.                     GOSUB Up1%@NL@%
  10780. %@AB@%                ' inside box%@AE@%%@NL@%
  10781.                 ELSEIF r - winRow - tbox.topRow + 1 <= tbox.maxLen THEN%@NL@%
  10782.                     tbox.currPos = r - winRow - tbox.topRow + 1%@NL@%
  10783.                 END IF%@NL@%
  10784. %@NL@%
  10785. %@AB@%                ' draw list%@AE@%%@NL@%
  10786.                 DrawList text$(), tbox, func%@NL@%
  10787.             ELSE%@NL@%
  10788.                 EXIT DO%@NL@%
  10789.             END IF%@NL@%
  10790.             WHILE TIMER < X! + .05: WEND%@NL@%
  10791.         LOOP%@NL@%
  10792. %@NL@%
  10793. %@AB@%    ' up arrow key hit%@AE@%%@NL@%
  10794.     ELSEIF status = 2 THEN%@NL@%
  10795.         GOSUB Up1%@NL@%
  10796. %@NL@%
  10797. %@AB@%    ' down arrow key hit%@AE@%%@NL@%
  10798.     ELSEIF status = 3 THEN%@NL@%
  10799.         GOSUB Down1%@NL@%
  10800.     END IF%@NL@%
  10801. %@NL@%
  10802.     DrawList text$(), tbox, func                    ' redraw list%@NL@%
  10803. %@NL@%
  10804.     EXIT SUB%@NL@%
  10805. %@NL@%
  10806. %@AB@%' scroll list up one%@AE@%%@NL@%
  10807. Up1:%@NL@%
  10808.     IF tbox.currPos > 1 THEN%@NL@%
  10809.         tbox.currPos = tbox.currPos - 1%@NL@%
  10810.     ELSEIF tbox.currTop > 1 THEN%@NL@%
  10811.         tbox.currTop = tbox.currTop - 1%@NL@%
  10812.     END IF%@NL@%
  10813. RETURN%@NL@%
  10814. %@NL@%
  10815. %@AB@%' scroll list down one%@AE@%%@NL@%
  10816. Down1:%@NL@%
  10817.     IF tbox.currPos < tbox.maxLen THEN%@NL@%
  10818.         tbox.currPos = tbox.currPos + 1%@NL@%
  10819.     ELSEIF tbox.currTop + tbox.maxLen <= tbox.listLen THEN%@NL@%
  10820.         tbox.currTop = tbox.currTop + 1%@NL@%
  10821.     END IF%@NL@%
  10822. RETURN%@NL@%
  10823. %@NL@%
  10824. END SUB%@NL@%
  10825. %@NL@%
  10826. %@AB@%'%@AE@%%@NL@%
  10827. %@AB@%' Sub Name: Setatt%@AE@%%@NL@%
  10828. %@AB@%'%@AE@%%@NL@%
  10829. %@AB@%' Description: Changes a color's attribute to that of another color's.%@AE@%%@NL@%
  10830. %@AB@%'              This is used in the ChangeTitle routine to allow user%@AE@%%@NL@%
  10831. %@AB@%'              color selections to immediately change the foreground%@AE@%%@NL@%
  10832. %@AB@%'              color of the title edit field.  This allows the user%@AE@%%@NL@%
  10833. %@AB@%'              to view the colors as they would look on a chart%@AE@%%@NL@%
  10834. %@AB@%'%@AE@%%@NL@%
  10835. %@AB@%' Arguments: change - color to change%@AE@%%@NL@%
  10836. %@AB@%'            source - color to change to%@AE@%%@NL@%
  10837. %@AB@%'%@AE@%%@NL@%
  10838. SUB SetAtt (change, source)%@NL@%
  10839. SHARED screenMode AS INTEGER%@NL@%
  10840. SHARED egacolor() AS INTEGER%@NL@%
  10841. %@NL@%
  10842. %@AB@%    ' map colors$ based on screen mode%@AE@%%@NL@%
  10843.     SELECT CASE screenMode%@NL@%
  10844.         CASE 10:%@NL@%
  10845.             IF source > 2 THEN%@NL@%
  10846.                 temp = 9                            ' set "normal" and "blink" to white%@NL@%
  10847.             ELSE%@NL@%
  10848.                 temp = source                       ' off = black; high white = bright white%@NL@%
  10849.             END IF%@NL@%
  10850.         CASE 1:%@NL@%
  10851.             IF source = 3 THEN                      ' map to cyan%@NL@%
  10852.                 temp = 13%@NL@%
  10853.             ELSEIF source = 4 THEN                  ' map to magenta%@NL@%
  10854.                 temp = 15%@NL@%
  10855.             ELSE                                    ' others okay%@NL@%
  10856.                 temp = source%@NL@%
  10857.             END IF%@NL@%
  10858.         CASE ELSE%@NL@%
  10859.             temp = source                           ' colors$ okay%@NL@%
  10860.     END SELECT%@NL@%
  10861. %@NL@%
  10862. %@AB@%    ' change attribute%@AE@%%@NL@%
  10863.     DIM regs AS RegType%@NL@%
  10864.     regs.ax = &H1000%@NL@%
  10865.     regs.bx = 256 * egacolor(TrueColr(temp)) + change%@NL@%
  10866.     CALL INTERRUPT(&H10, regs, regs)%@NL@%
  10867. %@NL@%
  10868. END SUB%@NL@%
  10869. %@NL@%
  10870. %@AB@%'%@AE@%%@NL@%
  10871. %@AB@%' Sub Name: SetDisplayColor%@AE@%%@NL@%
  10872. %@AB@%'%@AE@%%@NL@%
  10873. %@AB@%' Description: Changes the program's display to monochrome (no colors) or%@AE@%%@NL@%
  10874. %@AB@%'              to color (include colors in menu bar) based on the value of%@AE@%%@NL@%
  10875. %@AB@%'              colorDisplay.%@AE@%%@NL@%
  10876. %@AB@%'%@AE@%%@NL@%
  10877. %@AB@%' Arguments: none%@AE@%%@NL@%
  10878. %@AB@%'%@AE@%%@NL@%
  10879. SUB SetDisplayColor%@NL@%
  10880. SHARED colorDisplay AS INTEGER%@NL@%
  10881. %@NL@%
  10882.     MouseHide%@NL@%
  10883. %@NL@%
  10884. %@AB@%    ' redraw background based on display color%@AE@%%@NL@%
  10885.     SetUpBackground%@NL@%
  10886. %@NL@%
  10887. %@AB@%    ' set menu bar to include colors%@AE@%%@NL@%
  10888.     IF colorDisplay THEN%@NL@%
  10889.         MenuSetState OPTIONSTITLE, 1, 2%@NL@%
  10890.         MenuSetState OPTIONSTITLE, 2, 1%@NL@%
  10891.         MenuColor 0, 7, 4, 8, 0, 4, 7%@NL@%
  10892. %@AB@%    ' set monochrome menu bar%@AE@%%@NL@%
  10893.     ELSE%@NL@%
  10894.         MenuSetState OPTIONSTITLE, 1, 1%@NL@%
  10895.         MenuSetState OPTIONSTITLE, 2, 2%@NL@%
  10896.         MenuColor 0, 7, 15, 8, 7, 0, 15%@NL@%
  10897.     END IF%@NL@%
  10898. %@NL@%
  10899.     MenuShow%@NL@%
  10900.     MouseShow%@NL@%
  10901. %@NL@%
  10902. END SUB%@NL@%
  10903. %@NL@%
  10904. %@AB@%'%@AE@%%@NL@%
  10905. %@AB@%' Sub Name: SetUpBackground%@AE@%%@NL@%
  10906. %@AB@%'%@AE@%%@NL@%
  10907. %@AB@%' Description: Creates and displays background screen pattern%@AE@%%@NL@%
  10908. %@AB@%'%@AE@%%@NL@%
  10909. %@AB@%' Arguments: none%@AE@%%@NL@%
  10910. %@AB@%'%@AE@%%@NL@%
  10911. SUB SetUpBackground%@NL@%
  10912. SHARED colorDisplay AS INTEGER%@NL@%
  10913. %@NL@%
  10914.     MouseHide%@NL@%
  10915. %@NL@%
  10916.     WIDTH , 25%@NL@%
  10917.     IF colorDisplay THEN%@NL@%
  10918.         COLOR 15, 1                             ' set color for background%@NL@%
  10919.     ELSE%@NL@%
  10920.         COLOR 15, 0%@NL@%
  10921.     END IF%@NL@%
  10922.     CLS%@NL@%
  10923. %@NL@%
  10924.     FOR a = 2 TO 80 STEP 4                      ' create and display pattern%@NL@%
  10925.         FOR b = 2 TO 25 STEP 2%@NL@%
  10926.             LOCATE b, a%@NL@%
  10927.             PRINT CHR$(250);%@NL@%
  10928.         NEXT b%@NL@%
  10929.     NEXT a%@NL@%
  10930. %@NL@%
  10931.     MouseShow%@NL@%
  10932. %@NL@%
  10933. END SUB%@NL@%
  10934. %@NL@%
  10935. %@AB@%'%@AE@%%@NL@%
  10936. %@AB@%' Sub Name: SetUpMenu%@AE@%%@NL@%
  10937. %@AB@%'%@AE@%%@NL@%
  10938. %@AB@%' Description: Creates menu bar for the program%@AE@%%@NL@%
  10939. %@AB@%'%@AE@%%@NL@%
  10940. %@AB@%' Arguments: none%@AE@%%@NL@%
  10941. %@AB@%'%@AE@%%@NL@%
  10942. SUB SetUpMenu%@NL@%
  10943. %@NL@%
  10944. %@AB@%    ' file menu title%@AE@%%@NL@%
  10945.     MenuSet FILETITLE, 0, 1, "File", 1%@NL@%
  10946.     MenuSet FILETITLE, 1, 1, "New", 1%@NL@%
  10947.     MenuSet FILETITLE, 2, 1, "Open ...", 1%@NL@%
  10948.     MenuSet FILETITLE, 3, 1, "Save", 1%@NL@%
  10949.     MenuSet FILETITLE, 4, 1, "Save As ...", 6%@NL@%
  10950.     MenuSet FILETITLE, 5, 1, "-", 1%@NL@%
  10951.     MenuSet FILETITLE, 6, 1, "Exit", 2%@NL@%
  10952. %@NL@%
  10953. %@AB@%    ' view menu title%@AE@%%@NL@%
  10954.     MenuSet VIEWTITLE, 0, 1, "View", 1%@NL@%
  10955.     MenuSet VIEWTITLE, 1, 1, "Data ...", 1%@NL@%
  10956.     MenuSet VIEWTITLE, 2, 1, "Chart        F5", 1%@NL@%
  10957.     MenuSet VIEWTITLE, 3, 1, "Fonts ...", 1%@NL@%
  10958.     MenuSet VIEWTITLE, 4, 1, "Screen Mode ...", 1%@NL@%
  10959. %@NL@%
  10960. %@AB@%    ' gallery menu title%@AE@%%@NL@%
  10961.     MenuSet GALLERYTITLE, 0, 1, "Gallery", 1%@NL@%
  10962.     MenuSet GALLERYTITLE, 1, 1, "Bar ...", 1%@NL@%
  10963.     MenuSet GALLERYTITLE, 2, 1, "Column ...", 1%@NL@%
  10964.     MenuSet GALLERYTITLE, 3, 1, "Line ...", 1%@NL@%
  10965.     MenuSet GALLERYTITLE, 4, 1, "Scatter ...", 1%@NL@%
  10966.     MenuSet GALLERYTITLE, 5, 1, "Pie ...", 1%@NL@%
  10967. %@NL@%
  10968. %@AB@%    ' chart menu title%@AE@%%@NL@%
  10969.     MenuSet CHARTTITLE, 0, 1, "Chart", 1%@NL@%
  10970.     MenuSet CHARTTITLE, 1, 1, "Chart Window ...", 1%@NL@%
  10971.     MenuSet CHARTTITLE, 2, 1, "Data Window ...", 1%@NL@%
  10972.     MenuSet CHARTTITLE, 3, 1, "Legend ...", 1%@NL@%
  10973.     MenuSet CHARTTITLE, 4, 1, "X Axis ...", 1%@NL@%
  10974.     MenuSet CHARTTITLE, 5, 1, "Y Axis ...", 1%@NL@%
  10975. %@NL@%
  10976. %@AB@%    ' title menu title%@AE@%%@NL@%
  10977.     MenuSet TITLETITLE, 0, 1, "Title", 1%@NL@%
  10978.     MenuSet TITLETITLE, 1, 1, "Main ...", 1%@NL@%
  10979.     MenuSet TITLETITLE, 2, 1, "Sub ...", 1%@NL@%
  10980.     MenuSet TITLETITLE, 3, 1, "X Axis ...", 1%@NL@%
  10981.     MenuSet TITLETITLE, 4, 1, "Y Axis ...", 1%@NL@%
  10982. %@NL@%
  10983. %@AB@%    ' options menu title%@AE@%%@NL@%
  10984.     MenuSet OPTIONSTITLE, 0, 1, "Options", 1%@NL@%
  10985.     MenuSet OPTIONSTITLE, 1, 1, "Color", 1%@NL@%
  10986.     MenuSet OPTIONSTITLE, 2, 1, "Monochrome", 1%@NL@%
  10987. %@NL@%
  10988. %@AB@%    ' setup short cuts for some menu choices%@AE@%%@NL@%
  10989.     ShortCutKeySet VIEWTITLE, 2, CHR$(0) + CHR$(63)     ' F5 = View Chart%@NL@%
  10990. %@NL@%
  10991. %@AB@%    ' set original menu colors for monochrome screen%@AE@%%@NL@%
  10992.     MenuColor 0, 7, 15, 8, 7, 0, 15%@NL@%
  10993.     MenuPreProcess%@NL@%
  10994. %@NL@%
  10995. END SUB%@NL@%
  10996. %@NL@%
  10997. %@AB@%'%@AE@%%@NL@%
  10998. %@AB@%' Function Name: TrueColr%@AE@%%@NL@%
  10999. %@AB@%'%@AE@%%@NL@%
  11000. %@AB@%' Description: Maps a given chart color to its actual color%@AE@%%@NL@%
  11001. %@AB@%'              and returns this color.  This is needed because the chart%@AE@%%@NL@%
  11002. %@AB@%'              colors start with BLACK = 1 and HIGH WHITE = 2%@AE@%%@NL@%
  11003. %@AB@%'%@AE@%%@NL@%
  11004. %@AB@%' Arguments: colr - chart color number%@AE@%%@NL@%
  11005. %@AB@%'%@AE@%%@NL@%
  11006. FUNCTION TrueColr% (colr)%@NL@%
  11007. %@NL@%
  11008.     IF colr = 1 THEN                                ' black%@NL@%
  11009.         TrueColr% = 0                               ' bright white%@NL@%
  11010.     ELSEIF colr = 2 THEN%@NL@%
  11011.         TrueColr% = 15%@NL@%
  11012.     ELSE%@NL@%
  11013.         TrueColr% = colr - 2                        ' all others%@NL@%
  11014.     END IF%@NL@%
  11015. %@NL@%
  11016. END FUNCTION%@NL@%
  11017. %@NL@%
  11018. %@AB@%'%@AE@%%@NL@%
  11019. %@AB@%' Sub Name: ViewChart%@AE@%%@NL@%
  11020. %@AB@%'%@AE@%%@NL@%
  11021. %@AB@%' Description: Displays the chart%@AE@%%@NL@%
  11022. %@AB@%'%@AE@%%@NL@%
  11023. %@AB@%' Arguments: none%@AE@%%@NL@%
  11024. %@AB@%'%@AE@%%@NL@%
  11025. SUB ViewChart%@NL@%
  11026. SHARED setVal!(), Cat$(), setLen() AS INTEGER, setName$()%@NL@%
  11027. SHARED screenMode AS INTEGER%@NL@%
  11028. %@NL@%
  11029. %@AB@%    ' When a chart is drawn, data is moved from the 2-dimensional array%@AE@%%@NL@%
  11030. %@AB@%    ' into arrays suitable for the charting library routines.  The%@AE@%%@NL@%
  11031. %@AB@%    ' following arrays are used directly in calls to the charting routines:%@AE@%%@NL@%
  11032.     DIM ValX1!(1 TO cMaxValues)                    ' pass to chart routine%@NL@%
  11033.     DIM ValY1!(1 TO cMaxValues)%@NL@%
  11034.     DIM ValX2!(1 TO cMaxValues, 1 TO cMaxSeries)   ' pass to chartMS routine%@NL@%
  11035.     DIM ValY2!(1 TO cMaxValues, 1 TO cMaxSeries)%@NL@%
  11036. %@NL@%
  11037.     DIM explode(1 TO cMaxValues)  AS INTEGER       ' explode pie chart pieces%@NL@%
  11038. %@NL@%
  11039. %@NL@%
  11040. %@AB@%   ' Make sure some data exists%@AE@%%@NL@%
  11041.    IF setNum <= 0 THEN%@NL@%
  11042.        a$ = "|"%@NL@%
  11043.        a$ = a$ + "No data available for chart."%@NL@%
  11044.        junk = Alert(4, a$, 8, 15, 12, 65, "", "", "")%@NL@%
  11045.        EXIT SUB%@NL@%
  11046.    END IF%@NL@%
  11047. %@NL@%
  11048. %@AB@%   ' find the longest series%@AE@%%@NL@%
  11049.    maxLen% = 0%@NL@%
  11050.    FOR i% = 1 TO setNum%@NL@%
  11051.       IF setLen(i%) > maxLen% THEN maxLen% = setLen(i%)%@NL@%
  11052.    NEXT i%%@NL@%
  11053. %@NL@%
  11054. %@AB@%   ' Set up the proper screen mode (exit if not valid)%@AE@%%@NL@%
  11055.    ChartScreen screenMode%@NL@%
  11056.    IF ChartErr = cBadScreen THEN%@NL@%
  11057.         PrintError "Invalid screen mode. Can't display chart."%@NL@%
  11058.         EXIT SUB%@NL@%
  11059.    END IF%@NL@%
  11060. %@NL@%
  11061. %@AB@%   ' Process depending on chart type%@AE@%%@NL@%
  11062.    SELECT CASE CEnv.ChartType%@NL@%
  11063.       CASE cBar, cColumn, cLine, cPie:%@NL@%
  11064. %@AB@%         ' If the chart is a single series one or a pie chart:%@AE@%%@NL@%
  11065.          IF setNum = 1 OR CEnv.ChartType = cPie THEN%@NL@%
  11066. %@NL@%
  11067. %@AB@%            ' Transfer data into a single dimension array:%@AE@%%@NL@%
  11068.             FOR i% = 1 TO maxLen%%@NL@%
  11069.                ValX1!(i%) = setVal!(i%, 1)%@NL@%
  11070.             NEXT i%%@NL@%
  11071. %@NL@%
  11072.             IF CEnv.ChartType = cPie THEN%@NL@%
  11073. %@AB@%                ' determine which pieces to explode%@AE@%%@NL@%
  11074.                 FOR i% = 1 TO maxLen%%@NL@%
  11075.                     IF setVal!(i%, 2) <> 0 THEN%@NL@%
  11076.                         explode(i%) = 1%@NL@%
  11077.                     ELSE%@NL@%
  11078.                         explode(i%) = 0%@NL@%
  11079.                     END IF%@NL@%
  11080.                 NEXT i%%@NL@%
  11081. %@NL@%
  11082. %@AB@%                ' display pie chart%@AE@%%@NL@%
  11083.                 ChartPie CEnv, Cat$(), ValX1!(), explode(), maxLen%%@NL@%
  11084.             ELSE%@NL@%
  11085.                 Chart CEnv, Cat$(), ValX1!(), maxLen%%@NL@%
  11086.             END IF%@NL@%
  11087. %@NL@%
  11088. %@AB@%         ' If multiple series, then data is OK so just call routine:%@AE@%%@NL@%
  11089.          ELSE%@NL@%
  11090.             ChartMS CEnv, Cat$(), setVal!(), maxLen%, 1, setNum, setName$()%@NL@%
  11091.          END IF%@NL@%
  11092. %@NL@%
  11093.       CASE cScatter:%@NL@%
  11094. %@AB@%         ' Make sure there's enough data sets:%@AE@%%@NL@%
  11095.          IF setNum = 1 THEN%@NL@%
  11096.             SCREEN 0%@NL@%
  11097.             WIDTH 80%@NL@%
  11098.             SetUpBackground%@NL@%
  11099.             MenuShow%@NL@%
  11100.             MouseShow%@NL@%
  11101.             a$ = "|"%@NL@%
  11102.             a$ = a$ + "Too few data sets for Scatter chart"%@NL@%
  11103.             junk = Alert(4, a$, 8, 15, 12, 65, "", "", "")%@NL@%
  11104.             EXIT SUB%@NL@%
  11105. %@NL@%
  11106. %@AB@%         ' If it's a single series scatter, transfer data to one-%@AE@%%@NL@%
  11107. %@AB@%         ' dimensional arrays and make chart call:%@AE@%%@NL@%
  11108.          ELSEIF setNum = 2 THEN%@NL@%
  11109.             FOR i% = 1 TO maxLen%%@NL@%
  11110.                ValX1!(i%) = setVal!(i%, 1)%@NL@%
  11111.                ValY1!(i%) = setVal!(i%, 2)%@NL@%
  11112.             NEXT i%%@NL@%
  11113.             ChartScatter CEnv, ValX1!(), ValY1!(), maxLen%%@NL@%
  11114. %@NL@%
  11115. %@AB@%         ' If it's a multiple series scatter, transfer odd columns to%@AE@%%@NL@%
  11116. %@AB@%         ' X-axis data array and even columns to Y-axis array and make%@AE@%%@NL@%
  11117. %@AB@%         ' chart call:%@AE@%%@NL@%
  11118.          ELSE%@NL@%
  11119.             FOR j% = 2 TO setNum STEP 2%@NL@%
  11120.                FOR i% = 1 TO maxLen%%@NL@%
  11121.                   ValX2!(i%, j% \ 2) = setVal!(i%, j% - 1)%@NL@%
  11122.                   ValY2!(i%, j% \ 2) = setVal!(i%, j%)%@NL@%
  11123.                NEXT i%%@NL@%
  11124.             NEXT j%%@NL@%
  11125. %@NL@%
  11126.             ChartScatterMS CEnv, ValX2!(), ValY2!(), maxLen%, 1, setNum \ 2, setName$()%@NL@%
  11127.          END IF%@NL@%
  11128. %@NL@%
  11129.    END SELECT%@NL@%
  11130. %@NL@%
  11131. %@AB@%   ' If there's been a "fatal" error, indicate what it was:%@AE@%%@NL@%
  11132.    IF ChartErr <> 0 THEN%@NL@%
  11133.        GOSUB ViewError%@NL@%
  11134. %@NL@%
  11135. %@AB@%   ' Otherwise, just wait for a keypress:%@AE@%%@NL@%
  11136.    ELSE%@NL@%
  11137. %@AB@%      ' Wait for keypress%@AE@%%@NL@%
  11138.       DO%@NL@%
  11139.             c$ = INKEY$%@NL@%
  11140.             MousePoll r, c, lb, rb%@NL@%
  11141.       LOOP UNTIL c$ <> "" OR lb OR rb%@NL@%
  11142.       SCREEN 0%@NL@%
  11143.       WIDTH 80%@NL@%
  11144.       SetUpBackground%@NL@%
  11145.       MenuShow%@NL@%
  11146.       MouseShow%@NL@%
  11147.    END IF%@NL@%
  11148. %@NL@%
  11149. EXIT SUB%@NL@%
  11150. %@NL@%
  11151. %@AB@%' handle charting errors%@AE@%%@NL@%
  11152. ViewError:%@NL@%
  11153. %@NL@%
  11154. %@AB@%    ' re-init the display%@AE@%%@NL@%
  11155.     SCREEN 0%@NL@%
  11156.     WIDTH 80%@NL@%
  11157.     SetUpBackground%@NL@%
  11158.     MenuShow%@NL@%
  11159.     MouseShow%@NL@%
  11160. %@NL@%
  11161. %@AB@%    ' display appropriate error message%@AE@%%@NL@%
  11162.     SELECT CASE ChartErr%@NL@%
  11163.         CASE cBadDataWindow:%@NL@%
  11164.             PrintError "Data window cannot be displayed in available space."%@NL@%
  11165.         CASE cBadLegendWindow:%@NL@%
  11166.             PrintError "Invalid legend coordinates."%@NL@%
  11167.         CASE cTooFewSeries:%@NL@%
  11168.             PrintError "Too few series to plot."%@NL@%
  11169.         CASE cTooSmallN:%@NL@%
  11170.             PrintError "No data in series."%@NL@%
  11171.         CASE IS > 200:                              ' basic error%@NL@%
  11172.             PrintError "BASIC error #" + LTRIM$(STR$(ChartErr - 200)) + " occurred."%@NL@%
  11173.         CASE ELSE:                                  ' extraneous error%@NL@%
  11174.             PrintError "Charting error #" + LTRIM$(STR$(ChartErr)) + " occurred."%@NL@%
  11175.     END SELECT%@NL@%
  11176. %@NL@%
  11177. RETURN%@NL@%
  11178. %@NL@%
  11179. END SUB%@NL@%
  11180. %@NL@%
  11181. %@AB@%'%@AE@%%@NL@%
  11182. %@AB@%' Sub Name: ViewFont%@AE@%%@NL@%
  11183. %@AB@%'%@AE@%%@NL@%
  11184. %@AB@%' Description: Displays list of registered fonts and allows user to%@AE@%%@NL@%
  11185. %@AB@%'              select one or more of these fonts to load%@AE@%%@NL@%
  11186. %@AB@%'%@AE@%%@NL@%
  11187. %@AB@%' Arguments: none%@AE@%%@NL@%
  11188. %@AB@%'%@AE@%%@NL@%
  11189. SUB ViewFont%@NL@%
  11190. SHARED screenMode AS INTEGER%@NL@%
  11191. SHARED origPath$%@NL@%
  11192. DIM FI AS FontInfo%@NL@%
  11193. DIM rfonts$(1 TO MAXFONTS)%@NL@%
  11194. %@NL@%
  11195.     SetMaxFonts MAXFONTS, MAXFONTS%@NL@%
  11196. %@NL@%
  11197. %@AB@%    ' get default font%@AE@%%@NL@%
  11198.     DefaultFont Segment%, Offset%%@NL@%
  11199.     numReg = RegisterMemFont%(Segment%, Offset%)%@NL@%
  11200. %@NL@%
  11201. %@AB@%    ' use font files that are best suited for current screen mode%@AE@%%@NL@%
  11202.     IF MID$(origPath$, LEN(origPath$), 1) = "\" THEN%@NL@%
  11203.         t$ = ""%@NL@%
  11204.     ELSE%@NL@%
  11205.         t$ = "\"%@NL@%
  11206.     END IF%@NL@%
  11207.     SELECT CASE screenMode%@NL@%
  11208.         CASE 2, 8%@NL@%
  11209.             cour$ = origPath$ + t$ + "COURA.FON"%@NL@%
  11210.             helv$ = origPath$ + t$ + "HELVA.FON"%@NL@%
  11211.             tims$ = origPath$ + t$ + "TMSRA.FON"%@NL@%
  11212.         CASE 11, 12%@NL@%
  11213.             cour$ = origPath$ + t$ + "COURE.FON"%@NL@%
  11214.             helv$ = origPath$ + t$ + "HELVE.FON"%@NL@%
  11215.             tims$ = origPath$ + t$ + "TMSRE.FON"%@NL@%
  11216.         CASE ELSE%@NL@%
  11217.             cour$ = origPath$ + t$ + "COURB.FON"%@NL@%
  11218.             helv$ = origPath$ + t$ + "HELVB.FON"%@NL@%
  11219.             tims$ = origPath$ + t$ + "TMSRB.FON"%@NL@%
  11220.     END SELECT%@NL@%
  11221. %@AB@%    ' register courier fonts%@AE@%%@NL@%
  11222.     numReg = numReg + RegisterFonts%(cour$)%@NL@%
  11223.     fontname$ = cour$%@NL@%
  11224.     IF FontErr > 0 THEN GOSUB FontError%@NL@%
  11225. %@NL@%
  11226. %@AB@%    ' register helvetica fonts%@AE@%%@NL@%
  11227.     numReg = numReg + RegisterFonts%(helv$)%@NL@%
  11228.     fontname$ = helv$%@NL@%
  11229.     IF FontErr > 0 THEN GOSUB FontError%@NL@%
  11230. %@NL@%
  11231. %@AB@%    ' register times roman fonts%@AE@%%@NL@%
  11232.     numReg = numReg + RegisterFonts%(tims$)%@NL@%
  11233.     fontname$ = tims$%@NL@%
  11234.     IF FontErr > 0 THEN GOSUB FontError%@NL@%
  11235. %@NL@%
  11236. %@AB@%    ' create a list of registered fonts%@AE@%%@NL@%
  11237.     FOR i = 1 TO numReg%@NL@%
  11238.         GetRFontInfo i, FI%@NL@%
  11239.         rfonts$(i) = RTRIM$(MID$(FI.FaceName, 1, 8)) + STR$(FI.Points) + " Point"%@NL@%
  11240.     NEXT i%@NL@%
  11241. %@NL@%
  11242. %@AB@%    ' set up window display%@AE@%%@NL@%
  11243.     winRow = 5%@NL@%
  11244.     winCol = 25%@NL@%
  11245.     WindowOpen 1, winRow, winCol, winRow + numReg + 1, 51, 0, 7, 0, 7, 15, FALSE, FALSE, FALSE, TRUE, 2, "Chart Fonts"%@NL@%
  11246. %@NL@%
  11247. %@AB@%    ' open buttons for each font in list%@AE@%%@NL@%
  11248.     FOR i% = 1 TO numReg%@NL@%
  11249.         ButtonOpen i, 1, rfonts$(i), i, 4, 0, 0, 2%@NL@%
  11250.         FOR j% = 1 TO numFonts%@NL@%
  11251.             IF fonts$(j%) = rfonts$(i%) THEN ButtonSetState i, 2%@NL@%
  11252.         NEXT j%%@NL@%
  11253.     NEXT i%%@NL@%
  11254. %@NL@%
  11255.     WindowLine numReg + 1%@NL@%
  11256.     ButtonOpen numReg + 1, 2, "Load", numReg + 2, 4, 0, 0, 1%@NL@%
  11257.     ButtonOpen numReg + 2, 1, "Cancel ", numReg + 2, 15, 0, 0, 1%@NL@%
  11258. %@NL@%
  11259. %@AB@%    ' start with cursor on first button%@AE@%%@NL@%
  11260.     currButton = 1%@NL@%
  11261.     pushButton = numReg + 1%@NL@%
  11262. %@NL@%
  11263. %@AB@%    ' window control loop%@AE@%%@NL@%
  11264.     finished = FALSE%@NL@%
  11265.     WHILE NOT finished%@NL@%
  11266.         WindowDo currButton, 0%@NL@%
  11267.         SELECT CASE Dialog(0)%@NL@%
  11268.             CASE 1                                     ' button pressed%@NL@%
  11269.                 currButton = Dialog(1)%@NL@%
  11270.                 IF currButton > numReg THEN%@NL@%
  11271.                     pushButton = currButton%@NL@%
  11272.                     finished = TRUE%@NL@%
  11273.                 ELSE%@NL@%
  11274.                     ButtonToggle currButton%@NL@%
  11275.                 END IF%@NL@%
  11276.             CASE 6                                      ' enter%@NL@%
  11277.                 finished = TRUE%@NL@%
  11278.             CASE 7                                      ' tab%@NL@%
  11279.                 SELECT CASE currButton%@NL@%
  11280.                     CASE numReg, numReg + 1:%@NL@%
  11281.                         currButton = currButton + 1%@NL@%
  11282.                         ButtonSetState pushButton, 1%@NL@%
  11283.                         ButtonSetState currButton, 2%@NL@%
  11284.                         pushButton = currButton%@NL@%
  11285.                     CASE numReg + 2:%@NL@%
  11286.                         currButton = 1%@NL@%
  11287.                         ButtonSetState pushButton, 1%@NL@%
  11288.                         pushButton = numReg + 1%@NL@%
  11289.                         ButtonSetState pushButton, 2%@NL@%
  11290.                     CASE ELSE:%@NL@%
  11291.                         currButton = currButton + 1%@NL@%
  11292.                 END SELECT%@NL@%
  11293.             CASE 8                                      ' back tab%@NL@%
  11294.                 SELECT CASE currButton%@NL@%
  11295.                     CASE 1:%@NL@%
  11296.                         currButton = numReg + 2%@NL@%
  11297.                         ButtonSetState pushButton, 1%@NL@%
  11298.                         ButtonSetState currButton, 2%@NL@%
  11299.                         pushButton = currButton%@NL@%
  11300.                     CASE numReg + 2:%@NL@%
  11301.                         currButton = numReg + 1%@NL@%
  11302.                         ButtonSetState pushButton, 1%@NL@%
  11303.                         ButtonSetState currButton, 2%@NL@%
  11304.                         pushButton = currButton%@NL@%
  11305.                     CASE ELSE:%@NL@%
  11306.                         currButton = currButton - 1%@NL@%
  11307.                     END SELECT%@NL@%
  11308.             CASE 9                                      ' escape%@NL@%
  11309.                 pushButton = numReg + 2%@NL@%
  11310.                 finished = TRUE%@NL@%
  11311.             CASE 10, 12                                 ' up, left arrow%@NL@%
  11312.                 IF currButton <= numReg THEN ButtonSetState currButton, 2%@NL@%
  11313.             CASE 11, 13                                 ' down, right arrow%@NL@%
  11314.                 IF currButton <= numReg THEN ButtonSetState currButton, 1%@NL@%
  11315.             CASE 14                                     ' space bar%@NL@%
  11316.                 IF currButton <= numReg THEN%@NL@%
  11317.                     ButtonToggle currButton%@NL@%
  11318.                 ELSE%@NL@%
  11319.                     finished = TRUE%@NL@%
  11320.                 END IF%@NL@%
  11321.         END SELECT%@NL@%
  11322. %@NL@%
  11323. %@AB@%    ' finished and not cancelled%@AE@%%@NL@%
  11324.     IF finished AND pushButton = numReg + 1 THEN%@NL@%
  11325. %@AB@%        ' create font spec for load operation%@AE@%%@NL@%
  11326.         FontSpec$ = ""%@NL@%
  11327.         FOR i% = 1 TO numReg%@NL@%
  11328.             IF ButtonInquire(i) = 2 THEN%@NL@%
  11329.                 FontSpec$ = FontSpec$ + "/n" + LTRIM$(STR$(i))%@NL@%
  11330.             END IF%@NL@%
  11331.         NEXT i%%@NL@%
  11332. %@NL@%
  11333. %@AB@%        ' default if none chosen%@AE@%%@NL@%
  11334.         IF FontSpec$ = "" THEN%@NL@%
  11335.             PrintError "No fonts selected - using default."%@NL@%
  11336.             numFonts = LoadFont%("N1")%@NL@%
  11337.             REDIM fonts$(1)%@NL@%
  11338.             fonts$(1) = rfonts$(1)%@NL@%
  11339.         ELSE%@NL@%
  11340. %@AB@%            ' load selected fonts%@AE@%%@NL@%
  11341.             numLoaded = LoadFont%(RIGHT$(FontSpec$, LEN(FontSpec$) - 1))%@NL@%
  11342. %@NL@%
  11343. %@AB@%            ' notify user of error and let them try again.%@AE@%%@NL@%
  11344.             IF FontErr <> 0 THEN%@NL@%
  11345.                 GOSUB FontError%@NL@%
  11346.                 finished = FALSE%@NL@%
  11347.                 currButton = 1%@NL@%
  11348.             ELSE%@NL@%
  11349.                 REDIM fonts$(numLoaded)%@NL@%
  11350. %@AB@%                ' create a list of loaded fonts%@AE@%%@NL@%
  11351.                 FOR i = 1 TO numLoaded%@NL@%
  11352.                     SelectFont i%@NL@%
  11353.                     GetFontInfo FI%@NL@%
  11354.                     fonts$(i) = RTRIM$(MID$(FI.FaceName, 1, 8)) + STR$(FI.Points) + " Point"%@NL@%
  11355.                 NEXT i%@NL@%
  11356.                 numFonts = numLoaded%@NL@%
  11357.                 ClearFonts%@NL@%
  11358.             END IF%@NL@%
  11359.         END IF%@NL@%
  11360. %@AB@%    ' reload existing fonts if operation cancelled%@AE@%%@NL@%
  11361.     ELSEIF finished = TRUE AND pushButton = numReg + 2 THEN%@NL@%
  11362.         FontSpec$ = ""%@NL@%
  11363.         FOR i = 1 TO numReg%@NL@%
  11364.             FOR j% = 1 TO numFonts%@NL@%
  11365.                 IF fonts$(j%) = rfonts$(i%) THEN FontSpec$ = FontSpec$ + "/n" + LTRIM$(STR$(i))%@NL@%
  11366.             NEXT j%%@NL@%
  11367.         NEXT i%@NL@%
  11368.         numFonts = LoadFont%(RIGHT$(FontSpec$, LEN(FontSpec$) - 1))%@NL@%
  11369.     END IF%@NL@%
  11370. %@NL@%
  11371.     WEND%@NL@%
  11372. %@NL@%
  11373.     UnRegisterFonts%@NL@%
  11374. %@NL@%
  11375.     WindowClose 1%@NL@%
  11376. %@NL@%
  11377.     EXIT SUB%@NL@%
  11378. %@NL@%
  11379. %@AB@%' handle font loading errors%@AE@%%@NL@%
  11380. FontError:%@NL@%
  11381.     SELECT CASE FontErr%@NL@%
  11382.         CASE cNoFontMem:%@NL@%
  11383.             PrintError "Not enough memory to load selected fonts."%@NL@%
  11384.         CASE cFileNotFound:%@NL@%
  11385.             PrintError fontname$ + " font file not found."%@NL@%
  11386.         CASE cTooManyFonts:%@NL@%
  11387.             numReg = MAXFONTS%@NL@%
  11388.         CASE cBadFontFile:%@NL@%
  11389.             PrintError "Invalid font file format for " + fontname$ + "."%@NL@%
  11390.         CASE cNoFonts:%@NL@%
  11391.             PrintError "No fonts are loaded."%@NL@%
  11392.         CASE cBadFontType:%@NL@%
  11393.             PrintError "Font not a bitmap font."%@NL@%
  11394.         CASE IS > 200:                                  ' basic error%@NL@%
  11395.             PrintError "BASIC error #" + LTRIM$(STR$(FontErr - 200)) + " occurred."%@NL@%
  11396.         CASE ELSE                                       ' unplanned font error%@NL@%
  11397.             PrintError "Font error #" + LTRIM$(STR$(FontErr)) + " occurred."%@NL@%
  11398.     END SELECT%@NL@%
  11399. %@NL@%
  11400. RETURN%@NL@%
  11401. %@NL@%
  11402. END SUB%@NL@%
  11403. %@NL@%
  11404. %@AB@%'%@AE@%%@NL@%
  11405. %@AB@%' Sub Name: ViewScreenMode%@AE@%%@NL@%
  11406. %@AB@%'%@AE@%%@NL@%
  11407. %@AB@%' Description: Displays list of valid screen modes and allows the%@AE@%%@NL@%
  11408. %@AB@%'              user to select one for viewing the chart%@AE@%%@NL@%
  11409. %@AB@%'%@AE@%%@NL@%
  11410. %@AB@%' Arguments: none%@AE@%%@NL@%
  11411. %@AB@%'%@AE@%%@NL@%
  11412. SUB ViewScreenMode%@NL@%
  11413. SHARED screenMode AS INTEGER, numModes AS INTEGER, mode$()%@NL@%
  11414. %@NL@%
  11415. DIM modeBox AS ListBox%@NL@%
  11416. %@NL@%
  11417. %@AB@%    ' set up list box containing valid screen modes%@AE@%%@NL@%
  11418.     modeBox.scrollButton = 1%@NL@%
  11419.     modeBox.areaButton = 2%@NL@%
  11420.     modeBox.listLen = numModes%@NL@%
  11421.     modeBox.topRow = 1%@NL@%
  11422.     modeBox.botRow = numModes + 2%@NL@%
  11423.     modeBox.leftCol = 7%@NL@%
  11424.     modeBox.rightCol = 21%@NL@%
  11425. %@NL@%
  11426. %@AB@%    ' determine current screen mode%@AE@%%@NL@%
  11427.     FOR i = 1 TO numModes%@NL@%
  11428.         IF screenMode = VAL(mode$(i)) THEN modeBox.listPos = i%@NL@%
  11429.     NEXT i%@NL@%
  11430. %@NL@%
  11431. %@AB@%    ' set up display window%@AE@%%@NL@%
  11432.     winRow = 6%@NL@%
  11433.     winCol = 25%@NL@%
  11434.     WindowOpen 1, winRow, winCol, winRow + numModes + 3, 51, 0, 7, 0, 7, 15, FALSE, FALSE, FALSE, TRUE, 2, "Screen Mode"%@NL@%
  11435.     WindowLine numModes + 3%@NL@%
  11436. %@NL@%
  11437. %@AB@%    ' create the list box%@AE@%%@NL@%
  11438.     CreateListBox mode$(), modeBox, 0%@NL@%
  11439. %@NL@%
  11440. %@AB@%    ' open command buttons%@AE@%%@NL@%
  11441.     ButtonOpen 3, 2, "OK ", numModes + 4, 4, 0, 0, 1%@NL@%
  11442.     ButtonOpen 4, 1, "Cancel ", numModes + 4, 16, 0, 0, 1%@NL@%
  11443. %@NL@%
  11444. %@NL@%
  11445.         a$ = "Screen Mode Warning ||"%@NL@%
  11446.         a$ = a$ + "Selecting screen modes that support less than |"%@NL@%
  11447.         a$ = a$ + "than 16 colors will reset all chart colors to |"%@NL@%
  11448.         a$ = a$ + "their black and white defaults.               |"%@NL@%
  11449.         a$ = a$ + "|" + " Fonts should be reloaded after screen mode is   |"%@NL@%
  11450.         a$ = a$ + " changed to ensure best font match for screen   |"%@NL@%
  11451.         a$ = a$ + " resolution.                                     "%@NL@%
  11452.         junk = Alert(4, a$, 6, 15, 16, 65, "", "", "")%@NL@%
  11453. %@NL@%
  11454. %@NL@%
  11455. %@AB@%    ' start with cursor in area button%@AE@%%@NL@%
  11456.     currButton = 2%@NL@%
  11457.     pushButton = 3%@NL@%
  11458. %@NL@%
  11459. %@AB@%    ' window control loop%@AE@%%@NL@%
  11460.     finished = FALSE%@NL@%
  11461.     WHILE NOT finished%@NL@%
  11462.         WindowDo currButton, 0                         ' wait for event%@NL@%
  11463.         SELECT CASE Dialog(0)%@NL@%
  11464.             CASE 1                                     ' button pressed%@NL@%
  11465.                 currButton = Dialog(1)%@NL@%
  11466.                 SELECT CASE currButton%@NL@%
  11467.                     CASE 1, 2:%@NL@%
  11468.                         ScrollList mode$(), modeBox, currButton, 1, 0, winRow, winCol%@NL@%
  11469.                         currButton = 2%@NL@%
  11470.                     CASE 3, 4:%@NL@%
  11471.                         pushButton = currButton%@NL@%
  11472.                         finished = TRUE%@NL@%
  11473.                 END SELECT%@NL@%
  11474.             CASE 6                                      ' enter%@NL@%
  11475.                 finished = TRUE%@NL@%
  11476.             CASE 7                                      ' tab%@NL@%
  11477.                 SELECT CASE currButton%@NL@%
  11478.                     CASE 1, 2:%@NL@%
  11479.                         currButton = 3%@NL@%
  11480.                         ButtonSetState pushButton, 1%@NL@%
  11481.                         ButtonSetState currButton, 2%@NL@%
  11482.                         pushButton = 3%@NL@%
  11483.                     CASE 3:%@NL@%
  11484.                         currButton = 4%@NL@%
  11485.                         ButtonSetState pushButton, 1%@NL@%
  11486.                         ButtonSetState currButton, 2%@NL@%
  11487.                         pushButton = 4%@NL@%
  11488.                     CASE 4:%@NL@%
  11489.                         ButtonSetState currButton, 1%@NL@%
  11490.                         currButton = 2%@NL@%
  11491.                         pushButton = 3%@NL@%
  11492.                         ButtonSetState pushButton, 2%@NL@%
  11493.                 END SELECT%@NL@%
  11494.             CASE 8                                      ' back tab%@NL@%
  11495.                 SELECT CASE currButton%@NL@%
  11496.                     CASE 1, 2:%@NL@%
  11497.                         currButton = 4%@NL@%
  11498.                         ButtonSetState pushButton, 1%@NL@%
  11499.                         ButtonSetState currButton, 2%@NL@%
  11500.                         pushButton = 4%@NL@%
  11501.                     CASE 3: currButton = 2%@NL@%
  11502.                     CASE 4:%@NL@%
  11503.                         currButton = 3%@NL@%
  11504.                         ButtonSetState pushButton, 1%@NL@%
  11505.                         ButtonSetState currButton, 2%@NL@%
  11506.                         pushButton = 3%@NL@%
  11507.                     END SELECT%@NL@%
  11508.             CASE 9                                      ' escape%@NL@%
  11509.                 pushButton = 4%@NL@%
  11510.                 finished = TRUE%@NL@%
  11511.             CASE 10, 12                                 ' up, left arrow%@NL@%
  11512.                 SELECT CASE currButton%@NL@%
  11513.                     CASE 1, 2: ScrollList mode$(), modeBox, currButton, 2, 0, winRow, winCol%@NL@%
  11514.                 END SELECT%@NL@%
  11515.             CASE 11, 13                                 ' down, right arrow%@NL@%
  11516.                 SELECT CASE currButton%@NL@%
  11517.                     CASE 1, 2: ScrollList mode$(), modeBox, currButton, 3, 0, winRow, winCol%@NL@%
  11518.                 END SELECT%@NL@%
  11519.             CASE 14                                     ' space bar%@NL@%
  11520.                 IF currButton > 2 THEN finished = TRUE%@NL@%
  11521.         END SELECT%@NL@%
  11522.     WEND%@NL@%
  11523. %@NL@%
  11524. %@AB@%    ' if not canceled%@AE@%%@NL@%
  11525.     IF pushButton = 3 THEN%@NL@%
  11526. %@AB@%        ' change screen mode%@AE@%%@NL@%
  11527.         IF screenMode <> VAL(mode$(modeBox.listPos)) THEN%@NL@%
  11528.             IF setNum > 0 THEN chartChanged = TRUE%@NL@%
  11529. %@NL@%
  11530.             screenMode = VAL(mode$(modeBox.listPos))%@NL@%
  11531. %@NL@%
  11532. %@AB@%            ' reset window coords%@AE@%%@NL@%
  11533.             CEnv.ChartWindow.X1 = 0%@NL@%
  11534.             CEnv.ChartWindow.Y1 = 0%@NL@%
  11535.             CEnv.ChartWindow.X2 = 0%@NL@%
  11536.             CEnv.ChartWindow.Y2 = 0%@NL@%
  11537. %@NL@%
  11538. %@AB@%            ' change color list based on new screen mode%@AE@%%@NL@%
  11539.             InitColors%@NL@%
  11540.         END IF%@NL@%
  11541.     END IF%@NL@%
  11542. %@NL@%
  11543.     WindowClose 1%@NL@%
  11544. %@NL@%
  11545. END SUB%@NL@%
  11546. %@NL@%
  11547. %@NL@%
  11548. %@NL@%
  11549. %@2@%%@AH@%CHRTDEMO.BAS%@AE@%%@EH@%%@NL@%
  11550. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\CHRTDEMO.BAS%@AE@%%@NL@%
  11551. %@NL@%
  11552. %@AB@%'       CHRTDEMO.BAS - Main module of CHRTB demonstration program%@AE@%%@NL@%
  11553. %@AB@%'%@AE@%%@NL@%
  11554. %@AB@%'             Copyright (C) 1989, Microsoft Corporation%@AE@%%@NL@%
  11555. %@AB@%'%@AE@%%@NL@%
  11556. %@AB@%'   This demo program uses the Presentation Graphics and User Interface%@AE@%%@NL@%
  11557. %@AB@%'   toolboxes to implement a general purpose charting package.%@AE@%%@NL@%
  11558. %@AB@%'   It consists of three modules (CHRTDEMO.BAS, CHRTDEM1.BAS and CHRTDEM2.BAS)%@AE@%%@NL@%
  11559. %@AB@%'   and one include file (CHRTDEMO.BI).  It requires access to both the%@AE@%%@NL@%
  11560. %@AB@%'   Presentation Graphics and User Interface toolboxes.%@AE@%%@NL@%
  11561. %@AB@%'%@AE@%%@NL@%
  11562. %@AB@%'   EMS is needed to load and run the demo under QBX.  If you do not%@AE@%%@NL@%
  11563. %@AB@%'   have EMS, refer to the command line compile instructions below which%@AE@%%@NL@%
  11564. %@AB@%'   will allow you to run the demo from the DOS prompt.  Running the%@AE@%%@NL@%
  11565. %@AB@%'   demo under QBX requires access to the Presentation Graphics and User%@AE@%%@NL@%
  11566. %@AB@%'   Interface toolboxes.  This can be done in one of two methods:%@AE@%%@NL@%
  11567. %@AB@%'       1) One large QuickLib covering both toolboxes can be created.  The%@AE@%%@NL@%
  11568. %@AB@%'          library "CHRTDEM.LIB" and QuickLib "CHRTDEM.QLB" are created%@AE@%%@NL@%
  11569. %@AB@%'          as follows:%@AE@%%@NL@%
  11570. %@AB@%'           BC /X/FS chrtb.bas;%@AE@%%@NL@%
  11571. %@AB@%'           BC /X/FS fontb.bas;%@AE@%%@NL@%
  11572. %@AB@%'           LIB chrtdem.lib + uitbefr.lib + fontasm + chrtasm + fontb + chrtb;%@AE@%%@NL@%
  11573. %@AB@%'           LINK /Q chrtdem.lib, chrtdem.qlb,,qbxqlb.lib;%@AE@%%@NL@%
  11574. %@AB@%'          Once created, just start QBX with this QuickLib and load the%@AE@%%@NL@%
  11575. %@AB@%'          demo's modules (chrtdemo.bas, chrtdem1.bas and chrtdem2.bas).%@AE@%%@NL@%
  11576. %@AB@%'%@AE@%%@NL@%
  11577. %@AB@%'       2) Either the Presentation Graphics or User Interface QuickLib%@AE@%%@NL@%
  11578. %@AB@%'          may be used alone provided the other's source code files%@AE@%%@NL@%
  11579. %@AB@%'          are loaded into the QBX environment.  If CHRTBEFR.QLB is%@AE@%%@NL@%
  11580. %@AB@%'          is used then WINDOW.BAS, GENERAL.BAS, MENU.BAS and MOUSE.BAS%@AE@%%@NL@%
  11581. %@AB@%'          must be loaded.  If UITBEFR.QLB is used then CHRTB.BAS and%@AE@%%@NL@%
  11582. %@AB@%'          FONTB.BAS must be loaded.  Once a QuickLib is specified and%@AE@%%@NL@%
  11583. %@AB@%'          all necessary source files are loaded, load the program%@AE@%%@NL@%
  11584. %@AB@%'          modules (chrtdemo.bas, chrtdem1.bas and chrtdem2.bas)%@AE@%%@NL@%
  11585. %@AB@%'%@AE@%%@NL@%
  11586. %@AB@%'   To create a compiled version of the chart demo program perform the%@AE@%%@NL@%
  11587. %@AB@%'   following steps:%@AE@%%@NL@%
  11588. %@AB@%'       BC /X/FS chrtb.bas;%@AE@%%@NL@%
  11589. %@AB@%'       BC /X/FS fontb.bas;%@AE@%%@NL@%
  11590. %@AB@%'       LIB chrtdem.lib + uitbefr.lib + fontasm + chrtasm + fontb + chrtb;%@AE@%%@NL@%
  11591. %@AB@%'       BC /X/FS chrtdemo.bas;%@AE@%%@NL@%
  11592. %@AB@%'       BC /FS chrtdem1.bas;%@AE@%%@NL@%
  11593. %@AB@%'       BC /FS chrtdem2.bas;%@AE@%%@NL@%
  11594. %@AB@%'       LINK /EX chrtdemo chrtdem1 chrtdem2, chrtdemo.exe,, chrtdem.lib;%@AE@%%@NL@%
  11595. %@AB@%'   "CHRTDEMO" can now be run from the command line.%@AE@%%@NL@%
  11596. %@AB@%'%@AE@%%@NL@%
  11597. %@AB@%'%@AE@%%@NL@%
  11598. DEFINT A-Z%@NL@%
  11599. %@NL@%
  11600. %@AB@%'$INCLUDE: 'chrtdemo.bi'%@AE@%%@NL@%
  11601. %@NL@%
  11602. %@AB@%' local functions%@AE@%%@NL@%
  11603. DECLARE FUNCTION GetLoadFile% (FileName$)%@NL@%
  11604. DECLARE FUNCTION GetSaveFile% (FileName$)%@NL@%
  11605. DECLARE FUNCTION GetFileCount% (fileSpec$)%@NL@%
  11606. %@NL@%
  11607. %@AB@%' local subs%@AE@%%@NL@%
  11608. DECLARE SUB LoadChart (fileNum%)%@NL@%
  11609. DECLARE SUB ShowError (errorNum%)%@NL@%
  11610. %@NL@%
  11611. %@NL@%
  11612. %@AB@%' necessary variables for the toolboxes%@AE@%%@NL@%
  11613. DIM GloTitle(MAXMENU)           AS MenuTitleType%@NL@%
  11614. DIM GloItem(MAXMENU, MAXITEM)   AS MenuItemType%@NL@%
  11615. DIM GloWindow(MAXWINDOW)        AS windowType%@NL@%
  11616. DIM GloButton(MAXBUTTON)        AS buttonType%@NL@%
  11617. DIM GloEdit(MAXEDITFIELD)       AS EditFieldType%@NL@%
  11618. DIM GloWindowStack(MAXWINDOW)   AS INTEGER%@NL@%
  11619. DIM GloBuffer$(MAXWINDOW + 1, 2)%@NL@%
  11620. %@NL@%
  11621. %@AB@%' variables shared across modules%@AE@%%@NL@%
  11622. DIM colors$(1 TO MAXCOLORS)                     'valid colors$%@NL@%
  11623. DIM styles$(1 TO MAXSTYLES)                     'border style list%@NL@%
  11624. DIM fonts$(1 TO MAXFONTS)                       'fonts list%@NL@%
  11625. DIM Cat$(1 TO cMaxValues)                       'category names%@NL@%
  11626. DIM setName$(1 TO cMaxSets)                     'set names%@NL@%
  11627. DIM setLen(1 TO cMaxSets)   AS INTEGER          '# values per set%@NL@%
  11628. DIM setVal!(1 TO cMaxValues, 1 TO cMaxSets)     ' actual values%@NL@%
  11629. DIM mode$(1 TO 13)                              'list of modes%@NL@%
  11630. %@NL@%
  11631. %@NL@%
  11632. %@AB@%    ' set up main error handler%@AE@%%@NL@%
  11633.     ON ERROR GOTO ErrorHandle%@NL@%
  11634. %@NL@%
  11635. %@AB@%    ' initialize the program%@AE@%%@NL@%
  11636.     InitAll%@NL@%
  11637. %@NL@%
  11638. %@AB@%    ' Main loop%@AE@%%@NL@%
  11639.     WHILE NOT finished%@NL@%
  11640.         kbd$ = MenuInkey$%@NL@%
  11641.         WHILE MenuCheck(2)%@NL@%
  11642.             HandleMenuEvent%@NL@%
  11643.         WEND%@NL@%
  11644.     WEND%@NL@%
  11645. %@NL@%
  11646.     END%@NL@%
  11647. %@NL@%
  11648. %@AB@%'catch all error handler%@AE@%%@NL@%
  11649. ErrorHandle:%@NL@%
  11650.     ShowError ERR%@NL@%
  11651.     WindowClose 1                               ' close any active windows%@NL@%
  11652.     WindowClose 2%@NL@%
  11653. RESUME NEXT%@NL@%
  11654. %@NL@%
  11655. %@AB@%'%@AE@%%@NL@%
  11656. %@AB@%' Function Name: GetBestMode%@AE@%%@NL@%
  11657. %@AB@%'%@AE@%%@NL@%
  11658. %@AB@%' Description: Creates a list of valid screen modes for use by charting functions%@AE@%%@NL@%
  11659. %@AB@%'              and sets the initial screen mode to the highest resolution%@AE@%%@NL@%
  11660. %@AB@%'              possible.  If no graphic screen modes are available then%@AE@%%@NL@%
  11661. %@AB@%'              it causes the program to exit.%@AE@%%@NL@%
  11662. %@AB@%'%@AE@%%@NL@%
  11663. %@AB@%' Arguments: screenMode%@AE@%%@NL@%
  11664. %@AB@%'%@AE@%%@NL@%
  11665. SUB GetBestMode (screenMode)%@NL@%
  11666. SHARED mode$(), numModes AS INTEGER%@NL@%
  11667. %@NL@%
  11668. ON LOCAL ERROR GOTO badmode                     ' trap screen mode errors%@NL@%
  11669. %@NL@%
  11670. %@AB@%    ' test all possible screen modes creating a list of valid ones as we go%@AE@%%@NL@%
  11671.     numModes = 0%@NL@%
  11672.     FOR i = 13 TO 1 STEP -1%@NL@%
  11673.         valid = TRUE%@NL@%
  11674.         SCREEN i%@NL@%
  11675.         IF valid THEN%@NL@%
  11676.             numModes = numModes + 1%@NL@%
  11677.             mode$(numModes) = LTRIM$(STR$(i))%@NL@%
  11678.         END IF%@NL@%
  11679.     NEXT i%@NL@%
  11680. %@NL@%
  11681. %@AB@%    ' exit if no modes available%@AE@%%@NL@%
  11682.     IF numModes = 0 THEN%@NL@%
  11683.         screenMode = 0%@NL@%
  11684. %@AB@%    ' set current screen mode to best possible%@AE@%%@NL@%
  11685.     ELSEIF mode$(1) = "13" THEN%@NL@%
  11686.         screenMode = VAL(mode$(2))%@NL@%
  11687.     ELSE%@NL@%
  11688.         screenMode = VAL(mode$(1))%@NL@%
  11689.     END IF%@NL@%
  11690. %@NL@%
  11691. EXIT SUB%@NL@%
  11692. %@NL@%
  11693. badmode:%@NL@%
  11694.     valid = FALSE%@NL@%
  11695. RESUME NEXT%@NL@%
  11696. %@NL@%
  11697. END SUB%@NL@%
  11698. %@NL@%
  11699. %@AB@%'%@AE@%%@NL@%
  11700. %@AB@%' Func Name: GetFileCount%@AE@%%@NL@%
  11701. %@AB@%'%@AE@%%@NL@%
  11702. %@AB@%' Description: Returns number of DOS files matching a given file spec%@AE@%%@NL@%
  11703. %@AB@%'%@AE@%%@NL@%
  11704. %@AB@%' Arguments: fileSpec$ - DOS file spec  (i.e. "*.*")%@AE@%%@NL@%
  11705. %@AB@%'%@AE@%%@NL@%
  11706. FUNCTION GetFileCount% (fileSpec$)%@NL@%
  11707. %@NL@%
  11708. ON LOCAL ERROR GOTO GetCountError%@NL@%
  11709. %@NL@%
  11710.     count = 0%@NL@%
  11711. %@NL@%
  11712.     FileName$ = DIR$(fileSpec$)             ' Get first match if any%@NL@%
  11713. %@NL@%
  11714.     DO WHILE FileName$ <> ""                ' continue until no more matches%@NL@%
  11715.         count = count + 1%@NL@%
  11716.         FileName$ = DIR$%@NL@%
  11717.     LOOP%@NL@%
  11718. %@NL@%
  11719.     GetFileCount = count                    ' return count%@NL@%
  11720. %@NL@%
  11721.     EXIT FUNCTION%@NL@%
  11722. %@NL@%
  11723. GetCountError:%@NL@%
  11724. %@NL@%
  11725.     ShowError ERR                               ' display error message%@NL@%
  11726. %@NL@%
  11727. RESUME NEXT%@NL@%
  11728. %@NL@%
  11729. END FUNCTION%@NL@%
  11730. %@NL@%
  11731. %@AB@%'%@AE@%%@NL@%
  11732. %@AB@%' Func Name: GetLoadFile%@AE@%%@NL@%
  11733. %@AB@%'%@AE@%%@NL@%
  11734. %@AB@%' Description: Called by OpenChart, this prompts the user for a%@AE@%%@NL@%
  11735. %@AB@%'              DOS file to open.  It returns the file number of%@AE@%%@NL@%
  11736. %@AB@%'              the chart file with the actual file name being%@AE@%%@NL@%
  11737. %@AB@%'              passed back via the argument.%@AE@%%@NL@%
  11738. %@AB@%'%@AE@%%@NL@%
  11739. %@AB@%' Arguments: FileName$ - name of file to open%@AE@%%@NL@%
  11740. %@AB@%'%@AE@%%@NL@%
  11741. FUNCTION GetLoadFile% (FileName$)%@NL@%
  11742. DIM fileList$(1 TO 10)%@NL@%
  11743. DIM fileBox AS ListBox%@NL@%
  11744. %@NL@%
  11745. ON LOCAL ERROR GOTO GetLoadError                ' handle file opening errors%@NL@%
  11746. %@NL@%
  11747.     fileSpec$ = "*.CHT"                         ' default file spec%@NL@%
  11748.     origDir$ = CURDIR$%@NL@%
  11749.     origPos = 0                                 ' no file list element selected%@NL@%
  11750. %@NL@%
  11751. %@AB@%    ' get list of files matching spec%@AE@%%@NL@%
  11752.     fileCount = GetFileCount(fileSpec$)%@NL@%
  11753.     IF fileCount THEN%@NL@%
  11754.         REDIM fileList$(fileCount)%@NL@%
  11755.     END IF%@NL@%
  11756.     fileList$(1) = DIR$(fileSpec$)%@NL@%
  11757.     FOR i% = 2 TO fileCount%@NL@%
  11758.         fileList$(i%) = DIR$%@NL@%
  11759.     NEXT i%%@NL@%
  11760. %@NL@%
  11761. %@AB@%    ' set up list box for file list%@AE@%%@NL@%
  11762.     fileBox.scrollButton = 1%@NL@%
  11763.     fileBox.areaButton = 2%@NL@%
  11764.     fileBox.listLen = fileCount%@NL@%
  11765.     fileBox.topRow = 8%@NL@%
  11766.     fileBox.botRow = 14%@NL@%
  11767.     fileBox.leftCol = 7%@NL@%
  11768.     fileBox.rightCol = 22%@NL@%
  11769.     fileBox.listPos = origPos%@NL@%
  11770. %@NL@%
  11771. %@AB@%    ' create window for display%@AE@%%@NL@%
  11772.     winRow = 6%@NL@%
  11773.     winCol = 25%@NL@%
  11774.     WindowOpen 1, winRow, winCol, 21, 52, 0, 7, 0, 7, 15, FALSE, FALSE, FALSE, TRUE, 2, "Open Chart"%@NL@%
  11775.     WindowLocate 2, 2%@NL@%
  11776.     WindowPrint 2, "File Name:"%@NL@%
  11777.     WindowBox 1, 13, 3, 27%@NL@%
  11778.     WindowLocate 5, 2%@NL@%
  11779.     WindowPrint -1, origDir$%@NL@%
  11780.     WindowLocate 7, 11%@NL@%
  11781.     WindowPrint 2, "Files"%@NL@%
  11782.     WindowLine 15%@NL@%
  11783. %@NL@%
  11784. %@AB@%    ' create list box for file list%@AE@%%@NL@%
  11785.     CreateListBox fileList$(), fileBox, 5%@NL@%
  11786. %@NL@%
  11787. %@AB@%    ' open edit field for file spec%@AE@%%@NL@%
  11788.     EditFieldOpen 1, fileSpec$, 2, 14, 0, 7, 13, 70%@NL@%
  11789. %@NL@%
  11790. %@AB@%    ' open command buttons%@AE@%%@NL@%
  11791.     ButtonOpen 3, 2, "OK", 16, 5, 0, 0, 1%@NL@%
  11792.     ButtonOpen 4, 1, "Cancel", 16, 15, 0, 0, 1%@NL@%
  11793. %@NL@%
  11794. %@AB@%    ' start with cursor in edit field%@AE@%%@NL@%
  11795.     currButton = 0%@NL@%
  11796.     currEditField = 1%@NL@%
  11797.     pushButton = 3%@NL@%
  11798. %@NL@%
  11799. %@AB@%    ' control loop%@AE@%%@NL@%
  11800.     finished = FALSE%@NL@%
  11801.     WHILE NOT finished%@NL@%
  11802.         WindowDo currButton, currEditField              ' wait for event%@NL@%
  11803.         SELECT CASE Dialog(0)%@NL@%
  11804.             CASE 1                                      ' button pressed%@NL@%
  11805.                 currButton = Dialog(1)%@NL@%
  11806.                 SELECT CASE currButton%@NL@%
  11807.                     CASE 1, 2: currEditField = 0%@NL@%
  11808.                         ScrollList fileList$(), fileBox, currButton, 1, 0, winRow, winCol%@NL@%
  11809.                         currButton = 2%@NL@%
  11810.                     CASE 3, 4: pushButton = currButton%@NL@%
  11811.                         finished = TRUE%@NL@%
  11812.                 END SELECT%@NL@%
  11813.             CASE 2                                      ' Edit Field%@NL@%
  11814.                 currButton = 0%@NL@%
  11815.                 currEditField = 1%@NL@%
  11816.             CASE 6                                      ' enter%@NL@%
  11817.                 IF INSTR(EditFieldInquire$(1), "*") = 0 THEN finished = TRUE%@NL@%
  11818.             CASE 7                                      ' tab%@NL@%
  11819.                 SELECT CASE currButton%@NL@%
  11820.                     CASE 0: currButton = 2%@NL@%
  11821.                         currEditField = 0%@NL@%
  11822.                     CASE 1, 2:%@NL@%
  11823.                         currButton = 3%@NL@%
  11824.                         ButtonSetState 3, 2%@NL@%
  11825.                         ButtonSetState 4, 1%@NL@%
  11826.                         pushButton = 3%@NL@%
  11827.                     CASE 3:%@NL@%
  11828.                         currButton = 4%@NL@%
  11829.                         ButtonSetState 3, 1%@NL@%
  11830.                         ButtonSetState 4, 2%@NL@%
  11831.                         pushButton = 4%@NL@%
  11832.                     CASE 4:%@NL@%
  11833.                         currButton = 0%@NL@%
  11834.                         currEditField = 1%@NL@%
  11835.                         ButtonSetState 3, 2%@NL@%
  11836.                         ButtonSetState 4, 1%@NL@%
  11837.                         pushButton = 3%@NL@%
  11838.                 END SELECT%@NL@%
  11839.             CASE 8                                      ' back tab%@NL@%
  11840.                 SELECT CASE currButton%@NL@%
  11841.                     CASE 0: currButton = 4%@NL@%
  11842.                         currEditField = 0%@NL@%
  11843.                         ButtonSetState 3, 1%@NL@%
  11844.                         ButtonSetState 4, 2%@NL@%
  11845.                         pushButton = 4%@NL@%
  11846.                     CASE 1, 2:%@NL@%
  11847.                         currButton = 0%@NL@%
  11848.                         currEditField = 1%@NL@%
  11849.                     CASE 3:%@NL@%
  11850.                         currButton = 2%@NL@%
  11851.                     CASE 4:%@NL@%
  11852.                         currButton = 3%@NL@%
  11853.                         ButtonSetState 3, 2%@NL@%
  11854.                         ButtonSetState 4, 1%@NL@%
  11855.                         pushButton = 3%@NL@%
  11856.                 END SELECT%@NL@%
  11857.             CASE 9                                      ' escape%@NL@%
  11858.                 pushButton = 4%@NL@%
  11859.                 finished = TRUE%@NL@%
  11860.             CASE 10, 12                                 ' up, left arrow%@NL@%
  11861.                 IF currButton = 1 OR currButton = 2 THEN ScrollList fileList$(), fileBox, currButton, 2, 0, winRow, winCol%@NL@%
  11862.             CASE 11, 13                                 'down, right arrow%@NL@%
  11863.                 IF currButton = 1 OR currButton = 2 THEN ScrollList fileList$(), fileBox, currButton, 3, 0, winRow, winCol%@NL@%
  11864.             CASE 14                                     ' space bar%@NL@%
  11865.                 IF currButton > 2 THEN%@NL@%
  11866.                     pushButton = currButton%@NL@%
  11867.                     finished = TRUE%@NL@%
  11868.                 END IF%@NL@%
  11869.         END SELECT%@NL@%
  11870. %@NL@%
  11871.         temp$ = EditFieldInquire$(1)%@NL@%
  11872. %@NL@%
  11873. %@AB@%        ' simple error checking before finishing%@AE@%%@NL@%
  11874.         IF finished AND pushButton <> 4 THEN%@NL@%
  11875. %@AB@%            ' invalid file specified%@AE@%%@NL@%
  11876.             IF INSTR(temp$, "*") THEN%@NL@%
  11877.                 PrintError "Invalid file specification."%@NL@%
  11878.                 finished = FALSE%@NL@%
  11879.             ELSEIF LEN(temp$) = 0 THEN%@NL@%
  11880.                 PrintError "Must specify a name."%@NL@%
  11881.                 finished = FALSE%@NL@%
  11882.             ELSE%@NL@%
  11883.                 fileSpec$ = temp$%@NL@%
  11884.                 fileNum% = FREEFILE%@NL@%
  11885.                 OPEN fileSpec$ FOR INPUT AS fileNum%%@NL@%
  11886. %@NL@%
  11887.             END IF%@NL@%
  11888.         END IF%@NL@%
  11889. %@NL@%
  11890. %@AB@%        ' more processing to do%@AE@%%@NL@%
  11891.         IF NOT finished THEN%@NL@%
  11892. %@AB@%            ' update edit field display based on list box selection%@AE@%%@NL@%
  11893.             IF fileBox.listPos <> origPos THEN%@NL@%
  11894.                 fileSpec$ = fileList$(fileBox.listPos)%@NL@%
  11895.                 origPos = fileBox.listPos%@NL@%
  11896.                 EditFieldClose 1%@NL@%
  11897.                 EditFieldOpen 1, fileSpec$, 2, 14, 0, 7, 13, 70%@NL@%
  11898. %@AB@%            ' update list box contents based on new edit field contents%@AE@%%@NL@%
  11899.             ELSEIF LTRIM$(RTRIM$(fileSpec$)) <> LTRIM$(RTRIM$(temp$)) THEN%@NL@%
  11900.                 fileSpec$ = UCASE$(temp$)%@NL@%
  11901.                 IF fileSpec$ <> "" THEN%@NL@%
  11902.                     IF MID$(fileSpec$, 2, 1) = ":" THEN%@NL@%
  11903.                         CHDRIVE MID$(fileSpec$, 1, 2)%@NL@%
  11904.                         fileSpec$ = MID$(fileSpec$, 3, LEN(fileSpec$))%@NL@%
  11905.                     END IF%@NL@%
  11906.                     position = 0%@NL@%
  11907.                     WHILE INSTR(position + 1, fileSpec$, "\") <> 0%@NL@%
  11908.                         position = INSTR(position + 1, fileSpec$, "\")%@NL@%
  11909.                     WEND%@NL@%
  11910.                     IF position = 1 THEN%@NL@%
  11911.                         CHDIR "\"%@NL@%
  11912.                     ELSEIF position > 0 THEN%@NL@%
  11913.                         CHDIR LEFT$(fileSpec$, position - 1)%@NL@%
  11914.                     END IF%@NL@%
  11915.                     fileSpec$ = MID$(fileSpec$, position + 1, LEN(fileSpec$))%@NL@%
  11916.                     WindowLocate 5, 2%@NL@%
  11917.                     IF LEN(CURDIR$) > 26 THEN%@NL@%
  11918.                         direct$ = LEFT$(CURDIR$, 26)%@NL@%
  11919.                     ELSE%@NL@%
  11920.                         direct$ = CURDIR$%@NL@%
  11921.                     END IF%@NL@%
  11922.                     WindowPrint -1, direct$ + STRING$(26 - LEN(direct$), " ")%@NL@%
  11923. %@NL@%
  11924.                     fileCount = GetFileCount(fileSpec$)%@NL@%
  11925.                 ELSE%@NL@%
  11926.                     fileCount = 0%@NL@%
  11927.                 END IF%@NL@%
  11928. %@NL@%
  11929.                 EditFieldClose 1%@NL@%
  11930.                 EditFieldOpen 1, fileSpec$, 2, 14, 0, 7, 13, 70%@NL@%
  11931. %@NL@%
  11932.                 fileBox.listLen = fileCount%@NL@%
  11933.                 fileBox.maxLen = Min(fileCount, fileBox.boxLen)%@NL@%
  11934.                 origPos = 0%@NL@%
  11935.                 fileBox.listPos = origPos%@NL@%
  11936.                 fileBox.currTop = 1%@NL@%
  11937.                 fileBox.currPos = 0%@NL@%
  11938. %@AB@%                ' get new file list%@AE@%%@NL@%
  11939.                 IF fileCount = 0 THEN%@NL@%
  11940.                     REDIM fileList$(10)%@NL@%
  11941.                 ELSE%@NL@%
  11942.                     REDIM fileList$(fileCount)%@NL@%
  11943.                     fileList$(1) = DIR$(fileSpec$)%@NL@%
  11944.                     FOR i% = 2 TO fileCount%@NL@%
  11945.                         fileList$(i%) = DIR$%@NL@%
  11946.                     NEXT i%%@NL@%
  11947.                 END IF%@NL@%
  11948. %@NL@%
  11949.                 DrawList fileList$(), fileBox, 0   ' redraw file list%@NL@%
  11950.             END IF%@NL@%
  11951.         END IF%@NL@%
  11952.     WEND%@NL@%
  11953. %@NL@%
  11954. %@AB@%    ' if operation not canceled return file name and file number%@AE@%%@NL@%
  11955.     IF pushButton = 3 THEN%@NL@%
  11956.         FileName$ = fileSpec$%@NL@%
  11957.         GetLoadFile% = fileNum%%@NL@%
  11958.     ELSE%@NL@%
  11959.         GetLoadFile% = 0%@NL@%
  11960. %@NL@%
  11961.         CHDRIVE MID$(origDir$, 1, 2)%@NL@%
  11962.         CHDIR MID$(origDir$, 3, LEN(origDir$))%@NL@%
  11963.     END IF%@NL@%
  11964. %@NL@%
  11965.     WindowClose 1%@NL@%
  11966. %@NL@%
  11967.     EXIT FUNCTION%@NL@%
  11968. %@NL@%
  11969. %@AB@%' handle any file opening errors%@AE@%%@NL@%
  11970. GetLoadError:%@NL@%
  11971.     CLOSE fileNum%%@NL@%
  11972.     finished = FALSE                            ' don't allow exit until valid file chosen%@NL@%
  11973. %@NL@%
  11974.     ShowError ERR                               ' display error message%@NL@%
  11975. RESUME NEXT%@NL@%
  11976. %@NL@%
  11977. END FUNCTION%@NL@%
  11978. %@NL@%
  11979. %@AB@%'%@AE@%%@NL@%
  11980. %@AB@%' Func Name: GetSaveFile%@AE@%%@NL@%
  11981. %@AB@%'%@AE@%%@NL@%
  11982. %@AB@%' Description: Prompts the user for a DOS file to save the current%@AE@%%@NL@%
  11983. %@AB@%'              chart data and settings in.  It returns the file number%@AE@%%@NL@%
  11984. %@AB@%'              with the actual file name being passed back via the%@AE@%%@NL@%
  11985. %@AB@%'              argument.%@AE@%%@NL@%
  11986. %@AB@%'%@AE@%%@NL@%
  11987. %@AB@%' Arguments: fileName$ - name of save file%@AE@%%@NL@%
  11988. %@AB@%'%@AE@%%@NL@%
  11989. FUNCTION GetSaveFile% (FileName$)%@NL@%
  11990. %@NL@%
  11991. ON LOCAL ERROR GOTO GetSaveError                    ' handle file open errors%@NL@%
  11992. %@NL@%
  11993. %@AB@%    ' Open window for display%@AE@%%@NL@%
  11994.     WindowOpen 1, 8, 20, 12, 58, 0, 7, 0, 7, 15, FALSE, FALSE, FALSE, TRUE, 1, "Save Chart As"%@NL@%
  11995.     WindowLocate 2, 2%@NL@%
  11996.     WindowPrint 2, "File Name:"%@NL@%
  11997.     WindowBox 1, 13, 3, 38%@NL@%
  11998.     WindowLine 4%@NL@%
  11999. %@NL@%
  12000. %@AB@%    ' open edit field for file name%@AE@%%@NL@%
  12001.     EditFieldOpen 1, RTRIM$(FileName$), 2, 14, 0, 7, 24, 70%@NL@%
  12002. %@NL@%
  12003. %@AB@%    ' open command buttons%@AE@%%@NL@%
  12004.     ButtonOpen 1, 2, "OK", 5, 6, 0, 0, 1%@NL@%
  12005.     ButtonOpen 2, 1, "Cancel", 5, 25, 0, 0, 1%@NL@%
  12006. %@NL@%
  12007. %@AB@%    ' start with cursor in edit field%@AE@%%@NL@%
  12008.     currButton = 0%@NL@%
  12009.     currEditField = 1%@NL@%
  12010.     pushButton = 1%@NL@%
  12011. %@NL@%
  12012. %@AB@%    ' control loop for window%@AE@%%@NL@%
  12013.     finished = FALSE%@NL@%
  12014.     WHILE NOT finished%@NL@%
  12015.         WindowDo currButton, currEditField              ' wait for event%@NL@%
  12016.         SELECT CASE Dialog(0)%@NL@%
  12017.             CASE 1                                      ' Button pressed%@NL@%
  12018.                 pushButton = Dialog(1)%@NL@%
  12019.                 finished = TRUE%@NL@%
  12020.             CASE 2                                      ' Edit Field%@NL@%
  12021.                 currButton = 0%@NL@%
  12022.                 currEditField = 1%@NL@%
  12023.             CASE 6                                      ' enter%@NL@%
  12024.                 finished = TRUE%@NL@%
  12025.             CASE 7                                      ' tab%@NL@%
  12026.                 SELECT CASE currButton%@NL@%
  12027.                     CASE 0, 1:%@NL@%
  12028.                         ButtonSetState currButton, 1%@NL@%
  12029.                         currButton = currButton + 1%@NL@%
  12030.                         pushButton = currButton%@NL@%
  12031.                         ButtonSetState pushButton, 2%@NL@%
  12032.                         currEditField = 0%@NL@%
  12033.                     CASE 2%@NL@%
  12034.                         currButton = 0%@NL@%
  12035.                         pushButton = 1%@NL@%
  12036.                         currEditField = 1%@NL@%
  12037.                         ButtonSetState 1, 2%@NL@%
  12038.                         ButtonSetState 2, 1%@NL@%
  12039.                 END SELECT%@NL@%
  12040.             CASE 8                                      ' back tab%@NL@%
  12041.                 SELECT CASE currButton%@NL@%
  12042.                     CASE 0:%@NL@%
  12043.                         currButton = 2%@NL@%
  12044.                         pushButton = 2%@NL@%
  12045.                         currEditField = 0%@NL@%
  12046.                         ButtonSetState 1, 1%@NL@%
  12047.                         ButtonSetState 2, 2%@NL@%
  12048.                     CASE 1%@NL@%
  12049.                         currButton = 0%@NL@%
  12050.                         currEditField = 1%@NL@%
  12051.                     CASE 2%@NL@%
  12052.                         currButton = 1%@NL@%
  12053.                         pushButton = 1%@NL@%
  12054.                         ButtonSetState 1, 2%@NL@%
  12055.                         ButtonSetState 2, 1%@NL@%
  12056.                 END SELECT%@NL@%
  12057.             CASE 9                                      ' escape%@NL@%
  12058.                 pushButton = 2%@NL@%
  12059.                 finished = TRUE%@NL@%
  12060.             CASE 14                                     ' space bar%@NL@%
  12061.                 IF currButton <> 0 THEN%@NL@%
  12062.                     finished = TRUE%@NL@%
  12063.                 END IF%@NL@%
  12064.         END SELECT%@NL@%
  12065. %@NL@%
  12066. %@AB@%        ' simple error checking before finishing%@AE@%%@NL@%
  12067.         IF finished = TRUE AND pushButton = 1 THEN%@NL@%
  12068.             temp$ = EditFieldInquire$(1)%@NL@%
  12069. %@AB@%            ' must specify a file%@AE@%%@NL@%
  12070.             IF temp$ = "" THEN%@NL@%
  12071.                 PrintError "Must specify a name."%@NL@%
  12072.                 finished = FALSE%@NL@%
  12073. %@AB@%            ' check if file is valid and can be opened%@AE@%%@NL@%
  12074.             ELSE%@NL@%
  12075. %@AB@%                ' open file%@AE@%%@NL@%
  12076.                 fileNum% = FREEFILE%@NL@%
  12077.                 OPEN temp$ FOR OUTPUT AS fileNum%%@NL@%
  12078. %@NL@%
  12079.             END IF%@NL@%
  12080.         END IF%@NL@%
  12081.     WEND%@NL@%
  12082. %@NL@%
  12083. %@AB@%    ' if operation not canceled return file name and file number%@AE@%%@NL@%
  12084.     IF pushButton = 1 THEN%@NL@%
  12085.         FileName$ = EditFieldInquire$(1)%@NL@%
  12086.         GetSaveFile% = fileNum%%@NL@%
  12087.     ELSE%@NL@%
  12088.         GetSaveFile% = 0%@NL@%
  12089.     END IF%@NL@%
  12090. %@NL@%
  12091.     WindowClose 1%@NL@%
  12092. %@NL@%
  12093.     EXIT FUNCTION%@NL@%
  12094. %@NL@%
  12095. %@AB@%' local error handler%@AE@%%@NL@%
  12096. GetSaveError:%@NL@%
  12097.       finished = FALSE                              ' don't exit until valid file specified%@NL@%
  12098.       CLOSE fileNum%%@NL@%
  12099. %@NL@%
  12100.       ShowError ERR                                 ' display errors%@NL@%
  12101. RESUME NEXT%@NL@%
  12102. %@NL@%
  12103. END FUNCTION%@NL@%
  12104. %@NL@%
  12105. %@AB@%'%@AE@%%@NL@%
  12106. %@AB@%' Sub Name: LoadChart%@AE@%%@NL@%
  12107. %@AB@%'%@AE@%%@NL@%
  12108. %@AB@%' Description: Loads chart data and settings from the given file.%@AE@%%@NL@%
  12109. %@AB@%'%@AE@%%@NL@%
  12110. %@AB@%' Arguments: fileNum%  - file number%@AE@%%@NL@%
  12111. %@AB@%'%@AE@%%@NL@%
  12112. SUB LoadChart (fileNum%)%@NL@%
  12113. SHARED Cat$(), catLen AS INTEGER%@NL@%
  12114. SHARED setLen() AS INTEGER, setName$(), setVal!()%@NL@%
  12115. SHARED screenMode AS INTEGER, numModes AS INTEGER, mode$()%@NL@%
  12116. %@NL@%
  12117. ON LOCAL ERROR GOTO LoadError                       ' handle file loading errors%@NL@%
  12118. %@NL@%
  12119. %@AB@%    ' Read file until EOF is reached:%@AE@%%@NL@%
  12120.     DO UNTIL EOF(fileNum%)%@NL@%
  12121. %@AB@%        ' get data type from file (C=category, V=value, T=title, S=setting):%@AE@%%@NL@%
  12122.         INPUT #fileNum%, type$%@NL@%
  12123. %@NL@%
  12124. %@AB@%        ' category data%@AE@%%@NL@%
  12125.         IF UCASE$(type$) = "C" THEN%@NL@%
  12126.             INPUT #fileNum%, catLen%@NL@%
  12127.             FOR i% = 1 TO catLen%@NL@%
  12128.                 INPUT #fileNum%, Cat$(i%)%@NL@%
  12129.             NEXT i%%@NL@%
  12130. %@NL@%
  12131. %@AB@%        ' value data%@AE@%%@NL@%
  12132.         ELSEIF UCASE$(type$) = "V" THEN%@NL@%
  12133. %@AB@%            ' too many sets in file%@AE@%%@NL@%
  12134.             IF setNum >= cMaxSets THEN%@NL@%
  12135.                 PrintError "Too many data sets in file. Extra sets lost."%@NL@%
  12136.                 EXIT DO%@NL@%
  12137.             END IF%@NL@%
  12138. %@NL@%
  12139.             setNum = setNum + 1%@NL@%
  12140.             INPUT #fileNum%, setName$(setNum)         ' get set name%@NL@%
  12141.             INPUT #fileNum%, setLen(setNum)           ' get set length%@NL@%
  12142.             FOR i% = 1 TO setLen(setNum)%@NL@%
  12143.                 INPUT #fileNum%, setVal!(i%, setNum)  ' get set values%@NL@%
  12144.             NEXT i%%@NL@%
  12145. %@NL@%
  12146. %@AB@%        ' title data%@AE@%%@NL@%
  12147.         ELSEIF UCASE$(type$) = "T" THEN%@NL@%
  12148.             INPUT #fileNum%, CEnv.MainTitle.title%@NL@%
  12149.             INPUT #fileNum%, CEnv.SubTitle.title%@NL@%
  12150.             INPUT #fileNum%, CEnv.XAxis.AxisTitle.title%@NL@%
  12151.             INPUT #fileNum%, CEnv.YAxis.AxisTitle.title%@NL@%
  12152. %@NL@%
  12153. %@AB@%        ' chart settings%@AE@%%@NL@%
  12154.         ELSEIF UCASE$(type$) = "S" THEN%@NL@%
  12155.             INPUT #fileNum%, screenMode%@NL@%
  12156. %@AB@%            ' test for valid screen mode%@AE@%%@NL@%
  12157.             valid = FALSE%@NL@%
  12158.             FOR i = 1 TO numModes%@NL@%
  12159.                 IF screenMode = VAL(mode$(i)) THEN valid = TRUE%@NL@%
  12160.             NEXT i%@NL@%
  12161.             IF NOT valid THEN%@NL@%
  12162.                 IF mode$(1) = "13" THEN%@NL@%
  12163.                     screenMode = VAL(mode$(2))%@NL@%
  12164.                 ELSE%@NL@%
  12165.                     screenMode = VAL(mode$(1))%@NL@%
  12166.                 END IF%@NL@%
  12167.             END IF%@NL@%
  12168. %@NL@%
  12169.             INPUT #fileNum%, CEnv.ChartType, CEnv.ChartStyle, CEnv.DataFont%@NL@%
  12170. %@NL@%
  12171.             INPUT #fileNum%, CEnv.ChartWindow.X1, CEnv.ChartWindow.Y1, CEnv.ChartWindow.X2, CEnv.ChartWindow.Y2%@NL@%
  12172.             INPUT #fileNum%, CEnv.ChartWindow.Background, CEnv.ChartWindow.border, CEnv.ChartWindow.BorderStyle, CEnv.ChartWindow.BorderColor%@NL@%
  12173.             INPUT #fileNum%, CEnv.DataWindow.X1, CEnv.DataWindow.Y1, CEnv.DataWindow.X2, CEnv.DataWindow.Y2%@NL@%
  12174.             INPUT #fileNum%, CEnv.DataWindow.Background, CEnv.DataWindow.border, CEnv.DataWindow.BorderStyle, CEnv.DataWindow.BorderColor%@NL@%
  12175. %@NL@%
  12176.             INPUT #fileNum%, CEnv.MainTitle.TitleFont, CEnv.MainTitle.TitleColor, CEnv.MainTitle.Justify%@NL@%
  12177.             INPUT #fileNum%, CEnv.SubTitle.TitleFont, CEnv.SubTitle.TitleColor, CEnv.SubTitle.Justify%@NL@%
  12178. %@NL@%
  12179.             INPUT #fileNum%, CEnv.XAxis.Grid, CEnv.XAxis.GridStyle, CEnv.XAxis.AxisColor, CEnv.XAxis.Labeled%@NL@%
  12180.             INPUT #fileNum%, CEnv.XAxis.AxisTitle.TitleFont, CEnv.XAxis.AxisTitle.TitleColor, CEnv.XAxis.AxisTitle.Justify%@NL@%
  12181.             INPUT #fileNum%, CEnv.XAxis.RangeType, CEnv.XAxis.LogBase, CEnv.XAxis.AutoScale, CEnv.XAxis.ScaleMin%@NL@%
  12182.             INPUT #fileNum%, CEnv.XAxis.ScaleMax, CEnv.XAxis.ScaleFactor, CEnv.XAxis.TicFont, CEnv.XAxis.TicInterval, CEnv.XAxis.TicFormat, CEnv.XAxis.TicDecimals%@NL@%
  12183.             INPUT #fileNum%, CEnv.XAxis.ScaleTitle.title%@NL@%
  12184.             INPUT #fileNum%, CEnv.XAxis.ScaleTitle.TitleFont, CEnv.XAxis.ScaleTitle.TitleColor, CEnv.XAxis.ScaleTitle.Justify%@NL@%
  12185. %@NL@%
  12186.             INPUT #fileNum%, CEnv.YAxis.Grid, CEnv.YAxis.GridStyle, CEnv.YAxis.AxisColor, CEnv.YAxis.Labeled%@NL@%
  12187.             INPUT #fileNum%, CEnv.YAxis.AxisTitle.TitleFont, CEnv.YAxis.AxisTitle.TitleColor, CEnv.YAxis.AxisTitle.Justify%@NL@%
  12188.             INPUT #fileNum%, CEnv.YAxis.RangeType, CEnv.YAxis.LogBase, CEnv.YAxis.AutoScale, CEnv.YAxis.ScaleMin%@NL@%
  12189.             INPUT #fileNum%, CEnv.YAxis.ScaleMax, CEnv.YAxis.ScaleFactor, CEnv.YAxis.TicFont, CEnv.YAxis.TicInterval, CEnv.YAxis.TicFormat, CEnv.YAxis.TicDecimals%@NL@%
  12190.             INPUT #fileNum%, CEnv.YAxis.ScaleTitle.title%@NL@%
  12191.             INPUT #fileNum%, CEnv.YAxis.ScaleTitle.TitleFont, CEnv.YAxis.ScaleTitle.TitleColor, CEnv.YAxis.ScaleTitle.Justify%@NL@%
  12192. %@NL@%
  12193.             INPUT #fileNum%, CEnv.Legend.Legend, CEnv.Legend.Place, CEnv.Legend.TextColor, CEnv.Legend.TextFont, CEnv.Legend.AutoSize%@NL@%
  12194.             INPUT #fileNum%, CEnv.Legend.LegendWindow.X1, CEnv.Legend.LegendWindow.Y1, CEnv.Legend.LegendWindow.X2, CEnv.Legend.LegendWindow.Y2%@NL@%
  12195.             INPUT #fileNum%, CEnv.Legend.LegendWindow.Background, CEnv.Legend.LegendWindow.border, CEnv.Legend.LegendWindow.BorderStyle, CEnv.Legend.LegendWindow.BorderColor%@NL@%
  12196.         ELSE%@NL@%
  12197.             GOSUB LoadError%@NL@%
  12198.         END IF%@NL@%
  12199.     LOOP%@NL@%
  12200. %@NL@%
  12201. %@AB@%    ' close the file%@AE@%%@NL@%
  12202.     CLOSE fileNum%%@NL@%
  12203. %@NL@%
  12204. %@AB@%    ' clear any font pointers that don't map to current fonts%@AE@%%@NL@%
  12205.     ClearFonts%@NL@%
  12206. %@NL@%
  12207. %@AB@%    ' initialize color list depending on newly loaded screen mode%@AE@%%@NL@%
  12208.     InitColors%@NL@%
  12209. %@NL@%
  12210.     EXIT SUB%@NL@%
  12211. %@NL@%
  12212. %@AB@%' handle any file format errors%@AE@%%@NL@%
  12213. LoadError:%@NL@%
  12214. %@NL@%
  12215.     IF ERR THEN%@NL@%
  12216.         ShowError ERR%@NL@%
  12217.     ELSE%@NL@%
  12218.         PrintError "Invalid file format.  Can't continue loading."%@NL@%
  12219.     END IF%@NL@%
  12220. %@NL@%
  12221.     CLOSE fileNum%                              ' close and exit%@NL@%
  12222.     EXIT SUB%@NL@%
  12223. %@NL@%
  12224. RESUME NEXT%@NL@%
  12225. %@NL@%
  12226. END SUB%@NL@%
  12227. %@NL@%
  12228. %@AB@%'%@AE@%%@NL@%
  12229. %@AB@%' Sub Name: OpenChart%@AE@%%@NL@%
  12230. %@AB@%'%@AE@%%@NL@%
  12231. %@AB@%' Description: Handles both the "New" and "Open" operations from the%@AE@%%@NL@%
  12232. %@AB@%'              "File" menu title.%@AE@%%@NL@%
  12233. %@AB@%'%@AE@%%@NL@%
  12234. %@AB@%' Arguments: newFlag - flag for determining which operation (New or Open)%@AE@%%@NL@%
  12235. %@AB@%'                      to perform.%@AE@%%@NL@%
  12236. %@AB@%'%@AE@%%@NL@%
  12237. SUB OpenChart (newFlag)%@NL@%
  12238. SHARED saveFile$%@NL@%
  12239. %@NL@%
  12240. %@AB@%    ' allow user to save current chart if necessary%@AE@%%@NL@%
  12241.     IF chartChanged THEN%@NL@%
  12242.         a$ = "|"%@NL@%
  12243.         a$ = a$ + "Current chart has not been saved.  Save now?"%@NL@%
  12244. %@NL@%
  12245.         status = Alert(4, a$, 8, 15, 12, 65, "Yes", "No", "Cancel")%@NL@%
  12246. %@NL@%
  12247. %@AB@%        ' save current chart%@AE@%%@NL@%
  12248.         IF status = OK THEN%@NL@%
  12249.             status = SaveChart(saveFile$, FALSE)%@NL@%
  12250.         END IF%@NL@%
  12251.     ELSE%@NL@%
  12252.         status = OK%@NL@%
  12253.     END IF%@NL@%
  12254. %@NL@%
  12255.     IF status <> CANCEL THEN%@NL@%
  12256. %@AB@%        ' New option chosen so clear existing data, leave chart settings alone.%@AE@%%@NL@%
  12257.         IF newFlag = TRUE THEN%@NL@%
  12258.             MenuItemToggle GALLERYTITLE, CEnv.ChartType%@NL@%
  12259.             IF CEnv.ChartType = cPie THEN%@NL@%
  12260.                 MenuSetState CHARTTITLE, 4, 1%@NL@%
  12261.                 MenuSetState CHARTTITLE, 5, 1%@NL@%
  12262.                 MenuSetState TITLETITLE, 3, 1%@NL@%
  12263.                 MenuSetState TITLETITLE, 4, 1%@NL@%
  12264.             END IF%@NL@%
  12265.             InitChart%@NL@%
  12266.             saveFile$ = ""%@NL@%
  12267. %@AB@%        ' Open operation chosen so get file and load data%@AE@%%@NL@%
  12268.         ELSE%@NL@%
  12269.             fileNum% = GetLoadFile(saveFile$)%@NL@%
  12270. %@AB@%            ' if no errors opening file and operation not canceled then load data%@AE@%%@NL@%
  12271.             IF fileNum <> 0 THEN%@NL@%
  12272. %@AB@%                ' reset menu bar to nothing selected%@AE@%%@NL@%
  12273.                 MenuItemToggle GALLERYTITLE, CEnv.ChartType%@NL@%
  12274.                 IF CEnv.ChartType = cPie THEN%@NL@%
  12275.                     MenuSetState CHARTTITLE, 4, 1%@NL@%
  12276.                     MenuSetState CHARTTITLE, 5, 1%@NL@%
  12277.                     MenuSetState TITLETITLE, 3, 1%@NL@%
  12278.                     MenuSetState TITLETITLE, 4, 1%@NL@%
  12279.                 END IF%@NL@%
  12280. %@NL@%
  12281.                 ClearData                       'clear current data%@NL@%
  12282. %@NL@%
  12283.                 setNum = 0%@NL@%
  12284.                 LoadChart fileNum%             ' load the data%@NL@%
  12285. %@NL@%
  12286. %@AB@%                ' set menu bar according to new chart settings%@AE@%%@NL@%
  12287.                 MenuItemToggle GALLERYTITLE, CEnv.ChartType%@NL@%
  12288.                 IF CEnv.ChartType = cPie THEN%@NL@%
  12289.                     MenuSetState CHARTTITLE, 4, 0%@NL@%
  12290.                     MenuSetState CHARTTITLE, 5, 0%@NL@%
  12291.                     MenuSetState TITLETITLE, 3, 0%@NL@%
  12292.                     MenuSetState TITLETITLE, 4, 0%@NL@%
  12293.                 END IF%@NL@%
  12294. %@NL@%
  12295. %@AB@%                ' new chart not changed%@AE@%%@NL@%
  12296.                 chartChanged = FALSE%@NL@%
  12297. %@NL@%
  12298. %@AB@%                ' chart data exists so allow user to view chart%@AE@%%@NL@%
  12299.                 IF setNum > 0 THEN%@NL@%
  12300.                     MenuSetState VIEWTITLE, 2, 1%@NL@%
  12301.                 END IF%@NL@%
  12302.             END IF%@NL@%
  12303.         END IF%@NL@%
  12304.     END IF%@NL@%
  12305. %@NL@%
  12306. END SUB%@NL@%
  12307. %@NL@%
  12308. %@AB@%'%@AE@%%@NL@%
  12309. %@AB@%' Sub Name: PrintError%@AE@%%@NL@%
  12310. %@AB@%'%@AE@%%@NL@%
  12311. %@AB@%' Description: Prints error messages on the screen in an Alert box.%@AE@%%@NL@%
  12312. %@AB@%'%@AE@%%@NL@%
  12313. %@AB@%' Arguments: text$ - error message%@AE@%%@NL@%
  12314. %@AB@%'%@AE@%%@NL@%
  12315. SUB PrintError (text$)%@NL@%
  12316. %@NL@%
  12317.     textLen = LEN(text$) + 2%@NL@%
  12318.     lefCol = ((80 - textLen) / 2) - 1%@NL@%
  12319.     a$ = "| " + text$%@NL@%
  12320.     junk = Alert(4, a$, 8, lefCol, 12, textLen + lefCol, "", "", "")%@NL@%
  12321. %@NL@%
  12322. END SUB%@NL@%
  12323. %@NL@%
  12324. %@AB@%'%@AE@%%@NL@%
  12325. %@AB@%' Func Name: SaveChart%@AE@%%@NL@%
  12326. %@AB@%'%@AE@%%@NL@%
  12327. %@AB@%' Description: Performs both the "Save" and "Save AS" operations from%@AE@%%@NL@%
  12328. %@AB@%'              the "File" menu title.  If "Save As" was chosen or if%@AE@%%@NL@%
  12329. %@AB@%'              "Save" was chosen and no save file has been previously%@AE@%%@NL@%
  12330. %@AB@%'              specified, it prompts the user for a new file in%@AE@%%@NL@%
  12331. %@AB@%'              which to save the current chart.  Also returns the status of%@AE@%%@NL@%
  12332. %@AB@%'              save operation for use in other routines%@AE@%%@NL@%
  12333. %@AB@%'%@AE@%%@NL@%
  12334. %@AB@%' Arguments: fileName$ - name of previously specified save file (may be nil)%@AE@%%@NL@%
  12335. %@AB@%'            saveAsFlag - flag for invoking the "Save As" operation.%@AE@%%@NL@%
  12336. %@AB@%'%@AE@%%@NL@%
  12337. FUNCTION SaveChart% (FileName$, saveAsFlag)%@NL@%
  12338. SHARED Cat$(), catLen AS INTEGER%@NL@%
  12339. SHARED setLen() AS INTEGER, setName$(), setVal!()%@NL@%
  12340. SHARED screenMode AS INTEGER%@NL@%
  12341. %@NL@%
  12342. ON LOCAL ERROR GOTO SaveError                   ' handle file errors%@NL@%
  12343. %@NL@%
  12344. %@AB@%    ' get new file name if necessary%@AE@%%@NL@%
  12345.     IF FileName$ = "" OR saveAsFlag THEN%@NL@%
  12346.         fileNum% = GetSaveFile(FileName$)%@NL@%
  12347. %@AB@%    ' otherwise just open the file%@AE@%%@NL@%
  12348.     ELSE%@NL@%
  12349.         fileNum% = FREEFILE%@NL@%
  12350.         OPEN FileName$ FOR OUTPUT AS fileNum%%@NL@%
  12351.     END IF%@NL@%
  12352. %@NL@%
  12353. %@AB@%    ' quit save if cancel chosen above or error occurred during open.%@AE@%%@NL@%
  12354.     IF fileNum% = 0 THEN%@NL@%
  12355.         SaveChart% = CANCEL                     ' return status%@NL@%
  12356.         EXIT FUNCTION%@NL@%
  12357.     END IF%@NL@%
  12358. %@NL@%
  12359. %@AB@%    ' save category data%@AE@%%@NL@%
  12360.     IF catLen > 0 THEN%@NL@%
  12361.         PRINT #fileNum%, "C"%@NL@%
  12362.         PRINT #fileNum%, catLen%@NL@%
  12363. %@NL@%
  12364.         FOR i% = 1 TO catLen%@NL@%
  12365.             PRINT #fileNum%, Cat$(i%)%@NL@%
  12366.         NEXT i%%@NL@%
  12367.     END IF%@NL@%
  12368. %@NL@%
  12369. %@AB@%    ' save value data%@AE@%%@NL@%
  12370.     IF setNum > 0 THEN%@NL@%
  12371.         FOR j% = 1 TO setNum%@NL@%
  12372.             PRINT #fileNum%, "V"%@NL@%
  12373.             PRINT #fileNum%, setName$(j%)%@NL@%
  12374.             PRINT #fileNum%, setLen(j%)%@NL@%
  12375. %@NL@%
  12376.             FOR i% = 1 TO setLen(j%)%@NL@%
  12377.                 PRINT #fileNum%, setVal!(i%, j%)%@NL@%
  12378.             NEXT i%%@NL@%
  12379.         NEXT j%%@NL@%
  12380.     END IF%@NL@%
  12381. %@NL@%
  12382. %@AB@%    ' save titles%@AE@%%@NL@%
  12383.     PRINT #fileNum%, "T"%@NL@%
  12384.     PRINT #fileNum%, CEnv.MainTitle.title%@NL@%
  12385.     PRINT #fileNum%, CEnv.SubTitle.title%@NL@%
  12386.     PRINT #fileNum%, CEnv.XAxis.AxisTitle.title%@NL@%
  12387.     PRINT #fileNum%, CEnv.YAxis.AxisTitle.title%@NL@%
  12388. %@NL@%
  12389. %@AB@%    'save chart settings%@AE@%%@NL@%
  12390.     PRINT #fileNum%, "S"%@NL@%
  12391.     PRINT #fileNum%, screenMode%@NL@%
  12392. %@NL@%
  12393.     PRINT #fileNum%, CEnv.ChartType, CEnv.ChartStyle, CEnv.DataFont%@NL@%
  12394. %@NL@%
  12395.     PRINT #fileNum%, CEnv.ChartWindow.X1, CEnv.ChartWindow.Y1, CEnv.ChartWindow.X2, CEnv.ChartWindow.Y2%@NL@%
  12396.     PRINT #fileNum%, CEnv.ChartWindow.Background, CEnv.ChartWindow.border, CEnv.ChartWindow.BorderStyle, CEnv.ChartWindow.BorderColor%@NL@%
  12397.     PRINT #fileNum%, CEnv.DataWindow.X1, CEnv.DataWindow.Y1, CEnv.DataWindow.X2, CEnv.DataWindow.Y2%@NL@%
  12398.     PRINT #fileNum%, CEnv.DataWindow.Background, CEnv.DataWindow.border, CEnv.DataWindow.BorderStyle, CEnv.DataWindow.BorderColor%@NL@%
  12399. %@NL@%
  12400.     PRINT #fileNum%, CEnv.MainTitle.TitleFont, CEnv.MainTitle.TitleColor, CEnv.MainTitle.Justify%@NL@%
  12401.     PRINT #fileNum%, CEnv.SubTitle.TitleFont, CEnv.SubTitle.TitleColor, CEnv.SubTitle.Justify%@NL@%
  12402. %@NL@%
  12403.     PRINT #fileNum%, CEnv.XAxis.Grid, CEnv.XAxis.GridStyle, CEnv.XAxis.AxisColor, CEnv.XAxis.Labeled%@NL@%
  12404.     PRINT #fileNum%, CEnv.XAxis.AxisTitle.TitleFont, CEnv.XAxis.AxisTitle.TitleColor, CEnv.XAxis.AxisTitle.Justify%@NL@%
  12405.     PRINT #fileNum%, CEnv.XAxis.RangeType, CEnv.XAxis.LogBase, CEnv.XAxis.AutoScale, CEnv.XAxis.ScaleMin%@NL@%
  12406.     PRINT #fileNum%, CEnv.XAxis.ScaleMax, CEnv.XAxis.ScaleFactor, CEnv.XAxis.TicFont, CEnv.XAxis.TicInterval, CEnv.XAxis.TicFormat, CEnv.XAxis.TicDecimals%@NL@%
  12407.     PRINT #fileNum%, CEnv.XAxis.ScaleTitle.title%@NL@%
  12408.     PRINT #fileNum%, CEnv.XAxis.ScaleTitle.TitleFont, CEnv.XAxis.ScaleTitle.TitleColor, CEnv.XAxis.ScaleTitle.Justify%@NL@%
  12409. %@NL@%
  12410.     PRINT #fileNum%, CEnv.YAxis.Grid, CEnv.YAxis.GridStyle, CEnv.YAxis.AxisColor, CEnv.YAxis.Labeled%@NL@%
  12411.     PRINT #fileNum%, CEnv.YAxis.AxisTitle.TitleFont, CEnv.YAxis.AxisTitle.TitleColor, CEnv.YAxis.AxisTitle.Justify%@NL@%
  12412.     PRINT #fileNum%, CEnv.YAxis.RangeType, CEnv.YAxis.LogBase, CEnv.YAxis.AutoScale, CEnv.YAxis.ScaleMin%@NL@%
  12413.     PRINT #fileNum%, CEnv.YAxis.ScaleMax, CEnv.YAxis.ScaleFactor, CEnv.YAxis.TicFont, CEnv.YAxis.TicInterval, CEnv.YAxis.TicFormat, CEnv.YAxis.TicDecimals%@NL@%
  12414.     PRINT #fileNum%, CEnv.YAxis.ScaleTitle.title%@NL@%
  12415.     PRINT #fileNum%, CEnv.YAxis.ScaleTitle.TitleFont, CEnv.YAxis.ScaleTitle.TitleColor, CEnv.YAxis.ScaleTitle.Justify%@NL@%
  12416. %@NL@%
  12417.     PRINT #fileNum%, CEnv.Legend.Legend, CEnv.Legend.Place, CEnv.Legend.TextColor, CEnv.Legend.TextFont, CEnv.Legend.AutoSize%@NL@%
  12418.     PRINT #fileNum%, CEnv.Legend.LegendWindow.X1, CEnv.Legend.LegendWindow.Y1, CEnv.Legend.LegendWindow.X2, CEnv.Legend.LegendWindow.Y2%@NL@%
  12419.     PRINT #fileNum%, CEnv.Legend.LegendWindow.Background, CEnv.Legend.LegendWindow.border, CEnv.Legend.LegendWindow.BorderStyle, CEnv.Legend.LegendWindow.BorderColor%@NL@%
  12420. %@NL@%
  12421.     CLOSE fileNum%%@NL@%
  12422. %@NL@%
  12423.     SaveChart% = OK                             ' return status%@NL@%
  12424. %@NL@%
  12425.     chartChanged = FALSE                        ' reset global change flag%@NL@%
  12426. %@NL@%
  12427.     EXIT FUNCTION%@NL@%
  12428. %@NL@%
  12429. %@AB@%' local error handler%@AE@%%@NL@%
  12430. SaveError:%@NL@%
  12431.       SaveChart% = CANCEL                       ' return cancel status%@NL@%
  12432.       CLOSE fileNum%%@NL@%
  12433. %@NL@%
  12434.       ShowError ERR                             ' display error message%@NL@%
  12435. %@NL@%
  12436.       EXIT FUNCTION                             ' exit on error%@NL@%
  12437. RESUME NEXT%@NL@%
  12438. %@NL@%
  12439. END FUNCTION%@NL@%
  12440. %@NL@%
  12441. %@AB@%'%@AE@%%@NL@%
  12442. %@AB@%' Sub Name: ShowError%@AE@%%@NL@%
  12443. %@AB@%'%@AE@%%@NL@%
  12444. %@AB@%' Description: Displays an appropriate error message for the given error%@AE@%%@NL@%
  12445. %@AB@%'%@AE@%%@NL@%
  12446. %@AB@%' Arguments: errorNum - error number%@AE@%%@NL@%
  12447. %@AB@%'%@AE@%%@NL@%
  12448. SUB ShowError (errorNum)%@NL@%
  12449.       SELECT CASE errorNum%@NL@%
  12450.         CASE 6:                                 ' overflow%@NL@%
  12451.             PrintError "Overflow occurred."%@NL@%
  12452.         CASE 14:                                ' out of space%@NL@%
  12453.             PrintError "Out of string space.  Please restart."%@NL@%
  12454.         CASE 53:                                ' file not found%@NL@%
  12455.             PrintError "File not found."%@NL@%
  12456.         CASE 62:                                ' input past end of file%@NL@%
  12457.             PrintError "Invalid file format. Can't continue loading."%@NL@%
  12458.         CASE 64:                                ' bad file name%@NL@%
  12459.             PrintError "Invalid file name."%@NL@%
  12460.         CASE 68:                                ' device unavailable%@NL@%
  12461.             PrintError "Selected device unavailable."%@NL@%
  12462.         CASE 71:                                ' disk not ready%@NL@%
  12463.             PrintError "Disk not ready."%@NL@%
  12464.         CASE 75:                                ' path access error%@NL@%
  12465.             PrintError "Invalid path."%@NL@%
  12466.         CASE 76:                                ' path not found%@NL@%
  12467.             PrintError "Path not found."%@NL@%
  12468.         CASE ELSE                               ' catch all%@NL@%
  12469.             PrintError "BASIC error #" + LTRIM$(STR$(ERR)) + " occurred."%@NL@%
  12470.      END SELECT%@NL@%
  12471. %@NL@%
  12472. %@NL@%
  12473. END SUB%@NL@%
  12474. %@NL@%
  12475. %@AB@%'%@AE@%%@NL@%
  12476. %@AB@%' Sub Name: ViewData%@AE@%%@NL@%
  12477. %@AB@%'%@AE@%%@NL@%
  12478. %@AB@%' Description: Displays the current chart data and allows the user to%@AE@%%@NL@%
  12479. %@AB@%'              modify, delete or add to that data.%@AE@%%@NL@%
  12480. %@AB@%'%@AE@%%@NL@%
  12481. %@AB@%' Arguments: none%@AE@%%@NL@%
  12482. %@AB@%'%@AE@%%@NL@%
  12483. SUB ViewData%@NL@%
  12484. SHARED setVal!(), setLen()  AS INTEGER, setName$()%@NL@%
  12485. SHARED Cat$(), catLen AS INTEGER%@NL@%
  12486. SHARED GloEdit() AS EditFieldType%@NL@%
  12487. %@NL@%
  12488. %@AB@%    ' temporary data storage that allows user to cancel all changes and%@AE@%%@NL@%
  12489. %@AB@%    ' restore original data%@AE@%%@NL@%
  12490.     DIM tsetVal$(1 TO 15, 1 TO 15), tCat$(1 TO 15), tsetName$(1 TO 15)%@NL@%
  12491.     DIM tsetNum AS INTEGER%@NL@%
  12492.     DIM tsetLen(1 TO 15) AS INTEGER%@NL@%
  12493.     DIM tcatLen  AS INTEGER%@NL@%
  12494. %@NL@%
  12495.     ON LOCAL ERROR GOTO ViewDatError%@NL@%
  12496. %@NL@%
  12497. %@AB@%    ' fill out temp data%@AE@%%@NL@%
  12498.     FOR i = 1 TO cMaxSets%@NL@%
  12499.         tsetName$(i) = setName$(i)%@NL@%
  12500.         tCat$(i) = Cat$(i)%@NL@%
  12501.         tsetLen(i) = setLen(i)%@NL@%
  12502.         FOR j = 1 TO tsetLen(i)%@NL@%
  12503.             tsetVal$(j, i) = LTRIM$(STR$(setVal!(j, i)))%@NL@%
  12504.         NEXT j%@NL@%
  12505.         FOR j = tsetLen(i) + 1 TO cMaxValues%@NL@%
  12506.             tsetVal$(j, i) = ""%@NL@%
  12507.         NEXT j%@NL@%
  12508.     NEXT i%@NL@%
  12509.     tsetNum = setNum%@NL@%
  12510.     tcatLen = catLen%@NL@%
  12511. %@NL@%
  12512. %@AB@%    ' set up window%@AE@%%@NL@%
  12513.     winRow = 4%@NL@%
  12514.     winCol = 8%@NL@%
  12515.     WindowOpen 1, winRow, winCol, 23, 74, 0, 7, 0, 7, 15, FALSE, FALSE, FALSE, TRUE, 2, "Chart Data"%@NL@%
  12516.     WindowLocate 1, 2%@NL@%
  12517.     WindowPrint 2, "Series Name:"%@NL@%
  12518.     WindowBox 2, 2, 18, 24%@NL@%
  12519.     WindowLocate 1, 26%@NL@%
  12520.     WindowPrint 2, "Categories:"%@NL@%
  12521.     WindowBox 2, 26, 18, 48%@NL@%
  12522.     WindowLocate 1, 50%@NL@%
  12523.     WindowPrint 2, "Values:"%@NL@%
  12524.     WindowBox 2, 50, 18, 66%@NL@%
  12525.     WindowLine 19%@NL@%
  12526. %@NL@%
  12527. %@AB@%    ' display chart data%@AE@%%@NL@%
  12528.     FOR i = 1 TO 15%@NL@%
  12529.         IF i < 10 THEN%@NL@%
  12530.             a$ = " "%@NL@%
  12531.         ELSE%@NL@%
  12532.             a$ = ""%@NL@%
  12533.         END IF%@NL@%
  12534.         a$ = a$ + LTRIM$(STR$(i)) + ". "%@NL@%
  12535.         WindowLocate i + 2, 3%@NL@%
  12536.         WindowPrint 2, a$ + tsetName$(i)%@NL@%
  12537.         WindowLocate i + 2, 27%@NL@%
  12538.         WindowPrint 2, a$ + tCat$(i)%@NL@%
  12539.         WindowLocate i + 2, 51%@NL@%
  12540.         WindowPrint 2, a$ + MID$(tsetVal$(i, 1), 1, 10)%@NL@%
  12541.     NEXT i%@NL@%
  12542. %@AB@%    ' highlight first set name%@AE@%%@NL@%
  12543.     EditFieldOpen 1, tsetName$(1), 3, 7, 7, 0, 17, 16%@NL@%
  12544. %@NL@%
  12545.     IF tsetNum < cMaxSets THEN tsetNum = tsetNum + 1%@NL@%
  12546.     IF tcatLen < cMaxValues THEN tcatLen = tcatLen + 1%@NL@%
  12547.     IF tsetLen(1) < cMaxValues THEN tsetLen(1) = tsetLen(1) + 1%@NL@%
  12548. %@NL@%
  12549. %@AB@%    ' area buttons%@AE@%%@NL@%
  12550.     ButtonOpen 1, 1, "", 3, 3, 17, 23, 4%@NL@%
  12551.     ButtonOpen 2, 1, "", 3, 27, 17, 47, 4%@NL@%
  12552.     ButtonOpen 3, 1, "", 3, 51, 17, 65, 4%@NL@%
  12553. %@NL@%
  12554. %@AB@%    ' command buttons%@AE@%%@NL@%
  12555.     ButtonOpen 4, 1, "OK", 20, 15, 0, 0, 1%@NL@%
  12556.     ButtonOpen 5, 1, "Cancel", 20, 45, 0, 0, 1%@NL@%
  12557. %@NL@%
  12558. %@AB@%    ' start with cursor in first set name edit field%@AE@%%@NL@%
  12559.     currButton = 1%@NL@%
  12560.     prevButton = 1%@NL@%
  12561.     currRow = 1%@NL@%
  12562.     currEditField = 1%@NL@%
  12563.     currCat = 1%@NL@%
  12564.     currVal = 1%@NL@%
  12565.     currSet = 1%@NL@%
  12566. %@NL@%
  12567.     IF CEnv.ChartType = cPie THEN%@NL@%
  12568.         a$ = " Pie chart information||"%@NL@%
  12569.         a$ = a$ + " Only data values from the first series are plotted in pie charts. |"%@NL@%
  12570.         a$ = a$ + " Data values from the second series are used in determining whether|"%@NL@%
  12571.         a$ = a$ + " or not pie pieces are exploded.  Non-zero values in this series   |"%@NL@%
  12572.         a$ = a$ + " will cause corresponding pie pieces to be exploded.  All other    |"%@NL@%
  12573.         a$ = a$ + "  series will be ignored.                                           "%@NL@%
  12574. %@NL@%
  12575.         junk = Alert(4, a$, 8, 7, 17, 75, "", "", "")%@NL@%
  12576.     END IF%@NL@%
  12577. %@NL@%
  12578. %@AB@%    ' window control loop%@AE@%%@NL@%
  12579.     finished = FALSE%@NL@%
  12580.     WHILE NOT finished%@NL@%
  12581.         WindowDo currButton, currEditField%@NL@%
  12582. %@NL@%
  12583.         SELECT CASE Dialog(0)%@NL@%
  12584.             CASE 1                                      ' button pressed%@NL@%
  12585.                 currButton = Dialog(1)%@NL@%
  12586.                 SELECT CASE currButton%@NL@%
  12587.                     CASE 1, 2, 3%@NL@%
  12588.                         currRow = Dialog(17)%@NL@%
  12589.                     CASE 4, 5%@NL@%
  12590.                         finished = TRUE%@NL@%
  12591.                 END SELECT%@NL@%
  12592.                 GOSUB UpdateEdit%@NL@%
  12593.             CASE 2                                      ' Edit Field%@NL@%
  12594.                 currEditField = Dialog(2)%@NL@%
  12595.             CASE 6, 11                                  ' enter, down arrow%@NL@%
  12596.                 IF currButton > 3 AND Dialog(0) = 6 THEN%@NL@%
  12597.                     finished = TRUE%@NL@%
  12598.                 ELSE%@NL@%
  12599.                     currRow = currRow + 1%@NL@%
  12600.                     GOSUB UpdateEdit%@NL@%
  12601.                 END IF%@NL@%
  12602.             CASE 7                                      'tab%@NL@%
  12603.                 SELECT CASE currButton%@NL@%
  12604.                     CASE 1:%@NL@%
  12605.                         currButton = 2%@NL@%
  12606.                         currRow = currCat%@NL@%
  12607.                         GOSUB UpdateEdit%@NL@%
  12608.                     CASE 2:%@NL@%
  12609.                         currButton = 3%@NL@%
  12610.                         currRow = currVal%@NL@%
  12611.                         GOSUB UpdateEdit%@NL@%
  12612.                     CASE 3:%@NL@%
  12613.                         currButton = 4%@NL@%
  12614.                         ButtonToggle 4%@NL@%
  12615.                         GOSUB UpdateEdit%@NL@%
  12616.                     CASE 4:%@NL@%
  12617.                         currButton = 5%@NL@%
  12618.                         ButtonToggle 4%@NL@%
  12619.                         ButtonToggle 5%@NL@%
  12620.                     CASE 5:%@NL@%
  12621.                         currButton = 1%@NL@%
  12622.                         currRow = currSet%@NL@%
  12623.                         ButtonToggle 5%@NL@%
  12624.                         GOSUB UpdateEdit%@NL@%
  12625.                 END SELECT%@NL@%
  12626.             CASE 8                                      'back tab%@NL@%
  12627.                 SELECT CASE currButton%@NL@%
  12628.                     CASE 1:%@NL@%
  12629.                         currButton = 5%@NL@%
  12630.                         ButtonToggle 5%@NL@%
  12631.                         GOSUB UpdateEdit%@NL@%
  12632.                     CASE 2:%@NL@%
  12633.                         currButton = 1%@NL@%
  12634.                         currRow = currSet%@NL@%
  12635.                         GOSUB UpdateEdit%@NL@%
  12636.                     CASE 3:%@NL@%
  12637.                         currButton = 2%@NL@%
  12638.                         currRow = currCat%@NL@%
  12639.                         GOSUB UpdateEdit%@NL@%
  12640.                     CASE 4:%@NL@%
  12641.                         currButton = 3%@NL@%
  12642.                         currRow = currVal%@NL@%
  12643.                         ButtonToggle 4%@NL@%
  12644.                         GOSUB UpdateEdit%@NL@%
  12645.                     CASE 5:%@NL@%
  12646.                         currButton = 4%@NL@%
  12647.                         ButtonToggle 5%@NL@%
  12648.                         ButtonToggle 4%@NL@%
  12649.                 END SELECT%@NL@%
  12650.             CASE 9                                      'escape%@NL@%
  12651.                 currButton = 5%@NL@%
  12652.                 finished = TRUE%@NL@%
  12653.             CASE 10:                                    'up arrow%@NL@%
  12654.                 IF currButton < 4 THEN%@NL@%
  12655.                     currRow = currRow - 1%@NL@%
  12656.                     GOSUB UpdateEdit%@NL@%
  12657.                 END IF%@NL@%
  12658.             CASE 14                                     'space%@NL@%
  12659.                 IF currButton > 3 THEN finished = TRUE%@NL@%
  12660.         END SELECT%@NL@%
  12661. %@NL@%
  12662. %@AB@%        ' give delete warning before exit%@AE@%%@NL@%
  12663.         IF finished = TRUE AND currButton = 4 THEN%@NL@%
  12664.             temp = FALSE%@NL@%
  12665.             FOR i = 1 TO tsetNum%@NL@%
  12666.                 IF tsetName$(i) = "" AND tsetLen(i) > 0 AND NOT (tsetLen(i) = 1 AND tsetVal$(1, i) = "") THEN temp = TRUE%@NL@%
  12667.             NEXT i%@NL@%
  12668.             IF temp = TRUE THEN%@NL@%
  12669.                 a$ = "|"%@NL@%
  12670.                 a$ = a$ + "Series without names will be deleted upon exit."%@NL@%
  12671.                 reply = Alert(4, a$, 8, 10, 12, 70, "OK", "Cancel", "")%@NL@%
  12672.                 IF reply <> 1 THEN finished = FALSE%@NL@%
  12673.             END IF%@NL@%
  12674.         END IF%@NL@%
  12675.     WEND%@NL@%
  12676. %@NL@%
  12677. %@AB@%    ' finished so save new data%@AE@%%@NL@%
  12678.     IF currButton = 4 THEN%@NL@%
  12679.         ClearData                                       ' clear existing data%@NL@%
  12680. %@NL@%
  12681. %@AB@%        ' copy temporary values to permanent locations%@AE@%%@NL@%
  12682.         indx = 0%@NL@%
  12683.         FOR i = 1 TO tsetNum%@NL@%
  12684.             IF tsetName$(i) <> "" THEN%@NL@%
  12685.                 indx = indx + 1%@NL@%
  12686.                 setName$(indx) = tsetName$(i)              ' store set names%@NL@%
  12687.                 indx2 = 0%@NL@%
  12688.                 FOR j = 1 TO tsetLen(i)%@NL@%
  12689.                     IF tsetVal$(j, i) <> "" THEN%@NL@%
  12690.                         indx2 = indx2 + 1%@NL@%
  12691.                         setVal!(indx2, i) = VAL(tsetVal$(j, i))   ' store set values%@NL@%
  12692.                     END IF%@NL@%
  12693.                 NEXT j%@NL@%
  12694.                 setLen(indx) = indx2                     ' get set lengths%@NL@%
  12695.             END IF%@NL@%
  12696.         NEXT i%@NL@%
  12697.         setNum = indx%@NL@%
  12698. %@NL@%
  12699. %@AB@%        ' clear leftover names and set lengths%@AE@%%@NL@%
  12700.         FOR i = setNum + 1 TO cMaxSets%@NL@%
  12701.             setName$(i) = ""%@NL@%
  12702.             setLen(i) = 0%@NL@%
  12703.         NEXT i%@NL@%
  12704. %@NL@%
  12705. %@AB@%        ' store category names%@AE@%%@NL@%
  12706.         FOR i = 1 TO tcatLen%@NL@%
  12707.             Cat$(i) = tCat$(i)%@NL@%
  12708.         NEXT i%@NL@%
  12709.         catLen = tcatLen%@NL@%
  12710. %@NL@%
  12711.         FOR i = tcatLen TO 1 STEP -1%@NL@%
  12712.             IF Cat$(i) = "" THEN%@NL@%
  12713.                 catLen = catLen - 1%@NL@%
  12714.                 IF catLen <= 0 THEN EXIT FOR%@NL@%
  12715.             ELSE%@NL@%
  12716.                 EXIT FOR%@NL@%
  12717.             END IF%@NL@%
  12718.         NEXT i%@NL@%
  12719. %@NL@%
  12720. %@AB@%        ' clear leftover category names%@AE@%%@NL@%
  12721.         FOR i = catLen + 1 TO cMaxValues%@NL@%
  12722.             Cat$(i) = ""%@NL@%
  12723.         NEXT i%@NL@%
  12724. %@NL@%
  12725. %@AB@%        ' update active menu titles based on current data%@AE@%%@NL@%
  12726.         IF setNum > 0 THEN%@NL@%
  12727.             MenuSetState VIEWTITLE, 2, 1%@NL@%
  12728.             chartChanged = TRUE%@NL@%
  12729.         ELSE%@NL@%
  12730.             MenuSetState VIEWTITLE, 2, 0%@NL@%
  12731.         END IF%@NL@%
  12732.     END IF%@NL@%
  12733.     WindowClose 1%@NL@%
  12734. %@NL@%
  12735. %@NL@%
  12736.     EXIT SUB%@NL@%
  12737. %@NL@%
  12738. ViewDatError:%@NL@%
  12739.     PrintError "BASIC error #" + LTRIM$(STR$(ERR)) + " occurred."%@NL@%
  12740. RESUME NEXT%@NL@%
  12741. %@NL@%
  12742. %@AB@%' redraws the value edit column so it displays the current set's values%@AE@%%@NL@%
  12743. ResetVal:%@NL@%
  12744. %@AB@%    ' display new values%@AE@%%@NL@%
  12745.     FOR i = 1 TO cMaxValues%@NL@%
  12746.         WindowLocate i + 2, 55%@NL@%
  12747.         WindowPrint 2, tsetVal$(i, currSet) + STRING$(10 - LEN(tsetVal$(i, currSet)), " ")%@NL@%
  12748.     NEXT i%@NL@%
  12749. %@NL@%
  12750.     IF tsetLen(currSet) = 0 THEN%@NL@%
  12751.         tsetLen(currSet) = tsetLen(currSet) + 1%@NL@%
  12752.     ELSEIF tsetLen(currSet) < cMaxValues AND tsetVal$(tsetLen(currSet), currSet) <> "" THEN%@NL@%
  12753.         tsetLen(currSet) = tsetLen(currSet) + 1%@NL@%
  12754.     END IF%@NL@%
  12755. %@NL@%
  12756.     currVal = 31%@NL@%
  12757. %@NL@%
  12758. RETURN%@NL@%
  12759. %@NL@%
  12760. UpdateEdit:%@NL@%
  12761.     IF prevButton < 4 THEN GOSUB ClosePrevEdit%@NL@%
  12762. %@NL@%
  12763.     SELECT CASE currButton%@NL@%
  12764.         CASE 1:%@NL@%
  12765.             IF currRow <= 0 THEN%@NL@%
  12766.                 currRow = tsetNum%@NL@%
  12767.             ELSEIF currRow > 15 THEN%@NL@%
  12768.                 currRow = 1%@NL@%
  12769.             ELSEIF currRow = tsetNum + 1 AND tsetName$(tsetNum) <> "" THEN%@NL@%
  12770.                 tsetNum = tsetNum + 1%@NL@%
  12771.             ELSEIF currRow > tsetNum THEN%@NL@%
  12772.                 currRow = 1%@NL@%
  12773.             END IF%@NL@%
  12774.             WindowColor 0, 7%@NL@%
  12775.             WindowLocate currSet + 2, 7%@NL@%
  12776.             WindowPrint 2, tsetName$(currSet) + STRING$(17 - LEN(tsetName$(currSet)), " ")%@NL@%
  12777. %@NL@%
  12778.             FG = 7%@NL@%
  12779.             BG = 0%@NL@%
  12780.             vislen = 17%@NL@%
  12781.             totlen = 16%@NL@%
  12782.             currSet = currRow%@NL@%
  12783.             currCol = 7%@NL@%
  12784.             temp$ = tsetName$(currSet)%@NL@%
  12785.             IF prevButton = 1 THEN GOSUB ResetVal%@NL@%
  12786.         CASE 2:%@NL@%
  12787.             IF currRow <= 0 THEN%@NL@%
  12788.                 currRow = tcatLen%@NL@%
  12789.             ELSEIF currRow > 15 THEN%@NL@%
  12790.                 currRow = 1%@NL@%
  12791.             ELSEIF currRow > tcatLen THEN%@NL@%
  12792.                 tcatLen = currRow%@NL@%
  12793.             END IF%@NL@%
  12794.             FG = 0%@NL@%
  12795.             BG = 7%@NL@%
  12796.             vislen = 17%@NL@%
  12797.             totlen = 16%@NL@%
  12798.             currCat = currRow%@NL@%
  12799.             currCol = 31%@NL@%
  12800.             temp$ = tCat$(currCat)%@NL@%
  12801.         CASE 3:%@NL@%
  12802.             IF currRow <= 0 THEN%@NL@%
  12803.                 currRow = tsetLen(currSet)%@NL@%
  12804.             ELSEIF currRow > 15 THEN%@NL@%
  12805.                 currRow = 1%@NL@%
  12806.             ELSEIF currRow = tsetLen(currSet) + 1 AND tsetVal$(tsetLen(currSet), currSet) <> "" AND currRow THEN%@NL@%
  12807.                 tsetLen(currSet) = tsetLen(currSet) + 1%@NL@%
  12808.             ELSEIF currRow > tsetLen(currSet) THEN%@NL@%
  12809.                 currRow = 1%@NL@%
  12810.             END IF%@NL@%
  12811.             FG = 0%@NL@%
  12812.             BG = 7%@NL@%
  12813.             vislen = 11%@NL@%
  12814.             totlen = 20%@NL@%
  12815.             currVal = currRow%@NL@%
  12816.             currCol = 55%@NL@%
  12817.             temp$ = tsetVal$(currVal, currSet)%@NL@%
  12818.         CASE ELSE%@NL@%
  12819.             prevButton = currButton%@NL@%
  12820.             RETURN%@NL@%
  12821.     END SELECT%@NL@%
  12822. %@NL@%
  12823.     EditFieldOpen 1, temp$, currRow + 2, currCol, FG, BG, vislen, totlen%@NL@%
  12824.     currEditField = 1%@NL@%
  12825.     prevButton = currButton%@NL@%
  12826. RETURN%@NL@%
  12827. %@NL@%
  12828. ClosePrevEdit:%@NL@%
  12829.     temp$ = RTRIM$(EditFieldInquire$(1))%@NL@%
  12830.     EditFieldClose 1%@NL@%
  12831.     currEditField = 0%@NL@%
  12832.     IF prevButton = 1 THEN%@NL@%
  12833.         WindowColor 7, 0%@NL@%
  12834.     ELSE%@NL@%
  12835.         WindowColor 0, 7%@NL@%
  12836.     END IF%@NL@%
  12837. %@NL@%
  12838.     SELECT CASE prevButton%@NL@%
  12839.         CASE 1:%@NL@%
  12840.             tsetName$(currSet) = temp$%@NL@%
  12841.             temp$ = temp$ + STRING$(17 - LEN(temp$), " ")%@NL@%
  12842.             editRow = currSet + 2%@NL@%
  12843.             editCol = 7%@NL@%
  12844.         CASE 2:%@NL@%
  12845.             tCat$(currCat) = temp$%@NL@%
  12846.             editRow = currCat + 2%@NL@%
  12847.             editCol = 31%@NL@%
  12848.         CASE 3:%@NL@%
  12849.             tsetVal$(currVal, currSet) = temp$%@NL@%
  12850.             tval# = VAL(temp$)%@NL@%
  12851.             IF tval# = 0 AND temp$ <> "0" AND LEN(RTRIM$(temp$)) <> 0 THEN%@NL@%
  12852.                 PrintError "Warning: Non-numeric values will default to zero for charting."%@NL@%
  12853.             END IF%@NL@%
  12854.             temp$ = MID$(temp$, 1, 10)%@NL@%
  12855.             editRow = currVal + 2%@NL@%
  12856.             editCol = 55%@NL@%
  12857.     END SELECT%@NL@%
  12858. %@NL@%
  12859.     WindowLocate editRow, editCol%@NL@%
  12860.     WindowPrint 2, temp$%@NL@%
  12861.     WindowColor 0, 7%@NL@%
  12862. RETURN%@NL@%
  12863. %@NL@%
  12864. END SUB%@NL@%
  12865. %@NL@%
  12866. %@NL@%
  12867. %@NL@%
  12868. %@2@%%@AH@%COLORS.BAS%@AE@%%@EH@%%@NL@%
  12869. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\COLORS.BAS%@AE@%%@NL@%
  12870. %@NL@%
  12871. SCREEN 1%@NL@%
  12872. %@NL@%
  12873. Esc$ = CHR$(27)%@NL@%
  12874. %@AB@%' Draw three boxes and paint the interior%@AE@%%@NL@%
  12875. %@AB@%' of each box with a different color:%@AE@%%@NL@%
  12876. FOR ColorVal = 1 TO 3%@NL@%
  12877.    LINE (X, Y) -STEP(60, 50), ColorVal, BF%@NL@%
  12878.    X = X + 61%@NL@%
  12879.    Y = Y + 51%@NL@%
  12880. NEXT ColorVal%@NL@%
  12881. %@NL@%
  12882. LOCATE 21, 1%@NL@%
  12883. PRINT "Press ESC to end."%@NL@%
  12884. PRINT "Press any other key to continue."%@NL@%
  12885. %@NL@%
  12886. %@AB@%' Restrict additional printed output to the 23rd line:%@AE@%%@NL@%
  12887. VIEW PRINT 23 TO 23%@NL@%
  12888. DO%@NL@%
  12889.    PaletteVal = 1%@NL@%
  12890.    DO%@NL@%
  12891. %@NL@%
  12892. %@AB@%      ' PaletteVal is either 1 or 0:%@AE@%%@NL@%
  12893.       PaletteVal = 1 - PaletteVal%@NL@%
  12894. %@NL@%
  12895. %@AB@%      ' Set the background color and choose the palette:%@AE@%%@NL@%
  12896.       COLOR BackGroundVal, PaletteVal%@NL@%
  12897.       PRINT "Background ="; BackGroundVal;%@NL@%
  12898.       PRINT "Palette ="; PaletteVal;%@NL@%
  12899. %@NL@%
  12900.       Pause$ = INPUT$(1)        ' Wait for a keystroke.%@NL@%
  12901.       PRINT%@NL@%
  12902. %@AB@%   ' Exit the loop if both palettes have been shown,%@AE@%%@NL@%
  12903. %@AB@%   ' or if the user pressed the ESC key:%@AE@%%@NL@%
  12904.    LOOP UNTIL PaletteVal = 1 OR Pause$ = Esc$%@NL@%
  12905. %@NL@%
  12906.    BackGroundVal = BackGroundVal + 1%@NL@%
  12907. %@NL@%
  12908. %@AB@%' Exit this loop if all 16 background colors have%@AE@%%@NL@%
  12909. %@AB@%' been shown, or if the user pressed the ESC key:%@AE@%%@NL@%
  12910. LOOP UNTIL BackGroundVal > 15 OR Pause$ = Esc$%@NL@%
  12911. %@NL@%
  12912. SCREEN 0                     ' Restore text mode and%@NL@%
  12913. WIDTH 80                     ' 80-column screen width.%@NL@%
  12914. %@NL@%
  12915. %@NL@%
  12916. %@NL@%
  12917. %@2@%%@AH@%CRLF.BAS%@AE@%%@EH@%%@NL@%
  12918. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\CRLF.BAS%@AE@%%@NL@%
  12919. %@NL@%
  12920. DEFINT A-Z             ' Default variable type is integer.%@NL@%
  12921. %@NL@%
  12922. %@AB@%' The Backup$ FUNCTION makes a backup file with%@AE@%%@NL@%
  12923. %@AB@%' the same base as FileName$ plus a .BAK extension:%@AE@%%@NL@%
  12924. DECLARE FUNCTION Backup$ (FileName$)%@NL@%
  12925. %@NL@%
  12926. %@AB@%' Initialize symbolic constants and variables:%@AE@%%@NL@%
  12927. CONST FALSE = 0, TRUE = NOT FALSE%@NL@%
  12928. %@NL@%
  12929. CarReturn$ = CHR$(13)%@NL@%
  12930. LineFeed$ = CHR$(10)%@NL@%
  12931. %@NL@%
  12932. DO%@NL@%
  12933.    CLS%@NL@%
  12934. %@NL@%
  12935. %@AB@%   ' Input the name of the file to change:%@AE@%%@NL@%
  12936.    INPUT "Which file do you want to convert"; OutFile$%@NL@%
  12937. %@NL@%
  12938.    InFile$ = Backup$(OutFile$)  ' Get backup file's name.%@NL@%
  12939. %@NL@%
  12940.    ON ERROR GOTO ErrorHandler   ' Turn on error trapping.%@NL@%
  12941. %@NL@%
  12942.    NAME OutFile$ AS InFile$     ' Rename input file as%@NL@%
  12943. %@AB@%                                ' backup file.%@AE@%%@NL@%
  12944. %@NL@%
  12945.    ON ERROR GOTO 0              ' Turn off error trapping.%@NL@%
  12946. %@NL@%
  12947. %@AB@%   ' Open backup file for input and old file for output:%@AE@%%@NL@%
  12948.    OPEN InFile$ FOR INPUT AS #1%@NL@%
  12949.    OPEN OutFile$ FOR OUTPUT AS #2%@NL@%
  12950. %@NL@%
  12951. %@AB@%   ' The PrevCarReturn variable is a flag set to TRUE%@AE@%%@NL@%
  12952. %@AB@%   ' whenever the program reads a carriage-return character:%@AE@%%@NL@%
  12953.    PrevCarReturn = FALSE%@NL@%
  12954. %@AB@%' Read from input file until reaching end of file:%@AE@%%@NL@%
  12955.    DO UNTIL EOF(1)%@NL@%
  12956. %@NL@%
  12957. %@AB@%      ' This is not end of file, so read a character:%@AE@%%@NL@%
  12958.       FileChar$ = INPUT$(1, #1)%@NL@%
  12959. %@NL@%
  12960.       SELECT CASE FileChar$%@NL@%
  12961. %@NL@%
  12962.          CASE CarReturn$        ' The character is a CR.%@NL@%
  12963. %@NL@%
  12964. %@AB@%            ' If the previous character was also a%@AE@%%@NL@%
  12965. %@AB@%            ' CR, put a LF before the character:%@AE@%%@NL@%
  12966.             IF PrevCarReturn THEN%@NL@%
  12967.                 FileChar$ = LineFeed$ + FileChar$%@NL@%
  12968.             END IF%@NL@%
  12969. %@NL@%
  12970. %@AB@%            ' In any case, set the PrevCarReturn%@AE@%%@NL@%
  12971. %@AB@%            ' variable to TRUE:%@AE@%%@NL@%
  12972.             PrevCarReturn = TRUE%@NL@%
  12973. %@NL@%
  12974.          CASE LineFeed$         ' The character is a LF.%@NL@%
  12975. %@NL@%
  12976. %@AB@%            ' If the previous character was not a%@AE@%%@NL@%
  12977. %@AB@%            ' CR, put a CR before the character:%@AE@%%@NL@%
  12978.             IF NOT PrevCarReturn THEN%@NL@%
  12979.                 FileChar$ = CarReturn$ + FileChar$%@NL@%
  12980.             END IF%@NL@%
  12981. %@NL@%
  12982. %@AB@%            ' Set the PrevCarReturn variable to FALSE:%@AE@%%@NL@%
  12983.             PrevCarReturn = FALSE%@NL@%
  12984. %@NL@%
  12985.          CASE ELSE              ' Neither a CR nor a LF.%@NL@%
  12986. %@NL@%
  12987. %@AB@%            ' If the previous character was a CR,%@AE@%%@NL@%
  12988. %@AB@%            ' set the PrevCarReturn variable to FALSE%@AE@%%@NL@%
  12989. %@AB@%            ' and put a LF before the current character:%@AE@%%@NL@%
  12990.             IF PrevCarReturn THEN%@NL@%
  12991.                PrevCarReturn = FALSE%@NL@%
  12992.                FileChar$ = LineFeed$ + FileChar$%@NL@%
  12993.             END IF%@NL@%
  12994. %@NL@%
  12995.       END SELECT%@NL@%
  12996. %@NL@%
  12997. %@AB@%      ' Write the character(s) to the new file:%@AE@%%@NL@%
  12998.       PRINT #2, FileChar$;%@NL@%
  12999.    LOOP%@NL@%
  13000. %@NL@%
  13001. %@AB@%   ' Write a LF if the last character in the file was a CR:%@AE@%%@NL@%
  13002.    IF PrevCarReturn THEN PRINT #2, LineFeed$;%@NL@%
  13003. CLOSE                        ' Close both files.%@NL@%
  13004.    PRINT "Another file (Y/N)?"  ' Prompt to continue.%@NL@%
  13005. %@NL@%
  13006. %@AB@%   ' Change the input to uppercase (capital letter):%@AE@%%@NL@%
  13007.    More$ = UCASE$(INPUT$(1))%@NL@%
  13008. %@NL@%
  13009. %@AB@%' Continue the program if the user entered a "Y" or a "Y":%@AE@%%@NL@%
  13010. LOOP WHILE More$ = "Y"%@NL@%
  13011. END%@NL@%
  13012. %@NL@%
  13013. ErrorHandler:           ' Error-handling routine%@NL@%
  13014.    CONST NOFILE = 53, FILEEXISTS = 58%@NL@%
  13015. %@NL@%
  13016. %@AB@%   ' The ERR function returns the error code for last error:%@AE@%%@NL@%
  13017.    SELECT CASE ERR%@NL@%
  13018.       CASE NOFILE       ' Program couldn't find file%@NL@%
  13019. %@AB@%                        ' with input name.%@AE@%%@NL@%
  13020. %@NL@%
  13021.          PRINT "No such file in current directory."%@NL@%
  13022.          INPUT "Enter new name: ", OutFile$%@NL@%
  13023.          InFile$ = Backup$(OutFile$)%@NL@%
  13024.          RESUME%@NL@%
  13025.       CASE FILEEXISTS   ' There is already a file named%@NL@%
  13026. %@AB@%                        ' <filename>.BAK in this directory:%@AE@%%@NL@%
  13027. %@AB@%                        ' remove it, then continue.%@AE@%%@NL@%
  13028.          KILL InFile$%@NL@%
  13029.          RESUME%@NL@%
  13030.       CASE ELSE         ' An unanticipated error occurred:%@NL@%
  13031. %@AB@%                        ' stop the program.%@AE@%%@NL@%
  13032.          ON ERROR GOTO 0%@NL@%
  13033.    END SELECT%@NL@%
  13034. %@NL@%
  13035. %@AB@%' ======================== BACKUP$ =========================%@AE@%%@NL@%
  13036. %@AB@%'   This procedure returns a file name that consists of the%@AE@%%@NL@%
  13037. %@AB@%'   base name of the input file (everything before the ".")%@AE@%%@NL@%
  13038. %@AB@%'   plus the extension ".BAK"%@AE@%%@NL@%
  13039. %@AB@%' ==========================================================%@AE@%%@NL@%
  13040. %@NL@%
  13041. FUNCTION Backup$ (FileName$) STATIC%@NL@%
  13042. %@NL@%
  13043. %@AB@%   ' Look for a period:%@AE@%%@NL@%
  13044.    Extension = INSTR(FileName$, ".")%@NL@%
  13045. %@NL@%
  13046. %@AB@%   ' If there is a period, add .BAK to the base:%@AE@%%@NL@%
  13047.    IF Extension > 0 THEN%@NL@%
  13048.       Backup$ = LEFT$(FileName$, Extension - 1) + ".BAK"%@NL@%
  13049. %@AB@%   ' Otherwise, add .BAK to the whole name:%@AE@%%@NL@%
  13050.    ELSE%@NL@%
  13051.       Backup$ = FileName$ + ".BAK"%@NL@%
  13052.    END IF%@NL@%
  13053. END FUNCTION%@NL@%
  13054. %@NL@%
  13055. %@NL@%
  13056. %@NL@%
  13057. %@2@%%@AH@%CUBE.BAS%@AE@%%@EH@%%@NL@%
  13058. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\CUBE.BAS%@AE@%%@NL@%
  13059. %@NL@%
  13060. %@AB@%' Define the macro string used to draw the cube%@AE@%%@NL@%
  13061. %@AB@%' and paint its sides:%@AE@%%@NL@%
  13062. One$ =        "BR30 BU25 C1 R54 U45 L54 D45 BE20 P1,1        G20 C2 G20"%@NL@%
  13063. Two$ =        "R54 E20 L54 BD5 P2,2 U5 C4 G20 U45 E20 D45 BL5 P4,4"%@NL@%
  13064. Plot$ = One$ + Two$%@NL@%
  13065. %@NL@%
  13066. APage% = 1        ' Initialize values for the active and visual%@NL@%
  13067. VPage% = 0        ' pages as well as the angle of rotation.%@NL@%
  13068. Angle% = 0%@NL@%
  13069. %@NL@%
  13070. DO%@NL@%
  13071.    SCREEN 7, , APage%, VPage% ' Draw to the active page%@NL@%
  13072. %@AB@%                                 ' while showing the visual page.%@AE@%%@NL@%
  13073. %@NL@%
  13074.    CLS 1                      ' Clear the active page.%@NL@%
  13075. %@NL@%
  13076. %@AB@%   ' Rotate the        cube "Angle%" degrees:%@AE@%%@NL@%
  13077.    DRAW        "TA" + STR$(Angle%) + Plot$%@NL@%
  13078. %@NL@%
  13079. %@AB@%   ' Angle% is some multiple of        15 degrees:%@AE@%%@NL@%
  13080.    Angle% = (Angle% + 15) MOD 360%@NL@%
  13081. %@NL@%
  13082. %@AB@%   ' Drawing is complete, so make the cube visible in its%@AE@%%@NL@%
  13083. %@AB@%   ' new position by switching the active and visual pages:%@AE@%%@NL@%
  13084.    SWAP        APage%,        VPage%%@NL@%
  13085. %@NL@%
  13086. LOOP WHILE INKEY$ = ""              ' A keystroke ends the program.%@NL@%
  13087. %@NL@%
  13088. END%@NL@%
  13089. %@NL@%
  13090. %@NL@%
  13091. %@NL@%
  13092. %@2@%%@AH@%EDPAT.BAS%@AE@%%@EH@%%@NL@%
  13093. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\EDPAT.BAS%@AE@%%@NL@%
  13094. %@NL@%
  13095. DECLARE SUB DrawPattern ()%@NL@%
  13096. DECLARE SUB EditPattern ()%@NL@%
  13097. DECLARE SUB Initialize ()%@NL@%
  13098. DECLARE SUB ShowPattern (OK$)%@NL@%
  13099. %@NL@%
  13100. DIM Bit%(0 TO 7), Pattern$, PatternSize%%@NL@%
  13101. DO%@NL@%
  13102.    Initialize%@NL@%
  13103.    EditPattern%@NL@%
  13104.    ShowPattern OK$%@NL@%
  13105. LOOP WHILE OK$ = "Y"%@NL@%
  13106. %@NL@%
  13107. END%@NL@%
  13108. %@AB@%' ======================= DRAWPATTERN ====================%@AE@%%@NL@%
  13109. %@AB@%'  Draws a patterned rectangle on the right side of screen%@AE@%%@NL@%
  13110. %@AB@%' ========================================================%@AE@%%@NL@%
  13111. %@NL@%
  13112. %@AB@%' ======================= EDITPATTERN =====================%@AE@%%@NL@%
  13113. %@AB@%'                  Edits a tile-byte pattern%@AE@%%@NL@%
  13114. %@AB@%' =========================================================%@AE@%%@NL@%
  13115. %@NL@%
  13116. %@NL@%
  13117. %@AB@%' ======================= INITIALIZE ======================%@AE@%%@NL@%
  13118. %@AB@%'             Sets up starting pattern and screen%@AE@%%@NL@%
  13119. %@AB@%' =========================================================%@AE@%%@NL@%
  13120. %@NL@%
  13121. %@AB@%' ======================== SHOWPATTERN ====================%@AE@%%@NL@%
  13122. %@AB@%'   Prints the CHR$ values used by PAINT to make pattern%@AE@%%@NL@%
  13123. %@AB@%' =========================================================%@AE@%%@NL@%
  13124. %@NL@%
  13125. SUB DrawPattern STATIC%@NL@%
  13126. SHARED Pattern$%@NL@%
  13127.    VIEW (320, 24)-(622, 160), 0, 1  ' Set view to rectangle.%@NL@%
  13128.    PAINT (1, 1), Pattern$       ' Use PAINT to fill it.%@NL@%
  13129.    VIEW                 ' Set view to full screen.%@NL@%
  13130. %@NL@%
  13131. END SUB%@NL@%
  13132. %@NL@%
  13133. SUB EditPattern STATIC%@NL@%
  13134. SHARED Pattern$, Bit%(), PatternSize%%@NL@%
  13135. %@NL@%
  13136.    ByteNum% = 1     ' Starting position.%@NL@%
  13137.    BitNum% = 7%@NL@%
  13138.    Null$ = CHR$(0)  ' CHR$(0) is the first byte of the%@NL@%
  13139. %@AB@%                                        ' two-byte string returned when a%@AE@%%@NL@%
  13140. %@AB@%                                        ' direction key such as UP or DOWN is%@AE@%%@NL@%
  13141. %@AB@%                                        ' pressed.%@AE@%%@NL@%
  13142.    DO%@NL@%
  13143. %@NL@%
  13144. %@AB@%          ' Calculate starting location on screen of this bit:%@AE@%%@NL@%
  13145.           X% = ((7 - BitNum%) * 16) + 80%@NL@%
  13146.           Y% = (ByteNum% + 2) * 8%@NL@%
  13147. %@NL@%
  13148. %@AB@%          ' Wait for a key press (flash cursor each 3/10 second):%@AE@%%@NL@%
  13149.           State% = 0%@NL@%
  13150.           RefTime = 0%@NL@%
  13151.           DO%@NL@%
  13152. %@NL@%
  13153. %@AB@%         ' Check timer and switch cursor state if 3/10 second:%@AE@%%@NL@%
  13154.          IF ABS(TIMER - RefTime) > .3 THEN%@NL@%
  13155.                 RefTime = TIMER%@NL@%
  13156.                 State% = 1 - State%%@NL@%
  13157. %@NL@%
  13158. %@AB@%                ' Turn the  border of bit on and off:%@AE@%%@NL@%
  13159.                 LINE (X% - 1, Y% - 1)-STEP(15, 8), State%, B%@NL@%
  13160.          END IF%@NL@%
  13161. %@NL@%
  13162.          Check$ = INKEY$    ' Check for keystroke.%@NL@%
  13163. %@NL@%
  13164.           LOOP WHILE Check$ = ""    ' Loop until a key is pressed.%@NL@%
  13165. %@NL@%
  13166. %@AB@%          ' Erase cursor:%@AE@%%@NL@%
  13167.           LINE (X% - 1, Y% - 1)-STEP(15, 8), 0, B%@NL@%
  13168. %@NL@%
  13169.           SELECT CASE Check$    ' Respond to keystroke.%@NL@%
  13170. %@NL@%
  13171.           CASE CHR$(27)     ' ESC key pressed:%@NL@%
  13172.                  EXIT SUB       ' exit this subprogram.%@NL@%
  13173.           CASE CHR$(32)     ' SPACEBAR pressed:%@NL@%
  13174. %@AB@%                                                ' reset state of bit.%@AE@%%@NL@%
  13175. %@NL@%
  13176. %@AB@%                 ' Invert bit in pattern string:%@AE@%%@NL@%
  13177.                  CurrentByte% = ASC(MID$(Pattern$, ByteNum%, 1))%@NL@%
  13178.                  CurrentByte% = CurrentByte% XOR Bit%(BitNum%)%@NL@%
  13179.                  MID$(Pattern$, ByteNum%) = CHR$(CurrentByte%)%@NL@%
  13180. %@NL@%
  13181. %@AB@%                 ' Redraw bit on screen:%@AE@%%@NL@%
  13182.                  IF (CurrentByte% AND Bit%(BitNum%)) <> 0 THEN%@NL@%
  13183.                          CurrentColor% = 1%@NL@%
  13184.                  ELSE%@NL@%
  13185.                          CurrentColor% = 0%@NL@%
  13186.                  END IF%@NL@%
  13187.                  LINE (X% + 1, Y% + 1)-STEP(11, 4), CurrentColor%, BF%@NL@%
  13188. %@NL@%
  13189.           CASE CHR$(13)      ' ENTER key pressed: draw%@NL@%
  13190.                  DrawPattern         ' pattern in box on right.%@NL@%
  13191. %@NL@%
  13192.           CASE Null$ + CHR$(75)  ' LEFT key: move cursor left.%@NL@%
  13193. %@NL@%
  13194.                  BitNum% = BitNum% + 1%@NL@%
  13195.                  IF BitNum% > 7 THEN BitNum% = 0%@NL@%
  13196. %@NL@%
  13197.           CASE Null$ + CHR$(77)  ' RIGHT key: move cursor right.%@NL@%
  13198. %@NL@%
  13199.                  BitNum% = BitNum% - 1%@NL@%
  13200.                  IF BitNum% < 0 THEN BitNum% = 7%@NL@%
  13201. %@NL@%
  13202.           CASE Null$ + CHR$(72)  ' UP key: move cursor up.%@NL@%
  13203. %@NL@%
  13204.                  ByteNum% = ByteNum% - 1%@NL@%
  13205.                  IF ByteNum% < 1 THEN ByteNum% = PatternSize%%@NL@%
  13206. %@NL@%
  13207.           CASE Null$ + CHR$(80)  ' DOWN key: move cursor down.%@NL@%
  13208. %@NL@%
  13209.                  ByteNum% = ByteNum% + 1%@NL@%
  13210.                  IF ByteNum% > PatternSize% THEN ByteNum% = 1%@NL@%
  13211.           END SELECT%@NL@%
  13212.    LOOP%@NL@%
  13213. END SUB%@NL@%
  13214. %@NL@%
  13215. SUB Initialize STATIC%@NL@%
  13216. SHARED Pattern$, Bit%(), PatternSize%%@NL@%
  13217. %@NL@%
  13218. %@AB@%   ' Set up an array holding bits in positions 0 to 7:%@AE@%%@NL@%
  13219.    FOR I% = 0 TO 7%@NL@%
  13220.           Bit%(I%) = 2 ^ I%%@NL@%
  13221.    NEXT I%%@NL@%
  13222. %@NL@%
  13223.    CLS%@NL@%
  13224. %@NL@%
  13225. %@AB@%   ' Input the pattern size (in number of bytes):%@AE@%%@NL@%
  13226.    LOCATE 5, 5%@NL@%
  13227.    PRINT "Enter pattern size (1-16 rows):";%@NL@%
  13228.    DO%@NL@%
  13229.           LOCATE 5, 38%@NL@%
  13230.           PRINT "         ";%@NL@%
  13231.           LOCATE 5, 38%@NL@%
  13232.           INPUT "", PatternSize%%@NL@%
  13233.    LOOP WHILE PatternSize% < 1 OR PatternSize% > 16%@NL@%
  13234. %@NL@%
  13235. %@AB@%   ' Set initial pattern to all bits set:%@AE@%%@NL@%
  13236.    Pattern$ = STRING$(PatternSize%, 255)%@NL@%
  13237. %@NL@%
  13238.    SCREEN 2     ' 640 x 200 monochrome graphics mode%@NL@%
  13239. %@NL@%
  13240. %@AB@%   ' Draw dividing lines:%@AE@%%@NL@%
  13241.    LINE (0, 10)-(635, 10), 1%@NL@%
  13242.    LINE (300, 0)-(300, 199)%@NL@%
  13243.    LINE (302, 0)-(302, 199)%@NL@%
  13244. %@NL@%
  13245. %@AB@%   ' Print titles:%@AE@%%@NL@%
  13246.    LOCATE 1, 13: PRINT "Pattern Bytes"%@NL@%
  13247.    LOCATE 1, 53: PRINT "Pattern View"%@NL@%
  13248. %@NL@%
  13249. %@NL@%
  13250. %@AB@%' Draw editing screen for pattern:%@AE@%%@NL@%
  13251.    FOR I% = 1 TO PatternSize%%@NL@%
  13252. %@NL@%
  13253. %@AB@%          ' Print label on left of each line:%@AE@%%@NL@%
  13254.           LOCATE I% + 3, 8%@NL@%
  13255.           PRINT USING "##:"; I%%@NL@%
  13256. %@NL@%
  13257. %@AB@%          ' Draw "bit" boxes:%@AE@%%@NL@%
  13258.           X% = 80%@NL@%
  13259.           Y% = (I% + 2) * 8%@NL@%
  13260.           FOR J% = 1 TO 8%@NL@%
  13261.                 LINE (X%, Y%)-STEP(13, 6), 1, BF%@NL@%
  13262.                 X% = X% + 16%@NL@%
  13263.           NEXT J%%@NL@%
  13264.    NEXT I%%@NL@%
  13265. %@NL@%
  13266.    DrawPattern      ' Draw  "Pattern View" box.%@NL@%
  13267. %@NL@%
  13268.    LOCATE 21, 1%@NL@%
  13269.    PRINT "DIRECTION keys........Move cursor"%@NL@%
  13270.    PRINT "SPACEBAR............Changes point"%@NL@%
  13271.    PRINT "ENTER............Displays pattern"%@NL@%
  13272.    PRINT "ESC.........................Quits";%@NL@%
  13273. %@NL@%
  13274. END SUB%@NL@%
  13275. %@NL@%
  13276. SUB ShowPattern (OK$) STATIC%@NL@%
  13277. SHARED Pattern$, PatternSize%%@NL@%
  13278. %@NL@%
  13279. %@AB@%   ' Return screen to 80-column text mode:%@AE@%%@NL@%
  13280.    SCREEN 0, 0%@NL@%
  13281.    WIDTH 80%@NL@%
  13282. %@NL@%
  13283.    PRINT "The following characters make up your pattern:"%@NL@%
  13284.    PRINT%@NL@%
  13285. %@NL@%
  13286. %@AB@%   ' Print out the value for each pattern byte:%@AE@%%@NL@%
  13287.    FOR I% = 1 TO PatternSize%%@NL@%
  13288.           PatternByte% = ASC(MID$(Pattern$, I%, 1))%@NL@%
  13289.           PRINT "CHR$("; LTRIM$(STR$(PatternByte%)); ")"%@NL@%
  13290.    NEXT I%%@NL@%
  13291.    PRINT%@NL@%
  13292.    LOCATE , , 1%@NL@%
  13293.    PRINT "New pattern? ";%@NL@%
  13294.    OK$ = UCASE$(INPUT$(1))%@NL@%
  13295. END SUB%@NL@%
  13296. %@NL@%
  13297. %@NL@%
  13298. %@NL@%
  13299. %@2@%%@AH@%ENTAB.BAS%@AE@%%@EH@%%@NL@%
  13300. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\ENTAB.BAS%@AE@%%@NL@%
  13301. %@NL@%
  13302. %@AB@%' ENTAB.BAS%@AE@%%@NL@%
  13303. %@AB@%'%@AE@%%@NL@%
  13304. %@AB@%' Replace runs of spaces in a file with tabs.%@AE@%%@NL@%
  13305. %@AB@%'%@AE@%%@NL@%
  13306. DECLARE SUB SetTabPos ()%@NL@%
  13307. DECLARE SUB StripCommand (CLine$)%@NL@%
  13308. %@NL@%
  13309. %@NL@%
  13310. DEFINT A-Z%@NL@%
  13311. DECLARE FUNCTION ThisIsATab (Column AS INTEGER)%@NL@%
  13312. %@NL@%
  13313. CONST MAXLINE = 255%@NL@%
  13314. CONST TABSPACE = 8%@NL@%
  13315. CONST NO = 0, YES = NOT NO%@NL@%
  13316. %@NL@%
  13317. DIM SHARED TabStops(MAXLINE) AS INTEGER%@NL@%
  13318. %@NL@%
  13319. StripCommand (COMMAND$)%@NL@%
  13320. %@NL@%
  13321. %@AB@%' Set the tab positions (uses the global array TabStops).%@AE@%%@NL@%
  13322. SetTabPos%@NL@%
  13323. %@NL@%
  13324. LastColumn = 1%@NL@%
  13325. %@NL@%
  13326. DO%@NL@%
  13327. %@NL@%
  13328.    CurrentColumn = LastColumn%@NL@%
  13329. %@NL@%
  13330. %@AB@%' Replace a run of blanks with a tab when you reach a tab%@AE@%%@NL@%
  13331. %@AB@%' column. CurrentColumn is the current column read.%@AE@%%@NL@%
  13332. %@AB@%' LastColumn is the last column that was printed.%@AE@%%@NL@%
  13333.    DO%@NL@%
  13334.       C$ = INPUT$(1,#1)%@NL@%
  13335.       IF C$ <> " " AND C$ <> CHR$(9) THEN EXIT DO%@NL@%
  13336.       CurrentColumn = CurrentColumn + 1%@NL@%
  13337.       IF C$=CHR$(9) OR ThisIsATab(CurrentColumn) THEN%@NL@%
  13338. %@AB@%         ' Go to a tab column if we have a tab and this%@AE@%%@NL@%
  13339. %@AB@%         ' is not a tab column.%@AE@%%@NL@%
  13340.          DO WHILE NOT ThisIsATab(CurrentColumn)%@NL@%
  13341.             CurrentColumn=CurrentColumn+1%@NL@%
  13342.          LOOP%@NL@%
  13343.          PRINT #2, CHR$(9);%@NL@%
  13344.          LastColumn = CurrentColumn%@NL@%
  13345.       END IF%@NL@%
  13346.    LOOP%@NL@%
  13347. %@NL@%
  13348. %@AB@%' Print out any blanks left over.%@AE@%%@NL@%
  13349.    DO WHILE LastColumn < CurrentColumn%@NL@%
  13350.       PRINT #2, " ";%@NL@%
  13351.       LastColumn = LastColumn + 1%@NL@%
  13352.    LOOP%@NL@%
  13353. %@NL@%
  13354. %@AB@%' Print the non-blank character.%@AE@%%@NL@%
  13355.    PRINT #2, C$;%@NL@%
  13356. %@NL@%
  13357. %@AB@%' Reset the column position if this is the end of a line.%@AE@%%@NL@%
  13358.    IF C$ = CHR$(10) THEN%@NL@%
  13359.       LastColumn = 1%@NL@%
  13360.    ELSE%@NL@%
  13361.       LastColumn = LastColumn + 1%@NL@%
  13362.    END IF%@NL@%
  13363. %@NL@%
  13364. LOOP UNTIL EOF(1)%@NL@%
  13365. CLOSE #1, #2%@NL@%
  13366. END%@NL@%
  13367. %@NL@%
  13368. %@AB@%'------------------SUB SetTabPos-------------------------%@AE@%%@NL@%
  13369. %@AB@%' Set the tab positions in the array TabStops.%@AE@%%@NL@%
  13370. %@AB@%'%@AE@%%@NL@%
  13371. SUB SetTabPos STATIC%@NL@%
  13372.    FOR I = 1 TO 255%@NL@%
  13373.       TabStops(I) = ((I MOD TABSPACE) = 1)%@NL@%
  13374.    NEXT I%@NL@%
  13375. END SUB%@NL@%
  13376. %@AB@%'%@AE@%%@NL@%
  13377. %@AB@%'------------------SUB StripCommand----------------------%@AE@%%@NL@%
  13378. %@AB@%'%@AE@%%@NL@%
  13379. SUB StripCommand (CommandLine$) STATIC%@NL@%
  13380.    IF CommandLine$ = "" THEN%@NL@%
  13381.       INPUT "File to entab:   ", InFileName$%@NL@%
  13382.       INPUT "Store entabbed file in:   ", OutFileName$%@NL@%
  13383.    ELSE%@NL@%
  13384.       SpacePos = INSTR(CommandLine$, " ")%@NL@%
  13385.       IF SpacePos > 0 THEN%@NL@%
  13386.          InFileName$ = LEFT$(CommandLine$, SpacePos - 1)%@NL@%
  13387.          OutFileName$ = LTRIM$(MID$(CommandLine$, SpacePos))%@NL@%
  13388.       ELSE%@NL@%
  13389.          InFileName$ = CommandLine$%@NL@%
  13390.          INPUT "Store entabbed file in:   ", OutFileName$%@NL@%
  13391.       END IF%@NL@%
  13392.    END IF%@NL@%
  13393.    OPEN InFileName$ FOR INPUT AS #1%@NL@%
  13394.    OPEN OutFileName$ FOR OUTPUT AS #2%@NL@%
  13395. END SUB%@NL@%
  13396. %@AB@%'---------------FUNCTION ThisIsATab----------------------%@AE@%%@NL@%
  13397. %@AB@%' Answer the question, "Is this a tab position?"%@AE@%%@NL@%
  13398. %@AB@%'%@AE@%%@NL@%
  13399. FUNCTION ThisIsATab (LastColumn AS INTEGER) STATIC%@NL@%
  13400.    IF LastColumn > MAXLINE THEN%@NL@%
  13401.       ThisIsATab = YES%@NL@%
  13402.    ELSE%@NL@%
  13403.       ThisIsATab = TabStops(LastColumn)%@NL@%
  13404.    END IF%@NL@%
  13405. END FUNCTION%@NL@%
  13406. %@NL@%
  13407. %@NL@%
  13408. %@2@%%@AH@%FLPT.BAS%@AE@%%@EH@%%@NL@%
  13409. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\FLPT.BAS%@AE@%%@NL@%
  13410. %@NL@%
  13411. %@AB@%'%@AE@%%@NL@%
  13412. %@AB@%' FLPT.BAS%@AE@%%@NL@%
  13413. %@AB@%'%@AE@%%@NL@%
  13414. %@AB@%' Displays how a given real value is stored in memory.%@AE@%%@NL@%
  13415. %@AB@%'%@AE@%%@NL@%
  13416. %@AB@%'%@AE@%%@NL@%
  13417. DEFINT A-Z%@NL@%
  13418. DECLARE FUNCTION MHex$ (X AS INTEGER)%@NL@%
  13419. DIM Bytes(3)%@NL@%
  13420. %@NL@%
  13421. CLS%@NL@%
  13422. PRINT "Internal format of IEEE number (all values in hexadecimal)"%@NL@%
  13423. PRINT%@NL@%
  13424. DO%@NL@%
  13425. %@NL@%
  13426. %@AB@%   ' Get the value and calculate the address of the variable.%@AE@%%@NL@%
  13427.    INPUT "Enter a real number (or END to quit): ", A$%@NL@%
  13428.    IF UCASE$(A$) = "END" THEN EXIT DO%@NL@%
  13429.    RealValue! = VAL(A$)%@NL@%
  13430. %@AB@%   ' Convert the real value to a long without changing any of%@AE@%%@NL@%
  13431. %@AB@%   ' the bits.%@AE@%%@NL@%
  13432.    AsLong& = CVL(MKS$(RealValue!))%@NL@%
  13433. %@AB@%   ' Make a string of hex digits, and add leading zeroes.%@AE@%%@NL@%
  13434.    Strout$ = HEX$(AsLong&)%@NL@%
  13435.    Strout$ = STRING$(8 - LEN(Strout$), "0") + Strout$%@NL@%
  13436. %@NL@%
  13437. %@AB@%   ' Save the sign bit, and then eliminate it so it doesn't%@AE@%%@NL@%
  13438. %@AB@%   ' affect breaking out the bytes%@AE@%%@NL@%
  13439.    SignBit& = AsLong& AND &H80000000%@NL@%
  13440.    AsLong& = AsLong& AND &H7FFFFFFF%@NL@%
  13441. %@AB@%   ' Split the real value into four separate bytes%@AE@%%@NL@%
  13442. %@AB@%   ' --the AND removes unwanted bits; dividing by 256 shifts%@AE@%%@NL@%
  13443. %@AB@%   ' the value right 8 bit positions.%@AE@%%@NL@%
  13444.    FOR I = 0 TO 3%@NL@%
  13445.       Bytes(I) = AsLong& AND &HFF&%@NL@%
  13446.       AsLong& = AsLong& \ 256&%@NL@%
  13447.    NEXT I%@NL@%
  13448. %@AB@%   ' Display how the value appears in memory.%@AE@%%@NL@%
  13449.    PRINT%@NL@%
  13450.    PRINT "Bytes in Memory"%@NL@%
  13451.    PRINT " High    Low"%@NL@%
  13452.    FOR I = 1 TO 7 STEP 2%@NL@%
  13453.       PRINT " "; MID$(Strout$, I, 2);%@NL@%
  13454.    NEXT I%@NL@%
  13455.    PRINT : PRINT%@NL@%
  13456. %@NL@%
  13457. %@AB@%   ' Set the value displayed for the sign bit.%@AE@%%@NL@%
  13458.    Sign = ABS(SignBit& <> 0)%@NL@%
  13459. %@NL@%
  13460. %@AB@%   ' The exponent is the right seven bits of byte 3 and the%@AE@%%@NL@%
  13461. %@AB@%   ' leftmost bit of byte 2. Multiplying by 2 shifts left and%@AE@%%@NL@%
  13462. %@AB@%   ' makes room for the additional bit from byte 2.%@AE@%%@NL@%
  13463.    Exponent = Bytes(3) * 2 + Bytes(2) \ 128%@NL@%
  13464. %@NL@%
  13465. %@AB@%   ' The first part of the mantissa is the right seven bits%@AE@%%@NL@%
  13466. %@AB@%   ' of byte 2.  The OR operation makes sure the implied bit%@AE@%%@NL@%
  13467. %@AB@%   ' is displayed by setting the leftmost bit.%@AE@%%@NL@%
  13468.    Mant1 = (Bytes(2) OR &H80)%@NL@%
  13469.    PRINT " Bit 31    Bits 30-23  Implied Bit & Bits 22-0"%@NL@%
  13470.    PRINT "Sign Bit  Exponent Bits     Mantissa Bits"%@NL@%
  13471.    PRINT TAB(4); Sign; TAB(17); MHex$(Exponent);%@NL@%
  13472.    PRINT TAB(33); MHex$(Mant1); MHex$(Bytes(1)); MHex$(Bytes(0))%@NL@%
  13473.    PRINT%@NL@%
  13474. %@NL@%
  13475. LOOP%@NL@%
  13476. %@NL@%
  13477. %@AB@%' MHex$ makes sure we always get two hex digits.%@AE@%%@NL@%
  13478. FUNCTION MHex$ (X AS INTEGER) STATIC%@NL@%
  13479.    D$ = HEX$(X)%@NL@%
  13480.    IF LEN(D$) < 2 THEN D$ = "0" + D$%@NL@%
  13481.    MHex$ = D$%@NL@%
  13482. END FUNCTION%@NL@%
  13483. %@NL@%
  13484. %@NL@%
  13485. %@NL@%
  13486. %@2@%%@AH@%FONTASM.ASM%@AE@%%@EH@%%@NL@%
  13487. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\FONTASM.ASM%@AE@%%@NL@%
  13488. %@NL@%
  13489. .MODEL        MEDIUM%@NL@%
  13490. %@AB@%;************************************************************%@AE@%%@NL@%
  13491. %@AB@%; FONTASM.ASM - assembly lang routines for Font Toolbox%@AE@%%@NL@%
  13492. %@AB@%;%@AE@%%@NL@%
  13493. %@AB@%;  Copyright (C) 1989 Microsoft Corporation, All Rights Reserved%@AE@%%@NL@%
  13494. %@AB@%;%@AE@%%@NL@%
  13495. %@AB@%;   fl_SetBltDir    - Sets bltchar direction increments%@AE@%%@NL@%
  13496. %@AB@%;   fl_SetBltColor  - Sets color parameter for bltchar%@AE@%%@NL@%
  13497. %@AB@%;   fl_SetBltParams - Sets font related parameters for bltchar%@AE@%%@NL@%
  13498. %@AB@%;   fl_BltChar            - Character output routine%@AE@%%@NL@%
  13499. %@AB@%;%@AE@%%@NL@%
  13500. %@AB@%;   fl_MovMem            - Moves memory%@AE@%%@NL@%
  13501. %@AB@%;   fl_ansi            - Maps IBM chars to Windows ANSI;%@AE@%%@NL@%
  13502. %@AB@%;%@AE@%%@NL@%
  13503. %@AB@%;************************************************************%@AE@%%@NL@%
  13504. %@NL@%
  13505. %@AB@%; BltChar data block%@AE@%%@NL@%
  13506. .DATA%@NL@%
  13507. %@NL@%
  13508. %@AB@%; These are set by fl_SetBltParams%@AE@%%@NL@%
  13509. HdrLen            dw            0            %@AB@%;length of windows font file header%@AE@%%@NL@%
  13510. CharHeight  dw            0            %@AB@%;character height%@AE@%%@NL@%
  13511. FirstChar   dw            0            %@AB@%;first character defined in font%@AE@%%@NL@%
  13512. LastChar    dw            0            %@AB@%;last character defined in font%@AE@%%@NL@%
  13513. DefaultChar dw            0            %@AB@%;default character to use%@AE@%%@NL@%
  13514. %@NL@%
  13515. %@AB@%; This is set by fl_SetBltColor%@AE@%%@NL@%
  13516. CharColor   dw            0            %@AB@%;current character color%@AE@%%@NL@%
  13517. %@NL@%
  13518. %@AB@%; These are set by fl_SetBltDir%@AE@%%@NL@%
  13519. XPixInc     dw            1            %@AB@%;x inc for each pixel in character bitmap%@AE@%%@NL@%
  13520. YPixInc     dw            0            %@AB@%;y inc for each pixel in character bitmap%@AE@%%@NL@%
  13521. XRowInc     dw            0            %@AB@%;x inc for each row in character bitmap%@AE@%%@NL@%
  13522. YRowInc     dw            1            %@AB@%;y inc for each row in character bitmap%@AE@%%@NL@%
  13523. XColInc     dw            8            %@AB@%;x inc for each column (8 bits) in char bitmap%@AE@%%@NL@%
  13524. YColInc     dw            0            %@AB@%;y inc for each column (8 bits) in char bitmap%@AE@%%@NL@%
  13525. %@NL@%
  13526. .CODE%@NL@%
  13527. %@AB@%;********************************************************************%@AE@%%@NL@%
  13528. %@AB@%; fl_SetBltDir - Sets pixel, row, and column step values for bltchar%@AE@%%@NL@%
  13529. %@AB@%;%@AE@%%@NL@%
  13530. %@AB@%;   BASIC CALL:%@AE@%%@NL@%
  13531. %@AB@%;        fl.SetBltDir XPixInc%, YPixInc%, XRowInc%, YRowInc%%@AE@%%@NL@%
  13532. %@AB@%;%@AE@%%@NL@%
  13533. %@AB@%;   Comments:%@AE@%%@NL@%
  13534. %@AB@%;        When bltchar is blt-ing a bitmap to allow the different%@AE@%%@NL@%
  13535. %@AB@%;        directions to be output it uses preset counter increments%@AE@%%@NL@%
  13536. %@AB@%;        for moving a pixel, to the next row, and to the next column%@AE@%%@NL@%
  13537. %@AB@%;        of the bitmap. The pixel and row increments are input to this%@AE@%%@NL@%
  13538. %@AB@%;        routine. The column increments are calculates as 8 times the%@AE@%%@NL@%
  13539. %@AB@%;        pixel increment.%@AE@%%@NL@%
  13540. %@AB@%;%@AE@%%@NL@%
  13541. %@AB@%;********************************************************************%@AE@%%@NL@%
  13542. %@NL@%
  13543. %@AB@%; Parameters%@AE@%%@NL@%
  13544. pXPixInc    equ     WORD PTR [bp+12]%@NL@%
  13545. pYPixInc    equ     WORD PTR [bp+10]%@NL@%
  13546. pXRowInc    equ     WORD PTR [bp+8]%@NL@%
  13547. pYRowInc    equ     WORD PTR [bp+6]%@NL@%
  13548. %@NL@%
  13549.             PUBLIC  fl_SetBltDir%@NL@%
  13550. fl_SetBltDir PROC%@NL@%
  13551. %@NL@%
  13552.             push    bp                %@AB@%;Entry%@AE@%%@NL@%
  13553.             mov     bp,sp%@NL@%
  13554. %@NL@%
  13555.             mov     ax,pXRowInc %@AB@%;Save input parameters%@AE@%%@NL@%
  13556.             mov     XRowInc,ax%@NL@%
  13557.             mov     ax,pYRowInc%@NL@%
  13558.             mov     YRowInc,ax%@NL@%
  13559. %@NL@%
  13560.             mov     ax,pXPixInc%@NL@%
  13561.             mov     XPixInc,ax%@NL@%
  13562.             mov     cl,3%@NL@%
  13563.             shl     ax,cl%@NL@%
  13564.             mov     XColInc,ax        %@AB@%;Column increment = Pix Inc * 8%@AE@%%@NL@%
  13565. %@NL@%
  13566.             mov     ax,pYPixInc%@NL@%
  13567.             mov     YPixInc,ax%@NL@%
  13568.             mov     cl,3%@NL@%
  13569.             shl     ax,cl%@NL@%
  13570.             mov     YColInc,ax        %@AB@%;Column increment = Pix Inc * 8%@AE@%%@NL@%
  13571. %@NL@%
  13572.             pop     bp                %@AB@%;Exit%@AE@%%@NL@%
  13573.             ret     8%@NL@%
  13574. fl_SetBltDir ENDP%@NL@%
  13575. %@NL@%
  13576. %@AB@%;********************************************************************%@AE@%%@NL@%
  13577. %@AB@%; fl_SetBltColor - Sets the color of blt-ed characters%@AE@%%@NL@%
  13578. %@AB@%;%@AE@%%@NL@%
  13579. %@AB@%;   BASIC CALL:%@AE@%%@NL@%
  13580. %@AB@%;        fl.SetBltColor color%@AE@%%@NL@%
  13581. %@AB@%;%@AE@%%@NL@%
  13582. %@AB@%;********************************************************************%@AE@%%@NL@%
  13583. %@NL@%
  13584. %@AB@%; Parameters%@AE@%%@NL@%
  13585. pColor            EQU     WORD PTR [bp+6]%@NL@%
  13586. %@NL@%
  13587.             PUBLIC  fl_SetBltColor%@NL@%
  13588. fl_SetBltColor PROC%@NL@%
  13589. %@NL@%
  13590.             push    bp                    %@AB@%;Entry%@AE@%%@NL@%
  13591.             mov     bp,sp%@NL@%
  13592. %@NL@%
  13593.             mov     ax,pColor            %@AB@%;Save color in data block%@AE@%%@NL@%
  13594.             mov     CharColor,ax%@NL@%
  13595. %@NL@%
  13596.             pop     bp                    %@AB@%;Exit%@AE@%%@NL@%
  13597.             ret     2%@NL@%
  13598. %@NL@%
  13599. fl_SetBltColor        ENDP%@NL@%
  13600. %@NL@%
  13601. %@AB@%;********************************************************************%@AE@%%@NL@%
  13602. %@AB@%; fl_SetBltParams - Sets font-related params for bltchar%@AE@%%@NL@%
  13603. %@AB@%;%@AE@%%@NL@%
  13604. %@AB@%;   BASIC CALL:%@AE@%%@NL@%
  13605. %@AB@%;        fl.SetBltParams HdrLen%, CharHgt%, FirstChar%, LastChar%, DefChar%%@AE@%%@NL@%
  13606. %@AB@%;%@AE@%%@NL@%
  13607. %@AB@%;********************************************************************%@AE@%%@NL@%
  13608. %@NL@%
  13609. %@AB@%; Parameters%@AE@%%@NL@%
  13610. pHdrLen     equ     WORD PTR [bp+14]%@NL@%
  13611. pCharHgt    equ     WORD PTR [bp+12]%@NL@%
  13612. pFirstChar  equ     WORD PTR [bp+10]%@NL@%
  13613. pLastChar   equ     WORD PTR [bp+8]%@NL@%
  13614. pDefChar    equ     WORD PTR [bp+6]%@NL@%
  13615. %@NL@%
  13616.             PUBLIC  fl_SetBltParams%@NL@%
  13617. fl_SetBltParams PROC%@NL@%
  13618. %@NL@%
  13619.             push    bp                    %@AB@%;Entry%@AE@%%@NL@%
  13620.             mov     bp,sp%@NL@%
  13621. %@NL@%
  13622.             mov     ax,pHdrLen%@NL@%
  13623.             mov     HdrLen,ax%@NL@%
  13624. %@NL@%
  13625.             mov     ax,pCharHgt%@NL@%
  13626.             mov     CharHeight,ax%@NL@%
  13627. %@NL@%
  13628.             mov     ax,pFirstChar%@NL@%
  13629.             mov     FirstChar,ax%@NL@%
  13630. %@NL@%
  13631.             mov     ax,pLastChar%@NL@%
  13632.             mov     LastChar,ax%@NL@%
  13633. %@NL@%
  13634.             mov     ax,pDefChar%@NL@%
  13635.             mov     DefaultChar,ax%@NL@%
  13636. %@NL@%
  13637.             pop     bp                    %@AB@%;Exit%@AE@%%@NL@%
  13638.             ret     10%@NL@%
  13639. %@NL@%
  13640. fl_SetBltParams ENDP%@NL@%
  13641. %@NL@%
  13642. %@AB@%;********************************************************************%@AE@%%@NL@%
  13643. %@AB@%; fl_BltChar - Outputs a character's bitmap to the screen%@AE@%%@NL@%
  13644. %@AB@%;%@AE@%%@NL@%
  13645. %@AB@%;   BASIC CALL:%@AE@%%@NL@%
  13646. %@AB@%;        fl.BltChar FontAddr(far), Char%, X%, Y%%@AE@%%@NL@%
  13647. %@AB@%;%@AE@%%@NL@%
  13648. %@AB@%;********************************************************************%@AE@%%@NL@%
  13649. %@NL@%
  13650. %@AB@%; BASIC Procedures%@AE@%%@NL@%
  13651. EXTRN            B$N1I2:far, B$PSTC:far%@NL@%
  13652. %@NL@%
  13653. %@AB@%; Parameters%@AE@%%@NL@%
  13654. pFASeg            equ     WORD PTR [bp+14]%@NL@%
  13655. pFAOffset   equ     WORD PTR [bp+12]%@NL@%
  13656. pChar            equ     WORD PTR [bp+10]%@NL@%
  13657. pX            equ     WORD PTR [bp+8]%@NL@%
  13658. pY            equ     WORD PTR [bp+6]%@NL@%
  13659. %@NL@%
  13660. %@AB@%; Local Variables%@AE@%%@NL@%
  13661. .RowX            equ     WORD PTR [bp-2]%@NL@%
  13662. .RowY            equ     WORD PTR [bp-4]%@NL@%
  13663. .CharWid    equ     WORD PTR [bp-6]%@NL@%
  13664. .ColWid     equ     WORD PTR [bp-8]%@NL@%
  13665. %@NL@%
  13666.             PUBLIC  fl_BltChar%@NL@%
  13667. fl_BltChar  PROC%@NL@%
  13668. %@NL@%
  13669.             push    bp                    %@AB@%;Entry%@AE@%%@NL@%
  13670.             mov     bp,sp%@NL@%
  13671.             sub     sp,8            %@AB@%;Make room for local variables%@AE@%%@NL@%
  13672.             push    di%@NL@%
  13673.             push    si%@NL@%
  13674. %@NL@%
  13675.             %@AB@%;Normalize font address (make offset as small as possible)%@AE@%%@NL@%
  13676.             mov     ax,pFAOffset%@NL@%
  13677.             mov     bx,pFASeg%@NL@%
  13678.             push    ax%@NL@%
  13679.             mov     cl,4%@NL@%
  13680.             shr     ax,cl            %@AB@%;offset = offset div 16%@AE@%%@NL@%
  13681.             add     bx,ax            %@AB@%;seg = seg + offset%@AE@%%@NL@%
  13682.             pop     ax%@NL@%
  13683.             and     ax,0Fh            %@AB@%;offset = original offset mod 16%@AE@%%@NL@%
  13684.             mov     si,ax%@NL@%
  13685.             mov     es,bx%@NL@%
  13686. %@NL@%
  13687.             %@AB@%;Calculate character number%@AE@%%@NL@%
  13688.             mov     bx,pChar%@NL@%
  13689.             cmp     bx,LastChar%@NL@%
  13690.             ja            usedefchar            %@AB@%;Char is > last char, use default%@AE@%%@NL@%
  13691.             sub     bx,FirstChar%@NL@%
  13692.             jnc     getsize            %@AB@%;Char is > first char, is OK%@AE@%%@NL@%
  13693. usedefchar: mov     bx,DefaultChar%@NL@%
  13694. %@NL@%
  13695.             %@AB@%;Get character width from character table in font%@AE@%%@NL@%
  13696. getsize:    shl     bx,1%@NL@%
  13697.             shl     bx,1            %@AB@%;char = char * 4%@AE@%%@NL@%
  13698.             add     bx,si            %@AB@%;offset into char table%@AE@%%@NL@%
  13699.             mov     cx,es:[bx]            %@AB@%;cx = character width%@AE@%%@NL@%
  13700.             mov     .CharWid,cx%@NL@%
  13701. %@NL@%
  13702.             %@AB@%;Calculate character bitmap address%@AE@%%@NL@%
  13703.             inc     bx                    %@AB@%;move to next two bytes in char table%@AE@%%@NL@%
  13704.             inc     bx%@NL@%
  13705.             mov     cx,es:[bx]%@NL@%
  13706.             add     si,cx            %@AB@%;add bitmap offset into font index%@AE@%%@NL@%
  13707.             sub     si,HdrLen            %@AB@%;subtract length of header%@AE@%%@NL@%
  13708.             dec     si                    %@AB@%;decrement for use in output algorithm%@AE@%%@NL@%
  13709. %@NL@%
  13710.             %@AB@%;Blt character%@AE@%%@NL@%
  13711.             mov     cx,pX            %@AB@%;cx = x coord%@AE@%%@NL@%
  13712.             mov     dx,pY            %@AB@%;dx = y coord%@AE@%%@NL@%
  13713. %@NL@%
  13714.             mov     bx,.CharWid%@NL@%
  13715. %@NL@%
  13716. colloop:    mov     .RowX,cx            %@AB@%;save coordinates of this row%@AE@%%@NL@%
  13717.             mov     .RowY,dx%@NL@%
  13718.             push    bx                    %@AB@%;save remaining bits in character%@AE@%%@NL@%
  13719.             cmp     bx,8            %@AB@%;limit to 8 for this column%@AE@%%@NL@%
  13720.             jle     colloop2%@NL@%
  13721.             mov     bx,8%@NL@%
  13722. %@NL@%
  13723. colloop2:   mov     .ColWid,bx            %@AB@%;save width of this column for other rows%@AE@%%@NL@%
  13724.             mov     ax,CharHeight   %@AB@%;counter for number of rows%@AE@%%@NL@%
  13725. %@NL@%
  13726. rowloop:    push    ax%@NL@%
  13727.             inc     si                    %@AB@%;increment bitmap pointer%@AE@%%@NL@%
  13728.             mov     al,es:[si]            %@AB@%;get byte from bitmap%@AE@%%@NL@%
  13729. %@NL@%
  13730. pixloop:    shl     al,1            %@AB@%;check next bit (from left to right)%@AE@%%@NL@%
  13731.             jnc     nextpixel            %@AB@%;skip this pixel%@AE@%%@NL@%
  13732. %@NL@%
  13733.             push    ax                    %@AB@%;save registers%@AE@%%@NL@%
  13734.             push    bx%@NL@%
  13735.             push    cx%@NL@%
  13736.             push    dx%@NL@%
  13737.             push    es%@NL@%
  13738.             push    si%@NL@%
  13739. %@NL@%
  13740.             mov     ax,CharColor    %@AB@%;set up params for pset call%@AE@%%@NL@%
  13741.             push    ax                    %@AB@%;color%@AE@%%@NL@%
  13742.             push    cx                    %@AB@%;x-coordinate%@AE@%%@NL@%
  13743.             push    dx                    %@AB@%;y-coordinate%@AE@%%@NL@%
  13744.             call    B$N1I2            %@AB@%;set graphics cursor location%@AE@%%@NL@%
  13745.             call    B$PSTC            %@AB@%;call PSET%@AE@%%@NL@%
  13746. %@NL@%
  13747.             pop     si                    %@AB@%;restore registers%@AE@%%@NL@%
  13748.             pop     es%@NL@%
  13749.             pop     dx%@NL@%
  13750.             pop     cx%@NL@%
  13751.             pop     bx%@NL@%
  13752.             pop     ax%@NL@%
  13753. %@NL@%
  13754. nextpixel:  jz            nextrow            %@AB@%;skip remaining zero bits%@AE@%%@NL@%
  13755.             add     cx,XPixInc            %@AB@%;increment x and y coordinates%@AE@%%@NL@%
  13756.             add     dx,YPixInc%@NL@%
  13757.             dec     bx                    %@AB@%;check for end of byte%@AE@%%@NL@%
  13758.             jnz     pixloop            %@AB@%;go for another pixel%@AE@%%@NL@%
  13759. %@NL@%
  13760. nextrow:    mov     cx,.RowX            %@AB@%;retrieve the start coord of this row%@AE@%%@NL@%
  13761.             mov     dx,.RowY%@NL@%
  13762.             add     cx,XRowInc            %@AB@%;increment counters for next row%@AE@%%@NL@%
  13763.             add     dx,YRowInc%@NL@%
  13764.             mov     .RowX,cx            %@AB@%;save 'em back again%@AE@%%@NL@%
  13765.             mov     .RowY,dx%@NL@%
  13766.             mov     bx,.ColWid            %@AB@%;reset the column width%@AE@%%@NL@%
  13767.             pop     ax                    %@AB@%;check for the end of this column%@AE@%%@NL@%
  13768.             dec     ax%@NL@%
  13769.             jnz     rowloop            %@AB@%;repeat for another row%@AE@%%@NL@%
  13770. %@NL@%
  13771. nextcol:    mov     cx,pX            %@AB@%;retrieve the start coord of this column%@AE@%%@NL@%
  13772.             mov     dx,pY%@NL@%
  13773.             add     cx,XColInc            %@AB@%;increment coordinates for next column%@AE@%%@NL@%
  13774.             add     dx,YColInc%@NL@%
  13775.             mov     pX,cx            %@AB@%;save coordinates to use after next column%@AE@%%@NL@%
  13776.             mov     pY,dx%@NL@%
  13777.             pop     bx                    %@AB@%;check for end of the bitmap%@AE@%%@NL@%
  13778.             sub     bx,8%@NL@%
  13779.             ja            colloop            %@AB@%;repeat for another column%@AE@%%@NL@%
  13780. %@NL@%
  13781.             %@AB@%;Done%@AE@%%@NL@%
  13782.             mov     ax,.CharWid     %@AB@%;return value%@AE@%%@NL@%
  13783. %@NL@%
  13784.             pop     si                    %@AB@%;Exit%@AE@%%@NL@%
  13785.             pop     di%@NL@%
  13786.             mov     sp,bp%@NL@%
  13787.             pop     bp%@NL@%
  13788.             ret     10%@NL@%
  13789. fl_BltChar  ENDP%@NL@%
  13790. %@NL@%
  13791. %@AB@%;********************************************************************%@AE@%%@NL@%
  13792. %@AB@%; fl_MovMem - Moves memory bytes%@AE@%%@NL@%
  13793. %@AB@%;%@AE@%%@NL@%
  13794. %@AB@%;   BASIC CALL:%@AE@%%@NL@%
  13795. %@AB@%;        fl.MovMem source, dest, nbytes%@AE@%%@NL@%
  13796. %@AB@%;%@AE@%%@NL@%
  13797. %@AB@%;********************************************************************%@AE@%%@NL@%
  13798.             PUBLIC  fl_MovMem%@NL@%
  13799. fl_MovMem   PROC%@NL@%
  13800.             push    bp%@NL@%
  13801.             mov     bp,sp%@NL@%
  13802.             push    si%@NL@%
  13803.             push    ds%@NL@%
  13804.             push    di%@NL@%
  13805. %@NL@%
  13806.             les     di,[bp+12]%@NL@%
  13807.             lds     si,[bp+8]%@NL@%
  13808.             mov     cx,[bp+6]%@NL@%
  13809.             rep            movsb%@NL@%
  13810. %@NL@%
  13811.             pop     di%@NL@%
  13812.             pop     ds%@NL@%
  13813.             pop     si%@NL@%
  13814.             pop     bp%@NL@%
  13815.             ret     10%@NL@%
  13816. fl_MovMem   ENDP%@NL@%
  13817. %@NL@%
  13818. %@AB@%;********************************************************************%@AE@%%@NL@%
  13819. %@AB@%; fl_ansi - Converts IBM char to Windows ANSI mapping%@AE@%%@NL@%
  13820. %@AB@%;%@AE@%%@NL@%
  13821. %@AB@%;   BASIC CALL:%@AE@%%@NL@%
  13822. %@AB@%;        ansi_byte = fl_ansi (ibm_char%)%@AE@%%@NL@%
  13823. %@AB@%;%@AE@%%@NL@%
  13824. %@AB@%;********************************************************************%@AE@%%@NL@%
  13825. .CODE%@NL@%
  13826.             PUBLIC  fl_ansi%@NL@%
  13827. fl_ansi     PROC%@NL@%
  13828.             push    bp%@NL@%
  13829.             mov     bp,sp%@NL@%
  13830. %@NL@%
  13831.             xor     ax,ax            %@AB@%; zero ax%@AE@%%@NL@%
  13832.             mov     al,[bp+6]            %@AB@%; move input byte to ax%@AE@%%@NL@%
  13833.             mov     bx,ax            %@AB@%; copy byte to bx%@AE@%%@NL@%
  13834.             and     al,7FH            %@AB@%; mask off high bit%@AE@%%@NL@%
  13835.             test    bl,80H            %@AB@%; test bx to see it high bit set%@AE@%%@NL@%
  13836.             jz            fl_a_2            %@AB@%; if so then byte < 128, no translation%@AE@%%@NL@%
  13837. %@NL@%
  13838.             mov     bx,OFFSET _OemToAnsiTable%@NL@%
  13839.             xlat%@NL@%
  13840. %@NL@%
  13841. fl_a_2:     pop     bp%@NL@%
  13842.             ret     2%@NL@%
  13843. fl_ansi     ENDP%@NL@%
  13844. %@NL@%
  13845. %@NL@%
  13846. %@AB@%;***************************************************************************%@AE@%%@NL@%
  13847. %@AB@%;   USA OEM/ANSI translation tables.                                       *%@AE@%%@NL@%
  13848. %@AB@%;***************************************************************************%@AE@%%@NL@%
  13849. %@AB@%;%@AE@%%@NL@%
  13850. %@NL@%
  13851. %@AB@%; This translation table is used by U.S.A. and some European countries.%@AE@%%@NL@%
  13852. %@AB@%; The original IBM extended character set is now addressed as Code Page 437.%@AE@%%@NL@%
  13853. %@AB@%; With DOS 3.3 or later, IBM introduced Code Page 850 as the preeminent%@AE@%%@NL@%
  13854. %@AB@%; multilingual character set.%@AE@%%@NL@%
  13855. %@NL@%
  13856. %@AB@%; this translates Oem codes >= 128 to ANSI.%@AE@%%@NL@%
  13857. %@AB@%; there are 128 entries.%@AE@%%@NL@%
  13858. %@NL@%
  13859. .DATA%@NL@%
  13860. _OemToAnsiTable  label   byte%@NL@%
  13861. %@NL@%
  13862.         db   0C7H     %@AB@%; 80h  C cedilla%@AE@%%@NL@%
  13863.         db   0FCh     %@AB@%; 81h  u umlaut%@AE@%%@NL@%
  13864.         db   0E9h     %@AB@%; 82h  e acute%@AE@%%@NL@%
  13865.         db   0E2h     %@AB@%; 83h  a circumflex%@AE@%%@NL@%
  13866.         db   0E4h     %@AB@%; 84h  a umlaut%@AE@%%@NL@%
  13867.         db   0E0h     %@AB@%; 85h  a grave%@AE@%%@NL@%
  13868.         db   0E5h     %@AB@%; 86h  a ring%@AE@%%@NL@%
  13869.         db   0E7h     %@AB@%; 87h  c cedilla%@AE@%%@NL@%
  13870.         db   0EAh     %@AB@%; 88h  e circumflex%@AE@%%@NL@%
  13871.         db   0EBh     %@AB@%; 89h  e umlaut%@AE@%%@NL@%
  13872.         db   0E8h     %@AB@%; 8Ah  e grave%@AE@%%@NL@%
  13873.         db   0EFh     %@AB@%; 8Bh  i umlaut%@AE@%%@NL@%
  13874.         db   0EEh     %@AB@%; 8Ch  i circumflex%@AE@%%@NL@%
  13875.         db   0ECh     %@AB@%; 8Dh  i grave%@AE@%%@NL@%
  13876.         db   0C4h     %@AB@%; 8Eh  A umlaut%@AE@%%@NL@%
  13877.         db   0C5h     %@AB@%; 8Fh  A ring%@AE@%%@NL@%
  13878. %@NL@%
  13879.         db   0C9h     %@AB@%; 90h  E acute%@AE@%%@NL@%
  13880.         db   0E6h     %@AB@%; 91h  ae%@AE@%%@NL@%
  13881.         db   0C6h     %@AB@%; 92h  AE%@AE@%%@NL@%
  13882.         db   0F4h     %@AB@%; 93h  o circumflex%@AE@%%@NL@%
  13883.         db   0F6h     %@AB@%; 94h  o umlaut%@AE@%%@NL@%
  13884.         db   0F2h     %@AB@%; 95h  o grave%@AE@%%@NL@%
  13885.         db   0FBh     %@AB@%; 96h  u circumflex%@AE@%%@NL@%
  13886.         db   0F9h     %@AB@%; 97h  u grave%@AE@%%@NL@%
  13887.         db   0FFh     %@AB@%; 98h  y umlaut%@AE@%%@NL@%
  13888.         db   0D6h     %@AB@%; 99h  O umlaut%@AE@%%@NL@%
  13889.         db   0DCh     %@AB@%; 9Ah  U umlaut%@AE@%%@NL@%
  13890.         db   0A2h     %@AB@%; 9Bh  cent%@AE@%%@NL@%
  13891.         db   0A3h     %@AB@%; 9Ch  british pound%@AE@%%@NL@%
  13892.         db   0A5h     %@AB@%; 9Dh  yen%@AE@%%@NL@%
  13893.         db   070h     %@AB@%; 9Eh  Pesetas%@AE@%%@NL@%
  13894.         db   066h     %@AB@%; 9Fh  florin (dutch)%@AE@%%@NL@%
  13895. %@NL@%
  13896.         db   0E1h     %@AB@%; A0h  a acute%@AE@%%@NL@%
  13897.         db   0EDh     %@AB@%; A1h  i acute%@AE@%%@NL@%
  13898.         db   0F3h     %@AB@%; A2h  o acute%@AE@%%@NL@%
  13899.         db   0FAh     %@AB@%; A3h  u acute%@AE@%%@NL@%
  13900.         db   0F1h     %@AB@%; A4h  n tilde%@AE@%%@NL@%
  13901.         db   0D1h     %@AB@%; A5h  N tilde%@AE@%%@NL@%
  13902.         db   0AAh     %@AB@%; A6h  a underlined superscript%@AE@%%@NL@%
  13903.         db   0BAh     %@AB@%; A7h  o underlined superscript%@AE@%%@NL@%
  13904.         db   0BFh     %@AB@%; A8h  inverted question mark%@AE@%%@NL@%
  13905.         db   05Fh     %@AB@%; A9h  left top corner%@AE@%%@NL@%
  13906.         db   0ACh     %@AB@%; AAh  right top corner%@AE@%%@NL@%
  13907.         db   0BDh     %@AB@%; ABh  1/2%@AE@%%@NL@%
  13908.         db   0BCh     %@AB@%; ACh  1/4%@AE@%%@NL@%
  13909.         db   0A1h     %@AB@%; ADh  inverted point%@AE@%%@NL@%
  13910.         db   0ABh     %@AB@%; AEh  <<%@AE@%%@NL@%
  13911.         db   0BBh     %@AB@%; AFh  >>%@AE@%%@NL@%
  13912. %@NL@%
  13913.         db   05Fh     %@AB@%; B0h  here begins semigraphic characters%@AE@%%@NL@%
  13914.         db   05Fh     %@AB@%; B1h%@AE@%%@NL@%
  13915.         db   05Fh     %@AB@%; B2h%@AE@%%@NL@%
  13916.         db   0A6h     %@AB@%; B3h  Vertical bar%@AE@%%@NL@%
  13917.         db   05Fh     %@AB@%; B4h%@AE@%%@NL@%
  13918.         db   05Fh     %@AB@%; B5h%@AE@%%@NL@%
  13919.         db   05Fh     %@AB@%; B6h%@AE@%%@NL@%
  13920.         db   05Fh     %@AB@%; B7h%@AE@%%@NL@%
  13921.         db   05Fh     %@AB@%; B8h%@AE@%%@NL@%
  13922.         db   05Fh     %@AB@%; B9h%@AE@%%@NL@%
  13923.         db   05Fh     %@AB@%; BAh%@AE@%%@NL@%
  13924.         db   05Fh     %@AB@%; BBh%@AE@%%@NL@%
  13925.         db   05Fh     %@AB@%; BCh%@AE@%%@NL@%
  13926.         db   05Fh     %@AB@%; BDh%@AE@%%@NL@%
  13927.         db   05Fh     %@AB@%; BEh%@AE@%%@NL@%
  13928.         db   05Fh     %@AB@%; BFh%@AE@%%@NL@%
  13929. %@NL@%
  13930.         db   05Fh     %@AB@%; C0h%@AE@%%@NL@%
  13931.         db   05Fh     %@AB@%; C1h%@AE@%%@NL@%
  13932.         db   05Fh     %@AB@%; C2h%@AE@%%@NL@%
  13933.         db   05Fh     %@AB@%; C3h%@AE@%%@NL@%
  13934.         db   05Fh     %@AB@%; C4h%@AE@%%@NL@%
  13935.         db   05Fh     %@AB@%; C5h%@AE@%%@NL@%
  13936.         db   05Fh     %@AB@%; C6h%@AE@%%@NL@%
  13937.         db   05Fh     %@AB@%; C7h%@AE@%%@NL@%
  13938.         db   05Fh     %@AB@%; C8h%@AE@%%@NL@%
  13939.         db   05Fh     %@AB@%; C9h%@AE@%%@NL@%
  13940.         db   05Fh     %@AB@%; CAh%@AE@%%@NL@%
  13941.         db   05Fh     %@AB@%; CBh%@AE@%%@NL@%
  13942.         db   05Fh     %@AB@%; CCh%@AE@%%@NL@%
  13943.         db   05Fh     %@AB@%; CDh%@AE@%%@NL@%
  13944.         db   05Fh     %@AB@%; CEh%@AE@%%@NL@%
  13945.         db   05Fh     %@AB@%; CFh%@AE@%%@NL@%
  13946. %@NL@%
  13947.         db   05Fh     %@AB@%; D0h%@AE@%%@NL@%
  13948.         db   05Fh     %@AB@%; D1h%@AE@%%@NL@%
  13949.         db   05Fh     %@AB@%; D2h%@AE@%%@NL@%
  13950.         db   05Fh     %@AB@%; D3h%@AE@%%@NL@%
  13951.         db   05Fh     %@AB@%; D4h%@AE@%%@NL@%
  13952.         db   05Fh     %@AB@%; D5h%@AE@%%@NL@%
  13953.         db   05Fh     %@AB@%; D6h%@AE@%%@NL@%
  13954.         db   05Fh     %@AB@%; D7h%@AE@%%@NL@%
  13955.         db   05Fh     %@AB@%; D8h%@AE@%%@NL@%
  13956.         db   05Fh     %@AB@%; D9h%@AE@%%@NL@%
  13957.         db   05Fh     %@AB@%; DAh%@AE@%%@NL@%
  13958.         db   05Fh     %@AB@%; DBh%@AE@%%@NL@%
  13959.         db   05Fh     %@AB@%; DCh%@AE@%%@NL@%
  13960.         db   05Fh     %@AB@%; DDh%@AE@%%@NL@%
  13961.         db   05Fh     %@AB@%; DEh%@AE@%%@NL@%
  13962.         db   05Fh     %@AB@%; DFh  end of semigraphic characters%@AE@%%@NL@%
  13963. %@NL@%
  13964.         db   05Fh     %@AB@%; E0h  alpha%@AE@%%@NL@%
  13965.         db   0DFh     %@AB@%; E1h  german sharp S or greek beta%@AE@%%@NL@%
  13966.         db   05Fh     %@AB@%; E2h  lambda%@AE@%%@NL@%
  13967.         db   0B6h     %@AB@%; E3h  pi%@AE@%%@NL@%
  13968.         db   05Fh     %@AB@%; E4h  sigma uc%@AE@%%@NL@%
  13969.         db   05Fh     %@AB@%; E5h  sigma lc%@AE@%%@NL@%
  13970.         db   0B5h     %@AB@%; E6h  mu%@AE@%%@NL@%
  13971.         db   05Fh     %@AB@%; E7h  tau%@AE@%%@NL@%
  13972.         db   05Fh     %@AB@%; E8h  phi uc%@AE@%%@NL@%
  13973.         db   05Fh     %@AB@%; E9h  theta%@AE@%%@NL@%
  13974.         db   05Fh     %@AB@%; EAh  omega%@AE@%%@NL@%
  13975.         db   05Fh     %@AB@%; EBh  delta%@AE@%%@NL@%
  13976.         db   05Fh     %@AB@%; ECh  infinite%@AE@%%@NL@%
  13977.         db   0D8h     %@AB@%; EDh  math empty set or phi lc%@AE@%%@NL@%
  13978.         db   05Fh     %@AB@%; EEh  math own sign%@AE@%%@NL@%
  13979.         db   05Fh     %@AB@%; EFh  math include sign%@AE@%%@NL@%
  13980. %@NL@%
  13981.         db   05Fh     %@AB@%; F0h  math equivalence sign%@AE@%%@NL@%
  13982.         db   0B1h     %@AB@%; F1h  + underlined%@AE@%%@NL@%
  13983.         db   05Fh     %@AB@%; F2h  greater equal%@AE@%%@NL@%
  13984.         db   05Fh     %@AB@%; F3h  less equal%@AE@%%@NL@%
  13985.         db   05Fh     %@AB@%; F4h  math integral upper part%@AE@%%@NL@%
  13986.         db   05Fh     %@AB@%; F5h  math integral lower part%@AE@%%@NL@%
  13987.         db   05Fh     %@AB@%; F6h  math divide%@AE@%%@NL@%
  13988.         db   05Fh     %@AB@%; F7h  math approximately (~)%@AE@%%@NL@%
  13989.         db   0B0h     %@AB@%; F8h  degree%@AE@%%@NL@%
  13990.         db   0B7h     %@AB@%; F9h  period accent (bold)%@AE@%%@NL@%
  13991.         db   0B7h     %@AB@%; FAh  period accent%@AE@%%@NL@%
  13992.         db   05Fh     %@AB@%; FBh  math root%@AE@%%@NL@%
  13993.         db   06Eh     %@AB@%; FCh  n superscript%@AE@%%@NL@%
  13994.         db   0B2h     %@AB@%; FDh  2 superscript%@AE@%%@NL@%
  13995.         db   05Fh     %@AB@%; FEh%@AE@%%@NL@%
  13996.         db   05Fh     %@AB@%; FFh  blank%@AE@%%@NL@%
  13997. %@NL@%
  13998.         END%@NL@%
  13999. %@NL@%
  14000. %@NL@%
  14001. %@2@%%@AH@%FONTB.BAS%@AE@%%@EH@%%@NL@%
  14002. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\FONTB.BAS%@AE@%%@NL@%
  14003. %@NL@%
  14004. %@AB@%'*** FONTB.BAS - Font Routines for the Presentation Graphics Toolbox in%@AE@%%@NL@%
  14005. %@AB@%'           Microsoft BASIC 7.0, Professional Development System%@AE@%%@NL@%
  14006. %@AB@%'              Copyright (C) 1987-1989, Microsoft Corporation%@AE@%%@NL@%
  14007. %@AB@%'%@AE@%%@NL@%
  14008. %@AB@%'  NOTE:  This sample source code toolbox is intended to demonstrate some%@AE@%%@NL@%
  14009. %@AB@%'  of the extended capabilities of Microsoft BASIC 7.0 Professional Development%@AE@%%@NL@%
  14010. %@AB@%'  system that can help to leverage the professional developer's time more%@AE@%%@NL@%
  14011. %@AB@%'  effectively.  While you are free to use, modify, or distribute the routines%@AE@%%@NL@%
  14012. %@AB@%'  in this module in any way you find useful, it should be noted that these are%@AE@%%@NL@%
  14013. %@AB@%'  examples only and should not be relied upon as a fully-tested "add-on"%@AE@%%@NL@%
  14014. %@AB@%'  library.%@AE@%%@NL@%
  14015. %@AB@%'%@AE@%%@NL@%
  14016. %@AB@%'  PURPOSE:  These are the toolbox routines to handle graphics text using%@AE@%%@NL@%
  14017. %@AB@%'            Windows format raster font files:%@AE@%%@NL@%
  14018. %@AB@%'%@AE@%%@NL@%
  14019. %@AB@%'  To create a library and QuickLib containing the font routines found%@AE@%%@NL@%
  14020. %@AB@%'  in this file, follow these steps:%@AE@%%@NL@%
  14021. %@AB@%'       BC /X/FS fontb.bas%@AE@%%@NL@%
  14022. %@AB@%'       LIB fontb.lib + fontb + fontasm + qbx.lib;%@AE@%%@NL@%
  14023. %@AB@%'       LINK /Q fontb.lib, fontb.qlb,,qbxqlb.lib;%@AE@%%@NL@%
  14024. %@AB@%'  If you are going to use this FONTB.QLB QuickLib in conjunction with%@AE@%%@NL@%
  14025. %@AB@%'  the charting source code (CHRTB.BAS) or the UI toobox source code%@AE@%%@NL@%
  14026. %@AB@%'  (GENERAL.BAS, WINDOW.BAS, MENU.BAS and MOUSE.BAS), you need to%@AE@%%@NL@%
  14027. %@AB@%'  include the assembly code routines referenced in these files.  For the%@AE@%%@NL@%
  14028. %@AB@%'  charting routines, create FONTB.LIB as follows before you create the%@AE@%%@NL@%
  14029. %@AB@%'  QuickLib:%@AE@%%@NL@%
  14030. %@AB@%'       LIB fontb.lib + fontb + fontasm + chrtasm + qbx.lib;%@AE@%%@NL@%
  14031. %@AB@%'  For the UI toolbox routines, create the library as follows:%@AE@%%@NL@%
  14032. %@AB@%'       LIB fontb.lib + fontb + fontasm + uiasm + qbx.lib;%@AE@%%@NL@%
  14033. %@AB@%'**************************************************************************%@AE@%%@NL@%
  14034. %@NL@%
  14035. %@AB@%' $INCLUDE: 'QBX.BI'%@AE@%%@NL@%
  14036. %@AB@%' $INCLUDE: 'FONTB.BI'%@AE@%%@NL@%
  14037. %@NL@%
  14038. CONST cFALSE = 0              ' Logical False%@NL@%
  14039. CONST cTRUE = NOT cFALSE      ' Logical True%@NL@%
  14040. %@NL@%
  14041. CONST cDefaultColor = 15      ' Default character color (white in all modes)%@NL@%
  14042. CONST cDefaultDir = 0         ' Default character direction%@NL@%
  14043. CONST cDefaultFont = 1        ' Default font selected in LoadFont%@NL@%
  14044. %@NL@%
  14045. CONST cMaxFaceName = 32       ' Maximum length of a font name%@NL@%
  14046. CONST cMaxFileName = 66       ' Maximum length of a font file name%@NL@%
  14047. CONST cFontResource = &H8008  ' Identifies a font resource%@NL@%
  14048. CONST cBitMapType = 0         ' Bitmap font type%@NL@%
  14049. %@NL@%
  14050. CONST cFileFont = 0           ' Font comes from file%@NL@%
  14051. CONST cMemFont = 1            ' Font comes from memory%@NL@%
  14052. %@NL@%
  14053. CONST cSizeFontHeader = 118   ' Size of Windows font header%@NL@%
  14054. %@NL@%
  14055. %@AB@%' *********************************************************************%@AE@%%@NL@%
  14056. %@AB@%' Data Types:%@AE@%%@NL@%
  14057. %@NL@%
  14058. %@AB@%' Some global variables used:%@AE@%%@NL@%
  14059. TYPE GlobalParams%@NL@%
  14060.         MaxRegistered     AS INTEGER     ' Max number of registered fonts allowed%@NL@%
  14061.         MaxLoaded         AS INTEGER     ' Max number of loaded fonts allowed%@NL@%
  14062.         TotalRegistered   AS INTEGER     ' Number of fonts actually registered%@NL@%
  14063.         TotalLoaded       AS INTEGER     ' Number of fonts actually loaded%@NL@%
  14064. %@NL@%
  14065.         NextDataBlock     AS INTEGER     ' Next available block in font buffer%@NL@%
  14066. %@NL@%
  14067.         CurrentFont       AS INTEGER     ' Current font number in loaded fonts%@NL@%
  14068.         CHeight           AS INTEGER     ' Character height of current font%@NL@%
  14069.         FChar             AS INTEGER     ' First char in font%@NL@%
  14070.         LChar             AS INTEGER     ' Last char in font%@NL@%
  14071.         DChar             AS INTEGER     ' Default char for font%@NL@%
  14072.         DSeg              AS INTEGER     ' Segment of current font%@NL@%
  14073.         DOffset           AS INTEGER     ' Offset of current font%@NL@%
  14074.         FontSource        AS INTEGER     ' Source of current font (File or Mem)%@NL@%
  14075. %@NL@%
  14076.         CharColorInit     AS INTEGER     ' cFALSE (0) means color not initialized%@NL@%
  14077.         CharColor         AS INTEGER     ' Character color%@NL@%
  14078.         CharDirInit       AS INTEGER     ' cFALSE (0) means dir not initialized%@NL@%
  14079.         CharDir           AS INTEGER     ' Character direction%@NL@%
  14080.         CharSet           AS INTEGER     ' Character mappings to use%@NL@%
  14081. %@NL@%
  14082.         XPixInc           AS INTEGER     ' X increment direction (0, 1, -1)%@NL@%
  14083.         YPixInc           AS INTEGER     ' Y increment direction (0, 1, -1)%@NL@%
  14084. %@NL@%
  14085.         WindowSet         AS INTEGER     ' cTRUE if GTextWindow has been called%@NL@%
  14086.         WX1               AS SINGLE      ' Minimum WINDOW X%@NL@%
  14087.         WY1               AS SINGLE      ' Minimum WINDOW Y%@NL@%
  14088.         WX2               AS SINGLE      ' Maximum WINDOW X%@NL@%
  14089.         WY2               AS SINGLE      ' Maximum WINDOW Y%@NL@%
  14090.         WScrn             AS INTEGER     ' cTRUE means Y increases top to bottom%@NL@%
  14091. %@NL@%
  14092. END TYPE%@NL@%
  14093. %@NL@%
  14094. %@AB@%' The following 3 types are needed to read .FON files. They are documented%@AE@%%@NL@%
  14095. %@AB@%' in chapter 7 of the MS Windows Programmer's Reference:%@AE@%%@NL@%
  14096. %@NL@%
  14097. %@AB@%' Windows font file header:%@AE@%%@NL@%
  14098. TYPE WFHeader%@NL@%
  14099.         dfVersion         AS INTEGER%@NL@%
  14100.         dfSize            AS LONG%@NL@%
  14101.         dfCopyright       AS STRING * 60%@NL@%
  14102.         dfType            AS INTEGER%@NL@%
  14103.         dfPoints          AS INTEGER%@NL@%
  14104.         dfVertRes         AS INTEGER%@NL@%
  14105.         dfHorizRes        AS INTEGER%@NL@%
  14106.         dfAscent          AS INTEGER%@NL@%
  14107.         dfInternalLeading AS INTEGER%@NL@%
  14108.         dfExternalLeading AS INTEGER%@NL@%
  14109.         dfItalic          AS STRING * 1%@NL@%
  14110.         dfUnderline       AS STRING * 1%@NL@%
  14111.         dfStrikeOut       AS STRING * 1%@NL@%
  14112.         dfWeight          AS INTEGER%@NL@%
  14113.         dfCharSet         AS STRING * 1%@NL@%
  14114.         dfPixWidth        AS INTEGER%@NL@%
  14115.         dfPixHeight       AS INTEGER%@NL@%
  14116.         dfPitchAndFamily  AS STRING * 1%@NL@%
  14117.         dfAvgWidth        AS INTEGER%@NL@%
  14118.         dfMaxWidth        AS INTEGER%@NL@%
  14119.         dfFirstChar       AS STRING * 1%@NL@%
  14120.         dfLastChar        AS STRING * 1%@NL@%
  14121.         dfDefaultChar     AS STRING * 1%@NL@%
  14122.         dfBreakChar       AS STRING * 1%@NL@%
  14123.         dfWidthBytes      AS INTEGER%@NL@%
  14124.         dfDevice          AS LONG%@NL@%
  14125.         dfFace            AS LONG%@NL@%
  14126.         dfBitsPointer     AS LONG%@NL@%
  14127.         dfBitsOffset      AS LONG%@NL@%
  14128.         pad               AS STRING * 1  ' To ensure word boundry%@NL@%
  14129. END TYPE%@NL@%
  14130. %@NL@%
  14131. %@AB@%' Structure for reading resource type and number from a resource%@AE@%%@NL@%
  14132. %@AB@%' table:%@AE@%%@NL@%
  14133. TYPE ResType%@NL@%
  14134.         TypeID            AS INTEGER%@NL@%
  14135.         NumResource       AS INTEGER%@NL@%
  14136.         Reserved          AS LONG%@NL@%
  14137. END TYPE%@NL@%
  14138. %@NL@%
  14139. %@AB@%' Structure for reading an actual resource entry:%@AE@%%@NL@%
  14140. TYPE ResEntry%@NL@%
  14141.         AddrOffset        AS INTEGER%@NL@%
  14142.         Length            AS INTEGER%@NL@%
  14143.         ResourceKeywd     AS INTEGER%@NL@%
  14144.         ResID             AS INTEGER%@NL@%
  14145.         Reserved1         AS LONG%@NL@%
  14146. END TYPE%@NL@%
  14147. %@NL@%
  14148. %@AB@%' Internal font header data type:%@AE@%%@NL@%
  14149. TYPE IFontInfo%@NL@%
  14150.         Status            AS INTEGER  ' Processing status. 0=unproc. else <>0%@NL@%
  14151.         FontHeader        AS WFHeader ' The Windows font header%@NL@%
  14152.         FaceName          AS STRING * cMaxFaceName   ' Font name%@NL@%
  14153.         FileName          AS STRING * cMaxFileName   ' File name%@NL@%
  14154.         FontSource        AS INTEGER  ' 0=file, 1=memory%@NL@%
  14155.         FileLoc           AS LONG     ' Location in resource file of font file%@NL@%
  14156.         DataSeg           AS INTEGER  ' FontData index or Segment address of font%@NL@%
  14157.         DataOffset        AS INTEGER  ' Offset  address of font if in memory%@NL@%
  14158.         BitsOffset        AS INTEGER  ' Offset from beginning of data to bitmaps%@NL@%
  14159. END TYPE%@NL@%
  14160. %@NL@%
  14161. %@AB@%' Type for selecting registered fonts via LoadFont:%@AE@%%@NL@%
  14162. TYPE FontSpec%@NL@%
  14163.         FaceName    AS STRING * cMaxFaceName%@NL@%
  14164.         Pitch       AS STRING * 1%@NL@%
  14165.         PointSize   AS INTEGER     ' Fonts point size%@NL@%
  14166.         HorizRes    AS INTEGER     ' Horizontal resolution of font%@NL@%
  14167.         VertRes     AS INTEGER     ' Vertical resolution of font%@NL@%
  14168.         ScrnMode    AS INTEGER     ' Screen mode%@NL@%
  14169.         Height      AS INTEGER     ' Pixel height of font%@NL@%
  14170. %@NL@%
  14171.         Best        AS INTEGER     ' "Best" flag (true/false)%@NL@%
  14172. %@NL@%
  14173.         RegNum      AS INTEGER     ' Number of font in registered list%@NL@%
  14174. %@NL@%
  14175.         InMemory    AS INTEGER     ' Whether font is in memory (true/false)%@NL@%
  14176.         HdrSeg      AS INTEGER     ' Segment of font in memory%@NL@%
  14177.         HdrOff      AS INTEGER     ' Offset of font in segment%@NL@%
  14178.         DataSeg     AS INTEGER     ' Segment of data in memory%@NL@%
  14179.         DataOff     AS INTEGER     ' Offset of data in segment%@NL@%
  14180. END TYPE%@NL@%
  14181. %@NL@%
  14182. %@AB@%' *********************************************************************%@AE@%%@NL@%
  14183. %@AB@%' Routine Declarations:%@AE@%%@NL@%
  14184. %@NL@%
  14185. DECLARE SUB flSetFontErr (ErrNum AS INTEGER)%@NL@%
  14186. DECLARE SUB flClearFontErr ()%@NL@%
  14187. DECLARE SUB flRegisterFont (FileName$, FileNum%)%@NL@%
  14188. DECLARE SUB flReadFont (I%)%@NL@%
  14189. DECLARE SUB flSizeFontBuffer (NFonts%)%@NL@%
  14190. DECLARE SUB flInitSpec (Spec AS ANY)%@NL@%
  14191. DECLARE SUB flClearFontStatus ()%@NL@%
  14192. DECLARE SUB flGetCurrentScrnSize (XPixels%, YPixels%)%@NL@%
  14193. DECLARE SUB flGetBASICScrnSize (ScrnMode%, XPixels%, YPixels%)%@NL@%
  14194. DECLARE SUB flInitMask ()%@NL@%
  14195. DECLARE SUB flPSET (X%, Y%, Colr%)%@NL@%
  14196. DECLARE SUB flChkMax ()%@NL@%
  14197. %@NL@%
  14198. DECLARE FUNCTION flGetFonts! (NFonts%)%@NL@%
  14199. DECLARE FUNCTION flMatchFont! (FSpec AS ANY)%@NL@%
  14200. DECLARE FUNCTION flGetNum! (Txt$, ChPos%, Default!, ErrV!)%@NL@%
  14201. DECLARE FUNCTION flGetNextSpec! (SpecTxt$, ChPos%, Spec AS ANY)%@NL@%
  14202. DECLARE FUNCTION flDoNextResource! (Align%, FileName$, FileNum%)%@NL@%
  14203. DECLARE FUNCTION flOutGChar% (X%, Y%, ChVal%)%@NL@%
  14204. %@NL@%
  14205. %@AB@%' -- Assembly language routines%@AE@%%@NL@%
  14206. DECLARE SUB flMovMem ALIAS "fl_MovMem" (SEG dest AS ANY, BYVAL SrcSeg AS INTEGER, BYVAL SrcOffset AS INTEGER, BYVAL Count AS INTEGER)%@NL@%
  14207. DECLARE FUNCTION flANSI% ALIAS "fl_ansi" (BYVAL I%)%@NL@%
  14208. %@NL@%
  14209. DECLARE SUB flSetBltDir ALIAS "fl_SetBltDir" (BYVAL XPixInc%, BYVAL YPixInc%, BYVAL XRowInc%, BYVAL YRowInc%)%@NL@%
  14210. DECLARE SUB flSetBltColor ALIAS "fl_SetBltColor" (BYVAL CharColor%)%@NL@%
  14211. DECLARE SUB flSetBltParams ALIAS "fl_SetBltParams" (BYVAL HdrLen%, BYVAL CharHgt%, BYVAL FirstChar%, BYVAL LastChar%, BYVAL DefaultChar%)%@NL@%
  14212. DECLARE FUNCTION flbltchar% ALIAS "fl_BltChar" (BYVAL FASeg%, BYVAL FAOffset%, BYVAL Char%, BYVAL X%, BYVAL Y%)%@NL@%
  14213. %@NL@%
  14214. %@AB@%' *********************************************************************%@AE@%%@NL@%
  14215. %@AB@%' Variable Definitions:%@AE@%%@NL@%
  14216. %@NL@%
  14217. %@AB@%' The following arrays hold font headers and font data as fonts are%@AE@%%@NL@%
  14218. %@AB@%' registered and loaded. They are dynamically allocated so they can be%@AE@%%@NL@%
  14219. %@AB@%' changed in size to accomodate the number of fonts a program will be%@AE@%%@NL@%
  14220. %@AB@%' using:%@AE@%%@NL@%
  14221. %@NL@%
  14222. %@AB@%' $DYNAMIC%@AE@%%@NL@%
  14223. %@NL@%
  14224. %@AB@%' Array to hold header information for registered fonts:%@AE@%%@NL@%
  14225. DIM SHARED FontHdrReg(1 TO 10)  AS IFontInfo%@NL@%
  14226. %@NL@%
  14227. %@AB@%' Arrays to hold header information and registered font numbers%@AE@%%@NL@%
  14228. %@AB@%' for loaded fonts:%@AE@%%@NL@%
  14229. DIM SHARED FontHdrLoaded(1 TO 10) AS IFontInfo%@NL@%
  14230. DIM SHARED FontLoadList(1 TO 10) AS INTEGER%@NL@%
  14231. %@NL@%
  14232. %@AB@%' Array to hold font data information:%@AE@%%@NL@%
  14233. DIM SHARED FontData(1 TO 1) AS FontDataBlock%@NL@%
  14234. %@NL@%
  14235. %@AB@%' $STATIC%@AE@%%@NL@%
  14236. %@NL@%
  14237. %@AB@%' Structure holding global parameters:%@AE@%%@NL@%
  14238. DIM SHARED FGP AS GlobalParams%@NL@%
  14239. %@NL@%
  14240. %@AB@%' Error handler for flChkMax so these arrays will be dimensioned%@AE@%%@NL@%
  14241. %@AB@%' to 10 by default:%@AE@%%@NL@%
  14242. SetMax:%@NL@%
  14243.         REDIM FontHdrLoaded(1 TO 10) AS IFontInfo%@NL@%
  14244.         REDIM FontHdrReg(1 TO 10) AS IFontInfo%@NL@%
  14245.         REDIM FontLoadList(1 TO 10) AS INTEGER%@NL@%
  14246.         RESUME%@NL@%
  14247. %@NL@%
  14248. %@AB@%' Error handler for out of memory error:%@AE@%%@NL@%
  14249. MemErr:%@NL@%
  14250.         flSetFontErr cNoFontMem%@NL@%
  14251.         RESUME NEXT%@NL@%
  14252. %@NL@%
  14253. %@AB@%' Error handler for unexpected errors:%@AE@%%@NL@%
  14254. UnexpectedErr:%@NL@%
  14255.         flSetFontErr cFLUnexpectedErr + ERR%@NL@%
  14256.         RESUME NEXT%@NL@%
  14257. %@NL@%
  14258. %@AB@%' File not found error: RegisterFonts%@AE@%%@NL@%
  14259. NoFileErr:%@NL@%
  14260.         flSetFontErr cFileNotFound%@NL@%
  14261.         RESUME NEXT%@NL@%
  14262. %@NL@%
  14263. %@AB@%'=== flChkMax - Makes sure that max font settings are correct and%@AE@%%@NL@%
  14264. %@AB@%'                enforces default of 10 for max loaded and registered%@AE@%%@NL@%
  14265. %@AB@%'%@AE@%%@NL@%
  14266. %@AB@%'  Arguments:%@AE@%%@NL@%
  14267. %@AB@%'     none%@AE@%%@NL@%
  14268. %@AB@%'%@AE@%%@NL@%
  14269. %@AB@%'  Return Values:%@AE@%%@NL@%
  14270. %@AB@%'     none%@AE@%%@NL@%
  14271. %@AB@%'%@AE@%%@NL@%
  14272. %@AB@%'=================================================================%@AE@%%@NL@%
  14273. SUB flChkMax STATIC%@NL@%
  14274. SHARED FontHdrLoaded() AS IFontInfo%@NL@%
  14275. SHARED FontHdrReg() AS IFontInfo%@NL@%
  14276. SHARED FGP AS GlobalParams%@NL@%
  14277. %@NL@%
  14278. %@AB@%' Make sure that GP.MaxLoaded and GP.MaxRegistered match array dimensions%@AE@%%@NL@%
  14279. %@AB@%' this will only happen if user hasn't used SetMaxFonts and allows Fontlib%@AE@%%@NL@%
  14280. %@AB@%' to set a default of 10 since that is what the arrays are first DIM'd%@AE@%%@NL@%
  14281. %@AB@%' to:%@AE@%%@NL@%
  14282. %@NL@%
  14283. ON ERROR GOTO SetMax%@NL@%
  14284. FGP.MaxLoaded = UBOUND(FontHdrLoaded)%@NL@%
  14285. FGP.MaxRegistered = UBOUND(FontHdrReg)%@NL@%
  14286. ON ERROR GOTO UnexpectedErr%@NL@%
  14287. %@NL@%
  14288. END SUB%@NL@%
  14289. %@NL@%
  14290. %@AB@%'=== flClearFontErr - Sets the FontErr variable to 0%@AE@%%@NL@%
  14291. %@AB@%'%@AE@%%@NL@%
  14292. %@AB@%'  Arguments:%@AE@%%@NL@%
  14293. %@AB@%'     none%@AE@%%@NL@%
  14294. %@AB@%'%@AE@%%@NL@%
  14295. %@AB@%'  Return Values:%@AE@%%@NL@%
  14296. %@AB@%'     none%@AE@%%@NL@%
  14297. %@AB@%'%@AE@%%@NL@%
  14298. %@AB@%'=================================================================%@AE@%%@NL@%
  14299. SUB flClearFontErr STATIC%@NL@%
  14300. %@NL@%
  14301.         FontErr = 0%@NL@%
  14302. %@NL@%
  14303. END SUB%@NL@%
  14304. %@NL@%
  14305. %@AB@%'=== flClearFontStatus - Clears the status field in the registered font list%@AE@%%@NL@%
  14306. %@AB@%'%@AE@%%@NL@%
  14307. %@AB@%'  Arguments:%@AE@%%@NL@%
  14308. %@AB@%'     none%@AE@%%@NL@%
  14309. %@AB@%'%@AE@%%@NL@%
  14310. %@AB@%'=================================================================%@AE@%%@NL@%
  14311. SUB flClearFontStatus STATIC%@NL@%
  14312. SHARED FGP AS GlobalParams%@NL@%
  14313. SHARED FontHdrReg() AS IFontInfo%@NL@%
  14314. %@NL@%
  14315. FOR I% = 1 TO FGP.TotalRegistered%@NL@%
  14316.         FontHdrReg(I%).Status = 0%@NL@%
  14317. NEXT I%%@NL@%
  14318. %@NL@%
  14319. END SUB%@NL@%
  14320. %@NL@%
  14321. %@AB@%'=== flDoNextResource - Processes resource from resource table:%@AE@%%@NL@%
  14322. %@AB@%'%@AE@%%@NL@%
  14323. %@AB@%'  Arguments:%@AE@%%@NL@%
  14324. %@AB@%'     Align%      - Alignment shift count for finding resource data%@AE@%%@NL@%
  14325. %@AB@%'%@AE@%%@NL@%
  14326. %@AB@%'     FileName$   - Name of font file (passed to routine that actually%@AE@%%@NL@%
  14327. %@AB@%'                   registers resource entry)%@AE@%%@NL@%
  14328. %@AB@%'%@AE@%%@NL@%
  14329. %@AB@%'     FileNum%    - File number for reading%@AE@%%@NL@%
  14330. %@AB@%'%@AE@%%@NL@%
  14331. %@AB@%'  Return Value:%@AE@%%@NL@%
  14332. %@AB@%'     The number of fonts actually registered%@AE@%%@NL@%
  14333. %@AB@%'%@AE@%%@NL@%
  14334. %@AB@%'=================================================================%@AE@%%@NL@%
  14335. FUNCTION flDoNextResource (Align%, FileName$, FileNum%) STATIC%@NL@%
  14336. DIM ResID AS ResType, Entry AS ResEntry%@NL@%
  14337. %@NL@%
  14338. %@AB@%' Get the first few bytes identifying the resource type and the number%@AE@%%@NL@%
  14339. %@AB@%' of this type:%@AE@%%@NL@%
  14340. GET FileNum%, , ResID%@NL@%
  14341. %@NL@%
  14342. %@AB@%' If this is not the last resource then process it:%@AE@%%@NL@%
  14343. IF ResID.TypeID <> 0 THEN%@NL@%
  14344. %@NL@%
  14345. %@AB@%        ' Loop through the entries of this resource and if an entry happens to be%@AE@%%@NL@%
  14346. %@AB@%        ' a font resource then register it. The file location must be saved%@AE@%%@NL@%
  14347. %@AB@%        ' for each entry in the resource table since the flRegisterFont%@AE@%%@NL@%
  14348. %@AB@%        ' routine may go to some other part of the file to read the resource:%@AE@%%@NL@%
  14349.         FOR ResourceEntry = 1 TO ResID.NumResource%@NL@%
  14350. %@NL@%
  14351.                 GET FileNum%, , Entry%@NL@%
  14352.                 NextResLoc# = SEEK(FileNum%)%@NL@%
  14353.                 IF ResID.TypeID = cFontResource THEN%@NL@%
  14354. %@NL@%
  14355. %@AB@%                        ' Seek to font information, register it, then seek back to%@AE@%%@NL@%
  14356. %@AB@%                        ' the next resource table entry:%@AE@%%@NL@%
  14357.                         SEEK FileNum%, Entry.AddrOffset * 2 ^ Align% + 1%@NL@%
  14358.                         flRegisterFont FileName$, FileNum%%@NL@%
  14359.                         SEEK FileNum%, NextResLoc#%@NL@%
  14360.                         IF FontErr <> 0 THEN EXIT FUNCTION%@NL@%
  14361. %@NL@%
  14362.                 END IF%@NL@%
  14363. %@NL@%
  14364.         NEXT ResourceEntry%@NL@%
  14365. END IF%@NL@%
  14366. %@NL@%
  14367. %@AB@%' Return the current resource type so that RegisterFonts knows when the%@AE@%%@NL@%
  14368. %@AB@%' last resource has been read:%@AE@%%@NL@%
  14369. flDoNextResource = ResID.TypeID%@NL@%
  14370. %@NL@%
  14371. END FUNCTION%@NL@%
  14372. %@NL@%
  14373. %@AB@%'=== flGetBASICScrnSize - Returns screen size for specified BASIC screen mode%@AE@%%@NL@%
  14374. %@AB@%'%@AE@%%@NL@%
  14375. %@AB@%'  Arguments:%@AE@%%@NL@%
  14376. %@AB@%'%@AE@%%@NL@%
  14377. %@AB@%'     ScrnMode%   -  BASIC screen mode%@AE@%%@NL@%
  14378. %@AB@%'%@AE@%%@NL@%
  14379. %@AB@%'     XPixels%    -  Number of pixels in horizontal direction%@AE@%%@NL@%
  14380. %@AB@%'%@AE@%%@NL@%
  14381. %@AB@%'     YPixels%    -  Number of pixels in vertical direction%@AE@%%@NL@%
  14382. %@AB@%'%@AE@%%@NL@%
  14383. %@AB@%'=================================================================%@AE@%%@NL@%
  14384. SUB flGetBASICScrnSize (ScrnMode%, XPixels%, YPixels%) STATIC%@NL@%
  14385.         SELECT CASE ScrnMode%%@NL@%
  14386.                 CASE 1: XPixels% = 320: YPixels% = 200%@NL@%
  14387.                 CASE 2: XPixels% = 640: YPixels% = 200%@NL@%
  14388.                 CASE 3: XPixels% = 720: YPixels% = 348%@NL@%
  14389.                 CASE 4: XPixels% = 640: YPixels% = 400%@NL@%
  14390.                 CASE 7: XPixels% = 320: YPixels% = 200%@NL@%
  14391.                 CASE 8: XPixels% = 640: YPixels% = 200%@NL@%
  14392.                 CASE 9: XPixels% = 640: YPixels% = 350%@NL@%
  14393.                 CASE 10: XPixels% = 640: YPixels% = 350%@NL@%
  14394.                 CASE 11: XPixels% = 640: YPixels% = 480%@NL@%
  14395.                 CASE 12: XPixels% = 640: YPixels% = 480%@NL@%
  14396.                 CASE 13: XPixels% = 320: YPixels% = 200%@NL@%
  14397.                 CASE ELSE: XPixels% = 0: YPixels% = 0%@NL@%
  14398.         END SELECT%@NL@%
  14399. END SUB%@NL@%
  14400. %@NL@%
  14401. %@AB@%'=== flGetCurrentScrnSize - Returns screen size for current screen mode%@AE@%%@NL@%
  14402. %@AB@%'%@AE@%%@NL@%
  14403. %@AB@%'  Arguments:%@AE@%%@NL@%
  14404. %@AB@%'%@AE@%%@NL@%
  14405. %@AB@%'     XPixels%    -  Number of pixels in horizontal direction%@AE@%%@NL@%
  14406. %@AB@%'%@AE@%%@NL@%
  14407. %@AB@%'     YPixels%    -  Number of pixels in vertical direction%@AE@%%@NL@%
  14408. %@AB@%'%@AE@%%@NL@%
  14409. %@AB@%'=================================================================%@AE@%%@NL@%
  14410. SUB flGetCurrentScrnSize (XPixels%, YPixels%) STATIC%@NL@%
  14411. DIM Regs AS RegType%@NL@%
  14412. %@NL@%
  14413. %@AB@%' Use DOS interrupt to get current video display mode:%@AE@%%@NL@%
  14414. Regs.ax = &HF00%@NL@%
  14415. CALL INTERRUPT(&H10, Regs, Regs)%@NL@%
  14416. %@NL@%
  14417. %@AB@%' Set screen size based on mode:%@AE@%%@NL@%
  14418. SELECT CASE Regs.ax MOD 256%@NL@%
  14419.         CASE &H4: XPixels% = 320: YPixels% = 200%@NL@%
  14420.         CASE &H5: XPixels% = 320: YPixels% = 200%@NL@%
  14421.         CASE &H6: XPixels% = 640: YPixels% = 200%@NL@%
  14422.         CASE &H7: XPixels% = 720: YPixels% = 350%@NL@%
  14423.         CASE &H8: XPixels% = 720: YPixels% = 348     ' Hercules%@NL@%
  14424.         CASE &HD: XPixels% = 320: YPixels% = 200%@NL@%
  14425.         CASE &HE: XPixels% = 640: YPixels% = 200%@NL@%
  14426.         CASE &HF: XPixels% = 640: YPixels% = 350%@NL@%
  14427.         CASE &H10: XPixels% = 640: YPixels% = 350%@NL@%
  14428.         CASE &H11: XPixels% = 640: YPixels% = 480%@NL@%
  14429.         CASE &H12: XPixels% = 640: YPixels% = 480%@NL@%
  14430.         CASE &H13: XPixels% = 320: YPixels% = 200%@NL@%
  14431.         CASE &H40: XPixels% = 640: YPixels% = 400    ' Olivetti%@NL@%
  14432.         CASE ELSE: XPixels% = 0: YPixels = 0%@NL@%
  14433. END SELECT%@NL@%
  14434. END SUB%@NL@%
  14435. %@NL@%
  14436. %@AB@%'=== flGetFonts - Gets fonts specified in FontLoadList%@AE@%%@NL@%
  14437. %@AB@%'%@AE@%%@NL@%
  14438. %@AB@%'  Arguments:%@AE@%%@NL@%
  14439. %@AB@%'     NFonts%  -  Number of fonts to load%@AE@%%@NL@%
  14440. %@AB@%'%@AE@%%@NL@%
  14441. %@AB@%'  Return Values:%@AE@%%@NL@%
  14442. %@AB@%'     Number of fonts successfully loaded%@AE@%%@NL@%
  14443. %@AB@%'%@AE@%%@NL@%
  14444. %@AB@%'=================================================================%@AE@%%@NL@%
  14445. FUNCTION flGetFonts (NFonts%) STATIC%@NL@%
  14446. SHARED FGP AS GlobalParams%@NL@%
  14447. SHARED FontHdrReg() AS IFontInfo%@NL@%
  14448. SHARED FontHdrLoaded() AS IFontInfo%@NL@%
  14449. SHARED FontLoadList() AS INTEGER%@NL@%
  14450. %@NL@%
  14451. %@AB@%' Re-dimension font data buffer to fit all the fonts:%@AE@%%@NL@%
  14452. flSizeFontBuffer (NFonts%)%@NL@%
  14453. IF FontErr = cNoFontMem THEN EXIT FUNCTION%@NL@%
  14454. %@NL@%
  14455. %@AB@%' Clear the font status variables then load the fonts (the status variable%@AE@%%@NL@%
  14456. %@AB@%' is used to record which ones have already been loaded so they aren't%@AE@%%@NL@%
  14457. %@AB@%' loaded more than once):%@AE@%%@NL@%
  14458. flClearFontStatus%@NL@%
  14459. FOR Font% = 1 TO NFonts%%@NL@%
  14460.         FontNum% = FontLoadList(Font%)%@NL@%
  14461. %@NL@%
  14462. %@AB@%        ' If font already loaded then just copy the already-filled-out header%@AE@%%@NL@%
  14463. %@AB@%        ' to the new slot:%@AE@%%@NL@%
  14464.         IF FontHdrReg(FontNum%).Status <> 0 THEN%@NL@%
  14465.                 FontHdrLoaded(Font%) = FontHdrLoaded(FontHdrReg(FontNum%).Status)%@NL@%
  14466. %@NL@%
  14467. %@AB@%        ' Otherwise, read the font and update status in registered version%@AE@%%@NL@%
  14468. %@AB@%        ' to point to the first slot it was loaded into (so we can go get%@AE@%%@NL@%
  14469. %@AB@%        ' an already-filled-out header from there):%@AE@%%@NL@%
  14470.         ELSE%@NL@%
  14471.                 FontHdrLoaded(Font%) = FontHdrReg(FontNum%)%@NL@%
  14472. %@NL@%
  14473. %@AB@%                ' Hold any existing errors:%@AE@%%@NL@%
  14474.                 HoldErr% = FontErr%@NL@%
  14475.                 flClearFontErr%@NL@%
  14476. %@NL@%
  14477.                 flReadFont Font%%@NL@%
  14478. %@NL@%
  14479. %@AB@%                ' If there was an error in reading font, exit. Otherwise,%@AE@%%@NL@%
  14480. %@AB@%                ' reset the error to what it was before and continue:%@AE@%%@NL@%
  14481.                 IF FontErr <> 0 THEN%@NL@%
  14482.                         flGetFonts = FontNum% - 1%@NL@%
  14483.                         EXIT FUNCTION%@NL@%
  14484.                 ELSE%@NL@%
  14485.                         flSetFontErr HoldErr%%@NL@%
  14486.                 END IF%@NL@%
  14487. %@NL@%
  14488.                 FontHdrReg(FontNum%).Status = Font%%@NL@%
  14489.         END IF%@NL@%
  14490. NEXT Font%%@NL@%
  14491. %@NL@%
  14492. flGetFonts = NFonts%%@NL@%
  14493. END FUNCTION%@NL@%
  14494. %@NL@%
  14495. %@AB@%'=== flGetNextSpec - Parses the next spec from the spec string%@AE@%%@NL@%
  14496. %@AB@%'%@AE@%%@NL@%
  14497. %@AB@%'  Arguments:%@AE@%%@NL@%
  14498. %@AB@%'     SpecTxt$ -  String containing font specifications%@AE@%%@NL@%
  14499. %@AB@%'%@AE@%%@NL@%
  14500. %@AB@%'     ChPos%   -  Current position in string (updated in this routine)%@AE@%%@NL@%
  14501. %@AB@%'%@AE@%%@NL@%
  14502. %@AB@%'     Spec     -  Structure to contain parsed values%@AE@%%@NL@%
  14503. %@AB@%'%@AE@%%@NL@%
  14504. %@AB@%'%@AE@%%@NL@%
  14505. %@AB@%'  Return Values:%@AE@%%@NL@%
  14506. %@AB@%'     0    -  Spec was found%@AE@%%@NL@%
  14507. %@AB@%'%@AE@%%@NL@%
  14508. %@AB@%'     1    -  No spec found%@AE@%%@NL@%
  14509. %@AB@%'%@AE@%%@NL@%
  14510. %@AB@%'     2    -  Invalid spec found%@AE@%%@NL@%
  14511. %@AB@%'=================================================================%@AE@%%@NL@%
  14512. FUNCTION flGetNextSpec (SpecTxt$, ChPos%, Spec AS FontSpec) STATIC%@NL@%
  14513. %@NL@%
  14514. %@AB@%' Initialize some things:%@AE@%%@NL@%
  14515. SpecErr = cFALSE%@NL@%
  14516. SpecLen% = LEN(SpecTxt$)%@NL@%
  14517. %@NL@%
  14518. %@AB@%' If character pos starts past end of spec then we're done:%@AE@%%@NL@%
  14519. IF ChPos% > SpecLen% THEN%@NL@%
  14520.         flGetNextSpec = 1%@NL@%
  14521.         EXIT FUNCTION%@NL@%
  14522. END IF%@NL@%
  14523. %@NL@%
  14524. DO UNTIL ChPos% > SpecLen%%@NL@%
  14525. %@NL@%
  14526.         Param$ = UCASE$(MID$(SpecTxt$, ChPos%, 1))%@NL@%
  14527.         ChPos% = ChPos% + 1%@NL@%
  14528. %@NL@%
  14529.         SELECT CASE Param$%@NL@%
  14530. %@NL@%
  14531. %@AB@%                ' Skip blanks:%@AE@%%@NL@%
  14532.                 CASE " ":%@NL@%
  14533. %@NL@%
  14534. %@AB@%                ' Font title:%@AE@%%@NL@%
  14535.                 CASE "T":%@NL@%
  14536. %@NL@%
  14537. %@AB@%                        ' Scan for font title until blank or end of string:%@AE@%%@NL@%
  14538.                         StartPos% = ChPos%%@NL@%
  14539.                         DO UNTIL ChPos% > SpecLen%%@NL@%
  14540.                                 Char$ = MID$(SpecTxt$, ChPos%, 1)%@NL@%
  14541.                                 ChPos% = ChPos% + 1%@NL@%
  14542.                         LOOP%@NL@%
  14543. %@NL@%
  14544. %@AB@%                        ' Extract the title:%@AE@%%@NL@%
  14545.                         TitleLen% = ChPos% - StartPos%%@NL@%
  14546.                         IF TitleLen% <= 0 THEN%@NL@%
  14547.                                 SpecErr = cTRUE%@NL@%
  14548.                         ELSE%@NL@%
  14549.                                 Spec.FaceName = MID$(SpecTxt$, StartPos%, TitleLen%)%@NL@%
  14550.                         END IF%@NL@%
  14551. %@NL@%
  14552. %@AB@%                ' Fixed or Proportional font:%@AE@%%@NL@%
  14553.                 CASE "F", "P":%@NL@%
  14554.                         Spec.Pitch = Param$%@NL@%
  14555. %@NL@%
  14556. %@AB@%                ' Font Size (default to 12 points):%@AE@%%@NL@%
  14557.                 CASE "S":%@NL@%
  14558.                         Spec.PointSize = flGetNum(SpecTxt$, ChPos%, 12, SpecErr)%@NL@%
  14559. %@NL@%
  14560. %@AB@%                ' Screen Mode:%@AE@%%@NL@%
  14561.                 CASE "M":%@NL@%
  14562.                         Spec.ScrnMode = flGetNum(SpecTxt$, ChPos%, -1, SpecErr)%@NL@%
  14563. %@NL@%
  14564. %@AB@%                ' Pixel Height:%@AE@%%@NL@%
  14565.                 CASE "H":%@NL@%
  14566.                         Spec.Height = flGetNum(SpecTxt$, ChPos%, 0, SpecErr)%@NL@%
  14567. %@NL@%
  14568. %@AB@%                ' Best fit:%@AE@%%@NL@%
  14569.                 CASE "B":%@NL@%
  14570.                         Spec.Best = cTRUE%@NL@%
  14571. %@NL@%
  14572. %@AB@%                ' Registered font number:%@AE@%%@NL@%
  14573.                 CASE "N":%@NL@%
  14574.                         Spec.RegNum = flGetNum(SpecTxt$, ChPos%, 0, SpecErr)%@NL@%
  14575. %@NL@%
  14576. %@AB@%                ' Font in memory:%@AE@%%@NL@%
  14577.                 CASE "R":%@NL@%
  14578.                         Spec.InMemory = cTRUE%@NL@%
  14579. %@NL@%
  14580. %@AB@%                ' Spec separator:%@AE@%%@NL@%
  14581.                 CASE "/":%@NL@%
  14582.                         EXIT DO%@NL@%
  14583. %@NL@%
  14584. %@AB@%                ' Anything else is an error:%@AE@%%@NL@%
  14585.                 CASE ELSE:%@NL@%
  14586.                         SpecErr = cTRUE%@NL@%
  14587.                         ChPos% = ChPos% + 1%@NL@%
  14588.         END SELECT%@NL@%
  14589. LOOP%@NL@%
  14590. %@NL@%
  14591. %@AB@%' Spec is parsed, make sure a valid screen mode has been specified and%@AE@%%@NL@%
  14592. %@AB@%' adjust point sizes for 320x200 screens if necessary:%@AE@%%@NL@%
  14593. IF Spec.PointSize <> 0 THEN%@NL@%
  14594. %@NL@%
  14595. %@AB@%        ' Get screen size for specified mode (with "M" param) or current%@AE@%%@NL@%
  14596. %@AB@%        ' screen mode:%@AE@%%@NL@%
  14597.         IF Spec.ScrnMode < 0 THEN%@NL@%
  14598.                 flGetCurrentScrnSize XPixels%, YPixels%%@NL@%
  14599.         ELSE%@NL@%
  14600.                 flGetBASICScrnSize Spec.ScrnMode, XPixels%, YPixels%%@NL@%
  14601.         END IF%@NL@%
  14602. %@NL@%
  14603. %@AB@%        ' If this isn't a graphics mode then set an error and skip the rest:%@AE@%%@NL@%
  14604.         IF XPixels% = 0 THEN%@NL@%
  14605.                 SpecErr = cTRUE%@NL@%
  14606.                 Spec.PointSize = 0%@NL@%
  14607. %@NL@%
  14608. %@AB@%        ' If this is a 320x200 screen mode adjust point sizes to the%@AE@%%@NL@%
  14609. %@AB@%        ' equivalent EGA font point sizes. Also set the horizontal%@AE@%%@NL@%
  14610. %@AB@%        ' a vertical resolutions to search for in fonts (horizontal is%@AE@%%@NL@%
  14611. %@AB@%        ' 96 for all modes, vertical varies):%@AE@%%@NL@%
  14612.         ELSE%@NL@%
  14613. %@NL@%
  14614. %@AB@%                ' Use a horizontal resolution of 96 for all screens:%@AE@%%@NL@%
  14615.                 Spec.HorizRes = 96%@NL@%
  14616. %@NL@%
  14617.                 IF XPixels% = 320 THEN%@NL@%
  14618.                         Spec.VertRes = 72%@NL@%
  14619. %@NL@%
  14620. %@AB@%                        ' In a 320x200 mode scale point sizes to their equivalent%@AE@%%@NL@%
  14621. %@AB@%                        ' EGA fonts (special case 14 and 24 point fonts to map them%@AE@%%@NL@%
  14622. %@AB@%                        ' to the closest EGA font otherwise multiply point size by%@AE@%%@NL@%
  14623. %@AB@%                        ' 2/3:%@AE@%%@NL@%
  14624.                         SELECT CASE Spec.PointSize%@NL@%
  14625.                                 CASE 14: Spec.PointSize = 10%@NL@%
  14626.                                 CASE 24: Spec.PointSize = 18%@NL@%
  14627.                                 CASE ELSE: Spec.PointSize = Spec.PointSize * 2 / 3%@NL@%
  14628.                         END SELECT%@NL@%
  14629. %@NL@%
  14630.                 ELSE%@NL@%
  14631. %@NL@%
  14632. %@AB@%                        ' Other screen modes vary only in vertical resolution:%@AE@%%@NL@%
  14633.                         SELECT CASE YPixels%%@NL@%
  14634.                                 CASE 200: Spec.VertRes = 48%@NL@%
  14635.                                 CASE 350: Spec.VertRes = 72%@NL@%
  14636.                                 CASE 480: Spec.VertRes = 96%@NL@%
  14637.                         END SELECT%@NL@%
  14638.                 END IF%@NL@%
  14639.         END IF%@NL@%
  14640. END IF%@NL@%
  14641. %@NL@%
  14642. %@AB@%' If an error was found somewhere then pass it on and set-up to load%@AE@%%@NL@%
  14643. %@AB@%' first font:%@AE@%%@NL@%
  14644. IF SpecErr THEN%@NL@%
  14645.         flGetNextSpec = 2%@NL@%
  14646.         Spec.RegNum = 1%@NL@%
  14647. ELSE%@NL@%
  14648.         flGetNextSpec = 0%@NL@%
  14649. END IF%@NL@%
  14650. %@NL@%
  14651. END FUNCTION%@NL@%
  14652. %@NL@%
  14653. %@AB@%'=== flGetNum - Parses number from string%@AE@%%@NL@%
  14654. %@AB@%'%@AE@%%@NL@%
  14655. %@AB@%'  Arguments:%@AE@%%@NL@%
  14656. %@AB@%'     Txt$     -  String from which to parse number%@AE@%%@NL@%
  14657. %@AB@%'%@AE@%%@NL@%
  14658. %@AB@%'     ChPos%   -  Character position on which to start%@AE@%%@NL@%
  14659. %@AB@%'%@AE@%%@NL@%
  14660. %@AB@%'     Default  -  Default value if number not found%@AE@%%@NL@%
  14661. %@AB@%'%@AE@%%@NL@%
  14662. %@AB@%'     ErrV     -  Returns error as cTrue or cFalse%@AE@%%@NL@%
  14663. %@AB@%'%@AE@%%@NL@%
  14664. %@AB@%'  Return Values:%@AE@%%@NL@%
  14665. %@AB@%'     Returns value found or default%@AE@%%@NL@%
  14666. %@AB@%'%@AE@%%@NL@%
  14667. %@AB@%'  Notes:%@AE@%%@NL@%
  14668. %@AB@%'     Simple state machine:%@AE@%%@NL@%
  14669. %@AB@%'        state 0: Looking for first char%@AE@%%@NL@%
  14670. %@AB@%'        state 1: Found start (+, -, or digit)%@AE@%%@NL@%
  14671. %@AB@%'        state 2: Done%@AE@%%@NL@%
  14672. %@AB@%'        state 3: Error%@AE@%%@NL@%
  14673. %@AB@%'%@AE@%%@NL@%
  14674. %@AB@%'=================================================================%@AE@%%@NL@%
  14675. FUNCTION flGetNum (Txt$, ChPos%, Default, ErrV) STATIC%@NL@%
  14676. %@NL@%
  14677. %@AB@%' Start in state 0%@AE@%%@NL@%
  14678. State = 0%@NL@%
  14679. %@NL@%
  14680. %@AB@%' Loop until done%@AE@%%@NL@%
  14681. DO%@NL@%
  14682.         Char$ = MID$(Txt$, ChPos%, 1)%@NL@%
  14683.         SELECT CASE Char$%@NL@%
  14684. %@NL@%
  14685. %@AB@%                ' Plus and minus are only OK at the beginning:%@AE@%%@NL@%
  14686.                 CASE "+", "-":%@NL@%
  14687.                         SELECT CASE State%@NL@%
  14688.                                 CASE 0: Start% = ChPos%: State = 1%@NL@%
  14689.                                 CASE ELSE: State = 3%@NL@%
  14690.                         END SELECT%@NL@%
  14691. %@NL@%
  14692. %@AB@%                ' Digits are OK at the beginning of after plus and minus:%@AE@%%@NL@%
  14693.                 CASE "0" TO "9":%@NL@%
  14694.                         SELECT CASE State%@NL@%
  14695.                                 CASE 0: Start% = ChPos%: State = 1%@NL@%
  14696.                                 CASE ELSE:%@NL@%
  14697.                         END SELECT%@NL@%
  14698. %@NL@%
  14699. %@AB@%                ' Spaces are skipped:%@AE@%%@NL@%
  14700.                 CASE " ":%@NL@%
  14701. %@NL@%
  14702. %@AB@%                ' Anything else is an error at the beginning or marks the end:%@AE@%%@NL@%
  14703.                 CASE ELSE:%@NL@%
  14704.                         SELECT CASE State%@NL@%
  14705.                                 CASE 0: State = 3%@NL@%
  14706.                                 CASE 1: State = 2%@NL@%
  14707.                         END SELECT%@NL@%
  14708.         END SELECT%@NL@%
  14709. %@NL@%
  14710. %@AB@%        ' Go to next character:%@AE@%%@NL@%
  14711.         ChPos% = ChPos% + 1%@NL@%
  14712. LOOP UNTIL State = 2 OR State = 3%@NL@%
  14713. %@NL@%
  14714. %@AB@%' Scanning is complete; adjust ChPos% to mark last character processed:%@AE@%%@NL@%
  14715. ChPos% = ChPos% - 1%@NL@%
  14716. %@NL@%
  14717. %@AB@%' If error then set default number:%@AE@%%@NL@%
  14718. IF State = 3 THEN%@NL@%
  14719.         flGetNum = Default%@NL@%
  14720.         ErrV = cTRUE%@NL@%
  14721. %@NL@%
  14722. %@AB@%' Otherwise, extract number and get its value:%@AE@%%@NL@%
  14723. ELSE%@NL@%
  14724.         EndPos% = ChPos% - 1%@NL@%
  14725.         flGetNum = VAL(MID$(Txt$, Start%, EndPos%))%@NL@%
  14726.         ErrV = cFALSE%@NL@%
  14727. END IF%@NL@%
  14728. END FUNCTION%@NL@%
  14729. %@NL@%
  14730. %@AB@%'=== flInitSpec - Initializes font specification structure%@AE@%%@NL@%
  14731. %@AB@%'%@AE@%%@NL@%
  14732. %@AB@%'  Arguments:%@AE@%%@NL@%
  14733. %@AB@%'     Spec     -  FontSpec variable to initialize%@AE@%%@NL@%
  14734. %@AB@%'%@AE@%%@NL@%
  14735. %@AB@%'=================================================================%@AE@%%@NL@%
  14736. SUB flInitSpec (Spec AS FontSpec) STATIC%@NL@%
  14737. %@NL@%
  14738.         Spec.FaceName = ""%@NL@%
  14739.         Spec.Pitch = ""%@NL@%
  14740.         Spec.PointSize = 0%@NL@%
  14741.         Spec.ScrnMode = -1%@NL@%
  14742.         Spec.Height = 0%@NL@%
  14743.         Spec.Best = cFALSE%@NL@%
  14744.         Spec.RegNum = 0%@NL@%
  14745.         Spec.InMemory = cFALSE%@NL@%
  14746. %@NL@%
  14747. END SUB%@NL@%
  14748. %@NL@%
  14749. %@AB@%'=== flMatchFont - Finds first registered font that matches FontSpec%@AE@%%@NL@%
  14750. %@AB@%'%@AE@%%@NL@%
  14751. %@AB@%'  Arguments:%@AE@%%@NL@%
  14752. %@AB@%'     FSpec -  FontSpec variable containing specification to match%@AE@%%@NL@%
  14753. %@AB@%'%@AE@%%@NL@%
  14754. %@AB@%'  Return Values:%@AE@%%@NL@%
  14755. %@AB@%'     Number of registered font matched, -1 if no match.%@AE@%%@NL@%
  14756. %@AB@%'%@AE@%%@NL@%
  14757. %@AB@%'=================================================================%@AE@%%@NL@%
  14758. FUNCTION flMatchFont (FSpec AS FontSpec) STATIC%@NL@%
  14759. SHARED FGP AS GlobalParams%@NL@%
  14760. SHARED FontHdrReg() AS IFontInfo%@NL@%
  14761. %@NL@%
  14762. %@AB@%' Match a specific registered font:%@AE@%%@NL@%
  14763. IF FSpec.RegNum > 0 AND FSpec.RegNum <= FGP.TotalRegistered THEN%@NL@%
  14764.         flMatchFont = FSpec.RegNum%@NL@%
  14765.         EXIT FUNCTION%@NL@%
  14766. END IF%@NL@%
  14767. %@NL@%
  14768. %@AB@%' If this is an invalid spec. then no fonts matched:%@AE@%%@NL@%
  14769. IF FontErr <> 0 THEN%@NL@%
  14770.         flMatchFont = -1%@NL@%
  14771.         EXIT FUNCTION%@NL@%
  14772. END IF%@NL@%
  14773. %@NL@%
  14774. %@AB@%' Scan font for first one that matches the rest of the specs:%@AE@%%@NL@%
  14775. SelectedFont% = -1%@NL@%
  14776. BestSizeDiff = 3.402823E+38%@NL@%
  14777. BestFontNum% = -1%@NL@%
  14778. FOR FontNum% = 1 TO FGP.TotalRegistered%@NL@%
  14779. %@NL@%
  14780. %@AB@%        ' Match a font from memory:%@AE@%%@NL@%
  14781.         MemOK% = cTRUE%@NL@%
  14782.         IF FSpec.InMemory AND FontHdrReg(FontNum%).FontSource <> cMemFont THEN%@NL@%
  14783.                 MemOK% = cFALSE%@NL@%
  14784.         END IF%@NL@%
  14785. %@NL@%
  14786. %@AB@%        ' Match name:%@AE@%%@NL@%
  14787.         IF FSpec.FaceName = FontHdrReg(FontNum%).FaceName OR LTRIM$(FSpec.FaceName) = "" THEN%@NL@%
  14788.                 NameOK% = cTRUE%@NL@%
  14789.         ELSE%@NL@%
  14790.                 NameOK% = cFALSE%@NL@%
  14791.         END IF%@NL@%
  14792. %@NL@%
  14793. %@AB@%        ' Match pitch (fixed or proportional):%@AE@%%@NL@%
  14794.         Pitch$ = "F"%@NL@%
  14795.         IF FontHdrReg(FontNum%).FontHeader.dfPixWidth = 0 THEN Pitch$ = "P"%@NL@%
  14796.         IF FSpec.Pitch = Pitch$ OR FSpec.Pitch = " " THEN%@NL@%
  14797.                 PitchOK% = cTRUE%@NL@%
  14798.         ELSE%@NL@%
  14799.                 PitchOK% = cFALSE%@NL@%
  14800.         END IF%@NL@%
  14801. %@NL@%
  14802. %@AB@%        ' Match font size (if neither point or pixel size specified then%@AE@%%@NL@%
  14803. %@AB@%        ' this font is OK):%@AE@%%@NL@%
  14804.         IF FSpec.PointSize = 0 AND FSpec.Height = 0 THEN%@NL@%
  14805.                 SizeOK% = cTRUE%@NL@%
  14806. %@NL@%
  14807. %@AB@%        ' Otherwise, if point size specified (note that point size overrides%@AE@%%@NL@%
  14808. %@AB@%        ' the pixel height if they were both specified)...%@AE@%%@NL@%
  14809.         ELSEIF FSpec.PointSize <> 0 THEN%@NL@%
  14810. %@NL@%
  14811. %@AB@%                ' Make sure the font resolution matches the screen resolution%@AE@%%@NL@%
  14812. %@AB@%                ' (pass over this font if not):%@AE@%%@NL@%
  14813.                 IF FSpec.HorizRes <> FontHdrReg(FontNum%).FontHeader.dfHorizRes THEN%@NL@%
  14814.                         SizeOK% = cFALSE%@NL@%
  14815.                 ELSEIF FSpec.VertRes <> FontHdrReg(FontNum%).FontHeader.dfVertRes THEN%@NL@%
  14816.                         SizeOK% = cFALSE%@NL@%
  14817. %@NL@%
  14818. %@AB@%                ' Font has made it past the resolution check, now try to match size:%@AE@%%@NL@%
  14819.                 ELSE%@NL@%
  14820.                         SizeDiff = ABS(FSpec.PointSize - FontHdrReg(FontNum%).FontHeader.dfPoints)%@NL@%
  14821.                         IF SizeDiff = 0 THEN%@NL@%
  14822.                                 SizeOK% = cTRUE%@NL@%
  14823.                         ELSE%@NL@%
  14824.                                 SizeOK% = cFALSE%@NL@%
  14825.                         END IF%@NL@%
  14826.                 END IF%@NL@%
  14827. %@NL@%
  14828. %@NL@%
  14829. %@AB@%        ' Now, the case where height was specified and not point size:%@AE@%%@NL@%
  14830.         ELSEIF FSpec.Height <> 0 THEN%@NL@%
  14831.                 SizeDiff = ABS(FSpec.Height - FontHdrReg(FontNum%).FontHeader.dfPixHeight)%@NL@%
  14832.                 IF SizeDiff = 0 THEN%@NL@%
  14833.                         SizeOK% = cTRUE%@NL@%
  14834.                 ELSE%@NL@%
  14835.                         SizeOK% = cFALSE%@NL@%
  14836.                 END IF%@NL@%
  14837.         END IF%@NL@%
  14838. %@NL@%
  14839. %@AB@%        ' Do record keeping if best-fit was specified:%@AE@%%@NL@%
  14840.         IF NOT SizeOK% AND PitchOK% AND FSpec.Best AND SizeDiff < BestSizeDiff THEN%@NL@%
  14841.                 BestSizeDiff = SizeDiff%@NL@%
  14842.                 BestFontNum% = FontNum%%@NL@%
  14843.         END IF%@NL@%
  14844. %@NL@%
  14845. %@AB@%        ' See if this font is OK:%@AE@%%@NL@%
  14846.         IF MemOK% AND NameOK% AND PitchOK% AND SizeOK% THEN%@NL@%
  14847.                 SelectedFont% = FontNum%%@NL@%
  14848.                 EXIT FOR%@NL@%
  14849.         END IF%@NL@%
  14850. NEXT FontNum%%@NL@%
  14851. %@NL@%
  14852. %@AB@%' If no font was matched and best-fit was specified then select the%@AE@%%@NL@%
  14853. %@AB@%' best font:%@AE@%%@NL@%
  14854. IF SelectedFont% < 0 AND FSpec.Best THEN SelectedFont% = BestFontNum%%@NL@%
  14855. %@NL@%
  14856. %@AB@%' Return the font matched:%@AE@%%@NL@%
  14857. flMatchFont = SelectedFont%%@NL@%
  14858. %@NL@%
  14859. END FUNCTION%@NL@%
  14860. %@NL@%
  14861. %@AB@%'=== flReadFont - Reads font data and sets up font header%@AE@%%@NL@%
  14862. %@AB@%'%@AE@%%@NL@%
  14863. %@AB@%'  Arguments:%@AE@%%@NL@%
  14864. %@AB@%'     I%    -  Slot in loaded fonts to process%@AE@%%@NL@%
  14865. %@AB@%'%@AE@%%@NL@%
  14866. %@AB@%'=================================================================%@AE@%%@NL@%
  14867. SUB flReadFont (I%) STATIC%@NL@%
  14868. SHARED FGP AS GlobalParams%@NL@%
  14869. SHARED FontHdrLoaded() AS IFontInfo%@NL@%
  14870. SHARED FontData() AS FontDataBlock%@NL@%
  14871. %@NL@%
  14872. ON ERROR GOTO UnexpectedErr%@NL@%
  14873. %@NL@%
  14874. %@AB@%' If memory font then it's already in memory:%@AE@%%@NL@%
  14875. IF FontHdrLoaded(I%).FontSource = cMemFont THEN%@NL@%
  14876.         EXIT SUB%@NL@%
  14877. %@NL@%
  14878. %@AB@%' For a font from a file, read it in:%@AE@%%@NL@%
  14879. ELSE%@NL@%
  14880.         DataSize# = FontHdrLoaded(I%).FontHeader.dfSize - cSizeFontHeader%@NL@%
  14881.         NumBlocks% = -INT(-DataSize# / cFontBlockSize)%@NL@%
  14882.         FontHdrLoaded(I%).DataSeg = FGP.NextDataBlock%@NL@%
  14883. %@NL@%
  14884. %@AB@%        ' Get next available file number and open file:%@AE@%%@NL@%
  14885.         FileNum% = FREEFILE%@NL@%
  14886.         OPEN FontHdrLoaded(I%).FileName FOR BINARY AS FileNum%%@NL@%
  14887. %@NL@%
  14888. %@AB@%        ' Read blocks from the font file:%@AE@%%@NL@%
  14889.         DataLoc# = FontHdrLoaded(I%).FileLoc + cSizeFontHeader%@NL@%
  14890.         SEEK FileNum%, DataLoc#%@NL@%
  14891.         FOR BlockNum% = 0 TO NumBlocks% - 1%@NL@%
  14892.                 GET FileNum%, , FontData(FGP.NextDataBlock + BlockNum%)%@NL@%
  14893.         NEXT BlockNum%%@NL@%
  14894. %@NL@%
  14895. %@AB@%        ' Close the file:%@AE@%%@NL@%
  14896.         CLOSE FileNum%%@NL@%
  14897. %@NL@%
  14898. %@AB@%        ' Update the next data block pointer:%@AE@%%@NL@%
  14899.         FGP.NextDataBlock = FGP.NextDataBlock + NumBlocks%%@NL@%
  14900. END IF%@NL@%
  14901. %@NL@%
  14902. END SUB%@NL@%
  14903. %@NL@%
  14904. %@AB@%'=== flRegisterFont - Actually registers a font resource:%@AE@%%@NL@%
  14905. %@AB@%'%@AE@%%@NL@%
  14906. %@AB@%'  Arguments:%@AE@%%@NL@%
  14907. %@AB@%'     FileName$   - Name of font file (passed to routine that actually%@AE@%%@NL@%
  14908. %@AB@%'                   registers resource entry)%@AE@%%@NL@%
  14909. %@AB@%'%@AE@%%@NL@%
  14910. %@AB@%'     FileNum%    - File number for reading%@AE@%%@NL@%
  14911. %@AB@%'%@AE@%%@NL@%
  14912. %@AB@%'=================================================================%@AE@%%@NL@%
  14913. SUB flRegisterFont (FileName$, FileNum%) STATIC%@NL@%
  14914. SHARED FGP AS GlobalParams%@NL@%
  14915. SHARED FontHdrReg() AS IFontInfo%@NL@%
  14916. %@NL@%
  14917. DIM Byte AS STRING * 1, FontHeader AS WFHeader%@NL@%
  14918. %@NL@%
  14919. %@AB@%' Read the font header:%@AE@%%@NL@%
  14920. FontLoc# = SEEK(FileNum%)%@NL@%
  14921. GET FileNum%, , FontHeader%@NL@%
  14922. %@NL@%
  14923. %@AB@%' Only register vector fonts:%@AE@%%@NL@%
  14924. IF FontHeader.dfType AND &H1 <> cBitMapType THEN EXIT SUB%@NL@%
  14925. %@NL@%
  14926. %@AB@%' See that we're still within MaxRegistered limits:%@AE@%%@NL@%
  14927. IF FGP.TotalRegistered >= FGP.MaxRegistered THEN%@NL@%
  14928.         flSetFontErr cTooManyFonts%@NL@%
  14929.         EXIT SUB%@NL@%
  14930. END IF%@NL@%
  14931. %@NL@%
  14932. %@AB@%' Go to next "registered" font slot:%@AE@%%@NL@%
  14933. FGP.TotalRegistered = FGP.TotalRegistered + 1%@NL@%
  14934. %@NL@%
  14935. %@AB@%' Set font source and save the header and file location:%@AE@%%@NL@%
  14936. FontHdrReg(FGP.TotalRegistered).FontSource = cFileFont%@NL@%
  14937. FontHdrReg(FGP.TotalRegistered).FontHeader = FontHeader%@NL@%
  14938. FontHdrReg(FGP.TotalRegistered).FileLoc = FontLoc#%@NL@%
  14939. %@NL@%
  14940. %@AB@%' Get the face name (scan characters until zero byte):%@AE@%%@NL@%
  14941. SEEK FileNum%, FontLoc# + FontHeader.dfFace%@NL@%
  14942. FaceName$ = ""%@NL@%
  14943. FOR Char% = 0 TO cMaxFaceName - 1%@NL@%
  14944.         GET FileNum%, , Byte%@NL@%
  14945.         IF ASC(Byte) = 0 THEN EXIT FOR%@NL@%
  14946.         FaceName$ = FaceName$ + Byte%@NL@%
  14947. NEXT Char%%@NL@%
  14948. FontHdrReg(FGP.TotalRegistered).FaceName = FaceName$%@NL@%
  14949. %@NL@%
  14950. %@AB@%' Finally, save the file name:%@AE@%%@NL@%
  14951. FontHdrReg(FGP.TotalRegistered).FileName = FileName$%@NL@%
  14952. %@NL@%
  14953. END SUB%@NL@%
  14954. %@NL@%
  14955. %@AB@%'=== flSetFontErr - Sets the FontErr variable to an error value:%@AE@%%@NL@%
  14956. %@AB@%'%@AE@%%@NL@%
  14957. %@AB@%'  Arguments:%@AE@%%@NL@%
  14958. %@AB@%'     ErrNum   -  The error number to set FontErr variable to%@AE@%%@NL@%
  14959. %@AB@%'%@AE@%%@NL@%
  14960. %@AB@%'=================================================================%@AE@%%@NL@%
  14961. SUB flSetFontErr (ErrNum AS INTEGER) STATIC%@NL@%
  14962. %@NL@%
  14963.          FontErr = ErrNum%@NL@%
  14964. %@NL@%
  14965. END SUB%@NL@%
  14966. %@NL@%
  14967. %@AB@%'=== flSizeFontBuffer - Calculate the FontBuffer size required for all fonts%@AE@%%@NL@%
  14968. %@AB@%'%@AE@%%@NL@%
  14969. %@AB@%'  Arguments:%@AE@%%@NL@%
  14970. %@AB@%'     NFonts%  -  Number of font to be loaded%@AE@%%@NL@%
  14971. %@AB@%'%@AE@%%@NL@%
  14972. %@AB@%'  Notes:%@AE@%%@NL@%
  14973. %@AB@%'     The use of -INT(-N) in the following code rounds N to the next%@AE@%%@NL@%
  14974. %@AB@%'     larger integer%@AE@%%@NL@%
  14975. %@AB@%'%@AE@%%@NL@%
  14976. %@AB@%'=================================================================%@AE@%%@NL@%
  14977. SUB flSizeFontBuffer (NFonts%) STATIC%@NL@%
  14978. SHARED FGP AS GlobalParams%@NL@%
  14979. SHARED FontHdrReg() AS IFontInfo%@NL@%
  14980. SHARED FontLoadList() AS INTEGER%@NL@%
  14981. SHARED FontData() AS FontDataBlock%@NL@%
  14982. %@NL@%
  14983. %@NL@%
  14984. ON ERROR GOTO UnexpectedErr%@NL@%
  14985. IF NFonts% = 0 THEN EXIT SUB%@NL@%
  14986. %@NL@%
  14987. %@AB@%' Clear font status variables so we know what has been processed:%@AE@%%@NL@%
  14988. flClearFontStatus%@NL@%
  14989. %@NL@%
  14990. %@AB@%' Add sizes of all unique fonts together to get total size (each font%@AE@%%@NL@%
  14991. %@AB@%' begins on a new font block so the size of each font is calculated in%@AE@%%@NL@%
  14992. %@AB@%' terms of the number of font blocks it will take up):%@AE@%%@NL@%
  14993. Size = 0%@NL@%
  14994. FOR I% = 1 TO NFonts%%@NL@%
  14995.         FontNum% = FontLoadList(I%)%@NL@%
  14996.         IF FontHdrReg(FontNum%).Status = 0 THEN%@NL@%
  14997.                 FontSize = FontHdrReg(FontNum%).FontHeader.dfSize - cSizeFontHeader%@NL@%
  14998.                 Size = Size - INT(-FontSize / cFontBlockSize)%@NL@%
  14999.                 FontHdrReg(FontNum%).Status = 1%@NL@%
  15000.         END IF%@NL@%
  15001. NEXT I%%@NL@%
  15002. %@NL@%
  15003. %@AB@%' Dimension the FontData array to hold everything:%@AE@%%@NL@%
  15004. ON ERROR GOTO MemErr%@NL@%
  15005. REDIM FontData(1 TO Size) AS FontDataBlock%@NL@%
  15006. ON ERROR GOTO UnexpectedErr%@NL@%
  15007. %@NL@%
  15008. %@AB@%' Set the next font block to the start for when flReadFont begins%@AE@%%@NL@%
  15009. %@AB@%' putting data in the font buffer:%@AE@%%@NL@%
  15010. FGP.NextDataBlock = 1%@NL@%
  15011. %@NL@%
  15012. END SUB%@NL@%
  15013. %@NL@%
  15014. %@AB@%'=== GetFontInfo - Returns useful information about current font%@AE@%%@NL@%
  15015. %@AB@%'%@AE@%%@NL@%
  15016. %@AB@%'  Arguments:%@AE@%%@NL@%
  15017. %@AB@%'     FI    -  FontInfo type variable to receive info%@AE@%%@NL@%
  15018. %@AB@%'%@AE@%%@NL@%
  15019. %@AB@%'=================================================================%@AE@%%@NL@%
  15020. SUB GetFontInfo (FI AS FontInfo) STATIC%@NL@%
  15021. SHARED FGP AS GlobalParams%@NL@%
  15022. SHARED FontHdrLoaded() AS IFontInfo%@NL@%
  15023. %@NL@%
  15024. ON ERROR GOTO UnexpectedErr%@NL@%
  15025. %@NL@%
  15026. %@AB@%' Clear outstanding font errors:%@AE@%%@NL@%
  15027. flClearFontErr%@NL@%
  15028. %@NL@%
  15029. %@AB@%' Check that some fonts are loaded:%@AE@%%@NL@%
  15030. IF FGP.TotalLoaded <= 0 THEN%@NL@%
  15031.         flSetFontErr cNoFonts%@NL@%
  15032.         EXIT SUB%@NL@%
  15033. END IF%@NL@%
  15034. %@NL@%
  15035. %@AB@%' All OK, assign values from internal font header:%@AE@%%@NL@%
  15036. FI.FontNum = FGP.CurrentFont%@NL@%
  15037. FI.Ascent = FontHdrLoaded(FGP.CurrentFont).FontHeader.dfAscent%@NL@%
  15038. FI.Points = FontHdrLoaded(FGP.CurrentFont).FontHeader.dfPoints%@NL@%
  15039. FI.PixWidth = FontHdrLoaded(FGP.CurrentFont).FontHeader.dfPixWidth%@NL@%
  15040. FI.PixHeight = FontHdrLoaded(FGP.CurrentFont).FontHeader.dfPixHeight%@NL@%
  15041. FI.Leading = FontHdrLoaded(FGP.CurrentFont).FontHeader.dfInternalLeading%@NL@%
  15042. FI.MaxWidth = FontHdrLoaded(FGP.CurrentFont).FontHeader.dfMaxWidth%@NL@%
  15043. FI.AvgWidth = FontHdrLoaded(FGP.CurrentFont).FontHeader.dfAvgWidth%@NL@%
  15044. FI.FileName = FontHdrLoaded(FGP.CurrentFont).FileName%@NL@%
  15045. FI.FaceName = FontHdrLoaded(FGP.CurrentFont).FaceName%@NL@%
  15046. %@NL@%
  15047. END SUB%@NL@%
  15048. %@NL@%
  15049. %@AB@%'=== GetGTextLen - Returns bit length of string%@AE@%%@NL@%
  15050. %@AB@%'%@AE@%%@NL@%
  15051. %@AB@%'  Arguments:%@AE@%%@NL@%
  15052. %@AB@%'     Text$ -  String for which to return length%@AE@%%@NL@%
  15053. %@AB@%'%@AE@%%@NL@%
  15054. %@AB@%'  Return Values:%@AE@%%@NL@%
  15055. %@AB@%'     -1    -  Error (No fonts loaded, probably)%@AE@%%@NL@%
  15056. %@AB@%'%@AE@%%@NL@%
  15057. %@AB@%'     >=0   -  Length of string%@AE@%%@NL@%
  15058. %@AB@%'%@AE@%%@NL@%
  15059. %@AB@%'=================================================================%@AE@%%@NL@%
  15060. FUNCTION GetGTextLen% (Text$) STATIC%@NL@%
  15061. SHARED FGP AS GlobalParams%@NL@%
  15062. SHARED FontHdrLoaded() AS IFontInfo%@NL@%
  15063. SHARED FontData() AS FontDataBlock%@NL@%
  15064. %@NL@%
  15065. ON ERROR GOTO UnexpectedErr%@NL@%
  15066. %@NL@%
  15067. %@AB@%' Clear outstanding font errors:%@AE@%%@NL@%
  15068. flClearFontErr%@NL@%
  15069. %@NL@%
  15070. %@AB@%' Make sure some fonts are loaded:%@AE@%%@NL@%
  15071. IF FGP.TotalLoaded <= 0 THEN%@NL@%
  15072.         flSetFontErr cNoFonts%@NL@%
  15073.         GetGTextLen = -1%@NL@%
  15074.         EXIT FUNCTION%@NL@%
  15075. END IF%@NL@%
  15076. %@NL@%
  15077. %@AB@%' Assume this is a memory font (may override this later):%@AE@%%@NL@%
  15078. CharTblPtr% = FontHdrLoaded(FGP.CurrentFont).DataOffset%@NL@%
  15079. CharTblSeg% = FontHdrLoaded(FGP.CurrentFont).DataSeg%@NL@%
  15080. %@NL@%
  15081. %@AB@%' Index into font data array:%@AE@%%@NL@%
  15082. CharTable% = FontHdrLoaded(FGP.CurrentFont).DataSeg%@NL@%
  15083. %@NL@%
  15084. %@AB@%' Add together the character lengths from the character table:%@AE@%%@NL@%
  15085. TextLen% = 0%@NL@%
  15086. FOR I% = 1 TO LEN(Text$)%@NL@%
  15087. %@NL@%
  15088. %@AB@%        ' Get character code and translate to Ansi if IBM char set is specified:%@AE@%%@NL@%
  15089.         ChVal% = ASC(MID$(Text$, I%, 1))%@NL@%
  15090.         IF FGP.CharSet = cIBMChars THEN ChVal% = flANSI(ChVal%)%@NL@%
  15091. %@NL@%
  15092. %@AB@%        ' Convert to default char if out of range:%@AE@%%@NL@%
  15093.         IF ChVal% < FGP.FChar OR ChVal% > FGP.LChar THEN ChVal% = FGP.DChar%%@NL@%
  15094. %@NL@%
  15095. %@AB@%        ' Offset into character table for length word:%@AE@%%@NL@%
  15096.         CharOffset% = (ChVal% - FGP.FChar) * 4%@NL@%
  15097. %@NL@%
  15098. %@AB@%        ' Peek the data and add it to the text length:%@AE@%%@NL@%
  15099.         IF FontHdrLoaded(FGP.CurrentFont).FontSource = cFileFont THEN%@NL@%
  15100.                 CharTblPtr% = VARPTR(FontData(CharTable%))%@NL@%
  15101.                 CharTblSeg% = VARSEG(FontData(CharTable%))%@NL@%
  15102.         END IF%@NL@%
  15103.         DEF SEG = CharTblSeg%%@NL@%
  15104.         CharLen% = PEEK(CharTblPtr% + CharOffset%) + PEEK(CharTblPtr% + CharOffset% + 1) * 256%@NL@%
  15105.         TextLen% = TextLen% + CharLen%%@NL@%
  15106. NEXT I%%@NL@%
  15107. %@NL@%
  15108. GetGTextLen = TextLen%%@NL@%
  15109. %@NL@%
  15110. END FUNCTION%@NL@%
  15111. %@NL@%
  15112. %@AB@%'=== GetMaxFonts - Gets the maximum number of fonts that can be registered%@AE@%%@NL@%
  15113. %@AB@%'                  and loaded by the font library:%@AE@%%@NL@%
  15114. %@AB@%'%@AE@%%@NL@%
  15115. %@AB@%'  Arguments:%@AE@%%@NL@%
  15116. %@AB@%'     Registered  -  The maximum number of fonts that can be registered%@AE@%%@NL@%
  15117. %@AB@%'                    by the font library%@AE@%%@NL@%
  15118. %@AB@%'%@AE@%%@NL@%
  15119. %@AB@%'     Loaded      -  The maximum number of fonts that can be loaded by%@AE@%%@NL@%
  15120. %@AB@%'                    by the font library%@AE@%%@NL@%
  15121. %@AB@%'%@AE@%%@NL@%
  15122. %@AB@%'=================================================================%@AE@%%@NL@%
  15123. SUB GetMaxFonts (Registered AS INTEGER, Loaded AS INTEGER)%@NL@%
  15124. SHARED FGP AS GlobalParams%@NL@%
  15125. %@NL@%
  15126. ON ERROR GOTO UnexpectedErr%@NL@%
  15127. %@NL@%
  15128. %@AB@%' Clear outstanding font errors:%@AE@%%@NL@%
  15129. flClearFontErr%@NL@%
  15130. %@NL@%
  15131. %@AB@%' If SetMaxFonts hasn't been called then make sure the default is%@AE@%%@NL@%
  15132. %@AB@%' correct:%@AE@%%@NL@%
  15133. flChkMax%@NL@%
  15134. %@NL@%
  15135. %@AB@%' Simply return the values of the internal variables for maximum%@AE@%%@NL@%
  15136. %@AB@%' fonts registered and loaded:%@AE@%%@NL@%
  15137. Registered = FGP.MaxRegistered%@NL@%
  15138. Loaded = FGP.MaxLoaded%@NL@%
  15139. %@NL@%
  15140. END SUB%@NL@%
  15141. %@NL@%
  15142. %@AB@%'=== GetFontInfo - Returns useful information about current font%@AE@%%@NL@%
  15143. %@AB@%'%@AE@%%@NL@%
  15144. %@AB@%'  Arguments:%@AE@%%@NL@%
  15145. %@AB@%'     Font  -  Font number (in list of registered fonts) on which to get%@AE@%%@NL@%
  15146. %@AB@%'              information%@AE@%%@NL@%
  15147. %@AB@%'%@AE@%%@NL@%
  15148. %@AB@%'     FI    -  FontInfo type variable to receive info%@AE@%%@NL@%
  15149. %@AB@%'%@AE@%%@NL@%
  15150. %@AB@%'=================================================================%@AE@%%@NL@%
  15151. SUB GetRFontInfo (Font AS INTEGER, FI AS FontInfo) STATIC%@NL@%
  15152. SHARED FontHdrReg() AS IFontInfo%@NL@%
  15153. %@NL@%
  15154. ON ERROR GOTO UnexpectedErr%@NL@%
  15155. %@NL@%
  15156. %@AB@%' Clear outstanding font errors:%@AE@%%@NL@%
  15157. flClearFontErr%@NL@%
  15158. %@NL@%
  15159. %@AB@%' See that they've specified a valid font:%@AE@%%@NL@%
  15160. IF Font < 0 OR Font > FGP.TotalRegistered THEN%@NL@%
  15161.         flSetFontErr cBadFontNumber%@NL@%
  15162.         EXIT SUB%@NL@%
  15163. END IF%@NL@%
  15164. %@NL@%
  15165. %@AB@%' All OK, assign values from internal font header:%@AE@%%@NL@%
  15166. FI.FontNum = Font%@NL@%
  15167. FI.Ascent = FontHdrReg(Font).FontHeader.dfAscent%@NL@%
  15168. FI.Points = FontHdrReg(Font).FontHeader.dfPoints%@NL@%
  15169. FI.PixWidth = FontHdrReg(Font).FontHeader.dfPixWidth%@NL@%
  15170. FI.PixHeight = FontHdrReg(Font).FontHeader.dfPixHeight%@NL@%
  15171. FI.Leading = FontHdrReg(Font).FontHeader.dfInternalLeading%@NL@%
  15172. FI.MaxWidth = FontHdrReg(Font).FontHeader.dfMaxWidth%@NL@%
  15173. FI.AvgWidth = FontHdrReg(Font).FontHeader.dfAvgWidth%@NL@%
  15174. FI.FileName = FontHdrReg(Font).FileName%@NL@%
  15175. FI.FaceName = FontHdrReg(Font).FaceName%@NL@%
  15176. %@NL@%
  15177. END SUB%@NL@%
  15178. %@NL@%
  15179. %@AB@%'=== GetTotalFonts - Gets the total number of fonts that currently registered%@AE@%%@NL@%
  15180. %@AB@%'                    and loaded by the font library:%@AE@%%@NL@%
  15181. %@AB@%'%@AE@%%@NL@%
  15182. %@AB@%'  Arguments:%@AE@%%@NL@%
  15183. %@AB@%'     Registered  -  The total number of fonts registered by the font%@AE@%%@NL@%
  15184. %@AB@%'                    library%@AE@%%@NL@%
  15185. %@AB@%'%@AE@%%@NL@%
  15186. %@AB@%'     Loaded      -  The total number of fonts loaded by the font library%@AE@%%@NL@%
  15187. %@AB@%'%@AE@%%@NL@%
  15188. %@AB@%'=================================================================%@AE@%%@NL@%
  15189. SUB GetTotalFonts (Registered AS INTEGER, Loaded AS INTEGER)%@NL@%
  15190. SHARED FGP AS GlobalParams%@NL@%
  15191. %@NL@%
  15192. ON ERROR GOTO UnexpectedErr%@NL@%
  15193. %@NL@%
  15194. %@AB@%' Clear outstanding font errors:%@AE@%%@NL@%
  15195. flClearFontErr%@NL@%
  15196. %@NL@%
  15197. %@AB@%' Simply return the values of internal variables:%@AE@%%@NL@%
  15198. Registered = FGP.TotalRegistered%@NL@%
  15199. Loaded = FGP.TotalLoaded%@NL@%
  15200. %@NL@%
  15201. END SUB%@NL@%
  15202. %@NL@%
  15203. %@AB@%'=== GTextWindow - Communicates the current WINDOW to fontlib%@AE@%%@NL@%
  15204. %@AB@%'%@AE@%%@NL@%
  15205. %@AB@%'  Arguments:%@AE@%%@NL@%
  15206. %@AB@%'     X1    -  Minimum X value%@AE@%%@NL@%
  15207. %@AB@%'%@AE@%%@NL@%
  15208. %@AB@%'     Y1    -  Minimum Y value%@AE@%%@NL@%
  15209. %@AB@%'%@AE@%%@NL@%
  15210. %@AB@%'     X2    -  Maximum X value%@AE@%%@NL@%
  15211. %@AB@%'%@AE@%%@NL@%
  15212. %@AB@%'     Y2    -  Maximum Y value%@AE@%%@NL@%
  15213. %@AB@%'%@AE@%%@NL@%
  15214. %@AB@%'     Scrn% -  cTRUE means that window Y values increase top to bottom%@AE@%%@NL@%
  15215. %@AB@%'%@AE@%%@NL@%
  15216. %@AB@%'  Remarks:%@AE@%%@NL@%
  15217. %@AB@%'     Calling this with X1=X2 or Y1=Y2 will clear the current%@AE@%%@NL@%
  15218. %@AB@%'     window.%@AE@%%@NL@%
  15219. %@AB@%'%@AE@%%@NL@%
  15220. %@AB@%'=================================================================%@AE@%%@NL@%
  15221. SUB GTextWindow (X1 AS SINGLE, Y1 AS SINGLE, X2 AS SINGLE, Y2 AS SINGLE, Scrn%)%@NL@%
  15222. SHARED FGP AS GlobalParams%@NL@%
  15223. %@NL@%
  15224. ON ERROR GOTO UnexpectedErr%@NL@%
  15225. %@NL@%
  15226. %@AB@%' Clear outstanding font errors:%@AE@%%@NL@%
  15227. flClearFontErr%@NL@%
  15228. %@NL@%
  15229. %@AB@%' Save the window values in global variable:%@AE@%%@NL@%
  15230. FGP.WX1 = X1%@NL@%
  15231. FGP.WY1 = Y1%@NL@%
  15232. FGP.WX2 = X2%@NL@%
  15233. FGP.WY2 = Y2%@NL@%
  15234. FGP.WScrn = Scrn%%@NL@%
  15235. %@NL@%
  15236. %@AB@%' If window is valid then flag it as set:%@AE@%%@NL@%
  15237. FGP.WindowSet = ((X2 - X1) <> 0) AND ((Y2 - Y1) <> 0)%@NL@%
  15238. %@NL@%
  15239. END SUB%@NL@%
  15240. %@NL@%
  15241. %@AB@%'=== LoadFont - Loads one or more fonts according to specification string%@AE@%%@NL@%
  15242. %@AB@%'%@AE@%%@NL@%
  15243. %@AB@%'  Arguments:%@AE@%%@NL@%
  15244. %@AB@%'     SpecTxt$ -  String containing parameters specifying one or more%@AE@%%@NL@%
  15245. %@AB@%'                 fonts to load (see notes below)%@AE@%%@NL@%
  15246. %@AB@%'%@AE@%%@NL@%
  15247. %@AB@%'  Return Values:%@AE@%%@NL@%
  15248. %@AB@%'     The number of fonts loaded%@AE@%%@NL@%
  15249. %@AB@%'%@AE@%%@NL@%
  15250. %@AB@%'  Notes:%@AE@%%@NL@%
  15251. %@AB@%'     A spec. can contain the following parameters in any order.%@AE@%%@NL@%
  15252. %@AB@%'     Parameters are each one character immediately followed by a value%@AE@%%@NL@%
  15253. %@AB@%'     if called for. Multiple specifications may be entered separated%@AE@%%@NL@%
  15254. %@AB@%'     by slash (/) characters. Loadfont will search for the FIRST font in%@AE@%%@NL@%
  15255. %@AB@%'     the list of registered fonts that matches each spec. and load it. If%@AE@%%@NL@%
  15256. %@AB@%'     no font matches a specification registered font number one will be%@AE@%%@NL@%
  15257. %@AB@%'     used. If a given font is selected by more than one spec in the list%@AE@%%@NL@%
  15258. %@AB@%'     it will only be loaded once. When this routine is called all%@AE@%%@NL@%
  15259. %@AB@%'     previous fonts will be discarded:%@AE@%%@NL@%
  15260. %@AB@%'%@AE@%%@NL@%
  15261. %@AB@%'        T  -  followed by a blank-terminated name loads font by%@AE@%%@NL@%
  15262. %@AB@%'              specified name%@AE@%%@NL@%
  15263. %@AB@%'%@AE@%%@NL@%
  15264. %@AB@%'        F  -  No value. Selects only fixed pitch fonts%@AE@%%@NL@%
  15265. %@AB@%'%@AE@%%@NL@%
  15266. %@AB@%'        P  -  No value. Selects only proportional fonts%@AE@%%@NL@%
  15267. %@AB@%'%@AE@%%@NL@%
  15268. %@AB@%'        S  -  Followed by number specifies desired point size%@AE@%%@NL@%
  15269. %@AB@%'%@AE@%%@NL@%
  15270. %@AB@%'        M  -  Followed by number specifies the screen mode font will be%@AE@%%@NL@%
  15271. %@AB@%'              used on. This is used in conjunction with the "S" parameter%@AE@%%@NL@%
  15272. %@AB@%'              above to select appropriately sized font.%@AE@%%@NL@%
  15273. %@AB@%'%@AE@%%@NL@%
  15274. %@AB@%'        H  -  Followed by number specifies the pixel height of%@AE@%%@NL@%
  15275. %@AB@%'              font to select. "S" overrides this.%@AE@%%@NL@%
  15276. %@AB@%'%@AE@%%@NL@%
  15277. %@AB@%'        N  -  Followed by number selects specific font number%@AE@%%@NL@%
  15278. %@AB@%'              from the list of currently registered fonts.%@AE@%%@NL@%
  15279. %@AB@%'%@AE@%%@NL@%
  15280. %@AB@%'        R  -  Selects font stored in RAM memory%@AE@%%@NL@%
  15281. %@AB@%'%@AE@%%@NL@%
  15282. %@AB@%'=================================================================%@AE@%%@NL@%
  15283. FUNCTION LoadFont% (SpecTxt$) STATIC%@NL@%
  15284. SHARED FGP AS GlobalParams%@NL@%
  15285. DIM FSpec AS FontSpec%@NL@%
  15286. %@NL@%
  15287. ON ERROR GOTO UnexpectedErr%@NL@%
  15288. %@NL@%
  15289. %@AB@%' Clear outstanding errors and check for valid max limits:%@AE@%%@NL@%
  15290. flClearFontErr%@NL@%
  15291. %@NL@%
  15292. flChkMax%@NL@%
  15293. %@NL@%
  15294. %@AB@%' Make sure there's room to load a font:%@AE@%%@NL@%
  15295. IF FGP.TotalLoaded >= FGP.MaxLoaded THEN%@NL@%
  15296.         flSetFontErr cTooManyFonts%@NL@%
  15297.         EXIT FUNCTION%@NL@%
  15298. END IF%@NL@%
  15299. %@NL@%
  15300. %@AB@%' Make sure there are some registered fonts to look through:%@AE@%%@NL@%
  15301. IF FGP.TotalRegistered <= 0 THEN%@NL@%
  15302.         flSetFontErr cNoFonts%@NL@%
  15303.         EXIT FUNCTION%@NL@%
  15304. END IF%@NL@%
  15305. %@NL@%
  15306. %@AB@%' Process each spec in the spec string:%@AE@%%@NL@%
  15307. Slot% = 1%@NL@%
  15308. ChPos% = 1%@NL@%
  15309. DO UNTIL Slot% > FGP.MaxLoaded%@NL@%
  15310. %@NL@%
  15311. %@AB@%        ' Initialize the spec structure:%@AE@%%@NL@%
  15312.         flInitSpec FSpec%@NL@%
  15313. %@NL@%
  15314. %@AB@%        ' Get next spec from string (Found will be false if no spec found):%@AE@%%@NL@%
  15315.         SpecStatus% = flGetNextSpec(SpecTxt$, ChPos%, FSpec)%@NL@%
  15316.         SELECT CASE SpecStatus%%@NL@%
  15317.                 CASE 0:%@NL@%
  15318.                 CASE 1: EXIT DO%@NL@%
  15319.                 CASE 2: flSetFontErr cBadFontSpec%@NL@%
  15320.         END SELECT%@NL@%
  15321. %@NL@%
  15322. %@AB@%        ' Try to match font. Set font to one if none match:%@AE@%%@NL@%
  15323.         FontNum% = flMatchFont(FSpec)%@NL@%
  15324.         IF FontNum% < 1 THEN%@NL@%
  15325.                 flSetFontErr cFontNotFound%@NL@%
  15326.                 FontNum% = 1%@NL@%
  15327.         END IF%@NL@%
  15328. %@NL@%
  15329. %@AB@%        ' Record font in font load list:%@AE@%%@NL@%
  15330.         FontLoadList(Slot%) = FontNum%%@NL@%
  15331.         Slot% = Slot% + 1%@NL@%
  15332. LOOP%@NL@%
  15333. %@NL@%
  15334. %@AB@%' Now actually get the fonts in the load list:%@AE@%%@NL@%
  15335. FGP.TotalLoaded = flGetFonts(Slot% - 1)%@NL@%
  15336. FGP.CurrentFont = 1%@NL@%
  15337. %@NL@%
  15338. %@AB@%' Select the first font by default (pass outstanding font errors around%@AE@%%@NL@%
  15339. %@AB@%' it):%@AE@%%@NL@%
  15340. HoldErr% = FontErr%@NL@%
  15341. SelectFont cDefaultFont%@NL@%
  15342. IF HoldErr% <> 0 THEN flSetFontErr HoldErr%%@NL@%
  15343. %@NL@%
  15344. LoadFont = FGP.TotalLoaded%@NL@%
  15345. %@NL@%
  15346. END FUNCTION%@NL@%
  15347. %@NL@%
  15348. %@AB@%'=== OutGText - Outputs graphics text to the screen%@AE@%%@NL@%
  15349. %@AB@%'%@AE@%%@NL@%
  15350. %@AB@%'  Arguments:%@AE@%%@NL@%
  15351. %@AB@%'     X        -  X location of upper left of char box%@AE@%%@NL@%
  15352. %@AB@%'%@AE@%%@NL@%
  15353. %@AB@%'     Y        -  Y location of upper left of char box%@AE@%%@NL@%
  15354. %@AB@%'%@AE@%%@NL@%
  15355. %@AB@%'     Text$    -  Text string to output%@AE@%%@NL@%
  15356. %@AB@%'%@AE@%%@NL@%
  15357. %@AB@%'  Return Values:%@AE@%%@NL@%
  15358. %@AB@%'     Length of text output, Values of X and Y are updated%@AE@%%@NL@%
  15359. %@AB@%'%@AE@%%@NL@%
  15360. %@AB@%'=================================================================%@AE@%%@NL@%
  15361. FUNCTION OutGText% (X AS SINGLE, Y AS SINGLE, Text$) STATIC%@NL@%
  15362. SHARED FGP AS GlobalParams%@NL@%
  15363. SHARED FontHdrLoaded() AS IFontInfo%@NL@%
  15364. %@NL@%
  15365. ON ERROR GOTO UnexpectedErr%@NL@%
  15366. %@NL@%
  15367. %@AB@%' Clear outstanding font errors:%@AE@%%@NL@%
  15368. flClearFontErr%@NL@%
  15369. %@NL@%
  15370. %@AB@%' Make sure fonts are loaded:%@AE@%%@NL@%
  15371. IF FGP.TotalLoaded <= 0 THEN%@NL@%
  15372.         flSetFontErr cNoFonts%@NL@%
  15373.         EXIT FUNCTION%@NL@%
  15374. END IF%@NL@%
  15375. %@NL@%
  15376. IF NOT FGP.CharColorInit THEN SetGTextColor cDefaultColor%@NL@%
  15377. IF NOT FGP.CharDirInit THEN SetGTextDir cDefaultDir%@NL@%
  15378. %@NL@%
  15379. %@AB@%' Make sure a graphic mode is set:%@AE@%%@NL@%
  15380. flGetCurrentScrnSize XP%, YP%%@NL@%
  15381. IF XP% = 0 THEN EXIT FUNCTION%@NL@%
  15382. %@NL@%
  15383. %@AB@%' Save input location to working variables and erase any window setting:%@AE@%%@NL@%
  15384. IX% = PMAP(X, 0)%@NL@%
  15385. IY% = PMAP(Y, 1)%@NL@%
  15386. WINDOW%@NL@%
  15387. %@NL@%
  15388. %@AB@%' Map chars to valid ones and output them adding their lengths:%@AE@%%@NL@%
  15389. TextLen% = 0%@NL@%
  15390. FOR Char% = 1 TO LEN(Text$)%@NL@%
  15391.         ChVal% = ASC(MID$(Text$, Char%, 1))%@NL@%
  15392.         IF FGP.CharSet = cIBMChars THEN ChVal% = flANSI(ChVal%)%@NL@%
  15393. %@NL@%
  15394.         IF FGP.FontSource = cFileFont THEN%@NL@%
  15395.                 BitMapPtr% = VARPTR(FontData(FGP.DSeg))%@NL@%
  15396.                 BitMapSeg% = VARSEG(FontData(FGP.DSeg))%@NL@%
  15397.         ELSE%@NL@%
  15398.                 BitMapPtr% = FGP.DOffset%@NL@%
  15399.                 BitMapSeg% = FGP.DSeg%@NL@%
  15400.         END IF%@NL@%
  15401. %@NL@%
  15402.         CharLen% = flbltchar%(BitMapSeg%, BitMapPtr%, ChVal%, IX%, IY%)%@NL@%
  15403. %@NL@%
  15404.         IX% = IX% + FGP.XPixInc * CharLen%%@NL@%
  15405.         IY% = IY% + FGP.YPixInc * CharLen%%@NL@%
  15406. %@NL@%
  15407.         TextLen% = TextLen% + CharLen%%@NL@%
  15408. NEXT Char%%@NL@%
  15409. %@NL@%
  15410. %@AB@%' Reset window:%@AE@%%@NL@%
  15411. IF FGP.WindowSet THEN%@NL@%
  15412.         IF FGP.WScrn% THEN%@NL@%
  15413.                 WINDOW SCREEN (FGP.WX1, FGP.WY1)-(FGP.WX2, FGP.WY2)%@NL@%
  15414.         ELSE%@NL@%
  15415.                 WINDOW (FGP.WX1, FGP.WY1)-(FGP.WX2, FGP.WY2)%@NL@%
  15416.         END IF%@NL@%
  15417. END IF%@NL@%
  15418. %@NL@%
  15419. %@AB@%' Update locations%@AE@%%@NL@%
  15420. X = PMAP(IX%, 2)%@NL@%
  15421. Y = PMAP(IY%, 3)%@NL@%
  15422. %@NL@%
  15423. %@AB@%' Return total character length:%@AE@%%@NL@%
  15424. OutGText = TextLen%%@NL@%
  15425. %@NL@%
  15426. END FUNCTION%@NL@%
  15427. %@NL@%
  15428. %@AB@%'=== RegisterFonts - Loads header information from font resources:%@AE@%%@NL@%
  15429. %@AB@%'%@AE@%%@NL@%
  15430. %@AB@%'  Arguments:%@AE@%%@NL@%
  15431. %@AB@%'     FileName$   -  Path name for font file to register%@AE@%%@NL@%
  15432. %@AB@%'%@AE@%%@NL@%
  15433. %@AB@%'  Return Value:%@AE@%%@NL@%
  15434. %@AB@%'     The number of fonts actually registered%@AE@%%@NL@%
  15435. %@AB@%'%@AE@%%@NL@%
  15436. %@AB@%'  Notes:%@AE@%%@NL@%
  15437. %@AB@%'     Offsets documented in Windows document assume the file's first%@AE@%%@NL@%
  15438. %@AB@%'     byte is byte 0 (zero) and GET assumes the first byte is byte 1 so%@AE@%%@NL@%
  15439. %@AB@%'     many GET locations are expressed in the following code as%@AE@%%@NL@%
  15440. %@AB@%'     a documented offset + 1.%@AE@%%@NL@%
  15441. %@AB@%'%@AE@%%@NL@%
  15442. %@AB@%'=================================================================%@AE@%%@NL@%
  15443. FUNCTION RegisterFonts% (FileName$) STATIC%@NL@%
  15444. SHARED FGP AS GlobalParams%@NL@%
  15445. DIM Byte AS STRING * 1%@NL@%
  15446. %@NL@%
  15447. ON ERROR GOTO UnexpectedErr%@NL@%
  15448. %@NL@%
  15449. %@AB@%' Clear errors and make sure things are initialized:%@AE@%%@NL@%
  15450. flClearFontErr%@NL@%
  15451. %@NL@%
  15452. flChkMax%@NL@%
  15453. %@NL@%
  15454. %@AB@%' Get next available file number:%@AE@%%@NL@%
  15455. FileNum% = FREEFILE%@NL@%
  15456. %@NL@%
  15457. %@AB@%' Try to open the file for input first to make sure the file exists. This%@AE@%%@NL@%
  15458. %@AB@%' is done to avoid creating a zero length file if the file doesn't exist.%@AE@%%@NL@%
  15459. ON ERROR GOTO NoFileErr%@NL@%
  15460. OPEN FileName$ FOR INPUT AS FileNum%%@NL@%
  15461. ON ERROR GOTO UnexpectedErr%@NL@%
  15462. IF FontErr <> 0 THEN%@NL@%
  15463.         RegisterFonts = 0%@NL@%
  15464.         EXIT FUNCTION%@NL@%
  15465. END IF%@NL@%
  15466. CLOSE FileNum%%@NL@%
  15467. %@NL@%
  15468. %@AB@%' File seems to exist, so open it in binary mode:%@AE@%%@NL@%
  15469. OPEN FileName$ FOR BINARY ACCESS READ AS FileNum%%@NL@%
  15470. %@NL@%
  15471. %@AB@%' Get the byte that indicates whether this file has a new-style%@AE@%%@NL@%
  15472. %@AB@%' header on it. If not, then error:%@AE@%%@NL@%
  15473. GET FileNum%, &H18 + 1, Byte%@NL@%
  15474. IF ASC(Byte) <> &H40 THEN%@NL@%
  15475.         flSetFontErr cBadFontFile%@NL@%
  15476.         CLOSE FileNum%%@NL@%
  15477.         EXIT FUNCTION%@NL@%
  15478. END IF%@NL@%
  15479. %@NL@%
  15480. %@AB@%' Save the number of fonts currently registered for use later in%@AE@%%@NL@%
  15481. %@AB@%' calculating the number of fonts registered by this call:%@AE@%%@NL@%
  15482. OldTotal = FGP.TotalRegistered%@NL@%
  15483. %@NL@%
  15484. %@AB@%' Get the pointer to the new-style header:%@AE@%%@NL@%
  15485. GET FileNum%, &H3C + 1, Word%%@NL@%
  15486. NewHdr% = Word%%@NL@%
  15487. %@NL@%
  15488. %@AB@%' Get pointer to resource table:%@AE@%%@NL@%
  15489. GET FileNum%, Word% + &H22 + 1, Word%%@NL@%
  15490. ResourceEntry# = NewHdr% + Word% + 1%@NL@%
  15491. %@NL@%
  15492. %@AB@%' Get the alignment shift count from beginning of table:%@AE@%%@NL@%
  15493. GET FileNum%, ResourceEntry#, Align%%@NL@%
  15494. %@NL@%
  15495. %@AB@%' Loop, registering font resources until they have run out:%@AE@%%@NL@%
  15496. DO%@NL@%
  15497.         ResType% = flDoNextResource(Align%, FileName$, FileNum%)%@NL@%
  15498.         IF FontErr <> 0 THEN EXIT DO%@NL@%
  15499. LOOP UNTIL ResType% = 0%@NL@%
  15500. %@NL@%
  15501. CLOSE FileNum%%@NL@%
  15502. %@NL@%
  15503. %@AB@%' Finally, return number of fonts actually registered:%@AE@%%@NL@%
  15504. RegisterFonts = FGP.TotalRegistered - OldTotal%@NL@%
  15505. %@NL@%
  15506. END FUNCTION%@NL@%
  15507. %@NL@%
  15508. %@AB@%'=== RegisterMemFont - Loads header information from a memory-resident font%@AE@%%@NL@%
  15509. %@AB@%'%@AE@%%@NL@%
  15510. %@AB@%'  Arguments:%@AE@%%@NL@%
  15511. %@AB@%'     FontSeg%    -  Segment address of font to register%@AE@%%@NL@%
  15512. %@AB@%'%@AE@%%@NL@%
  15513. %@AB@%'     FontOffset% -  Offset address of font to register%@AE@%%@NL@%
  15514. %@AB@%'%@AE@%%@NL@%
  15515. %@AB@%'  Return Value:%@AE@%%@NL@%
  15516. %@AB@%'     The number of fonts actually registered (0 or 1)%@AE@%%@NL@%
  15517. %@AB@%'%@AE@%%@NL@%
  15518. %@AB@%'  Notes:%@AE@%%@NL@%
  15519. %@AB@%'     Memory resident fonts cannot be stored in BASIC relocatable data%@AE@%%@NL@%
  15520. %@AB@%'     structures (like arrays or non-fixed strings).%@AE@%%@NL@%
  15521. %@AB@%'%@AE@%%@NL@%
  15522. %@AB@%'=================================================================%@AE@%%@NL@%
  15523. FUNCTION RegisterMemFont% (FontSeg AS INTEGER, FontOffset AS INTEGER) STATIC%@NL@%
  15524. SHARED FGP AS GlobalParams%@NL@%
  15525. SHARED FontHdrReg() AS IFontInfo%@NL@%
  15526. DIM FontHeader AS WFHeader%@NL@%
  15527. %@NL@%
  15528. ON ERROR GOTO UnexpectedErr%@NL@%
  15529. %@NL@%
  15530. %@AB@%' Clear error and check max limits:%@AE@%%@NL@%
  15531. flClearFontErr%@NL@%
  15532. flChkMax%@NL@%
  15533. %@NL@%
  15534. %@AB@%' Get the font header:%@AE@%%@NL@%
  15535. flMovMem FontHeader, FontSeg, FontOffset, cSizeFontHeader%@NL@%
  15536. %@NL@%
  15537. %@AB@%' Only register vector fonts:%@AE@%%@NL@%
  15538. IF FontHeader.dfType AND &H1 <> cBitMapType THEN%@NL@%
  15539.         flSetFontErr cBadFontType%@NL@%
  15540.         RegisterMemFont = 0%@NL@%
  15541.         EXIT FUNCTION%@NL@%
  15542. END IF%@NL@%
  15543. %@NL@%
  15544. %@AB@%' See that we're still within MaxRegistered limits:%@AE@%%@NL@%
  15545. IF FGP.TotalRegistered >= FGP.MaxRegistered THEN%@NL@%
  15546.         flSetFontErr cTooManyFonts%@NL@%
  15547.         RegisterMemFont = 0%@NL@%
  15548.         EXIT FUNCTION%@NL@%
  15549. END IF%@NL@%
  15550. %@NL@%
  15551. %@AB@%' Go to next "registered" font slot:%@AE@%%@NL@%
  15552. FGP.TotalRegistered = FGP.TotalRegistered + 1%@NL@%
  15553. %@NL@%
  15554. %@AB@%' Set font source and save the header:%@AE@%%@NL@%
  15555. FontHdrReg(FGP.TotalRegistered).FontSource = cMemFont%@NL@%
  15556. FontHdrReg(FGP.TotalRegistered).FontHeader = FontHeader%@NL@%
  15557. %@NL@%
  15558. %@AB@%' Set font location in memory:%@AE@%%@NL@%
  15559. FontHdrReg(FGP.TotalRegistered).DataSeg = FontSeg%@NL@%
  15560. FontHdrReg(FGP.TotalRegistered).DataOffset = FontOffset + cSizeFontHeader%@NL@%
  15561. %@NL@%
  15562. %@AB@%' Get the face name (scan characters until zero byte):%@AE@%%@NL@%
  15563. FaceLoc% = FontOffset + FontHeader.dfFace%@NL@%
  15564. FaceName$ = ""%@NL@%
  15565. DEF SEG = FontSeg%@NL@%
  15566. FOR Char% = 0 TO cMaxFaceName - 1%@NL@%
  15567.         Byte% = PEEK(FaceLoc% + Char%)%@NL@%
  15568.         IF Byte% = 0 THEN EXIT FOR%@NL@%
  15569.         FaceName$ = FaceName$ + CHR$(Byte%)%@NL@%
  15570. NEXT Char%%@NL@%
  15571. FontHdrReg(FGP.TotalRegistered).FaceName = FaceName$%@NL@%
  15572. %@NL@%
  15573. %@AB@%' Finally, return number of fonts actually registered:%@AE@%%@NL@%
  15574. RegisterMemFont = 1%@NL@%
  15575. %@NL@%
  15576. END FUNCTION%@NL@%
  15577. %@NL@%
  15578. %@AB@%'=== SelectFont - Selects current font from among loaded fonts%@AE@%%@NL@%
  15579. %@AB@%'%@AE@%%@NL@%
  15580. %@AB@%'  Arguments:%@AE@%%@NL@%
  15581. %@AB@%'     FontNum% -  Font number to select%@AE@%%@NL@%
  15582. %@AB@%'%@AE@%%@NL@%
  15583. %@AB@%'=================================================================%@AE@%%@NL@%
  15584. SUB SelectFont (FontNum AS INTEGER) STATIC%@NL@%
  15585. SHARED FGP AS GlobalParams%@NL@%
  15586. %@NL@%
  15587. ON ERROR GOTO UnexpectedErr%@NL@%
  15588. %@NL@%
  15589. %@AB@%' Clear outstanding font errors:%@AE@%%@NL@%
  15590. flClearFontErr%@NL@%
  15591. %@NL@%
  15592. %@AB@%' If no fonts are loaded then error:%@AE@%%@NL@%
  15593. IF FGP.TotalLoaded <= 0 THEN%@NL@%
  15594.         flSetFontErr cNoFonts%@NL@%
  15595.         EXIT SUB%@NL@%
  15596. END IF%@NL@%
  15597. %@NL@%
  15598. %@AB@%' Now, map the font number to an acceptable one and select it:%@AE@%%@NL@%
  15599. IF FontNum <= 0 THEN%@NL@%
  15600.         FGP.CurrentFont = 1%@NL@%
  15601. ELSE%@NL@%
  15602.         FGP.CurrentFont = (ABS(FontNum - 1) MOD (FGP.TotalLoaded)) + 1%@NL@%
  15603. END IF%@NL@%
  15604. %@NL@%
  15605. %@AB@%' Get First, Last and Default character params from header:%@AE@%%@NL@%
  15606. FGP.FChar = ASC(FontHdrLoaded(FGP.CurrentFont).FontHeader.dfFirstChar)%@NL@%
  15607. FGP.LChar = ASC(FontHdrLoaded(FGP.CurrentFont).FontHeader.dfLastChar)%@NL@%
  15608. FGP.DChar = ASC(FontHdrLoaded(FGP.CurrentFont).FontHeader.dfDefaultChar)%@NL@%
  15609. FGP.CHeight = FontHdrLoaded(FGP.CurrentFont).FontHeader.dfPixHeight%@NL@%
  15610. flSetBltParams cSizeFontHeader, FGP.CHeight, FGP.FChar, FGP.LChar, FGP.DChar%@NL@%
  15611. %@NL@%
  15612. %@AB@%' Set some other commonly used elements of font info:%@AE@%%@NL@%
  15613. FGP.DSeg = FontHdrLoaded(FGP.CurrentFont).DataSeg%@NL@%
  15614. FGP.DOffset = FontHdrLoaded(FGP.CurrentFont).DataOffset%@NL@%
  15615. FGP.FontSource = FontHdrLoaded(FGP.CurrentFont).FontSource%@NL@%
  15616. %@NL@%
  15617. END SUB%@NL@%
  15618. %@NL@%
  15619. %@AB@%'=== SetGCharset - Specifies IBM or Windows char set%@AE@%%@NL@%
  15620. %@AB@%'%@AE@%%@NL@%
  15621. %@AB@%'  Arguments:%@AE@%%@NL@%
  15622. %@AB@%'     Charset%    -  cIBMChars for IBM character mappings%@AE@%%@NL@%
  15623. %@AB@%'                    cWindowsChars for Windows character mappings%@AE@%%@NL@%
  15624. %@AB@%'%@AE@%%@NL@%
  15625. %@AB@%'=================================================================%@AE@%%@NL@%
  15626. SUB SetGCharset (CharSet AS INTEGER) STATIC%@NL@%
  15627. SHARED FGP AS GlobalParams%@NL@%
  15628. %@NL@%
  15629. ON ERROR GOTO UnexpectedErr%@NL@%
  15630. %@NL@%
  15631. %@AB@%' Clear outstanding font errors:%@AE@%%@NL@%
  15632. flClearFontErr%@NL@%
  15633. %@NL@%
  15634. IF CharSet = cWindowsChars THEN%@NL@%
  15635.         FGP.CharSet = cWindowsChars%@NL@%
  15636. ELSE%@NL@%
  15637.         FGP.CharSet = cIBMChars%@NL@%
  15638. END IF%@NL@%
  15639. %@NL@%
  15640. END SUB%@NL@%
  15641. %@NL@%
  15642. %@AB@%'=== SetGTextColor - Sets color for drawing characters%@AE@%%@NL@%
  15643. %@AB@%'%@AE@%%@NL@%
  15644. %@AB@%'  Arguments:%@AE@%%@NL@%
  15645. %@AB@%'     FColor   -  Color number%@AE@%%@NL@%
  15646. %@AB@%'%@AE@%%@NL@%
  15647. %@AB@%'=================================================================%@AE@%%@NL@%
  15648. SUB SetGTextColor (FColor AS INTEGER) STATIC%@NL@%
  15649. SHARED FGP AS GlobalParams%@NL@%
  15650. %@NL@%
  15651. ON ERROR GOTO UnexpectedErr%@NL@%
  15652. %@NL@%
  15653. %@AB@%' Clear outstanding font errors:%@AE@%%@NL@%
  15654. flClearFontErr%@NL@%
  15655. %@NL@%
  15656. FGP.CharColor = ABS(FColor)%@NL@%
  15657. flSetBltColor FGP.CharColor%@NL@%
  15658. FGP.CharColorInit = cTRUE%@NL@%
  15659. %@NL@%
  15660. END SUB%@NL@%
  15661. %@NL@%
  15662. %@AB@%'=== SetGTextDir - Sets character direction for OutGText%@AE@%%@NL@%
  15663. %@AB@%'%@AE@%%@NL@%
  15664. %@AB@%'  Arguments:%@AE@%%@NL@%
  15665. %@AB@%'     Dir   -  Character direction:%@AE@%%@NL@%
  15666. %@AB@%'              0 = Horizontal-Right%@AE@%%@NL@%
  15667. %@AB@%'              1 = Vertical-Up%@AE@%%@NL@%
  15668. %@AB@%'              2 = Horizontal-Left%@AE@%%@NL@%
  15669. %@AB@%'              3 = Vertical-Down%@AE@%%@NL@%
  15670. %@AB@%'%@AE@%%@NL@%
  15671. %@AB@%'=================================================================%@AE@%%@NL@%
  15672. SUB SetGTextDir (Dir AS INTEGER) STATIC%@NL@%
  15673. SHARED FGP AS GlobalParams%@NL@%
  15674. %@NL@%
  15675. ON ERROR GOTO UnexpectedErr%@NL@%
  15676. %@NL@%
  15677. %@AB@%' Clear outstanding font errors:%@AE@%%@NL@%
  15678. flClearFontErr%@NL@%
  15679. %@NL@%
  15680. SELECT CASE Dir%@NL@%
  15681. %@NL@%
  15682. %@AB@%        ' Vertical - up%@AE@%%@NL@%
  15683.         CASE 1:  FGP.XPixInc% = 0%@NL@%
  15684.                                 FGP.YPixInc% = -1%@NL@%
  15685.                                 XRowInc% = 1%@NL@%
  15686.                                 YRowInc% = 0%@NL@%
  15687.                                 FGP.CharDir = 1%@NL@%
  15688. %@NL@%
  15689. %@AB@%        ' Horizontal -left%@AE@%%@NL@%
  15690.         CASE 2:  FGP.XPixInc% = -1%@NL@%
  15691.                                 FGP.YPixInc% = 0%@NL@%
  15692.                                 XRowInc% = 0%@NL@%
  15693.                                 YRowInc% = -1%@NL@%
  15694.                                 FGP.CharDir = 2%@NL@%
  15695. %@NL@%
  15696. %@AB@%        ' Vertical - down%@AE@%%@NL@%
  15697.         CASE 3:  FGP.XPixInc% = 0%@NL@%
  15698.                                 FGP.YPixInc% = 1%@NL@%
  15699.                                 XRowInc% = -1%@NL@%
  15700.                                 YRowInc% = 0%@NL@%
  15701.                                 FGP.CharDir = 3%@NL@%
  15702. %@NL@%
  15703. %@AB@%        ' Horizontal - right%@AE@%%@NL@%
  15704.         CASE ELSE:  FGP.XPixInc% = 1%@NL@%
  15705.                                         FGP.YPixInc% = 0%@NL@%
  15706.                                         XRowInc% = 0%@NL@%
  15707.                                         YRowInc% = 1%@NL@%
  15708.                                         FGP.CharDir = 0%@NL@%
  15709.         END SELECT%@NL@%
  15710. %@NL@%
  15711. %@AB@%        ' Call routine to set these increments in the char output routine%@AE@%%@NL@%
  15712.         flSetBltDir FGP.XPixInc%, FGP.YPixInc%, XRowInc%, YRowInc%%@NL@%
  15713.         FGP.CharDirInit = cTRUE%@NL@%
  15714. %@NL@%
  15715. END SUB%@NL@%
  15716. %@NL@%
  15717. %@AB@%'=== SetMaxFonts - Sets the maximum number of fonts that can be registered%@AE@%%@NL@%
  15718. %@AB@%'                  and loaded by the font library:%@AE@%%@NL@%
  15719. %@AB@%'%@AE@%%@NL@%
  15720. %@AB@%'  Arguments:%@AE@%%@NL@%
  15721. %@AB@%'     Registered  -  The maximum number of fonts that can be registered%@AE@%%@NL@%
  15722. %@AB@%'                    by the font library%@AE@%%@NL@%
  15723. %@AB@%'%@AE@%%@NL@%
  15724. %@AB@%'     Loaded      -  The maximum number of fonts that can be loaded by%@AE@%%@NL@%
  15725. %@AB@%'                    by the font library%@AE@%%@NL@%
  15726. %@AB@%'%@AE@%%@NL@%
  15727. %@AB@%'  Return Values:%@AE@%%@NL@%
  15728. %@AB@%'     Sets error if values are not positive. Adjusts MaxReg and MaxLoad%@AE@%%@NL@%
  15729. %@AB@%'     internal values and resets the length of FontHdrReg and FontHdrLoad%@AE@%%@NL@%
  15730. %@AB@%'     arrays if the new value is different from previous one%@AE@%%@NL@%
  15731. %@AB@%'%@AE@%%@NL@%
  15732. %@AB@%'=================================================================%@AE@%%@NL@%
  15733. SUB SetMaxFonts (Registered AS INTEGER, Loaded AS INTEGER) STATIC%@NL@%
  15734. SHARED FGP AS GlobalParams%@NL@%
  15735. SHARED FontHdrReg() AS IFontInfo%@NL@%
  15736. SHARED FontHdrLoaded() AS IFontInfo%@NL@%
  15737. SHARED FontLoadList() AS INTEGER%@NL@%
  15738. SHARED FontData() AS FontDataBlock%@NL@%
  15739. %@NL@%
  15740. ON ERROR GOTO UnexpectedErr%@NL@%
  15741. %@NL@%
  15742. %@AB@%' Clear errors:%@AE@%%@NL@%
  15743. flClearFontErr%@NL@%
  15744. %@NL@%
  15745. %@AB@%' Check to see that values are within range:%@AE@%%@NL@%
  15746. IF Registered <= 0 OR Loaded <= 0 THEN%@NL@%
  15747.         flSetFontErr cBadFontLimit%@NL@%
  15748.         EXIT SUB%@NL@%
  15749. END IF%@NL@%
  15750. %@NL@%
  15751. %@AB@%' Values are ostensibly OK. Reset values and redimension arrays:%@AE@%%@NL@%
  15752. %@AB@%' Reset values for registered fonts:%@AE@%%@NL@%
  15753. FGP.TotalRegistered = 0%@NL@%
  15754. FGP.MaxRegistered = Registered%@NL@%
  15755. %@NL@%
  15756. ON ERROR GOTO MemErr%@NL@%
  15757. REDIM FontHdrReg(1 TO FGP.MaxRegistered) AS IFontInfo%@NL@%
  15758. ON ERROR GOTO UnexpectedErr%@NL@%
  15759. %@NL@%
  15760. %@AB@%' Reset values for loaded fonts:%@AE@%%@NL@%
  15761. FGP.TotalLoaded = 0%@NL@%
  15762. FGP.MaxLoaded = Loaded%@NL@%
  15763. %@NL@%
  15764. ON ERROR GOTO MemErr%@NL@%
  15765. REDIM FontLoadList(1 TO FGP.MaxLoaded) AS INTEGER%@NL@%
  15766. REDIM FontHdrLoaded(1 TO FGP.MaxLoaded) AS IFontInfo%@NL@%
  15767. ON ERROR GOTO UnexpectedErr%@NL@%
  15768. %@NL@%
  15769. %@AB@%' Clear font data array:%@AE@%%@NL@%
  15770. ERASE FontData%@NL@%
  15771. %@NL@%
  15772. END SUB%@NL@%
  15773. %@NL@%
  15774. %@AB@%'=== UnRegisterFonts - Erases registered font header array and resets%@AE@%%@NL@%
  15775. %@AB@%'                      total registered fonts to 0:%@AE@%%@NL@%
  15776. %@AB@%'%@AE@%%@NL@%
  15777. %@AB@%'  Arguments:%@AE@%%@NL@%
  15778. %@AB@%'     ErrNum   -  The error number to set FontErr variable to%@AE@%%@NL@%
  15779. %@AB@%'%@AE@%%@NL@%
  15780. %@AB@%'=================================================================%@AE@%%@NL@%
  15781. SUB UnRegisterFonts STATIC%@NL@%
  15782. SHARED FontHdrReg() AS IFontInfo, FGP AS GlobalParams%@NL@%
  15783. %@NL@%
  15784. ON ERROR GOTO UnexpectedErr%@NL@%
  15785. %@NL@%
  15786. %@AB@%' Clear outstanding font errors:%@AE@%%@NL@%
  15787. flClearFontErr%@NL@%
  15788. %@NL@%
  15789. REDIM FontHdrReg(1 TO 1)  AS IFontInfo%@NL@%
  15790. FGP.MaxRegistered = UBOUND(FontHdrReg, 1)%@NL@%
  15791. FGP.TotalRegistered = 0%@NL@%
  15792. %@NL@%
  15793. END SUB%@NL@%
  15794. %@NL@%
  15795. %@NL@%
  15796. %@NL@%
  15797. %@2@%%@AH@%FONTDEMO.BAS%@AE@%%@EH@%%@NL@%
  15798. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\FONTDEMO.BAS%@AE@%%@NL@%
  15799. %@NL@%
  15800. %@AB@%'       FONTDEMO.BAS - FONTB demonstration program.%@AE@%%@NL@%
  15801. %@AB@%'%@AE@%%@NL@%
  15802. %@AB@%'  Copyright (C) 1989 Microsoft Corporation, All Rights Reserved%@AE@%%@NL@%
  15803. %@AB@%'%@AE@%%@NL@%
  15804. %@AB@%'  This program demonstrates some of the capabilities of the fonts%@AE@%%@NL@%
  15805. %@AB@%'  toolbox.  It loads font files found in the current directory and%@AE@%%@NL@%
  15806. %@AB@%'  and allows you to select a font for display.%@AE@%%@NL@%
  15807. %@AB@%'%@AE@%%@NL@%
  15808. %@AB@%'  The following font files are provided with BASIC 7.0:%@AE@%%@NL@%
  15809. %@AB@%'     - Raster fonts designed for screen resolution of 640x200%@AE@%%@NL@%
  15810. %@AB@%'           COURA.FON%@AE@%%@NL@%
  15811. %@AB@%'           HELVA.FON%@AE@%%@NL@%
  15812. %@AB@%'           TMSRA.FON%@AE@%%@NL@%
  15813. %@AB@%'     - Raster fonts designed for screen resolution of 640x350%@AE@%%@NL@%
  15814. %@AB@%'           COURB.FON%@AE@%%@NL@%
  15815. %@AB@%'           HELVB.FON%@AE@%%@NL@%
  15816. %@AB@%'           TMSRB.FON%@AE@%%@NL@%
  15817. %@AB@%'     - Raster fonts designed for screen resolution of 640x480%@AE@%%@NL@%
  15818. %@AB@%'           COURE.FON%@AE@%%@NL@%
  15819. %@AB@%'           HELVE.FON%@AE@%%@NL@%
  15820. %@AB@%'           TMSRE.FON%@AE@%%@NL@%
  15821. %@AB@%'%@AE@%%@NL@%
  15822. %@AB@%' $INCLUDE: 'FONTB.BI'%@AE@%%@NL@%
  15823. CONST TRUE = -1%@NL@%
  15824. CONST FALSE = 0%@NL@%
  15825. DECLARE SUB DriveScreen ()%@NL@%
  15826. DECLARE SUB GetFiles ()%@NL@%
  15827. DECLARE SUB GetModes ()%@NL@%
  15828. DECLARE SUB ShowScreen ()%@NL@%
  15829. %@NL@%
  15830. DIM SHARED FI AS FontInfo%@NL@%
  15831. DIM SHARED totalmodes AS INTEGER%@NL@%
  15832. DIM SHARED modes(1 TO 13) AS INTEGER%@NL@%
  15833. DIM SHARED fontfiles(1 TO 18) AS STRING%@NL@%
  15834. DIM SHARED totalfonts AS INTEGER%@NL@%
  15835. DIM SHARED currentfont AS INTEGER%@NL@%
  15836. DIM SHARED currentmode AS INTEGER%@NL@%
  15837. GetModes%@NL@%
  15838. GetFiles%@NL@%
  15839. currentfont = 1%@NL@%
  15840. DO%@NL@%
  15841.     DriveScreen%@NL@%
  15842.     ShowScreen%@NL@%
  15843. LOOP%@NL@%
  15844. END%@NL@%
  15845. %@NL@%
  15846. %@AB@%'%@AE@%%@NL@%
  15847. %@AB@%'DriveScreen displays the lists of available fonts and screen modes and%@AE@%%@NL@%
  15848. %@AB@%'scrolls through them with arrow keys.%@AE@%%@NL@%
  15849. %@AB@%'%@AE@%%@NL@%
  15850. SUB DriveScreen STATIC%@NL@%
  15851. IF init% = 0 THEN%@NL@%
  15852.     set$ = "f"%@NL@%
  15853.     max% = totalfonts%@NL@%
  15854.     posit% = currentfont%@NL@%
  15855.     modedim$ = "320x200640x200720x348640x400              320x200"%@NL@%
  15856.     modedim$ = modedim$ + "640x200640x350640x350640x480640x480320x200"%@NL@%
  15857. %@NL@%
  15858. %@AB@%    'Check if monitor supports color or mono.%@AE@%%@NL@%
  15859. %@NL@%
  15860.     SELECT CASE modes(1)%@NL@%
  15861.         CASE 13, 9, 8, 7%@NL@%
  15862.             mode$ = "color"%@NL@%
  15863.         CASE 3, 4, 10%@NL@%
  15864.             mode$ = "mono"%@NL@%
  15865.         CASE 2%@NL@%
  15866.             IF modes(2) = 1 THEN%@NL@%
  15867.                 mode$ = "color"%@NL@%
  15868.             ELSE%@NL@%
  15869.                 mode$ = "mono"%@NL@%
  15870.             END IF%@NL@%
  15871.     END SELECT%@NL@%
  15872.     FOR i% = 1 TO totalmodes%@NL@%
  15873.         IF modes(i%) = 4 THEN mode$ = "mono"%@NL@%
  15874.     NEXT i%%@NL@%
  15875. %@NL@%
  15876. %@AB@%    'Set colors based on type of monitor.%@AE@%%@NL@%
  15877. %@NL@%
  15878.     SELECT CASE mode$%@NL@%
  15879.         CASE "color"%@NL@%
  15880.             listfore% = 7%@NL@%
  15881.             listback% = 0%@NL@%
  15882.             titleon% = 15%@NL@%
  15883.             titleoff% = 7%@NL@%
  15884.             titleback% = 1%@NL@%
  15885.             back% = 1%@NL@%
  15886.             high% = 15%@NL@%
  15887.         CASE "mono"%@NL@%
  15888.             listfore% = 7%@NL@%
  15889.             listback% = 0%@NL@%
  15890.             titleon% = 0%@NL@%
  15891.             titleoff% = 2%@NL@%
  15892.             titleback% = 7%@NL@%
  15893.             back% = 0%@NL@%
  15894.             high% = 7%@NL@%
  15895.     END SELECT%@NL@%
  15896.     init% = 1%@NL@%
  15897. END IF%@NL@%
  15898. %@NL@%
  15899. %@AB@%'Display the screen with the current selections.%@AE@%%@NL@%
  15900. %@NL@%
  15901. SCREEN 0%@NL@%
  15902. WIDTH 80, 25%@NL@%
  15903. LOCATE , , 0: COLOR 0, back%%@NL@%
  15904. PRINT SPACE$(1920)%@NL@%
  15905. LOCATE 2, 1: COLOR high%, back%%@NL@%
  15906. PRINT "  Font Toolbox Demo"%@NL@%
  15907. COLOR titleoff%, back%%@NL@%
  15908. PRINT "  Copyright (C) 1989 Microsoft Corporation"%@NL@%
  15909. LOCATE 22, 1: COLOR titleoff%, back%%@NL@%
  15910. PRINT SPC(55); "<CR> to view fontfile"%@NL@%
  15911. PRINT SPC(55); "ESC to exit"%@NL@%
  15912. %@NL@%
  15913. GOSUB swaptitles%@NL@%
  15914. GOSUB swaptitles%@NL@%
  15915. FOR i% = 1 TO totalfonts%@NL@%
  15916.     LOCATE 5 + i%, 20%@NL@%
  15917.     COLOR listfore%, listback%%@NL@%
  15918.     PRINT LEFT$(fontfiles(i%) + "       ", 12)%@NL@%
  15919. NEXT i%%@NL@%
  15920. LOCATE 5 + currentfont, 20%@NL@%
  15921. COLOR listback%, listfore%%@NL@%
  15922. PRINT LEFT$(fontfiles(currentfont) + "       ", 12)%@NL@%
  15923. %@NL@%
  15924. FOR i% = 1 TO totalmodes%@NL@%
  15925.     LOCATE 5 + i%, 50%@NL@%
  15926.     COLOR listfore%, listback%%@NL@%
  15927.     PRINT LEFT$(STR$(modes(i%)) + "   ", 4) + MID$(modedim$, 7 * modes(i%) - 6, 7)%@NL@%
  15928. NEXT i%%@NL@%
  15929. LOCATE 5 + currentmode, 50%@NL@%
  15930. COLOR listback%, listfore%%@NL@%
  15931. PRINT LEFT$(STR$(modes(currentmode)) + "   ", 4) + MID$(modedim$, 7 * modes(currentmode) - 6, 7)%@NL@%
  15932. %@NL@%
  15933. %@AB@%'Scroll through choices%@AE@%%@NL@%
  15934. %@NL@%
  15935. DO%@NL@%
  15936.     SELECT CASE INKEY$%@NL@%
  15937.         CASE CHR$(0) + CHR$(72)%@NL@%
  15938.             GOSUB upone%@NL@%
  15939.         CASE CHR$(0) + CHR$(80)%@NL@%
  15940.             GOSUB downone%@NL@%
  15941.         CASE CHR$(9), CHR$(0) + CHR$(15), CHR$(0) + CHR$(75), CHR$(0) + CHR$(77)%@NL@%
  15942.             GOSUB swaptitles%@NL@%
  15943.         CASE CHR$(13), CHR$(32): EXIT DO%@NL@%
  15944.         CASE CHR$(27)%@NL@%
  15945.           COLOR 15, 0%@NL@%
  15946.           CLS%@NL@%
  15947.           END%@NL@%
  15948.     END SELECT%@NL@%
  15949. LOOP%@NL@%
  15950. EXIT SUB%@NL@%
  15951. %@NL@%
  15952. swaptitles:%@NL@%
  15953.     IF set$ = "f" THEN%@NL@%
  15954.         set$ = "m"%@NL@%
  15955.         max% = totalmodes%@NL@%
  15956.         posit% = currentmode%@NL@%
  15957.         LOCATE 5, 20: COLOR titleoff%, back%%@NL@%
  15958.         PRINT "Font files:"%@NL@%
  15959.         LOCATE 5, 50: COLOR titleon%, titleback%%@NL@%
  15960.         PRINT "Screen Modes:"%@NL@%
  15961.     ELSEIF set$ = "m" THEN%@NL@%
  15962.         set$ = "f"%@NL@%
  15963.         max% = totalfonts%@NL@%
  15964.         posit% = currentfont%@NL@%
  15965.         LOCATE 5, 20: COLOR titleon%, titleback%%@NL@%
  15966.         PRINT "Font files:"%@NL@%
  15967.         LOCATE 5, 50: COLOR titleoff%, back%%@NL@%
  15968.         PRINT "Screen Modes:"%@NL@%
  15969.     END IF%@NL@%
  15970. RETURN%@NL@%
  15971. %@NL@%
  15972. upone:%@NL@%
  15973.     oldpos% = posit%%@NL@%
  15974.     posit% = (posit% + max% - 2) MOD max% + 1%@NL@%
  15975.     GOSUB redraw%@NL@%
  15976. RETURN%@NL@%
  15977. %@NL@%
  15978. downone:%@NL@%
  15979.     oldpos% = posit%%@NL@%
  15980.     posit% = posit% MOD max% + 1%@NL@%
  15981.     GOSUB redraw%@NL@%
  15982. RETURN%@NL@%
  15983. %@NL@%
  15984. redraw:%@NL@%
  15985.     IF set$ = "f" THEN%@NL@%
  15986.         LOCATE 5 + oldpos%, 20%@NL@%
  15987.         COLOR listfore%, listback%%@NL@%
  15988.         PRINT LEFT$(fontfiles(oldpos%) + "       ", 12)%@NL@%
  15989.         LOCATE 5 + posit%, 20%@NL@%
  15990.         COLOR listback%, listfore%%@NL@%
  15991.         PRINT LEFT$(fontfiles(posit%) + "       ", 12)%@NL@%
  15992.         currentfont = posit%%@NL@%
  15993.     ELSE%@NL@%
  15994.         LOCATE 5 + oldpos%, 50%@NL@%
  15995.         COLOR listfore%, listback%%@NL@%
  15996.         PRINT LEFT$(STR$(modes(oldpos%)) + "   ", 4) + MID$(modedim$, 7 * modes(oldpos%) - 6, 7)%@NL@%
  15997.         LOCATE 5 + posit%, 50%@NL@%
  15998.         COLOR listback%, listfore%%@NL@%
  15999.         PRINT LEFT$(STR$(modes(posit%)) + "   ", 4) + MID$(modedim$, 7 * modes(posit%) - 6, 7)%@NL@%
  16000.         currentmode = posit%%@NL@%
  16001.     END IF%@NL@%
  16002. RETURN%@NL@%
  16003. %@NL@%
  16004. END SUB%@NL@%
  16005. %@NL@%
  16006. %@AB@%'%@AE@%%@NL@%
  16007. %@AB@%'GetFiles finds all *.fon files in the current working directory and checks%@AE@%%@NL@%
  16008. %@AB@%'if they are legitimate.  If the files are ok, they are added to files list.%@AE@%%@NL@%
  16009. %@AB@%'%@AE@%%@NL@%
  16010. SUB GetFiles%@NL@%
  16011. SCREEN 0%@NL@%
  16012. WIDTH 80, 25%@NL@%
  16013. tryagain:%@NL@%
  16014. CLS%@NL@%
  16015. PRINT "Checking fontfiles..."%@NL@%
  16016. totalfonts = 0%@NL@%
  16017. X$ = DIR$("*.fon")%@NL@%
  16018. IF X$ = "" THEN%@NL@%
  16019.     PRINT "No font files found in current directory."%@NL@%
  16020.     PRINT "Push a shell to change directories? [yn]"%@NL@%
  16021.     try$ = "a"%@NL@%
  16022.     DO UNTIL INSTR(1, "NYny", try$)%@NL@%
  16023.         try$ = INPUT$(1)%@NL@%
  16024.     LOOP%@NL@%
  16025.     SELECT CASE UCASE$(try$)%@NL@%
  16026.         CASE "Y"%@NL@%
  16027.             PRINT "Type 'EXIT' to return to demo."%@NL@%
  16028.             SHELL%@NL@%
  16029.             GOTO tryagain%@NL@%
  16030.         CASE "N"%@NL@%
  16031.             END%@NL@%
  16032.     END SELECT%@NL@%
  16033. ELSE%@NL@%
  16034.     DO WHILE X$ <> ""%@NL@%
  16035.         PRINT "   "; UCASE$(X$); "--";%@NL@%
  16036.         SetMaxFonts 10, 10%@NL@%
  16037.         Reg% = RegisterFonts(X$)%@NL@%
  16038.         IF Reg% = 0 THEN%@NL@%
  16039.             PRINT "bad font file"%@NL@%
  16040.         ELSE%@NL@%
  16041.             totalfonts = totalfonts + 1%@NL@%
  16042.             fontfiles(totalfonts) = UCASE$(X$)%@NL@%
  16043.             PRINT "OK"%@NL@%
  16044.             IF totalfonts = 18 THEN EXIT DO%@NL@%
  16045.         END IF%@NL@%
  16046.         X$ = DIR$%@NL@%
  16047.     LOOP%@NL@%
  16048. END IF%@NL@%
  16049. SLEEP 1%@NL@%
  16050. END SUB%@NL@%
  16051. %@NL@%
  16052. %@AB@%'%@AE@%%@NL@%
  16053. %@AB@%'GetModes tries all screen modes from 1-13 to see if they are supported.%@AE@%%@NL@%
  16054. %@AB@%'If a mode is supported, it is added to the list of available modes.%@AE@%%@NL@%
  16055. %@AB@%'%@AE@%%@NL@%
  16056. SUB GetModes%@NL@%
  16057. ON LOCAL ERROR GOTO badmode%@NL@%
  16058. nextactive% = 1%@NL@%
  16059. totalmodes = 0%@NL@%
  16060. FOR i% = 13 TO 1 STEP -1%@NL@%
  16061.     good% = TRUE%@NL@%
  16062.     SCREEN i%%@NL@%
  16063.     IF good% THEN%@NL@%
  16064.         modes(nextactive%) = i%%@NL@%
  16065.         nextactive% = nextactive% + 1%@NL@%
  16066.         totalmodes = totalmodes + 1%@NL@%
  16067.     END IF%@NL@%
  16068. NEXT i%%@NL@%
  16069. IF totalmodes = 0 THEN%@NL@%
  16070.     PRINT "No graphics modes available"%@NL@%
  16071.     END%@NL@%
  16072. END IF%@NL@%
  16073. %@NL@%
  16074. IF modes(1) = 13 THEN%@NL@%
  16075.     currentmode = 2%@NL@%
  16076. ELSE%@NL@%
  16077.     currentmode = 1%@NL@%
  16078. END IF%@NL@%
  16079. EXIT SUB%@NL@%
  16080. badmode:%@NL@%
  16081.     good% = FALSE%@NL@%
  16082.     RESUME NEXT%@NL@%
  16083. END SUB%@NL@%
  16084. %@NL@%
  16085. %@AB@%'%@AE@%%@NL@%
  16086. %@AB@%'ShowScreen displays all the fonts in the current font file and current%@AE@%%@NL@%
  16087. %@AB@%'graphics mode.%@AE@%%@NL@%
  16088. %@AB@%'%@AE@%%@NL@%
  16089. SUB ShowScreen%@NL@%
  16090.     SetMaxFonts 10, 10%@NL@%
  16091.     TotalReg% = RegisterFonts(fontfiles(currentfont))%@NL@%
  16092.     SCREEN modes(currentmode)%@NL@%
  16093.     PRINT "Please wait..."%@NL@%
  16094. %@NL@%
  16095.     IF FontErr THEN%@NL@%
  16096.         CLS%@NL@%
  16097.         PRINT "Unable to continue, FontErr ="; FontErr%@NL@%
  16098.         C$ = INPUT$(1)%@NL@%
  16099.         EXIT SUB%@NL@%
  16100.     END IF%@NL@%
  16101.     IF TotalReg% > 10 THEN TotalReg% = 10%@NL@%
  16102. %@NL@%
  16103.     StrLen% = TotalReg% * 3 - 1%@NL@%
  16104.     IF TotalReg% > 9 THEN StrLen% = StrLen% + TotalReg% - 9%@NL@%
  16105.     LoadStr$ = LEFT$("N1/N2/N3/N4/N5/N6/N7/N8/N9/N10", StrLen%)%@NL@%
  16106.     TotalLoad% = LoadFont(LoadStr$)%@NL@%
  16107. %@NL@%
  16108.     SELECT CASE modes(currentmode)%@NL@%
  16109.         CASE 1: XS% = 160: YS% = 100%@NL@%
  16110.         CASE 2: XS% = 320: YS% = 100%@NL@%
  16111.         CASE 3: XS% = 360: YS% = 174%@NL@%
  16112.         CASE 4: XS% = 320: YS% = 200%@NL@%
  16113.         CASE 7: XS% = 160: YS% = 100%@NL@%
  16114.         CASE 8: XS% = 320: YS% = 100%@NL@%
  16115.         CASE 9: XS% = 320: YS% = 175%@NL@%
  16116.         CASE 10: XS% = 320: YS% = 175%@NL@%
  16117.         CASE 11: XS% = 320: YS% = 240%@NL@%
  16118.         CASE 12: XS% = 320: YS% = 240%@NL@%
  16119.         CASE 13: XS% = 160: YS% = 100%@NL@%
  16120.     END SELECT%@NL@%
  16121. %@NL@%
  16122.     prompt$ = "Press any key."%@NL@%
  16123.     FOR i% = 1 TO TotalLoad%%@NL@%
  16124.         CLS%@NL@%
  16125.         SelectFont INT(i%)%@NL@%
  16126.         GetFontInfo FI%@NL@%
  16127.         SetGTextDir 0%@NL@%
  16128.         SetGTextColor 14%@NL@%
  16129.         Length% = OutGText(1, 1, RTRIM$(FI.FaceName))%@NL@%
  16130.         Length% = OutGText(1, 1 + FI.PixHeight, LTRIM$(STR$(FI.Points) + " Point"))%@NL@%
  16131.         FOR Dir% = 0 TO 3%@NL@%
  16132.             SetGTextDir Dir%%@NL@%
  16133.             SetGTextColor 15 - Dir%%@NL@%
  16134.             SELECT CASE Dir%%@NL@%
  16135.                 CASE 0: X% = XS%: Y% = YS% - FI.PixHeight%@NL@%
  16136.                 CASE 1: X% = XS% - FI.PixHeight: Y% = YS%%@NL@%
  16137.                 CASE 2: X% = XS%: Y% = YS% + FI.PixHeight%@NL@%
  16138.                 CASE 3: X% = XS% + FI.PixHeight: Y% = YS%%@NL@%
  16139.             END SELECT%@NL@%
  16140.             Length% = OutGText(CSNG(X%), CSNG(Y%), "Microsoft")%@NL@%
  16141.         NEXT Dir%%@NL@%
  16142.         SelectFont 2%@NL@%
  16143.         GetFontInfo FI%@NL@%
  16144.         SetGTextColor 14%@NL@%
  16145.         SetGTextDir 0%@NL@%
  16146.         IF i% = TotalLoad% THEN prompt$ = "Press ESC to go on."%@NL@%
  16147.         Length% = GetGTextLen(prompt$)%@NL@%
  16148.         Length% = OutGText(2 * XS% - Length% - 10, 2 * YS% - FI.PixHeight - 1, prompt$)%@NL@%
  16149.         IF i% = TotalLoad% THEN%@NL@%
  16150.             DO UNTIL INKEY$ = CHR$(27): LOOP%@NL@%
  16151.         ELSE%@NL@%
  16152.             a$ = INPUT$(1)%@NL@%
  16153.         END IF%@NL@%
  16154.     NEXT i%%@NL@%
  16155. END SUB%@NL@%
  16156. %@NL@%
  16157. %@NL@%
  16158. %@NL@%
  16159. %@2@%%@AH@%GENERAL.BAS%@AE@%%@EH@%%@NL@%
  16160. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\GENERAL.BAS%@AE@%%@NL@%
  16161. %@NL@%
  16162. %@AB@%'============================================================================%@AE@%%@NL@%
  16163. %@AB@%'%@AE@%%@NL@%
  16164. %@AB@%'     GENERAL.BAS - General Routines for the User Interface Toolbox in%@AE@%%@NL@%
  16165. %@AB@%'           Microsoft BASIC 7.0, Professional Development System%@AE@%%@NL@%
  16166. %@AB@%'              Copyright (C) 1987-1989, Microsoft Corporation%@AE@%%@NL@%
  16167. %@AB@%'%@AE@%%@NL@%
  16168. %@AB@%'  NOTE:    This sample source code toolbox is intended to demonstrate some%@AE@%%@NL@%
  16169. %@AB@%'           of the extended capabilities of Microsoft BASIC 7.0 Professional%@AE@%%@NL@%
  16170. %@AB@%'           Development system that can help to leverage the professional%@AE@%%@NL@%
  16171. %@AB@%'           developer's time more effectively.  While you are free to use,%@AE@%%@NL@%
  16172. %@AB@%'           modify, or distribute the routines in this module in any way you%@AE@%%@NL@%
  16173. %@AB@%'           find useful, it should be noted that these are examples only and%@AE@%%@NL@%
  16174. %@AB@%'           should not be relied upon as a fully-tested "add-on" library.%@AE@%%@NL@%
  16175. %@AB@%'%@AE@%%@NL@%
  16176. %@AB@%'  PURPOSE: These are the general purpose routines needed by the other%@AE@%%@NL@%
  16177. %@AB@%'           modules in the user interface toolbox.%@AE@%%@NL@%
  16178. %@AB@%'%@AE@%%@NL@%
  16179. %@AB@%'  To create a library and QuickLib containing the routines found%@AE@%%@NL@%
  16180. %@AB@%'  in this file, follow these steps:%@AE@%%@NL@%
  16181. %@AB@%'       BC /X/FS general.bas%@AE@%%@NL@%
  16182. %@AB@%'       LIB general.lib + general + uiasm + qbx.lib;%@AE@%%@NL@%
  16183. %@AB@%'       LINK /Q general.lib, general.qlb,,qbxqlb.lib;%@AE@%%@NL@%
  16184. %@AB@%'  Creating a library and QuickLib for any of the other UI toolbox files%@AE@%%@NL@%
  16185. %@AB@%'  (WINDOW.BAS, MENU.BAS and MOUSE.BAS) is done this way also.%@AE@%%@NL@%
  16186. %@AB@%'%@AE@%%@NL@%
  16187. %@AB@%'  To create a library and QuickLib containing all routines from%@AE@%%@NL@%
  16188. %@AB@%'  the User Interface toolbox follow these steps:%@AE@%%@NL@%
  16189. %@AB@%'       BC /X/FS general.bas%@AE@%%@NL@%
  16190. %@AB@%'       BC /X/FS window.bas%@AE@%%@NL@%
  16191. %@AB@%'       BC /X/FS mouse.bas%@AE@%%@NL@%
  16192. %@AB@%'       BC /X/FS menu.bas%@AE@%%@NL@%
  16193. %@AB@%'       LIB uitb.lib + general + window + mouse + menu + uiasm + qbx.lib;%@AE@%%@NL@%
  16194. %@AB@%'       LINK /Q uitb.lib, uitb.qlb,,qbxqlb.lib;%@AE@%%@NL@%
  16195. %@AB@%'  If you are going to use this QuickLib in conjunction with the font source%@AE@%%@NL@%
  16196. %@AB@%'  code (FONTB.BAS) or the charting source code (CHRTB.BAS), you need to%@AE@%%@NL@%
  16197. %@AB@%'  include the assembly code routines referenced in these files.  For the font%@AE@%%@NL@%
  16198. %@AB@%'  routines, perform the following LIB command after creating the library but%@AE@%%@NL@%
  16199. %@AB@%'  before creating the QuickLib as described above:%@AE@%%@NL@%
  16200. %@AB@%'       LIB uitb.lib + fontasm;%@AE@%%@NL@%
  16201. %@AB@%'  For the charting routines, perform the following LIB command after creating%@AE@%%@NL@%
  16202. %@AB@%'  the library but before creating the QuickLib as described above:%@AE@%%@NL@%
  16203. %@AB@%'       LIB uitb.lib + chrtasm;%@AE@%%@NL@%
  16204. %@AB@%'%@AE@%%@NL@%
  16205. %@AB@%'============================================================================%@AE@%%@NL@%
  16206. %@NL@%
  16207. DEFINT A-Z%@NL@%
  16208. %@NL@%
  16209. %@AB@%'$INCLUDE: 'general.bi'%@AE@%%@NL@%
  16210. %@AB@%'$INCLUDE: 'mouse.bi'%@AE@%%@NL@%
  16211. %@NL@%
  16212. FUNCTION AltToASCII$ (kbd$)%@NL@%
  16213. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  16214. %@AB@%    ' Converts Alt+A to A,Alt+B to B, etc.  You send it a string.  The right%@AE@%%@NL@%
  16215. %@AB@%    ' most character is compared to the string below, and is converted to%@AE@%%@NL@%
  16216. %@AB@%    ' the proper character.%@AE@%%@NL@%
  16217. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  16218.     index = INSTR("xyz{|}~Çü !" + CHR$(34) + "#$%&,-./012éâ", RIGHT$(kbd$, 1))%@NL@%
  16219. %@NL@%
  16220.     IF index = 0 THEN%@NL@%
  16221.         AltToASCII = ""%@NL@%
  16222.     ELSE%@NL@%
  16223.         AltToASCII = MID$("1234567890QWERTYUIOPASDFGHJKLZXCVBNM-=", index, 1)%@NL@%
  16224.     END IF%@NL@%
  16225. %@NL@%
  16226. END FUNCTION%@NL@%
  16227. %@NL@%
  16228. SUB Box (row1, col1, row2, col2, fore, back, border$, fillFlag) STATIC%@NL@%
  16229. %@NL@%
  16230. %@AB@%    '=======================================================================%@AE@%%@NL@%
  16231. %@AB@%    '  Use default border if an illegal border$ is passed%@AE@%%@NL@%
  16232. %@AB@%    '=======================================================================%@AE@%%@NL@%
  16233. %@NL@%
  16234.     IF LEN(border$) < 9 THEN%@NL@%
  16235.         t$ = "┌─┐│ │└─┘"%@NL@%
  16236.     ELSE%@NL@%
  16237.         t$ = border$%@NL@%
  16238.     END IF%@NL@%
  16239. %@NL@%
  16240. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  16241. %@AB@%    ' Check coordinates for validity, then draw box%@AE@%%@NL@%
  16242. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  16243. %@NL@%
  16244.     IF col1 <= (col2 - 2) AND row1 <= (row2 - 2) AND col1 >= MINCOL AND row1 >= MINROW AND col2 <= MAXCOL AND row2 <= MAXROW THEN%@NL@%
  16245.         MouseHide%@NL@%
  16246.         BoxWidth = col2 - col1 + 1%@NL@%
  16247.         BoxHeight = row2 - row1 + 1%@NL@%
  16248.         LOCATE row1, col1%@NL@%
  16249.         COLOR fore, back%@NL@%
  16250.         PRINT LEFT$(t$, 1); STRING$(BoxWidth - 2, MID$(t$, 2, 1)); MID$(t$, 3, 1)%@NL@%
  16251.         LOCATE row2, col1%@NL@%
  16252.         PRINT MID$(t$, 7, 1); STRING$(BoxWidth - 2, MID$(t$, 8, 1)); MID$(t$, 9, 1);%@NL@%
  16253. %@NL@%
  16254.         FOR a = row1 + 1 TO row1 + BoxHeight - 2%@NL@%
  16255.             LOCATE a, col1%@NL@%
  16256.             PRINT MID$(t$, 4, 1);%@NL@%
  16257. %@NL@%
  16258.             IF fillFlag THEN%@NL@%
  16259.                 PRINT STRING$(BoxWidth - 2, MID$(t$, 5, 1));%@NL@%
  16260.             ELSE%@NL@%
  16261.                 LOCATE a, col1 + BoxWidth - 1%@NL@%
  16262.             END IF%@NL@%
  16263. %@NL@%
  16264.             PRINT MID$(t$, 6, 1);%@NL@%
  16265.         NEXT a%@NL@%
  16266.         LOCATE row1 + 1, col1 + 1%@NL@%
  16267.         MouseShow%@NL@%
  16268.     END IF%@NL@%
  16269. %@NL@%
  16270. END SUB%@NL@%
  16271. %@NL@%
  16272. SUB GetBackground (row1, col1, row2, col2, buffer$) STATIC%@NL@%
  16273. %@NL@%
  16274. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  16275. %@AB@%    ' Create enough space in buffer$ to hold the screen info behind the box%@AE@%%@NL@%
  16276. %@AB@%    ' Then, call GetCopyBox to store the background in buffer$%@AE@%%@NL@%
  16277. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  16278. %@NL@%
  16279.     IF row1 >= 1 AND row2 <= MAXROW AND col1 >= 1 AND col2 <= MAXCOL THEN%@NL@%
  16280.         Wid = col2 - col1 + 1%@NL@%
  16281.         Hei = row2 - row1 + 1%@NL@%
  16282.         size = 4 + (2 * Wid * Hei)%@NL@%
  16283.         buffer$ = SPACE$(size)%@NL@%
  16284. %@NL@%
  16285.         CALL GetCopyBox(row1, col1, row2, col2, buffer$)%@NL@%
  16286.     END IF%@NL@%
  16287. %@NL@%
  16288. END SUB%@NL@%
  16289. %@NL@%
  16290. FUNCTION GetShiftState (bit)%@NL@%
  16291. %@NL@%
  16292. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  16293. %@AB@%    ' Returns the shift state after calling interrupt 22%@AE@%%@NL@%
  16294. %@AB@%    '    bit 0 : right shift%@AE@%%@NL@%
  16295. %@AB@%    '        1 : left shift%@AE@%%@NL@%
  16296. %@AB@%    '        2 : ctrl key%@AE@%%@NL@%
  16297. %@AB@%    '        3 : alt key%@AE@%%@NL@%
  16298. %@AB@%    '        4 : scroll lock%@AE@%%@NL@%
  16299. %@AB@%    '        5 : num lock%@AE@%%@NL@%
  16300. %@AB@%    '        6 : caps lock%@AE@%%@NL@%
  16301. %@AB@%    '        7 : insert state%@AE@%%@NL@%
  16302. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  16303. %@NL@%
  16304.     IF bit >= 0 AND bit <= 7 THEN%@NL@%
  16305.         DIM regs AS RegType%@NL@%
  16306.         regs.ax = 2 * 256%@NL@%
  16307.         INTERRUPT 22, regs, regs%@NL@%
  16308. %@NL@%
  16309.         IF regs.ax AND 2 ^ bit THEN%@NL@%
  16310.             GetShiftState = TRUE%@NL@%
  16311.         ELSE%@NL@%
  16312.             GetShiftState = FALSE%@NL@%
  16313.         END IF%@NL@%
  16314.     ELSE%@NL@%
  16315.         GetShiftState = FALSE%@NL@%
  16316.     END IF%@NL@%
  16317. %@NL@%
  16318. END FUNCTION%@NL@%
  16319. %@NL@%
  16320. SUB PutBackground (row, col, buffer$)%@NL@%
  16321. %@NL@%
  16322. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  16323. %@AB@%    ' This sub checks the boundries before executing the put command%@AE@%%@NL@%
  16324. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  16325. %@NL@%
  16326.     IF row >= 1 AND row <= MAXROW AND col >= 1 AND col <= MAXCOL THEN%@NL@%
  16327.         CALL PutCopyBox(row, col, buffer$)%@NL@%
  16328.     END IF%@NL@%
  16329. %@NL@%
  16330. END SUB%@NL@%
  16331. %@NL@%
  16332. SUB scroll (row1, col1, row2, col2, lines, attr)%@NL@%
  16333. %@NL@%
  16334. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  16335. %@AB@%    ' Make sure coordinates are in proper order%@AE@%%@NL@%
  16336. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  16337. %@NL@%
  16338.     IF row1 > row2 THEN%@NL@%
  16339.         SWAP row1, row2%@NL@%
  16340.     END IF%@NL@%
  16341. %@NL@%
  16342.     IF col1 > col2 THEN%@NL@%
  16343.         SWAP col1, col2%@NL@%
  16344.     END IF%@NL@%
  16345. %@NL@%
  16346. %@AB@%     ' ======================================================================%@AE@%%@NL@%
  16347. %@AB@%     ' If coordinates are valid, prepare registers, and call interrupt%@AE@%%@NL@%
  16348. %@AB@%     ' ======================================================================%@AE@%%@NL@%
  16349. %@NL@%
  16350.     IF row1 >= MINROW AND row2 <= MAXROW AND col1 >= MINCOL AND col2 <= MAXCOL THEN%@NL@%
  16351.         DIM regs AS RegType%@NL@%
  16352. %@NL@%
  16353.         IF lines < 0 THEN%@NL@%
  16354.             regs.ax = 256 * 7 + (-lines)%@NL@%
  16355.             regs.bx = 256 * attr%@NL@%
  16356.             regs.cx = 256 * (row1 - 1) + (col1 - 1)%@NL@%
  16357.             regs.dx = 256 * (row2 - 1) + (col2 - 1)%@NL@%
  16358.         ELSE%@NL@%
  16359.             regs.ax = 256 * 6 + lines%@NL@%
  16360.             regs.bx = 256 * (attr MOD 8) * 16%@NL@%
  16361.             regs.cx = 256 * (row1 - 1) + (col1 - 1)%@NL@%
  16362.             regs.dx = 256 * (row2 - 1) + (col2 - 1)%@NL@%
  16363.         END IF%@NL@%
  16364. %@NL@%
  16365.         INTERRUPT 16, regs, regs%@NL@%
  16366.     END IF%@NL@%
  16367. %@NL@%
  16368. END SUB%@NL@%
  16369. %@NL@%
  16370. %@NL@%
  16371. %@NL@%
  16372. %@2@%%@AH@%INDEX.BAS%@AE@%%@EH@%%@NL@%
  16373. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\INDEX.BAS%@AE@%%@NL@%
  16374. %@NL@%
  16375. DEFINT A-Z%@NL@%
  16376. %@NL@%
  16377. %@AB@%' Define the symbolic constants used globally in the program:%@AE@%%@NL@%
  16378. CONST FALSE = 0, TRUE = NOT FALSE%@NL@%
  16379. %@NL@%
  16380. %@AB@%' Define a record structure for random-file records:%@AE@%%@NL@%
  16381. TYPE StockItem%@NL@%
  16382.         PartNumber AS STRING * 6%@NL@%
  16383.         Description AS STRING * 20%@NL@%
  16384.         UnitPrice AS SINGLE%@NL@%
  16385.         Quantity AS INTEGER%@NL@%
  16386. END TYPE%@NL@%
  16387. %@NL@%
  16388. %@AB@%' Define a record structure for each element of the index:%@AE@%%@NL@%
  16389. TYPE IndexType%@NL@%
  16390.         RecordNumber AS INTEGER%@NL@%
  16391.         PartNumber AS STRING * 6%@NL@%
  16392. END TYPE%@NL@%
  16393. %@NL@%
  16394. %@AB@%' Declare procedures that will be called:%@AE@%%@NL@%
  16395. DECLARE FUNCTION Filter$ (Prompt$)%@NL@%
  16396. DECLARE FUNCTION FindRecord% (PartNumber$, RecordVar AS StockItem)%@NL@%
  16397. %@NL@%
  16398. DECLARE SUB AddRecord (RecordVar AS StockItem)%@NL@%
  16399. DECLARE SUB InputRecord (RecordVar AS StockItem)%@NL@%
  16400. DECLARE SUB PrintRecord (RecordVar AS StockItem)%@NL@%
  16401. DECLARE SUB SortIndex ()%@NL@%
  16402. DECLARE SUB ShowPartNumbers ()%@NL@%
  16403. %@AB@%' Define a buffer (using the StockItem type)%@AE@%%@NL@%
  16404. %@AB@%' and define and dimension the index array:%@AE@%%@NL@%
  16405. DIM StockRecord AS StockItem, index(1 TO 100) AS IndexType%@NL@%
  16406. %@NL@%
  16407. %@AB@%' Open the random-access file:%@AE@%%@NL@%
  16408. OPEN "STOCK.DAT" FOR RANDOM AS #1 LEN = LEN(StockRecord)%@NL@%
  16409. %@NL@%
  16410. %@AB@%' Calculate number of records in the file:%@AE@%%@NL@%
  16411. NumberOfRecords = LOF(1) \ LEN(StockRecord)%@NL@%
  16412. %@NL@%
  16413. %@AB@%' If there are records, read them and build the index:%@AE@%%@NL@%
  16414. IF NumberOfRecords <> 0 THEN%@NL@%
  16415.         FOR RecordNumber = 1 TO NumberOfRecords%@NL@%
  16416. %@NL@%
  16417. %@AB@%                ' Read the data from a new record in the file:%@AE@%%@NL@%
  16418.                 GET #1, RecordNumber, StockRecord%@NL@%
  16419. %@NL@%
  16420. %@AB@%                ' Place part number and record number in index:%@AE@%%@NL@%
  16421.                 index(RecordNumber).RecordNumber = RecordNumber%@NL@%
  16422.                 index(RecordNumber).PartNumber = StockRecord.PartNumber%@NL@%
  16423.         NEXT%@NL@%
  16424. %@NL@%
  16425.         SortIndex            ' Sort index in part-number order.%@NL@%
  16426. END IF%@NL@%
  16427. %@NL@%
  16428. DO                      ' Main-menu loop.%@NL@%
  16429.         CLS%@NL@%
  16430.         PRINT "(A)dd records."%@NL@%
  16431.         PRINT "(L)ook up records."%@NL@%
  16432.         PRINT "(Q)uit program."%@NL@%
  16433.         PRINT%@NL@%
  16434.         LOCATE , , 1%@NL@%
  16435.         PRINT "Type your choice (A, L, or Q) here: ";%@NL@%
  16436. %@NL@%
  16437. %@AB@%        ' Loop until user presses, A, L, or Q:%@AE@%%@NL@%
  16438.         DO%@NL@%
  16439.                 Choice$ = UCASE$(INPUT$(1))%@NL@%
  16440.         LOOP WHILE INSTR("ALQ", Choice$) = 0%@NL@%
  16441. %@NL@%
  16442. %@AB@%        ' Branch according to choice:%@AE@%%@NL@%
  16443.         SELECT CASE Choice$%@NL@%
  16444.                 CASE "A"%@NL@%
  16445.          AddRecord StockRecord%@NL@%
  16446.                 CASE "L"%@NL@%
  16447.          IF NumberOfRecords = 0 THEN%@NL@%
  16448.                  PRINT : PRINT "No records in file yet. ";%@NL@%
  16449.                  PRINT "Press any key to continue.";%@NL@%
  16450.                  Pause$ = INPUT$(1)%@NL@%
  16451.          ELSE%@NL@%
  16452.                  InputRecord StockRecord%@NL@%
  16453.          END IF%@NL@%
  16454.                 CASE "Q"          ' End program.%@NL@%
  16455.         END SELECT%@NL@%
  16456. LOOP UNTIL Choice$ = "Q"%@NL@%
  16457. %@NL@%
  16458. CLOSE #1                ' All done, close file and end.%@NL@%
  16459. END%@NL@%
  16460. %@AB@%' ======================== ADDRECORD ======================%@AE@%%@NL@%
  16461. %@AB@%' Adds records to the file from input typed at the keyboard%@AE@%%@NL@%
  16462. %@AB@%' =========================================================%@AE@%%@NL@%
  16463. %@AB@%' ========================= FILTER ========================%@AE@%%@NL@%
  16464. %@AB@%'       Filters all non-numeric characters from a string%@AE@%%@NL@%
  16465. %@AB@%'       and returns the filtered string%@AE@%%@NL@%
  16466. %@AB@%' =========================================================%@AE@%%@NL@%
  16467. %@AB@%' ======================= FINDRECORD ===================%@AE@%%@NL@%
  16468. %@AB@%'  Uses a binary search to locate a record in the index%@AE@%%@NL@%
  16469. %@AB@%' ======================================================%@AE@%%@NL@%
  16470. %@AB@%' ======================= PRINTRECORD =====================%@AE@%%@NL@%
  16471. %@AB@%'                Prints a record on the screen%@AE@%%@NL@%
  16472. %@AB@%' =========================================================%@AE@%%@NL@%
  16473. %@AB@%' ===================== SHOWPARTNUMBERS ===================%@AE@%%@NL@%
  16474. %@AB@%' Prints an index of all the part numbers in the upper part%@AE@%%@NL@%
  16475. %@AB@%' of the screen%@AE@%%@NL@%
  16476. %@AB@%' =========================================================%@AE@%%@NL@%
  16477. %@AB@%' ========================= SORTINDEX =====================%@AE@%%@NL@%
  16478. %@AB@%'                Sorts the index by part number%@AE@%%@NL@%
  16479. %@AB@%' =========================================================%@AE@%%@NL@%
  16480. %@NL@%
  16481. %@NL@%
  16482. SUB AddRecord (RecordVar AS StockItem) STATIC%@NL@%
  16483.         SHARED index() AS IndexType, NumberOfRecords%@NL@%
  16484.         DO%@NL@%
  16485.                 CLS%@NL@%
  16486.                 INPUT "Part Number: ", RecordVar.PartNumber%@NL@%
  16487.                 INPUT "Description: ", RecordVar.Description%@NL@%
  16488. %@NL@%
  16489. %@AB@%                ' Call the Filter$ FUNCTION to input price & quantity:%@AE@%%@NL@%
  16490.                 RecordVar.UnitPrice = VAL(Filter$("Unit Price : "))%@NL@%
  16491.                 RecordVar.Quantity = VAL(Filter$("Quantity   : "))%@NL@%
  16492. %@NL@%
  16493.                 NumberOfRecords = NumberOfRecords + 1%@NL@%
  16494. %@NL@%
  16495.                 PUT #1, NumberOfRecords, RecordVar%@NL@%
  16496. %@NL@%
  16497.                 index(NumberOfRecords).RecordNumber = NumberOfRecords%@NL@%
  16498.                 index(NumberOfRecords).PartNumber = RecordVar.PartNumber%@NL@%
  16499.                 PRINT : PRINT "Add another? ";%@NL@%
  16500.                 OK$ = UCASE$(INPUT$(1))%@NL@%
  16501.         LOOP WHILE OK$ = "Y"%@NL@%
  16502. %@NL@%
  16503.         SortIndex            ' Sort index file again.%@NL@%
  16504. END SUB%@NL@%
  16505. %@NL@%
  16506. FUNCTION Filter$ (Prompt$) STATIC%@NL@%
  16507.         ValTemp2$ = ""%@NL@%
  16508.         PRINT Prompt$;                    ' Print the prompt passed.%@NL@%
  16509.         INPUT "", ValTemp1$               ' Input a number as%@NL@%
  16510. %@AB@%                                                                                                 ' a string.%@AE@%%@NL@%
  16511.         StringLength = LEN(ValTemp1$)     ' Get the string's length.%@NL@%
  16512.         FOR I% = 1 TO StringLength        ' Go through the string,%@NL@%
  16513.                 Char$ = MID$(ValTemp1$, I%, 1) ' one character at a time.%@NL@%
  16514. %@NL@%
  16515. %@AB@%                ' Is the character a valid part of a number (i.e.,%@AE@%%@NL@%
  16516. %@AB@%                ' a digit or a decimal point)?  If yes, add it to%@AE@%%@NL@%
  16517. %@AB@%                ' the end of a new string:%@AE@%%@NL@%
  16518.                 IF INSTR(".0123456789", Char$) > 0 THEN%@NL@%
  16519.                         ValTemp2$ = ValTemp2$ + Char$%@NL@%
  16520. %@NL@%
  16521. %@AB@%                ' Otherwise, check to see if it's a lowercase "l",%@AE@%%@NL@%
  16522. %@AB@%                ' since typewriter users may enter a one that way:%@AE@%%@NL@%
  16523.                 ELSEIF Char$ = "l" THEN%@NL@%
  16524.                         ValTemp2$ = ValTemp2$ + "1" ' Change the "l" to a "1".%@NL@%
  16525.                 END IF%@NL@%
  16526.         NEXT I%%@NL@%
  16527. %@NL@%
  16528.         Filter$ = ValTemp2$               ' Return filtered string.%@NL@%
  16529. %@NL@%
  16530. END FUNCTION%@NL@%
  16531. %@NL@%
  16532. FUNCTION FindRecord% (Part$, RecordVar AS StockItem) STATIC%@NL@%
  16533.         SHARED index() AS IndexType, NumberOfRecords%@NL@%
  16534. %@NL@%
  16535. %@AB@%        ' Set top and bottom bounds of search:%@AE@%%@NL@%
  16536.         TopRecord = NumberOfRecords%@NL@%
  16537.         BottomRecord = 1%@NL@%
  16538. %@NL@%
  16539. %@AB@%        ' Search until top of range is less than bottom:%@AE@%%@NL@%
  16540.         DO UNTIL (TopRecord < BottomRecord)%@NL@%
  16541. %@NL@%
  16542. %@AB@%                ' Choose midpoint:%@AE@%%@NL@%
  16543.                 Midpoint = (TopRecord + BottomRecord) \ 2%@NL@%
  16544. %@NL@%
  16545. %@AB@%                ' Test to see if it's the one wanted (RTRIM$()%@AE@%%@NL@%
  16546. %@AB@%                ' trims trailing blanks from a fixed string):%@AE@%%@NL@%
  16547.                 Test$ = RTRIM$(index(Midpoint).PartNumber)%@NL@%
  16548. %@NL@%
  16549. %@AB@%                ' If it is, exit loop:%@AE@%%@NL@%
  16550.                 IF Test$ = Part$ THEN%@NL@%
  16551.          EXIT DO%@NL@%
  16552. %@NL@%
  16553. %@AB@%                ' Otherwise, if what we're looking for is greater,%@AE@%%@NL@%
  16554. %@AB@%                ' move bottom up:%@AE@%%@NL@%
  16555.                 ELSEIF Part$ > Test$ THEN%@NL@%
  16556.          BottomRecord = Midpoint + 1%@NL@%
  16557. %@NL@%
  16558. %@AB@%                ' Otherwise, move the top down:%@AE@%%@NL@%
  16559.                 ELSE%@NL@%
  16560.          TopRecord = Midpoint - 1%@NL@%
  16561.                 END IF%@NL@%
  16562.         LOOP%@NL@%
  16563. %@NL@%
  16564. %@AB@%        ' If part was found, input record from file using%@AE@%%@NL@%
  16565. %@AB@%        ' pointer in index and set FindRecord% to TRUE:%@AE@%%@NL@%
  16566.         IF Test$ = Part$ THEN%@NL@%
  16567.                 GET #1, index(Midpoint).RecordNumber, RecordVar%@NL@%
  16568.                 FindRecord% = TRUE%@NL@%
  16569. %@NL@%
  16570. %@AB@%        ' Otherwise, if part was not found, set FindRecord%%@AE@%%@NL@%
  16571. %@AB@%        ' to FALSE:%@AE@%%@NL@%
  16572.         ELSE%@NL@%
  16573.                 FindRecord% = FALSE%@NL@%
  16574.         END IF%@NL@%
  16575. END FUNCTION%@NL@%
  16576. %@NL@%
  16577. %@AB@%' ======================= INPUTRECORD =====================%@AE@%%@NL@%
  16578. %@AB@%'    First, INPUTRECORD calls SHOWPARTNUMBERS, which prints%@AE@%%@NL@%
  16579. %@AB@%'    a menu of part numbers on the top of the screen. Next,%@AE@%%@NL@%
  16580. %@AB@%'    INPUTRECORD prompts the user to enter a part number.%@AE@%%@NL@%
  16581. %@AB@%'    Finally, it calls the FINDRECORD and PRINTRECORD%@AE@%%@NL@%
  16582. %@AB@%'    procedures to find and print the given record.%@AE@%%@NL@%
  16583. %@AB@%' =========================================================%@AE@%%@NL@%
  16584. SUB InputRecord (RecordVar AS StockItem) STATIC%@NL@%
  16585.         CLS%@NL@%
  16586.         ShowPartNumbers      ' Call the ShowPartNumbers SUB.%@NL@%
  16587. %@NL@%
  16588. %@AB@%        ' Print data from specified records%@AE@%%@NL@%
  16589. %@AB@%        ' on the bottom part of the screen:%@AE@%%@NL@%
  16590.         DO%@NL@%
  16591.                 PRINT "Type a part number listed above ";%@NL@%
  16592.                 INPUT "(or Q to quit) and press <ENTER>: ", Part$%@NL@%
  16593.                 IF UCASE$(Part$) <> "Q" THEN%@NL@%
  16594.          IF FindRecord(Part$, RecordVar) THEN%@NL@%
  16595.                  PrintRecord RecordVar%@NL@%
  16596.          ELSE%@NL@%
  16597.                  PRINT "Part not found."%@NL@%
  16598.          END IF%@NL@%
  16599.                 END IF%@NL@%
  16600.                 PRINT STRING$(40, "_")%@NL@%
  16601.         LOOP WHILE UCASE$(Part$) <> "Q"%@NL@%
  16602. %@NL@%
  16603.         VIEW PRINT   ' Restore the text viewport to entire screen.%@NL@%
  16604. END SUB%@NL@%
  16605. %@NL@%
  16606. SUB PrintRecord (RecordVar AS StockItem) STATIC%@NL@%
  16607.         PRINT "Part Number: "; RecordVar.PartNumber%@NL@%
  16608.         PRINT "Description: "; RecordVar.Description%@NL@%
  16609.         PRINT USING "Unit Price :$$###.##"; RecordVar.UnitPrice%@NL@%
  16610.         PRINT "Quantity   :"; RecordVar.Quantity%@NL@%
  16611. END SUB%@NL@%
  16612. %@NL@%
  16613. SUB ShowPartNumbers STATIC%@NL@%
  16614.         SHARED index() AS IndexType, NumberOfRecords%@NL@%
  16615. %@NL@%
  16616.         CONST NUMCOLS = 8, COLWIDTH = 80 \ NUMCOLS%@NL@%
  16617. %@NL@%
  16618. %@AB@%        ' At the top of the screen, print a menu indexing all%@AE@%%@NL@%
  16619. %@AB@%        ' the part numbers for records in the file. This menu is%@AE@%%@NL@%
  16620. %@AB@%        ' printed in columns of equal length (except possibly the%@AE@%%@NL@%
  16621. %@AB@%        ' last column, which may be shorter than the others):%@AE@%%@NL@%
  16622.         ColumnLength = NumberOfRecords%@NL@%
  16623.         DO WHILE ColumnLength MOD NUMCOLS%@NL@%
  16624.                 ColumnLength = ColumnLength + 1%@NL@%
  16625.         LOOP%@NL@%
  16626.         ColumnLength = ColumnLength \ NUMCOLS%@NL@%
  16627.         Column = 1%@NL@%
  16628.         RecordNumber = 1%@NL@%
  16629. DO UNTIL RecordNumber > NumberOfRecords%@NL@%
  16630.                 FOR Row = 1 TO ColumnLength%@NL@%
  16631.          LOCATE Row, Column%@NL@%
  16632.          PRINT index(RecordNumber).PartNumber%@NL@%
  16633.          RecordNumber = RecordNumber + 1%@NL@%
  16634.          IF RecordNumber > NumberOfRecords THEN EXIT FOR%@NL@%
  16635.                 NEXT Row%@NL@%
  16636.                 Column = Column + COLWIDTH%@NL@%
  16637.         LOOP%@NL@%
  16638. %@NL@%
  16639.         LOCATE ColumnLength + 1, 1%@NL@%
  16640.         PRINT STRING$(80, "_")       ' Print separator line.%@NL@%
  16641. %@NL@%
  16642. %@AB@%        ' Scroll information about records below the part-number%@AE@%%@NL@%
  16643. %@AB@%        ' menu (this way, the part numbers are not erased):%@AE@%%@NL@%
  16644.         VIEW PRINT ColumnLength + 2 TO 24%@NL@%
  16645. END SUB%@NL@%
  16646. %@NL@%
  16647. SUB SortIndex STATIC%@NL@%
  16648.         SHARED index() AS IndexType, NumberOfRecords%@NL@%
  16649. %@NL@%
  16650. %@AB@%        ' Set comparison offset to half the number of records%@AE@%%@NL@%
  16651. %@AB@%        ' in index:%@AE@%%@NL@%
  16652.         Offset = NumberOfRecords \ 2%@NL@%
  16653. %@NL@%
  16654. %@AB@%        ' Loop until offset gets to zero:%@AE@%%@NL@%
  16655.         DO WHILE Offset > 0%@NL@%
  16656.                 Limit = NumberOfRecords - Offset%@NL@%
  16657.                 DO%@NL@%
  16658. %@NL@%
  16659. %@AB@%         ' Assume no switches at this offset:%@AE@%%@NL@%
  16660.          Switch = FALSE%@NL@%
  16661. %@NL@%
  16662. %@AB@%         ' Compare elements and switch ones out of order:%@AE@%%@NL@%
  16663.          FOR I = 1 TO Limit%@NL@%
  16664.                  IF index(I).PartNumber > index(I + Offset).PartNumber THEN%@NL@%
  16665.                          SWAP index(I), index(I + Offset)%@NL@%
  16666.                          Switch = I%@NL@%
  16667.                  END IF%@NL@%
  16668.          NEXT I%@NL@%
  16669. %@NL@%
  16670. %@AB@%         ' Sort on next pass only to where%@AE@%%@NL@%
  16671. %@AB@%         ' last switch was made:%@AE@%%@NL@%
  16672.          Limit = Switch%@NL@%
  16673.                 LOOP WHILE Switch%@NL@%
  16674. %@NL@%
  16675. %@AB@%                ' No switches at last offset, try one half as big:%@AE@%%@NL@%
  16676.                 Offset = Offset \ 2%@NL@%
  16677.         LOOP%@NL@%
  16678. END SUB%@NL@%
  16679. %@NL@%
  16680. %@NL@%
  16681. %@NL@%
  16682. %@2@%%@AH@%MANDEL.BAS%@AE@%%@EH@%%@NL@%
  16683. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\MANDEL.BAS%@AE@%%@NL@%
  16684. %@NL@%
  16685. DEFINT A-Z           ' Default variable type is integer.%@NL@%
  16686. %@NL@%
  16687. DECLARE        SUB ShiftPalette ()%@NL@%
  16688. DECLARE        SUB WindowVals (WL%, WR%, WT%, WB%)%@NL@%
  16689. DECLARE        SUB ScreenTest (EM%, CR%, VL%, VR%, VT%, VB%)%@NL@%
  16690. %@NL@%
  16691. CONST FALSE = 0, TRUE = NOT FALSE ' Boolean constants%@NL@%
  16692. %@NL@%
  16693. %@AB@%' Set maximum number of iterations per point:%@AE@%%@NL@%
  16694. CONST MAXLOOP =        30, MAXSIZE = 1000000%@NL@%
  16695. %@NL@%
  16696. DIM PaletteArray(15)%@NL@%
  16697. FOR I =        0 TO 15: PaletteArray(I) = I: NEXT I%@NL@%
  16698. %@NL@%
  16699. %@AB@%' Call WindowVals to get coordinates of window corners:%@AE@%%@NL@%
  16700. WindowVals WLeft, WRight, WTop,        WBottom%@NL@%
  16701. %@NL@%
  16702. %@AB@%' Call ScreenTest to find out if this is an EGA machine%@AE@%%@NL@%
  16703. %@AB@%' and get coordinates of viewport corners:%@AE@%%@NL@%
  16704. ScreenTest EgaMode, ColorRange,        VLeft, VRight, VTop, VBottom%@NL@%
  16705. %@NL@%
  16706. %@AB@%' Define viewport and corresponding window:%@AE@%%@NL@%
  16707. VIEW (VLeft, VTop)-(VRight, VBottom), 0, ColorRange%@NL@%
  16708. WINDOW (WLeft, WTop)-(WRight, WBottom)%@NL@%
  16709. %@NL@%
  16710. LOCATE 24, 10 : PRINT "Press any key to quit.";%@NL@%
  16711. %@NL@%
  16712. XLength        = VRight - VLeft%@NL@%
  16713. YLength        = VBottom - VTop%@NL@%
  16714. ColorWidth = MAXLOOP \ ColorRange%@NL@%
  16715. %@NL@%
  16716. %@AB@%' Loop through each pixel in viewport and calculate%@AE@%%@NL@%
  16717. %@AB@%' whether or not it is in the Mandelbrot Set:%@AE@%%@NL@%
  16718. FOR Y =        0 TO YLength           ' Loop through every line%@NL@%
  16719. %@AB@%                           ' in the viewport.%@AE@%%@NL@%
  16720.    LogicY = PMAP(Y, 3)           ' Get the pixel's view%@NL@%
  16721. %@AB@%                           ' y-coordinate.%@AE@%%@NL@%
  16722.    PSET        (WLeft,        LogicY)           ' Plot leftmost pixel in the line.%@NL@%
  16723.    OldColor = 0                   ' Start with background color.%@NL@%
  16724. %@NL@%
  16725.    FOR X = 0 TO        XLength           ' Loop through every pixel%@NL@%
  16726. %@AB@%                           ' in the line.%@AE@%%@NL@%
  16727.       LogicX = PMAP(X, 2)  ' Get the pixel's view%@NL@%
  16728. %@AB@%                           ' x-coordinate.%@AE@%%@NL@%
  16729.       MandelX& = LogicX%@NL@%
  16730.       MandelY& = LogicY%@NL@%
  16731. %@AB@%      ' Do the calculations to see if this point%@AE@%%@NL@%
  16732. %@AB@%      ' is in the Mandelbrot Set:%@AE@%%@NL@%
  16733.       FOR I = 1        TO MAXLOOP%@NL@%
  16734.          RealNum& = MandelX& * MandelX&%@NL@%
  16735.          ImagNum& = MandelY& * MandelY&%@NL@%
  16736.          IF (RealNum& + ImagNum&) >= MAXSIZE THEN EXIT FOR%@NL@%
  16737.          MandelY& = (MandelX& * MandelY&) \ 250 + LogicY%@NL@%
  16738.          MandelX& = (RealNum& - ImagNum&) \ 500 + LogicX%@NL@%
  16739.       NEXT I%@NL@%
  16740. %@NL@%
  16741. %@AB@%      '        Assign a color to the point:%@AE@%%@NL@%
  16742.       PColor = I \ ColorWidth%@NL@%
  16743. %@NL@%
  16744. %@AB@%      '        If color has changed, draw a line from%@AE@%%@NL@%
  16745. %@AB@%      ' the last point referenced to the new point,%@AE@%%@NL@%
  16746. %@AB@%      '        using the old color:%@AE@%%@NL@%
  16747.       IF PColor        <> OldColor THEN%@NL@%
  16748.          LINE -(LogicX, LogicY), (ColorRange - OldColor)%@NL@%
  16749.          OldColor = PColor%@NL@%
  16750.       END IF%@NL@%
  16751. %@NL@%
  16752.       IF INKEY$        <> "" THEN END%@NL@%
  16753.    NEXT        X%@NL@%
  16754. %@NL@%
  16755. %@AB@%   ' Draw the last line        segment        to the right edge%@AE@%%@NL@%
  16756. %@AB@%   ' of the viewport:%@AE@%%@NL@%
  16757.    LINE        -(LogicX, LogicY), (ColorRange - OldColor)%@NL@%
  16758. %@NL@%
  16759. %@AB@%   ' If        this is        an EGA machine,        shift the palette after%@AE@%%@NL@%
  16760. %@AB@%   ' drawing each line:%@AE@%%@NL@%
  16761.    IF EgaMode THEN ShiftPalette%@NL@%
  16762. NEXT Y%@NL@%
  16763. %@NL@%
  16764. DO%@NL@%
  16765. %@AB@%   ' Continue shifting the palette%@AE@%%@NL@%
  16766. %@AB@%   ' until the user presses a key:%@AE@%%@NL@%
  16767.    IF EgaMode THEN ShiftPalette%@NL@%
  16768. LOOP WHILE INKEY$ = ""%@NL@%
  16769. %@NL@%
  16770. SCREEN 0, 0                ' Restore the screen to text mode,%@NL@%
  16771. WIDTH 80                ' 80 columns.%@NL@%
  16772. END%@NL@%
  16773. %@NL@%
  16774. BadScreen:                ' Error handler that is invoked if%@NL@%
  16775.    EgaMode = FALSE        ' there is no EGA graphics card%@NL@%
  16776.    RESUME NEXT%@NL@%
  16777. %@AB@%' ====================== ShiftPalette =====================%@AE@%%@NL@%
  16778. %@AB@%'    Rotates the palette by one each time it is called%@AE@%%@NL@%
  16779. %@AB@%' =========================================================%@AE@%%@NL@%
  16780. %@NL@%
  16781. SUB ShiftPalette STATIC%@NL@%
  16782.    SHARED PaletteArray(), ColorRange%@NL@%
  16783. %@NL@%
  16784.    FOR I = 1 TO        ColorRange%@NL@%
  16785.       PaletteArray(I) =        (PaletteArray(I) MOD ColorRange) + 1%@NL@%
  16786.    NEXT        I%@NL@%
  16787.    PALETTE USING PaletteArray(0)%@NL@%
  16788. %@NL@%
  16789. END SUB%@NL@%
  16790. %@AB@%' ======================= ScreenTest ======================%@AE@%%@NL@%
  16791. %@AB@%'    Uses a SCREEN 8 statement as a test to see if user has%@AE@%%@NL@%
  16792. %@AB@%'    EGA hardware. If this causes an error, the EM flag is%@AE@%%@NL@%
  16793. %@AB@%'    set to FALSE, and the screen is set with SCREEN 1.%@AE@%%@NL@%
  16794. %@NL@%
  16795. %@AB@%'    Also sets values for corners of viewport (VL = left,%@AE@%%@NL@%
  16796. %@AB@%'    VR = right, VT = top, VB = bottom), scaled with the%@AE@%%@NL@%
  16797. %@AB@%'    correct aspect ratio so viewport is a perfect square.%@AE@%%@NL@%
  16798. %@AB@%' =========================================================%@AE@%%@NL@%
  16799. %@NL@%
  16800. SUB ScreenTest (EM, CR,        VL, VR,        VT, VB) STATIC%@NL@%
  16801.    EM =        TRUE%@NL@%
  16802.    ON ERROR GOTO BadScreen%@NL@%
  16803.    SCREEN 8, 1%@NL@%
  16804.    ON ERROR GOTO 0%@NL@%
  16805. %@NL@%
  16806.    IF EM THEN                        ' No error, SCREEN 8 is OK.%@NL@%
  16807.       VL = 110: VR = 529%@NL@%
  16808.       VT = 5: VB = 179%@NL@%
  16809.       CR = 15                        ' 16 colors (0 - 15)%@NL@%
  16810. %@NL@%
  16811.    ELSE                                ' Error, so use SCREEN 1.%@NL@%
  16812.       SCREEN 1,        1%@NL@%
  16813.       VL = 55: VR = 264%@NL@%
  16814.       VT = 5: VB = 179%@NL@%
  16815.       CR = 3                        ' 4 colors (0 - 3)%@NL@%
  16816.    END IF%@NL@%
  16817. %@NL@%
  16818. END SUB%@NL@%
  16819. %@AB@%' ======================= WindowVals ======================%@AE@%%@NL@%
  16820. %@AB@%'     Gets window corners as input from the user, or sets%@AE@%%@NL@%
  16821. %@AB@%'     values for the corners if there is no input%@AE@%%@NL@%
  16822. %@AB@%' =========================================================%@AE@%%@NL@%
  16823. %@NL@%
  16824. SUB WindowVals (WL, WR,        WT, WB)        STATIC%@NL@%
  16825.    CLS%@NL@%
  16826.    PRINT "This program prints the graphic representation of"%@NL@%
  16827.    PRINT "the complete Mandelbrot Set. The default window"%@NL@%
  16828.    PRINT "is from (-1000,625) to (250,-625). To zoom in on"%@NL@%
  16829.    PRINT "part of the figure, input coordinates inside"%@NL@%
  16830.    PRINT "this window."%@NL@%
  16831.    PRINT "Press <ENTER> to see the default window or"%@NL@%
  16832.    PRINT "any other key to input window coordinates: ";%@NL@%
  16833.    LOCATE , , 1%@NL@%
  16834.    Resp$ = INPUT$(1)%@NL@%
  16835. %@NL@%
  16836. %@AB@%   ' User didn't press ENTER, so input window corners:%@AE@%%@NL@%
  16837.    IF Resp$ <> CHR$(13)        THEN%@NL@%
  16838.       PRINT%@NL@%
  16839.       INPUT "x-coordinate of upper-left corner: ", WL%@NL@%
  16840.       DO%@NL@%
  16841.          INPUT "x-coordinate of lower-right corner: ", WR%@NL@%
  16842.          IF WR <= WL THEN%@NL@%
  16843.             PRINT "Right corner must be greater than left corner."%@NL@%
  16844.          END IF%@NL@%
  16845.       LOOP WHILE WR <= WL%@NL@%
  16846.       INPUT "y-coordinate of upper-left corner: ", WT%@NL@%
  16847.       DO%@NL@%
  16848.          INPUT "y-coordinate of lower-right corner: ", WB%@NL@%
  16849.          IF WB >= WT THEN%@NL@%
  16850.             PRINT "Bottom corner must be less than top corner."%@NL@%
  16851.          END IF%@NL@%
  16852.       LOOP WHILE WB >= WT%@NL@%
  16853. %@NL@%
  16854. %@AB@%   ' User pressed ENTER, so set default values:%@AE@%%@NL@%
  16855.    ELSE%@NL@%
  16856.       WL = -1000%@NL@%
  16857.       WR = 250%@NL@%
  16858.       WT = 625%@NL@%
  16859.       WB = -625%@NL@%
  16860.    END IF%@NL@%
  16861. END SUB%@NL@%
  16862. %@NL@%
  16863. %@NL@%
  16864. %@NL@%
  16865. %@2@%%@AH@%MATB.BAS%@AE@%%@EH@%%@NL@%
  16866. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\MATB.BAS%@AE@%%@NL@%
  16867. %@NL@%
  16868. %@AB@%'*** MATB.BAS - Matrix Math Routines for the Matrix Math Toolbox in%@AE@%%@NL@%
  16869. %@AB@%'           Microsoft BASIC 7.0, Professional Development System%@AE@%%@NL@%
  16870. %@AB@%'              Copyright (C) 1987-1989, Microsoft Corporation%@AE@%%@NL@%
  16871. %@AB@%'%@AE@%%@NL@%
  16872. %@AB@%'  NOTE:  This sample source code toolbox is intended to demonstrate some%@AE@%%@NL@%
  16873. %@AB@%'  of the extended capabilities of Microsoft BASIC 7.0 Professional Development%@AE@%%@NL@%
  16874. %@AB@%'  system that can help to leverage the professional developer's time more%@AE@%%@NL@%
  16875. %@AB@%'  effectively.  While you are free to use, modify, or distribute the routines%@AE@%%@NL@%
  16876. %@AB@%'  in this module in any way you find useful, it should be noted that these are%@AE@%%@NL@%
  16877. %@AB@%'  examples only and should not be relied upon as a fully-tested "add-on"%@AE@%%@NL@%
  16878. %@AB@%'  library.%@AE@%%@NL@%
  16879. %@AB@%'%@AE@%%@NL@%
  16880. %@AB@%'  Purpose:%@AE@%%@NL@%
  16881. %@AB@%'This toolbox contains routines which perform elementary operations on systems%@AE@%%@NL@%
  16882. %@AB@%'of linear equations represented as matrices.  The functions return integer%@AE@%%@NL@%
  16883. %@AB@%'error codes in the name and results in the parameter list.  The functions%@AE@%%@NL@%
  16884. %@AB@%'matbs?% and matlu?% found in this module are intended for internal use only.%@AE@%%@NL@%
  16885. %@AB@%'Error codes returned:%@AE@%%@NL@%
  16886. %@AB@%'     0  no error                     -1  matrix not invertible%@AE@%%@NL@%
  16887. %@AB@%'    -2  matrix not square            -3  inner dimensions different%@AE@%%@NL@%
  16888. %@AB@%'    -4  matrix dimensions different  -5  result matrix dimensioned incorrectly%@AE@%%@NL@%
  16889. %@AB@%'    any other codes returned are standard BASIC errors%@AE@%%@NL@%
  16890. %@AB@%'%@AE@%%@NL@%
  16891. %@AB@%'-------------------------------------------------------------------%@AE@%%@NL@%
  16892. %@AB@%'MatDet, MatSEqn, and MatInv all use LU-decomposition to implement Gaussian%@AE@%%@NL@%
  16893. %@AB@%'elimination.  A brief explanation of what is meant by an LU matrix is given%@AE@%%@NL@%
  16894. %@AB@%'below, followed by simplified versions of the two internal routines used to%@AE@%%@NL@%
  16895. %@AB@%'do all elimination.%@AE@%%@NL@%
  16896. %@AB@%'%@AE@%%@NL@%
  16897. %@AB@%'What is meant by an LU matrix:%@AE@%%@NL@%
  16898. %@AB@%'An upper triangle matrix (one with all nonzero entries on or above the main%@AE@%%@NL@%
  16899. %@AB@%'diagonal) can be solved immediately.  The goal of Gaussian elimination is to%@AE@%%@NL@%
  16900. %@AB@%'transform a non upper triangle system into an equivalent triangular one.%@AE@%%@NL@%
  16901. %@AB@%'%@AE@%%@NL@%
  16902. %@AB@%'Given a system of equations represented in matrix form by Ax=b, we need a%@AE@%%@NL@%
  16903. %@AB@%'linear transformation L such that LA=U where U is and upper triangular matrix.%@AE@%%@NL@%
  16904. %@AB@%'Then Ux=LAx=Lb and Ux=Lb is an upper triangular system.%@AE@%%@NL@%
  16905. %@AB@%'%@AE@%%@NL@%
  16906. %@AB@%'This library explicitly calculates U, but L is never saved in its own array.%@AE@%%@NL@%
  16907. %@AB@%'When we do a row operation to create a zero below the main diagonal, we no%@AE@%%@NL@%
  16908. %@AB@%'longer need to save that value because we know it is zero.  This leaves the%@AE@%%@NL@%
  16909. %@AB@%'space available to save the multiplier used in the row operation.  When%@AE@%%@NL@%
  16910. %@AB@%'elimination is completed (ie, when the matrix is upper triangular), these%@AE@%%@NL@%
  16911. %@AB@%'multipliers give us a complete record of what we did to A to make it upper%@AE@%%@NL@%
  16912. %@AB@%'triangular.  This is equivalent to saying the multipliers represent L.  We now%@AE@%%@NL@%
  16913. %@AB@%'have a U and an L stored in the same matrix!  This type of matrix will be%@AE@%%@NL@%
  16914. %@AB@%'referred to as an LU matrix, or just LU.%@AE@%%@NL@%
  16915. %@AB@%'%@AE@%%@NL@%
  16916. %@AB@%'The following code fragments get LU and backsolve Ux=Lb.  The actual routines%@AE@%%@NL@%
  16917. %@AB@%'used in the toolbox are much more involved because they implement total%@AE@%%@NL@%
  16918. %@AB@%'pivoting and implicit row scaling to reduce round off errors.  However, all the%@AE@%%@NL@%
  16919. %@AB@%'extras (pivoting, scaling, error checking) are extraneous to the main routines,%@AE@%%@NL@%
  16920. %@AB@%'which total only 20 lines.  If you are unfamilar with this type of matrix math,%@AE@%%@NL@%
  16921. %@AB@%'gaining an understanding of these 20 lines is a very good introduction.  Try%@AE@%%@NL@%
  16922. %@AB@%'working through a 2x2 or 3x3 example by hand to see what is happening.  The%@AE@%%@NL@%
  16923. %@AB@%'numerical techniques used to reduce round off error will not be discussed.%@AE@%%@NL@%
  16924. %@AB@%'%@AE@%%@NL@%
  16925. %@AB@%'-------------------------------------------------------------------%@AE@%%@NL@%
  16926. %@AB@%'Given the coefficient matrix A(1 TO N, 1 TO N) and the vector b(1 TO N),%@AE@%%@NL@%
  16927. %@AB@%'the following fragments will find x(1 TO N) satisfying Ax=b using Gaussian%@AE@%%@NL@%
  16928. %@AB@%'elimination.%@AE@%%@NL@%
  16929. %@AB@%'%@AE@%%@NL@%
  16930. %@AB@%'matlu:%@AE@%%@NL@%
  16931. %@AB@%'Perform row operations to get all zeroes below the main diagonal.%@AE@%%@NL@%
  16932. %@AB@%'Define Rj(1 TO N) to be the vector corresponding to the jth row of A.%@AE@%%@NL@%
  16933. %@AB@%'Let Rrow = Rrow + m*Rpvt where m = -Rrow(pvt)/Rpvt(pvt).%@AE@%%@NL@%
  16934. %@AB@%'Then A(row, pvt)=0.%@AE@%%@NL@%
  16935. %@AB@%'%@AE@%%@NL@%
  16936. %@AB@%'** FOR pvt = 1 TO (N - 1)%@AE@%%@NL@%
  16937. %@AB@%'**    FOR row = (pvt + 1) TO N%@AE@%%@NL@%
  16938. %@AB@%'**       'Save m for later use in the space just made 0.%@AE@%%@NL@%
  16939. %@AB@%'**       A(row, pvt) = -A(row, pvt) / A(pvt, pvt)%@AE@%%@NL@%
  16940. %@AB@%'**       'Do the row operation.%@AE@%%@NL@%
  16941. %@AB@%'**       FOR col = (pvt + 1) TO N%@AE@%%@NL@%
  16942. %@AB@%'**          A(row, col) = A(row, col) + A(row, pvt) * A(pvt, col)%@AE@%%@NL@%
  16943. %@AB@%'**       NEXT col%@AE@%%@NL@%
  16944. %@AB@%'**    NEXT row%@AE@%%@NL@%
  16945. %@AB@%'** NEXT pvt%@AE@%%@NL@%
  16946. %@AB@%'%@AE@%%@NL@%
  16947. %@AB@%'matbs:%@AE@%%@NL@%
  16948. %@AB@%'Do the same row operations on b using the multipliers saved in A.%@AE@%%@NL@%
  16949. %@AB@%'%@AE@%%@NL@%
  16950. %@AB@%'** FOR pvt = 1 TO (N - 1)%@AE@%%@NL@%
  16951. %@AB@%'**    FOR row = (pvt + 1) TO N%@AE@%%@NL@%
  16952. %@AB@%'**       b(row) = b(row) + A(row, pvt) * b(pvt)%@AE@%%@NL@%
  16953. %@AB@%'**    NEXT row%@AE@%%@NL@%
  16954. %@AB@%'** NEXT pvt%@AE@%%@NL@%
  16955. %@AB@%'%@AE@%%@NL@%
  16956. %@AB@%'Backsolve Ux=Lb to find x.%@AE@%%@NL@%
  16957. %@AB@%'                               N%@AE@%%@NL@%
  16958. %@AB@%'For r = N to 1, x(r) = [b(r) - Σ (A(r,c)*x(c))]/A(r,r)%@AE@%%@NL@%
  16959. %@AB@%'                              c=r+1%@AE@%%@NL@%
  16960. %@AB@%'** FOR row = N TO 1 STEP -1%@AE@%%@NL@%
  16961. %@AB@%'**    x(row) = b(row)%@AE@%%@NL@%
  16962. %@AB@%'**    FOR col = (row + 1) TO N%@AE@%%@NL@%
  16963. %@AB@%'**       x(row) = x(row) - A(row, col) * x(col)%@AE@%%@NL@%
  16964. %@AB@%'**    NEXT col%@AE@%%@NL@%
  16965. %@AB@%'**    x(row) = x(row) / A(row, row)%@AE@%%@NL@%
  16966. %@AB@%'** NEXT row%@AE@%%@NL@%
  16967. %@AB@%'%@AE@%%@NL@%
  16968. %@AB@%'===================================================================%@AE@%%@NL@%
  16969. %@AB@%'$INCLUDE: 'matb.bi'%@AE@%%@NL@%
  16970. DECLARE FUNCTION matbsD% (A() AS DOUBLE, b() AS DOUBLE, x() AS DOUBLE)%@NL@%
  16971. DECLARE FUNCTION matbsS% (A() AS SINGLE, b() AS SINGLE, x() AS SINGLE)%@NL@%
  16972. DECLARE FUNCTION matluD% (A() AS DOUBLE)%@NL@%
  16973. DECLARE FUNCTION matluS% (A() AS SINGLE)%@NL@%
  16974. DIM SHARED lo AS INTEGER, up AS INTEGER%@NL@%
  16975. DIM SHARED continue AS INTEGER, count AS INTEGER%@NL@%
  16976. DIM SHARED rpvt(lo TO up) AS INTEGER, cpvt(lo TO up) AS INTEGER%@NL@%
  16977. END%@NL@%
  16978. %@NL@%
  16979. %@AB@%'=======================MatAddC%====================================%@AE@%%@NL@%
  16980. %@AB@%'MatAddC% adds two currency type matrices and places the sum in%@AE@%%@NL@%
  16981. %@AB@%'the first.%@AE@%%@NL@%
  16982. %@AB@%'%@AE@%%@NL@%
  16983. %@AB@%'Parameters: matrices Alpha,Beta%@AE@%%@NL@%
  16984. %@AB@%'%@AE@%%@NL@%
  16985. %@AB@%'Returns: Alpha() = Alpha() + Beta()%@AE@%%@NL@%
  16986. %@AB@%'===================================================================%@AE@%%@NL@%
  16987. FUNCTION MatAddC% (Alpha() AS CURRENCY, Beta() AS CURRENCY)%@NL@%
  16988. ON LOCAL ERROR GOTO cadderr: MatAddC% = 0%@NL@%
  16989. %@AB@%'check if Alpha, Beta have same dimensions if not, exit and send back error%@AE@%%@NL@%
  16990. IF (LBOUND(Alpha, 1) <> LBOUND(Beta, 1)) OR (UBOUND(Alpha, 1) <> UBOUND(Beta, 1)) OR (LBOUND(Alpha, 2) <> LBOUND(Beta, 2)) OR (UBOUND(Alpha, 2) <> UBOUND(Beta, 2)) THEN ERROR 196%@NL@%
  16991. %@AB@%'loop through and add elements%@AE@%%@NL@%
  16992. FOR row% = LBOUND(Alpha, 1) TO UBOUND(Alpha, 1)%@NL@%
  16993.    FOR col% = LBOUND(Alpha, 2) TO UBOUND(Alpha, 2)%@NL@%
  16994.       Alpha(row%, col%) = Alpha(row%, col%) + Beta(row%, col%)%@NL@%
  16995.    NEXT col%%@NL@%
  16996. NEXT row%%@NL@%
  16997. caddexit:%@NL@%
  16998. EXIT FUNCTION%@NL@%
  16999. cadderr:%@NL@%
  17000.    MatAddC% = (ERR + 5) MOD 200 - 5%@NL@%
  17001.    RESUME caddexit%@NL@%
  17002. END FUNCTION%@NL@%
  17003. %@NL@%
  17004. %@AB@%'=======================MatAddD%====================================%@AE@%%@NL@%
  17005. %@AB@%'MatAddD% adds two double precision matrices and places the sum in%@AE@%%@NL@%
  17006. %@AB@%'the first.%@AE@%%@NL@%
  17007. %@AB@%'%@AE@%%@NL@%
  17008. %@AB@%'Parameters: matrices Alpha,Beta%@AE@%%@NL@%
  17009. %@AB@%'%@AE@%%@NL@%
  17010. %@AB@%'Returns: Alpha() = Alpha() + Beta()%@AE@%%@NL@%
  17011. %@AB@%'===================================================================%@AE@%%@NL@%
  17012. FUNCTION MatAddD% (Alpha() AS DOUBLE, Beta() AS DOUBLE)%@NL@%
  17013. ON LOCAL ERROR GOTO dadderr: MatAddD% = 0%@NL@%
  17014. %@AB@%'check if Alpha, Beta have same dimensions if not, exit and send back error%@AE@%%@NL@%
  17015. IF (LBOUND(Alpha, 1) <> LBOUND(Beta, 1)) OR (UBOUND(Alpha, 1) <> UBOUND(Beta, 1)) OR (LBOUND(Alpha, 2) <> LBOUND(Beta, 2)) OR (UBOUND(Alpha, 2) <> UBOUND(Beta, 2)) THEN ERROR 196%@NL@%
  17016. %@AB@%'loop through and add elements%@AE@%%@NL@%
  17017. FOR row% = LBOUND(Alpha, 1) TO UBOUND(Alpha, 1)%@NL@%
  17018.    FOR col% = LBOUND(Alpha, 2) TO UBOUND(Alpha, 2)%@NL@%
  17019.       Alpha(row%, col%) = Alpha(row%, col%) + Beta(row%, col%)%@NL@%
  17020.    NEXT col%%@NL@%
  17021. NEXT row%%@NL@%
  17022. daddexit:%@NL@%
  17023. EXIT FUNCTION%@NL@%
  17024. dadderr:%@NL@%
  17025.    MatAddD% = (ERR + 5) MOD 200 - 5%@NL@%
  17026.    RESUME daddexit%@NL@%
  17027. END FUNCTION%@NL@%
  17028. %@NL@%
  17029. %@AB@%'=======================MatAddI%====================================%@AE@%%@NL@%
  17030. %@AB@%'MatAddI% adds two integer matrices and places the sum in%@AE@%%@NL@%
  17031. %@AB@%'the first.%@AE@%%@NL@%
  17032. %@AB@%'%@AE@%%@NL@%
  17033. %@AB@%'Parameters: matrices Alpha,Beta%@AE@%%@NL@%
  17034. %@AB@%'%@AE@%%@NL@%
  17035. %@AB@%'Returns: Alpha() = Alpha() + Beta()%@AE@%%@NL@%
  17036. %@AB@%'===================================================================%@AE@%%@NL@%
  17037. FUNCTION MatAddI% (Alpha() AS INTEGER, Beta() AS INTEGER)%@NL@%
  17038. ON LOCAL ERROR GOTO iadderr: MatAddI% = 0%@NL@%
  17039. %@AB@%'check if Alpha, Beta have same dimensions if not, exit and send back error%@AE@%%@NL@%
  17040. IF (LBOUND(Alpha, 1) <> LBOUND(Beta, 1)) OR (UBOUND(Alpha, 1) <> UBOUND(Beta, 1)) OR (LBOUND(Alpha, 2) <> LBOUND(Beta, 2)) OR (UBOUND(Alpha, 2) <> UBOUND(Beta, 2)) THEN ERROR 196%@NL@%
  17041. %@AB@%'loop through and add elements%@AE@%%@NL@%
  17042. FOR row% = LBOUND(Alpha, 1) TO UBOUND(Alpha, 1)%@NL@%
  17043.    FOR col% = LBOUND(Alpha, 2) TO UBOUND(Alpha, 2)%@NL@%
  17044.       Alpha(row%, col%) = Alpha(row%, col%) + Beta(row%, col%)%@NL@%
  17045.    NEXT col%%@NL@%
  17046. NEXT row%%@NL@%
  17047. iaddexit:%@NL@%
  17048. EXIT FUNCTION%@NL@%
  17049. iadderr:%@NL@%
  17050.    MatAddI% = (ERR + 5) MOD 200 - 5%@NL@%
  17051.    RESUME iaddexit%@NL@%
  17052. END FUNCTION%@NL@%
  17053. %@NL@%
  17054. %@AB@%'=======================MatAddL%====================================%@AE@%%@NL@%
  17055. %@AB@%'MatAddL% adds two long integer matrices and places the sum in%@AE@%%@NL@%
  17056. %@AB@%'the first.%@AE@%%@NL@%
  17057. %@AB@%'%@AE@%%@NL@%
  17058. %@AB@%'Parameters: matrices Alpha,Beta%@AE@%%@NL@%
  17059. %@AB@%'%@AE@%%@NL@%
  17060. %@AB@%'Returns: Alpha() = Alpha() + Beta()%@AE@%%@NL@%
  17061. %@AB@%'===================================================================%@AE@%%@NL@%
  17062. FUNCTION MatAddL% (Alpha() AS LONG, Beta() AS LONG)%@NL@%
  17063. ON LOCAL ERROR GOTO ladderr: MatAddL% = 0%@NL@%
  17064. %@AB@%'check if Alpha, Beta have same dimensions if not, exit and send back error%@AE@%%@NL@%
  17065. IF (LBOUND(Alpha, 1) <> LBOUND(Beta, 1)) OR (UBOUND(Alpha, 1) <> UBOUND(Beta, 1)) OR (LBOUND(Alpha, 2) <> LBOUND(Beta, 2)) OR (UBOUND(Alpha, 2) <> UBOUND(Beta, 2)) THEN ERROR 196%@NL@%
  17066. %@AB@%'loop through and add elements%@AE@%%@NL@%
  17067. FOR row% = LBOUND(Alpha, 1) TO UBOUND(Alpha, 1)%@NL@%
  17068.    FOR col% = LBOUND(Alpha, 2) TO UBOUND(Alpha, 2)%@NL@%
  17069.       Alpha(row%, col%) = Alpha(row%, col%) + Beta(row%, col%)%@NL@%
  17070.    NEXT col%%@NL@%
  17071. NEXT row%%@NL@%
  17072. laddexit:%@NL@%
  17073. EXIT FUNCTION%@NL@%
  17074. ladderr:%@NL@%
  17075.    MatAddL% = (ERR + 5) MOD 200 - 5%@NL@%
  17076.    RESUME laddexit%@NL@%
  17077. END FUNCTION%@NL@%
  17078. %@NL@%
  17079. %@AB@%'=======================MatAddS%====================================%@AE@%%@NL@%
  17080. %@AB@%'MatAddS% adds two single precision matrices and places the sum in%@AE@%%@NL@%
  17081. %@AB@%'the first.%@AE@%%@NL@%
  17082. %@AB@%'%@AE@%%@NL@%
  17083. %@AB@%'Parameters: matrices Alpha,Beta%@AE@%%@NL@%
  17084. %@AB@%'%@AE@%%@NL@%
  17085. %@AB@%'Returns: Alpha() = Alpha() + Beta()%@AE@%%@NL@%
  17086. %@AB@%'===================================================================%@AE@%%@NL@%
  17087. FUNCTION MatAddS% (Alpha() AS SINGLE, Beta() AS SINGLE)%@NL@%
  17088. ON LOCAL ERROR GOTO sadderr: MatAddS% = 0%@NL@%
  17089. %@AB@%'check if Alpha, Beta have same dimensions if not, exit and send back error%@AE@%%@NL@%
  17090. IF (LBOUND(Alpha, 1) <> LBOUND(Beta, 1)) OR (UBOUND(Alpha, 1) <> UBOUND(Beta, 1)) OR (LBOUND(Alpha, 2) <> LBOUND(Beta, 2)) OR (UBOUND(Alpha, 2) <> UBOUND(Beta, 2)) THEN ERROR 196%@NL@%
  17091. %@AB@%'loop through and add elements%@AE@%%@NL@%
  17092. FOR row% = LBOUND(Alpha, 1) TO UBOUND(Alpha, 1)%@NL@%
  17093.    FOR col% = LBOUND(Alpha, 2) TO UBOUND(Alpha, 2)%@NL@%
  17094.       Alpha(row%, col%) = Alpha(row%, col%) + Beta(row%, col%)%@NL@%
  17095.    NEXT col%%@NL@%
  17096. NEXT row%%@NL@%
  17097. saddexit:%@NL@%
  17098. EXIT FUNCTION%@NL@%
  17099. sadderr:%@NL@%
  17100.    MatAddS% = (ERR + 5) MOD 200 - 5%@NL@%
  17101.    RESUME saddexit%@NL@%
  17102. END FUNCTION%@NL@%
  17103. %@NL@%
  17104. %@AB@%'========================matbsD=====================================%@AE@%%@NL@%
  17105. %@AB@%'matbsD% takes a matrix in LU form, found by matluD%, and a vector b%@AE@%%@NL@%
  17106. %@AB@%'and solves the system Ux=Lb for x. matrices A,b,x are double precision.%@AE@%%@NL@%
  17107. %@AB@%'%@AE@%%@NL@%
  17108. %@AB@%'Parameters: LU matrix in A, corresponding pivot vectors in rpvt and cpvt,%@AE@%%@NL@%
  17109. %@AB@%'            right side in b%@AE@%%@NL@%
  17110. %@AB@%'%@AE@%%@NL@%
  17111. %@AB@%'Returns: solution in x, b is modified, rest unchanged%@AE@%%@NL@%
  17112. %@AB@%'===================================================================%@AE@%%@NL@%
  17113. FUNCTION matbsD% (A() AS DOUBLE, b() AS DOUBLE, x() AS DOUBLE)%@NL@%
  17114. ON LOCAL ERROR GOTO dbserr: matbsD% = 0%@NL@%
  17115. %@AB@%'do row operations on b using the multipliers in L to find Lb%@AE@%%@NL@%
  17116. FOR pvt% = lo TO (up - 1)%@NL@%
  17117.    c% = cpvt(pvt%)%@NL@%
  17118.    FOR row% = (pvt% + 1) TO up%@NL@%
  17119.       r% = rpvt(row%)%@NL@%
  17120.       b(r%) = b(r%) + A(r%, c%) * b(rpvt(pvt%))%@NL@%
  17121.    NEXT row%%@NL@%
  17122. NEXT pvt%%@NL@%
  17123. %@AB@%'backsolve Ux=Lb to find x%@AE@%%@NL@%
  17124. FOR row% = up TO lo STEP -1%@NL@%
  17125.    c% = cpvt(row%)%@NL@%
  17126.    r% = rpvt(row%)%@NL@%
  17127.    x(c%) = b(r%)%@NL@%
  17128.    FOR col% = (row% + 1) TO up%@NL@%
  17129.       x(c%) = x(c%) - A(r%, cpvt(col%)) * x(cpvt(col%))%@NL@%
  17130.    NEXT col%%@NL@%
  17131.    x(c%) = x(c%) / A(r%, c%)%@NL@%
  17132. NEXT row%%@NL@%
  17133. dbsexit:%@NL@%
  17134. EXIT FUNCTION%@NL@%
  17135. dbserr:%@NL@%
  17136.    matbsD% = ERR%@NL@%
  17137.    RESUME dbsexit%@NL@%
  17138. END FUNCTION%@NL@%
  17139. %@NL@%
  17140. %@AB@%'========================matbsS=====================================%@AE@%%@NL@%
  17141. %@AB@%'matbsS% takes a matrix in LU form, found by matluS%, and a vector b%@AE@%%@NL@%
  17142. %@AB@%'and solves the system Ux=Lb for x. matrices A,b,x are single precision.%@AE@%%@NL@%
  17143. %@AB@%'%@AE@%%@NL@%
  17144. %@AB@%'Parameters: LU matrix in A, corresponding pivot vectors in rpvt and cpvt,%@AE@%%@NL@%
  17145. %@AB@%'            right side in b%@AE@%%@NL@%
  17146. %@AB@%'%@AE@%%@NL@%
  17147. %@AB@%'Returns: solution in x, b is modified, rest unchanged%@AE@%%@NL@%
  17148. %@AB@%'===================================================================%@AE@%%@NL@%
  17149. FUNCTION matbsS% (A() AS SINGLE, b() AS SINGLE, x() AS SINGLE)%@NL@%
  17150. ON LOCAL ERROR GOTO sbserr: matbsS% = 0%@NL@%
  17151. %@AB@%'do row operations on b using the multipliers in L to find Lb%@AE@%%@NL@%
  17152. FOR pvt% = lo TO (up - 1)%@NL@%
  17153.    c% = cpvt(pvt%)%@NL@%
  17154.    FOR row% = (pvt% + 1) TO up%@NL@%
  17155.       r% = rpvt(row%)%@NL@%
  17156.       b(r%) = b(r%) + A(r%, c%) * b(rpvt(pvt%))%@NL@%
  17157.    NEXT row%%@NL@%
  17158. NEXT pvt%%@NL@%
  17159. %@AB@%'backsolve Ux=Lb to find x%@AE@%%@NL@%
  17160. FOR row% = up TO lo STEP -1%@NL@%
  17161.    c% = cpvt(row%)%@NL@%
  17162.    r% = rpvt(row%)%@NL@%
  17163.    x(c%) = b(r%)%@NL@%
  17164.    FOR col% = (row% + 1) TO up%@NL@%
  17165.       x(c%) = x(c%) - A(r%, cpvt(col%)) * x(cpvt(col%))%@NL@%
  17166.    NEXT col%%@NL@%
  17167.    x(c%) = x(c%) / A(r%, c%)%@NL@%
  17168. NEXT row%%@NL@%
  17169. sbsexit:%@NL@%
  17170. EXIT FUNCTION%@NL@%
  17171. sbserr:%@NL@%
  17172.    matbsS% = ERR%@NL@%
  17173.    RESUME sbsexit%@NL@%
  17174. END FUNCTION%@NL@%
  17175. %@NL@%
  17176. %@AB@%'========================MatDetC%===================================%@AE@%%@NL@%
  17177. %@AB@%'MatDetC% finds the determinant of a square, currency type matrix%@AE@%%@NL@%
  17178. %@AB@%'%@AE@%%@NL@%
  17179. %@AB@%'Parameters: A(n x n) matrix, det@ to return the determinant%@AE@%%@NL@%
  17180. %@AB@%'%@AE@%%@NL@%
  17181. %@AB@%'Returns: matrix A in LU form, determinant%@AE@%%@NL@%
  17182. %@AB@%'===================================================================%@AE@%%@NL@%
  17183. FUNCTION MatDetC% (A() AS CURRENCY, det@)%@NL@%
  17184. ON LOCAL ERROR GOTO cdeterr: errcode% = 0%@NL@%
  17185. lo = LBOUND(A, 1)%@NL@%
  17186. up = UBOUND(A, 1)%@NL@%
  17187. REDIM rpvt(lo TO up) AS INTEGER, cpvt(lo TO up) AS INTEGER%@NL@%
  17188. %@AB@%'make temporary double precision matrix to find pivots%@AE@%%@NL@%
  17189. DIM Tmp(lo TO up, LBOUND(A, 2) TO UBOUND(A, 2)) AS DOUBLE%@NL@%
  17190. FOR row% = lo TO up%@NL@%
  17191.    FOR col% = LBOUND(A, 2) TO UBOUND(A, 2)%@NL@%
  17192.       Tmp(row%, col%) = CDBL(A(row%, col%))%@NL@%
  17193.    NEXT col%%@NL@%
  17194. NEXT row%%@NL@%
  17195. errcode% = matluD%(Tmp())              'Get LU matrix%@NL@%
  17196. IF NOT continue THEN%@NL@%
  17197.    IF errcode% = 199 THEN det@ = 0@%@NL@%
  17198.    ERROR errcode%%@NL@%
  17199. ELSE%@NL@%
  17200.    detD# = 1#                          '+/- determinant = product of the pivots%@NL@%
  17201.    FOR pvt% = lo TO up%@NL@%
  17202.       detD# = detD# * Tmp(rpvt(pvt%), cpvt(pvt%))%@NL@%
  17203.    NEXT pvt%                           'count contains the total number of row%@NL@%
  17204.    det@ = (-1@) ^ count * CCUR(detD#)  'and column switches due to pivoting.%@NL@%
  17205.    IF errcode% THEN ERROR errcode%     'multiply the determinant by -1 for%@NL@%
  17206. END IF                                 'each switch.%@NL@%
  17207. cdetexit:%@NL@%
  17208. ERASE rpvt, cpvt, Tmp%@NL@%
  17209. MatDetC% = errcode%%@NL@%
  17210. EXIT FUNCTION%@NL@%
  17211. cdeterr:%@NL@%
  17212.    errcode% = (ERR + 5) MOD 200 - 5%@NL@%
  17213.    RESUME cdetexit%@NL@%
  17214. END FUNCTION%@NL@%
  17215. %@NL@%
  17216. %@AB@%'========================MatDetD%===================================%@AE@%%@NL@%
  17217. %@AB@%'MatDetD% finds the determinant of a square, double precision matrix%@AE@%%@NL@%
  17218. %@AB@%'%@AE@%%@NL@%
  17219. %@AB@%'Parameters: A(n x n) matrix, det# to return the determinant%@AE@%%@NL@%
  17220. %@AB@%'%@AE@%%@NL@%
  17221. %@AB@%'Returns: matrix A in LU form, determinant%@AE@%%@NL@%
  17222. %@AB@%'===================================================================%@AE@%%@NL@%
  17223. FUNCTION MatDetD% (A() AS DOUBLE, det#)%@NL@%
  17224. ON LOCAL ERROR GOTO ddeterr: errcode% = 0%@NL@%
  17225. lo = LBOUND(A, 1)%@NL@%
  17226. up = UBOUND(A, 1)%@NL@%
  17227. REDIM rpvt(lo TO up) AS INTEGER, cpvt(lo TO up) AS INTEGER%@NL@%
  17228. errcode% = matluD%(A())             'Get LU matrix%@NL@%
  17229. IF NOT continue THEN%@NL@%
  17230.    IF errcode% = 199 THEN det# = 0#%@NL@%
  17231.    ERROR errcode%%@NL@%
  17232. ELSE%@NL@%
  17233.    det# = 1#                        '+/- determinant = product of the pivots%@NL@%
  17234.    FOR pvt% = lo TO up%@NL@%
  17235.       det# = det# * A(rpvt(pvt%), cpvt(pvt%))%@NL@%
  17236.    NEXT pvt%                         'count contains the total number of row%@NL@%
  17237.    det# = (-1) ^ count * det#        'and column switches due to pivoting.%@NL@%
  17238.    IF errcode% THEN ERROR errcode%   'multiply the determinant by -1 for%@NL@%
  17239. END IF                               'each switch%@NL@%
  17240. ddetexit:%@NL@%
  17241. ERASE rpvt, cpvt%@NL@%
  17242. MatDetD% = errcode%%@NL@%
  17243. EXIT FUNCTION%@NL@%
  17244. ddeterr:%@NL@%
  17245.    errcode% = (ERR + 5) MOD 200 - 5%@NL@%
  17246.    RESUME ddetexit%@NL@%
  17247. END FUNCTION%@NL@%
  17248. %@NL@%
  17249. %@AB@%'========================MatDetI%===================================%@AE@%%@NL@%
  17250. %@AB@%'MatDetI% finds the determinant of a square, integer matrix%@AE@%%@NL@%
  17251. %@AB@%'%@AE@%%@NL@%
  17252. %@AB@%'Parameters: A(n x n) matrix, det% to return the determinant%@AE@%%@NL@%
  17253. %@AB@%'%@AE@%%@NL@%
  17254. %@AB@%'Returns: matrix A unchanged, determinant%@AE@%%@NL@%
  17255. %@AB@%'===================================================================%@AE@%%@NL@%
  17256. FUNCTION MatDetI% (A() AS INTEGER, det%)%@NL@%
  17257. ON LOCAL ERROR GOTO ideterr: errcode% = 0%@NL@%
  17258. lo = LBOUND(A, 1)%@NL@%
  17259. up = UBOUND(A, 1)%@NL@%
  17260. REDIM rpvt(lo TO up) AS INTEGER, cpvt(lo TO up) AS INTEGER%@NL@%
  17261. %@AB@%'make temporary single precision matrix to find pivots%@AE@%%@NL@%
  17262. DIM Tmp(lo TO up, LBOUND(A, 2) TO UBOUND(A, 2)) AS SINGLE%@NL@%
  17263. FOR row% = lo TO up%@NL@%
  17264.    FOR col% = LBOUND(A, 2) TO UBOUND(A, 2)%@NL@%
  17265.       Tmp(row%, col%) = CSNG(A(row%, col%))%@NL@%
  17266.    NEXT col%%@NL@%
  17267. NEXT row%%@NL@%
  17268. errcode% = matluS%(Tmp())              'Get LU matrix%@NL@%
  17269. IF NOT continue THEN%@NL@%
  17270.    IF errcode% = 199 THEN det% = 0%@NL@%
  17271.    ERROR errcode%%@NL@%
  17272. ELSE%@NL@%
  17273.    detS! = 1!                          '+/- determinant = product of the pivots%@NL@%
  17274.    FOR pvt% = lo TO up%@NL@%
  17275.       detS! = detS! * Tmp(rpvt(pvt%), cpvt(pvt%))%@NL@%
  17276.    NEXT pvt%                           'count contains the total number of row%@NL@%
  17277.    det% = (-1) ^ count * CINT(detS!)   'and column switches due to pivoting.%@NL@%
  17278.    IF errcode% THEN ERROR errcode%     'multiply the determinant by -1 for%@NL@%
  17279. END IF                                 'each switch%@NL@%
  17280. idetexit:%@NL@%
  17281. ERASE rpvt, cpvt, Tmp%@NL@%
  17282. MatDetI% = errcode%%@NL@%
  17283. EXIT FUNCTION%@NL@%
  17284. ideterr:%@NL@%
  17285.    errcode% = (ERR + 5) MOD 200 - 5%@NL@%
  17286.    RESUME idetexit%@NL@%
  17287. END FUNCTION%@NL@%
  17288. %@NL@%
  17289. %@AB@%'========================MatDetL%===================================%@AE@%%@NL@%
  17290. %@AB@%'MatDetL% finds the determinant of a square, long integer matrix%@AE@%%@NL@%
  17291. %@AB@%'%@AE@%%@NL@%
  17292. %@AB@%'Parameters: A(n x n) matrix, det& to return the determinant%@AE@%%@NL@%
  17293. %@AB@%'%@AE@%%@NL@%
  17294. %@AB@%'Returns: matrix A unchanged, determinant%@AE@%%@NL@%
  17295. %@AB@%'===================================================================%@AE@%%@NL@%
  17296. FUNCTION MatDetL% (A() AS LONG, det&)%@NL@%
  17297. ON LOCAL ERROR GOTO ldeterr: errcode% = 0%@NL@%
  17298. lo = LBOUND(A, 1)%@NL@%
  17299. up = UBOUND(A, 1)%@NL@%
  17300. REDIM rpvt(lo TO up) AS INTEGER, cpvt(lo TO up) AS INTEGER%@NL@%
  17301. %@AB@%'make temporary double precision matrix to find pivots%@AE@%%@NL@%
  17302. DIM Tmp(lo TO up, LBOUND(A, 2) TO UBOUND(A, 2)) AS DOUBLE%@NL@%
  17303. FOR row% = lo TO up%@NL@%
  17304.    FOR col% = LBOUND(A, 2) TO UBOUND(A, 2)%@NL@%
  17305.       Tmp(row%, col%) = CDBL(A(row%, col%))%@NL@%
  17306.    NEXT col%%@NL@%
  17307. NEXT row%%@NL@%
  17308. errcode% = matluD%(Tmp())              'Get LU matrix%@NL@%
  17309. IF NOT continue THEN%@NL@%
  17310.    IF errcode% = 199 THEN det& = 0&%@NL@%
  17311.    ERROR errcode%%@NL@%
  17312. ELSE%@NL@%
  17313.    detD# = 1#                          '+/- determinant = product of the pivots%@NL@%
  17314.    FOR pvt% = lo TO up%@NL@%
  17315.       detD# = detD# * Tmp(rpvt(pvt%), cpvt(pvt%))%@NL@%
  17316.    NEXT pvt%                           'count contains the total number of row%@NL@%
  17317.    det& = (-1&) ^ count * CLNG(detD#)  'and column switches due to pivoting.%@NL@%
  17318.    IF errcode% THEN ERROR errcode%     'multiply the determinant by -1 for%@NL@%
  17319. END IF                                 'each switch%@NL@%
  17320. ldetexit:%@NL@%
  17321. ERASE rpvt, cpvt, Tmp%@NL@%
  17322. MatDetL% = errcode%%@NL@%
  17323. EXIT FUNCTION%@NL@%
  17324. ldeterr:%@NL@%
  17325.    errcode% = (ERR + 5) MOD 200 - 5%@NL@%
  17326.    RESUME ldetexit%@NL@%
  17327. END FUNCTION%@NL@%
  17328. %@NL@%
  17329. %@AB@%'========================MatDetS%===================================%@AE@%%@NL@%
  17330. %@AB@%'MatDetS% finds the determinant of a square, single precision matrix%@AE@%%@NL@%
  17331. %@AB@%'%@AE@%%@NL@%
  17332. %@AB@%'Parameters: A(n x n) matrix, det! to return the determinant%@AE@%%@NL@%
  17333. %@AB@%'%@AE@%%@NL@%
  17334. %@AB@%'Returns: matrix A in LU form, determinant%@AE@%%@NL@%
  17335. %@AB@%'===================================================================%@AE@%%@NL@%
  17336. FUNCTION MatDetS% (A() AS SINGLE, det!)%@NL@%
  17337. ON LOCAL ERROR GOTO sdeterr: errcode% = 0%@NL@%
  17338. lo = LBOUND(A, 1)%@NL@%
  17339. up = UBOUND(A, 1)%@NL@%
  17340. REDIM rpvt(lo TO up) AS INTEGER, cpvt(lo TO up) AS INTEGER%@NL@%
  17341. errcode% = matluS%(A())                'Get LU matrix%@NL@%
  17342. IF NOT continue THEN%@NL@%
  17343.    IF errcode% = 199 THEN det! = 0!%@NL@%
  17344.    ERROR errcode%%@NL@%
  17345. ELSE%@NL@%
  17346.    det! = 1!                           '+/- determinant = product of the pivots%@NL@%
  17347.    FOR pvt% = lo TO up%@NL@%
  17348.       det! = det! * A(rpvt(pvt%), cpvt(pvt%))%@NL@%
  17349.    NEXT pvt%                           'count contains the total number of row%@NL@%
  17350.    det! = (-1) ^ count * det!          'and column switches due to pivoting.%@NL@%
  17351.    IF errcode% THEN ERROR errcode%     'multiply the determinant by -1 for%@NL@%
  17352. END IF                                 'each switch%@NL@%
  17353. sdetexit:%@NL@%
  17354. ERASE rpvt, cpvt%@NL@%
  17355. MatDetS% = errcode%%@NL@%
  17356. EXIT FUNCTION%@NL@%
  17357. sdeterr:%@NL@%
  17358.    errcode% = (ERR + 5) MOD 200 - 5%@NL@%
  17359.    RESUME sdetexit%@NL@%
  17360. END FUNCTION%@NL@%
  17361. %@NL@%
  17362. %@AB@%'========================MatInvC%===================================%@AE@%%@NL@%
  17363. %@AB@%'MatInvC% uses the matluD% and matbsD procedures to invert a square, currency%@AE@%%@NL@%
  17364. %@AB@%'type matrix.  Let e(N) contain all zeroes except for the jth position, which%@AE@%%@NL@%
  17365. %@AB@%'is 1.  Then the jth column of A^-1 is x, where Ax=e.%@AE@%%@NL@%
  17366. %@AB@%'%@AE@%%@NL@%
  17367. %@AB@%'Parameters: A(n x n) matrix%@AE@%%@NL@%
  17368. %@AB@%'%@AE@%%@NL@%
  17369. %@AB@%'Returns: A^-1%@AE@%%@NL@%
  17370. %@AB@%'===================================================================%@AE@%%@NL@%
  17371. FUNCTION MatInvC% (A() AS CURRENCY)%@NL@%
  17372. ON LOCAL ERROR GOTO cinverr: errcode% = 0%@NL@%
  17373. lo = LBOUND(A, 1)%@NL@%
  17374. up = UBOUND(A, 1)%@NL@%
  17375. REDIM rpvt(lo TO up) AS INTEGER, cpvt(lo TO up) AS INTEGER%@NL@%
  17376. %@AB@%'duplicate A() in a double precision work matrix, Tmp()%@AE@%%@NL@%
  17377. DIM Tmp(lo TO up, LBOUND(A, 2) TO UBOUND(A, 2)) AS DOUBLE%@NL@%
  17378. DIM e(lo TO up) AS DOUBLE, x(lo TO up) AS DOUBLE%@NL@%
  17379. FOR row% = lo TO up%@NL@%
  17380.    FOR col% = LBOUND(A, 2) TO UBOUND(A, 2)%@NL@%
  17381.       Tmp(row%, col%) = CDBL(A(row%, col%))%@NL@%
  17382.    NEXT col%%@NL@%
  17383. NEXT row%%@NL@%
  17384. errcode% = matluD%(Tmp())                    'Put LU in Tmp%@NL@%
  17385. IF NOT continue THEN ERROR errcode%%@NL@%
  17386. FOR col% = lo TO up                          'Find A^-1 one column at a time%@NL@%
  17387.    e(col%) = 1#%@NL@%
  17388.    bserrcode% = matbsD%(Tmp(), e(), x())%@NL@%
  17389.    IF bserrcode% THEN ERROR bserrcode%%@NL@%
  17390.    FOR row% = lo TO up%@NL@%
  17391.       A(row%, col%) = CCUR(x(row%))          'Put the column into A%@NL@%
  17392.       e(row%) = 0#%@NL@%
  17393.    NEXT row%%@NL@%
  17394. NEXT col%%@NL@%
  17395. IF errcode% THEN ERROR errcode%%@NL@%
  17396. cinvexit:%@NL@%
  17397. ERASE Tmp, e, x, rpvt, cpvt%@NL@%
  17398. MatInvC% = errcode%%@NL@%
  17399. EXIT FUNCTION%@NL@%
  17400. cinverr:%@NL@%
  17401.    errcode% = (ERR + 5) MOD 200 - 5%@NL@%
  17402.    RESUME cinvexit%@NL@%
  17403. END FUNCTION%@NL@%
  17404. %@NL@%
  17405. %@AB@%'========================MatInvD%===================================%@AE@%%@NL@%
  17406. %@AB@%'MatInvD% uses the matluD% and matbsD procedures to invert a square, double%@AE@%%@NL@%
  17407. %@AB@%'precision matrix.  Let e(N) contain all zeroes except for the jth position,%@AE@%%@NL@%
  17408. %@AB@%'which is 1.  Then the jth column of A^-1 is x, where Ax=e.%@AE@%%@NL@%
  17409. %@AB@%'%@AE@%%@NL@%
  17410. %@AB@%'Parameters: A(n x n) matrix%@AE@%%@NL@%
  17411. %@AB@%'%@AE@%%@NL@%
  17412. %@AB@%'Returns: A^-1%@AE@%%@NL@%
  17413. %@AB@%'===================================================================%@AE@%%@NL@%
  17414. FUNCTION MatInvD% (A() AS DOUBLE)%@NL@%
  17415. ON LOCAL ERROR GOTO dinverr: errcode% = 0%@NL@%
  17416. lo = LBOUND(A, 1)%@NL@%
  17417. up = UBOUND(A, 1)%@NL@%
  17418. DIM Ain(lo TO up, lo TO up) AS DOUBLE%@NL@%
  17419. DIM e(lo TO up) AS DOUBLE, x(lo TO up) AS DOUBLE%@NL@%
  17420. REDIM rpvt(lo TO up) AS INTEGER, cpvt(lo TO up) AS INTEGER%@NL@%
  17421. errcode% = matluD%(A())                     'Get LU matrix%@NL@%
  17422. IF NOT continue THEN ERROR errcode%%@NL@%
  17423. FOR col% = lo TO up                         'Find A^-1 one column at a time%@NL@%
  17424.    e(col%) = 1#%@NL@%
  17425.    bserrcode% = matbsD%(A(), e(), x())%@NL@%
  17426.    IF bserrcode% THEN ERROR bserrcode%%@NL@%
  17427.    FOR row% = lo TO up%@NL@%
  17428.       Ain(row%, col%) = x(row%)%@NL@%
  17429.       e(row%) = 0#%@NL@%
  17430.    NEXT row%%@NL@%
  17431. NEXT col%%@NL@%
  17432. FOR col% = lo TO up                         'Put A^-1 in A%@NL@%
  17433.    FOR row% = lo TO up%@NL@%
  17434.       A(row%, col%) = Ain(row%, col%)%@NL@%
  17435.    NEXT row%%@NL@%
  17436. NEXT col%%@NL@%
  17437. IF errcode% THEN ERROR errcode%%@NL@%
  17438. dinvexit:%@NL@%
  17439. ERASE e, x, Ain, rpvt, cpvt%@NL@%
  17440. MatInvD% = errcode%%@NL@%
  17441. EXIT FUNCTION%@NL@%
  17442. dinverr:%@NL@%
  17443.    errcode% = (ERR + 5) MOD 200 - 5%@NL@%
  17444.    RESUME dinvexit%@NL@%
  17445. END FUNCTION%@NL@%
  17446. %@NL@%
  17447. %@AB@%'========================MatInvS%===================================%@AE@%%@NL@%
  17448. %@AB@%'MatInvS% uses the matluS% and matbsS procedures to invert a square, single%@AE@%%@NL@%
  17449. %@AB@%'precision matrix.  Let e(N) contain all zeroes except for the jth position,%@AE@%%@NL@%
  17450. %@AB@%'which is 1. Then the jth column of A^-1 is x, where Ax=e.%@AE@%%@NL@%
  17451. %@AB@%'%@AE@%%@NL@%
  17452. %@AB@%'Parameters: A(n x n) matrix%@AE@%%@NL@%
  17453. %@AB@%'%@AE@%%@NL@%
  17454. %@AB@%'Returns: A^-1%@AE@%%@NL@%
  17455. %@AB@%'===================================================================%@AE@%%@NL@%
  17456. FUNCTION MatInvS% (A() AS SINGLE)%@NL@%
  17457. ON LOCAL ERROR GOTO sinverr: errcode% = 0%@NL@%
  17458. lo = LBOUND(A, 1)%@NL@%
  17459. up = UBOUND(A, 1)%@NL@%
  17460. DIM Ain(lo TO up, lo TO up) AS SINGLE%@NL@%
  17461. DIM e(lo TO up) AS SINGLE, x(lo TO up) AS SINGLE%@NL@%
  17462. REDIM rpvt(lo TO up) AS INTEGER, cpvt(lo TO up) AS INTEGER%@NL@%
  17463. errcode% = matluS%(A())                     'Get LU matrix%@NL@%
  17464. IF NOT continue THEN ERROR errcode%%@NL@%
  17465. FOR col% = lo TO up                         'find A^-1 one column at a time%@NL@%
  17466.    e(col%) = 1!%@NL@%
  17467.    bserrcode% = matbsS%(A(), e(), x())%@NL@%
  17468.    IF bserrcode% THEN ERROR bserrcode%%@NL@%
  17469.    FOR row% = lo TO up%@NL@%
  17470.       Ain(row%, col%) = x(row%)%@NL@%
  17471.       e(row%) = 0!%@NL@%
  17472.    NEXT row%%@NL@%
  17473. NEXT col%%@NL@%
  17474. FOR col% = lo TO up                         'put A^-1 in A%@NL@%
  17475.    FOR row% = lo TO up%@NL@%
  17476.       A(row%, col%) = Ain(row%, col%)%@NL@%
  17477.    NEXT row%%@NL@%
  17478. NEXT col%%@NL@%
  17479. IF errcode% THEN ERROR errcode%%@NL@%
  17480. sinvexit:%@NL@%
  17481. ERASE e, x, Ain, rpvt, cpvt%@NL@%
  17482. MatInvS% = errcode%%@NL@%
  17483. EXIT FUNCTION%@NL@%
  17484. sinverr:%@NL@%
  17485.    errcode% = (ERR + 5) MOD 200 - 5%@NL@%
  17486.    RESUME sinvexit%@NL@%
  17487. END FUNCTION%@NL@%
  17488. %@NL@%
  17489. %@AB@%'========================matluD%====================================%@AE@%%@NL@%
  17490. %@AB@%'matluD% does Gaussian elimination with total pivoting to put a square, double%@AE@%%@NL@%
  17491. %@AB@%'precision matrix in LU form. The multipliers used in the row operations to%@AE@%%@NL@%
  17492. %@AB@%'create zeroes below the main diagonal are saved in the zero spaces.%@AE@%%@NL@%
  17493. %@AB@%'%@AE@%%@NL@%
  17494. %@AB@%'Parameters: A(n x n) matrix, rpvt(n) and cpvt(n) permutation vectors%@AE@%%@NL@%
  17495. %@AB@%'            used to index the row and column pivots%@AE@%%@NL@%
  17496. %@AB@%'%@AE@%%@NL@%
  17497. %@AB@%'Returns: A in LU form with corresponding pivot vectors; the total number of%@AE@%%@NL@%
  17498. %@AB@%'         pivots in count, which is used to find the sign of the determinant.%@AE@%%@NL@%
  17499. %@AB@%'===================================================================%@AE@%%@NL@%
  17500. FUNCTION matluD% (A() AS DOUBLE)%@NL@%
  17501. ON LOCAL ERROR GOTO dluerr: errcode% = 0%@NL@%
  17502. %@AB@%'Checks if A is square, returns error code if not%@AE@%%@NL@%
  17503. IF NOT (lo = LBOUND(A, 2) AND up = UBOUND(A, 2)) THEN ERROR 198%@NL@%
  17504. DIM rownorm(lo TO up) AS DOUBLE%@NL@%
  17505. count = 0                            'initialize count, continue%@NL@%
  17506. continue = -1%@NL@%
  17507. FOR row% = lo TO up                  'initialize rpvt and cpvt%@NL@%
  17508.    rpvt(row%) = row%%@NL@%
  17509.    cpvt(row%) = row%%@NL@%
  17510.    rownorm(row%) = 0#                'find the row norms of A()%@NL@%
  17511.    FOR col% = lo TO up%@NL@%
  17512.       rownorm(row%) = rownorm(row%) + ABS(A(row%, col%))%@NL@%
  17513.    NEXT col%%@NL@%
  17514.    IF rownorm(row%) = 0# THEN        'if any rownorm is zero, the matrix%@NL@%
  17515.       continue = 0                   'is singular, set error, exit and%@NL@%
  17516.       ERROR 199                      'do not continue%@NL@%
  17517.    END IF%@NL@%
  17518. NEXT row%%@NL@%
  17519. FOR pvt% = lo TO (up - 1)%@NL@%
  17520. %@AB@%'Find best available pivot%@AE@%%@NL@%
  17521.    max# = 0#                         'checks all values in rows and columns not%@NL@%
  17522.    FOR row% = pvt% TO up             'already used for pivoting and saves the%@NL@%
  17523.       r% = rpvt(row%)                'largest absolute number and its position%@NL@%
  17524.       FOR col% = pvt% TO up%@NL@%
  17525.          c% = cpvt(col%)%@NL@%
  17526.          temp# = ABS(A(r%, c%)) / rownorm(r%)%@NL@%
  17527.          IF temp# > max# THEN%@NL@%
  17528.             max# = temp#%@NL@%
  17529.             bestrow% = row%          'save the position of new max#%@NL@%
  17530.             bestcol% = col%%@NL@%
  17531.          END IF%@NL@%
  17532.       NEXT col%%@NL@%
  17533.    NEXT row%%@NL@%
  17534.    IF max# = 0# THEN                 'if no nonzero number is found, A is%@NL@%
  17535.       continue = 0                   'singular, send back error, do not continue%@NL@%
  17536.       ERROR 199%@NL@%
  17537.    ELSEIF pvt% > 1 THEN              'check if drop in pivots is too much%@NL@%
  17538.       IF max# < (deps# * oldmax#) THEN errcode% = 199%@NL@%
  17539.    END IF%@NL@%
  17540.    oldmax# = max#%@NL@%
  17541.    IF rpvt(pvt%) <> rpvt(bestrow%) THEN%@NL@%
  17542.       count = count + 1                    'if a row or column pivot is%@NL@%
  17543.       SWAP rpvt(pvt%), rpvt(bestrow%)      'necessary, count it and permute%@NL@%
  17544.    END IF                                  'rpvt or cpvt. Note: the rows and%@NL@%
  17545.    IF cpvt(pvt%) <> cpvt(bestcol%) THEN    'columns are not actually switched,%@NL@%
  17546.       count = count + 1                    'only the order in which they are%@NL@%
  17547.       SWAP cpvt(pvt%), cpvt(bestcol%)      'used.%@NL@%
  17548.    END IF%@NL@%
  17549. %@AB@%'Eliminate all values below the pivot%@AE@%%@NL@%
  17550.    rp% = rpvt(pvt%)%@NL@%
  17551.    cp% = cpvt(pvt%)%@NL@%
  17552.    FOR row% = (pvt% + 1) TO up%@NL@%
  17553.       r% = rpvt(row%)%@NL@%
  17554.       A(r%, cp%) = -A(r%, cp%) / A(rp%, cp%)  'save multipliers%@NL@%
  17555.       FOR col% = (pvt% + 1) TO up%@NL@%
  17556.          c% = cpvt(col%)                      'complete row operations%@NL@%
  17557.          A(r%, c%) = A(r%, c%) + A(r%, cp%) * A(rp%, c%)%@NL@%
  17558.       NEXT col%%@NL@%
  17559.    NEXT row%%@NL@%
  17560. NEXT pvt%%@NL@%
  17561. IF A(rpvt(up), cpvt(up)) = 0# THEN%@NL@%
  17562.    continue = 0                      'if last pivot is zero or pivot drop is%@NL@%
  17563.    ERROR 199                         'too large, A is singular, send back error%@NL@%
  17564. ELSEIF (ABS(A(rpvt(up), cpvt(up))) / rownorm(rpvt(up))) < (deps# * oldmax#) THEN%@NL@%
  17565.    errcode% = 199                    'if pivot is not identically zero then%@NL@%
  17566. END IF                               'continue remains TRUE%@NL@%
  17567. IF errcode% THEN ERROR errcode%%@NL@%
  17568. dluexit:%@NL@%
  17569. matluD% = errcode%%@NL@%
  17570. EXIT FUNCTION%@NL@%
  17571. dluerr:%@NL@%
  17572.    IF errcode% < 199 THEN continue = 0%@NL@%
  17573.    errcode% = ERR%@NL@%
  17574.    RESUME dluexit%@NL@%
  17575. END FUNCTION%@NL@%
  17576. %@NL@%
  17577. %@AB@%'========================matluS%====================================%@AE@%%@NL@%
  17578. %@AB@%'matluS% does Gaussian elimination with total pivoting to put a square, single%@AE@%%@NL@%
  17579. %@AB@%'precision matrix in LU form. The multipliers used in the row operations to%@AE@%%@NL@%
  17580. %@AB@%'create zeroes below the main diagonal are saved in the zero spaces.%@AE@%%@NL@%
  17581. %@AB@%'%@AE@%%@NL@%
  17582. %@AB@%'Parameters: A(n x n) matrix, rpvt(n) and cpvt(n) permutation vectors%@AE@%%@NL@%
  17583. %@AB@%'            used to index the row and column pivots%@AE@%%@NL@%
  17584. %@AB@%'%@AE@%%@NL@%
  17585. %@AB@%'Returns: A in LU form with corresponding pivot vectors; the total number of%@AE@%%@NL@%
  17586. %@AB@%'         pivots in count, which is used to find the sign of the determinant.%@AE@%%@NL@%
  17587. %@AB@%'===================================================================%@AE@%%@NL@%
  17588. FUNCTION matluS% (A() AS SINGLE)%@NL@%
  17589. ON LOCAL ERROR GOTO sluerr: errcode% = 0%@NL@%
  17590. %@AB@%'Checks if A is square, returns error code if not%@AE@%%@NL@%
  17591. IF NOT (lo = LBOUND(A, 2) AND up = UBOUND(A, 2)) THEN ERROR 198%@NL@%
  17592. DIM rownorm(lo TO up) AS SINGLE%@NL@%
  17593. count = 0                            'initialize count, continue%@NL@%
  17594. continue = -1%@NL@%
  17595. FOR row% = lo TO up                  'initialize rpvt and cpvt%@NL@%
  17596.    rpvt(row%) = row%%@NL@%
  17597.    cpvt(row%) = row%%@NL@%
  17598.    rownorm(row%) = 0!                'find the row norms of A()%@NL@%
  17599.    FOR col% = lo TO up%@NL@%
  17600.       rownorm(row%) = rownorm(row%) + ABS(A(row%, col%))%@NL@%
  17601.    NEXT col%%@NL@%
  17602.    IF rownorm(row%) = 0! THEN        'if any rownorm is zero, the matrix%@NL@%
  17603.       continue = 0                   'is singular, set error, exit and do%@NL@%
  17604.       ERROR 199                      'not continue%@NL@%
  17605.    END IF%@NL@%
  17606. NEXT row%%@NL@%
  17607. FOR pvt% = lo TO (up - 1)%@NL@%
  17608. %@AB@%'Find best available pivot%@AE@%%@NL@%
  17609.    max! = 0!                         'checks all values in rows and columns not%@NL@%
  17610.    FOR row% = pvt% TO up             'already used for pivoting and finds the%@NL@%
  17611.       r% = rpvt(row%)                'number largest in absolute value relative%@NL@%
  17612.       FOR col% = pvt% TO up          'to its row norm%@NL@%
  17613.          c% = cpvt(col%)%@NL@%
  17614.          temp! = ABS(A(r%, c%)) / rownorm(r%)%@NL@%
  17615.          IF temp! > max! THEN%@NL@%
  17616.             max! = temp!%@NL@%
  17617.             bestrow% = row%          'save the position of new max!%@NL@%
  17618.             bestcol% = col%%@NL@%
  17619.          END IF%@NL@%
  17620.       NEXT col%%@NL@%
  17621.    NEXT row%%@NL@%
  17622.    IF max! = 0! THEN                 'if no nonzero number is found, A is%@NL@%
  17623.       continue = 0                   'singular, send back error, do not continue%@NL@%
  17624.       ERROR 199%@NL@%
  17625.    ELSEIF pvt% > 1 THEN              'check if drop in pivots is too much%@NL@%
  17626.       IF max! < (seps! * oldmax!) THEN errcode% = 199%@NL@%
  17627.    END IF%@NL@%
  17628.    oldmax! = max!%@NL@%
  17629.    IF rpvt(pvt%) <> rpvt(bestrow%) THEN%@NL@%
  17630.       count = count + 1                    'if a row or column pivot is%@NL@%
  17631.       SWAP rpvt(pvt%), rpvt(bestrow%)      'necessary, count it and permute%@NL@%
  17632.    END IF                                  'rpvt or cpvt. Note: the rows and%@NL@%
  17633.    IF cpvt(pvt%) <> cpvt(bestcol%) THEN    'columns are not actually switched,%@NL@%
  17634.       count = count + 1                    'only the order in which they are%@NL@%
  17635.       SWAP cpvt(pvt%), cpvt(bestcol%)      'used.%@NL@%
  17636.    END IF%@NL@%
  17637. %@AB@%'Eliminate all values below the pivot%@AE@%%@NL@%
  17638.    rp% = rpvt(pvt%)%@NL@%
  17639.    cp% = cpvt(pvt%)%@NL@%
  17640.    FOR row% = (pvt% + 1) TO up%@NL@%
  17641.       r% = rpvt(row%)%@NL@%
  17642.       A(r%, cp%) = -A(r%, cp%) / A(rp%, cp%)  'save multipliers%@NL@%
  17643.       FOR col% = (pvt% + 1) TO up%@NL@%
  17644.          c% = cpvt(col%)                      'complete row operations%@NL@%
  17645.          A(r%, c%) = A(r%, c%) + A(r%, cp%) * A(rp%, c%)%@NL@%
  17646.       NEXT col%%@NL@%
  17647.    NEXT row%%@NL@%
  17648. NEXT pvt%%@NL@%
  17649. IF A(rpvt(up), cpvt(up)) = 0! THEN%@NL@%
  17650.    continue = 0                      'if last pivot is zero or pivot drop is%@NL@%
  17651.    ERROR 199                         'too large, A is singular, send back error%@NL@%
  17652. ELSEIF (ABS(A(rpvt(up), cpvt(up))) / rownorm(rpvt(up))) < (seps! * oldmax!) THEN%@NL@%
  17653.    errcode% = 199                    'if pivot is not identically zero then%@NL@%
  17654. END IF                               'continue remains TRUE%@NL@%
  17655. IF errcode% THEN ERROR errcode%%@NL@%
  17656. sluexit:%@NL@%
  17657. matluS% = errcode%%@NL@%
  17658. EXIT FUNCTION%@NL@%
  17659. sluerr:%@NL@%
  17660.    errcode% = ERR%@NL@%
  17661.    IF errcode% < 199 THEN continue = 0%@NL@%
  17662.    RESUME sluexit%@NL@%
  17663. END FUNCTION%@NL@%
  17664. %@NL@%
  17665. %@AB@%'=======================MatMultC%===================================%@AE@%%@NL@%
  17666. %@AB@%'MatMultC% multiplies two currency type matrices and places the%@AE@%%@NL@%
  17667. %@AB@%'product in a result matrix%@AE@%%@NL@%
  17668. %@AB@%'%@AE@%%@NL@%
  17669. %@AB@%'Parameters: matrices Alpha,Beta,Gamma%@AE@%%@NL@%
  17670. %@AB@%'%@AE@%%@NL@%
  17671. %@AB@%'Returns: Gamma() = Alpha() * Beta()%@AE@%%@NL@%
  17672. %@AB@%'===================================================================%@AE@%%@NL@%
  17673. FUNCTION MatMultC% (Alpha() AS CURRENCY, Beta() AS CURRENCY, Gamma() AS CURRENCY)%@NL@%
  17674. ON LOCAL ERROR GOTO cmulterr: MatMultC% = 0%@NL@%
  17675. IF (LBOUND(Alpha, 2) <> LBOUND(Beta, 1)) OR (UBOUND(Alpha, 2) <> UBOUND(Beta, 1)) THEN%@NL@%
  17676.    ERROR 197                   'check inside dimensions%@NL@%
  17677. ELSEIF (LBOUND(Alpha, 1) <> LBOUND(Gamma, 1)) OR (UBOUND(Alpha, 1) <> UBOUND(Gamma, 1)) OR (LBOUND(Beta, 2) <> LBOUND(Gamma, 2)) OR (UBOUND(Beta, 2) <> UBOUND(Gamma, 2)) THEN%@NL@%
  17678.    ERROR 195                   'check dimensions of result matrix%@NL@%
  17679. END IF%@NL@%
  17680. %@AB@%'loop through, Gamma(row,col)=inner product of Alpha(row,*) and Beta(*,col)%@AE@%%@NL@%
  17681. FOR row% = LBOUND(Gamma, 1) TO UBOUND(Gamma, 1)%@NL@%
  17682.    FOR col% = LBOUND(Gamma, 2) TO UBOUND(Gamma, 2)%@NL@%
  17683.       Gamma(row%, col%) = 0@%@NL@%
  17684.       FOR inside% = LBOUND(Alpha, 2) TO UBOUND(Alpha, 2)%@NL@%
  17685.          Gamma(row%, col%) = Gamma(row%, col%) + Alpha(row%, inside%) * Beta(inside%, col%)%@NL@%
  17686.       NEXT inside%%@NL@%
  17687.    NEXT col%%@NL@%
  17688. NEXT row%%@NL@%
  17689. cmultexit:%@NL@%
  17690. EXIT FUNCTION%@NL@%
  17691. cmulterr:%@NL@%
  17692.    MatMultC% = (ERR + 5) MOD 200 - 5%@NL@%
  17693.    RESUME cmultexit%@NL@%
  17694. END FUNCTION%@NL@%
  17695. %@NL@%
  17696. %@AB@%'=======================MatMultD%===================================%@AE@%%@NL@%
  17697. %@AB@%'MatMultD% multiplies two double precision matrices and places the%@AE@%%@NL@%
  17698. %@AB@%'product in a result matrix%@AE@%%@NL@%
  17699. %@AB@%'%@AE@%%@NL@%
  17700. %@AB@%'Parameters: matrices Alpha,Beta,Gamma%@AE@%%@NL@%
  17701. %@AB@%'%@AE@%%@NL@%
  17702. %@AB@%'Returns: Gamma() = Alpha() * Beta()%@AE@%%@NL@%
  17703. %@AB@%'===================================================================%@AE@%%@NL@%
  17704. FUNCTION MatMultD% (Alpha() AS DOUBLE, Beta() AS DOUBLE, Gamma() AS DOUBLE)%@NL@%
  17705. ON LOCAL ERROR GOTO dmulterr: MatMultD% = 0%@NL@%
  17706. IF (LBOUND(Alpha, 2) <> LBOUND(Beta, 1)) OR (UBOUND(Alpha, 2) <> UBOUND(Beta, 1)) THEN%@NL@%
  17707.    ERROR 197                   'check inside dimensions%@NL@%
  17708. ELSEIF (LBOUND(Alpha, 1) <> LBOUND(Gamma, 1)) OR (UBOUND(Alpha, 1) <> UBOUND(Gamma, 1)) OR (LBOUND(Beta, 2) <> LBOUND(Gamma, 2)) OR (UBOUND(Beta, 2) <> UBOUND(Gamma, 2)) THEN%@NL@%
  17709.    ERROR 195                   'check dimensions of result matrix%@NL@%
  17710. END IF%@NL@%
  17711. %@AB@%'loop through, Gamma(row,col)=inner product of Alpha(row,*) and Beta(*,col)%@AE@%%@NL@%
  17712. FOR row% = LBOUND(Gamma, 1) TO UBOUND(Gamma, 1)%@NL@%
  17713.    FOR col% = LBOUND(Gamma, 2) TO UBOUND(Gamma, 2)%@NL@%
  17714.       Gamma(row%, col%) = 0#%@NL@%
  17715.       FOR inside% = LBOUND(Alpha, 2) TO UBOUND(Alpha, 2)%@NL@%
  17716.          Gamma(row%, col%) = Gamma(row%, col%) + Alpha(row%, inside%) * Beta(inside%, col%)%@NL@%
  17717.       NEXT inside%%@NL@%
  17718.    NEXT col%%@NL@%
  17719. NEXT row%%@NL@%
  17720. dmultexit:%@NL@%
  17721. EXIT FUNCTION%@NL@%
  17722. dmulterr:%@NL@%
  17723.    MatMultD% = (ERR + 5) MOD 200 - 5%@NL@%
  17724.    RESUME dmultexit%@NL@%
  17725. END FUNCTION%@NL@%
  17726. %@NL@%
  17727. %@AB@%'=======================MatMultI%===================================%@AE@%%@NL@%
  17728. %@AB@%'MatMultI% multiplies two integer matrices and places the product in%@AE@%%@NL@%
  17729. %@AB@%'a result matrix%@AE@%%@NL@%
  17730. %@AB@%'%@AE@%%@NL@%
  17731. %@AB@%'Parameters: matrices Alpha,Beta,Gamma%@AE@%%@NL@%
  17732. %@AB@%'%@AE@%%@NL@%
  17733. %@AB@%'Returns: Gamma() = Alpha() * Beta()%@AE@%%@NL@%
  17734. %@AB@%'===================================================================%@AE@%%@NL@%
  17735. FUNCTION MatMultI% (Alpha() AS INTEGER, Beta() AS INTEGER, Gamma() AS INTEGER)%@NL@%
  17736. ON LOCAL ERROR GOTO imulterr: MatMultI% = 0%@NL@%
  17737. IF (LBOUND(Alpha, 2) <> LBOUND(Beta, 1)) OR (UBOUND(Alpha, 2) <> UBOUND(Beta, 1)) THEN%@NL@%
  17738.    ERROR 197                   'check inside dimensions%@NL@%
  17739. ELSEIF (LBOUND(Alpha, 1) <> LBOUND(Gamma, 1)) OR (UBOUND(Alpha, 1) <> UBOUND(Gamma, 1)) OR (LBOUND(Beta, 2) <> LBOUND(Gamma, 2)) OR (UBOUND(Beta, 2) <> UBOUND(Gamma, 2)) THEN%@NL@%
  17740.    ERROR 195                   'check dimensions of result matrix%@NL@%
  17741. END IF%@NL@%
  17742. %@AB@%'loop through, Gamma(row,col)=inner product of Alpha(row,*) and Beta(*,col)%@AE@%%@NL@%
  17743. FOR row% = LBOUND(Gamma, 1) TO UBOUND(Gamma, 1)%@NL@%
  17744.    FOR col% = LBOUND(Gamma, 2) TO UBOUND(Gamma, 2)%@NL@%
  17745.       Gamma(row%, col%) = 0%@NL@%
  17746.       FOR inside% = LBOUND(Alpha, 2) TO UBOUND(Alpha, 2)%@NL@%
  17747.          Gamma(row%, col%) = Gamma(row%, col%) + Alpha(row%, inside%) * Beta(inside%, col%)%@NL@%
  17748.       NEXT inside%%@NL@%
  17749.    NEXT col%%@NL@%
  17750. NEXT row%%@NL@%
  17751. imultexit:%@NL@%
  17752. EXIT FUNCTION%@NL@%
  17753. imulterr:%@NL@%
  17754.    MatMultI% = (ERR + 5) MOD 200 - 5%@NL@%
  17755.    RESUME imultexit%@NL@%
  17756. END FUNCTION%@NL@%
  17757. %@NL@%
  17758. %@AB@%'=======================MatMultL%===================================%@AE@%%@NL@%
  17759. %@AB@%'MatMultL% multiplies two long integer matrices and places the product%@AE@%%@NL@%
  17760. %@AB@%'in a result matrix%@AE@%%@NL@%
  17761. %@AB@%'%@AE@%%@NL@%
  17762. %@AB@%'Parameters: matrices Alpha,Beta,Gamma%@AE@%%@NL@%
  17763. %@AB@%'%@AE@%%@NL@%
  17764. %@AB@%'Returns: Gamma() = Alpha() * Beta()%@AE@%%@NL@%
  17765. %@AB@%'===================================================================%@AE@%%@NL@%
  17766. FUNCTION MatMultL% (Alpha() AS LONG, Beta() AS LONG, Gamma() AS LONG)%@NL@%
  17767. ON LOCAL ERROR GOTO lmulterr: MatMultL% = 0%@NL@%
  17768. IF (LBOUND(Alpha, 2) <> LBOUND(Beta, 1)) OR (UBOUND(Alpha, 2) <> UBOUND(Beta, 1)) THEN%@NL@%
  17769.    ERROR 197                   'check inside dimensions%@NL@%
  17770. ELSEIF (LBOUND(Alpha, 1) <> LBOUND(Gamma, 1)) OR (UBOUND(Alpha, 1) <> UBOUND(Gamma, 1)) OR (LBOUND(Beta, 2) <> LBOUND(Gamma, 2)) OR (UBOUND(Beta, 2) <> UBOUND(Gamma, 2)) THEN%@NL@%
  17771.    ERROR 195                   'check dimensions of result matrix%@NL@%
  17772. END IF%@NL@%
  17773. %@AB@%'loop through, Gamma(row,col)=inner product of Alpha(row,*) and Beta(*,col)%@AE@%%@NL@%
  17774. FOR row% = LBOUND(Gamma, 1) TO UBOUND(Gamma, 1)%@NL@%
  17775.    FOR col% = LBOUND(Gamma, 2) TO UBOUND(Gamma, 2)%@NL@%
  17776.       Gamma(row%, col%) = 0&%@NL@%
  17777.       FOR inside% = LBOUND(Alpha, 2) TO UBOUND(Alpha, 2)%@NL@%
  17778.          Gamma(row%, col%) = Gamma(row%, col%) + Alpha(row%, inside%) * Beta(inside%, col%)%@NL@%
  17779.       NEXT inside%%@NL@%
  17780.    NEXT col%%@NL@%
  17781. NEXT row%%@NL@%
  17782. lmultexit:%@NL@%
  17783. EXIT FUNCTION%@NL@%
  17784. lmulterr:%@NL@%
  17785.    MatMultL% = (ERR + 5) MOD 200 - 5%@NL@%
  17786.    RESUME lmultexit%@NL@%
  17787. END FUNCTION%@NL@%
  17788. %@NL@%
  17789. %@AB@%'=======================MatMultS%===================================%@AE@%%@NL@%
  17790. %@AB@%'MatMultS% multiplies two single precision matrices and places the%@AE@%%@NL@%
  17791. %@AB@%'product in a result matrix%@AE@%%@NL@%
  17792. %@AB@%'%@AE@%%@NL@%
  17793. %@AB@%'Parameters: matrices Alpha,Beta,Gamma%@AE@%%@NL@%
  17794. %@AB@%'%@AE@%%@NL@%
  17795. %@AB@%'Returns: Gamma() = Alpha() * Beta()%@AE@%%@NL@%
  17796. %@AB@%'===================================================================%@AE@%%@NL@%
  17797. FUNCTION MatMultS% (Alpha() AS SINGLE, Beta() AS SINGLE, Gamma() AS SINGLE)%@NL@%
  17798. ON LOCAL ERROR GOTO smulterr: MatMultS% = 0%@NL@%
  17799. IF (LBOUND(Alpha, 2) <> LBOUND(Beta, 1)) OR (UBOUND(Alpha, 2) <> UBOUND(Beta, 1)) THEN%@NL@%
  17800.    ERROR 197                   'check inside dimensions%@NL@%
  17801. ELSEIF (LBOUND(Alpha, 1) <> LBOUND(Gamma, 1)) OR (UBOUND(Alpha, 1) <> UBOUND(Gamma, 1)) OR (LBOUND(Beta, 2) <> LBOUND(Gamma, 2)) OR (UBOUND(Beta, 2) <> UBOUND(Gamma, 2)) THEN%@NL@%
  17802.    ERROR 195                   'check dimensions of result matrix%@NL@%
  17803. END IF%@NL@%
  17804. %@AB@%'loop through, Gamma(row,col)=inner product of Alpha(row,*) and Beta(*,col)%@AE@%%@NL@%
  17805. FOR row% = LBOUND(Gamma, 1) TO UBOUND(Gamma, 1)%@NL@%
  17806.    FOR col% = LBOUND(Gamma, 2) TO UBOUND(Gamma, 2)%@NL@%
  17807.       Gamma(row%, col%) = 0!%@NL@%
  17808.       FOR inside% = LBOUND(Alpha, 2) TO UBOUND(Alpha, 2)%@NL@%
  17809.          Gamma(row%, col%) = Gamma(row%, col%) + Alpha(row%, inside%) * Beta(inside%, col%)%@NL@%
  17810.       NEXT inside%%@NL@%
  17811.    NEXT col%%@NL@%
  17812. NEXT row%%@NL@%
  17813. smultexit:%@NL@%
  17814. EXIT FUNCTION%@NL@%
  17815. smulterr:%@NL@%
  17816.    MatMultS% = (ERR + 5) MOD 200 - 5%@NL@%
  17817.    RESUME smultexit%@NL@%
  17818. END FUNCTION%@NL@%
  17819. %@NL@%
  17820. %@AB@%'========================MatSEqnC%==================================%@AE@%%@NL@%
  17821. %@AB@%'MatSEqnC% solves a system of n linear equations, Ax=b, and puts the%@AE@%%@NL@%
  17822. %@AB@%'answer in b. A is first put in LU form by matluC%, then matbsC is called%@AE@%%@NL@%
  17823. %@AB@%'to solve the system.  matrices A,b are currency type.%@AE@%%@NL@%
  17824. %@AB@%'%@AE@%%@NL@%
  17825. %@AB@%'Parameters: A(n x n) contains coefficient matrix, b(N) contains the right side%@AE@%%@NL@%
  17826. %@AB@%'%@AE@%%@NL@%
  17827. %@AB@%'Returns: A in LU form, solution in b%@AE@%%@NL@%
  17828. %@AB@%'===================================================================%@AE@%%@NL@%
  17829. FUNCTION MatSEqnC% (A() AS CURRENCY, b() AS CURRENCY)%@NL@%
  17830. ON LOCAL ERROR GOTO cseqnerr: errcode% = 0%@NL@%
  17831. lo = LBOUND(A, 1)%@NL@%
  17832. up = UBOUND(A, 1)%@NL@%
  17833. REDIM rpvt(lo TO up) AS INTEGER, cpvt(lo TO up) AS INTEGER%@NL@%
  17834. %@AB@%'duplicate A(), b() in temporary double precision matrices Tmp(), btmp()%@AE@%%@NL@%
  17835. DIM Tmp(lo TO up, LBOUND(A, 2) TO UBOUND(A, 2)) AS DOUBLE%@NL@%
  17836. DIM x(lo TO up) AS DOUBLE, btmp(lo TO up) AS DOUBLE%@NL@%
  17837. FOR row% = lo TO up%@NL@%
  17838.    FOR col% = LBOUND(A, 2) TO UBOUND(A, 2)%@NL@%
  17839.       Tmp(row%, col%) = CDBL(A(row%, col%))%@NL@%
  17840.    NEXT col%%@NL@%
  17841. NEXT row%%@NL@%
  17842. errcode% = matluD%(Tmp())                   'Get LU matrix%@NL@%
  17843. IF NOT continue THEN ERROR errcode%%@NL@%
  17844. %@AB@%'check dimensions of b, make double precision copy if ok.%@AE@%%@NL@%
  17845. IF (lo <> LBOUND(b)) OR (up <> UBOUND(b)) THEN ERROR 197%@NL@%
  17846. FOR row% = lo TO up%@NL@%
  17847.    btmp(row%) = CDBL(b(row%))%@NL@%
  17848. NEXT row%%@NL@%
  17849. bserrcode% = matbsD%(Tmp(), btmp(), x())    'Backsolve system%@NL@%
  17850. IF bserrcode% THEN ERROR bserrcode%%@NL@%
  17851. FOR row% = lo TO up%@NL@%
  17852.    b(row%) = CCUR(x(row%))                  'Put solution in b for return%@NL@%
  17853. NEXT row%%@NL@%
  17854. IF errcode% THEN ERROR errcode%%@NL@%
  17855. cseqnexit:%@NL@%
  17856. ERASE Tmp, btmp, x, rpvt, cpvt%@NL@%
  17857. MatSEqnC% = errcode%%@NL@%
  17858. EXIT FUNCTION%@NL@%
  17859. cseqnerr:%@NL@%
  17860.    errcode% = (ERR + 5) MOD 200 - 5%@NL@%
  17861.    RESUME cseqnexit%@NL@%
  17862. END FUNCTION%@NL@%
  17863. %@NL@%
  17864. %@AB@%'========================MatSEqnD%==================================%@AE@%%@NL@%
  17865. %@AB@%'MatSEqnD% solves a system of n linear equations, Ax=b, and puts the%@AE@%%@NL@%
  17866. %@AB@%'answer in b. A is first put in LU form by matluD%, then matbsD is called%@AE@%%@NL@%
  17867. %@AB@%'to solve the system.  matrices A,b are double precision.%@AE@%%@NL@%
  17868. %@AB@%'%@AE@%%@NL@%
  17869. %@AB@%'Parameters: A(n x n) contains coefficient matrix, b(N) contains the right side%@AE@%%@NL@%
  17870. %@AB@%'%@AE@%%@NL@%
  17871. %@AB@%'Returns: A in LU form, solution in b%@AE@%%@NL@%
  17872. %@AB@%'===================================================================%@AE@%%@NL@%
  17873. FUNCTION MatSEqnD% (A() AS DOUBLE, b() AS DOUBLE)%@NL@%
  17874. ON LOCAL ERROR GOTO dseqnerr: errcode% = 0%@NL@%
  17875. lo = LBOUND(A, 1)%@NL@%
  17876. up = UBOUND(A, 1)%@NL@%
  17877. DIM x(lo TO up) AS DOUBLE%@NL@%
  17878. REDIM rpvt(lo TO up) AS INTEGER, cpvt(lo TO up) AS INTEGER%@NL@%
  17879. errcode% = matluD%(A())                      'Get LU matrix%@NL@%
  17880. IF NOT continue THEN ERROR errcode%%@NL@%
  17881. %@AB@%'check dimensions of b%@AE@%%@NL@%
  17882. IF (lo <> LBOUND(b)) OR (up <> UBOUND(b)) THEN ERROR 197%@NL@%
  17883. bserrcode% = matbsD%(A(), b(), x())          'Backsolve system%@NL@%
  17884. IF bserrcode% THEN ERROR bserrcode%%@NL@%
  17885. FOR row% = lo TO up%@NL@%
  17886.    b(row%) = x(row%)                         'Put solution in b for return%@NL@%
  17887. NEXT row%%@NL@%
  17888. IF errcode% THEN ERROR errcode%%@NL@%
  17889. dseqnexit:%@NL@%
  17890. ERASE x, rpvt, cpvt%@NL@%
  17891. MatSEqnD% = errcode%%@NL@%
  17892. EXIT FUNCTION%@NL@%
  17893. dseqnerr:%@NL@%
  17894.    errcode% = (ERR + 5) MOD 200 - 5%@NL@%
  17895.    RESUME dseqnexit%@NL@%
  17896. END FUNCTION%@NL@%
  17897. %@NL@%
  17898. %@AB@%'========================MatSEqnS%==================================%@AE@%%@NL@%
  17899. %@AB@%'MatSEqnS% solves a system of n linear equations, Ax=b, and puts the%@AE@%%@NL@%
  17900. %@AB@%'answer in b. A is first put in LU form by matluS%, then matbsS is called%@AE@%%@NL@%
  17901. %@AB@%'to solve the system.  matrices A,b are single precision.%@AE@%%@NL@%
  17902. %@AB@%'%@AE@%%@NL@%
  17903. %@AB@%'Parameters: A(n x n) contains coefficient matrix, b(N) contains the right side%@AE@%%@NL@%
  17904. %@AB@%'%@AE@%%@NL@%
  17905. %@AB@%'Returns: A in LU form, solution in b%@AE@%%@NL@%
  17906. %@AB@%'===================================================================%@AE@%%@NL@%
  17907. FUNCTION MatSEqnS% (A() AS SINGLE, b() AS SINGLE)%@NL@%
  17908. ON LOCAL ERROR GOTO sseqnerr: errcode% = 0%@NL@%
  17909. lo = LBOUND(A, 1)%@NL@%
  17910. up = UBOUND(A, 1)%@NL@%
  17911. DIM x(lo TO up) AS SINGLE%@NL@%
  17912. REDIM rpvt(lo TO up) AS INTEGER, cpvt(lo TO up) AS INTEGER%@NL@%
  17913. errcode% = matluS%(A())                      'Get LU matrix%@NL@%
  17914. IF NOT continue THEN ERROR errcode%%@NL@%
  17915. %@AB@%'check dimensions of b%@AE@%%@NL@%
  17916. IF (lo <> LBOUND(b)) OR (up <> UBOUND(b)) THEN ERROR 197%@NL@%
  17917. bserrcode% = matbsS%(A(), b(), x())          'Backsolve system%@NL@%
  17918. IF bserrcode% THEN ERROR bserrcode%%@NL@%
  17919. FOR row% = lo TO up%@NL@%
  17920.    b(row%) = x(row%)                         'Put solution in b for return%@NL@%
  17921. NEXT row%%@NL@%
  17922. IF errcode% THEN ERROR errcode%%@NL@%
  17923. sseqnexit:%@NL@%
  17924. ERASE x, rpvt, cpvt%@NL@%
  17925. MatSEqnS% = errcode%%@NL@%
  17926. EXIT FUNCTION%@NL@%
  17927. sseqnerr:%@NL@%
  17928.    errcode% = (ERR + 5) MOD 200 - 5%@NL@%
  17929.    RESUME sseqnexit%@NL@%
  17930. END FUNCTION%@NL@%
  17931. %@NL@%
  17932. %@AB@%'=======================MatSubC%====================================%@AE@%%@NL@%
  17933. %@AB@%'MatSubC% takes the difference of two currency type matrices and%@AE@%%@NL@%
  17934. %@AB@%'places the result in the first.%@AE@%%@NL@%
  17935. %@AB@%'%@AE@%%@NL@%
  17936. %@AB@%'Params: matrices Alpha,Beta%@AE@%%@NL@%
  17937. %@AB@%'%@AE@%%@NL@%
  17938. %@AB@%'Returns: Alpha=Alpha-Beta%@AE@%%@NL@%
  17939. %@AB@%'===================================================================%@AE@%%@NL@%
  17940. FUNCTION MatSubC% (Alpha() AS CURRENCY, Beta() AS CURRENCY)%@NL@%
  17941. ON LOCAL ERROR GOTO csuberr: MatSubC% = 0%@NL@%
  17942. %@AB@%'check if Alpha, Beta have same dimensions if not, exit and send back error%@AE@%%@NL@%
  17943. IF (LBOUND(Alpha, 1) <> LBOUND(Beta, 1)) OR (UBOUND(Alpha, 1) <> UBOUND(Beta, 1)) OR (LBOUND(Alpha, 2) <> LBOUND(Beta, 2)) OR (UBOUND(Alpha, 2) <> UBOUND(Beta, 2)) THEN ERROR 196%@NL@%
  17944. %@AB@%'loop through and subtract elements%@AE@%%@NL@%
  17945. FOR row% = LBOUND(Alpha, 1) TO UBOUND(Alpha, 1)%@NL@%
  17946.    FOR col% = LBOUND(Alpha, 2) TO UBOUND(Alpha, 2)%@NL@%
  17947.       Alpha(row%, col%) = Alpha(row%, col%) - Beta(row%, col%)%@NL@%
  17948.    NEXT col%%@NL@%
  17949. NEXT row%%@NL@%
  17950. csubexit:%@NL@%
  17951. EXIT FUNCTION%@NL@%
  17952. csuberr:%@NL@%
  17953.    MatSubC% = (ERR + 5) MOD 200 - 5%@NL@%
  17954.    RESUME csubexit:%@NL@%
  17955. END FUNCTION%@NL@%
  17956. %@NL@%
  17957. %@AB@%'=======================MatSubD%====================================%@AE@%%@NL@%
  17958. %@AB@%'MatSubD% takes the difference of two double precision matrices and%@AE@%%@NL@%
  17959. %@AB@%'places the result in the first.%@AE@%%@NL@%
  17960. %@AB@%'%@AE@%%@NL@%
  17961. %@AB@%'Parameters: matrices Alpha,Beta%@AE@%%@NL@%
  17962. %@AB@%'%@AE@%%@NL@%
  17963. %@AB@%'Returns: Alpha() = Alpha() - Beta()%@AE@%%@NL@%
  17964. %@AB@%'===================================================================%@AE@%%@NL@%
  17965. FUNCTION MatSubD% (Alpha() AS DOUBLE, Beta() AS DOUBLE)%@NL@%
  17966. ON LOCAL ERROR GOTO dsuberr: MatSubD% = 0%@NL@%
  17967. %@AB@%'check if Alpha, Beta have same dimensions if not, exit and send back error%@AE@%%@NL@%
  17968. IF (LBOUND(Alpha, 1) <> LBOUND(Beta, 1)) OR (UBOUND(Alpha, 1) <> UBOUND(Beta, 1)) OR (LBOUND(Alpha, 2) <> LBOUND(Beta, 2)) OR (UBOUND(Alpha, 2) <> UBOUND(Beta, 2)) THEN ERROR 196%@NL@%
  17969. %@AB@%'loop through and subtract elements%@AE@%%@NL@%
  17970. FOR row% = LBOUND(Alpha, 1) TO UBOUND(Alpha, 1)%@NL@%
  17971.    FOR col% = LBOUND(Alpha, 2) TO UBOUND(Alpha, 2)%@NL@%
  17972.       Alpha(row%, col%) = Alpha(row%, col%) - Beta(row%, col%)%@NL@%
  17973.    NEXT col%%@NL@%
  17974. NEXT row%%@NL@%
  17975. dsubexit:%@NL@%
  17976. EXIT FUNCTION%@NL@%
  17977. dsuberr:%@NL@%
  17978.    MatSubD% = (ERR + 5) MOD 200 - 5%@NL@%
  17979.    RESUME dsubexit:%@NL@%
  17980. END FUNCTION%@NL@%
  17981. %@NL@%
  17982. %@AB@%'=======================MatSubI%====================================%@AE@%%@NL@%
  17983. %@AB@%'MatSubI% takes the difference of two integer matrices and places the%@AE@%%@NL@%
  17984. %@AB@%'result in the first.%@AE@%%@NL@%
  17985. %@AB@%'%@AE@%%@NL@%
  17986. %@AB@%'Parameters: matrices Alpha,Beta%@AE@%%@NL@%
  17987. %@AB@%'%@AE@%%@NL@%
  17988. %@AB@%'Returns: Alpha() = Alpha() - Beta()%@AE@%%@NL@%
  17989. %@AB@%'===================================================================%@AE@%%@NL@%
  17990. FUNCTION MatSubI% (Alpha() AS INTEGER, Beta() AS INTEGER)%@NL@%
  17991. ON LOCAL ERROR GOTO isuberr: MatSubI% = 0%@NL@%
  17992. %@AB@%'check if Alpha, Beta have same dimensions if not, exit and send back error%@AE@%%@NL@%
  17993. IF (LBOUND(Alpha, 1) <> LBOUND(Beta, 1)) OR (UBOUND(Alpha, 1) <> UBOUND(Beta, 1)) OR (LBOUND(Alpha, 2) <> LBOUND(Beta, 2)) OR (UBOUND(Alpha, 2) <> UBOUND(Beta, 2)) THEN ERROR 196%@NL@%
  17994. %@AB@%'loop through and subtract elements%@AE@%%@NL@%
  17995. FOR row% = LBOUND(Alpha, 1) TO UBOUND(Alpha, 1)%@NL@%
  17996.    FOR col% = LBOUND(Alpha, 2) TO UBOUND(Alpha, 2)%@NL@%
  17997.       Alpha(row%, col%) = Alpha(row%, col%) - Beta(row%, col%)%@NL@%
  17998.    NEXT col%%@NL@%
  17999. NEXT row%%@NL@%
  18000. isubexit:%@NL@%
  18001. EXIT FUNCTION%@NL@%
  18002. isuberr:%@NL@%
  18003.    MatSubI% = (ERR + 5) MOD 200 - 5%@NL@%
  18004.    RESUME isubexit:%@NL@%
  18005. END FUNCTION%@NL@%
  18006. %@NL@%
  18007. %@AB@%'=======================MatSubL%====================================%@AE@%%@NL@%
  18008. %@AB@%'MatSubL% takes the difference of two long integer matrices and places%@AE@%%@NL@%
  18009. %@AB@%'the result in the first.%@AE@%%@NL@%
  18010. %@AB@%'%@AE@%%@NL@%
  18011. %@AB@%'Parameters: matrices Alpha,Beta%@AE@%%@NL@%
  18012. %@AB@%'%@AE@%%@NL@%
  18013. %@AB@%'Returns: Alpha() = Alpha() - Beta()%@AE@%%@NL@%
  18014. %@AB@%'===================================================================%@AE@%%@NL@%
  18015. FUNCTION MatSubL% (Alpha() AS LONG, Beta() AS LONG)%@NL@%
  18016. ON LOCAL ERROR GOTO lsuberr: MatSubL% = 0%@NL@%
  18017. %@AB@%'check if Alpha, Beta have same dimensions if not, exit and send back error%@AE@%%@NL@%
  18018. IF (LBOUND(Alpha, 1) <> LBOUND(Beta, 1)) OR (UBOUND(Alpha, 1) <> UBOUND(Beta, 1)) OR (LBOUND(Alpha, 2) <> LBOUND(Beta, 2)) OR (UBOUND(Alpha, 2) <> UBOUND(Beta, 2)) THEN ERROR 196%@NL@%
  18019. %@AB@%'loop through and subtract elements%@AE@%%@NL@%
  18020. FOR row% = LBOUND(Alpha, 1) TO UBOUND(Alpha, 1)%@NL@%
  18021.    FOR col% = LBOUND(Alpha, 2) TO UBOUND(Alpha, 2)%@NL@%
  18022.       Alpha(row%, col%) = Alpha(row%, col%) - Beta(row%, col%)%@NL@%
  18023.    NEXT col%%@NL@%
  18024. NEXT row%%@NL@%
  18025. lsubexit:%@NL@%
  18026. EXIT FUNCTION%@NL@%
  18027. lsuberr:%@NL@%
  18028.    MatSubL% = (ERR + 5) MOD 200 - 5%@NL@%
  18029.    RESUME lsubexit:%@NL@%
  18030. END FUNCTION%@NL@%
  18031. %@NL@%
  18032. %@AB@%'=======================MatSubS%====================================%@AE@%%@NL@%
  18033. %@AB@%'MatSubS% takes the difference of two single precision matrices and%@AE@%%@NL@%
  18034. %@AB@%'places the result in the first.%@AE@%%@NL@%
  18035. %@AB@%'%@AE@%%@NL@%
  18036. %@AB@%'Parameters: matrices Alpha,Beta%@AE@%%@NL@%
  18037. %@AB@%'%@AE@%%@NL@%
  18038. %@AB@%'Returns: Alpha() = Alpha() - Beta()%@AE@%%@NL@%
  18039. %@AB@%'===================================================================%@AE@%%@NL@%
  18040. FUNCTION MatSubS% (Alpha() AS SINGLE, Beta() AS SINGLE)%@NL@%
  18041. ON LOCAL ERROR GOTO ssuberr: MatSubS% = 0%@NL@%
  18042. %@AB@%'check if Alpha, Beta have same dimensions if not, exit and send back error%@AE@%%@NL@%
  18043. IF (LBOUND(Alpha, 1) <> LBOUND(Beta, 1)) OR (UBOUND(Alpha, 1) <> UBOUND(Beta, 1)) OR (LBOUND(Alpha, 2) <> LBOUND(Beta, 2)) OR (UBOUND(Alpha, 2) <> UBOUND(Beta, 2)) THEN ERROR 196%@NL@%
  18044. %@AB@%'loop through and subtract elements%@AE@%%@NL@%
  18045. FOR row% = LBOUND(Alpha, 1) TO UBOUND(Alpha, 1)%@NL@%
  18046.    FOR col% = LBOUND(Alpha, 2) TO UBOUND(Alpha, 2)%@NL@%
  18047.       Alpha(row%, col%) = Alpha(row%, col%) - Beta(row%, col%)%@NL@%
  18048.    NEXT col%%@NL@%
  18049. NEXT row%%@NL@%
  18050. ssubexit:%@NL@%
  18051. EXIT FUNCTION%@NL@%
  18052. ssuberr:%@NL@%
  18053.    MatSubS% = (ERR + 5) MOD 200 - 5%@NL@%
  18054.    RESUME ssubexit:%@NL@%
  18055. END FUNCTION%@NL@%
  18056. %@NL@%
  18057. %@NL@%
  18058. %@NL@%
  18059. %@2@%%@AH@%MENU.BAS%@AE@%%@EH@%%@NL@%
  18060. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\MENU.BAS%@AE@%%@NL@%
  18061. %@NL@%
  18062. %@AB@%'============================================================================%@AE@%%@NL@%
  18063. %@AB@%'%@AE@%%@NL@%
  18064. %@AB@%'     MENU.BAS - Pull-down Menu Routines for the User Interface Toolbox in%@AE@%%@NL@%
  18065. %@AB@%'           Microsoft BASIC 7.0, Professional Development System%@AE@%%@NL@%
  18066. %@AB@%'              Copyright (C) 1987-1989, Microsoft Corporation%@AE@%%@NL@%
  18067. %@AB@%'%@AE@%%@NL@%
  18068. %@AB@%'  NOTE:    This sample source code toolbox is intended to demonstrate some%@AE@%%@NL@%
  18069. %@AB@%'           of the extended capabilities of Microsoft BASIC 7.0 Professional%@AE@%%@NL@%
  18070. %@AB@%'           Development system that can help to leverage the professional%@AE@%%@NL@%
  18071. %@AB@%'           developer's time more effectively.  While you are free to use,%@AE@%%@NL@%
  18072. %@AB@%'           modify, or distribute the routines in this module in any way you%@AE@%%@NL@%
  18073. %@AB@%'           find useful, it should be noted that these are examples only and%@AE@%%@NL@%
  18074. %@AB@%'           should not be relied upon as a fully-tested "add-on" library.%@AE@%%@NL@%
  18075. %@AB@%'%@AE@%%@NL@%
  18076. %@AB@%'  PURPOSE: These are the routines which provide support for the pull-down%@AE@%%@NL@%
  18077. %@AB@%'           menus in the user interface toolbox.%@AE@%%@NL@%
  18078. %@AB@%'%@AE@%%@NL@%
  18079. %@AB@%'  For information on creating a library and QuickLib from the routines%@AE@%%@NL@%
  18080. %@AB@%'  contained in this file, read the comment header of GENERAL.BAS.%@AE@%%@NL@%
  18081. %@AB@%'%@AE@%%@NL@%
  18082. %@AB@%'============================================================================%@AE@%%@NL@%
  18083. %@NL@%
  18084. DEFINT A-Z%@NL@%
  18085. %@NL@%
  18086. %@AB@%'$INCLUDE: 'general.bi'%@AE@%%@NL@%
  18087. %@AB@%'$INCLUDE: 'mouse.bi'%@AE@%%@NL@%
  18088. %@AB@%'$INCLUDE: 'menu.bi'%@AE@%%@NL@%
  18089. %@NL@%
  18090. COMMON SHARED /uitools/ GloMenu    AS MenuMiscType%@NL@%
  18091. COMMON SHARED /uitools/ GloTitle() AS MenuTitleType%@NL@%
  18092. COMMON SHARED /uitools/ GloItem()  AS MenuItemType%@NL@%
  18093. %@NL@%
  18094. FUNCTION MenuCheck (action%) STATIC%@NL@%
  18095. %@NL@%
  18096.     SELECT CASE action%@NL@%
  18097. %@NL@%
  18098. %@AB@%    '=======================================================================%@AE@%%@NL@%
  18099. %@AB@%    ' This simulates "polling" for a menu event.  If a menu event occured,%@AE@%%@NL@%
  18100. %@AB@%    ' GloMenu.currMenu and .currItem are set.  When MenuCheck(0) is%@AE@%%@NL@%
  18101. %@AB@%    ' called, these values are transfered to .lastMenu and .lastItem.%@AE@%%@NL@%
  18102. %@AB@%    ' MenuCheck(0) then returns the menu number, or 0 (FALSE) if none%@AE@%%@NL@%
  18103. %@AB@%    ' selected as of last call%@AE@%%@NL@%
  18104. %@AB@%    '=======================================================================%@AE@%%@NL@%
  18105. %@NL@%
  18106.         CASE 0%@NL@%
  18107.             GloMenu.lastMenu = GloMenu.currMenu%@NL@%
  18108.             GloMenu.lastItem = GloMenu.currItem%@NL@%
  18109.             GloMenu.currMenu = 0%@NL@%
  18110.             GloMenu.currItem = 0%@NL@%
  18111.             MenuCheck = GloMenu.lastMenu%@NL@%
  18112. %@NL@%
  18113. %@AB@%        '===================================================================%@AE@%%@NL@%
  18114. %@AB@%        ' Returns the menu item last selected.  Functions only after a call%@AE@%%@NL@%
  18115. %@AB@%        ' to MenuCheck(0)%@AE@%%@NL@%
  18116. %@AB@%        '===================================================================%@AE@%%@NL@%
  18117. %@NL@%
  18118.         CASE 1%@NL@%
  18119.             MenuCheck = GloMenu.lastItem%@NL@%
  18120. %@NL@%
  18121. %@AB@%        '===================================================================%@AE@%%@NL@%
  18122. %@AB@%        ' Checks GloMenu.currMenu and .currItem.  If both are not 0, this%@AE@%%@NL@%
  18123. %@AB@%        ' returns TRUE meaning a menu has been selected since MenuCheck(0)%@AE@%%@NL@%
  18124. %@AB@%        ' was last called.  This does not change any values, it simply%@AE@%%@NL@%
  18125. %@AB@%        ' reports on the current state.%@AE@%%@NL@%
  18126. %@AB@%        '===================================================================%@AE@%%@NL@%
  18127. %@NL@%
  18128.         CASE 2%@NL@%
  18129.             IF GloMenu.currMenu = 0 OR GloMenu.currItem = 0 THEN%@NL@%
  18130.                 MenuCheck = FALSE%@NL@%
  18131.             ELSE%@NL@%
  18132.                 MenuCheck = TRUE%@NL@%
  18133.             END IF%@NL@%
  18134.         CASE ELSE%@NL@%
  18135.             MenuCheck = 0%@NL@%
  18136.     END SELECT%@NL@%
  18137. %@NL@%
  18138. END FUNCTION%@NL@%
  18139. %@NL@%
  18140. SUB MenuColor (fore, back, highlight, disabled, cursorFore, cursorBack, cursorHi)%@NL@%
  18141. %@NL@%
  18142.     GloMenu.fore = fore%@NL@%
  18143.     GloMenu.back = back%@NL@%
  18144.     GloMenu.highlight = highlight%@NL@%
  18145.     GloMenu.disabled = disabled%@NL@%
  18146.     GloMenu.cursorFore = cursorFore%@NL@%
  18147.     GloMenu.cursorBack = cursorBack%@NL@%
  18148.     GloMenu.cursorHi = cursorHi%@NL@%
  18149. %@NL@%
  18150. END SUB%@NL@%
  18151. %@NL@%
  18152. SUB MenuDo STATIC%@NL@%
  18153. %@NL@%
  18154. %@AB@%    '=======================================================================%@AE@%%@NL@%
  18155. %@AB@%    ' If menu event trapping turned off, return immediately%@AE@%%@NL@%
  18156. %@AB@%    '=======================================================================%@AE@%%@NL@%
  18157. %@NL@%
  18158.     IF NOT GloMenu.MenuOn THEN%@NL@%
  18159.         EXIT SUB%@NL@%
  18160.     END IF%@NL@%
  18161. %@NL@%
  18162. %@AB@%    '=======================================================================%@AE@%%@NL@%
  18163. %@AB@%    ' Initialize MenuDo's variables, and then enter the main loop%@AE@%%@NL@%
  18164. %@AB@%    '=======================================================================%@AE@%%@NL@%
  18165. %@NL@%
  18166.     GOSUB MenuDoInit%@NL@%
  18167. %@NL@%
  18168.     WHILE NOT MenuDoDone%@NL@%
  18169. %@NL@%
  18170. %@AB@%        '===================================================================%@AE@%%@NL@%
  18171. %@AB@%        ' If in MouseMode then%@AE@%%@NL@%
  18172. %@AB@%        '   if button is pressed, check where mouse is and react acccordingly.%@AE@%%@NL@%
  18173. %@AB@%        '   if button not pressed, switch to keyboard mode.%@AE@%%@NL@%
  18174. %@AB@%        '===================================================================%@AE@%%@NL@%
  18175.         IF mouseMode THEN%@NL@%
  18176.             MousePoll mouseRow, mouseCol, lButton, rButton%@NL@%
  18177.             IF lButton THEN%@NL@%
  18178.                 IF mouseRow = 1 THEN%@NL@%
  18179.                     GOSUB MenuDoGetMouseMenu%@NL@%
  18180.                 ELSE%@NL@%
  18181.                     GOSUB MenuDoGetMouseItem%@NL@%
  18182.                 END IF%@NL@%
  18183.             ELSE%@NL@%
  18184.                 mouseMode = FALSE%@NL@%
  18185.                 GOSUB MenuDoMouseRelease%@NL@%
  18186.                 IF NOT pulldown THEN%@NL@%
  18187.                     GOSUB MenuDoShowTitleAccessKeys%@NL@%
  18188.                 END IF%@NL@%
  18189.             END IF%@NL@%
  18190.         ELSE%@NL@%
  18191. %@NL@%
  18192. %@AB@%            '===============================================================%@AE@%%@NL@%
  18193. %@AB@%            ' If in keyboard mode, show the cursor, wait for key, hide cursor%@AE@%%@NL@%
  18194. %@AB@%            ' Perform the desired action based on what key was pressed.%@AE@%%@NL@%
  18195. %@AB@%            '===============================================================%@AE@%%@NL@%
  18196. %@NL@%
  18197.             GOSUB MenuDoShowCursor%@NL@%
  18198.             GOSUB MenuDoGetKey%@NL@%
  18199.             GOSUB MenuDoHideCursor%@NL@%
  18200. %@NL@%
  18201.             SELECT CASE kbd$%@NL@%
  18202.                 CASE "enter":       GOSUB MenuDoEnter%@NL@%
  18203.                 CASE "up":          GOSUB MenuDoUp%@NL@%
  18204.                 CASE "down":        GOSUB menuDoDown%@NL@%
  18205.                 CASE "left":        GOSUB MenuDoLeft%@NL@%
  18206.                 CASE "right":       GOSUB MenuDoRight%@NL@%
  18207.                 CASE "escape":      GOSUB MenuDoEscape%@NL@%
  18208.                 CASE "altReleased": GOSUB MenuDoAltReleased%@NL@%
  18209.                 CASE "mouse":       GOSUB MenuDoMousePress%@NL@%
  18210.                 CASE ELSE:          GOSUB MenuDoAccessKey%@NL@%
  18211.             END SELECT%@NL@%
  18212.         END IF%@NL@%
  18213.     WEND%@NL@%
  18214.     GOSUB MenuDoHideTitleAccessKeys%@NL@%
  18215.     EXIT SUB%@NL@%
  18216. %@NL@%
  18217. %@AB@%'===========================================================================%@AE@%%@NL@%
  18218. %@AB@%' Initialize variables for proper MenuDo execution.%@AE@%%@NL@%
  18219. %@AB@%'===========================================================================%@AE@%%@NL@%
  18220. %@NL@%
  18221. MenuDoInit:%@NL@%
  18222.     REDIM buffer$(MAXMENU), copyFlag(MAXMENU)             'Stores screen backround%@NL@%
  18223. %@NL@%
  18224.     FOR a = 1 TO MAXMENU%@NL@%
  18225.         buffer$(a) = ""                         '1 buffer per menu%@NL@%
  18226.         copyFlag(a) = FALSE                     'FALSE means not copied yet%@NL@%
  18227.     NEXT a%@NL@%
  18228. %@NL@%
  18229.     pulldown = FALSE                            'FALSE means no menu is shown%@NL@%
  18230.     MenuDoDone = FALSE                          'FALSE means keep going in loop%@NL@%
  18231. %@NL@%
  18232.     altWasReleased = FALSE                      'Set to TRUE if ALT is pressed%@NL@%
  18233. %@AB@%                                                'and then released%@AE@%%@NL@%
  18234. %@NL@%
  18235.     altWasPressedAgain = FALSE                  'Set to TRUE is ALT is pressed%@NL@%
  18236. %@AB@%                                                'and then released, and then%@AE@%%@NL@%
  18237. %@AB@%                                                'pressed again.%@AE@%%@NL@%
  18238. %@NL@%
  18239. %@AB@%    '=======================================================================%@AE@%%@NL@%
  18240. %@AB@%    ' If mouse installed and button is pressed, then set MouseMode to TRUE%@AE@%%@NL@%
  18241. %@AB@%    ' Else, set MouseMode to FALSE%@AE@%%@NL@%
  18242. %@AB@%    '=======================================================================%@AE@%%@NL@%
  18243. %@NL@%
  18244.     MousePoll mouseRow, mouseCol, lButton, rButton%@NL@%
  18245.     IF lButton THEN%@NL@%
  18246.         mouseMode = TRUE%@NL@%
  18247.         currMenu = 0%@NL@%
  18248.         currItem = 0%@NL@%
  18249.     ELSE%@NL@%
  18250.         mouseMode = FALSE%@NL@%
  18251.         currMenu = 1%@NL@%
  18252.         currItem = 0%@NL@%
  18253.         GOSUB MenuDoShowTitleAccessKeys%@NL@%
  18254.     END IF%@NL@%
  18255. %@NL@%
  18256. RETURN%@NL@%
  18257. %@NL@%
  18258. %@AB@%'===========================================================================%@AE@%%@NL@%
  18259. %@AB@%' This shows the cursor at the location CurrMenu,CurrItem.%@AE@%%@NL@%
  18260. %@AB@%'===========================================================================%@AE@%%@NL@%
  18261. %@NL@%
  18262. MenuDoShowCursor:%@NL@%
  18263. %@NL@%
  18264.     MouseHide%@NL@%
  18265.     IF currMenu <> 0 AND RTRIM$(GloItem(currMenu, currItem).text) <> "-" THEN%@NL@%
  18266.         IF currItem = 0 THEN%@NL@%
  18267.             COLOR GloMenu.cursorFore, GloMenu.cursorBack%@NL@%
  18268.             LOCATE 1, GloTitle(currMenu).lColTitle%@NL@%
  18269.             PRINT " "; RTRIM$(GloTitle(currMenu).text); " ";%@NL@%
  18270.             IF NOT mouseMode THEN%@NL@%
  18271.                COLOR GloMenu.cursorHi, GloMenu.cursorBack%@NL@%
  18272.                LOCATE 1, GloTitle(currMenu).lColTitle + GloTitle(currMenu).accessKey%@NL@%
  18273.                PRINT MID$(GloTitle(currMenu).text, GloTitle(currMenu).accessKey, 1);%@NL@%
  18274.             END IF%@NL@%
  18275.         ELSE%@NL@%
  18276.             IF GloItem(currMenu, currItem).state = 2 THEN%@NL@%
  18277.                 chk$ = CHR$(175)%@NL@%
  18278.             ELSE%@NL@%
  18279.                 chk$ = " "%@NL@%
  18280.             END IF%@NL@%
  18281. %@NL@%
  18282.             COLOR GloMenu.cursorFore, GloMenu.cursorBack%@NL@%
  18283.             LOCATE GloItem(currMenu, currItem).row, GloTitle(currMenu).lColItem + 1%@NL@%
  18284.             PRINT chk$; LEFT$(GloItem(currMenu, currItem).text, GloTitle(currMenu).itemLength); " ";%@NL@%
  18285. %@NL@%
  18286.             IF GloItem(currMenu, currItem).state > 0 THEN%@NL@%
  18287.                 COLOR GloMenu.cursorHi, GloMenu.cursorBack%@NL@%
  18288.                 LOCATE GloItem(currMenu, currItem).row, col + GloItem(currMenu, currItem).accessKey + 1%@NL@%
  18289.                 PRINT MID$(GloItem(currMenu, currItem).text, GloItem(currMenu, currItem).accessKey, 1);%@NL@%
  18290.             END IF%@NL@%
  18291. %@NL@%
  18292.         END IF%@NL@%
  18293.     END IF%@NL@%
  18294.     MouseShow%@NL@%
  18295. %@NL@%
  18296. RETURN%@NL@%
  18297. %@NL@%
  18298. %@AB@%'===========================================================================%@AE@%%@NL@%
  18299. %@AB@%' This hides the cursor at the location CurrMenu,CurrItem.%@AE@%%@NL@%
  18300. %@AB@%'===========================================================================%@AE@%%@NL@%
  18301. %@NL@%
  18302. MenuDoHideCursor:%@NL@%
  18303. %@NL@%
  18304.     MouseHide%@NL@%
  18305.     IF currMenu <> 0 AND RTRIM$(GloItem(currMenu, currItem).text) <> "-" THEN%@NL@%
  18306.         IF currItem = 0 THEN%@NL@%
  18307.             SELECT CASE GloTitle(currMenu).state%@NL@%
  18308.                 CASE 0: COLOR GloMenu.disabled, GloMenu.back%@NL@%
  18309.                 CASE 1, 2: COLOR GloMenu.fore, GloMenu.back%@NL@%
  18310.                 CASE ELSE%@NL@%
  18311.             END SELECT%@NL@%
  18312.             LOCATE 1, GloTitle(currMenu).lColTitle%@NL@%
  18313.             PRINT " "; RTRIM$(GloTitle(currMenu).text); " ";%@NL@%
  18314. %@NL@%
  18315.             IF GloTitle(currMenu).state > 0 THEN%@NL@%
  18316.                 COLOR GloMenu.highlight, GloMenu.back%@NL@%
  18317.                 LOCATE 1, GloTitle(currMenu).lColTitle + GloTitle(currMenu).accessKey%@NL@%
  18318.                 PRINT MID$(GloTitle(currMenu).text, GloTitle(currMenu).accessKey, 1);%@NL@%
  18319.             END IF%@NL@%
  18320.         ELSE%@NL@%
  18321.             IF GloItem(currMenu, currItem).state = 2 THEN%@NL@%
  18322.                 chk$ = CHR$(175)%@NL@%
  18323.             ELSE%@NL@%
  18324.                 chk$ = " "%@NL@%
  18325.             END IF%@NL@%
  18326.             SELECT CASE GloItem(currMenu, currItem).state%@NL@%
  18327.                 CASE 0: COLOR GloMenu.disabled, GloMenu.back%@NL@%
  18328.                 CASE 1, 2: COLOR GloMenu.fore, GloMenu.back%@NL@%
  18329.                 CASE ELSE%@NL@%
  18330.             END SELECT%@NL@%
  18331.             LOCATE GloItem(currMenu, currItem).row, GloTitle(currMenu).lColItem + 1%@NL@%
  18332.             PRINT chk$; LEFT$(GloItem(currMenu, currItem).text, GloTitle(currMenu).itemLength); " ";%@NL@%
  18333. %@NL@%
  18334.             IF GloItem(currMenu, currItem).state > 0 THEN%@NL@%
  18335.                 COLOR GloMenu.highlight, GloMenu.back%@NL@%
  18336.                 LOCATE GloItem(currMenu, currItem).row, col + GloItem(currMenu, currItem).accessKey + 1%@NL@%
  18337.                 PRINT MID$(GloItem(currMenu, currItem).text, GloItem(currMenu, currItem).accessKey, 1);%@NL@%
  18338.             END IF%@NL@%
  18339. %@NL@%
  18340.         END IF%@NL@%
  18341.     END IF%@NL@%
  18342.     MouseShow%@NL@%
  18343. RETURN%@NL@%
  18344. %@NL@%
  18345. %@AB@%'===========================================================================%@AE@%%@NL@%
  18346. %@AB@%' Handles state where mouse is at row #1.%@AE@%%@NL@%
  18347. %@AB@%'===========================================================================%@AE@%%@NL@%
  18348. %@NL@%
  18349. MenuDoGetMouseMenu:%@NL@%
  18350. %@NL@%
  18351. %@AB@%    '=======================================================================%@AE@%%@NL@%
  18352. %@AB@%    ' Computes the menu number based on mouse column location.  Uses info%@AE@%%@NL@%
  18353. %@AB@%    ' calculated in MenuShow()%@AE@%%@NL@%
  18354. %@AB@%    '=======================================================================%@AE@%%@NL@%
  18355. %@NL@%
  18356.     newMenu = CVI(MID$(GloMenu.menuIndex, mouseCol * 2 - 1, 2))%@NL@%
  18357. %@NL@%
  18358.     IF GloTitle(newMenu).state <> 1 THEN%@NL@%
  18359.         newMenu = 0%@NL@%
  18360.     END IF%@NL@%
  18361. %@NL@%
  18362. %@AB@%    '=======================================================================%@AE@%%@NL@%
  18363. %@AB@%    ' If new menu<>current menu, hide current menu, show new menu, assign new%@AE@%%@NL@%
  18364. %@AB@%    ' menu to current menu%@AE@%%@NL@%
  18365. %@AB@%    '=======================================================================%@AE@%%@NL@%
  18366. %@NL@%
  18367.     IF newMenu <> currMenu THEN%@NL@%
  18368.         GOSUB MenuDoHidePullDown%@NL@%
  18369.         currMenu = newMenu%@NL@%
  18370.         currItem = 0%@NL@%
  18371.         GOSUB menuDoShowPullDown%@NL@%
  18372.     END IF%@NL@%
  18373. %@NL@%
  18374. RETURN%@NL@%
  18375. %@NL@%
  18376. %@AB@%'===========================================================================%@AE@%%@NL@%
  18377. %@AB@%' Handles state where mouse is not in row #1.  If a menu is down, it picks%@AE@%%@NL@%
  18378. %@AB@%' the proper menu item based on which row the mouse is located%@AE@%%@NL@%
  18379. %@AB@%'===========================================================================%@AE@%%@NL@%
  18380. %@NL@%
  18381. MenuDoGetMouseItem:%@NL@%
  18382. %@NL@%
  18383. %@AB@%    '=======================================================================%@AE@%%@NL@%
  18384. %@AB@%    ' If pulldown, and mouse column is within the menu area, then compute new%@AE@%%@NL@%
  18385. %@AB@%    ' item  based on computations done in MenuShow.  If not in box, then new%@AE@%%@NL@%
  18386. %@AB@%    ' item = 0%@AE@%%@NL@%
  18387. %@AB@%    '=======================================================================%@AE@%%@NL@%
  18388. %@NL@%
  18389.     IF pulldown THEN%@NL@%
  18390.         IF mouseCol >= GloTitle(currMenu).lColItem AND mouseCol <= GloTitle(currMenu).rColItem AND mouseRow <= GloTitle(currMenu).lowestRow AND mouseRow - 2 <= MAXITEM THEN%@NL@%
  18391.             newItem = GloItem(currMenu, mouseRow - 2).index%@NL@%
  18392.         ELSE%@NL@%
  18393.             newItem = 0%@NL@%
  18394.         END IF%@NL@%
  18395. %@NL@%
  18396. %@AB@%        ' ===================================================================%@AE@%%@NL@%
  18397. %@AB@%        ' If current item <> new item, hide old cursor, show new cursor,%@AE@%%@NL@%
  18398. %@AB@%        ' assign new item to current item.%@AE@%%@NL@%
  18399. %@AB@%        ' ===================================================================%@AE@%%@NL@%
  18400. %@NL@%
  18401.         IF currItem <> newItem THEN%@NL@%
  18402.             IF currItem <> 0 THEN%@NL@%
  18403.                 GOSUB MenuDoHideCursor%@NL@%
  18404.             END IF%@NL@%
  18405.             currItem = newItem%@NL@%
  18406.             GOSUB MenuDoShowCursor%@NL@%
  18407.         END IF%@NL@%
  18408.     END IF%@NL@%
  18409. RETURN%@NL@%
  18410. %@NL@%
  18411. %@AB@%' ===========================================================================%@AE@%%@NL@%
  18412. %@AB@%' Handles state when MenuDo is in mouse mode, and mouse button is released.%@AE@%%@NL@%
  18413. %@AB@%' ===========================================================================%@AE@%%@NL@%
  18414. %@NL@%
  18415. MenuDoMouseRelease:%@NL@%
  18416.     menuMode = FALSE%@NL@%
  18417. %@NL@%
  18418. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  18419. %@AB@%    ' If no menu selected, then exit MenuDo returning 0s for menu and item%@AE@%%@NL@%
  18420. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  18421. %@NL@%
  18422.     IF currMenu = 0 THEN%@NL@%
  18423.         GloMenu.currMenu = 0%@NL@%
  18424.         GloMenu.currItem = 0%@NL@%
  18425.         MenuDoDone = TRUE%@NL@%
  18426.     ELSE%@NL@%
  18427. %@NL@%
  18428. %@AB@%        ' ===================================================================%@AE@%%@NL@%
  18429. %@AB@%        ' If menu is down, but no item is selected then%@AE@%%@NL@%
  18430. %@AB@%        '    if mouse is on the top row, simply gosub the MenuDoDown routine%@AE@%%@NL@%
  18431. %@AB@%        '    else hide menu then exit MenuDo returning 0's for menu and item%@AE@%%@NL@%
  18432. %@AB@%        ' ===================================================================%@AE@%%@NL@%
  18433. %@NL@%
  18434.         IF currItem = 0 THEN%@NL@%
  18435.             IF mouseRow = 1 THEN%@NL@%
  18436.                 GOSUB menuDoDown%@NL@%
  18437.             ELSE%@NL@%
  18438.                 GOSUB MenuDoHidePullDown%@NL@%
  18439.                 GloMenu.currMenu = 0%@NL@%
  18440.                 GloMenu.currItem = 0%@NL@%
  18441.                 MenuDoDone = TRUE%@NL@%
  18442.             END IF%@NL@%
  18443.         ELSE%@NL@%
  18444. %@NL@%
  18445. %@AB@%            ' ===============================================================%@AE@%%@NL@%
  18446. %@AB@%            ' If current (menu,item)'s state is disabled, then just beep%@AE@%%@NL@%
  18447. %@AB@%            ' ===============================================================%@AE@%%@NL@%
  18448. %@NL@%
  18449.             IF GloItem(currMenu, currItem).state = 0 THEN%@NL@%
  18450.                 BEEP%@NL@%
  18451. %@NL@%
  18452. %@AB@%            ' ===============================================================%@AE@%%@NL@%
  18453. %@AB@%            ' If current (menu,item)'s state is a line%@AE@%%@NL@%
  18454. %@AB@%            ' then exit MenuDo returning 0s for menu and item%@AE@%%@NL@%
  18455. %@AB@%            ' ===============================================================%@AE@%%@NL@%
  18456. %@NL@%
  18457.             ELSEIF RTRIM$(GloItem(currMenu, currItem).text) = "-" THEN%@NL@%
  18458.                 GOSUB MenuDoHidePullDown%@NL@%
  18459.                 GloMenu.currMenu = 0%@NL@%
  18460.                 GloMenu.currItem = 0%@NL@%
  18461.                 MenuDoDone = TRUE%@NL@%
  18462.             ELSE%@NL@%
  18463. %@NL@%
  18464. %@AB@%                ' ===========================================================%@AE@%%@NL@%
  18465. %@AB@%                ' Otherwise, selection must be valid, exit MenuDo, returning%@AE@%%@NL@%
  18466. %@AB@%                ' proper menu,item pair in the proper global variables%@AE@%%@NL@%
  18467. %@AB@%                ' ===========================================================%@AE@%%@NL@%
  18468.                 GOSUB MenuDoHidePullDown%@NL@%
  18469.                 GloMenu.currMenu = currMenu%@NL@%
  18470.                 GloMenu.currItem = currItem%@NL@%
  18471.                 MenuDoDone = TRUE%@NL@%
  18472.             END IF%@NL@%
  18473.         END IF%@NL@%
  18474.     END IF%@NL@%
  18475. RETURN%@NL@%
  18476. %@NL@%
  18477. %@AB@%' ==========================================================================%@AE@%%@NL@%
  18478. %@AB@%' This routine shows the menu bar's access keys%@AE@%%@NL@%
  18479. %@AB@%' ==========================================================================%@AE@%%@NL@%
  18480. %@NL@%
  18481. MenuDoShowTitleAccessKeys:%@NL@%
  18482.     MouseHide%@NL@%
  18483.     COLOR GloMenu.highlight, GloMenu.back%@NL@%
  18484.     FOR menu = 1 TO MAXMENU%@NL@%
  18485.         IF GloTitle(menu).state = 1 THEN%@NL@%
  18486.             LOCATE 1, GloTitle(menu).lColTitle + GloTitle(menu).accessKey%@NL@%
  18487.             PRINT MID$(GloTitle(menu).text, GloTitle(menu).accessKey, 1);%@NL@%
  18488.         END IF%@NL@%
  18489.     NEXT menu%@NL@%
  18490.     MouseShow%@NL@%
  18491. RETURN%@NL@%
  18492. %@NL@%
  18493. %@NL@%
  18494. %@AB@%' ===========================================================================%@AE@%%@NL@%
  18495. %@AB@%' This routine hides the menu bar's access keys%@AE@%%@NL@%
  18496. %@AB@%' ===========================================================================%@AE@%%@NL@%
  18497. %@NL@%
  18498. MenuDoHideTitleAccessKeys:%@NL@%
  18499.     MouseHide%@NL@%
  18500.     COLOR GloMenu.fore, GloMenu.back%@NL@%
  18501.     FOR menu = 1 TO MAXMENU%@NL@%
  18502.         IF GloTitle(menu).state = 1 THEN%@NL@%
  18503.             LOCATE 1, GloTitle(menu).lColTitle + GloTitle(menu).accessKey%@NL@%
  18504.             PRINT MID$(GloTitle(menu).text, GloTitle(menu).accessKey, 1);%@NL@%
  18505.         END IF%@NL@%
  18506.     NEXT menu%@NL@%
  18507.     MouseShow%@NL@%
  18508. RETURN%@NL@%
  18509. %@NL@%
  18510. %@AB@%' ===========================================================================%@AE@%%@NL@%
  18511. %@AB@%' Waits for key press, then returns the key press.  It also returns several%@AE@%%@NL@%
  18512. %@AB@%' tokens such as "menu", or "altReleased" in special cases.  Read on...%@AE@%%@NL@%
  18513. %@AB@%' ===========================================================================%@AE@%%@NL@%
  18514. %@NL@%
  18515. MenuDoGetKey:%@NL@%
  18516.     DO%@NL@%
  18517.         kbd$ = INKEY$%@NL@%
  18518. %@NL@%
  18519. %@AB@%        ' ===================================================================%@AE@%%@NL@%
  18520. %@AB@%        ' If ALT key pressed, then if it was a access key (Alt+A..) reduce%@AE@%%@NL@%
  18521. %@AB@%        '  the Alt+A to A.%@AE@%%@NL@%
  18522. %@AB@%        '  Also set the altPressed flags to reflect the current state of the%@AE@%%@NL@%
  18523. %@AB@%        '  ALT key.%@AE@%%@NL@%
  18524. %@AB@%        ' ===================================================================%@AE@%%@NL@%
  18525. %@NL@%
  18526.         IF GetShiftState(3) THEN%@NL@%
  18527.             IF kbd$ = "" THEN%@NL@%
  18528.                 IF altWasReleased THEN%@NL@%
  18529.                     altWasPressedAgain = TRUE%@NL@%
  18530.                 END IF%@NL@%
  18531.             ELSE%@NL@%
  18532.                 altWasPressedAgain = FALSE%@NL@%
  18533.                 kbd$ = AltToASCII(kbd$)%@NL@%
  18534.             END IF%@NL@%
  18535.             altWasReleased = FALSE%@NL@%
  18536.         ELSE%@NL@%
  18537. %@NL@%
  18538. %@AB@%            ' ===============================================================%@AE@%%@NL@%
  18539. %@AB@%            ' If ALT key is released (initially), then pressed, then released%@AE@%%@NL@%
  18540. %@AB@%            ' again with no other action in between, then return the%@AE@%%@NL@%
  18541. %@AB@%            ' token "altReleased"%@AE@%%@NL@%
  18542. %@AB@%            ' ===============================================================%@AE@%%@NL@%
  18543. %@NL@%
  18544.             IF altWasPressedAgain THEN%@NL@%
  18545.                 kbd$ = "altReleased"%@NL@%
  18546.                 altWasPressedAgain = FALSE%@NL@%
  18547.             ELSE%@NL@%
  18548. %@NL@%
  18549. %@AB@%                ' ===========================================================%@AE@%%@NL@%
  18550. %@AB@%                ' Based on the key that was pressed, return the proper token%@AE@%%@NL@%
  18551. %@AB@%                ' ===========================================================%@AE@%%@NL@%
  18552. %@NL@%
  18553.                 altWasReleased = TRUE%@NL@%
  18554. %@NL@%
  18555.                 SELECT CASE kbd$%@NL@%
  18556.                     CASE CHR$(27) + "": kbd$ = "escape"%@NL@%
  18557.                     CASE CHR$(32) + "": kbd$ = ""%@NL@%
  18558.                     CASE CHR$(13) + "": kbd$ = "enter"%@NL@%
  18559.                     CASE CHR$(0) + "H": kbd$ = "up"%@NL@%
  18560.                     CASE CHR$(0) + "P": kbd$ = "down"%@NL@%
  18561.                     CASE CHR$(0) + "K": kbd$ = "left"%@NL@%
  18562.                     CASE CHR$(0) + "M": kbd$ = "right"%@NL@%
  18563.                     CASE ELSE%@NL@%
  18564.                         IF LEN(kbd$) = 1 THEN%@NL@%
  18565.                             kbd$ = UCASE$(kbd$)%@NL@%
  18566.                         END IF%@NL@%
  18567.                 END SELECT%@NL@%
  18568.             END IF%@NL@%
  18569.         END IF%@NL@%
  18570. %@NL@%
  18571. %@AB@%        ' ===================================================================%@AE@%%@NL@%
  18572. %@AB@%        ' If mouse button is pressed, it overrides all key actions, and%@AE@%%@NL@%
  18573. %@AB@%        ' the token "mouse" is returned%@AE@%%@NL@%
  18574. %@AB@%        ' ===================================================================%@AE@%%@NL@%
  18575. %@NL@%
  18576.         MousePoll mouseRow, mouseCol, lButton, rButton%@NL@%
  18577.         IF lButton THEN%@NL@%
  18578.             kbd$ = "mouse"%@NL@%
  18579.         END IF%@NL@%
  18580. %@NL@%
  18581.     LOOP UNTIL kbd$ <> ""%@NL@%
  18582. %@NL@%
  18583. RETURN%@NL@%
  18584. %@NL@%
  18585. %@NL@%
  18586. %@AB@%' ===========================================================================%@AE@%%@NL@%
  18587. %@AB@%' Handles the state where the up arrow is pressed.  It searches for the%@AE@%%@NL@%
  18588. %@AB@%' first non empty, non "-" (dashed) item.%@AE@%%@NL@%
  18589. %@AB@%' ===========================================================================%@AE@%%@NL@%
  18590. %@NL@%
  18591. MenuDoUp:%@NL@%
  18592.     IF currItem <> 0 THEN%@NL@%
  18593.         DO%@NL@%
  18594.             currItem = (currItem + MAXITEM - 2) MOD MAXITEM + 1%@NL@%
  18595.         LOOP UNTIL GloItem(currMenu, currItem).state >= 0 AND RTRIM$(GloItem(currMenu, currItem).text) <> "-"%@NL@%
  18596.     END IF%@NL@%
  18597. RETURN%@NL@%
  18598. %@NL@%
  18599. %@NL@%
  18600. %@AB@%' ===========================================================================%@AE@%%@NL@%
  18601. %@AB@%' Handles 2 different states:%@AE@%%@NL@%
  18602. %@AB@%'%@AE@%%@NL@%
  18603. %@AB@%'  State 1: Menu is open, and the down arrow is pressed.%@AE@%%@NL@%
  18604. %@AB@%'%@AE@%%@NL@%
  18605. %@AB@%'  State 2: Any time a new menu is opened, and the top item%@AE@%%@NL@%
  18606. %@AB@%'      is to be the current item.  Specifically:%@AE@%%@NL@%
  18607. %@AB@%'          - When no menu is opened, and the down arrow is pressed%@AE@%%@NL@%
  18608. %@AB@%'          - When the mouse is released over the menu title%@AE@%%@NL@%
  18609. %@AB@%'          - When a menu is opened, and the user hits right/left arrow%@AE@%%@NL@%
  18610. %@AB@%'          - When enter is pressed while cursor is on title bar%@AE@%%@NL@%
  18611. %@AB@%'          - When a access key is used on the title bar.%@AE@%%@NL@%
  18612. %@AB@%' ===========================================================================%@AE@%%@NL@%
  18613. %@NL@%
  18614. menuDoDown:%@NL@%
  18615.     DO%@NL@%
  18616.         IF currItem = 0 THEN%@NL@%
  18617.             GOSUB MenuDoHideTitleAccessKeys%@NL@%
  18618.             GOSUB menuDoShowPullDown%@NL@%
  18619.             currItem = (currItem) MOD MAXITEM + 1%@NL@%
  18620.         ELSEIF currItem > 0 THEN%@NL@%
  18621.             currItem = (currItem) MOD MAXITEM + 1%@NL@%
  18622.         END IF%@NL@%
  18623. %@NL@%
  18624.     LOOP UNTIL GloItem(currMenu, currItem).state >= 0 AND RTRIM$(GloItem(currMenu, currItem).text) <> "-"%@NL@%
  18625. RETURN%@NL@%
  18626. %@NL@%
  18627. %@NL@%
  18628. %@AB@%' ===========================================================================%@AE@%%@NL@%
  18629. %@AB@%' Handles state when the left arrow is pressed.  If a menu is down, it%@AE@%%@NL@%
  18630. %@AB@%' hides it.  It then finds the first valid menu to the left.  If the menu%@AE@%%@NL@%
  18631. %@AB@%' was initially down, then the new menu is pulled down as well%@AE@%%@NL@%
  18632. %@AB@%' ===========================================================================%@AE@%%@NL@%
  18633. %@NL@%
  18634. MenuDoLeft:%@NL@%
  18635.     IF pulldown THEN%@NL@%
  18636.         GOSUB MenuDoHidePullDown%@NL@%
  18637.         pulldown = TRUE%@NL@%
  18638.     END IF%@NL@%
  18639. %@NL@%
  18640.     DO%@NL@%
  18641.         currMenu = (currMenu + MAXMENU - 2) MOD MAXMENU + 1%@NL@%
  18642.     LOOP UNTIL GloTitle(currMenu).state = 1%@NL@%
  18643. %@NL@%
  18644.     IF pulldown THEN%@NL@%
  18645.         currItem = 0%@NL@%
  18646.         GOSUB menuDoDown%@NL@%
  18647.     END IF%@NL@%
  18648. RETURN%@NL@%
  18649. %@NL@%
  18650. %@NL@%
  18651. %@AB@%' ===========================================================================%@AE@%%@NL@%
  18652. %@AB@%' Handles state when the right arrow is pressed.  If a menu is down, it%@AE@%%@NL@%
  18653. %@AB@%' hides it.  It then finds the first valid menu to the right.  If the menu%@AE@%%@NL@%
  18654. %@AB@%' was initially down, then the new menu is pulled down as well%@AE@%%@NL@%
  18655. %@AB@%' ===========================================================================%@AE@%%@NL@%
  18656. %@NL@%
  18657. MenuDoRight:%@NL@%
  18658.     IF pulldown THEN%@NL@%
  18659.         GOSUB MenuDoHidePullDown%@NL@%
  18660.         pulldown = TRUE%@NL@%
  18661.     END IF%@NL@%
  18662. %@NL@%
  18663.     DO%@NL@%
  18664.         currMenu = (currMenu) MOD MAXMENU + 1%@NL@%
  18665.     LOOP UNTIL GloTitle(currMenu).state = 1%@NL@%
  18666. %@NL@%
  18667.     IF pulldown THEN%@NL@%
  18668.         currItem = 0%@NL@%
  18669.         GOSUB menuDoDown%@NL@%
  18670.     END IF%@NL@%
  18671. RETURN%@NL@%
  18672. %@NL@%
  18673. %@NL@%
  18674. %@AB@%' ===========================================================================%@AE@%%@NL@%
  18675. %@AB@%' Handles state when the ESC key is pressed.  First hides the menu, and%@AE@%%@NL@%
  18676. %@AB@%' then exits menuDo, returning 0's in the proper global variables%@AE@%%@NL@%
  18677. %@AB@%' ===========================================================================%@AE@%%@NL@%
  18678. %@NL@%
  18679. MenuDoEscape:%@NL@%
  18680.     GOSUB MenuDoHidePullDown%@NL@%
  18681.     GloMenu.currMenu = 0%@NL@%
  18682.     GloMenu.currItem = 0%@NL@%
  18683.     MenuDoDone = TRUE%@NL@%
  18684. RETURN%@NL@%
  18685. %@NL@%
  18686. %@AB@%' ===========================================================================%@AE@%%@NL@%
  18687. %@AB@%' Handles state when Enter is pressed.  If on a valid item, return the%@AE@%%@NL@%
  18688. %@AB@%' proper (menu,item) pair and exit.  Else beep.  If on a valid menu%@AE@%%@NL@%
  18689. %@AB@%' this will open the menu by calling MenuDoDown%@AE@%%@NL@%
  18690. %@AB@%' ===========================================================================%@AE@%%@NL@%
  18691. %@NL@%
  18692. MenuDoEnter:%@NL@%
  18693.     IF currItem = 0 THEN%@NL@%
  18694.         IF GloTitle(currMenu).state = 0 THEN%@NL@%
  18695.             BEEP%@NL@%
  18696.         ELSE%@NL@%
  18697.             GOSUB menuDoDown%@NL@%
  18698.         END IF%@NL@%
  18699.     ELSE%@NL@%
  18700.         IF GloItem(currMenu, currItem).state <= 0 THEN%@NL@%
  18701.             BEEP%@NL@%
  18702.         ELSE%@NL@%
  18703.             GOSUB MenuDoHidePullDown%@NL@%
  18704.             GloMenu.currMenu = currMenu%@NL@%
  18705.             GloMenu.currItem = currItem%@NL@%
  18706.             MenuDoDone = TRUE%@NL@%
  18707.         END IF%@NL@%
  18708.     END IF%@NL@%
  18709. RETURN%@NL@%
  18710. %@NL@%
  18711. %@NL@%
  18712. %@AB@%' ===========================================================================%@AE@%%@NL@%
  18713. %@AB@%' If ALT pressed and released with nothing else happening in between, it%@AE@%%@NL@%
  18714. %@AB@%' will exit if no menu is open, or close the menu if one is open.%@AE@%%@NL@%
  18715. %@AB@%' ===========================================================================%@AE@%%@NL@%
  18716. %@NL@%
  18717. MenuDoAltReleased:%@NL@%
  18718.     IF pulldown THEN%@NL@%
  18719.         GOSUB MenuDoHidePullDown%@NL@%
  18720.         currItem = 0%@NL@%
  18721.         GOSUB MenuDoShowTitleAccessKeys%@NL@%
  18722.     ELSE%@NL@%
  18723.         GloMenu.currMenu = 0%@NL@%
  18724.         GloMenu.currItem = 0%@NL@%
  18725.         MenuDoDone = TRUE%@NL@%
  18726.     END IF%@NL@%
  18727. RETURN%@NL@%
  18728. %@NL@%
  18729. %@NL@%
  18730. %@AB@%' ===========================================================================%@AE@%%@NL@%
  18731. %@AB@%' If mouse is pressed while in keyboard mode, this routine assigns%@AE@%%@NL@%
  18732. %@AB@%' TRUE to MouseMode, resets the item, and hides the access keys%@AE@%%@NL@%
  18733. %@AB@%' ===========================================================================%@AE@%%@NL@%
  18734. %@NL@%
  18735. MenuDoMousePress:%@NL@%
  18736.     mouseMode = TRUE%@NL@%
  18737.     currItem = 0%@NL@%
  18738.     IF NOT pulldown THEN%@NL@%
  18739.         GOSUB MenuDoHideTitleAccessKeys%@NL@%
  18740.     END IF%@NL@%
  18741. RETURN%@NL@%
  18742. %@NL@%
  18743. %@NL@%
  18744. %@AB@%' ===========================================================================%@AE@%%@NL@%
  18745. %@AB@%' If a access key is pressed%@AE@%%@NL@%
  18746. %@AB@%' ===========================================================================%@AE@%%@NL@%
  18747. %@NL@%
  18748. MenuDoAccessKey:%@NL@%
  18749. %@NL@%
  18750. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  18751. %@AB@%    ' If an access key is pressed%@AE@%%@NL@%
  18752. %@AB@%    '   If no menu selected, search titles for matching access key, and open%@AE@%%@NL@%
  18753. %@AB@%    '      than menu.%@AE@%%@NL@%
  18754. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  18755. %@NL@%
  18756.     IF currItem = 0 THEN%@NL@%
  18757.         newMenu = (currMenu + MAXMENU - 2) MOD MAXMENU + 1%@NL@%
  18758.         loopEnd = (currMenu + MAXMENU - 2) MOD MAXMENU + 1%@NL@%
  18759.         DO%@NL@%
  18760.             newMenu = (newMenu) MOD MAXMENU + 1%@NL@%
  18761.         LOOP UNTIL (UCASE$(MID$(GloTitle(newMenu).text, GloTitle(newMenu).accessKey, 1)) = kbd$ AND GloTitle(newMenu).state = 1) OR newMenu = loopEnd%@NL@%
  18762. %@NL@%
  18763.         IF kbd$ = UCASE$(MID$(GloTitle(newMenu).text, GloTitle(newMenu).accessKey, 1)) THEN%@NL@%
  18764.             currMenu = newMenu%@NL@%
  18765.             GOSUB menuDoDown%@NL@%
  18766.         END IF%@NL@%
  18767.     ELSE%@NL@%
  18768. %@NL@%
  18769. %@AB@%        ' ===================================================================%@AE@%%@NL@%
  18770. %@AB@%        ' If menu is selected, search items for matching access key, and%@AE@%%@NL@%
  18771. %@AB@%        ' select that (menu,item) and exit MenuDo if item is enabled%@AE@%%@NL@%
  18772. %@AB@%        ' ===================================================================%@AE@%%@NL@%
  18773. %@NL@%
  18774.         newItem = (currItem + MAXITEM - 2) MOD MAXITEM + 1%@NL@%
  18775.         loopEnd = (currItem + MAXITEM - 2) MOD MAXITEM + 1%@NL@%
  18776.         DO%@NL@%
  18777.             newItem = (newItem) MOD MAXITEM + 1%@NL@%
  18778.         LOOP UNTIL (UCASE$(MID$(GloItem(currMenu, newItem).text, GloItem(currMenu, newItem).accessKey, 1)) = kbd$ AND GloItem(currMenu, newItem).state > 0 AND RTRIM$(GloItem(currMenu, newItem).text) <> "-") OR newItem = loopEnd%@NL@%
  18779. %@NL@%
  18780. %@NL@%
  18781.         IF kbd$ = UCASE$(MID$(GloItem(currMenu, newItem).text, GloItem(currMenu, newItem).accessKey, 1)) THEN%@NL@%
  18782.             currItem = newItem%@NL@%
  18783. %@NL@%
  18784.             IF GloItem(currMenu, currItem).state <= 0 THEN%@NL@%
  18785.                 BEEP%@NL@%
  18786.             ELSE%@NL@%
  18787.                 GOSUB MenuDoHidePullDown%@NL@%
  18788.                 GloMenu.currMenu = currMenu%@NL@%
  18789.                 GloMenu.currItem = currItem%@NL@%
  18790.                 MenuDoDone = TRUE%@NL@%
  18791.             END IF%@NL@%
  18792.         END IF%@NL@%
  18793.     END IF%@NL@%
  18794. RETURN%@NL@%
  18795. %@NL@%
  18796. %@AB@%' ===========================================================================%@AE@%%@NL@%
  18797. %@AB@%' Draws the menu -- only if menu is enabled.%@AE@%%@NL@%
  18798. %@AB@%' ===========================================================================%@AE@%%@NL@%
  18799. %@NL@%
  18800. menuDoShowPullDown:%@NL@%
  18801.     IF currMenu <> 0 AND GloTitle(currMenu).state = 1 THEN%@NL@%
  18802. %@NL@%
  18803. %@AB@%        ' ===================================================================%@AE@%%@NL@%
  18804. %@AB@%        ' Copies the background if this is the first time this particular%@AE@%%@NL@%
  18805. %@AB@%        ' menu is being drawn%@AE@%%@NL@%
  18806. %@AB@%        ' ===================================================================%@AE@%%@NL@%
  18807. %@NL@%
  18808.         MouseHide%@NL@%
  18809.         IF NOT copyFlag(currMenu) THEN%@NL@%
  18810.             IF GloTitle(currMenu).rColItem - GloTitle(currMenu).lColItem < LEN(GloTitle(currMenu).text) THEN%@NL@%
  18811.                 GloTitle(currMenu).rColItem = GloTitle(currMenu).lColItem + LEN(GloTitle(currMenu).text)%@NL@%
  18812.             END IF%@NL@%
  18813. %@NL@%
  18814.             GetBackground 1, GloTitle(currMenu).lColItem, GloTitle(currMenu).lowestRow, GloTitle(currMenu).rColItem + 2, buffer$(currMenu)%@NL@%
  18815.             copyFlag(currMenu) = TRUE%@NL@%
  18816.         END IF%@NL@%
  18817. %@NL@%
  18818. %@AB@%        ' ===================================================================%@AE@%%@NL@%
  18819. %@AB@%        ' Draw the menu, this is pretty straight forward%@AE@%%@NL@%
  18820. %@AB@%        ' ===================================================================%@AE@%%@NL@%
  18821.         pulldown = TRUE%@NL@%
  18822.         length = GloTitle(currMenu).itemLength%@NL@%
  18823.         IF length = 0 THEN length = 6%@NL@%
  18824.         lowestRow = 3%@NL@%
  18825.         col = GloTitle(currMenu).lColItem%@NL@%
  18826. %@NL@%
  18827.         COLOR GloMenu.cursorFore, GloMenu.cursorBack%@NL@%
  18828.         LOCATE 1, GloTitle(currMenu).lColTitle%@NL@%
  18829.         PRINT " "; RTRIM$(GloTitle(currMenu).text); " ";%@NL@%
  18830. %@NL@%
  18831.         COLOR GloMenu.fore, GloMenu.back%@NL@%
  18832.         LOCATE 2, col%@NL@%
  18833.         PRINT "┌"; STRING$(length + 2, "─"); "┐"%@NL@%
  18834. %@NL@%
  18835.         FOR item = 1 TO MAXITEM%@NL@%
  18836.             IF GloItem(currMenu, item).state >= 0 THEN%@NL@%
  18837.                 IF GloItem(currMenu, item).state = 2 THEN%@NL@%
  18838.                     chk$ = CHR$(175)%@NL@%
  18839.                 ELSE%@NL@%
  18840.                     chk$ = " "%@NL@%
  18841.                 END IF%@NL@%
  18842. %@NL@%
  18843.                 LOCATE GloItem(currMenu, item).row, col%@NL@%
  18844.                 COLOR GloMenu.fore, GloMenu.back%@NL@%
  18845. %@NL@%
  18846.                 IF RTRIM$(GloItem(currMenu, item).text) = "-" THEN%@NL@%
  18847.                     PRINT "├"; STRING$(length + 2, "─"); "┤"%@NL@%
  18848.                 ELSE%@NL@%
  18849.                     PRINT "│"; chk$;%@NL@%
  18850.                     IF GloItem(currMenu, item).state > 0 THEN%@NL@%
  18851.                         COLOR GloMenu.fore, GloMenu.back%@NL@%
  18852.                     ELSE%@NL@%
  18853.                         COLOR GloMenu.disabled, GloMenu.back%@NL@%
  18854.                     END IF%@NL@%
  18855.                     PRINT LEFT$(GloItem(currMenu, item).text + SPACE$(20), length);%@NL@%
  18856.                     COLOR GloMenu.fore, GloMenu.back%@NL@%
  18857.                     PRINT " │";%@NL@%
  18858. %@NL@%
  18859.                     IF GloItem(currMenu, item).state > 0 THEN%@NL@%
  18860.                         COLOR GloMenu.highlight, GloMenu.back%@NL@%
  18861.                         LOCATE GloItem(currMenu, item).row, col + GloItem(currMenu, item).accessKey + 1%@NL@%
  18862.                         PRINT MID$(GloItem(currMenu, item).text, GloItem(currMenu, item).accessKey, 1);%@NL@%
  18863.                     END IF%@NL@%
  18864.                 END IF%@NL@%
  18865.                 lowestRow = GloItem(currMenu, item).row + 1%@NL@%
  18866.             END IF%@NL@%
  18867.         NEXT item%@NL@%
  18868. %@NL@%
  18869.         COLOR GloMenu.fore, GloMenu.back%@NL@%
  18870.         LOCATE lowestRow, col%@NL@%
  18871.         PRINT "└"; STRING$(length + 2, "─"); "┘";%@NL@%
  18872. %@NL@%
  18873.         rCol = col + length + 5%@NL@%
  18874. %@NL@%
  18875.         AttrBox 3, rCol - 1, lowestRow, rCol, 8%@NL@%
  18876.         AttrBox lowestRow + 1, col + 2, lowestRow + 1, rCol, 8%@NL@%
  18877.     END IF%@NL@%
  18878. %@NL@%
  18879.     MouseShow%@NL@%
  18880. %@NL@%
  18881. RETURN%@NL@%
  18882. %@NL@%
  18883. %@AB@%' ===========================================================================%@AE@%%@NL@%
  18884. %@AB@%' Replace the background over the menu%@AE@%%@NL@%
  18885. %@AB@%' ===========================================================================%@AE@%%@NL@%
  18886. %@NL@%
  18887. MenuDoHidePullDown:%@NL@%
  18888.     IF pulldown THEN%@NL@%
  18889.         MouseHide%@NL@%
  18890. %@NL@%
  18891.         PutBackground 1, GloTitle(currMenu).lColItem, buffer$(currMenu)%@NL@%
  18892. %@NL@%
  18893.         MouseShow%@NL@%
  18894.         pulldown = FALSE%@NL@%
  18895.     END IF%@NL@%
  18896. RETURN%@NL@%
  18897. %@NL@%
  18898. END SUB%@NL@%
  18899. %@NL@%
  18900. SUB MenuEvent%@NL@%
  18901. %@NL@%
  18902. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  18903. %@AB@%    ' If ALT key is pressed, let MenuDo take over.  NOTE:  This will%@AE@%%@NL@%
  18904. %@AB@%    ' not call MenuDo if the ALT key has not been released at least%@AE@%%@NL@%
  18905. %@AB@%    ' once since the last time MenuDo was called.  This prevents the menu%@AE@%%@NL@%
  18906. %@AB@%    ' from flashing if the user simply holds down the ALT key.%@AE@%%@NL@%
  18907. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  18908. %@NL@%
  18909.     IF GetShiftState(3) THEN%@NL@%
  18910.         IF GloMenu.altKeyReset THEN%@NL@%
  18911.             MenuDo%@NL@%
  18912.             GloMenu.altKeyReset = FALSE%@NL@%
  18913.         END IF%@NL@%
  18914.     ELSE%@NL@%
  18915.         GloMenu.altKeyReset = TRUE%@NL@%
  18916.     END IF%@NL@%
  18917. %@NL@%
  18918. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  18919. %@AB@%    ' Call MenuDo if the mouse button is down, and the cursor is on the top row%@AE@%%@NL@%
  18920. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  18921. %@NL@%
  18922.     MousePoll mouseRow, mouseCol, lButton, rButton%@NL@%
  18923.     IF mouseRow = 1 AND lButton THEN%@NL@%
  18924.         MenuDo%@NL@%
  18925.     END IF%@NL@%
  18926. %@NL@%
  18927. END SUB%@NL@%
  18928. %@NL@%
  18929. SUB MenuInit%@NL@%
  18930. %@NL@%
  18931. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  18932. %@AB@%    '  Initialize global menu arrays%@AE@%%@NL@%
  18933. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  18934. %@NL@%
  18935.     FOR menu = 1 TO MAXMENU%@NL@%
  18936.         GloTitle(menu).text = ""%@NL@%
  18937.         GloTitle(menu).state = -1            'state of -1 means "empty"%@NL@%
  18938.         GloTitle(menu).rColItem = 0           'These get set in MenuShow%@NL@%
  18939.         GloTitle(menu).lColItem = 0           ' |%@NL@%
  18940.         GloTitle(menu).rColTitle = 0          ' |%@NL@%
  18941.         GloTitle(menu).lColTitle = 0          ' |%@NL@%
  18942.         GloTitle(menu).itemLength = 0         ' |%@NL@%
  18943.         GloTitle(menu).accessKey = 1            'Initial AccessKey of 1%@NL@%
  18944. %@NL@%
  18945.         FOR item = 1 TO MAXITEM%@NL@%
  18946.             GloItem(menu, item).text = ""%@NL@%
  18947.             GloItem(menu, item).state = -1      'state of -1 means "empty"%@NL@%
  18948.             GloItem(menu, item).index = 0       'These get set in MenuShow%@NL@%
  18949.             GloItem(menu, item).row = 0         '  |%@NL@%
  18950.             GloItem(menu, item).accessKey = 1   'Initial AccessKey of 1%@NL@%
  18951.         NEXT item%@NL@%
  18952.     NEXT menu%@NL@%
  18953. %@NL@%
  18954. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  18955. %@AB@%    ' Initialize mouse%@AE@%%@NL@%
  18956. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  18957. %@NL@%
  18958.     MouseInit%@NL@%
  18959. %@NL@%
  18960. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  18961. %@AB@%    ' Set initial state of ALT key to "reset"%@AE@%%@NL@%
  18962. %@AB@%    ' Clear out shortcut key index%@AE@%%@NL@%
  18963. %@AB@%    ' Set initial state of menu to ON%@AE@%%@NL@%
  18964. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  18965. %@NL@%
  18966.     GloMenu.altKeyReset = TRUE%@NL@%
  18967.     GloMenu.shortcutKeyIndex = STRING$(100, 0)%@NL@%
  18968.     GloMenu.MenuOn = TRUE%@NL@%
  18969. %@NL@%
  18970.     GloMenu.fore = 0%@NL@%
  18971.     GloMenu.back = 7%@NL@%
  18972.     GloMenu.highlight = 15%@NL@%
  18973.     GloMenu.disabled = 8%@NL@%
  18974.     GloMenu.cursorFore = 7%@NL@%
  18975.     GloMenu.cursorBack = 0%@NL@%
  18976.     GloMenu.cursorHi = 15%@NL@%
  18977. %@NL@%
  18978. END SUB%@NL@%
  18979. %@NL@%
  18980. FUNCTION MenuInkey$ STATIC%@NL@%
  18981. %@NL@%
  18982. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  18983. %@AB@%    ' Scan keyboard, return KBD$ by default -- unless it is over written below%@AE@%%@NL@%
  18984. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  18985. %@NL@%
  18986.     kbd$ = INKEY$%@NL@%
  18987.     MenuInkey$ = kbd$%@NL@%
  18988. %@NL@%
  18989. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  18990. %@AB@%    ' Check if KBD$ matches a shortcut key.  If it does, return "menu" instead%@AE@%%@NL@%
  18991. %@AB@%    ' of the key that was pressed%@AE@%%@NL@%
  18992. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  18993. %@NL@%
  18994.     ShortCutKeyEvent kbd$%@NL@%
  18995.     IF MenuCheck(2) THEN%@NL@%
  18996.         MenuInkey$ = "menu"%@NL@%
  18997.     ELSE%@NL@%
  18998. %@NL@%
  18999. %@AB@%        ' ===================================================================%@AE@%%@NL@%
  19000. %@AB@%        ' Call menu event, which looks at mouse, and state of ALT key%@AE@%%@NL@%
  19001. %@AB@%        ' If a menu item is selected, return "menu" instead of KBD$%@AE@%%@NL@%
  19002. %@AB@%        ' ===================================================================%@AE@%%@NL@%
  19003. %@NL@%
  19004.         MenuEvent%@NL@%
  19005.         IF MenuCheck(2) THEN%@NL@%
  19006.             MenuInkey$ = "menu"%@NL@%
  19007.         END IF%@NL@%
  19008.     END IF%@NL@%
  19009. %@NL@%
  19010. END FUNCTION%@NL@%
  19011. %@NL@%
  19012. SUB MenuItemToggle (menu, item)%@NL@%
  19013. %@NL@%
  19014.     IF item >= 0 AND menu >= 1 AND item <= MAXITEM AND menu <= MAXMENU THEN%@NL@%
  19015. %@NL@%
  19016.         IF item = 0 OR GloItem(menu, item).state < 1 OR GloItem(menu, item).state > 2 THEN%@NL@%
  19017.             SOUND 2000, 40%@NL@%
  19018.         ELSE%@NL@%
  19019.             GloItem(menu, item).state = 3 - GloItem(menu, item).state%@NL@%
  19020.         END IF%@NL@%
  19021. %@NL@%
  19022.     END IF%@NL@%
  19023. END SUB%@NL@%
  19024. %@NL@%
  19025. DEFSNG A-Z%@NL@%
  19026. SUB MenuOff%@NL@%
  19027. %@NL@%
  19028. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  19029. %@AB@%    ' Simply assigns FALSE to the proper global variable%@AE@%%@NL@%
  19030. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  19031. %@NL@%
  19032.     GloMenu.MenuOn = FALSE%@NL@%
  19033. %@NL@%
  19034. END SUB%@NL@%
  19035. %@NL@%
  19036. DEFINT A-Z%@NL@%
  19037. SUB MenuOn%@NL@%
  19038. %@NL@%
  19039. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  19040. %@AB@%    ' Simply assigns TRUE to the proper global variable%@AE@%%@NL@%
  19041. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  19042. %@NL@%
  19043.     GloMenu.MenuOn = TRUE%@NL@%
  19044. %@NL@%
  19045. END SUB%@NL@%
  19046. %@NL@%
  19047. SUB MenuPreProcess STATIC%@NL@%
  19048. %@NL@%
  19049.     currCol = 2     'Represents the col where first menu title is located%@NL@%
  19050. %@NL@%
  19051. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  19052. %@AB@%    ' Menu index is a fast way of decoding which menu the mouse cursor%@AE@%%@NL@%
  19053. %@AB@%    ' is pointing to based on the col of the cursor.  See MENU.BI for details.%@AE@%%@NL@%
  19054. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  19055. %@NL@%
  19056.     GloMenu.menuIndex = STRING$(160, 0)%@NL@%
  19057. %@NL@%
  19058. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  19059. %@AB@%    ' Process each menu, one at a time%@AE@%%@NL@%
  19060. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  19061. %@NL@%
  19062.     FOR menu = 1 TO MAXMENU%@NL@%
  19063. %@NL@%
  19064. %@AB@%        ' ===================================================================%@AE@%%@NL@%
  19065. %@AB@%        ' If state is empty, or text is "" then clear out data for that menu%@AE@%%@NL@%
  19066. %@AB@%        ' ===================================================================%@AE@%%@NL@%
  19067. %@NL@%
  19068.         IF GloTitle(menu).state < 0 OR LEN(RTRIM$(GloTitle(menu).text)) = 0 THEN%@NL@%
  19069.             GloTitle(menu).rColItem = 0%@NL@%
  19070.             GloTitle(menu).lColItem = 0%@NL@%
  19071.             GloTitle(menu).rColTitle = 0%@NL@%
  19072.             GloTitle(menu).lColTitle = 0%@NL@%
  19073.             GloTitle(menu).itemLength = 0%@NL@%
  19074.             GloTitle(menu).state = -1%@NL@%
  19075.        ELSE%@NL@%
  19076. %@AB@%            ' ===============================================================%@AE@%%@NL@%
  19077. %@AB@%            ' else, assign data about the column location to the global storage%@AE@%%@NL@%
  19078. %@AB@%            ' ===============================================================%@AE@%%@NL@%
  19079. %@NL@%
  19080.             GloTitle(menu).lColTitle = currCol%@NL@%
  19081.             GloTitle(menu).rColTitle = currCol + LEN(RTRIM$(GloTitle(menu).text)) + 1%@NL@%
  19082.             GloTitle(menu).lColItem = currCol - 1%@NL@%
  19083. %@NL@%
  19084.             IF GloTitle(menu).rColTitle > MAXCOL THEN%@NL@%
  19085.                 BEEP: CLS : PRINT "Menu bar longer than screen!  Cannot function!"%@NL@%
  19086.                 END%@NL@%
  19087.             END IF%@NL@%
  19088. %@NL@%
  19089. %@AB@%            ' ===============================================================%@AE@%%@NL@%
  19090. %@AB@%            ' Update the index about where the menu is located, increment%@AE@%%@NL@%
  19091. %@AB@%            ' currCol%@AE@%%@NL@%
  19092. %@AB@%            ' ===============================================================%@AE@%%@NL@%
  19093. %@NL@%
  19094.             FOR index = currCol TO currCol + LEN(RTRIM$(GloTitle(menu).text)) + 1%@NL@%
  19095.                 MID$(GloMenu.menuIndex, index * 2 - 1, 2) = MKI$(menu)%@NL@%
  19096.             NEXT index%@NL@%
  19097. %@NL@%
  19098.             currCol = currCol + LEN(RTRIM$(GloTitle(menu).text)) + 2%@NL@%
  19099. %@NL@%
  19100. %@AB@%            ' ===============================================================%@AE@%%@NL@%
  19101. %@AB@%            ' Process the items in the menu, computing the%@AE@%%@NL@%
  19102. %@AB@%            ' longest item, and preparing the row index%@AE@%%@NL@%
  19103. %@AB@%            ' ===============================================================%@AE@%%@NL@%
  19104. %@NL@%
  19105.             GloTitle(menu).itemLength = 0%@NL@%
  19106.             currRow = 3%@NL@%
  19107.             iFlag = FALSE%@NL@%
  19108. %@NL@%
  19109.             FOR item = 1 TO MAXITEM%@NL@%
  19110.                 GloItem(menu, currRow - 2).index = 0%@NL@%
  19111.                 IF GloItem(menu, item).state >= 0 THEN%@NL@%
  19112.                     GloItem(menu, currRow - 2).index = item%@NL@%
  19113.                     GloItem(menu, item).row = currRow%@NL@%
  19114.                     currRow = currRow + 1%@NL@%
  19115.                     IF LEN(RTRIM$(GloItem(menu, item).text)) > GloTitle(menu).itemLength THEN%@NL@%
  19116.                         GloTitle(menu).itemLength = LEN(RTRIM$(GloItem(menu, item).text))%@NL@%
  19117.                     END IF%@NL@%
  19118.                     iFlag = TRUE%@NL@%
  19119.                 END IF%@NL@%
  19120.             NEXT item%@NL@%
  19121. %@NL@%
  19122. %@AB@%            ' ===============================================================%@AE@%%@NL@%
  19123. %@AB@%            ' If all items were empty, disable the menu itself%@AE@%%@NL@%
  19124. %@AB@%            ' else, assign the longest length to the proper variable%@AE@%%@NL@%
  19125. %@AB@%            ' ===============================================================%@AE@%%@NL@%
  19126. %@NL@%
  19127.             IF NOT iFlag THEN%@NL@%
  19128.                 GloTitle(menu).state = 0%@NL@%
  19129.             ELSE%@NL@%
  19130.                 GloTitle(menu).rColItem = GloTitle(menu).lColItem + GloTitle(menu).itemLength + 3%@NL@%
  19131.                 IF GloTitle(menu).rColItem > MAXCOL - 2 THEN%@NL@%
  19132.                    diff = GloTitle(menu).rColItem - (MAXCOL - 2)%@NL@%
  19133.                    GloTitle(menu).rColItem = GloTitle(menu).rColItem - diff%@NL@%
  19134.                    GloTitle(menu).lColItem = GloTitle(menu).lColItem - diff%@NL@%
  19135.                 END IF%@NL@%
  19136.             END IF%@NL@%
  19137. %@NL@%
  19138.         END IF%@NL@%
  19139. %@NL@%
  19140.         GloTitle(menu).lowestRow = currRow + 1%@NL@%
  19141.     NEXT menu%@NL@%
  19142. %@NL@%
  19143. END SUB%@NL@%
  19144. %@NL@%
  19145. SUB MenuSet (menu, item, state, text$, accessKey) STATIC%@NL@%
  19146. %@NL@%
  19147.     IF accessKey > LEN(text$) THEN accessKey = LEN(text$)%@NL@%
  19148. %@NL@%
  19149.     IF item >= 0 AND menu >= 1 AND item <= MAXITEM AND menu <= MAXMENU THEN%@NL@%
  19150. %@NL@%
  19151. %@AB@%        ' ===================================================================%@AE@%%@NL@%
  19152. %@AB@%        ' Assign parameters to proper global menu variables%@AE@%%@NL@%
  19153. %@AB@%        ' ===================================================================%@AE@%%@NL@%
  19154. %@NL@%
  19155.         IF item = 0 THEN%@NL@%
  19156.             IF state < -1 OR state > 1 THEN%@NL@%
  19157.                 SOUND 3000, 40%@NL@%
  19158.             ELSE%@NL@%
  19159.                 GloTitle(menu).text = text$%@NL@%
  19160.                 GloTitle(menu).state = state%@NL@%
  19161.                 GloTitle(menu).accessKey = accessKey%@NL@%
  19162.             END IF%@NL@%
  19163.         ELSE%@NL@%
  19164.             IF state < -1 OR state > 2 THEN%@NL@%
  19165.                 SOUND 4000, 40%@NL@%
  19166.             ELSE%@NL@%
  19167.                 GloItem(menu, item).text = text$%@NL@%
  19168.                 GloItem(menu, item).state = state%@NL@%
  19169.                 GloItem(menu, item).accessKey = accessKey%@NL@%
  19170.             END IF%@NL@%
  19171.         END IF%@NL@%
  19172.     END IF%@NL@%
  19173. %@NL@%
  19174. END SUB%@NL@%
  19175. %@NL@%
  19176. SUB MenuSetState (menu, item, state) STATIC%@NL@%
  19177. %@NL@%
  19178. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  19179. %@AB@%    ' Assign parameters to proper global menu variables%@AE@%%@NL@%
  19180. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  19181. %@NL@%
  19182.     IF item = 0 THEN%@NL@%
  19183.         IF state < 0 OR state > 1 OR GloTitle(menu).state < 0 THEN%@NL@%
  19184.             SOUND 5000, 40%@NL@%
  19185.         ELSE%@NL@%
  19186.             GloTitle(menu).state = state%@NL@%
  19187.         END IF%@NL@%
  19188.     ELSE%@NL@%
  19189.         IF state < 0 OR state > 2 OR GloItem(menu, item).state < 0 THEN%@NL@%
  19190.             SOUND 6000, 40%@NL@%
  19191.         ELSE%@NL@%
  19192.             GloItem(menu, item).state = state%@NL@%
  19193.         END IF%@NL@%
  19194.     END IF%@NL@%
  19195. %@NL@%
  19196. END SUB%@NL@%
  19197. %@NL@%
  19198. DEFSNG A-Z%@NL@%
  19199. SUB MenuShow%@NL@%
  19200. %@NL@%
  19201. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  19202. %@AB@%    ' This section actually prints the menu on the screen%@AE@%%@NL@%
  19203. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  19204. %@NL@%
  19205.     COLOR GloMenu.fore, GloMenu.back%@NL@%
  19206.     LOCATE 1, 1%@NL@%
  19207.     PRINT SPACE$(MAXCOL);%@NL@%
  19208. %@NL@%
  19209.     FOR menu = 1 TO MAXMENU%@NL@%
  19210.         SELECT CASE GloTitle(menu).state%@NL@%
  19211.             CASE 0:%@NL@%
  19212.                 COLOR GloMenu.disabled, GloMenu.back%@NL@%
  19213.                 LOCATE 1, GloTitle(menu).lColTitle + 1%@NL@%
  19214.                 PRINT RTRIM$(GloTitle(menu).text$);%@NL@%
  19215.             CASE 1:%@NL@%
  19216.                 COLOR GloMenu.fore, GloMenu.back%@NL@%
  19217.                 LOCATE 1, GloTitle(menu).lColTitle + 1%@NL@%
  19218.                 PRINT RTRIM$(GloTitle(menu).text$);%@NL@%
  19219.             CASE ELSE%@NL@%
  19220.         END SELECT%@NL@%
  19221. %@NL@%
  19222.     NEXT menu%@NL@%
  19223. %@NL@%
  19224. END SUB%@NL@%
  19225. %@NL@%
  19226. DEFINT A-Z%@NL@%
  19227. SUB ShortCutKeyDelete (menu, item) STATIC%@NL@%
  19228. %@NL@%
  19229. %@AB@%    '=======================================================================%@AE@%%@NL@%
  19230. %@AB@%    ' Search through shortcut key index until the menu,item pair is found%@AE@%%@NL@%
  19231. %@AB@%    ' or the end of the list is reached.%@AE@%%@NL@%
  19232. %@AB@%    '=======================================================================%@AE@%%@NL@%
  19233. %@NL@%
  19234.     ptr = -1%@NL@%
  19235.     DO%@NL@%
  19236.         ptr = ptr + 1%@NL@%
  19237.         temp = CVI(MID$(GloMenu.shortcutKeyIndex, ptr * 4 + 1, 2))%@NL@%
  19238.         testMenu = INT(temp / 256)%@NL@%
  19239.         testItem = INT(temp MOD 256)%@NL@%
  19240.     LOOP UNTIL (menu = testMenu AND item = testItem) OR testMenu = 0 AND testItem = 0 OR ptr = 25%@NL@%
  19241. %@NL@%
  19242. %@AB@%    '=======================================================================%@AE@%%@NL@%
  19243. %@AB@%    ' If a match is found, delete the shortcut key by squeezing out the four%@AE@%%@NL@%
  19244. %@AB@%    ' bytes that represents the shortcut key, and adding four chr$(0) at the%@AE@%%@NL@%
  19245. %@AB@%    ' end.%@AE@%%@NL@%
  19246. %@AB@%    '=======================================================================%@AE@%%@NL@%
  19247. %@NL@%
  19248.     IF menu = testMenu AND item = testItem THEN%@NL@%
  19249.         GloMenu.shortcutKeyIndex = LEFT$(GloMenu.shortcutKeyIndex, ptr * 4) + RIGHT$(GloMenu.shortcutKeyIndex, 96 - ptr * 4) + STRING$(4, 0)%@NL@%
  19250.     END IF%@NL@%
  19251. %@NL@%
  19252. END SUB%@NL@%
  19253. %@NL@%
  19254. SUB ShortCutKeyEvent (theKey$)%@NL@%
  19255. %@NL@%
  19256. %@AB@%    '=======================================================================%@AE@%%@NL@%
  19257. %@AB@%    ' If menu event trapping turned off, return immediately%@AE@%%@NL@%
  19258. %@AB@%    '=======================================================================%@AE@%%@NL@%
  19259. %@NL@%
  19260.     IF NOT GloMenu.MenuOn THEN%@NL@%
  19261.         EXIT SUB%@NL@%
  19262.     END IF%@NL@%
  19263. %@NL@%
  19264. %@AB@%    '=======================================================================%@AE@%%@NL@%
  19265. %@AB@%    ' Make sure the length of theKey$ is two bytes by adding a chr$(0) if%@AE@%%@NL@%
  19266. %@AB@%    ' necessary.  If the length is > 2, make it null.%@AE@%%@NL@%
  19267. %@AB@%    '=======================================================================%@AE@%%@NL@%
  19268. %@NL@%
  19269.     SELECT CASE LEN(theKey$)%@NL@%
  19270.         CASE 1%@NL@%
  19271.             theKey$ = theKey$ + CHR$(0)%@NL@%
  19272.         CASE 2%@NL@%
  19273.         CASE ELSE%@NL@%
  19274.             theKey$ = ""%@NL@%
  19275.     END SELECT%@NL@%
  19276. %@NL@%
  19277. %@AB@%    '=======================================================================%@AE@%%@NL@%
  19278. %@AB@%    ' Search the shortcut key list for a match -- only if theKey$ is valid.%@AE@%%@NL@%
  19279. %@AB@%    '=======================================================================%@AE@%%@NL@%
  19280. %@NL@%
  19281.     IF theKey$ <> "" THEN%@NL@%
  19282. %@NL@%
  19283.         ptr = -1%@NL@%
  19284.         DO%@NL@%
  19285.             ptr = ptr + 1%@NL@%
  19286.             testKey$ = MID$(GloMenu.shortcutKeyIndex, ptr * 4 + 3, 2)%@NL@%
  19287. %@NL@%
  19288.         LOOP UNTIL theKey$ = testKey$ OR testKey$ = STRING$(2, 0) OR ptr = 25%@NL@%
  19289. %@NL@%
  19290. %@AB@%        '===================================================================%@AE@%%@NL@%
  19291. %@AB@%        ' If match is found, make sure menu choice is valid (state > 0)%@AE@%%@NL@%
  19292. %@AB@%        ' If so, assign the proper global variables.%@AE@%%@NL@%
  19293. %@AB@%        '===================================================================%@AE@%%@NL@%
  19294. %@NL@%
  19295.     IF theKey$ = testKey$ THEN%@NL@%
  19296.             temp = CVI(MID$(GloMenu.shortcutKeyIndex, ptr * 4 + 1, 2))%@NL@%
  19297.             tempMenu = INT(temp / 256)%@NL@%
  19298.             tempItem = INT(temp MOD 256)%@NL@%
  19299. %@NL@%
  19300.             IF GloItem(tempMenu, tempItem).state > 0 THEN%@NL@%
  19301.                 GloMenu.currMenu = tempMenu%@NL@%
  19302.                 GloMenu.currItem = tempItem%@NL@%
  19303.             END IF%@NL@%
  19304.         END IF%@NL@%
  19305.     END IF%@NL@%
  19306. %@NL@%
  19307. END SUB%@NL@%
  19308. %@NL@%
  19309. SUB ShortCutKeySet (menu, item, shortcutKey$)%@NL@%
  19310. %@NL@%
  19311. %@AB@%    '=======================================================================%@AE@%%@NL@%
  19312. %@AB@%    ' Make sure the length of theKey$ is two bytes by adding a chr$(0) if%@AE@%%@NL@%
  19313. %@AB@%    ' necessary.  If the length is >2, make it null.%@AE@%%@NL@%
  19314. %@AB@%    '=======================================================================%@AE@%%@NL@%
  19315. %@NL@%
  19316.     SELECT CASE LEN(shortcutKey$)%@NL@%
  19317.         CASE 1%@NL@%
  19318.             shortcutKey$ = shortcutKey$ + CHR$(0)%@NL@%
  19319.         CASE 2%@NL@%
  19320.         CASE ELSE%@NL@%
  19321.             shortcutKey$ = ""%@NL@%
  19322.     END SELECT%@NL@%
  19323. %@NL@%
  19324. %@AB@%    '=======================================================================%@AE@%%@NL@%
  19325. %@AB@%    ' First delete the shortcut key, just in case it already exists, and then%@AE@%%@NL@%
  19326. %@AB@%    ' and the shortcut key to the front of the shortcut key index string.%@AE@%%@NL@%
  19327. %@AB@%    '=======================================================================%@AE@%%@NL@%
  19328. %@NL@%
  19329.     ShortCutKeyDelete menu, item%@NL@%
  19330.     IF shortcutKey$ <> "" THEN%@NL@%
  19331.         newKey$ = MKI$(menu * 256 + item) + shortcutKey$%@NL@%
  19332.         GloMenu.shortcutKeyIndex = newKey$ + LEFT$(GloMenu.shortcutKeyIndex, 396)%@NL@%
  19333.     END IF%@NL@%
  19334. %@NL@%
  19335. END SUB%@NL@%
  19336. %@NL@%
  19337. %@NL@%
  19338. %@NL@%
  19339. %@2@%%@AH@%MOUSE.BAS%@AE@%%@EH@%%@NL@%
  19340. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\MOUSE.BAS%@AE@%%@NL@%
  19341. %@NL@%
  19342. %@AB@%'============================================================================%@AE@%%@NL@%
  19343. %@AB@%'%@AE@%%@NL@%
  19344. %@AB@%'    MOUSE.BAS - Mouse Support Routines for the User Interface Toolbox in%@AE@%%@NL@%
  19345. %@AB@%'           Microsoft BASIC 7.0, Professional Development System%@AE@%%@NL@%
  19346. %@AB@%'              Copyright (C) 1987-1989, Microsoft Corporation%@AE@%%@NL@%
  19347. %@AB@%'%@AE@%%@NL@%
  19348. %@AB@%' NOTE:     This sample source code toolbox is intended to demonstrate some%@AE@%%@NL@%
  19349. %@AB@%'           of the extended capabilities of Microsoft BASIC 7.0 Professional%@AE@%%@NL@%
  19350. %@AB@%'           Development system that can help to leverage the professional%@AE@%%@NL@%
  19351. %@AB@%'           developer's time more effectively.  While you are free to use,%@AE@%%@NL@%
  19352. %@AB@%'           modify, or distribute the routines in this module in any way you%@AE@%%@NL@%
  19353. %@AB@%'           find useful, it should be noted that these are examples only and%@AE@%%@NL@%
  19354. %@AB@%'           should not be relied upon as a fully-tested "add-on" library.%@AE@%%@NL@%
  19355. %@AB@%'%@AE@%%@NL@%
  19356. %@AB@%'  PURPOSE: These routines are required for mouse support in the user%@AE@%%@NL@%
  19357. %@AB@%'           interface toolbox, but they may be used independently as well.%@AE@%%@NL@%
  19358. %@AB@%'%@AE@%%@NL@%
  19359. %@AB@%'  For information on creating a library and QuickLib from the routines%@AE@%%@NL@%
  19360. %@AB@%'  contained in this file, read the comment header of GENERAL.BAS.%@AE@%%@NL@%
  19361. %@AB@%'%@AE@%%@NL@%
  19362. %@AB@%'============================================================================%@AE@%%@NL@%
  19363. %@NL@%
  19364. DEFINT A-Z%@NL@%
  19365. %@NL@%
  19366. %@AB@%'$INCLUDE: 'general.bi'%@AE@%%@NL@%
  19367. %@AB@%'$INCLUDE: 'mouse.bi'%@AE@%%@NL@%
  19368. %@AB@%'$INCLUDE: 'menu.bi'%@AE@%%@NL@%
  19369. %@NL@%
  19370. COMMON SHARED /uitools/ GloMenu      AS MenuMiscType%@NL@%
  19371. COMMON SHARED /uitools/ GloTitle()   AS MenuTitleType%@NL@%
  19372. COMMON SHARED /uitools/ GloItem()    AS MenuItemType%@NL@%
  19373. %@NL@%
  19374. SUB MouseBorder (row1, col1, row2, col2) STATIC%@NL@%
  19375. %@NL@%
  19376. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  19377. %@AB@%    ' Sets max and min bounds on mouse movement both vertically, and%@AE@%%@NL@%
  19378. %@AB@%    ' horizontally%@AE@%%@NL@%
  19379. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  19380. %@NL@%
  19381.     MouseDriver 7, 0, (col1 - 1) * 8, (col2 - 1) * 8%@NL@%
  19382.     MouseDriver 8, 0, (row1 - 1) * 8, (row2 - 1) * 8%@NL@%
  19383. %@NL@%
  19384. END SUB%@NL@%
  19385. %@NL@%
  19386. SUB MouseDriver (m0, m1, m2, m3) STATIC%@NL@%
  19387. %@NL@%
  19388.     DIM regs AS RegType%@NL@%
  19389. %@NL@%
  19390.     IF MouseChecked = FALSE THEN%@NL@%
  19391.         DEF SEG = 0%@NL@%
  19392. %@NL@%
  19393.         MouseSegment& = 256& * PEEK(207) + PEEK(206)%@NL@%
  19394.         MouseOffset& = 256& * PEEK(205) + PEEK(204)%@NL@%
  19395. %@NL@%
  19396.         DEF SEG = MouseSegment&%@NL@%
  19397. %@NL@%
  19398.         IF (MouseSegment& = 0 AND MouseOffset& = 0) OR PEEK(MouseOffset&) = 207 THEN%@NL@%
  19399.             MousePresent = FALSE%@NL@%
  19400.             MouseChecked = TRUE%@NL@%
  19401.             DEF SEG%@NL@%
  19402.         END IF%@NL@%
  19403.     END IF%@NL@%
  19404. %@NL@%
  19405.     IF MousePresent = FALSE AND MouseChecked = TRUE THEN%@NL@%
  19406.         EXIT SUB%@NL@%
  19407.     END IF%@NL@%
  19408. %@NL@%
  19409. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  19410. %@AB@%    ' Calls interrupt 51 to invoke mouse functions in the MS Mouse Driver.%@AE@%%@NL@%
  19411. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  19412. %@NL@%
  19413.     regs.ax = m0%@NL@%
  19414.     regs.bx = m1%@NL@%
  19415.     regs.cx = m2%@NL@%
  19416.     regs.dx = m3%@NL@%
  19417. %@NL@%
  19418.     Interrupt 51, regs, regs%@NL@%
  19419. %@NL@%
  19420.     m0 = regs.ax%@NL@%
  19421.     m1 = regs.bx%@NL@%
  19422.     m2 = regs.cx%@NL@%
  19423.     m3 = regs.dx%@NL@%
  19424. %@NL@%
  19425.     IF MouseChecked THEN EXIT SUB%@NL@%
  19426. %@NL@%
  19427. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  19428. %@AB@%    ' Check for successful mouse initialization%@AE@%%@NL@%
  19429. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  19430. %@NL@%
  19431.     IF m0 AND NOT MouseChecked THEN%@NL@%
  19432.         MousePresent = TRUE%@NL@%
  19433.     END IF%@NL@%
  19434. %@NL@%
  19435.     MouseChecked = TRUE%@NL@%
  19436. %@NL@%
  19437. END SUB%@NL@%
  19438. %@NL@%
  19439. SUB MouseHide%@NL@%
  19440. %@NL@%
  19441. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  19442. %@AB@%    ' Decrements internal cursor flag%@AE@%%@NL@%
  19443. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  19444. %@NL@%
  19445.    MouseDriver 2, 0, 0, 0%@NL@%
  19446. %@NL@%
  19447. END SUB%@NL@%
  19448. %@NL@%
  19449. SUB MouseInit%@NL@%
  19450. %@NL@%
  19451. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  19452. %@AB@%    ' Mouse driver's initialization routine%@AE@%%@NL@%
  19453. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  19454. %@NL@%
  19455.     MouseDriver 0, 0, 0, 0%@NL@%
  19456. %@NL@%
  19457. END SUB%@NL@%
  19458. %@NL@%
  19459. SUB MousePoll (row, col, lButton, rButton) STATIC%@NL@%
  19460. %@NL@%
  19461. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  19462. %@AB@%    ' Polls mouse driver, then sets parms correctly%@AE@%%@NL@%
  19463. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  19464. %@NL@%
  19465.     MouseDriver 3, button, col, row%@NL@%
  19466.     row = row / 8 + 1%@NL@%
  19467.     col = col / 8 + 1%@NL@%
  19468. %@NL@%
  19469.     IF button AND 1 THEN%@NL@%
  19470.         lButton = TRUE%@NL@%
  19471.     ELSE%@NL@%
  19472.         lButton = FALSE%@NL@%
  19473.     END IF%@NL@%
  19474. %@NL@%
  19475.     IF button AND 2 THEN%@NL@%
  19476.         rButton = TRUE%@NL@%
  19477.     ELSE%@NL@%
  19478.         rButton = FALSE%@NL@%
  19479.     END IF%@NL@%
  19480. %@NL@%
  19481. END SUB%@NL@%
  19482. %@NL@%
  19483. SUB MouseShow%@NL@%
  19484. %@NL@%
  19485. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  19486. %@AB@%    ' Increments mouse's internal cursor flag%@AE@%%@NL@%
  19487. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  19488. %@NL@%
  19489.     MouseDriver 1, 0, 0, 0%@NL@%
  19490. %@NL@%
  19491. END SUB%@NL@%
  19492. %@NL@%
  19493. %@NL@%
  19494. %@NL@%
  19495. %@2@%%@AH@%MUSIC.BAS%@AE@%%@EH@%%@NL@%
  19496. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\MUSIC.BAS%@AE@%%@NL@%
  19497. %@NL@%
  19498. %@AB@%' Turn on trapping of background music events:%@AE@%%@NL@%
  19499. PLAY ON%@NL@%
  19500. %@NL@%
  19501. %@AB@%' Branch to the Refresh subroutine when there are fewer than%@AE@%%@NL@%
  19502. %@AB@%' two notes in the background music buffer:%@AE@%%@NL@%
  19503. ON PLAY(2) GOSUB Refresh%@NL@%
  19504. %@NL@%
  19505. PRINT "Press any key to start, q to end."%@NL@%
  19506. Pause$ = INPUT$(1)%@NL@%
  19507. %@NL@%
  19508. %@AB@%' Select the background music option for PLAY:%@AE@%%@NL@%
  19509. PLAY "MB"%@NL@%
  19510. %@NL@%
  19511. %@AB@%' Start playing the music, so notes will be put in the%@AE@%%@NL@%
  19512. %@AB@%' background music buffer:%@AE@%%@NL@%
  19513. GOSUB Refresh%@NL@%
  19514. %@NL@%
  19515. I = 0%@NL@%
  19516. %@NL@%
  19517. DO%@NL@%
  19518. %@NL@%
  19519. %@AB@%        ' Print the numbers from 0 to 10,000 over and over until%@AE@%%@NL@%
  19520. %@AB@%        ' the user presses the "q" key. While this is happening,%@AE@%%@NL@%
  19521. %@AB@%        ' the music will repeat in the background:%@AE@%%@NL@%
  19522.         PRINT I%@NL@%
  19523.         I = (I + 1) MOD 10001%@NL@%
  19524. LOOP UNTIL INKEY$ = "q"%@NL@%
  19525. %@NL@%
  19526. END%@NL@%
  19527. %@NL@%
  19528. Refresh:%@NL@%
  19529. %@NL@%
  19530. %@AB@%        ' Plays the opening motive of%@AE@%%@NL@%
  19531. %@AB@%        ' Beethoven's Fifth Symphony:%@AE@%%@NL@%
  19532.         Listen$ = "t180 o2 p2 p8 L8 GGG L2 E-"%@NL@%
  19533.         Fate$   = "p24 p8 L8 FFF L2 D"%@NL@%
  19534.         PLAY Listen$ + Fate$%@NL@%
  19535.         RETURN%@NL@%
  19536. %@NL@%
  19537. %@NL@%
  19538. %@NL@%
  19539. %@2@%%@AH@%MXADSTA.ASM%@AE@%%@EH@%%@NL@%
  19540. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\MXADSTA.ASM%@AE@%%@NL@%
  19541. %@NL@%
  19542. %@AB@%;***************************** ADDSTRING ********************************%@AE@%%@NL@%
  19543. %@AB@%; This procedure accepts two far strings, concatenates them, and%@AE@%%@NL@%
  19544. %@AB@%; returns the result in the form of a far string.%@AE@%%@NL@%
  19545. %@NL@%
  19546.         .model  medium,basic        %@AB@%;Define memory model to match BASIC.%@AE@%%@NL@%
  19547.         .stack%@NL@%
  19548.         .data?%@NL@%
  19549.         maxst = 50                  %@AB@%;Maximum bytes reserved for strings%@AE@%%@NL@%
  19550. inbuffer1       db  maxst dup(0)    %@AB@%;Room for first fixed-length string%@AE@%%@NL@%
  19551. inbuffer2       db  maxst dup(0)    %@AB@%;and second one%@AE@%%@NL@%
  19552. outbuffer       db  2*maxst dup(0)  %@AB@%;Work area for string processing%@AE@%%@NL@%
  19553.         .data%@NL@%
  19554. sh              dd  0               %@AB@%;Output string descriptor%@AE@%%@NL@%
  19555.         .code%@NL@%
  19556. addstring   proc    uses si di ds, s1:far ptr, s1len, s2:far ptr, s2len%@NL@%
  19557. %@NL@%
  19558. %@AB@%;First get BASIC to convert BASIC strings into standard form.%@AE@%%@NL@%
  19559.         les     ax,s1               %@AB@%;Push far pointer to%@AE@%%@NL@%
  19560.         push    es                  %@AB@%;input string descriptor.%@AE@%%@NL@%
  19561.         push    ax%@NL@%
  19562.         xor     ax,ax               %@AB@%;Push a zero to indicate%@AE@%%@NL@%
  19563.         push    ax                  %@AB@%;it is variable length.%@AE@%%@NL@%
  19564.         push    ds                  %@AB@%;Push far pointer to%@AE@%%@NL@%
  19565.         lea     ax, inbuffer1       %@AB@%;destination string.%@AE@%%@NL@%
  19566.         push    ax%@NL@%
  19567.         mov     ax,maxst            %@AB@%;Push length of destination%@AE@%%@NL@%
  19568.         push    ax                  %@AB@%;fixed-length string.%@AE@%%@NL@%
  19569.         extrn   stringassign:proc%@NL@%
  19570.         call    stringassign        %@AB@%;Call BASIC to assign variable-length%@AE@%%@NL@%
  19571.                                     %@AB@%;string to fixed-length string.%@AE@%%@NL@%
  19572.         les     ax,s2               %@AB@%;Push far pointer to second%@AE@%%@NL@%
  19573.         push    es                  %@AB@%;input string descriptor.%@AE@%%@NL@%
  19574.         push    ax%@NL@%
  19575.         xor     ax,ax               %@AB@%;Push a zero to indicate%@AE@%%@NL@%
  19576.         push    ax                  %@AB@%;it is variable length.%@AE@%%@NL@%
  19577.         push    ds                  %@AB@%;Push far pointer to%@AE@%%@NL@%
  19578.         lea     ax,inbuffer2        %@AB@%;second destination string.%@AE@%%@NL@%
  19579.         push    ax%@NL@%
  19580.         mov     ax,maxst            %@AB@%;Push length of destination%@AE@%%@NL@%
  19581.         push    ax                  %@AB@%;fixed-length string.%@AE@%%@NL@%
  19582.         extrn   stringassign:proc%@NL@%
  19583.         call    stringassign        %@AB@%;Call BASIC to assign variable-length%@AE@%%@NL@%
  19584.                                     %@AB@%;string to fixed-length string.%@AE@%%@NL@%
  19585. %@AB@%;Concatenate strings.%@AE@%%@NL@%
  19586.         lea     si,inbuffer1        %@AB@%;Copy first string to buffer.%@AE@%%@NL@%
  19587.         lea     di,outbuffer%@NL@%
  19588.         mov     ax,ds%@NL@%
  19589.         mov     es,ax%@NL@%
  19590.         mov     cx,s1len%@NL@%
  19591.         rep     movsb%@NL@%
  19592.         lea     si,inbuffer2        %@AB@%;Concatenate second string to%@AE@%%@NL@%
  19593.         mov     cx,s2len            %@AB@%;end of first.%@AE@%%@NL@%
  19594.         rep     movsb%@NL@%
  19595. %@NL@%
  19596. %@AB@%;Get BASIC to convert result back into a BASIC string.%@AE@%%@NL@%
  19597.         push    ds                  %@AB@%;Push far pointer to fixed-length%@AE@%%@NL@%
  19598.         lea     ax,outbuffer        %@AB@%;result string.%@AE@%%@NL@%
  19599.         push    ax%@NL@%
  19600.         mov     ax,s1len            %@AB@%;Compute total length of%@AE@%%@NL@%
  19601.         mov     bx,s2len            %@AB@%;fixed-length result string.%@AE@%%@NL@%
  19602.         add     ax,bx%@NL@%
  19603.         push    ax                  %@AB@%;Push length.%@AE@%%@NL@%
  19604.         push    ds                  %@AB@%;Push far pointer to sh (BASIC%@AE@%%@NL@%
  19605.         lea     ax,sh               %@AB@%;will use this in StringAssign).%@AE@%%@NL@%
  19606.         push    ax%@NL@%
  19607.         xor     ax,ax               %@AB@%;Push a zero for length%@AE@%%@NL@%
  19608.         push    ax                  %@AB@%;indicating variable-length.%@AE@%%@NL@%
  19609.         call    stringassign        %@AB@%;Call BASIC to assign the%@AE@%%@NL@%
  19610.                                     %@AB@%;result to sh.%@AE@%%@NL@%
  19611.         lea     ax,sh               %@AB@%;Return output string pointer%@AE@%%@NL@%
  19612.                                     %@AB@%;in ax and go back to BASIC.%@AE@%%@NL@%
  19613.         ret%@NL@%
  19614. %@NL@%
  19615. addstring       endp%@NL@%
  19616.                 end%@NL@%
  19617. %@NL@%
  19618. %@NL@%
  19619. %@2@%%@AH@%MXADSTB.BAS%@AE@%%@EH@%%@NL@%
  19620. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\MXADSTB.BAS%@AE@%%@NL@%
  19621. %@NL@%
  19622. DEFINT A-Z%@NL@%
  19623. %@NL@%
  19624. %@AB@%'Start program in BASIC for proper initialization.%@AE@%%@NL@%
  19625. %@AB@%' Define external and internal procedures.%@AE@%%@NL@%
  19626. DECLARE SUB shakespeare ()%@NL@%
  19627. DECLARE SUB StringAssign (BYVAL srcsegment, BYVAL srcoffset, BYVAL srclen, BYVAL destsegment, BYVAL destoffset, BYVAL destlen)%@NL@%
  19628. DECLARE SUB addstring (instrg1off, instrg1len, instrg2off, instrg2len, outstrgoff, outstrglen)%@NL@%
  19629. DECLARE SUB StringRelease (s$)%@NL@%
  19630. %@NL@%
  19631. %@AB@%'Go to main routine in second language%@AE@%%@NL@%
  19632. CALL shakespeare%@NL@%
  19633. %@NL@%
  19634. %@AB@%'The non-BASIC program calls this SUB to add the two strings together%@AE@%%@NL@%
  19635. SUB addstring (instrg1off, instrg1len, instrg2off, instrg2len, outstrgoff, outstrglen)%@NL@%
  19636. %@NL@%
  19637. %@AB@%'Create variable-length strings and transfer non-BASIC fixed strings to them.%@AE@%%@NL@%
  19638. %@AB@%'Use VARSEG() to compute the segement of the strings returned from the other%@AE@%%@NL@%
  19639. %@AB@%'language--this is the DGROUP segment, and all string descriptors are found%@AE@%%@NL@%
  19640. %@AB@%'in this segment (even though the far string itself is elsewhere).%@AE@%%@NL@%
  19641. %@NL@%
  19642. CALL StringAssign(VARSEG(a$), instrg1off, instrg1len, VARSEG(a$), VARPTR(a$), 0)%@NL@%
  19643. CALL StringAssign(VARSEG(b$), instrg2off, instrg2len, VARSEG(b$), VARPTR(b$), 0)%@NL@%
  19644. %@NL@%
  19645. %@AB@%' Process the strings--in this case, add them.%@AE@%%@NL@%
  19646. c$ = a$ + b$%@NL@%
  19647. %@NL@%
  19648. %@AB@%' Calculate the new output length.%@AE@%%@NL@%
  19649. outstrglen = LEN(c$)%@NL@%
  19650. %@NL@%
  19651. %@AB@%' Transfer string output to a non-BASIC fixed-length string.%@AE@%%@NL@%
  19652. CALL StringAssign(VARSEG(c$), VARPTR(c$), 0, VARSEG(c$), outstrgoff, outstrglen)%@NL@%
  19653. %@NL@%
  19654. END SUB%@NL@%
  19655. %@NL@%
  19656. %@NL@%
  19657. %@NL@%
  19658. %@2@%%@AH@%MXADSTC.C%@AE@%%@EH@%%@NL@%
  19659. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\MXADSTC.C%@AE@%%@NL@%
  19660. %@NL@%
  19661. %@AI@%#include %@AE@%<string.h> %@NL@%
  19662. %@NL@%
  19663. %@AB@%/* Function Prototypes force either correct data typing or compiler warnings.%@NL@%
  19664. %@AB@% * Note all functions exported to BASIC and all BASIC callback (extern)%@NL@%
  19665. %@AB@% * functions are declared with the far pascal calling convention.%@NL@%
  19666. %@AB@% * WARNING: This must be compiled with the Medium memory model (/AM)%@NL@%
  19667. %@AB@% */%@AE@%%@NL@%
  19668. %@NL@%
  19669. char * pascal addstring( char far *s1, int s1len,%@NL@%
  19670.               char far *s2, int s2len );%@NL@%
  19671. extern void far pascal StringAssign( char far *source, int slen,%@NL@%
  19672.                        char far *dest, int dlen );%@NL@%
  19673. %@NL@%
  19674. %@AB@%/* Declare global char array to contain new BASIC string descriptor.%@NL@%
  19675. %@AB@% */%@AE@%%@NL@%
  19676. char BASICDesc[4];%@NL@%
  19677. %@NL@%
  19678. char * pascal addstring( char far *s1, int s1len,%@NL@%
  19679.               char far *s2, int s2len )%@NL@%
  19680. {%@NL@%
  19681.     char TS1[50];%@NL@%
  19682.     char TS2[50];%@NL@%
  19683.     char TSBig[100];%@NL@%
  19684. %@NL@%
  19685.     %@AB@%/* Use the BASIC callback StringAssign to retrieve information%@NL@%
  19686. %@AB@%     * from the descriptors, s1 and s2, and place them in the temporary%@NL@%
  19687. %@AB@%     * arrays TS1 and TS2.%@NL@%
  19688. %@AB@%     */%@AE@%%@NL@%
  19689.     StringAssign( s1, 0, TS1, 49 );        %@AB@%/* Get S1 as array of char */%@AE@%%@NL@%
  19690.     StringAssign( s2, 0, TS2, 49 );        %@AB@%/* Get S2 as array of char */%@AE@%%@NL@%
  19691. %@NL@%
  19692.     %@AB@%/* Copy the data from TS1 into TSBig, then append the data from%@NL@%
  19693. %@AB@%     * TS2.%@NL@%
  19694. %@AB@%     */%@AE@%%@NL@%
  19695.     memcpy( TSBig, TS1, s1len );%@NL@%
  19696.     memcpy( &TSBig[s1len], TS2, s2len );%@NL@%
  19697. %@NL@%
  19698.     StringAssign( TSBig, s1len + s2len, BASICDesc, 0 );%@NL@%
  19699. %@NL@%
  19700.     return BASICDesc;%@NL@%
  19701. }%@NL@%
  19702. %@NL@%
  19703. %@AB@%/*%@NL@%
  19704. %@AB@% * If, for example, we wanted to return not just one variable length string,%@NL@%
  19705. %@AB@% * but rather the variable length string and the reverse of that:%@NL@%
  19706. %@AB@% *%@NL@%
  19707. %@AB@% * call addstring( "foo ", 4, "bar", 3, a$, r$ )%@NL@%
  19708. %@AB@% *%@NL@%
  19709. %@AB@% * you get "foo bar" in a$ and "rab oof" in r$.%@NL@%
  19710. %@AB@% *%@NL@%
  19711. %@AB@% * Say you give me s1, and s2 (and their respective lengths) on input; for%@NL@%
  19712. %@AB@% * output, I want s3 and s4.%@NL@%
  19713. %@AB@% *%@NL@%
  19714. %@AB@% * Change the StringAssign for TSBig to assign to s3 instead of BASICDesc.%@NL@%
  19715. %@AB@% *%@NL@%
  19716. %@AB@% * Add the following lines of code:%@NL@%
  19717. %@AB@% *%@NL@%
  19718. %@AB@% *     TSBig[s1len + s2len] = '\0';%@NL@%
  19719. %@AB@% *     strrev( TSBig );%@NL@%
  19720. %@AB@% *     StringAssign( TSBig, s1len + s2len, s4, 0 );%@NL@%
  19721. %@AB@% *%@NL@%
  19722. %@AB@% * Delete the return statement.%@NL@%
  19723. %@AB@% *%@NL@%
  19724. %@AB@% * Change the prototype and function header to say:%@NL@%
  19725. %@AB@% *%@NL@%
  19726. %@AB@% * void far pascal addstring%@NL@%
  19727. %@AB@% *%@NL@%
  19728. %@AB@% * instead of%@NL@%
  19729. %@AB@% *%@NL@%
  19730. %@AB@% * char far * pascal addstring%@NL@%
  19731. %@AB@% */%@AE@%%@NL@%
  19732. %@NL@%
  19733. %@NL@%
  19734. %@2@%%@AH@%MXADSTF.FOR%@AE@%%@EH@%%@NL@%
  19735. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\MXADSTF.FOR%@AE@%%@NL@%
  19736. %@NL@%
  19737. %@AB@%C ******************** ADDSTRING  *********************%@AE@%%@NL@%
  19738. %@AB@%C This program is in file MXADSTF.FOR%@AE@%%@NL@%
  19739. %@AB@%C Declare interface to Stringassign subprogram. The pointer fields are%@AE@%%@NL@%
  19740. %@AB@%C declared INTEGER*4, so that different types of far pointers can be%@AE@%%@NL@%
  19741. %@AB@%C passed without conflict. The INTEGER*4 fields are essentially generic%@AE@%%@NL@%
  19742. %@AB@%C pointers. [VALUE] must be specified, or FORTRAN will pass pointers to%@AE@%%@NL@%
  19743. %@AB@%C pointers. INTEGER*2 also passed by [VALUE], to be consistent with%@AE@%%@NL@%
  19744. %@AB@%C declaration of Stringassign.%@AE@%%@NL@%
  19745. %@AB@%C%@AE@%%@NL@%
  19746.        INTERFACE TO SUBROUTINE STRASG [ALIAS:'STRINGASSIGN'] (S,SL,D,DL)%@NL@%
  19747.        INTEGER*4 S [VALUE]%@NL@%
  19748.        INTEGER*2 SL [VALUE]%@NL@%
  19749.        INTEGER*4 D [VALUE]%@NL@%
  19750.        INTEGER*2 DL [VALUE]%@NL@%
  19751.        END%@NL@%
  19752. %@AB@%C%@AE@%%@NL@%
  19753. %@AB@%C Declare heading of Addstring function in the same way as above: the%@AE@%%@NL@%
  19754. %@AB@%C pointer fields are INTEGER*4%@AE@%%@NL@%
  19755. %@AB@%C%@AE@%%@NL@%
  19756.        INTEGER*2 FUNCTION ADDSTR [ALIAS:'ADDSTRING'] (S1,S1LEN,S2,S2LEN)%@NL@%
  19757.        INTEGER*4 S1 [VALUE]%@NL@%
  19758.        INTEGER*2 S1LEN [VALUE]%@NL@%
  19759.        INTEGER*4 S2 [VALUE]%@NL@%
  19760.        INTEGER*2 S2LEN [VALUE]%@NL@%
  19761. %@AB@%C%@AE@%%@NL@%
  19762. %@AB@%C Local parameters TS1, TS2, and BIGSTR are temporary strings. STRDES is%@AE@%%@NL@%
  19763. %@AB@%C a four-byte object into which Stringassign will put BASIC string%@AE@%%@NL@%
  19764. %@AB@%C descriptor.%@AE@%%@NL@%
  19765. %@AB@%C%@AE@%%@NL@%
  19766. %@AB@%       CHARACTER*50 TS1, TS2%@AE@%%@NL@%
  19767. %@AB@%       CHARACTER*100 BIGSTR%@AE@%%@NL@%
  19768.        INTEGER*4 STRDES%@NL@%
  19769. %@NL@%
  19770.         TS1 = " "%@NL@%
  19771.         TS2 = " "%@NL@%
  19772.         STRDES = 0%@NL@%
  19773. %@NL@%
  19774. %@AB@%C%@AE@%%@NL@%
  19775. %@AB@%C Use the LOCFAR function to take the far address of data. LOCFAR returns%@AE@%%@NL@%
  19776. %@AB@%C a value of type INTEGER*4.%@AE@%%@NL@%
  19777. %@AB@%C%@AE@%%@NL@%
  19778. %@AB@%       CALL STRASG (S1, 0, LOCFAR(TS1), S1LEN)%@AE@%%@NL@%
  19779. %@AB@%       CALL STRASG (S2, 0, LOCFAR(TS2), S2LEN)%@AE@%%@NL@%
  19780.        BIGSTR = TS1(1:S1LEN) // TS2(1:S2LEN)%@NL@%
  19781. %@AB@%       CALL STRASG (LOCFAR(BIGSTR), S1LEN+S2LEN, LOCFAR(STRDES), 0)%@AE@%%@NL@%
  19782.        ADDSTR = LOC(STRDES)%@NL@%
  19783.        RETURN%@NL@%
  19784.        END%@NL@%
  19785. %@NL@%
  19786. %@NL@%
  19787. %@2@%%@AH@%MXSHKA.ASM%@AE@%%@EH@%%@NL@%
  19788. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\MXSHKA.ASM%@AE@%%@NL@%
  19789. %@NL@%
  19790. %@AB@%;*************************** SHAKESPEARE ******************************%@AE@%%@NL@%
  19791. %@AB@%; This program creates two strings and passes them to a BASIC procedure%@AE@%%@NL@%
  19792. %@AB@%; called addstring (in file MXADSTB.BAS).  This procedure concatenates%@AE@%%@NL@%
  19793. %@AB@%; the strings and passes the result to MASM which prints it.%@AE@%%@NL@%
  19794. %@NL@%
  19795.         .model  medium,basic        %@AB@%;Use same memory model as BASIC.%@AE@%%@NL@%
  19796.         .stack%@NL@%
  19797.         .data                       %@AB@%;Create the data.%@AE@%%@NL@%
  19798. phrase1         db      "To be or not to be%@AB@%;"%@AE@%%@NL@%
  19799. phrase1len      dw      $-phrase1%@NL@%
  19800. phrase1off      dw      phrase1%@NL@%
  19801. phrase2         db      " that is the question."%@NL@%
  19802. phrase2len      dw      $-phrase2%@NL@%
  19803. phrase2off      dw      phrase2%@NL@%
  19804. sentence        db      100 dup(0)  %@AB@%;Make room for return data%@AE@%%@NL@%
  19805. sentencelen     dw      0           %@AB@%;and a length indicator.%@AE@%%@NL@%
  19806. sentenceoff     dw      sentence%@NL@%
  19807. %@NL@%
  19808.         .code%@NL@%
  19809. shakespeare proc    uses si%@NL@%
  19810. %@NL@%
  19811. %@AB@%;First call BASIC to concatenate strings.%@AE@%%@NL@%
  19812.         lea     ax,phrase1off       %@AB@%;Push far address of%@AE@%%@NL@%
  19813.         push    ax                  %@AB@%;fixed-length string #1,%@AE@%%@NL@%
  19814.         lea     ax,phrase1len       %@AB@%;and its length.%@AE@%%@NL@%
  19815.         push    ax%@NL@%
  19816.         lea     ax,phrase2off       %@AB@%;Do the same for the%@AE@%%@NL@%
  19817.         push    ax                  %@AB@%;address of string #2,%@AE@%%@NL@%
  19818.         lea     ax,phrase2len       %@AB@%;and its length.%@AE@%%@NL@%
  19819.         push    ax%@NL@%
  19820.         lea     ax,sentenceoff      %@AB@%;Push far address of%@AE@%%@NL@%
  19821.         push    ax                  %@AB@%;the return string,%@AE@%%@NL@%
  19822.         lea     ax,sentencelen      %@AB@%;and its length.%@AE@%%@NL@%
  19823.         push    ax%@NL@%
  19824.         extrn   addstring:proc      %@AB@%;Call BASIC function to%@AE@%%@NL@%
  19825.         call    addstring           %@AB@%;concatenate the strings and%@AE@%%@NL@%
  19826.                                     %@AB@%;put the result in the%@AE@%%@NL@%
  19827.                                     %@AB@%;fixed-length return string.%@AE@%%@NL@%
  19828. %@NL@%
  19829. %@AB@%;Call DOS to print string. The DOS string output routine (09H)%@AE@%%@NL@%
  19830. %@AB@%;requires that strings end with a "$" character.%@AE@%%@NL@%
  19831.         mov     bx,sentencelen      %@AB@%;Go to end of the result string%@AE@%%@NL@%
  19832.         lea     si,sentence         %@AB@%;and add a "$" (24h) character.%@AE@%%@NL@%
  19833.         mov     byte ptr [bx + si],24h%@NL@%
  19834. %@NL@%
  19835.         lea     dx,sentence         %@AB@%;Set up registers%@AE@%%@NL@%
  19836.         mov     ah,9                %@AB@%;and call DOS to%@AE@%%@NL@%
  19837.         int     21h                 %@AB@%;print result string.%@AE@%%@NL@%
  19838.         ret%@NL@%
  19839. %@NL@%
  19840. shakespeare endp%@NL@%
  19841. %@NL@%
  19842.         end%@NL@%
  19843. %@NL@%
  19844. %@NL@%
  19845. %@2@%%@AH@%MXSHKB.BAS%@AE@%%@EH@%%@NL@%
  19846. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\MXSHKB.BAS%@AE@%%@NL@%
  19847. %@NL@%
  19848. DEFINT A-Z%@NL@%
  19849. %@AB@%'Define non-basic procedures%@AE@%%@NL@%
  19850. DECLARE FUNCTION addstring$(SEG s1$, BYVAL s1length, SEG s2$, BYVAL s2length)%@NL@%
  19851. %@NL@%
  19852. %@NL@%
  19853. %@AB@%'Create the data%@AE@%%@NL@%
  19854. a$ = "To be or not to be;"%@NL@%
  19855. b$ = " that is the question."%@NL@%
  19856. %@NL@%
  19857. %@AB@%'Use non-BASIC function to add two BASIC far strings%@AE@%%@NL@%
  19858. c$ = addstring(a$, LEN(a$), b$, LEN(b$))%@NL@%
  19859. %@NL@%
  19860. %@AB@%'print the result on the screen%@AE@%%@NL@%
  19861. %@NL@%
  19862. PRINT c$%@NL@%
  19863. %@NL@%
  19864. %@NL@%
  19865. %@2@%%@AH@%MXSHKC.C%@AE@%%@EH@%%@NL@%
  19866. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\MXSHKC.C%@AE@%%@NL@%
  19867. %@NL@%
  19868. %@AI@%#include %@AE@%<stdio.h> %@NL@%
  19869. %@AI@%#include %@AE@%<string.h> %@NL@%
  19870. %@NL@%
  19871. %@AB@%/* Function Prototypes force either correct data typing or compiler warnings.%@NL@%
  19872. %@AB@% * Note all functions exported to BASIC and all BASIC callback (extern)%@NL@%
  19873. %@AB@% * functions are declared with the far pascal calling convention.%@NL@%
  19874. %@AB@% * IMPORTANT: This must be compiled with the Medium memory model (/AM)%@NL@%
  19875. %@AB@% */%@AE@%%@NL@%
  19876. void far pascal shakespeare( void );%@NL@%
  19877. extern void far pascal addstring( char  ** s1, int * s1len,%@NL@%
  19878.                                     char ** s2, int * s2len,%@NL@%
  19879.                                     char ** s3, int * s3len );%@NL@%
  19880. %@NL@%
  19881. void far pascal shakespeare( void )%@NL@%
  19882. {%@NL@%
  19883.     char * s1 = "To be or not to be;";%@NL@%
  19884.     int  s1len;%@NL@%
  19885.     char * s2 = " that is the question.";%@NL@%
  19886.     int  s2len;%@NL@%
  19887.     char s3[100];%@NL@%
  19888.     int  s3len;%@NL@%
  19889.     char * s3add = s3;%@NL@%
  19890. %@NL@%
  19891.     s1len = strlen( s1 );%@NL@%
  19892.     s2len = strlen( s2 );%@NL@%
  19893.     addstring( &s1, &s1len, &s2, &s2len, &s3add, &s3len );%@NL@%
  19894. %@NL@%
  19895.     s3[s3len] = '\0';%@NL@%
  19896.     printf("\n%s", s3 );%@NL@%
  19897. }%@NL@%
  19898. %@NL@%
  19899. %@NL@%
  19900. %@2@%%@AH@%MXSHKF.FOR%@AE@%%@EH@%%@NL@%
  19901. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\MXSHKF.FOR%@AE@%%@NL@%
  19902. %@NL@%
  19903. %@AB@%C *********************** SHAKESPEARE ****************%@AE@%%@NL@%
  19904. %@AB@%C This program is in file MXSHKF.FOR%@AE@%%@NL@%
  19905. %@AB@%C Declare interface to BASIC routine ADDSTRING.%@AE@%%@NL@%
  19906. %@AB@%C All parameters must be passed NEAR, for compatibility with BASIC's%@AE@%%@NL@%
  19907. %@AB@%C conventions.%@AE@%%@NL@%
  19908. %@AB@%C%@AE@%%@NL@%
  19909. %@NL@%
  19910. %@NL@%
  19911.        INTERFACE TO SUBROUTINE ADDSTR[ALIAS:'ADDSTRING']%@NL@%
  19912.      * (S1,L1,S2,L2,S3,L3)%@NL@%
  19913.        INTEGER*2 S1 [NEAR]%@NL@%
  19914.        INTEGER*2 L1 [NEAR]%@NL@%
  19915.        INTEGER*2 S2 [NEAR]%@NL@%
  19916.        INTEGER*2 L2 [NEAR]%@NL@%
  19917.        INTEGER*2 S3 [NEAR]%@NL@%
  19918.        INTEGER*2 L3 [NEAR]%@NL@%
  19919.        END%@NL@%
  19920. %@AB@%C%@AE@%%@NL@%
  19921. %@AB@%C Declare subroutine SHAKESPEARE, which declares two strings, calls BASIC%@AE@%%@NL@%
  19922. %@AB@%C subroutine ADDSTRING, and prints the result.%@AE@%%@NL@%
  19923. %@AB@%C%@AE@%%@NL@%
  19924.        SUBROUTINE SHAKES [ALIAS:'SHAKESPEARE']%@NL@%
  19925. %@AB@%       CHARACTER*50 STR1, STR2%@AE@%%@NL@%
  19926. %@AB@%       CHARACTER*100 STR3%@AE@%%@NL@%
  19927.        INTEGER*2 STRLEN1, STRLEN2, STRLEN3%@NL@%
  19928.        INTEGER*2 TMP1, TMP2, TMP3%@NL@%
  19929. %@AB@%C%@AE@%%@NL@%
  19930. %@AB@%C The subroutine uses FORTRAN LEN_TRIM function, which returns the length%@AE@%%@NL@%
  19931. %@AB@%C of string, excluding trailing blanks. (All FORTRAN strings are initialized%@AE@%%@NL@%
  19932. %@AB@%C to blanks.)%@AE@%%@NL@%
  19933. %@AB@%C%@AE@%%@NL@%
  19934.        STR1 = 'To be or not to be;'%@NL@%
  19935.        STRLEN1 = LEN_TRIM(STR1)%@NL@%
  19936.        STR2 = ' that is the question.'%@NL@%
  19937.        STRLEN2 = LEN_TRIM(STR2)%@NL@%
  19938.        TMP1 = LOC(STR1)%@NL@%
  19939.        TMP2 = LOC(STR2)%@NL@%
  19940.        TMP3 = LOC(STR3)%@NL@%
  19941. %@AB@%       CALL ADDSTR (TMP1, STRLEN1, TMP2, STRLEN2, TMP3, STRLEN3)%@AE@%%@NL@%
  19942.        WRITE (*,*) STR3%@NL@%
  19943.        END%@NL@%
  19944. %@NL@%
  19945. %@NL@%
  19946. %@NL@%
  19947. %@2@%%@AH@%PALETTE.BAS%@AE@%%@EH@%%@NL@%
  19948. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\PALETTE.BAS%@AE@%%@NL@%
  19949. %@NL@%
  19950. DECLARE SUB InitPalette ()%@NL@%
  19951. DECLARE        SUB ChangePalette ()%@NL@%
  19952. DECLARE        SUB DrawEllipses ()%@NL@%
  19953. %@NL@%
  19954. DEFINT A-Z%@NL@%
  19955. DIM SHARED PaletteArray(15)%@NL@%
  19956. %@NL@%
  19957. SCREEN 8                 ' 640 x 200 resolution; 16 colors%@NL@%
  19958. %@NL@%
  19959. InitPalette                 ' Initialize PaletteArray.%@NL@%
  19960. DrawEllipses                 ' Draw and paint concentric ellipses.%@NL@%
  19961. %@NL@%
  19962. DO                         ' Shift the palette until a key%@NL@%
  19963.    ChangePalette         ' is pressed.%@NL@%
  19964. LOOP WHILE INKEY$ = ""%@NL@%
  19965. %@NL@%
  19966. END%@NL@%
  19967. %@NL@%
  19968. %@NL@%
  19969. %@AB@%' ====================== InitPalette ======================%@AE@%%@NL@%
  19970. %@AB@%'    This procedure initializes the integer array used to%@AE@%%@NL@%
  19971. %@AB@%'    change the palette.%@AE@%%@NL@%
  19972. %@AB@%' =========================================================%@AE@%%@NL@%
  19973. %@NL@%
  19974. SUB InitPalette        STATIC%@NL@%
  19975.    FOR I = 0 TO        15%@NL@%
  19976.       PaletteArray(I) =        I%@NL@%
  19977.    NEXT        I%@NL@%
  19978. END SUB%@NL@%
  19979. %@AB@%' ===================== DrawEllipses ======================%@AE@%%@NL@%
  19980. %@AB@%'    This procedure draws 15 concentric ellipses and%@AE@%%@NL@%
  19981. %@AB@%'    paints the interior of each with a different color.%@AE@%%@NL@%
  19982. %@AB@%' =========================================================%@AE@%%@NL@%
  19983. %@NL@%
  19984. SUB DrawEllipses STATIC%@NL@%
  19985.    CONST ASPECT        = 1 / 3%@NL@%
  19986.    FOR ColorVal        = 15 TO        1 STEP -1%@NL@%
  19987.       Radius = 20 * ColorVal%@NL@%
  19988.       CIRCLE (320, 100), Radius, ColorVal, , , ASPECT%@NL@%
  19989.       PAINT (320, 100),        ColorVal%@NL@%
  19990.    NEXT%@NL@%
  19991. END SUB%@NL@%
  19992. %@NL@%
  19993. %@NL@%
  19994. %@AB@%' ===================== ChangePalette =====================%@AE@%%@NL@%
  19995. %@AB@%'  This procedure rotates the palette by one each time it%@AE@%%@NL@%
  19996. %@AB@%'  is called. For example, after the first call to%@AE@%%@NL@%
  19997. %@AB@%'  ChangePalette, PaletteArray(1) = 2, PaletteArray(2) = 3,%@AE@%%@NL@%
  19998. %@AB@%'  . . . , PaletteArray(14) = 15, and PaletteArray(15) = 1%@AE@%%@NL@%
  19999. %@AB@%' =========================================================%@AE@%%@NL@%
  20000. %@NL@%
  20001. SUB ChangePalette STATIC%@NL@%
  20002.    FOR I = 1 TO        15%@NL@%
  20003.       PaletteArray(I) =        (PaletteArray(I) MOD 15) + 1%@NL@%
  20004.    NEXT        I%@NL@%
  20005.    PALETTE USING PaletteArray(0) ' Shift the color displayed%@NL@%
  20006. %@AB@%                                 ' by each of the attributes.%@AE@%%@NL@%
  20007. END SUB%@NL@%
  20008. %@NL@%
  20009. %@NL@%
  20010. %@NL@%
  20011. %@2@%%@AH@%PASSWRD.BAS%@AE@%%@EH@%%@NL@%
  20012. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\PASSWRD.BAS%@AE@%%@NL@%
  20013. %@NL@%
  20014. DECLARE FUNCTION CertifiedOperator% ()%@NL@%
  20015. CONST FALSE = 0, True = NOT FALSE%@NL@%
  20016. %@NL@%
  20017. IF CertifiedOperator = FALSE THEN%@NL@%
  20018.         PRINT "Connection Refused."%@NL@%
  20019.         END%@NL@%
  20020. END IF%@NL@%
  20021. %@NL@%
  20022. PRINT "Connected to Network."%@NL@%
  20023. %@AB@%'Main program continues here.%@AE@%%@NL@%
  20024. %@AB@%'  .%@AE@%%@NL@%
  20025. %@AB@%'  .%@AE@%%@NL@%
  20026. %@AB@%'  .%@AE@%%@NL@%
  20027. END%@NL@%
  20028. %@NL@%
  20029. FUNCTION CertifiedOperator%%@NL@%
  20030. ON LOCAL ERROR GOTO Handler%@NL@%
  20031. %@AB@%'Count the number of times the operator tries to sign on.%@AE@%%@NL@%
  20032. Attempts% = 0%@NL@%
  20033. %@NL@%
  20034. TryAgain:%@NL@%
  20035. %@AB@%'Assume the operator has valid credentials.%@AE@%%@NL@%
  20036. CertifiedOperator = True%@NL@%
  20037. %@AB@%'Keep track of bad entries.%@AE@%%@NL@%
  20038. Attempts% = Attempts% + 1%@NL@%
  20039. IF Attempts% > 3 THEN ERROR 255%@NL@%
  20040. %@AB@%'Check out the operator's credentials.%@AE@%%@NL@%
  20041. INPUT "Enter Account Number"; Account$%@NL@%
  20042. IF LEFT$(Account$, 4) <> "1234" THEN ERROR 200%@NL@%
  20043. INPUT "Enter Password"; Password$%@NL@%
  20044. IF Password$ <> "Swordfish" THEN ERROR 201%@NL@%
  20045. EXIT FUNCTION%@NL@%
  20046. %@NL@%
  20047. Handler:%@NL@%
  20048. SELECT CASE ERR%@NL@%
  20049. %@AB@%    'Start over if account number doesn't have "1234" in it.%@AE@%%@NL@%
  20050.         CASE 200%@NL@%
  20051.                 PRINT "Illegal account number. Please re-enter."%@NL@%
  20052.                 RESUME TryAgain%@NL@%
  20053. %@AB@%    'Start over if the password is wrong.%@AE@%%@NL@%
  20054.         CASE 201%@NL@%
  20055.                 PRINT "Wrong password. Please re-enter both items."%@NL@%
  20056.                 RESUME TryAgain%@NL@%
  20057. %@AB@%    'Return false if operator makes too many mistakes.%@AE@%%@NL@%
  20058.         CASE 255%@NL@%
  20059.                 CertifiedOperator% = FALSE%@NL@%
  20060.                 EXIT FUNCTION%@NL@%
  20061. END SELECT%@NL@%
  20062. %@NL@%
  20063. END FUNCTION%@NL@%
  20064. %@NL@%
  20065. %@NL@%
  20066. %@2@%%@AH@%PGBAR.BAS%@AE@%%@EH@%%@NL@%
  20067. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\PGBAR.BAS%@AE@%%@NL@%
  20068. %@NL@%
  20069. %@AB@%' PGBAR.BAS:  Create sample bar chart%@AE@%%@NL@%
  20070. %@NL@%
  20071. DEFINT A-Z%@NL@%
  20072. %@AB@%' $INCLUDE: 'CHRTB.BI'%@AE@%%@NL@%
  20073. CONST FALSE = 0, TRUE = NOT FALSE, MONTHS = 12%@NL@%
  20074. CONST HIGHESTMODE = 13, TEXTONLY = 0%@NL@%
  20075. %@NL@%
  20076. DIM Env AS ChartEnvironment                 ' See CHRTB.BI for declaration of                     ' the ChartEnvironment type%@NL@%
  20077. DIM MonthCategories(1 TO MONTHS) AS STRING  ' Array for categories (used for%@NL@%
  20078. %@AB@%                                                                                                                                                                                ' Pie, Column and Bar Charts)%@AE@%%@NL@%
  20079. DIM OJvalues(1 TO MONTHS) AS SINGLE         ' Array for 1st data series%@NL@%
  20080. %@NL@%
  20081. DECLARE FUNCTION BestMode ()%@NL@%
  20082. %@NL@%
  20083. %@AB@%' Initialize the data arrays%@AE@%%@NL@%
  20084. FOR index = 1 TO MONTHS: READ OJvalues(index): NEXT index%@NL@%
  20085. FOR index = 1 TO MONTHS: READ MonthCategories$(index): NEXT index%@NL@%
  20086. %@NL@%
  20087. %@AB@%' Pass the value returned by the BestMode function to the Presentation%@AE@%%@NL@%
  20088. %@AB@%' Graphics routine ChartScreen to set the graphics mode for charting%@AE@%%@NL@%
  20089. %@NL@%
  20090. ChartScreen (BestMode)      ' Even if SCREEN is already set to an acceptable%@NL@%
  20091. %@AB@%                                                                                                                ' mode, you still have to set it with ChartScreen%@AE@%%@NL@%
  20092. IF ChartErr = cBadScreen THEN   ' Check to make sure ChartScreen succeeded%@NL@%
  20093.         PRINT "Sorry --- There is a screen-mode problem in the Charting library"%@NL@%
  20094.         END%@NL@%
  20095. END IF%@NL@%
  20096. %@AB@%' Initialize a default pie chart%@AE@%%@NL@%
  20097. %@AB@%                                                                                                                                                ' Pass Env (the environment variable),%@AE@%%@NL@%
  20098. DefaultChart Env, cBar, cPlain      ' the constant cBar (for Bar Chart) and%@NL@%
  20099. %@AB@%                                                                                                                                                ' cPlain%@AE@%%@NL@%
  20100. %@NL@%
  20101. %@AB@%' Add Titles and some chart options. These assignments modify some default%@AE@%%@NL@%
  20102. %@AB@%' values set in the variable Env (of type ChartEnvironment) by DefaultChart%@AE@%%@NL@%
  20103. %@NL@%
  20104. Env.MainTitle.Title = "Good Neighbor Grocery" ' Specifies text of chart title%@NL@%
  20105. Env.MainTitle.TitleColor = 15                 ' Specifies color of title text%@NL@%
  20106. Env.MainTitle.Justify = cRight                ' How to align of title text%@NL@%
  20107. Env.SubTitle.Title = "Orange Juice Sales"     ' Text of chart subtitle%@NL@%
  20108. Env.SubTitle.TitleColor = 15                  ' Color of subtitle text%@NL@%
  20109. Env.SubTitle.Justify = cRight                 ' How to align of subtitle text%@NL@%
  20110. Env.ChartWindow.Border = cNo                  ' Specifies chart has no border%@NL@%
  20111. %@NL@%
  20112. %@AB@%' The next 2 assignments label the x-axis and y-axis%@AE@%%@NL@%
  20113. Env.XAxis.AxisTitle.Title = "Quantity (cases)"%@NL@%
  20114. Env.YAxis.AxisTitle.Title = "Months"%@NL@%
  20115. %@NL@%
  20116. %@AB@%' Call the bar-charting routine --- Arguments for call to Chart are:%@AE@%%@NL@%
  20117. %@AB@%' Env                 - Environment variable%@AE@%%@NL@%
  20118. %@AB@%' MonthCategories()   - Array containing Category labels%@AE@%%@NL@%
  20119. %@AB@%' OJvalues()          - Array containing Data values to chart%@AE@%%@NL@%
  20120. %@AB@%' MONTHS              - Tells number of data values to chart%@AE@%%@NL@%
  20121. %@NL@%
  20122.         Chart Env, MonthCategories(), OJvalues(), MONTHS%@NL@%
  20123.         SLEEP%@NL@%
  20124. %@AB@%        '  If the rest of your program isn't graphic, reset original mode here%@AE@%%@NL@%
  20125. END%@NL@%
  20126. %@NL@%
  20127. %@AB@%' Simulate data generation for chart values and category labels%@AE@%%@NL@%
  20128. DATA 33,27,42,64,106,157,182,217,128,62,43,36%@NL@%
  20129. DATA "Jan","Feb","Mar","Apr","May","Jun","Jly","Aug","Sep","Oct","Nov","Dec",%@NL@%
  20130. %@NL@%
  20131. %@AB@%'============= Function to determine and set highest resolution ========%@AE@%%@NL@%
  20132. %@AB@%' The BestMode function uses a local error trap to check available modes,%@AE@%%@NL@%
  20133. %@AB@%' then assigns the integer representing the best mode for charting to its%@AE@%%@NL@%
  20134. %@AB@%' name so it is returned to the caller. The function terminate execution if%@AE@%%@NL@%
  20135. %@AB@%' the hardware doesn't support a mode appropriate for Presentation Graphics%@AE@%%@NL@%
  20136. %@AB@%'========================================================================%@AE@%%@NL@%
  20137. FUNCTION BestMode%@NL@%
  20138. %@NL@%
  20139. %@AB@%' Set a trap for an expected local error --- handled within the function%@AE@%%@NL@%
  20140. ON LOCAL ERROR GOTO ScreenError%@NL@%
  20141. %@NL@%
  20142. FOR TestValue = HIGHESTMODE TO 0 STEP -1%@NL@%
  20143.         DisplayError = FALSE%@NL@%
  20144.         SCREEN TestValue%@NL@%
  20145.         IF DisplayError = FALSE THEN%@NL@%
  20146.                 SELECT CASE TestValue%@NL@%
  20147.                         CASE 12, 13%@NL@%
  20148.                                 BestMode = 12%@NL@%
  20149.                         CASE 9, 10, 11%@NL@%
  20150.                                 BestMode = 9%@NL@%
  20151.                         CASE 8, 4, 3%@NL@%
  20152.                                 BestMode = TestValue%@NL@%
  20153.                         CASE 2, 7%@NL@%
  20154.                                 BestMode = 2%@NL@%
  20155.                         CASE 1%@NL@%
  20156.                                 BestMode = 1%@NL@%
  20157.                         CASE ELSE%@NL@%
  20158.                                 PRINT "Sorry, you need graphics to display charts"%@NL@%
  20159.                                 END%@NL@%
  20160.                 END SELECT%@NL@%
  20161.                 EXIT FUNCTION%@NL@%
  20162.         END IF%@NL@%
  20163. NEXT TestValue%@NL@%
  20164. %@AB@%' Note there is no need to turn off the local error handler. It is turned off%@AE@%%@NL@%
  20165. %@AB@%' automatically when control passes out of the function%@AE@%%@NL@%
  20166. %@NL@%
  20167. EXIT FUNCTION%@NL@%
  20168. %@AB@%'==================== | Local error handler code |=======================%@AE@%%@NL@%
  20169. %@AB@%' The ScreenError label identifies a local error handler relied in the%@AE@%%@NL@%
  20170. %@AB@%' BestMode function. Invalid SCREEN values generate Error # 5 (Illegal%@AE@%%@NL@%
  20171. %@AB@%' function call) --- so if that is not the error reset ERROR to the ERR%@AE@%%@NL@%
  20172. %@AB@%' value that was generated so the error can be passed to other, possibly%@AE@%%@NL@%
  20173. %@AB@%' more appropriate errors.%@AE@%%@NL@%
  20174. ScreenError:%@NL@%
  20175.         IF ERR = 5 THEN%@NL@%
  20176.                 DisplayError = TRUE%@NL@%
  20177.                 RESUME NEXT%@NL@%
  20178.         ELSE%@NL@%
  20179.                 ERROR ERR%@NL@%
  20180.         END IF%@NL@%
  20181. END FUNCTION%@NL@%
  20182. %@NL@%
  20183. %@NL@%
  20184. %@NL@%
  20185. %@2@%%@AH@%PGLINEMS.BAS%@AE@%%@EH@%%@NL@%
  20186. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\PGLINEMS.BAS%@AE@%%@NL@%
  20187. %@NL@%
  20188. %@AB@%' PGLINEMS.BAS - Program to generate a simple multi-data series line chart%@AE@%%@NL@%
  20189. %@NL@%
  20190. DEFINT A-Z%@NL@%
  20191. %@AB@%'$INCLUDE: 'CHRTB.BI'                 ' Declarations and Definitions%@AE@%%@NL@%
  20192. DIM Env AS ChartEnvironment           ' Variable to hold environment structure%@NL@%
  20193. DIM AxisLabels(1 TO 4) AS STRING      ' Array of categories%@NL@%
  20194. DIM LegendLabels(1 TO 2) AS STRING    ' Array of series labels%@NL@%
  20195. DIM Values(1 TO 4, 1 TO 3) AS SINGLE  ' 2-dimentsion array of values to plot%@NL@%
  20196. %@NL@%
  20197. DIM Col%(0 TO cPalLen)          ' Define arrays to hold values retrieved with%@NL@%
  20198. DIM Lines%(0 TO cPalLen)        ' call to GetPaletteDef. By modifying these%@NL@%
  20199. DIM Fill$(0 TO cPalLen)         ' values, then calling ResetPaletteDef, you%@NL@%
  20200. DIM Char%(0 TO cPalLen)         ' can change colors, plot characters, borders,%@NL@%
  20201. DIM Bord%(0 TO cPalLen)         ' and even the line styles and fill patterns%@NL@%
  20202. %@NL@%
  20203. %@AB@%' Read the data to display into the arrays%@AE@%%@NL@%
  20204. %@NL@%
  20205. FOR index = 1 TO 2: READ LegendLabels(index): NEXT index%@NL@%
  20206. FOR index = 1 TO 4: READ AxisLabels(index): NEXT index%@NL@%
  20207. %@NL@%
  20208. FOR columnindex = 1 TO 2                ' The array has 2 columns, each of%@NL@%
  20209.   FOR rowindex = 1 TO 4                 ' which has 4 rows. Each column rep-%@NL@%
  20210.     READ Values(rowindex, columnindex)  ' resents 1 full data series. First,%@NL@%
  20211.   NEXT rowindex                         ' fill column 1, then fill column 2%@NL@%
  20212. NEXT columnindex                        ' with values from the last DATA%@NL@%
  20213. %@AB@%                                        ' statement (below).%@AE@%%@NL@%
  20214. CLS%@NL@%
  20215. %@NL@%
  20216. ChartScreen 2                           ' Set a common graphics mode%@NL@%
  20217. %@NL@%
  20218. %@AB@%' Retrieve current palette settings, then assign some new values%@AE@%%@NL@%
  20219. %@NL@%
  20220. GetPaletteDef Col%(), Lines%(), Fill$(), Char%(), Bord%()%@NL@%
  20221. %@NL@%
  20222.  Col%(2) = (15)          '  Assign white as color for second-series plot line%@NL@%
  20223.  Char%(1) = (4)          '  Assign  "" as plot character for 1st plot line%@NL@%
  20224.  Char%(2) = (18)         '  Assign  "" as plot character for 2nd plot line%@NL@%
  20225. %@NL@%
  20226. %@AB@%' Reset the palettes with modified arrays%@AE@%%@NL@%
  20227. %@NL@%
  20228. SetPaletteDef Col%(), Lines%(), Fill$(), Char%(), Bord%()   ' Enter the changes%@NL@%
  20229. %@NL@%
  20230. DefaultChart Env, cLine, cLines         ' Set up multi-series line chart%@NL@%
  20231. %@NL@%
  20232. %@AB@%' Display the chart%@AE@%%@NL@%
  20233. %@NL@%
  20234. ChartMS Env, AxisLabels(), Values(), 4, 1, 2, LegendLabels()%@NL@%
  20235. %@NL@%
  20236. SLEEP                                   ' Keep it onscreen until user presses%@NL@%
  20237. %@AB@%                                        ' a key%@AE@%%@NL@%
  20238. END%@NL@%
  20239. %@NL@%
  20240. %@AB@%' Simulated data to be shown on chart%@AE@%%@NL@%
  20241. DATA "Qtr 1","Qtr 2"%@NL@%
  20242. DATA "Admn","Markg","Prodn","Devel"%@NL@%
  20243. DATA 38,30,40,32,18,40,20,12%@NL@%
  20244. %@NL@%
  20245. %@NL@%
  20246. %@NL@%
  20247. %@2@%%@AH@%PGPIE.BAS%@AE@%%@EH@%%@NL@%
  20248. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\PGPIE.BAS%@AE@%%@NL@%
  20249. %@NL@%
  20250. %@AB@%' PGPIE.BAS:  Create sample pie chart%@AE@%%@NL@%
  20251. %@NL@%
  20252. DEFINT A-Z%@NL@%
  20253. %@AB@%' $INCLUDE: 'fontb.BI'%@AE@%%@NL@%
  20254. %@AB@%' $INCLUDE: 'CHRTB.BI'%@AE@%%@NL@%
  20255. CONST FALSE = 0, TRUE = NOT FALSE, MONTHS = 12%@NL@%
  20256. CONST HIGHESTMODE = 13, TEXTONLY = 0%@NL@%
  20257. %@NL@%
  20258. DIM Env AS ChartEnvironment                 ' See CHRTB.BI for declaration of                     ' the ChartEnvironment type%@NL@%
  20259. DIM MonthCategories(1 TO MONTHS) AS STRING  ' Array for categories%@NL@%
  20260. DIM OJvalues(1 TO MONTHS) AS SINGLE         ' Array for 1st data series%@NL@%
  20261. DIM Exploded(1 TO MONTHS) AS INTEGER        ' "Explode" flags array (specifies%@NL@%
  20262. %@AB@%                                                                                                                                                                                '  which pie slices are separated)%@AE@%%@NL@%
  20263. DECLARE FUNCTION BestMode ()%@NL@%
  20264. %@NL@%
  20265. %@AB@%' Initialize the data arrays%@AE@%%@NL@%
  20266. FOR index = 1 TO MONTHS: READ OJvalues(index): NEXT index%@NL@%
  20267. FOR index = 1 TO MONTHS: READ MonthCategories$(index): NEXT index%@NL@%
  20268. %@NL@%
  20269. %@AB@%' Set the elements of the array that determines separation of the pie slices%@AE@%%@NL@%
  20270. FOR Flags = 1 TO MONTHS                       ' If value of OJvalues(Flags)%@NL@%
  20271.         Exploded(Flags) = (OJvalues(Flags) >= 100)  ' >= 100 the corresponding flag%@NL@%
  20272. NEXT Flags                                    ' is set true, separating slices%@NL@%
  20273. %@NL@%
  20274. %@AB@%' Pass the value returned by the BestMode function to the Presentation%@AE@%%@NL@%
  20275. %@AB@%' Graphics routine ChartScreen to set the graphics mode for charting%@AE@%%@NL@%
  20276. %@NL@%
  20277. ChartScreen (BestMode)      ' Even if SCREEN is already set to an acceptable%@NL@%
  20278. %@AB@%                                                                                                                ' mode, you still have to set it with ChartScreen%@AE@%%@NL@%
  20279. %@NL@%
  20280. IF ChartErr = cBadScreen THEN   ' Check to make sure ChartScreen succeeded%@NL@%
  20281.         PRINT "Sorry --- There is a screen-mode problem in the Charting library"%@NL@%
  20282.         END%@NL@%
  20283. END IF%@NL@%
  20284. %@NL@%
  20285. %@AB@%' Initialize a default pie chart%@AE@%%@NL@%
  20286. %@AB@%                                                                                                                                                ' Pass Env (the environment variable),%@AE@%%@NL@%
  20287. DefaultChart Env, cPie, cPercent    ' the constant cPie (for Pie Chart) and%@NL@%
  20288. %@AB@%                                                                                                                                                ' cPercent (label slices with percentage)%@AE@%%@NL@%
  20289. %@NL@%
  20290. %@AB@%' Add Titles and some chart options. These assignments modify some default%@AE@%%@NL@%
  20291. %@AB@%' values set in the variable Env (of type ChartEnvironment) by DefaultChart%@AE@%%@NL@%
  20292. %@NL@%
  20293. %@NL@%
  20294. Env.MainTitle.Title = "Good Neighbor Grocery" ' Specifies text of chart title%@NL@%
  20295. Env.MainTitle.TitleColor = 15                 ' Specifies color of title text%@NL@%
  20296. Env.MainTitle.Justify = cCenter               ' How to align of title text%@NL@%
  20297. Env.SubTitle.Title = "Orange Juice Sales"     ' Text of chart subtitle%@NL@%
  20298. Env.SubTitle.TitleColor = 11                  ' Color of subtitle text%@NL@%
  20299. Env.SubTitle.Justify = cCenter                ' How to align of subtitle text%@NL@%
  20300. Env.ChartWindow.Border = cYes                 ' Specifies chart has no border%@NL@%
  20301. %@NL@%
  20302. %@AB@%' Call the pie-charting routine --- Arguments for call to ChartPie are:%@AE@%%@NL@%
  20303. %@AB@%' Env                 - Environment variable%@AE@%%@NL@%
  20304. %@AB@%' MonthCategories()   - Array containing Category labels%@AE@%%@NL@%
  20305. %@AB@%' OJvalues()          - Array containing Data values to chart%@AE@%%@NL@%
  20306. %@AB@%' Exploded()          - Integer array tells which pieces of the pie should%@AE@%%@NL@%
  20307. %@AB@%'                         be separated (non-zero=exploded, 0=not exploded)%@AE@%%@NL@%
  20308. %@AB@%' MONTHS              - Tells number of data values to chart%@AE@%%@NL@%
  20309. %@NL@%
  20310.         ChartPie Env, MonthCategories(), OJvalues(), Exploded(), MONTHS%@NL@%
  20311.         SLEEP%@NL@%
  20312. %@AB@%        '  If the rest of your program isn't graphic, reset original mode here%@AE@%%@NL@%
  20313. END%@NL@%
  20314. %@NL@%
  20315. %@AB@%' Simulate data generation for chart values and category labels%@AE@%%@NL@%
  20316. DATA 33,27,42,64,106,157,182,217,128,62,43,36%@NL@%
  20317. DATA "Jan","Feb","Mar","Apr","May","Jun","Jly","Aug","Sep","Oct","Nov","Dec"%@NL@%
  20318. %@NL@%
  20319. %@AB@%'============= Function to determine and set highest resolution ========%@AE@%%@NL@%
  20320. %@AB@%' The BestMode function uses a local error trap to check available modes,%@AE@%%@NL@%
  20321. %@AB@%' then assigns the integer representing the best mode for charting to its%@AE@%%@NL@%
  20322. %@AB@%' name so it is returned to the caller. The function terminate execution if%@AE@%%@NL@%
  20323. %@AB@%' the hardware doesn't support a mode appropriate for Presentation Graphics%@AE@%%@NL@%
  20324. %@AB@%'========================================================================%@AE@%%@NL@%
  20325. FUNCTION BestMode%@NL@%
  20326. %@NL@%
  20327. %@AB@%' Set a trap for an expected local error --- handled within the function%@AE@%%@NL@%
  20328. ON LOCAL ERROR GOTO ScreenError%@NL@%
  20329. %@NL@%
  20330. FOR TestValue = HIGHESTMODE TO 0 STEP -1%@NL@%
  20331.         DisplayError = FALSE%@NL@%
  20332.         SCREEN TestValue%@NL@%
  20333.         IF DisplayError = FALSE THEN%@NL@%
  20334.                 SELECT CASE TestValue%@NL@%
  20335.                         CASE 12, 13%@NL@%
  20336.                                 BestMode = 12%@NL@%
  20337.                         CASE 9, 10, 11%@NL@%
  20338.                                 BestMode = 9%@NL@%
  20339.                         CASE 8, 4, 3%@NL@%
  20340.                                 BestMode = TestValue%@NL@%
  20341.                         CASE 2, 7%@NL@%
  20342.                                 BestMode = 2%@NL@%
  20343.                         CASE 1%@NL@%
  20344.                                 BestMode = 1%@NL@%
  20345.                         CASE ELSE%@NL@%
  20346.                                 PRINT "Sorry, you need graphics to display charts"%@NL@%
  20347.                                 END%@NL@%
  20348.                 END SELECT%@NL@%
  20349.                 EXIT FUNCTION%@NL@%
  20350.         END IF%@NL@%
  20351. NEXT TestValue%@NL@%
  20352. %@AB@%' Note there is no need to turn off the local error handler. It is turned off%@AE@%%@NL@%
  20353. %@AB@%' automatically when control passes out of the function%@AE@%%@NL@%
  20354. %@NL@%
  20355. EXIT FUNCTION%@NL@%
  20356. %@AB@%'==================== | Local error handler code |=======================%@AE@%%@NL@%
  20357. %@AB@%' The ScreenError label identifies a local error handler relied in the%@AE@%%@NL@%
  20358. %@AB@%' BestMode function. Invalid SCREEN values generate Error # 5 (Illegal%@AE@%%@NL@%
  20359. %@AB@%' function call) --- so if that is not the error reset ERROR to the ERR%@AE@%%@NL@%
  20360. %@AB@%' value that was generated so the error can be passed to other, possibly%@AE@%%@NL@%
  20361. %@AB@%' more appropriate errors.%@AE@%%@NL@%
  20362. ScreenError:%@NL@%
  20363.         IF ERR = 5 THEN%@NL@%
  20364.                 DisplayError = TRUE%@NL@%
  20365.                 RESUME NEXT%@NL@%
  20366.         ELSE%@NL@%
  20367.                 ERROR ERR%@NL@%
  20368.         END IF%@NL@%
  20369. END FUNCTION%@NL@%
  20370. %@NL@%
  20371. %@NL@%
  20372. %@NL@%
  20373. %@2@%%@AH@%PGSCAT.BAS%@AE@%%@EH@%%@NL@%
  20374. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\PGSCAT.BAS%@AE@%%@NL@%
  20375. %@NL@%
  20376. %@AB@%' PGSCAT.BAS:  Create sample scatter diagram%@AE@%%@NL@%
  20377. %@NL@%
  20378. DEFINT A-Z%@NL@%
  20379. %@AB@%' $INCLUDE: 'CHRTB.BI'%@AE@%%@NL@%
  20380. CONST FALSE = 0, TRUE = NOT FALSE, MONTHS = 12%@NL@%
  20381. CONST HIGHESTMODE = 13, TEXTONLY = 0%@NL@%
  20382. %@NL@%
  20383. DIM Env AS ChartEnvironment                 ' See CHRTB.BI for declaration of                     ' the%@NL@%
  20384. %@AB@%                                                                                                                                                                                ' ChartEnvironment type%@AE@%%@NL@%
  20385. DIM OJvalues(1 TO MONTHS) AS SINGLE         ' Array for 1st data series%@NL@%
  20386. DIM HCvalues(1 TO MONTHS) AS SINGLE         ' Array for 2nd data series%@NL@%
  20387. DECLARE FUNCTION BestMode ()%@NL@%
  20388. %@NL@%
  20389. %@AB@%' Initialize the data arrays%@AE@%%@NL@%
  20390. FOR index = 1 TO MONTHS: READ OJvalues(index): NEXT index%@NL@%
  20391. FOR index = 1 TO MONTHS: READ HCvalues(index): NEXT index%@NL@%
  20392. %@NL@%
  20393. %@AB@%' Pass the value returned by the BestMode function to the Presentation%@AE@%%@NL@%
  20394. %@AB@%' Graphics routine ChartScreen to set the graphics mode for charting%@AE@%%@NL@%
  20395. %@NL@%
  20396. ChartScreen (BestMode)      ' Even if SCREEN is already set to an acceptable%@NL@%
  20397. %@AB@%                                                                                                                ' mode, you still have to set it with ChartScreen%@AE@%%@NL@%
  20398. IF ChartErr = cBadScreen THEN   ' Check to make sure ChartScreen succeeded%@NL@%
  20399.         PRINT "Sorry --- There is a screen-mode problem in the Charting library"%@NL@%
  20400.         END%@NL@%
  20401. END IF%@NL@%
  20402. %@NL@%
  20403. %@AB@%' Initialize a default pie chart%@AE@%%@NL@%
  20404. %@AB@%                                                                                                                                                        ' Pass Env (the environment variable);%@AE@%%@NL@%
  20405. DefaultChart Env, cScatter, cNoLines  ' constant cScatter (for Scatter Chart);%@NL@%
  20406. %@AB@%                                                                                                                                                        ' cNoLines (unjoined points)%@AE@%%@NL@%
  20407. %@NL@%
  20408. %@AB@%' Add Titles and some chart options. These assignments modify some default%@AE@%%@NL@%
  20409. %@AB@%' values set in the variable Env (of type ChartEnvironment) by DefaultChart%@AE@%%@NL@%
  20410. %@NL@%
  20411. Env.MainTitle.Title = "Good Neighbor Grocery" ' Specifies text of chart title%@NL@%
  20412. Env.MainTitle.TitleColor = 11                 ' Specifies color of title text%@NL@%
  20413. Env.MainTitle.Justify = cRight                ' How to align of title text%@NL@%
  20414. Env.SubTitle.Title = "OJ vs. Hot Chocolate"   ' Text of chart subtitle%@NL@%
  20415. Env.SubTitle.TitleColor = 15                  ' Color of subtitle text%@NL@%
  20416. Env.SubTitle.Justify = cRight                 ' How to align of subtitle text%@NL@%
  20417. Env.ChartWindow.Border = cNo                  ' Specifies chart has no border%@NL@%
  20418. %@NL@%
  20419. %@AB@%' The next two assignments label the x and y axes of the chart%@AE@%%@NL@%
  20420. Env.XAxis.AxisTitle.Title = "Orange Juice Sales"%@NL@%
  20421. Env.YAxis.AxisTitle.Title = "Hot Chocolate Sales"%@NL@%
  20422. %@NL@%
  20423. %@AB@%' Call the pie-charting routine --- Arguments for call to ChartPie are:%@AE@%%@NL@%
  20424. %@AB@%' Env                 - Environment variable%@AE@%%@NL@%
  20425. %@AB@%' OJvalues            - Array containing orange-juice sales values to chart%@AE@%%@NL@%
  20426. %@AB@%' HCvalues            - Array containing hot-chocolate sales values to chart%@AE@%%@NL@%
  20427. %@AB@%' MONTHS              - Tells number of data values to chart%@AE@%%@NL@%
  20428. %@NL@%
  20429.         ChartScatter Env, OJvalues(), HCvalues(), MONTHS%@NL@%
  20430.         SLEEP%@NL@%
  20431. %@AB@%        '  If the rest of your program isn't graphic, reset original mode here%@AE@%%@NL@%
  20432. END%@NL@%
  20433. %@NL@%
  20434. %@AB@%' Simulate data generation for chart values and category labels%@AE@%%@NL@%
  20435. DATA 33,27,42,64,106,157,182,217,128,62,43,36%@NL@%
  20436. DATA 37,37,30,19,10,5,2,1,7,15,28,39%@NL@%
  20437. %@NL@%
  20438. %@AB@%'============= Function to determine and set highest resolution ========%@AE@%%@NL@%
  20439. %@AB@%' The BestMode function uses a local error trap to check available modes,%@AE@%%@NL@%
  20440. %@AB@%' then assigns the integer representing the best mode for charting to its%@AE@%%@NL@%
  20441. %@AB@%' name so it is returned to the caller. The function terminate execution if%@AE@%%@NL@%
  20442. %@AB@%' the hardware doesn't support a mode appropriate for Presentation Graphics%@AE@%%@NL@%
  20443. %@AB@%'========================================================================%@AE@%%@NL@%
  20444. FUNCTION BestMode%@NL@%
  20445. %@NL@%
  20446. %@AB@%' Set a trap for an expected local error --- handled within the function%@AE@%%@NL@%
  20447. ON LOCAL ERROR GOTO ScreenError%@NL@%
  20448. %@NL@%
  20449. FOR TestValue = HIGHESTMODE TO 0 STEP -1%@NL@%
  20450.         DisplayError = FALSE%@NL@%
  20451.         SCREEN TestValue%@NL@%
  20452.         IF DisplayError = FALSE THEN%@NL@%
  20453.                 SELECT CASE TestValue%@NL@%
  20454.                         CASE 12, 13%@NL@%
  20455.                                 BestMode = 12%@NL@%
  20456.                         CASE 9, 10, 11%@NL@%
  20457.                                 BestMode = 9%@NL@%
  20458.                         CASE 8, 4, 3%@NL@%
  20459.                                 BestMode = TestValue%@NL@%
  20460.                         CASE 2, 7%@NL@%
  20461.                                 BestMode = 2%@NL@%
  20462.                         CASE 1%@NL@%
  20463.                                 BestMode = 1%@NL@%
  20464.                         CASE ELSE%@NL@%
  20465.                                 PRINT "Sorry, you need graphics to display charts"%@NL@%
  20466.                                 END%@NL@%
  20467.                 END SELECT%@NL@%
  20468.                 EXIT FUNCTION%@NL@%
  20469.         END IF%@NL@%
  20470. NEXT TestValue%@NL@%
  20471. %@AB@%' Note there is no need to turn off the local error handler. It is turned off%@AE@%%@NL@%
  20472. %@AB@%' automatically when control passes out of the function%@AE@%%@NL@%
  20473. %@NL@%
  20474. EXIT FUNCTION%@NL@%
  20475. %@AB@%'==================== | Local error handler code |=======================%@AE@%%@NL@%
  20476. %@AB@%' The ScreenError label identifies a local error handler relied in the%@AE@%%@NL@%
  20477. %@AB@%' BestMode function. Invalid SCREEN values generate Error # 5 (Illegal%@AE@%%@NL@%
  20478. %@AB@%' function call) --- so if that is not the error reset ERROR to the ERR%@AE@%%@NL@%
  20479. %@AB@%' value that was generated so the error can be passed to other, possibly%@AE@%%@NL@%
  20480. %@AB@%' more appropriate errors.%@AE@%%@NL@%
  20481. ScreenError:%@NL@%
  20482.         IF ERR = 5 THEN%@NL@%
  20483.                 DisplayError = TRUE%@NL@%
  20484.                 RESUME NEXT%@NL@%
  20485.         ELSE%@NL@%
  20486.                 ERROR ERR%@NL@%
  20487.         END IF%@NL@%
  20488. END FUNCTION%@NL@%
  20489. %@NL@%
  20490. %@NL@%
  20491. %@NL@%
  20492. %@2@%%@AH@%PLOTTER.BAS%@AE@%%@EH@%%@NL@%
  20493. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\PLOTTER.BAS%@AE@%%@NL@%
  20494. %@NL@%
  20495. %@AB@%' Values for keys on the numeric keypad and the spacebar:%@AE@%%@NL@%
  20496. CONST UP = 72, DOWN = 80, LFT = 75, RGHT = 77%@NL@%
  20497. CONST UPLFT = 71, UPRGHT = 73, DOWNLFT = 79, DOWNRGHT = 81%@NL@%
  20498. CONST SPACEBAR = " "%@NL@%
  20499. %@NL@%
  20500. %@AB@%' Null$ is the first character of the two-character INKEY$%@AE@%%@NL@%
  20501. %@AB@%' value returned for direction keys such as UP and DOWN:%@AE@%%@NL@%
  20502. Null$ = CHR$(0)%@NL@%
  20503. %@AB@%' Plot$ = "" means draw lines; Plot$ = "B" means%@AE@%%@NL@%
  20504. %@AB@%' move graphics cursor, but don't draw lines:%@AE@%%@NL@%
  20505. Plot$ = ""%@NL@%
  20506. %@NL@%
  20507. PRINT "Use the cursor movement keys to draw lines."%@NL@%
  20508. PRINT "Press spacebar to toggle line drawing on and off."%@NL@%
  20509. PRINT "Press <ENTER> to begin. Press q to end the program."%@NL@%
  20510. DO : LOOP WHILE INKEY$ = ""%@NL@%
  20511. %@NL@%
  20512. SCREEN 1%@NL@%
  20513. %@NL@%
  20514. DO%@NL@%
  20515.    SELECT CASE KeyVal$%@NL@%
  20516.       CASE Null$ + CHR$(UP)%@NL@%
  20517.          DRAW Plot$ + "C1 U2"%@NL@%
  20518.       CASE Null$ + CHR$(DOWN)%@NL@%
  20519.          DRAW Plot$ + "C1 D2"%@NL@%
  20520.       CASE Null$ + CHR$(LFT)%@NL@%
  20521.          DRAW Plot$ + "C2 L2"%@NL@%
  20522.       CASE Null$ + CHR$(RGHT)%@NL@%
  20523.          DRAW Plot$ + "C2 R2"%@NL@%
  20524.       CASE Null$ + CHR$(UPLFT)%@NL@%
  20525.          DRAW Plot$ + "C3 H2"%@NL@%
  20526.       CASE Null$ + CHR$(UPRGHT)%@NL@%
  20527.          DRAW Plot$ + "C3 E2"%@NL@%
  20528.       CASE Null$ + CHR$(DOWNLFT)%@NL@%
  20529.          DRAW Plot$ + "C3 G2"%@NL@%
  20530.       CASE Null$ + CHR$(DOWNRGHT)%@NL@%
  20531.          DRAW Plot$ + "C3 F2"%@NL@%
  20532.       CASE SPACEBAR%@NL@%
  20533.          IF Plot$ = "" THEN Plot$ = "B " ELSE Plot$ = ""%@NL@%
  20534.       CASE ELSE%@NL@%
  20535. %@AB@%         ' The user pressed some key other than one of the%@AE@%%@NL@%
  20536. %@AB@%         ' direction keys, the spacebar, or "q," so%@AE@%%@NL@%
  20537. %@AB@%         ' don't do anything.%@AE@%%@NL@%
  20538.    END SELECT%@NL@%
  20539. %@NL@%
  20540.    KeyVal$ = INKEY$%@NL@%
  20541. %@NL@%
  20542. LOOP UNTIL KeyVal$ = "q"%@NL@%
  20543. %@NL@%
  20544. SCREEN 0, 0                ' Restore the screen to 80-column%@NL@%
  20545. WIDTH 80                ' text mode and end.%@NL@%
  20546. END%@NL@%
  20547. %@NL@%
  20548. %@NL@%
  20549. %@NL@%
  20550. %@2@%%@AH@%QLBDUMP.BAS%@AE@%%@EH@%%@NL@%
  20551. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\QLBDUMP.BAS%@AE@%%@NL@%
  20552. %@NL@%
  20553. %@AB@%'This program prints the names of Quick library procedures.%@AE@%%@NL@%
  20554. %@NL@%
  20555. DECLARE SUB DumpSym (SymStart AS INTEGER, QHdrPos AS LONG)%@NL@%
  20556. %@NL@%
  20557. TYPE ExeHdr                   'Part of DOS .EXE header.%@NL@%
  20558.      other1    AS STRING * 8  'Other header information.%@NL@%
  20559.      CParHdr   AS INTEGER     'Size of header in paragraphs.%@NL@%
  20560.      other2    AS STRING * 10 'Other header information.%@NL@%
  20561.      IP         AS INTEGER    'Initial IP value.%@NL@%
  20562.      CS         AS INTEGER    'Initial (relative) CS value.%@NL@%
  20563. END TYPE%@NL@%
  20564. TYPE QBHdr                    'QLB header.%@NL@%
  20565.      QBHead    AS STRING * 6  'QBX specific heading.%@NL@%
  20566.      Magic     AS INTEGER     'Magic word: identifies file as a Quick library.%@NL@%
  20567.      SymStart  AS INTEGER     'Offset from header to first code symbol.%@NL@%
  20568.      DatStart  AS INTEGER     'Offset from header to first data symbol.%@NL@%
  20569. END TYPE%@NL@%
  20570. %@NL@%
  20571. TYPE QbSym                    'QuickLib symbol entry.%@NL@%
  20572.      Flags     AS INTEGER     'Symbol flags.%@NL@%
  20573.      NameStart AS INTEGER     'Offset into name table.%@NL@%
  20574.      other     AS STRING * 4  'Other header information.%@NL@%
  20575. END TYPE%@NL@%
  20576. %@NL@%
  20577. DIM EHdr AS ExeHdr, Qhdr AS QBHdr, QHdrPos AS LONG%@NL@%
  20578. %@NL@%
  20579. INPUT "Enter Quick library file name: ", FileName$%@NL@%
  20580. FileName$ = UCASE$(FileName$)%@NL@%
  20581. IF INSTR(FileName$, ".QLB") = 0 THEN FileName$ = FileName$ + ".QLB"%@NL@%
  20582. INPUT "Enter output file name or press ENTER for screen: ", OutFile$%@NL@%
  20583. OutFile$ = UCASE$(OutFile$)%@NL@%
  20584. IF OutFile$ = "" THEN OutFile$ = "CON"%@NL@%
  20585. %@NL@%
  20586. IF DIR$(FileName$) = "" THEN PRINT "File "; FileName$; " not found.": END%@NL@%
  20587. %@NL@%
  20588. OPEN FileName$ FOR BINARY AS #1%@NL@%
  20589. OPEN OutFile$ FOR OUTPUT AS #2%@NL@%
  20590. %@NL@%
  20591. GET #1, , EHdr                     'Read the EXE format header.%@NL@%
  20592. TEMP1& = EHdr.CParHdr + EHdr.CS    'Use a LONG temp to prevent overflow.%@NL@%
  20593. QHdrPos = TEMP1& * 16 + EHdr.IP + 1%@NL@%
  20594. %@NL@%
  20595. GET #1, QHdrPos, Qhdr              'Read the QuickLib format header.%@NL@%
  20596. IF Qhdr.Magic <> &H6C75 THEN PRINT "Not a valid QBX Quick-Library": END%@NL@%
  20597. %@NL@%
  20598. PRINT #2, "Code Symbols:": PRINT #2,%@NL@%
  20599. DumpSym Qhdr.SymStart, QHdrPos     'Dump code symbols.%@NL@%
  20600. PRINT #2,%@NL@%
  20601. PRINT #2, "Data Symbols:": PRINT #2, ""%@NL@%
  20602. DumpSym Qhdr.DatStart, QHdrPos     'Dump data symbols.%@NL@%
  20603. PRINT #2,%@NL@%
  20604. %@NL@%
  20605. END%@NL@%
  20606. %@NL@%
  20607. SUB DumpSym (SymStart AS INTEGER, QHdrPos AS LONG)%@NL@%
  20608.         DIM QlbSym AS QbSym%@NL@%
  20609.         DIM NextSym AS LONG, CurrentSym AS LONG%@NL@%
  20610. %@NL@%
  20611. %@AB@%    'Calculate the location of the first symbol entry, then read that entry.%@AE@%%@NL@%
  20612.         NextSym = QHdrPos + SymStart%@NL@%
  20613.         GET #1, NextSym, QlbSym%@NL@%
  20614. DO%@NL@%
  20615.         NextSym = SEEK(1)         'Save the location of the next symbol.%@NL@%
  20616.                 CurrentSym = QHdrPos + QlbSym.NameStart%@NL@%
  20617.         SEEK #1, CurrentSym       'Use SEEK to move to the name%@NL@%
  20618. %@AB@%                                  'for the current symbol entry.%@AE@%%@NL@%
  20619.         Prospect$ = INPUT$(40, 1) 'Read the longest legal string,%@NL@%
  20620. %@AB@%                                  'plus one additional byte for%@AE@%%@NL@%
  20621. %@AB@%                                  'the final null character (CHR$(0)).%@AE@%%@NL@%
  20622. %@NL@%
  20623. %@AB@%        'Extract the null-terminated name.%@AE@%%@NL@%
  20624.                 SName$ = LEFT$(Prospect$, INSTR(Prospect$, CHR$(0)))%@NL@%
  20625. %@NL@%
  20626. %@AB@%        'Print only those names that do not begin with "__", "$", or "b$"%@AE@%%@NL@%
  20627. %@AB@%        'as these names are usually considered reserved.%@AE@%%@NL@%
  20628.                 T$ = LEFT$(SName$, 2)%@NL@%
  20629.                 IF T$ <> "__" AND LEFT$(SName$, 1) <> "$" AND UCASE$(T$) <> "B$" THEN%@NL@%
  20630.                         PRINT #2, "  " + SName$%@NL@%
  20631.                 END IF%@NL@%
  20632. %@NL@%
  20633.         GET #1, NextSym, QlbSym    'Read a symbol entry.%@NL@%
  20634.     LOOP WHILE QlbSym.Flags        'Flags=0 (false) means end of table.%@NL@%
  20635. %@NL@%
  20636. END SUB%@NL@%
  20637. %@NL@%
  20638. %@NL@%
  20639. %@2@%%@AH@%REMLINE.BAS%@AE@%%@EH@%%@NL@%
  20640. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\REMLINE.BAS%@AE@%%@NL@%
  20641. %@NL@%
  20642. DEFINT A-Z%@NL@%
  20643. %@AB@%'%@AE@%%@NL@%
  20644. %@AB@%'   Microsoft RemLine - Line Number Removal Utility%@AE@%%@NL@%
  20645. %@AB@%'   Copyright (C) Microsoft Corporation   - 1985, 1986, 1987%@AE@%%@NL@%
  20646. %@AB@%'%@AE@%%@NL@%
  20647. %@AB@%'   REMLINE.BAS is a program to remove line numbers from Microsoft BASIC%@AE@%%@NL@%
  20648. %@AB@%'   Programs. It removes only those line numbers that are not the object%@AE@%%@NL@%
  20649. %@AB@%'   of one of the following statements: GOSUB, RETURN, GOTO, THEN, ELSE,%@AE@%%@NL@%
  20650. %@AB@%'   RESUME, RESTORE, or RUN.%@AE@%%@NL@%
  20651. %@AB@%'%@AE@%%@NL@%
  20652. %@AB@%'   REMLINE is run by typing%@AE@%%@NL@%
  20653. %@AB@%'%@AE@%%@NL@%
  20654. %@AB@%'      REMLINE [<input> [, <output>]]%@AE@%%@NL@%
  20655. %@AB@%'%@AE@%%@NL@%
  20656. %@AB@%'   where <input> is the name of the file to be processed and <output>%@AE@%%@NL@%
  20657. %@AB@%'   is the name of the file or device to receive the reformatted output.%@AE@%%@NL@%
  20658. %@AB@%'   If no extension is given, .BAS is assumed (except for output devices).%@AE@%%@NL@%
  20659. %@AB@%'   If file names are not given, REMLINE prompts for file names. If both%@AE@%%@NL@%
  20660. %@AB@%'   file names are the same, REMLINE saves the original file with the%@AE@%%@NL@%
  20661. %@AB@%'   extension .BAK.%@AE@%%@NL@%
  20662. %@AB@%'%@AE@%%@NL@%
  20663. %@AB@%'   REMLINE makes several assumptions about the program:%@AE@%%@NL@%
  20664. %@AB@%'%@AE@%%@NL@%
  20665. %@AB@%'     1. It must be correct syntactically, and must run in BASICA or%@AE@%%@NL@%
  20666. %@AB@%'        GWBASIC interpreter.%@AE@%%@NL@%
  20667. %@AB@%'     2. There is a 400 line limit. To process larger files, change%@AE@%%@NL@%
  20668. %@AB@%'        MaxLines constant.%@AE@%%@NL@%
  20669. %@AB@%'     3. The first number encountered on a line is considered a line%@AE@%%@NL@%
  20670. %@AB@%'        number; thus some continuation lines (in a compiler specific%@AE@%%@NL@%
  20671. %@AB@%'        constructiion) may not be handled correctly.%@AE@%%@NL@%
  20672. %@AB@%'     4. REMLINE can handle simple statements that test the ERL function%@AE@%%@NL@%
  20673. %@AB@%'        using  relational operators such as =, <, and >. For example,%@AE@%%@NL@%
  20674. %@AB@%'        the following statement is handled correctly:%@AE@%%@NL@%
  20675. %@AB@%'%@AE@%%@NL@%
  20676. %@AB@%'             IF ERL = 100 THEN END%@AE@%%@NL@%
  20677. %@AB@%'%@AE@%%@NL@%
  20678. %@AB@%'        Line 100 is not removed from the source code. However, more%@AE@%%@NL@%
  20679. %@AB@%'        complex expressions that contain the +, -, AND, OR, XOR, EQV,%@AE@%%@NL@%
  20680. %@AB@%'        MOD, or IMP operators may not be handled correctly. For example,%@AE@%%@NL@%
  20681. %@AB@%'        in the following statement REMLINE does not recognize line 105%@AE@%%@NL@%
  20682. %@AB@%'        as a referenced line number and removes it from the source code:%@AE@%%@NL@%
  20683. %@AB@%'%@AE@%%@NL@%
  20684. %@AB@%'             IF ERL + 5 = 105 THEN END%@AE@%%@NL@%
  20685. %@AB@%'%@AE@%%@NL@%
  20686. %@AB@%'   If you do not like the way REMLINE formats its output, you can modify%@AE@%%@NL@%
  20687. %@AB@%'   the output lines in SUB GenOutFile. An example is shown in comments.%@AE@%%@NL@%
  20688. %@NL@%
  20689. %@AB@%' Function and Subprogram declarations%@AE@%%@NL@%
  20690. %@NL@%
  20691. DECLARE FUNCTION GetToken$ (Search$, Delim$)%@NL@%
  20692. DECLARE FUNCTION StrSpn% (InString$, Separator$)%@NL@%
  20693. DECLARE FUNCTION StrBrk% (InString$, Separator$)%@NL@%
  20694. DECLARE FUNCTION IsDigit% (Char$)%@NL@%
  20695. DECLARE SUB GetFileNames ()%@NL@%
  20696. DECLARE SUB BuildTable ()%@NL@%
  20697. DECLARE SUB GenOutFile ()%@NL@%
  20698. DECLARE SUB InitKeyTable ()%@NL@%
  20699. %@NL@%
  20700. %@AB@%' Global and constant data%@AE@%%@NL@%
  20701. %@NL@%
  20702. CONST TRUE = -1%@NL@%
  20703. CONST false = 0%@NL@%
  20704. CONST MaxLines = 400%@NL@%
  20705. %@NL@%
  20706. DIM SHARED LineTable!(MaxLines)%@NL@%
  20707. DIM SHARED LineCount%@NL@%
  20708. DIM SHARED Seps$, InputFile$, OutputFile$, TmpFile$%@NL@%
  20709. %@NL@%
  20710. %@AB@%' Keyword search data%@AE@%%@NL@%
  20711. %@NL@%
  20712. CONST KeyWordCount = 9%@NL@%
  20713. DIM SHARED KeyWordTable$(KeyWordCount)%@NL@%
  20714. %@NL@%
  20715. KeyData:%@NL@%
  20716.    DATA THEN, ELSE, GOSUB, GOTO, RESUME, RETURN, RESTORE, RUN, ERL, ""%@NL@%
  20717. %@NL@%
  20718. %@AB@%' Start of module-level program code%@AE@%%@NL@%
  20719. %@NL@%
  20720.    Seps$ = " ,:=<>()" + CHR$(9)%@NL@%
  20721.    InitKeyTable%@NL@%
  20722.    GetFileNames%@NL@%
  20723.    ON ERROR GOTO FileErr1%@NL@%
  20724.    OPEN InputFile$ FOR INPUT AS 1%@NL@%
  20725.    ON ERROR GOTO 0%@NL@%
  20726.    COLOR 7: PRINT "Working"; : COLOR 23: PRINT " . . .": COLOR 7: PRINT%@NL@%
  20727.    BuildTable%@NL@%
  20728.    CLOSE #1%@NL@%
  20729.    OPEN InputFile$ FOR INPUT AS 1%@NL@%
  20730.    ON ERROR GOTO FileErr2%@NL@%
  20731.    OPEN OutputFile$ FOR OUTPUT AS 2%@NL@%
  20732.    ON ERROR GOTO 0%@NL@%
  20733.    GenOutFile%@NL@%
  20734.    CLOSE #1, #2%@NL@%
  20735.    IF OutputFile$ <> "CON" THEN CLS%@NL@%
  20736. %@NL@%
  20737. END%@NL@%
  20738. %@NL@%
  20739. FileErr1:%@NL@%
  20740.    CLS%@NL@%
  20741.    PRINT "      Invalid file name": PRINT%@NL@%
  20742.    INPUT "      New input file name (ENTER to terminate): ", InputFile$%@NL@%
  20743.    IF InputFile$ = "" THEN END%@NL@%
  20744. FileErr2:%@NL@%
  20745.    INPUT "      Output file name (ENTER to print to screen) :", OutputFile$%@NL@%
  20746.    PRINT%@NL@%
  20747.    IF (OutputFile$ = "") THEN OutputFile$ = "CON"%@NL@%
  20748.    IF TmpFile$ = "" THEN%@NL@%
  20749.       RESUME%@NL@%
  20750.    ELSE%@NL@%
  20751.       TmpFile$ = ""%@NL@%
  20752.       RESUME NEXT%@NL@%
  20753.    END IF%@NL@%
  20754. %@NL@%
  20755. %@AB@%'%@AE@%%@NL@%
  20756. %@AB@%' BuildTable:%@AE@%%@NL@%
  20757. %@AB@%'   Examines the entire text file looking for line numbers that are%@AE@%%@NL@%
  20758. %@AB@%'   the object of GOTO, GOSUB, etc. As each is found, it is entered%@AE@%%@NL@%
  20759. %@AB@%'   into a table of line numbers. The table is used during a second%@AE@%%@NL@%
  20760. %@AB@%'   pass (see GenOutFile), when all line numbers not in the list%@AE@%%@NL@%
  20761. %@AB@%'   are removed.%@AE@%%@NL@%
  20762. %@AB@%' Input:%@AE@%%@NL@%
  20763. %@AB@%'   Uses globals KeyWordTable$, KeyWordCount, and Seps$%@AE@%%@NL@%
  20764. %@AB@%' Output:%@AE@%%@NL@%
  20765. %@AB@%'   Modefies LineTable! and LineCount%@AE@%%@NL@%
  20766. %@AB@%'%@AE@%%@NL@%
  20767. SUB BuildTable STATIC%@NL@%
  20768. %@NL@%
  20769.    DO WHILE NOT EOF(1)%@NL@%
  20770. %@AB@%      ' Get line and first token%@AE@%%@NL@%
  20771.       LINE INPUT #1, InLin$%@NL@%
  20772.       token$ = GetToken$(InLin$, Seps$)%@NL@%
  20773.       DO WHILE (token$ <> "")%@NL@%
  20774.          FOR KeyIndex = 1 TO KeyWordCount%@NL@%
  20775. %@AB@%            ' See if token is keyword%@AE@%%@NL@%
  20776.             IF (KeyWordTable$(KeyIndex) = UCASE$(token$)) THEN%@NL@%
  20777. %@AB@%               ' Get possible line number after keyword%@AE@%%@NL@%
  20778.                token$ = GetToken$("", Seps$)%@NL@%
  20779. %@AB@%               ' Check each token to see if it is a line number%@AE@%%@NL@%
  20780. %@AB@%               ' (the LOOP is necessary for the multiple numbers%@AE@%%@NL@%
  20781. %@AB@%               ' of ON GOSUB or ON GOTO). A non-numeric token will%@AE@%%@NL@%
  20782. %@AB@%               ' terminate search.%@AE@%%@NL@%
  20783.                DO WHILE (IsDigit(LEFT$(token$, 1)))%@NL@%
  20784.                   LineCount = LineCount + 1%@NL@%
  20785.                   LineTable!(LineCount) = VAL(token$)%@NL@%
  20786.                   token$ = GetToken$("", Seps$)%@NL@%
  20787.                   IF token$ <> "" THEN KeyIndex = 0%@NL@%
  20788.                LOOP%@NL@%
  20789.             END IF%@NL@%
  20790.          NEXT KeyIndex%@NL@%
  20791. %@AB@%         ' Get next token%@AE@%%@NL@%
  20792.          token$ = GetToken$("", Seps$)%@NL@%
  20793.       LOOP%@NL@%
  20794.    LOOP%@NL@%
  20795. %@NL@%
  20796. END SUB%@NL@%
  20797. %@NL@%
  20798. %@AB@%'%@AE@%%@NL@%
  20799. %@AB@%' GenOutFile:%@AE@%%@NL@%
  20800. %@AB@%'  Generates an output file with unreferenced line numbers removed.%@AE@%%@NL@%
  20801. %@AB@%' Input:%@AE@%%@NL@%
  20802. %@AB@%'  Uses globals LineTable!, LineCount, and Seps$%@AE@%%@NL@%
  20803. %@AB@%' Output:%@AE@%%@NL@%
  20804. %@AB@%'  Processed file%@AE@%%@NL@%
  20805. %@AB@%'%@AE@%%@NL@%
  20806. SUB GenOutFile STATIC%@NL@%
  20807. %@NL@%
  20808. %@AB@%   ' Speed up by eliminating comma and colon (can't separate first token)%@AE@%%@NL@%
  20809.    Sep$ = " " + CHR$(9)%@NL@%
  20810.    DO WHILE NOT EOF(1)%@NL@%
  20811.       LINE INPUT #1, InLin$%@NL@%
  20812.       IF (InLin$ <> "") THEN%@NL@%
  20813. %@AB@%         ' Get first token and process if it is a line number%@AE@%%@NL@%
  20814.          token$ = GetToken$(InLin$, Sep$)%@NL@%
  20815.          IF IsDigit(LEFT$(token$, 1)) THEN%@NL@%
  20816.             LineNumber! = VAL(token$)%@NL@%
  20817.             FoundNumber = false%@NL@%
  20818. %@AB@%            ' See if line number is in table of referenced line numbers%@AE@%%@NL@%
  20819.             FOR index = 1 TO LineCount%@NL@%
  20820.                IF (LineNumber! = LineTable!(index)) THEN%@NL@%
  20821.                   FoundNumber = TRUE%@NL@%
  20822.                END IF%@NL@%
  20823.             NEXT index%@NL@%
  20824. %@AB@%            ' Modify line strings%@AE@%%@NL@%
  20825.             IF (NOT FoundNumber) THEN%@NL@%
  20826.                token$ = SPACE$(LEN(token$))%@NL@%
  20827.                MID$(InLin$, StrSpn(InLin$, Sep$), LEN(token$)) = token$%@NL@%
  20828.             END IF%@NL@%
  20829. %@NL@%
  20830. %@AB@%            ' You can replace the previous lines with your own%@AE@%%@NL@%
  20831. %@AB@%            ' code to reformat output. For example, try these lines:%@AE@%%@NL@%
  20832. %@NL@%
  20833. %@AB@%            'TmpPos1 = StrSpn(InLin$, Sep$) + LEN(Token$)%@AE@%%@NL@%
  20834. %@AB@%            'TmpPos2 = TmpPos1 + StrSpn(MID$(InLin$, TmpPos1), Sep$)%@AE@%%@NL@%
  20835. %@AB@%            '%@AE@%%@NL@%
  20836. %@AB@%            'IF FoundNumber THEN%@AE@%%@NL@%
  20837. %@AB@%            '   InLin$ = LEFT$(InLin$, TmpPos1 - 1) + CHR$(9) + MID$(InLin$, TmpPos2)%@AE@%%@NL@%
  20838. %@AB@%            'ELSE%@AE@%%@NL@%
  20839. %@AB@%            '   InLin$ = CHR$(9) + MID$(InLin$, TmpPos2)%@AE@%%@NL@%
  20840. %@AB@%            'END IF%@AE@%%@NL@%
  20841. %@NL@%
  20842.          END IF%@NL@%
  20843.       END IF%@NL@%
  20844. %@AB@%      ' Print line to file or console (PRINT is faster than console device)%@AE@%%@NL@%
  20845.       IF OutputFile$ = "CON" THEN%@NL@%
  20846.          PRINT InLin$%@NL@%
  20847.       ELSE%@NL@%
  20848.          PRINT #2, InLin$%@NL@%
  20849.       END IF%@NL@%
  20850.    LOOP%@NL@%
  20851. %@NL@%
  20852. END SUB%@NL@%
  20853. %@NL@%
  20854. %@AB@%'%@AE@%%@NL@%
  20855. %@AB@%' GetFileNames:%@AE@%%@NL@%
  20856. %@AB@%'  Gets a file name from COMMAND$ or by prompting the user.%@AE@%%@NL@%
  20857. %@AB@%' Input:%@AE@%%@NL@%
  20858. %@AB@%'  Used Command$ or user input%@AE@%%@NL@%
  20859. %@AB@%' Output:%@AE@%%@NL@%
  20860. %@AB@%'  Defines InputFiles$ and OutputFiles$%@AE@%%@NL@%
  20861. %@AB@%'%@AE@%%@NL@%
  20862. SUB GetFileNames STATIC%@NL@%
  20863. %@NL@%
  20864.    IF (COMMAND$ = "") THEN%@NL@%
  20865.       CLS%@NL@%
  20866.       PRINT " Microsoft RemLine: Line Number Removal Utility"%@NL@%
  20867.       PRINT "       (.BAS assumed if no extension given)"%@NL@%
  20868.       PRINT%@NL@%
  20869.       INPUT "      Input file name (ENTER to terminate): ", InputFile$%@NL@%
  20870.       IF InputFile$ = "" THEN END%@NL@%
  20871.       INPUT "      Output file name (ENTER to print to screen): ", OutputFile$%@NL@%
  20872.       PRINT%@NL@%
  20873.       IF (OutputFile$ = "") THEN OutputFile$ = "CON"%@NL@%
  20874.    ELSE%@NL@%
  20875.       InputFile$ = UCASE$(GetToken$(COMMAND$, Seps$))%@NL@%
  20876.       OutputFile$ = UCASE$(GetToken$("", Seps$))%@NL@%
  20877.       IF (OutputFile$ = "") THEN%@NL@%
  20878.          INPUT "      Output file name (ENTER to print to screen): ", OutputFile$%@NL@%
  20879.          PRINT%@NL@%
  20880.          IF (OutputFile$ = "") THEN OutputFile$ = "CON"%@NL@%
  20881.       END IF%@NL@%
  20882.    END IF%@NL@%
  20883.    IF INSTR(InputFile$, ".") = 0 THEN%@NL@%
  20884.       InputFile$ = InputFile$ + ".BAS"%@NL@%
  20885.    END IF%@NL@%
  20886.    IF INSTR(OutputFile$, ".") = 0 THEN%@NL@%
  20887.       SELECT CASE OutputFile$%@NL@%
  20888.          CASE "CON", "SCRN", "PRN", "COM1", "COM2", "LPT1", "LPT2", "LPT3"%@NL@%
  20889.             EXIT SUB%@NL@%
  20890.          CASE ELSE%@NL@%
  20891.             OutputFile$ = OutputFile$ + ".BAS"%@NL@%
  20892.       END SELECT%@NL@%
  20893.    END IF%@NL@%
  20894.    DO WHILE InputFile$ = OutputFile$%@NL@%
  20895.       TmpFile$ = LEFT$(InputFile$, INSTR(InputFile$, ".")) + "BAK"%@NL@%
  20896.       ON ERROR GOTO FileErr1%@NL@%
  20897.       NAME InputFile$ AS TmpFile$%@NL@%
  20898.       ON ERROR GOTO 0%@NL@%
  20899.       IF TmpFile$ <> "" THEN InputFile$ = TmpFile$%@NL@%
  20900.    LOOP%@NL@%
  20901. %@NL@%
  20902. END SUB%@NL@%
  20903. %@NL@%
  20904. %@AB@%'%@AE@%%@NL@%
  20905. %@AB@%' GetToken$:%@AE@%%@NL@%
  20906. %@AB@%'  Extracts tokens from a string. A token is a word that is surrounded%@AE@%%@NL@%
  20907. %@AB@%'  by separators, such as spaces or commas. Tokens are extracted and%@AE@%%@NL@%
  20908. %@AB@%'  analyzed when parsing sentences or commands. To use the GetToken$%@AE@%%@NL@%
  20909. %@AB@%'  function, pass the string to be parsed on the first call, then pass%@AE@%%@NL@%
  20910. %@AB@%'  a null string on subsequent calls until the function returns a null%@AE@%%@NL@%
  20911. %@AB@%'  to indicate that the entire string has been parsed.%@AE@%%@NL@%
  20912. %@AB@%' Input:%@AE@%%@NL@%
  20913. %@AB@%'  Search$ = string to search%@AE@%%@NL@%
  20914. %@AB@%'  Delim$  = String of separators%@AE@%%@NL@%
  20915. %@AB@%' Output:%@AE@%%@NL@%
  20916. %@AB@%'  GetToken$ = next token%@AE@%%@NL@%
  20917. %@AB@%'%@AE@%%@NL@%
  20918. FUNCTION GetToken$ (Search$, Delim$) STATIC%@NL@%
  20919. %@NL@%
  20920. %@AB@%   ' Note that SaveStr$ and BegPos must be static from call to call%@AE@%%@NL@%
  20921. %@AB@%   ' (other variables are only static for efficiency).%@AE@%%@NL@%
  20922. %@AB@%   ' If first call, make a copy of the string%@AE@%%@NL@%
  20923.    IF (Search$ <> "") THEN%@NL@%
  20924.       BegPos = 1%@NL@%
  20925.       SaveStr$ = Search$%@NL@%
  20926.    END IF%@NL@%
  20927. %@NL@%
  20928. %@AB@%   ' Find the start of the next token%@AE@%%@NL@%
  20929.    NewPos = StrSpn(MID$(SaveStr$, BegPos, LEN(SaveStr$)), Delim$)%@NL@%
  20930.    IF NewPos THEN%@NL@%
  20931. %@AB@%      ' Set position to start of token%@AE@%%@NL@%
  20932.       BegPos = NewPos + BegPos - 1%@NL@%
  20933.    ELSE%@NL@%
  20934. %@AB@%      ' If no new token, quit and return null%@AE@%%@NL@%
  20935.       GetToken$ = ""%@NL@%
  20936.       EXIT FUNCTION%@NL@%
  20937.    END IF%@NL@%
  20938. %@NL@%
  20939. %@AB@%   ' Find end of token%@AE@%%@NL@%
  20940.    NewPos = StrBrk(MID$(SaveStr$, BegPos, LEN(SaveStr$)), Delim$)%@NL@%
  20941.    IF NewPos THEN%@NL@%
  20942. %@AB@%      ' Set position to end of token%@AE@%%@NL@%
  20943.       NewPos = BegPos + NewPos - 1%@NL@%
  20944.    ELSE%@NL@%
  20945. %@AB@%      ' If no end of token, return set to end a value%@AE@%%@NL@%
  20946.       NewPos = LEN(SaveStr$) + 1%@NL@%
  20947.    END IF%@NL@%
  20948. %@AB@%   ' Cut token out of search string%@AE@%%@NL@%
  20949.    GetToken$ = MID$(SaveStr$, BegPos, NewPos - BegPos)%@NL@%
  20950. %@AB@%   ' Set new starting position%@AE@%%@NL@%
  20951.    BegPos = NewPos%@NL@%
  20952. %@NL@%
  20953. END FUNCTION%@NL@%
  20954. %@NL@%
  20955. %@AB@%'%@AE@%%@NL@%
  20956. %@AB@%' InitKeyTable:%@AE@%%@NL@%
  20957. %@AB@%'  Initializes a keyword table. Keywords must be recognized so that%@AE@%%@NL@%
  20958. %@AB@%'  line numbers can be distinguished from numeric constants.%@AE@%%@NL@%
  20959. %@AB@%' Input:%@AE@%%@NL@%
  20960. %@AB@%'  Uses KeyData%@AE@%%@NL@%
  20961. %@AB@%' Output:%@AE@%%@NL@%
  20962. %@AB@%'  Modifies global array KeyWordTable$%@AE@%%@NL@%
  20963. %@AB@%'%@AE@%%@NL@%
  20964. SUB InitKeyTable STATIC%@NL@%
  20965. %@NL@%
  20966.    RESTORE KeyData%@NL@%
  20967.    FOR Count = 1 TO KeyWordCount%@NL@%
  20968.       READ KeyWord$%@NL@%
  20969.       KeyWordTable$(Count) = KeyWord$%@NL@%
  20970.    NEXT%@NL@%
  20971. %@NL@%
  20972. END SUB%@NL@%
  20973. %@NL@%
  20974. %@AB@%'%@AE@%%@NL@%
  20975. %@AB@%' IsDigit:%@AE@%%@NL@%
  20976. %@AB@%'  Returns true if character passed is a decimal digit. Since any%@AE@%%@NL@%
  20977. %@AB@%'  BASIC token starting with a digit is a number, the function only%@AE@%%@NL@%
  20978. %@AB@%'  needs to check the first digit. Doesn't check for negative numbers,%@AE@%%@NL@%
  20979. %@AB@%'  but that's not needed here.%@AE@%%@NL@%
  20980. %@AB@%' Input:%@AE@%%@NL@%
  20981. %@AB@%'  Char$ - initial character of string to check%@AE@%%@NL@%
  20982. %@AB@%' Output:%@AE@%%@NL@%
  20983. %@AB@%'  IsDigit - true if within 0 - 9%@AE@%%@NL@%
  20984. %@AB@%'%@AE@%%@NL@%
  20985. FUNCTION IsDigit (Char$) STATIC%@NL@%
  20986. %@NL@%
  20987.    IF (Char$ = "") THEN%@NL@%
  20988.       IsDigit = false%@NL@%
  20989.    ELSE%@NL@%
  20990.       CharAsc = ASC(Char$)%@NL@%
  20991.       IsDigit = (CharAsc >= ASC("0")) AND (CharAsc <= ASC("9"))%@NL@%
  20992.    END IF%@NL@%
  20993. %@NL@%
  20994. END FUNCTION%@NL@%
  20995. %@NL@%
  20996. %@AB@%'%@AE@%%@NL@%
  20997. %@AB@%' StrBrk:%@AE@%%@NL@%
  20998. %@AB@%'  Searches InString$ to find the first character from among those in%@AE@%%@NL@%
  20999. %@AB@%'  Separator$. Returns the index of that character. This function can%@AE@%%@NL@%
  21000. %@AB@%'  be used to find the end of a token.%@AE@%%@NL@%
  21001. %@AB@%' Input:%@AE@%%@NL@%
  21002. %@AB@%'  InString$ = string to search%@AE@%%@NL@%
  21003. %@AB@%'  Separator$ = characters to search for%@AE@%%@NL@%
  21004. %@AB@%' Output:%@AE@%%@NL@%
  21005. %@AB@%'  StrBrk = index to first match in InString$ or 0 if none match%@AE@%%@NL@%
  21006. %@AB@%'%@AE@%%@NL@%
  21007. FUNCTION StrBrk (InString$, Separator$) STATIC%@NL@%
  21008. %@NL@%
  21009.    Ln = LEN(InString$)%@NL@%
  21010.    BegPos = 1%@NL@%
  21011. %@AB@%   ' Look for end of token (first character that is a delimiter).%@AE@%%@NL@%
  21012.    DO WHILE INSTR(Separator$, MID$(InString$, BegPos, 1)) = 0%@NL@%
  21013.       IF BegPos > Ln THEN%@NL@%
  21014.          StrBrk = 0%@NL@%
  21015.          EXIT FUNCTION%@NL@%
  21016.       ELSE%@NL@%
  21017.          BegPos = BegPos + 1%@NL@%
  21018.       END IF%@NL@%
  21019.    LOOP%@NL@%
  21020.    StrBrk = BegPos%@NL@%
  21021. %@NL@%
  21022. END FUNCTION%@NL@%
  21023. %@NL@%
  21024. %@AB@%'%@AE@%%@NL@%
  21025. %@AB@%' StrSpn:%@AE@%%@NL@%
  21026. %@AB@%'  Searches InString$ to find the first character that is not one of%@AE@%%@NL@%
  21027. %@AB@%'  those in Separator$. Returns the index of that character. This%@AE@%%@NL@%
  21028. %@AB@%'  function can be used to find the start of a token.%@AE@%%@NL@%
  21029. %@AB@%' Input:%@AE@%%@NL@%
  21030. %@AB@%'  InString$ = string to search%@AE@%%@NL@%
  21031. %@AB@%'  Separator$ = characters to search for%@AE@%%@NL@%
  21032. %@AB@%' Output:%@AE@%%@NL@%
  21033. %@AB@%'  StrSpn = index to first nonmatch in InString$ or 0 if all match%@AE@%%@NL@%
  21034. %@AB@%'%@AE@%%@NL@%
  21035. FUNCTION StrSpn% (InString$, Separator$) STATIC%@NL@%
  21036. %@NL@%
  21037.    Ln = LEN(InString$)%@NL@%
  21038.    BegPos = 1%@NL@%
  21039. %@AB@%   ' Look for start of a token (character that isn't a delimiter).%@AE@%%@NL@%
  21040.    DO WHILE INSTR(Separator$, MID$(InString$, BegPos, 1))%@NL@%
  21041.       IF BegPos > Ln THEN%@NL@%
  21042.          StrSpn = 0%@NL@%
  21043.          EXIT FUNCTION%@NL@%
  21044.       ELSE%@NL@%
  21045.          BegPos = BegPos + 1%@NL@%
  21046.       END IF%@NL@%
  21047.    LOOP%@NL@%
  21048.    StrSpn = BegPos%@NL@%
  21049. %@NL@%
  21050. END FUNCTION%@NL@%
  21051. %@NL@%
  21052. %@NL@%
  21053. %@NL@%
  21054. %@2@%%@AH@%SINEWAVE.BAS%@AE@%%@EH@%%@NL@%
  21055. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\SINEWAVE.BAS%@AE@%%@NL@%
  21056. %@NL@%
  21057. SCREEN 2%@NL@%
  21058. %@NL@%
  21059. %@AB@%' Viewport sized to proper scale for graph:%@AE@%%@NL@%
  21060. VIEW (20, 2)-(620, 172), , 1%@NL@%
  21061. CONST PI = 3.141592653589#%@NL@%
  21062. %@NL@%
  21063. %@AB@%' Make window large enough to graph sine wave from%@AE@%%@NL@%
  21064. %@AB@%' 0 radians to pi radians:%@AE@%%@NL@%
  21065. WINDOW (0, -1.1)-(2 * PI, 1.1)%@NL@%
  21066. Style% = &HFF00         ' Use to make dashed line.%@NL@%
  21067. VIEW PRINT 23 TO 24  ' Scroll printed output in rows 23, 24.%@NL@%
  21068. DO%@NL@%
  21069.         PRINT TAB(20);%@NL@%
  21070.         INPUT "Number of cycles (0 to end): ", Cycles%@NL@%
  21071.         CLS%@NL@%
  21072.         LINE (2 * PI, 0)-(0, 0), , , Style%  ' Draw the x axis.%@NL@%
  21073.         IF Cycles > 0 THEN%@NL@%
  21074. %@NL@%
  21075. %@AB@%                '  Start at (0,0) and plot the graph:%@AE@%%@NL@%
  21076.                 FOR X = 0 TO 2 * PI STEP .01%@NL@%
  21077.          Y = SIN(Cycles * X) ' Calculate the y coordinate.%@NL@%
  21078.          LINE -(X, Y)     ' Draw a line to new point.%@NL@%
  21079.                 NEXT X%@NL@%
  21080.         END IF%@NL@%
  21081. LOOP WHILE Cycles > 0%@NL@%
  21082. %@NL@%
  21083. %@NL@%
  21084. %@NL@%
  21085. %@2@%%@AH@%STRTONUM.BAS%@AE@%%@EH@%%@NL@%
  21086. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\STRTONUM.BAS%@AE@%%@NL@%
  21087. %@NL@%
  21088. DECLARE FUNCTION Filter$ (Txt$, FilterString$)%@NL@%
  21089. %@NL@%
  21090. %@AB@%' Input a line:%@AE@%%@NL@%
  21091. LINE INPUT "Enter a number with commas: "; A$%@NL@%
  21092. %@NL@%
  21093. %@AB@%' Look only for valid numeric characters (0123456789.-)%@AE@%%@NL@%
  21094. %@AB@%' in the input string:%@AE@%%@NL@%
  21095. CleanNum$ = Filter$(A$, "0123456789.-")%@NL@%
  21096. %@NL@%
  21097. %@AB@%' Convert the string to a number:%@AE@%%@NL@%
  21098. PRINT "The number's value = "; VAL(CleanNum$)%@NL@%
  21099. END%@NL@%
  21100. %@NL@%
  21101. %@AB@%' ========================== FILTER =======================%@AE@%%@NL@%
  21102. %@AB@%'         Takes unwanted characters out of a string by%@AE@%%@NL@%
  21103. %@AB@%'         comparing them with a filter string containing%@AE@%%@NL@%
  21104. %@AB@%'         only acceptable numeric characters%@AE@%%@NL@%
  21105. %@AB@%' =========================================================%@AE@%%@NL@%
  21106. %@NL@%
  21107. FUNCTION Filter$ (Txt$, FilterString$) STATIC%@NL@%
  21108.    Temp$ = ""%@NL@%
  21109.    TxtLength = LEN(Txt$)%@NL@%
  21110. %@NL@%
  21111.    FOR I = 1 TO TxtLength     ' Isolate each character in%@NL@%
  21112.       C$ = MID$(Txt$, I, 1)   ' the string.%@NL@%
  21113. %@NL@%
  21114. %@AB@%      ' If the character is in the filter string, save it:%@AE@%%@NL@%
  21115.       IF INSTR(FilterString$, C$) <> 0 THEN%@NL@%
  21116.          Temp$ = Temp$ + C$%@NL@%
  21117.       END IF%@NL@%
  21118.    NEXT I%@NL@%
  21119. %@NL@%
  21120.    Filter$ = Temp$%@NL@%
  21121. END FUNCTION%@NL@%
  21122. %@NL@%
  21123. %@NL@%
  21124. %@NL@%
  21125. %@2@%%@AH@%TERMINAL.BAS%@AE@%%@EH@%%@NL@%
  21126. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\TERMINAL.BAS%@AE@%%@NL@%
  21127. %@NL@%
  21128. DEFINT A-Z%@NL@%
  21129. %@NL@%
  21130. DECLARE        SUB Filter (InString$)%@NL@%
  21131. %@NL@%
  21132. COLOR 7, 1                        ' Set screen color.%@NL@%
  21133. CLS%@NL@%
  21134. %@NL@%
  21135. Quit$ = CHR$(0) + CHR$(16)        ' Value returned by INKEY$%@NL@%
  21136. %@AB@%                                ' when ALT+q is pressed.%@AE@%%@NL@%
  21137. %@NL@%
  21138. %@AB@%' Set up prompt on bottom line of screen and turn cursor on:%@AE@%%@NL@%
  21139. LOCATE 24, 1, 1%@NL@%
  21140. PRINT STRING$(80, "_");%@NL@%
  21141. LOCATE 25, 1%@NL@%
  21142. PRINT TAB(30); "Press ALT+q to quit";%@NL@%
  21143. %@NL@%
  21144. VIEW PRINT 1 TO        23                ' Print between lines 1 & 23.%@NL@%
  21145. %@NL@%
  21146. %@AB@%' Open communications (1200 baud, no parity, 8-bit data,%@AE@%%@NL@%
  21147. %@AB@%' 1 stop bit, 256-byte input buffer):%@AE@%%@NL@%
  21148. OPEN "COM1:1200,N,8,1" FOR RANDOM AS #1        LEN = 256%@NL@%
  21149. %@NL@%
  21150. DO                                ' Main communications loop.%@NL@%
  21151. %@NL@%
  21152.    KeyInput$ = INKEY$                ' Check the keyboard.%@NL@%
  21153. %@NL@%
  21154.    IF KeyInput$        = Quit$        THEN        ' Exit the loop if the user%@NL@%
  21155.       EXIT DO                        ' pressed ALT+q.%@NL@%
  21156. %@NL@%
  21157.    ELSEIF KeyInput$ <> "" THEN        ' Otherwise, if the user has%@NL@%
  21158.       PRINT #1,        KeyInput$;        ' pressed a key, send the%@NL@%
  21159.    END IF                        ' character typed to modem.%@NL@%
  21160. %@AB@% ' Check the modem. If characters are waiting (EOF(1) is%@AE@%%@NL@%
  21161. %@AB@% ' true), get them and print them to the screen:%@AE@%%@NL@%
  21162.  IF NOT EOF(1) THEN%@NL@%
  21163. %@NL@%
  21164. %@AB@%      ' LOC(1) gives the number of characters waiting:%@AE@%%@NL@%
  21165.       ModemInput$ = INPUT$(LOC(1), #1)%@NL@%
  21166. %@NL@%
  21167.       Filter ModemInput$        ' Filter out line feeds and%@NL@%
  21168.       PRINT ModemInput$;        ' backspaces, then print.%@NL@%
  21169.    END IF%@NL@%
  21170. LOOP%@NL@%
  21171. %@NL@%
  21172. CLOSE                                ' End communications.%@NL@%
  21173. CLS%@NL@%
  21174. END%@NL@%
  21175. %@AB@%'%@AE@%%@NL@%
  21176. %@AB@%' ========================= FILTER ========================%@AE@%%@NL@%
  21177. %@AB@%'               Filters characters in an input string%@AE@%%@NL@%
  21178. %@AB@%' =========================================================%@AE@%%@NL@%
  21179. %@AB@%'%@AE@%%@NL@%
  21180. SUB Filter (InString$) STATIC%@NL@%
  21181. %@NL@%
  21182. %@AB@%   ' Look for backspace characters and recode%@AE@%%@NL@%
  21183. %@AB@%   ' them to CHR$(29) (the LEFT cursor key):%@AE@%%@NL@%
  21184.    DO%@NL@%
  21185.       BackSpace = INSTR(InString$, CHR$(8))%@NL@%
  21186.       IF BackSpace THEN%@NL@%
  21187.       MID$(InString$, BackSpace) = CHR$(29)%@NL@%
  21188.       END IF%@NL@%
  21189.    LOOP WHILE BackSpace%@NL@%
  21190. %@NL@%
  21191. %@AB@%   ' Look for line-feed characters and%@AE@%%@NL@%
  21192. %@AB@%   ' remove any found:%@AE@%%@NL@%
  21193.    DO%@NL@%
  21194.       LnFd = INSTR(InString$, CHR$(10))%@NL@%
  21195.       IF LnFd THEN%@NL@%
  21196.    InString$=LEFT$(InString$,LnFd-1)+MID$(InString$,LnFd+1)%@NL@%
  21197.       END IF%@NL@%
  21198.    LOOP WHILE LnFd%@NL@%
  21199. %@NL@%
  21200. END SUB%@NL@%
  21201. %@NL@%
  21202. %@NL@%
  21203. %@NL@%
  21204. %@2@%%@AH@%TIMER.BAS%@AE@%%@EH@%%@NL@%
  21205. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\TIMER.BAS%@AE@%%@NL@%
  21206. %@NL@%
  21207. %@AB@%' Declare external MASM procedures.%@AE@%%@NL@%
  21208. DECLARE SUB SetInt%@NL@%
  21209. DECLARE SUB RestInt%@NL@%
  21210. %@NL@%
  21211. %@AB@%' Install new interrupt service routine.%@AE@%%@NL@%
  21212. CALL SetInt%@NL@%
  21213. %@NL@%
  21214. %@AB@%' Set up the BASIC event handler.%@AE@%%@NL@%
  21215. ON UEVENT GOSUB SpecialTask%@NL@%
  21216. UEVENT ON%@NL@%
  21217. %@NL@%
  21218. DO%@NL@%
  21219. %@AB@%' Normal program operation occurs here.%@AE@%%@NL@%
  21220. %@AB@%' Program ends when any key is pressed.%@AE@%%@NL@%
  21221. LOOP UNTIL INKEY$ <> ""%@NL@%
  21222. %@NL@%
  21223. %@AB@%' Restore old interrupt service routine before quitting.%@AE@%%@NL@%
  21224. CALL RestInt%@NL@%
  21225. %@NL@%
  21226. END%@NL@%
  21227. %@NL@%
  21228. %@AB@%' Program branches here every 4.5 seconds.%@AE@%%@NL@%
  21229. SpecialTask:%@NL@%
  21230. %@AB@%' Code for performing the special task goes here, for example:%@AE@%%@NL@%
  21231. PRINT "Arrived here after 4.5 seconds."%@NL@%
  21232. RETURN%@NL@%
  21233. %@NL@%
  21234. %@NL@%
  21235. %@NL@%
  21236. %@2@%%@AH@%TIMERA.ASM%@AE@%%@EH@%%@NL@%
  21237. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\TIMERA.ASM%@AE@%%@NL@%
  21238. %@NL@%
  21239. %@AB@%;*************************  TIMERA.ASM  ******************************%@AE@%%@NL@%
  21240. %@AB@%; This program, along with TIMER.BAS, makes use of the BASIC SetUEvent%@AE@%%@NL@%
  21241. %@AB@%; routine to print a message on the screen every 4.5 seconds.%@AE@%%@NL@%
  21242. %@AB@%; This file has three procedures.  SetInt sets up the new DOS interrupt%@AE@%%@NL@%
  21243. %@AB@%; vector.  EventHandler increments a counter 18 times a second and%@AE@%%@NL@%
  21244. %@AB@%; notifies BASIC when 4.5 seconds have elapsed.  RestInt restores the%@AE@%%@NL@%
  21245. %@AB@%; old interrupt vector.%@AE@%%@NL@%
  21246. %@NL@%
  21247.             .model  medium, basic           %@AB@%;Stay compatible with BASIC.%@AE@%%@NL@%
  21248.             .code%@NL@%
  21249. SetInt      proc    uses ds                 %@AB@%;Get old interrupt vector%@AE@%%@NL@%
  21250.             mov     ax, 351CH               %@AB@%;and save it.%@AE@%%@NL@%
  21251.                         int        21h%@NL@%
  21252.             mov     word ptr cs:OldVector, bx%@NL@%
  21253.             mov     word ptr cs:OldVector + 2, es%@NL@%
  21254. %@NL@%
  21255.             push    cs                      %@AB@%;Set the new%@AE@%%@NL@%
  21256.             pop ds                          %@AB@%;interrupt vector%@AE@%%@NL@%
  21257.             lea dx, EventHandler            %@AB@%;to the address%@AE@%%@NL@%
  21258.             mov ax, 251CH                   %@AB@%;of our service%@AE@%%@NL@%
  21259.             int 21H                         %@AB@%;routine.%@AE@%%@NL@%
  21260.                         ret%@NL@%
  21261. SetInt      endp%@NL@%
  21262. %@NL@%
  21263. public  EventHandler                        %@AB@%;Make this routine%@AE@%%@NL@%
  21264.                                             %@AB@%;public for debugging--%@AE@%%@NL@%
  21265. EventHandler    proc                        %@AB@%;it will check to see if%@AE@%%@NL@%
  21266.                 extrn   SetUEvent: proc     %@AB@%;4.5 seconds have passed.%@AE@%%@NL@%
  21267. %@NL@%
  21268.             push    bx%@NL@%
  21269.             lea     bx, TimerTicks%@NL@%
  21270.             inc     byte ptr cs:[bx]        %@AB@%;Have 4.5 seconds elapsed?%@AE@%%@NL@%
  21271.             cmp     byte ptr cs:[bx], 82%@NL@%
  21272.             jnz     Continue%@NL@%
  21273.             mov     byte ptr cs:[bx], 0     %@AB@%;If true, reset counter,%@AE@%%@NL@%
  21274.             push    ax                      %@AB@%;save registers, and%@AE@%%@NL@%
  21275.             push    cx                      %@AB@%;have BASIC set the%@AE@%%@NL@%
  21276.             push    dx                      %@AB@%;user event flag.%@AE@%%@NL@%
  21277.             push    es%@NL@%
  21278.             call    SetUevent%@NL@%
  21279.             pop     es%@NL@%
  21280.             pop     dx                      %@AB@%;Restore registers.%@AE@%%@NL@%
  21281.             pop     cx%@NL@%
  21282.             pop     ax%@NL@%
  21283. Continue:%@NL@%
  21284.             pop     bx%@NL@%
  21285.             jmp     cs:OldVector            %@AB@%;Continue on with the%@AE@%%@NL@%
  21286.                                             %@AB@%;old service routine.%@AE@%%@NL@%
  21287. %@NL@%
  21288. TimerTicks  db      0                       %@AB@%;Keep data in code segment%@AE@%%@NL@%
  21289. OldVector   dd      0                       %@AB@%;where it can be found no%@AE@%%@NL@%
  21290.                                             %@AB@%;matter where in memory the%@AE@%%@NL@%
  21291. EventHandler    endp                        %@AB@%;interrupt occurs.%@AE@%%@NL@%
  21292. %@NL@%
  21293. RestInt     proc    uses ds                 %@AB@%;Restore the old%@AE@%%@NL@%
  21294.             lds     dx, cs:OldVector        %@AB@%;interrupt vector%@AE@%%@NL@%
  21295.             mov     ax, 251CH               %@AB@%;so things will%@AE@%%@NL@%
  21296.             int     21h                     %@AB@%;keep working when%@AE@%%@NL@%
  21297.             ret                             %@AB@%;this BASIC program is%@AE@%%@NL@%
  21298. RestInt     endp                            %@AB@%;finished.%@AE@%%@NL@%
  21299.                         end%@NL@%
  21300. %@NL@%
  21301. %@NL@%
  21302. %@2@%%@AH@%TOKEN.BAS%@AE@%%@EH@%%@NL@%
  21303. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\TOKEN.BAS%@AE@%%@NL@%
  21304. %@NL@%
  21305. %@AB@%' TOKEN.BAS%@AE@%%@NL@%
  21306. %@AB@%'%@AE@%%@NL@%
  21307. %@AB@%' Demonstrates a BASIC version of the strtok C function.%@AE@%%@NL@%
  21308. %@AB@%'%@AE@%%@NL@%
  21309. DECLARE FUNCTION StrTok$(Source$,Delimiters$)%@NL@%
  21310. %@NL@%
  21311. LINE INPUT "Enter string: ",P$%@NL@%
  21312. %@AB@%' Set up the characters that separate tokens.%@AE@%%@NL@%
  21313. Delimiters$=" ,;:().?"+CHR$(9)+CHR$(34)%@NL@%
  21314. %@AB@%' Invoke StrTok$ with the string to tokenize.%@AE@%%@NL@%
  21315. Token$=StrTok$(P$,Delimiters$)%@NL@%
  21316. WHILE Token$<>""%@NL@%
  21317.    PRINT Token$%@NL@%
  21318. %@AB@%   ' Call StrTok$ with a null string so it knows this%@AE@%%@NL@%
  21319. %@AB@%   ' isn't the first call.%@AE@%%@NL@%
  21320.    Token$=StrTok$("",Delimiters$)%@NL@%
  21321. WEND%@NL@%
  21322. %@NL@%
  21323. FUNCTION StrTok$(Srce$,Delim$)%@NL@%
  21324. STATIC Start%, SaveStr$%@NL@%
  21325. %@NL@%
  21326. %@AB@%   ' If first call, make a copy of the string.%@AE@%%@NL@%
  21327.    IF Srce$<>"" THEN%@NL@%
  21328.       Start%=1 : SaveStr$=Srce$%@NL@%
  21329.    END IF%@NL@%
  21330. %@NL@%
  21331.    BegPos%=Start% : Ln%=LEN(SaveStr$)%@NL@%
  21332. %@AB@%   ' Look for start of a token (character that isn't delimiter).%@AE@%%@NL@%
  21333.    WHILE BegPos%<=Ln% AND INSTR(Delim$,MID$(SaveStr$,BegPos%,1))<>0%@NL@%
  21334.       BegPos%=BegPos%+1%@NL@%
  21335.    WEND%@NL@%
  21336. %@AB@%   ' Test for token start found.%@AE@%%@NL@%
  21337.    IF BegPos% > Ln% THEN%@NL@%
  21338.       StrTok$="" : EXIT FUNCTION%@NL@%
  21339.    END IF%@NL@%
  21340. %@AB@%   ' Find the end of the token.%@AE@%%@NL@%
  21341.    EndPos%=BegPos%%@NL@%
  21342.    WHILE EndPos% <= Ln% AND INSTR(Delim$,MID$(SaveStr$,EndPos%,1))=0%@NL@%
  21343.       EndPos%=EndPos%+1%@NL@%
  21344.    WEND%@NL@%
  21345.    StrTok$=MID$(SaveStr$,BegPos%,EndPos%-BegPos%)%@NL@%
  21346. %@AB@%   ' Set starting point for search for next token.%@AE@%%@NL@%
  21347.    Start%=EndPos%%@NL@%
  21348. %@NL@%
  21349. END FUNCTION%@NL@%
  21350. %@NL@%
  21351. %@NL@%
  21352. %@2@%%@AH@%TORUS.BAS%@AE@%%@EH@%%@NL@%
  21353. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\TORUS.BAS%@AE@%%@NL@%
  21354. %@NL@%
  21355. %@AB@%' ======================================================================%@AE@%%@NL@%
  21356. %@AB@%'                                TORUS%@AE@%%@NL@%
  21357. %@AB@%'   This program draws a Torus figure. The program accepts user input%@AE@%%@NL@%
  21358. %@AB@%'   to specify various TORUS parameters. It checks the current system%@AE@%%@NL@%
  21359. %@AB@%'   configuration and takes appropriate action to set the best possible%@AE@%%@NL@%
  21360. %@AB@%'   initial mode.%@AE@%%@NL@%
  21361. %@AB@%' ======================================================================%@AE@%%@NL@%
  21362. %@NL@%
  21363. DEFINT A-Z%@NL@%
  21364. DECLARE SUB GetConfig ()%@NL@%
  21365. DECLARE SUB SetPalette ()%@NL@%
  21366. DECLARE SUB TorusDefine ()%@NL@%
  21367. DECLARE SUB TorusCalc (T() AS ANY)%@NL@%
  21368. DECLARE SUB TorusColor (T() AS ANY)%@NL@%
  21369. DECLARE SUB TorusSort (Low, High)%@NL@%
  21370. DECLARE SUB TorusDraw (T() AS ANY, Index())%@NL@%
  21371. DECLARE SUB TileDraw (T AS ANY)%@NL@%
  21372. DECLARE SUB TorusRotate (First)%@NL@%
  21373. DECLARE SUB Delay (Seconds!)%@NL@%
  21374. DECLARE SUB CountTiles (T1, T2)%@NL@%
  21375. DECLARE SUB Message (Text$)%@NL@%
  21376. DECLARE SUB SetConfig (mode)%@NL@%
  21377. DECLARE FUNCTION Inside (T AS ANY)%@NL@%
  21378. DECLARE FUNCTION DegToRad! (Degrees)%@NL@%
  21379. DECLARE FUNCTION Rotated (Lower, Upper, Current, Inc)%@NL@%
  21380. %@NL@%
  21381. %@AB@%' General purpose constants%@AE@%%@NL@%
  21382. CONST PI = 3.14159%@NL@%
  21383. CONST TRUE = -1, FALSE = 0%@NL@%
  21384. CONST BACK = 0%@NL@%
  21385. CONST TROW = 24, TCOL = 60%@NL@%
  21386. %@NL@%
  21387. %@AB@%' Rotation flags%@AE@%%@NL@%
  21388. CONST RNDM = -1%@NL@%
  21389. CONST START = 0%@NL@%
  21390. CONST CONTINUE = 1%@NL@%
  21391. %@NL@%
  21392. %@AB@%' Constants for best available screen mode%@AE@%%@NL@%
  21393. CONST VGA = 12%@NL@%
  21394. CONST MCGA = 13%@NL@%
  21395. CONST EGA256 = 9%@NL@%
  21396. CONST EGA64 = 8%@NL@%
  21397. CONST MONO = 10%@NL@%
  21398. CONST HERC = 3%@NL@%
  21399. CONST CGA = 1%@NL@%
  21400. %@NL@%
  21401. %@AB@%' User-defined type for tiles - an array of these make a torus%@AE@%%@NL@%
  21402. TYPE Tile%@NL@%
  21403.    x1    AS SINGLE%@NL@%
  21404.    x2    AS SINGLE%@NL@%
  21405.    x3    AS SINGLE%@NL@%
  21406.    x4    AS SINGLE%@NL@%
  21407.    y1    AS SINGLE%@NL@%
  21408.    y2    AS SINGLE%@NL@%
  21409.    y3    AS SINGLE%@NL@%
  21410.    y4    AS SINGLE%@NL@%
  21411.    z1    AS SINGLE%@NL@%
  21412.    xc    AS SINGLE%@NL@%
  21413.    yc    AS SINGLE%@NL@%
  21414.    TColor AS INTEGER%@NL@%
  21415. END TYPE%@NL@%
  21416. %@NL@%
  21417. %@AB@%' User-defined type to hold information about the mode%@AE@%%@NL@%
  21418. TYPE Config%@NL@%
  21419.    Scrn     AS INTEGER%@NL@%
  21420.    Colors   AS INTEGER%@NL@%
  21421.    Atribs   AS INTEGER%@NL@%
  21422.    XPix     AS INTEGER%@NL@%
  21423.    YPix     AS INTEGER%@NL@%
  21424.    TCOL     AS INTEGER%@NL@%
  21425.    TROW     AS INTEGER%@NL@%
  21426. END TYPE%@NL@%
  21427. %@NL@%
  21428. DIM VC AS Config%@NL@%
  21429. %@NL@%
  21430. %@AB@%' User-defined type to hold information about current Torus%@AE@%%@NL@%
  21431. TYPE TORUS%@NL@%
  21432.    Panel    AS INTEGER%@NL@%
  21433.    Sect     AS INTEGER%@NL@%
  21434.    Thick    AS SINGLE%@NL@%
  21435.    XDegree  AS INTEGER%@NL@%
  21436.    YDegree  AS INTEGER%@NL@%
  21437.    Bord     AS STRING * 3%@NL@%
  21438.    Delay    AS SINGLE%@NL@%
  21439. END TYPE%@NL@%
  21440. %@NL@%
  21441. DIM TOR AS TORUS, Max AS INTEGER%@NL@%
  21442. %@NL@%
  21443. %@AB@%' A palette of colors to paint with%@AE@%%@NL@%
  21444. DIM Pal(0 TO 300) AS LONG%@NL@%
  21445. %@NL@%
  21446. %@AB@%' Error variables to check screen type%@AE@%%@NL@%
  21447. DIM InitRows AS INTEGER, BestMode AS INTEGER, Available AS STRING%@NL@%
  21448. %@NL@%
  21449. %@AB@%' The code of the module-level program begins here%@AE@%%@NL@%
  21450. %@NL@%
  21451. %@AB@%   ' Initialize defaults%@AE@%%@NL@%
  21452.    TOR.Thick = 3: TOR.Bord = "YES"%@NL@%
  21453.    TOR.Panel = 8: TOR.Sect = 14%@NL@%
  21454.    TOR.XDegree = 60: TOR.YDegree = 165%@NL@%
  21455. %@NL@%
  21456. %@AB@%   ' Get best configuration and set initial graphics mode to it%@AE@%%@NL@%
  21457.    GetConfig%@NL@%
  21458.    VC.Scrn = BestMode%@NL@%
  21459. %@NL@%
  21460.    DO WHILE TRUE           ' Loop forever (exit is from within a SUB)%@NL@%
  21461. %@NL@%
  21462. %@AB@%      ' Get Torus definition from user%@AE@%%@NL@%
  21463.       TorusDefine%@NL@%
  21464. %@NL@%
  21465. %@AB@%      ' Dynamically dimension arrays%@AE@%%@NL@%
  21466.       DO%@NL@%
  21467.          Tmp = TOR.Panel%@NL@%
  21468.          Max = TOR.Panel * TOR.Sect%@NL@%
  21469. %@NL@%
  21470. %@AB@%         ' Array for indexes%@AE@%%@NL@%
  21471.          REDIM Index(0 TO Max - 1) AS INTEGER%@NL@%
  21472. %@AB@%         ' Turn on error trap for insufficient memory%@AE@%%@NL@%
  21473.          ON ERROR GOTO MemErr%@NL@%
  21474. %@AB@%         ' Array for tiles%@AE@%%@NL@%
  21475.          REDIM T(0 TO Max - 1) AS Tile%@NL@%
  21476.          ON ERROR GOTO 0%@NL@%
  21477.       LOOP UNTIL Tmp = TOR.Panel%@NL@%
  21478. %@NL@%
  21479. %@AB@%      ' Initialize array of indexes%@AE@%%@NL@%
  21480.       FOR Til = 0 TO Max - 1%@NL@%
  21481.          Index(Til) = Til%@NL@%
  21482.       NEXT%@NL@%
  21483. %@NL@%
  21484. %@AB@%      ' Calculate the points of each tile on the torus%@AE@%%@NL@%
  21485.       Message "Calculating"%@NL@%
  21486.       TorusCalc T()%@NL@%
  21487. %@NL@%
  21488. %@AB@%      ' Color each tile in the torus.%@AE@%%@NL@%
  21489.       TorusColor T()%@NL@%
  21490. %@NL@%
  21491. %@AB@%      ' Sort the tiles by their "distance" from the screen%@AE@%%@NL@%
  21492.       Message "Sorting"%@NL@%
  21493.       TorusSort 0, Max - 1%@NL@%
  21494. %@NL@%
  21495. %@AB@%      ' Set the screen mode%@AE@%%@NL@%
  21496.       SCREEN VC.Scrn%@NL@%
  21497. %@NL@%
  21498. %@AB@%      ' Mix a palette of colors%@AE@%%@NL@%
  21499.       SetPalette%@NL@%
  21500. %@NL@%
  21501. %@AB@%      ' Set logical window with variable thickness%@AE@%%@NL@%
  21502. %@AB@%      ' Center is 0, up and right are positive, down and left are negative%@AE@%%@NL@%
  21503.       WINDOW (-(TOR.Thick + 1), -(TOR.Thick + 1))-(TOR.Thick + 1, TOR.Thick + 1)%@NL@%
  21504. %@NL@%
  21505. %@AB@%      ' Draw and paint the tiles, the farthest first and nearest last%@AE@%%@NL@%
  21506.       TorusDraw T(), Index()%@NL@%
  21507. %@NL@%
  21508. %@AB@%      ' Rotate the torus by rotating the color palette%@AE@%%@NL@%
  21509.       DO WHILE INKEY$ = ""%@NL@%
  21510.          Delay (TOR.Delay)%@NL@%
  21511.          TorusRotate CONTINUE%@NL@%
  21512.       LOOP%@NL@%
  21513.       SCREEN 0%@NL@%
  21514.       WIDTH 80%@NL@%
  21515.    LOOP%@NL@%
  21516. %@NL@%
  21517. %@AB@%   ' Restore original rows%@AE@%%@NL@%
  21518.    WIDTH 80, InitRows%@NL@%
  21519. %@NL@%
  21520. END%@NL@%
  21521. %@NL@%
  21522. %@AB@%' Error trap to make torus screen independent%@AE@%%@NL@%
  21523. VideoErr:%@NL@%
  21524.    SELECT CASE BestMode    ' Fall through until something works%@NL@%
  21525.       CASE VGA%@NL@%
  21526.          BestMode = MCGA%@NL@%
  21527.          Available = "12BD"%@NL@%
  21528.       CASE MCGA%@NL@%
  21529.          BestMode = EGA256%@NL@%
  21530.          Available = "12789"%@NL@%
  21531.       CASE EGA256%@NL@%
  21532.          BestMode = CGA%@NL@%
  21533.          Available = "12"%@NL@%
  21534.       CASE CGA%@NL@%
  21535.          BestMode = MONO%@NL@%
  21536.          Available = "A"%@NL@%
  21537.       CASE MONO%@NL@%
  21538.          BestMode = HERC%@NL@%
  21539.          Available = "3"%@NL@%
  21540.       CASE ELSE%@NL@%
  21541.          PRINT "Sorry. Graphics not available. Can't run Torus."%@NL@%
  21542.          END%@NL@%
  21543.    END SELECT%@NL@%
  21544.    RESUME%@NL@%
  21545. %@NL@%
  21546. %@AB@%' Trap to detect 64K EGA%@AE@%%@NL@%
  21547. EGAErr:%@NL@%
  21548.    BestMode = EGA64%@NL@%
  21549.    Available = "12789"%@NL@%
  21550.    RESUME NEXT%@NL@%
  21551. %@NL@%
  21552. %@AB@%' Trap to detect insufficient memory for large Torus%@AE@%%@NL@%
  21553. MemErr:%@NL@%
  21554.    LOCATE 22, 1%@NL@%
  21555.    PRINT "Out of memory"%@NL@%
  21556.    PRINT "Reducing panels from"; TOR.Panel; "to"; TOR.Panel - 1%@NL@%
  21557.    PRINT "Reducing sections from"; TOR.Sect; "to"; TOR.Sect - 1;%@NL@%
  21558.    DO WHILE INKEY$ = "": LOOP%@NL@%
  21559.    TOR.Panel = TOR.Panel - 1%@NL@%
  21560.    TOR.Sect = TOR.Sect - 1%@NL@%
  21561.    RESUME NEXT%@NL@%
  21562. %@NL@%
  21563. %@AB@%' Trap to determine initial number of rows so they can be restored%@AE@%%@NL@%
  21564. RowErr:%@NL@%
  21565.    IF InitRows = 50 THEN%@NL@%
  21566.       InitRows = 43%@NL@%
  21567.       RESUME%@NL@%
  21568.    ELSE%@NL@%
  21569.       InitRows = 25%@NL@%
  21570.       RESUME NEXT%@NL@%
  21571.    END IF%@NL@%
  21572. %@NL@%
  21573. %@AB@%' ============================ CountTiles ==============================%@AE@%%@NL@%
  21574. %@AB@%'   Displays number of the tiles currently being calculated or sorted.%@AE@%%@NL@%
  21575. %@AB@%' ======================================================================%@AE@%%@NL@%
  21576. %@AB@%'%@AE@%%@NL@%
  21577. SUB CountTiles (T1, T2) STATIC%@NL@%
  21578. %@NL@%
  21579. %@AB@%   ' Erase previous%@AE@%%@NL@%
  21580.    LOCATE TROW - 1, TCOL: PRINT SPACE$(19);%@NL@%
  21581. %@AB@%   ' If positive, display - give negative values to erase%@AE@%%@NL@%
  21582.    IF T1 > 0 AND T2 > 0 THEN%@NL@%
  21583.       LOCATE TROW - 1, TCOL%@NL@%
  21584.       PRINT "Tile ";%@NL@%
  21585.       PRINT USING " ###"; T1;%@NL@%
  21586.       PRINT USING " ###"; T2;%@NL@%
  21587.    END IF%@NL@%
  21588. %@NL@%
  21589. END SUB%@NL@%
  21590. %@NL@%
  21591. %@AB@%' ============================ DegToRad ================================%@AE@%%@NL@%
  21592. %@AB@%'   Convert degrees to radians, since BASIC trigonometric functions%@AE@%%@NL@%
  21593. %@AB@%'   require radians.%@AE@%%@NL@%
  21594. %@AB@%' ======================================================================%@AE@%%@NL@%
  21595. %@AB@%'%@AE@%%@NL@%
  21596. FUNCTION DegToRad! (Degrees) STATIC%@NL@%
  21597. %@NL@%
  21598.    DegToRad! = (Degrees * 2 * PI) / 360%@NL@%
  21599. %@NL@%
  21600. END FUNCTION%@NL@%
  21601. %@NL@%
  21602. %@AB@%' =============================== Delay ================================%@AE@%%@NL@%
  21603. %@AB@%'   Delay based on time so that wait will be the same on any processor.%@AE@%%@NL@%
  21604. %@AB@%'   Notice the check for negative numbers so that the delay won't%@AE@%%@NL@%
  21605. %@AB@%'   freeze at midnight when the delay could become negative.%@AE@%%@NL@%
  21606. %@AB@%' ======================================================================%@AE@%%@NL@%
  21607. %@AB@%'%@AE@%%@NL@%
  21608. SUB Delay (Seconds!) STATIC%@NL@%
  21609. %@NL@%
  21610.    Begin! = TIMER%@NL@%
  21611.    DO UNTIL (TIMER - Begin! > Seconds!) OR (TIMER - Begin! < 0)%@NL@%
  21612.    LOOP%@NL@%
  21613. %@NL@%
  21614. END SUB%@NL@%
  21615. %@NL@%
  21616. %@AB@%' ============================ GetConfig ===============================%@AE@%%@NL@%
  21617. %@AB@%'   Get the starting number of lines and the video adapter.%@AE@%%@NL@%
  21618. %@AB@%' ======================================================================%@AE@%%@NL@%
  21619. %@AB@%'%@AE@%%@NL@%
  21620. SUB GetConfig STATIC%@NL@%
  21621. SHARED InitRows AS INTEGER, BestMode AS INTEGER, Available AS STRING%@NL@%
  21622. %@NL@%
  21623. %@AB@%   ' Assume 50 line display and fall through error%@AE@%%@NL@%
  21624. %@AB@%   ' until we get the actual number%@AE@%%@NL@%
  21625.    InitRows = 50%@NL@%
  21626.    ON ERROR GOTO RowErr%@NL@%
  21627.    LOCATE InitRows, 1%@NL@%
  21628. %@NL@%
  21629. %@AB@%   ' Assume best possible screen mode%@AE@%%@NL@%
  21630.    BestMode = VGA%@NL@%
  21631.    Available = "12789BCD"%@NL@%
  21632. %@NL@%
  21633.    ON ERROR GOTO VideoErr%@NL@%
  21634. %@AB@%   ' Fall through error trap until a mode works%@AE@%%@NL@%
  21635.    SCREEN BestMode%@NL@%
  21636. %@AB@%   ' If EGA, then check pages to see whether more than 64K%@AE@%%@NL@%
  21637.    ON ERROR GOTO EGAErr%@NL@%
  21638.    IF BestMode = EGA256 THEN SCREEN 8, , 1%@NL@%
  21639. %@NL@%
  21640.    ON ERROR GOTO 0%@NL@%
  21641. %@NL@%
  21642. %@AB@%   ' Reset text mode%@AE@%%@NL@%
  21643.    SCREEN 0, , 0%@NL@%
  21644.    WIDTH 80, 25%@NL@%
  21645. %@NL@%
  21646. END SUB%@NL@%
  21647. %@NL@%
  21648. %@AB@%' ============================== Inside ================================%@AE@%%@NL@%
  21649. %@AB@%'   Finds a point, T.xc and T.yc, that is mathematically within a tile.%@AE@%%@NL@%
  21650. %@AB@%'   Then check to see if the point is actually inside. Because of the%@AE@%%@NL@%
  21651. %@AB@%'   jagged edges of tiles, the center point is often actually inside%@AE@%%@NL@%
  21652. %@AB@%'   very thin tiles. Such tiles will not be painted, This causes%@AE@%%@NL@%
  21653. %@AB@%'   imperfections that are often visible at the edge of the Torus.%@AE@%%@NL@%
  21654. %@AB@%'%@AE@%%@NL@%
  21655. %@AB@%'   Return FALSE if a center point is not found inside a tile.%@AE@%%@NL@%
  21656. %@AB@%' ======================================================================%@AE@%%@NL@%
  21657. %@AB@%'%@AE@%%@NL@%
  21658. FUNCTION Inside (T AS Tile) STATIC%@NL@%
  21659. SHARED VC AS Config%@NL@%
  21660. DIM Highest AS SINGLE, Lowest AS SINGLE%@NL@%
  21661. %@NL@%
  21662.    Border = VC.Atribs - 1%@NL@%
  21663. %@NL@%
  21664. %@AB@%   ' Find an inside point. Since some tiles are triangles, the%@AE@%%@NL@%
  21665. %@AB@%   ' diagonal center isn't good enough. Instead find the center%@AE@%%@NL@%
  21666. %@AB@%   ' by drawing a diagonal from the center of the outside to%@AE@%%@NL@%
  21667. %@AB@%   ' a bottom corner.%@AE@%%@NL@%
  21668.    T.xc = T.x2 + ((T.x3 + (T.x4 - T.x3) / 2 - T.x2) / 2)%@NL@%
  21669.    T.yc = T.y2 + ((T.y3 + (T.y4 - T.y3) / 2 - T.y2) / 2)%@NL@%
  21670. %@NL@%
  21671. %@AB@%   ' If we're on a border, no need to fill%@AE@%%@NL@%
  21672.    IF POINT(T.xc, T.yc) = Border THEN%@NL@%
  21673.       Inside = FALSE%@NL@%
  21674.       EXIT FUNCTION%@NL@%
  21675.    END IF%@NL@%
  21676. %@NL@%
  21677. %@AB@%   ' Find highest and lowest Y on the tile%@AE@%%@NL@%
  21678.    Highest = T.y1%@NL@%
  21679.    Lowest = T.y1%@NL@%
  21680.    IF T.y2 > Highest THEN Highest = T.y2%@NL@%
  21681.    IF T.y2 < Lowest THEN Lowest = T.y2%@NL@%
  21682.    IF T.y3 > Highest THEN Highest = T.y3%@NL@%
  21683.    IF T.y3 < Lowest THEN Lowest = T.y3%@NL@%
  21684.    IF T.y4 > Highest THEN Highest = T.y4%@NL@%
  21685.    IF T.y4 < Lowest THEN Lowest = T.y4%@NL@%
  21686. %@NL@%
  21687. %@AB@%   ' Convert coordinates to pixels%@AE@%%@NL@%
  21688.    X = PMAP(T.xc, 0)%@NL@%
  21689.    YU = PMAP(T.yc, 1)%@NL@%
  21690.    YD = YU%@NL@%
  21691.    H = PMAP(Highest, 1)%@NL@%
  21692.    L = PMAP(Lowest, 1)%@NL@%
  21693. %@NL@%
  21694. %@AB@%   ' Search for top and bottom tile borders until we either find them%@AE@%%@NL@%
  21695. %@AB@%   ' both, or check beyond the highest and lowest points.%@AE@%%@NL@%
  21696. %@NL@%
  21697.    IsUp = FALSE%@NL@%
  21698.    IsDown = FALSE%@NL@%
  21699. %@NL@%
  21700.    DO%@NL@%
  21701.       YU = YU - 1%@NL@%
  21702.       YD = YD + 1%@NL@%
  21703. %@NL@%
  21704. %@AB@%      ' Search up%@AE@%%@NL@%
  21705.       IF NOT IsUp THEN%@NL@%
  21706.          IF POINT(T.xc, PMAP(YU, 3)) = Border THEN IsUp = TRUE%@NL@%
  21707.       END IF%@NL@%
  21708. %@NL@%
  21709. %@AB@%      ' Search down%@AE@%%@NL@%
  21710.       IF NOT IsDown THEN%@NL@%
  21711.          IF POINT(T.xc, PMAP(YD, 3)) = Border THEN IsDown = TRUE%@NL@%
  21712.       END IF%@NL@%
  21713. %@NL@%
  21714. %@AB@%      ' If top and bottom are found, we're inside%@AE@%%@NL@%
  21715.       IF IsUp AND IsDown THEN%@NL@%
  21716.          Inside = TRUE%@NL@%
  21717.          EXIT FUNCTION%@NL@%
  21718.       END IF%@NL@%
  21719. %@NL@%
  21720.    LOOP UNTIL (YD > L) AND (YU < H)%@NL@%
  21721.    Inside = FALSE%@NL@%
  21722. %@NL@%
  21723. END FUNCTION%@NL@%
  21724. %@NL@%
  21725. %@AB@%' ============================= Message ================================%@AE@%%@NL@%
  21726. %@AB@%'   Displays a status message followed by blinking dots.%@AE@%%@NL@%
  21727. %@AB@%' ======================================================================%@AE@%%@NL@%
  21728. %@AB@%'%@AE@%%@NL@%
  21729. SUB Message (Text$) STATIC%@NL@%
  21730. SHARED VC AS Config%@NL@%
  21731. %@NL@%
  21732.    LOCATE TROW, TCOL: PRINT SPACE$(19);%@NL@%
  21733.    LOCATE TROW, TCOL%@NL@%
  21734.    COLOR 7       ' White%@NL@%
  21735.    PRINT Text$;%@NL@%
  21736.    COLOR 23      ' Blink%@NL@%
  21737.    PRINT " . . .";%@NL@%
  21738.    COLOR 7       ' White%@NL@%
  21739. %@NL@%
  21740. END SUB%@NL@%
  21741. %@NL@%
  21742. %@AB@%' ============================ Rotated =================================%@AE@%%@NL@%
  21743. %@AB@%'   Returns the Current value adjusted by Inc and rotated if necessary%@AE@%%@NL@%
  21744. %@AB@%'   so that it falls within the range of Lower and Upper.%@AE@%%@NL@%
  21745. %@AB@%' ======================================================================%@AE@%%@NL@%
  21746. %@AB@%'%@AE@%%@NL@%
  21747. FUNCTION Rotated (Lower, Upper, Current, Inc)%@NL@%
  21748. %@NL@%
  21749. %@AB@%   ' Calculate the next value%@AE@%%@NL@%
  21750.    Current = Current + Inc%@NL@%
  21751. %@NL@%
  21752. %@AB@%   ' Handle special cases of rotating off top or bottom%@AE@%%@NL@%
  21753.    IF Current > Upper THEN Current = Lower%@NL@%
  21754.    IF Current < Lower THEN Current = Upper%@NL@%
  21755.    Rotated = Current%@NL@%
  21756. %@NL@%
  21757. END FUNCTION%@NL@%
  21758. %@NL@%
  21759. %@AB@%' ============================ SetConfig ===============================%@AE@%%@NL@%
  21760. %@AB@%'   Sets the correct values for each field of the VC variable. They%@AE@%%@NL@%
  21761. %@AB@%'   vary depending on Mode and on the current configuration.%@AE@%%@NL@%
  21762. %@AB@%' ======================================================================%@AE@%%@NL@%
  21763. %@AB@%'%@AE@%%@NL@%
  21764. SUB SetConfig (mode AS INTEGER) STATIC%@NL@%
  21765. SHARED VC AS Config, BestMode AS INTEGER%@NL@%
  21766. %@NL@%
  21767.    SELECT CASE mode%@NL@%
  21768.       CASE 1   ' Four-color graphics for CGA, EGA, VGA, and MCGA%@NL@%
  21769.          IF BestMode = CGA OR BestMode = MCGA THEN%@NL@%
  21770.             VC.Colors = 0%@NL@%
  21771.          ELSE%@NL@%
  21772.             VC.Colors = 16%@NL@%
  21773.          END IF%@NL@%
  21774.          VC.Atribs = 4%@NL@%
  21775.          VC.XPix = 319%@NL@%
  21776.          VC.YPix = 199%@NL@%
  21777.          VC.TCOL = 40%@NL@%
  21778.          VC.TROW = 25%@NL@%
  21779.       CASE 2   ' Two-color medium-res graphics for CGA, EGA, VGA, and MCGA%@NL@%
  21780.          IF BestMode = CGA OR BestMode = MCGA THEN%@NL@%
  21781.             VC.Colors = 0%@NL@%
  21782.          ELSE%@NL@%
  21783.             VC.Colors = 16%@NL@%
  21784.          END IF%@NL@%
  21785.          VC.Atribs = 2%@NL@%
  21786.          VC.XPix = 639%@NL@%
  21787.          VC.YPix = 199%@NL@%
  21788.          VC.TCOL = 80%@NL@%
  21789.          VC.TROW = 25%@NL@%
  21790.       CASE 3   ' Two-color high-res graphics for Hercules%@NL@%
  21791.          VC.Colors = 0%@NL@%
  21792.          VC.Atribs = 2%@NL@%
  21793.          VC.XPix = 720%@NL@%
  21794.          VC.YPix = 348%@NL@%
  21795.          VC.TCOL = 80%@NL@%
  21796.          VC.TROW = 25%@NL@%
  21797.       CASE 7   ' 16-color medium-res graphics for EGA and VGA%@NL@%
  21798.          VC.Colors = 16%@NL@%
  21799.          VC.Atribs = 16%@NL@%
  21800.          VC.XPix = 319%@NL@%
  21801.          VC.YPix = 199%@NL@%
  21802.          VC.TCOL = 40%@NL@%
  21803.          VC.TROW = 25%@NL@%
  21804.       CASE 8   ' 16-color high-res graphics for EGA and VGA%@NL@%
  21805.          VC.Colors = 16%@NL@%
  21806.          VC.Atribs = 16%@NL@%
  21807.          VC.XPix = 639%@NL@%
  21808.          VC.YPix = 199%@NL@%
  21809.          VC.TCOL = 80%@NL@%
  21810.          VC.TROW = 25%@NL@%
  21811.       CASE 9   ' 16- or 4-color very high-res graphics for EGA and VGA%@NL@%
  21812.          VC.Colors = 64%@NL@%
  21813.          IF BestMode = EGA64 THEN VC.Atribs = 4 ELSE VC.Atribs = 16%@NL@%
  21814.          VC.XPix = 639%@NL@%
  21815.          VC.YPix = 349%@NL@%
  21816.          VC.TCOL = 80%@NL@%
  21817.          VC.TROW = 25%@NL@%
  21818.       CASE 10  ' Two-color high-res graphics for EGA or VGA monochrome%@NL@%
  21819.          VC.Colors = 0%@NL@%
  21820.          VC.Atribs = 2%@NL@%
  21821.          VC.XPix = 319%@NL@%
  21822.          VC.YPix = 199%@NL@%
  21823.          VC.TCOL = 80%@NL@%
  21824.          VC.TROW = 25%@NL@%
  21825.       CASE 11  ' Two-color very high-res graphics for VGA and MCGA%@NL@%
  21826. %@AB@%         ' Note that for VGA screens 11, 12, and 13, more colors are%@AE@%%@NL@%
  21827. %@AB@%         ' available, depending on how the colors are mixed.%@AE@%%@NL@%
  21828.          VC.Colors = 216%@NL@%
  21829.          VC.Atribs = 2%@NL@%
  21830.          VC.XPix = 639%@NL@%
  21831.          VC.YPix = 479%@NL@%
  21832.          VC.TCOL = 80%@NL@%
  21833.          VC.TROW = 30%@NL@%
  21834.       CASE 12  ' 16-color very high-res graphics for VGA%@NL@%
  21835.          VC.Colors = 216%@NL@%
  21836.          VC.Atribs = 16%@NL@%
  21837.          VC.XPix = 639%@NL@%
  21838.          VC.YPix = 479%@NL@%
  21839.          VC.TCOL = 80%@NL@%
  21840.          VC.TROW = 30%@NL@%
  21841.       CASE 13  ' 256-color medium-res graphics for VGA and MCGA%@NL@%
  21842.          VC.Colors = 216%@NL@%
  21843.          VC.Atribs = 256%@NL@%
  21844.          VC.XPix = 639%@NL@%
  21845.          VC.YPix = 479%@NL@%
  21846.          VC.TCOL = 40%@NL@%
  21847.          VC.TROW = 25%@NL@%
  21848.       CASE ELSE%@NL@%
  21849.          VC.Colors = 16%@NL@%
  21850.          VC.Atribs = 16%@NL@%
  21851.          VC.XPix = 0%@NL@%
  21852.          VC.YPix = 0%@NL@%
  21853.          VC.TCOL = 80%@NL@%
  21854.          VC.TROW = 25%@NL@%
  21855.          VC.Scrn = 0%@NL@%
  21856.          EXIT SUB%@NL@%
  21857.    END SELECT%@NL@%
  21858.    VC.Scrn = mode%@NL@%
  21859. %@NL@%
  21860. END SUB%@NL@%
  21861. %@NL@%
  21862. %@AB@%' ============================ SetPalette ==============================%@AE@%%@NL@%
  21863. %@AB@%'   Mixes palette colors in an array.%@AE@%%@NL@%
  21864. %@AB@%' ======================================================================%@AE@%%@NL@%
  21865. %@AB@%'%@AE@%%@NL@%
  21866. SUB SetPalette STATIC%@NL@%
  21867. SHARED VC AS Config, Pal() AS LONG%@NL@%
  21868. %@NL@%
  21869. %@AB@%   ' Mix only if the adapter supports color attributes%@AE@%%@NL@%
  21870.    IF VC.Colors THEN%@NL@%
  21871.       SELECT CASE VC.Scrn%@NL@%
  21872.          CASE 1, 2, 7, 8%@NL@%
  21873. %@AB@%            ' Red, green, blue, and intense in four bits of a byte%@AE@%%@NL@%
  21874. %@AB@%            ' Bits: 0000irgb%@AE@%%@NL@%
  21875. %@AB@%            ' Change the order of FOR loops to change color mix%@AE@%%@NL@%
  21876.             Index = 0%@NL@%
  21877.             FOR Bs = 0 TO 1%@NL@%
  21878.                FOR Gs = 0 TO 1%@NL@%
  21879.                   FOR Rs = 0 TO 1%@NL@%
  21880.                      FOR Hs = 0 TO 1%@NL@%
  21881.                         Pal(Index) = Hs * 8 + Rs * 4 + Gs * 2 + Bs%@NL@%
  21882.                         Index = Index + 1%@NL@%
  21883.                      NEXT%@NL@%
  21884.                   NEXT%@NL@%
  21885.                NEXT%@NL@%
  21886.             NEXT%@NL@%
  21887.          CASE 9%@NL@%
  21888. %@AB@%            ' EGA red, green, and blue colors in 6 bits of a byte%@AE@%%@NL@%
  21889. %@AB@%            ' Capital letters repesent intense, lowercase normal%@AE@%%@NL@%
  21890. %@AB@%            ' Bits:  00rgbRGB%@AE@%%@NL@%
  21891. %@AB@%            ' Change the order of FOR loops to change color mix%@AE@%%@NL@%
  21892.             Index = 0%@NL@%
  21893.             FOR Bs = 0 TO 1%@NL@%
  21894.                FOR Gs = 0 TO 1%@NL@%
  21895.                   FOR Rs = 0 TO 1%@NL@%
  21896.                      FOR HRs = 0 TO 1%@NL@%
  21897.                         FOR HGs = 0 TO 1%@NL@%
  21898.                            FOR HBs = 0 TO 1%@NL@%
  21899.                               Pal(Index) = Rs * 32 + Gs * 16 + Bs * 8 + HRs * 4 + HGs * 2 + HBs%@NL@%
  21900.                               Index = Index + 1%@NL@%
  21901.                            NEXT%@NL@%
  21902.                         NEXT%@NL@%
  21903.                      NEXT%@NL@%
  21904.                   NEXT%@NL@%
  21905.                NEXT%@NL@%
  21906.             NEXT%@NL@%
  21907.          CASE 11, 12, 13%@NL@%
  21908. %@AB@%            ' VGA colors in 6 bits of 3 bytes of a long integer%@AE@%%@NL@%
  21909. %@AB@%            ' Bits:  000000000 00bbbbbb 00gggggg 00rrrrrr%@AE@%%@NL@%
  21910. %@AB@%            ' Change the order of FOR loops to change color mix%@AE@%%@NL@%
  21911. %@AB@%            ' Decrease the STEP and increase VC.Colors to get more colors%@AE@%%@NL@%
  21912.             Index = 0%@NL@%
  21913.             FOR Rs = 0 TO 63 STEP 11%@NL@%
  21914.                FOR Bs = 0 TO 63 STEP 11%@NL@%
  21915.                   FOR Gs = 0 TO 63 STEP 11%@NL@%
  21916.                      Pal(Index) = (65536 * Bs) + (256 * Gs) + Rs%@NL@%
  21917.                      Index = Index + 1%@NL@%
  21918.                   NEXT%@NL@%
  21919.                NEXT%@NL@%
  21920.             NEXT%@NL@%
  21921.          CASE ELSE%@NL@%
  21922.       END SELECT%@NL@%
  21923. %@AB@%      ' Assign colors%@AE@%%@NL@%
  21924.       IF VC.Atribs > 2 THEN TorusRotate RNDM%@NL@%
  21925.    END IF%@NL@%
  21926. %@NL@%
  21927. END SUB%@NL@%
  21928. %@NL@%
  21929. %@AB@%' ============================ TileDraw ================================%@AE@%%@NL@%
  21930. %@AB@%'   Draw and optionally paint a tile. Tiles are painted if there are%@AE@%%@NL@%
  21931. %@AB@%'   more than two atributes and if the inside of the tile can be found.%@AE@%%@NL@%
  21932. %@AB@%' ======================================================================%@AE@%%@NL@%
  21933. %@AB@%'%@AE@%%@NL@%
  21934. SUB TileDraw (T AS Tile) STATIC%@NL@%
  21935. SHARED VC AS Config, TOR AS TORUS%@NL@%
  21936. %@NL@%
  21937. %@AB@%   'Set border%@AE@%%@NL@%
  21938.    Border = VC.Atribs - 1%@NL@%
  21939. %@NL@%
  21940.    IF VC.Atribs = 2 THEN%@NL@%
  21941. %@AB@%      ' Draw and quit for two-color modes%@AE@%%@NL@%
  21942.       LINE (T.x1, T.y1)-(T.x2, T.y2), T.TColor%@NL@%
  21943.       LINE -(T.x3, T.y3), T.TColor%@NL@%
  21944.       LINE -(T.x4, T.y4), T.TColor%@NL@%
  21945.       LINE -(T.x1, T.y1), T.TColor%@NL@%
  21946.       EXIT SUB%@NL@%
  21947.    ELSE%@NL@%
  21948. %@AB@%      ' For other modes, draw in the border color%@AE@%%@NL@%
  21949. %@AB@%      ' (which must be different than any tile color)%@AE@%%@NL@%
  21950.       LINE (T.x1, T.y1)-(T.x2, T.y2), Border%@NL@%
  21951.       LINE -(T.x3, T.y3), Border%@NL@%
  21952.       LINE -(T.x4, T.y4), Border%@NL@%
  21953.       LINE -(T.x1, T.y1), Border%@NL@%
  21954.    END IF%@NL@%
  21955. %@NL@%
  21956. %@AB@%   ' See if tile is large enough to be painted%@AE@%%@NL@%
  21957.    IF Inside(T) THEN%@NL@%
  21958. %@AB@%      'Black out the center to make sure it isn't paint color%@AE@%%@NL@%
  21959.       PRESET (T.xc, T.yc)%@NL@%
  21960. %@AB@%      ' Paint tile black so colors of underlying tiles can't interfere%@AE@%%@NL@%
  21961.       PAINT STEP(0, 0), BACK, Border%@NL@%
  21962. %@AB@%      ' Fill with the final tile color.%@AE@%%@NL@%
  21963.       PAINT STEP(0, 0), T.TColor, Border%@NL@%
  21964.    END IF%@NL@%
  21965. %@NL@%
  21966. %@AB@%   ' A border drawn with the background color looks like a border.%@AE@%%@NL@%
  21967. %@AB@%   ' One drawn with the tile color doesn't look like a border.%@AE@%%@NL@%
  21968.    IF TOR.Bord = "YES" THEN%@NL@%
  21969.       Border = BACK%@NL@%
  21970.    ELSE%@NL@%
  21971.       Border = T.TColor%@NL@%
  21972.    END IF%@NL@%
  21973. %@NL@%
  21974. %@AB@%   ' Redraw with the final border%@AE@%%@NL@%
  21975.    LINE (T.x1, T.y1)-(T.x2, T.y2), Border%@NL@%
  21976.    LINE -(T.x3, T.y3), Border%@NL@%
  21977.    LINE -(T.x4, T.y4), Border%@NL@%
  21978.    LINE -(T.x1, T.y1), Border%@NL@%
  21979. %@NL@%
  21980. END SUB%@NL@%
  21981. %@NL@%
  21982. DEFSNG A-Z%@NL@%
  21983. %@AB@%' =========================== TorusCalc ================================%@AE@%%@NL@%
  21984. %@AB@%'   Calculates the x and y coordinates for each tile.%@AE@%%@NL@%
  21985. %@AB@%' ======================================================================%@AE@%%@NL@%
  21986. %@AB@%'%@AE@%%@NL@%
  21987. SUB TorusCalc (T() AS Tile) STATIC%@NL@%
  21988. SHARED TOR AS TORUS, Max AS INTEGER%@NL@%
  21989. DIM XSect AS INTEGER, YPanel AS INTEGER%@NL@%
  21990. %@NL@%
  21991. %@AB@%   ' Calculate sine and cosine of the angles of rotation%@AE@%%@NL@%
  21992.    XRot = DegToRad(TOR.XDegree)%@NL@%
  21993.    YRot = DegToRad(TOR.YDegree)%@NL@%
  21994.    CXRot = COS(XRot)%@NL@%
  21995.    SXRot = SIN(XRot)%@NL@%
  21996.    CYRot = COS(YRot)%@NL@%
  21997.    SYRot = SIN(YRot)%@NL@%
  21998. %@NL@%
  21999. %@AB@%   ' Calculate the angle to increment between one tile and the next.%@AE@%%@NL@%
  22000.    XInc = 2 * PI / TOR.Sect%@NL@%
  22001.    YInc = 2 * PI / TOR.Panel%@NL@%
  22002. %@NL@%
  22003. %@AB@%   ' First calculate the first point, which will be used as a reference%@AE@%%@NL@%
  22004. %@AB@%   ' for future points. This point must be calculated separately because%@AE@%%@NL@%
  22005. %@AB@%   ' it is both the beginning and the end of the center seam.%@AE@%%@NL@%
  22006.    FirstY = (TOR.Thick + 1) * CYRot%@NL@%
  22007. %@NL@%
  22008. %@AB@%   ' Starting point is x1 of 0 section, 0 panel     last     0%@AE@%%@NL@%
  22009.    T(0).x1 = FirstY                             ' +------+------+%@NL@%
  22010. %@AB@%   ' Also x2 of tile on last section, 0 panel   ' |      |      | last%@AE@%%@NL@%
  22011.    T(TOR.Sect - 1).x2 = FirstY                  ' |    x3|x4    |%@NL@%
  22012. %@AB@%   ' Also x3 of last section, last panel        ' +------+------+%@AE@%%@NL@%
  22013.    T(Max - 1).x3 = FirstY                       ' |    x2|x1    |  0%@NL@%
  22014. %@AB@%   ' Also x4 of 0 section, last panel           ' |      |      |%@AE@%%@NL@%
  22015.    T(Max - TOR.Sect).x4 = FirstY                ' +------+------+%@NL@%
  22016. %@AB@%   ' A similar pattern is used for assigning all points of Torus%@AE@%%@NL@%
  22017. %@NL@%
  22018. %@AB@%   ' Starting Y point is 0 (center)%@AE@%%@NL@%
  22019.    T(0).y1 = 0%@NL@%
  22020.    T(TOR.Sect - 1).y2 = 0%@NL@%
  22021.    T(Max - 1).y3 = 0%@NL@%
  22022.    T(Max - TOR.Sect).y4 = 0%@NL@%
  22023. %@NL@%
  22024. %@AB@%   ' Only one z coordinate is used in sort, so other three can be ignored%@AE@%%@NL@%
  22025.    T(0).z1 = -(TOR.Thick + 1) * SYRot%@NL@%
  22026. %@NL@%
  22027. %@AB@%   ' Starting at first point, work around the center seam of the Torus.%@AE@%%@NL@%
  22028. %@AB@%   ' Assign points for each section. The seam must be calculated separately%@AE@%%@NL@%
  22029. %@AB@%   ' because it is both beginning and of each section.%@AE@%%@NL@%
  22030.    FOR XSect = 1 TO TOR.Sect - 1%@NL@%
  22031. %@NL@%
  22032. %@AB@%      ' X, Y, and Z elements of equation%@AE@%%@NL@%
  22033.       sx = (TOR.Thick + 1) * COS(XSect * XInc)%@NL@%
  22034.       sy = (TOR.Thick + 1) * SIN(XSect * XInc) * CXRot%@NL@%
  22035.       sz = (TOR.Thick + 1) * SIN(XSect * XInc) * SXRot%@NL@%
  22036.       ssx = (sz * SYRot) + (sx * CYRot)%@NL@%
  22037. %@NL@%
  22038.       T(XSect).x1 = ssx%@NL@%
  22039.       T(XSect - 1).x2 = ssx%@NL@%
  22040.       T(Max - TOR.Sect + XSect - 1).x3 = ssx%@NL@%
  22041.       T(Max - TOR.Sect + XSect).x4 = ssx%@NL@%
  22042. %@NL@%
  22043.       T(XSect).y1 = sy%@NL@%
  22044.       T(XSect - 1).y2 = sy%@NL@%
  22045.       T(Max - TOR.Sect + XSect - 1).y3 = sy%@NL@%
  22046.       T(Max - TOR.Sect + XSect).y4 = sy%@NL@%
  22047. %@NL@%
  22048.       T(XSect).z1 = (sz * CYRot) - (sx * SYRot)%@NL@%
  22049.    NEXT%@NL@%
  22050. %@NL@%
  22051. %@AB@%   ' Now start at the first seam between panel and assign points for%@AE@%%@NL@%
  22052. %@AB@%   ' each section of each panel. The outer loop assigns the initial%@AE@%%@NL@%
  22053. %@AB@%   ' point for the panel. This point must be calculated separately%@AE@%%@NL@%
  22054. %@AB@%   ' since it is both the beginning and the end of the seam of panels.%@AE@%%@NL@%
  22055.    FOR YPanel = 1 TO TOR.Panel - 1%@NL@%
  22056. %@NL@%
  22057. %@AB@%      ' X, Y, and Z elements of equation%@AE@%%@NL@%
  22058.       sx = TOR.Thick + COS(YPanel * YInc)%@NL@%
  22059.       sy = -SIN(YPanel * YInc) * SXRot%@NL@%
  22060.       sz = SIN(YPanel * YInc) * CXRot%@NL@%
  22061.       ssx = (sz * SYRot) + (sx * CYRot)%@NL@%
  22062. %@NL@%
  22063. %@AB@%      ' Assign X points for each panel%@AE@%%@NL@%
  22064. %@AB@%      ' Current ring, current side%@AE@%%@NL@%
  22065.       T(TOR.Sect * YPanel).x1 = ssx%@NL@%
  22066. %@AB@%      ' Current ring minus 1, next side%@AE@%%@NL@%
  22067.       T(TOR.Sect * (YPanel + 1) - 1).x2 = ssx%@NL@%
  22068. %@AB@%      ' Current ring minus 1, previous side%@AE@%%@NL@%
  22069.       T(TOR.Sect * YPanel - 1).x3 = ssx%@NL@%
  22070. %@AB@%      ' Current ring, previous side%@AE@%%@NL@%
  22071.       T(TOR.Sect * (YPanel - 1)).x4 = ssx%@NL@%
  22072. %@NL@%
  22073. %@AB@%      ' Assign Y points for each panel%@AE@%%@NL@%
  22074.       T(TOR.Sect * YPanel).y1 = sy%@NL@%
  22075.       T(TOR.Sect * (YPanel + 1) - 1).y2 = sy%@NL@%
  22076.       T(TOR.Sect * YPanel - 1).y3 = sy%@NL@%
  22077.       T(TOR.Sect * (YPanel - 1)).y4 = sy%@NL@%
  22078. %@NL@%
  22079. %@AB@%      ' Z point for each panel%@AE@%%@NL@%
  22080.       T(TOR.Sect * YPanel).z1 = (sz * CYRot) - (sx * SYRot)%@NL@%
  22081. %@NL@%
  22082. %@AB@%      ' The inner loop assigns points for each ring (except the first)%@AE@%%@NL@%
  22083. %@AB@%      ' on the current side.%@AE@%%@NL@%
  22084.       FOR XSect = 1 TO TOR.Sect - 1%@NL@%
  22085. %@NL@%
  22086. %@AB@%         ' Display section and panel%@AE@%%@NL@%
  22087.          CountTiles XSect, YPanel%@NL@%
  22088. %@NL@%
  22089.          ty = (TOR.Thick + COS(YPanel * YInc)) * SIN(XSect * XInc)%@NL@%
  22090.          tz = SIN(YPanel * YInc)%@NL@%
  22091.          sx = (TOR.Thick + COS(YPanel * YInc)) * COS(XSect * XInc)%@NL@%
  22092.          sy = ty * CXRot - tz * SXRot%@NL@%
  22093.          sz = ty * SXRot + tz * CXRot%@NL@%
  22094.          ssx = (sz * SYRot) + (sx * CYRot)%@NL@%
  22095. %@NL@%
  22096.          T(TOR.Sect * YPanel + XSect).x1 = ssx%@NL@%
  22097.          T(TOR.Sect * YPanel + XSect - 1).x2 = ssx%@NL@%
  22098.          T(TOR.Sect * (YPanel - 1) + XSect - 1).x3 = ssx%@NL@%
  22099.          T(TOR.Sect * (YPanel - 1) + XSect).x4 = ssx%@NL@%
  22100. %@NL@%
  22101.          T(TOR.Sect * YPanel + XSect).y1 = sy%@NL@%
  22102.          T(TOR.Sect * YPanel + XSect - 1).y2 = sy%@NL@%
  22103.          T(TOR.Sect * (YPanel - 1) + XSect - 1).y3 = sy%@NL@%
  22104.          T(TOR.Sect * (YPanel - 1) + XSect).y4 = sy%@NL@%
  22105. %@NL@%
  22106.          T(TOR.Sect * YPanel + XSect).z1 = (sz * CYRot) - (sx * SYRot)%@NL@%
  22107.       NEXT%@NL@%
  22108.    NEXT%@NL@%
  22109. %@AB@%   ' Erase message%@AE@%%@NL@%
  22110.    CountTiles -1, -1%@NL@%
  22111. %@NL@%
  22112. END SUB%@NL@%
  22113. %@NL@%
  22114. DEFINT A-Z%@NL@%
  22115. %@AB@%' =========================== TorusColor ===============================%@AE@%%@NL@%
  22116. %@AB@%'   Assigns color atributes to each tile.%@AE@%%@NL@%
  22117. %@AB@%' ======================================================================%@AE@%%@NL@%
  22118. %@AB@%'%@AE@%%@NL@%
  22119. SUB TorusColor (T() AS Tile) STATIC%@NL@%
  22120. SHARED VC AS Config, Max AS INTEGER%@NL@%
  22121. %@NL@%
  22122. %@AB@%   ' Skip first and last atributes%@AE@%%@NL@%
  22123.    LastAtr = VC.Atribs - 2%@NL@%
  22124.    Atr = 1%@NL@%
  22125. %@NL@%
  22126. %@AB@%   ' Cycle through each attribute until all tiles are done%@AE@%%@NL@%
  22127.    FOR Til = 0 TO Max - 1%@NL@%
  22128.       IF (Atr >= LastAtr) THEN%@NL@%
  22129.          Atr = 1%@NL@%
  22130.       ELSE%@NL@%
  22131.          Atr = Atr + 1%@NL@%
  22132.       END IF%@NL@%
  22133.       T(Til).TColor = Atr%@NL@%
  22134.    NEXT%@NL@%
  22135. %@NL@%
  22136. END SUB%@NL@%
  22137. %@NL@%
  22138. %@AB@%' ============================ TorusDefine =============================%@AE@%%@NL@%
  22139. %@AB@%'   Define the attributes of a Torus based on information from the%@AE@%%@NL@%
  22140. %@AB@%'   user, the video configuration, and the current screen mode.%@AE@%%@NL@%
  22141. %@AB@%' ======================================================================%@AE@%%@NL@%
  22142. %@AB@%'%@AE@%%@NL@%
  22143. SUB TorusDefine STATIC%@NL@%
  22144. SHARED VC AS Config, TOR AS TORUS, Available AS STRING%@NL@%
  22145. %@NL@%
  22146. %@AB@%' Constants for key codes and column positions%@AE@%%@NL@%
  22147. CONST ENTER = 13, ESCAPE = 27%@NL@%
  22148. CONST DOWNARROW = 80, UPARROW = 72, LEFTARROW = 75, RIGHTARROW = 77%@NL@%
  22149. CONST COL1 = 20, COL2 = 50, ROW = 9%@NL@%
  22150. %@NL@%
  22151. %@AB@%   ' Display key instructions%@AE@%%@NL@%
  22152.    LOCATE 1, COL1%@NL@%
  22153.    PRINT "UP .............. Move to next field"%@NL@%
  22154.    LOCATE 2, COL1%@NL@%
  22155.    PRINT "DOWN ........ Move to previous field"%@NL@%
  22156.    LOCATE 3, COL1%@NL@%
  22157.    PRINT "LEFT ......... Rotate field value up"%@NL@%
  22158.    LOCATE 4, COL1%@NL@%
  22159.    PRINT "RIGHT ...... Rotate field value down"%@NL@%
  22160.    LOCATE 5, COL1%@NL@%
  22161.    PRINT "ENTER .... Start with current values"%@NL@%
  22162.    LOCATE 6, COL1%@NL@%
  22163.    PRINT "ESCAPE .................. Quit Torus"%@NL@%
  22164. %@NL@%
  22165. %@AB@%   ' Block cursor%@AE@%%@NL@%
  22166.    LOCATE ROW, COL1, 1, 1, 12%@NL@%
  22167. %@AB@%   ' Display fields%@AE@%%@NL@%
  22168.    LOCATE ROW, COL1: PRINT "Thickness";%@NL@%
  22169.    LOCATE ROW, COL2: PRINT USING "[ # ]"; TOR.Thick;%@NL@%
  22170. %@NL@%
  22171.    LOCATE ROW + 2, COL1: PRINT "Panels per Section";%@NL@%
  22172.    LOCATE ROW + 2, COL2: PRINT USING "[ ## ]"; TOR.Panel;%@NL@%
  22173. %@NL@%
  22174.    LOCATE ROW + 4, COL1: PRINT "Sections per Torus";%@NL@%
  22175.    LOCATE ROW + 4, COL2: PRINT USING "[ ## ]"; TOR.Sect;%@NL@%
  22176. %@NL@%
  22177.    LOCATE ROW + 6, COL1: PRINT "Tilt around Horizontal Axis";%@NL@%
  22178.    LOCATE ROW + 6, COL2: PRINT USING "[ ### ]"; TOR.XDegree;%@NL@%
  22179. %@NL@%
  22180.    LOCATE ROW + 8, COL1: PRINT "Tilt around Vertical Axis";%@NL@%
  22181.    LOCATE ROW + 8, COL2: PRINT USING "[ ### ]"; TOR.YDegree;%@NL@%
  22182. %@NL@%
  22183.    LOCATE ROW + 10, COL1: PRINT "Tile Border";%@NL@%
  22184.    LOCATE ROW + 10, COL2: PRINT USING "[ & ] "; TOR.Bord;%@NL@%
  22185. %@NL@%
  22186.    LOCATE ROW + 12, COL1: PRINT "Screen Mode";%@NL@%
  22187.    LOCATE ROW + 12, COL2: PRINT USING "[ ## ]"; VC.Scrn%@NL@%
  22188. %@NL@%
  22189. %@AB@%   ' Skip field 10 if there's only one value%@AE@%%@NL@%
  22190.    IF LEN(Available$) = 1 THEN Fields = 10 ELSE Fields = 12%@NL@%
  22191. %@NL@%
  22192. %@AB@%   ' Update field values and position based on keystrokes%@AE@%%@NL@%
  22193.    DO%@NL@%
  22194. %@AB@%      ' Put cursor on field%@AE@%%@NL@%
  22195.       LOCATE ROW + Fld, COL2 + 2%@NL@%
  22196. %@AB@%      ' Get a key and strip null off if it's an extended code%@AE@%%@NL@%
  22197.       DO%@NL@%
  22198.          K$ = INKEY$%@NL@%
  22199.       LOOP WHILE K$ = ""%@NL@%
  22200.       Ky = ASC(RIGHT$(K$, 1))%@NL@%
  22201. %@NL@%
  22202.       SELECT CASE Ky%@NL@%
  22203.          CASE ESCAPE%@NL@%
  22204. %@AB@%            ' End program%@AE@%%@NL@%
  22205.             CLS : END%@NL@%
  22206.          CASE UPARROW, DOWNARROW%@NL@%
  22207. %@AB@%            ' Adjust field location%@AE@%%@NL@%
  22208.             IF Ky = DOWNARROW THEN Inc = 2 ELSE Inc = -2%@NL@%
  22209.             Fld = Rotated(0, Fields, Fld, Inc)%@NL@%
  22210.          CASE RIGHTARROW, LEFTARROW%@NL@%
  22211. %@AB@%            ' Adjust field%@AE@%%@NL@%
  22212.             IF Ky = RIGHTARROW THEN Inc = 1 ELSE Inc = -1%@NL@%
  22213.             SELECT CASE Fld%@NL@%
  22214.                CASE 0%@NL@%
  22215. %@AB@%                  ' Thickness%@AE@%%@NL@%
  22216.                   TOR.Thick = Rotated(1, 9, INT(TOR.Thick), Inc)%@NL@%
  22217.                   PRINT USING "#"; TOR.Thick%@NL@%
  22218.                CASE 2%@NL@%
  22219. %@AB@%                  ' Panels%@AE@%%@NL@%
  22220.                   TOR.Panel = Rotated(6, 20, TOR.Panel, Inc)%@NL@%
  22221.                   PRINT USING "##"; TOR.Panel%@NL@%
  22222.                CASE 4%@NL@%
  22223. %@AB@%                  ' Sections%@AE@%%@NL@%
  22224.                   TOR.Sect = Rotated(6, 20, TOR.Sect, Inc)%@NL@%
  22225.                   PRINT USING "##"; TOR.Sect%@NL@%
  22226.                CASE 6%@NL@%
  22227. %@AB@%                  ' Horizontal tilt%@AE@%%@NL@%
  22228.                   TOR.XDegree = Rotated(0, 345, TOR.XDegree, (15 * Inc))%@NL@%
  22229.                   PRINT USING "###"; TOR.XDegree%@NL@%
  22230.                CASE 8%@NL@%
  22231. %@AB@%                  ' Vertical tilt%@AE@%%@NL@%
  22232.                   TOR.YDegree = Rotated(0, 345, TOR.YDegree, (15 * Inc))%@NL@%
  22233.                   PRINT USING "###"; TOR.YDegree%@NL@%
  22234.                CASE 10%@NL@%
  22235. %@AB@%                  ' Border%@AE@%%@NL@%
  22236.                   IF VC.Atribs > 2 THEN%@NL@%
  22237.                      IF TOR.Bord = "YES" THEN%@NL@%
  22238.                         TOR.Bord = "NO"%@NL@%
  22239.                      ELSE%@NL@%
  22240.                         TOR.Bord = "YES"%@NL@%
  22241.                      END IF%@NL@%
  22242.                   END IF%@NL@%
  22243.                   PRINT TOR.Bord%@NL@%
  22244.                CASE 12%@NL@%
  22245. %@AB@%                  ' Available screen modes%@AE@%%@NL@%
  22246.                   I = INSTR(Available$, HEX$(VC.Scrn))%@NL@%
  22247.                   I = Rotated(1, LEN(Available$), I, Inc)%@NL@%
  22248.                   VC.Scrn = VAL("&h" + MID$(Available$, I, 1))%@NL@%
  22249.                   PRINT USING "##"; VC.Scrn%@NL@%
  22250.                CASE ELSE%@NL@%
  22251.             END SELECT%@NL@%
  22252.          CASE ELSE%@NL@%
  22253.       END SELECT%@NL@%
  22254. %@AB@%   ' Set configuration data for graphics mode%@AE@%%@NL@%
  22255.    SetConfig VC.Scrn%@NL@%
  22256. %@AB@%   ' Draw Torus if ENTER%@AE@%%@NL@%
  22257.    LOOP UNTIL Ky = ENTER%@NL@%
  22258. %@NL@%
  22259. %@AB@%   ' Remove cursor%@AE@%%@NL@%
  22260.    LOCATE 1, 1, 0%@NL@%
  22261. %@NL@%
  22262. %@AB@%   ' Set different delays depending on mode%@AE@%%@NL@%
  22263.    SELECT CASE VC.Scrn%@NL@%
  22264.       CASE 1%@NL@%
  22265.          TOR.Delay = .3%@NL@%
  22266.       CASE 2, 3, 10, 11, 13%@NL@%
  22267.          TOR.Delay = 0%@NL@%
  22268.       CASE ELSE%@NL@%
  22269.          TOR.Delay = .05%@NL@%
  22270.    END SELECT%@NL@%
  22271. %@NL@%
  22272. %@AB@%   ' Get new random seed for this torus%@AE@%%@NL@%
  22273.    RANDOMIZE TIMER%@NL@%
  22274. %@NL@%
  22275. END SUB%@NL@%
  22276. %@NL@%
  22277. %@AB@%' =========================== TorusDraw ================================%@AE@%%@NL@%
  22278. %@AB@%'   Draws each tile of the torus starting with the farthest and working%@AE@%%@NL@%
  22279. %@AB@%'   to the closest. Thus nearer tiles overwrite farther tiles to give%@AE@%%@NL@%
  22280. %@AB@%'   a three-dimensional effect. Notice that the index of the tile being%@AE@%%@NL@%
  22281. %@AB@%'   drawn is actually the index of an array of indexes. This is because%@AE@%%@NL@%
  22282. %@AB@%'   the array of tiles is not sorted, but the parallel array of indexes%@AE@%%@NL@%
  22283. %@AB@%'   is. See TorusSort for an explanation of how indexes are sorted.%@AE@%%@NL@%
  22284. %@AB@%' ======================================================================%@AE@%%@NL@%
  22285. %@AB@%'%@AE@%%@NL@%
  22286. SUB TorusDraw (T() AS Tile, Index() AS INTEGER)%@NL@%
  22287. SHARED Max AS INTEGER%@NL@%
  22288. %@NL@%
  22289.    FOR Til = 0 TO Max - 1%@NL@%
  22290.       TileDraw T(Index(Til))%@NL@%
  22291.    NEXT%@NL@%
  22292. %@NL@%
  22293. END SUB%@NL@%
  22294. %@NL@%
  22295. %@AB@%' =========================== TorusRotate ==============================%@AE@%%@NL@%
  22296. %@AB@%'   Rotates the Torus. This can be done more successfully in some modes%@AE@%%@NL@%
  22297. %@AB@%'   than in others. There are three methods:%@AE@%%@NL@%
  22298. %@AB@%'%@AE@%%@NL@%
  22299. %@AB@%'     1. Rotate the palette colors assigned to each attribute%@AE@%%@NL@%
  22300. %@AB@%'     2. Draw, erase, and redraw the torus (two-color modes)%@AE@%%@NL@%
  22301. %@AB@%'     3. Rotate between two palettes (CGA and MCGA screen 1)%@AE@%%@NL@%
  22302. %@AB@%'%@AE@%%@NL@%
  22303. %@AB@%'   Note that for EGA and VGA screen 2, methods 1 and 2 are both used.%@AE@%%@NL@%
  22304. %@AB@%' ======================================================================%@AE@%%@NL@%
  22305. %@AB@%'%@AE@%%@NL@%
  22306. SUB TorusRotate (First) STATIC%@NL@%
  22307. SHARED VC AS Config, TOR AS TORUS, Pal() AS LONG, Max AS INTEGER%@NL@%
  22308. SHARED T() AS Tile, Index() AS INTEGER, BestMode AS INTEGER%@NL@%
  22309. DIM Temp AS LONG%@NL@%
  22310. %@NL@%
  22311. %@AB@%   ' For EGA and higher rotate colors through palette%@AE@%%@NL@%
  22312.    IF VC.Colors THEN%@NL@%
  22313. %@NL@%
  22314. %@AB@%      ' Argument determines whether to start at next color, first color,%@AE@%%@NL@%
  22315. %@AB@%      ' or random color%@AE@%%@NL@%
  22316.       SELECT CASE First%@NL@%
  22317.          CASE RNDM%@NL@%
  22318.             FirstClr = INT(RND * VC.Colors)%@NL@%
  22319.          CASE START%@NL@%
  22320.             FirstClr = 0%@NL@%
  22321.          CASE ELSE%@NL@%
  22322.             FirstClr = FirstClr - 1%@NL@%
  22323.       END SELECT%@NL@%
  22324. %@NL@%
  22325. %@AB@%      ' Set last color to smaller of last possible color or last tile%@AE@%%@NL@%
  22326.       IF VC.Colors > Max - 1 THEN%@NL@%
  22327.          LastClr = Max - 1%@NL@%
  22328.       ELSE%@NL@%
  22329.          LastClr = VC.Colors - 1%@NL@%
  22330.       END IF%@NL@%
  22331. %@NL@%
  22332. %@AB@%      ' If color is too low, rotate to end%@AE@%%@NL@%
  22333.       IF FirstClr < 0 OR FirstClr >= LastClr THEN FirstClr = LastClr%@NL@%
  22334. %@NL@%
  22335. %@AB@%      ' Set last attribute%@AE@%%@NL@%
  22336.       IF VC.Atribs = 2 THEN%@NL@%
  22337. %@AB@%         ' Last for two-color modes%@AE@%%@NL@%
  22338.          LastAtr = VC.Atribs - 1%@NL@%
  22339.       ELSE%@NL@%
  22340. %@AB@%         ' Smaller of last color or next-to-last attribute%@AE@%%@NL@%
  22341.          IF LastClr < VC.Atribs - 2 THEN%@NL@%
  22342.             LastAtr = LastClr%@NL@%
  22343.          ELSE%@NL@%
  22344.             LastAtr = VC.Atribs - 2%@NL@%
  22345.          END IF%@NL@%
  22346.       END IF%@NL@%
  22347. %@NL@%
  22348. %@AB@%      ' Cycle through attributes, assigning colors%@AE@%%@NL@%
  22349.       Work = FirstClr%@NL@%
  22350.       FOR Atr = LastAtr TO 1 STEP -1%@NL@%
  22351.          PALETTE Atr, Pal(Work)%@NL@%
  22352.          Work = Work - 1%@NL@%
  22353.          IF Work < 0 THEN Work = LastClr%@NL@%
  22354.       NEXT%@NL@%
  22355. %@NL@%
  22356.    END IF%@NL@%
  22357. %@NL@%
  22358. %@AB@%   ' For two-color screens, the best we can do is erase and redraw the torus%@AE@%%@NL@%
  22359.    IF VC.Atribs = 2 THEN%@NL@%
  22360. %@NL@%
  22361. %@AB@%      ' Set all tiles to color%@AE@%%@NL@%
  22362.       FOR I = 0 TO Max - 1%@NL@%
  22363.          T(I).TColor = Toggle%@NL@%
  22364.       NEXT%@NL@%
  22365. %@AB@%      ' Draw Torus%@AE@%%@NL@%
  22366.       TorusDraw T(), Index()%@NL@%
  22367. %@AB@%      ' Toggle between color and background%@AE@%%@NL@%
  22368.       Toggle = (Toggle + 1) MOD 2%@NL@%
  22369. %@NL@%
  22370.    END IF%@NL@%
  22371. %@NL@%
  22372. %@AB@%   ' For CGA or MCGA screen 1, toggle palettes using the COLOR statement%@AE@%%@NL@%
  22373. %@AB@%   ' (these modes do not allow the PALETTE statement)%@AE@%%@NL@%
  22374.    IF VC.Scrn = 1 AND (BestMode = CGA OR BestMode = MCGA) THEN%@NL@%
  22375.       COLOR , Toggle%@NL@%
  22376.       Toggle = (Toggle + 1) MOD 2%@NL@%
  22377.       EXIT SUB%@NL@%
  22378.    END IF%@NL@%
  22379. %@NL@%
  22380. END SUB%@NL@%
  22381. %@NL@%
  22382. %@AB@%' ============================ TorusSort ===============================%@AE@%%@NL@%
  22383. %@AB@%'   Sorts the tiles of the Torus according to their Z axis (distance%@AE@%%@NL@%
  22384. %@AB@%'   from the "front" of the screen). When the tiles are drawn, the%@AE@%%@NL@%
  22385. %@AB@%'   farthest will be drawn first, and nearer tiles will overwrite them%@AE@%%@NL@%
  22386. %@AB@%'   to give a three-dimensional effect.%@AE@%%@NL@%
  22387. %@AB@%'%@AE@%%@NL@%
  22388. %@AB@%'   To make sorting as fast as possible, the Quick Sort algorithm is%@AE@%%@NL@%
  22389. %@AB@%'   used. Also, the array of tiles is not actually sorted. Instead a%@AE@%%@NL@%
  22390. %@AB@%'   parallel array of tile indexes is sorted. This complicates things,%@AE@%%@NL@%
  22391. %@AB@%'   but makes the sort much faster, since two-byte integers are swapped%@AE@%%@NL@%
  22392. %@AB@%'   instead of 46-byte Tile variables.%@AE@%%@NL@%
  22393. %@AB@%' ======================================================================%@AE@%%@NL@%
  22394. %@AB@%'%@AE@%%@NL@%
  22395. SUB TorusSort (Low, High)%@NL@%
  22396. SHARED T() AS Tile, Index() AS INTEGER%@NL@%
  22397. DIM Partition AS SINGLE%@NL@%
  22398. %@NL@%
  22399.    IF Low < High THEN%@NL@%
  22400. %@AB@%      ' If only one, compare and swap if necessary%@AE@%%@NL@%
  22401. %@AB@%      ' The SUB procedure only stops recursing when it reaches this point%@AE@%%@NL@%
  22402.       IF High - Low = 1 THEN%@NL@%
  22403.          IF T(Index(Low)).z1 > T(Index(High)).z1 THEN%@NL@%
  22404.             CountTiles High, Low%@NL@%
  22405.             SWAP Index(Low), Index(High)%@NL@%
  22406.          END IF%@NL@%
  22407.       ELSE%@NL@%
  22408. %@AB@%      ' If more than one, separate into two random groups%@AE@%%@NL@%
  22409.          RandIndex = INT(RND * (High - Low + 1)) + Low%@NL@%
  22410.          CountTiles High, Low%@NL@%
  22411.          SWAP Index(High), Index(RandIndex%)%@NL@%
  22412.          Partition = T(Index(High)).z1%@NL@%
  22413. %@AB@%         ' Sort one group%@AE@%%@NL@%
  22414.          DO%@NL@%
  22415.             I = Low: J = High%@NL@%
  22416. %@AB@%            ' Find the largest%@AE@%%@NL@%
  22417.             DO WHILE (I < J) AND (T(Index(I)).z1 <= Partition)%@NL@%
  22418.                I = I + 1%@NL@%
  22419.             LOOP%@NL@%
  22420. %@AB@%            ' Find the smallest%@AE@%%@NL@%
  22421.             DO WHILE (J > I) AND (T(Index(J)).z1 >= Partition)%@NL@%
  22422.                J = J - 1%@NL@%
  22423.             LOOP%@NL@%
  22424. %@AB@%            ' Swap them if necessary%@AE@%%@NL@%
  22425.             IF I < J THEN%@NL@%
  22426.                CountTiles High, Low%@NL@%
  22427.                SWAP Index(I), Index(J)%@NL@%
  22428.             END IF%@NL@%
  22429.          LOOP WHILE I < J%@NL@%
  22430. %@NL@%
  22431. %@AB@%         ' Now get the other group and recursively sort it%@AE@%%@NL@%
  22432.          CountTiles High, Low%@NL@%
  22433.          SWAP Index(I), Index(High)%@NL@%
  22434.          IF (I - Low) < (High - I) THEN%@NL@%
  22435.             TorusSort Low, I - 1%@NL@%
  22436.             TorusSort I + 1, High%@NL@%
  22437.          ELSE%@NL@%
  22438.             TorusSort I + 1, High%@NL@%
  22439.             TorusSort Low, I - 1%@NL@%
  22440.          END IF%@NL@%
  22441.       END IF%@NL@%
  22442.    END IF%@NL@%
  22443. %@NL@%
  22444. END SUB%@NL@%
  22445. %@NL@%
  22446. %@NL@%
  22447. %@NL@%
  22448. %@2@%%@AH@%UIASM.ASM%@AE@%%@EH@%%@NL@%
  22449. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\UIASM.ASM%@AE@%%@NL@%
  22450. %@NL@%
  22451. %@AB@%;-----------------------------------------------------------------------------%@AE@%%@NL@%
  22452. %@AB@%;-----------------------------------------------------------------------------%@AE@%%@NL@%
  22453. %@AB@%;%@AE@%%@NL@%
  22454. %@AB@%;  UIASM.ASM%@AE@%%@NL@%
  22455. %@AB@%;%@AE@%%@NL@%
  22456. %@AB@%;  Copyright (C) 1989 Microsoft Corporation, All Rights Reserved%@AE@%%@NL@%
  22457. %@AB@%;%@AE@%%@NL@%
  22458. %@AB@%;  GetCopyBox : Gets screen box info and places into string variable%@AE@%%@NL@%
  22459. %@AB@%;  PutCopyBox : Puts screen box info from string variable onto screen%@AE@%%@NL@%
  22460. %@AB@%;  AttrBox    : Changes the color attributes of all characters within a box%@AE@%%@NL@%
  22461. %@AB@%;%@AE@%%@NL@%
  22462. %@AB@%;-----------------------------------------------------------------------------%@AE@%%@NL@%
  22463. %@AB@%;-----------------------------------------------------------------------------%@AE@%%@NL@%
  22464. %@NL@%
  22465. %@AB@%;NOTE: For optimum speed, these routines write directly to screen memory%@AE@%%@NL@%
  22466. %@AB@%;      without waiting for re-trace.  If "snow" is a problem, these routines%@AE@%%@NL@%
  22467. %@AB@%;      will need modification.%@AE@%%@NL@%
  22468. %@NL@%
  22469. .model medium%@NL@%
  22470. %@NL@%
  22471.         extrn   STRINGADDRESS:far       %@AB@%;BASIC RTL entry point for string info%@AE@%%@NL@%
  22472. %@NL@%
  22473. .data%@NL@%
  22474. %@NL@%
  22475. attr    db      ?                       %@AB@%;destination attribute (AttrBox)%@AE@%%@NL@%
  22476. x0      db      ?                       %@AB@%;x coord of upper-left%@AE@%%@NL@%
  22477. y0      db      ?                       %@AB@%;y coord of upper-left%@AE@%%@NL@%
  22478. x1      db      ?                       %@AB@%;x coord of lower-right%@AE@%%@NL@%
  22479. y1      db      ?                       %@AB@%;y coord of lower-right%@AE@%%@NL@%
  22480. bwidth  db      ?                       %@AB@%;box width%@AE@%%@NL@%
  22481. height  db      ?                       %@AB@%;box height%@AE@%%@NL@%
  22482. strdoff dw      ?                       %@AB@%;string pointer offset%@AE@%%@NL@%
  22483. strdseg dw      ?                       %@AB@%;string pointer segment%@AE@%%@NL@%
  22484. scrseg  dw      ?                       %@AB@%;screen segment%@AE@%%@NL@%
  22485. movword dw      ?                       %@AB@%;word count to move/change%@AE@%%@NL@%
  22486. %@NL@%
  22487. .code%@NL@%
  22488. %@NL@%
  22489. %@AB@%;---------------------------------------place segment of screen memory%@AE@%%@NL@%
  22490. %@AB@%;---------------------------------------in SCRSEG%@AE@%%@NL@%
  22491. get_scrseg      proc%@NL@%
  22492. %@NL@%
  22493.         push    ax                      %@AB@%;save value of AX%@AE@%%@NL@%
  22494.         mov     ah,0Fh%@NL@%
  22495.         int     10h                     %@AB@%;INT 10H fn. 0Fh - Get Video Mode%@AE@%%@NL@%
  22496.         mov     dgroup:scrseg,0B800h    %@AB@%;assume COLOR screen for now%@AE@%%@NL@%
  22497.         cmp     al,07h                  %@AB@%;is it MONOCHROME mode?%@AE@%%@NL@%
  22498.         jne     arnd1%@NL@%
  22499.         mov     dgroup:scrseg,0B000h    %@AB@%;yes, set for mono screen seg%@AE@%%@NL@%
  22500. arnd1:  pop     ax                      %@AB@%;restore AX%@AE@%%@NL@%
  22501.         ret                             %@AB@%;and exit%@AE@%%@NL@%
  22502. %@NL@%
  22503. get_scrseg      endp%@NL@%
  22504. %@NL@%
  22505. %@NL@%
  22506. %@AB@%;----------------------------------------Given X and Y in AH and AL, find%@AE@%%@NL@%
  22507. %@AB@%;----------------------------------------the offset into screen memory and%@AE@%%@NL@%
  22508. %@AB@%;----------------------------------------return in AX%@AE@%%@NL@%
  22509. get_memxy       proc%@NL@%
  22510. %@NL@%
  22511.         push    dx                      %@AB@%;save DX%@AE@%%@NL@%
  22512.         push    ax                      %@AB@%;save coords%@AE@%%@NL@%
  22513.         mov     dl,160%@NL@%
  22514.         mul     dl                      %@AB@%;multiply Y by 160%@AE@%%@NL@%
  22515.         pop     dx                      %@AB@%;put coords in DX%@AE@%%@NL@%
  22516.         mov     dl,dh%@NL@%
  22517.         mov     dh,0%@NL@%
  22518.         add     dl,dl                   %@AB@%;double X%@AE@%%@NL@%
  22519.         add     ax,dx                   %@AB@%;and add to mult. result for final!%@AE@%%@NL@%
  22520.         pop     dx                      %@AB@%;restore DX%@AE@%%@NL@%
  22521.         ret%@NL@%
  22522. %@NL@%
  22523. get_memxy       endp%@NL@%
  22524. %@NL@%
  22525. %@NL@%
  22526. %@AB@%;-----------------------------------------------------------------------------%@AE@%%@NL@%
  22527. %@AB@%;----------------------------------------This is the routine that copies%@AE@%%@NL@%
  22528. %@AB@%;----------------------------------------screen info to the string variable%@AE@%%@NL@%
  22529. %@AB@%;-----------------------------------------------------------------------------%@AE@%%@NL@%
  22530.         public  getcopybox%@NL@%
  22531. getcopybox      proc    far%@NL@%
  22532. %@NL@%
  22533.         push    bp%@NL@%
  22534.         mov     bp,sp%@NL@%
  22535.         push    ds%@NL@%
  22536.         push    es%@NL@%
  22537.         push    si%@NL@%
  22538.         push    di                      %@AB@%;preserve registers%@AE@%%@NL@%
  22539. %@NL@%
  22540. get_start:%@NL@%
  22541.         mov     bx,[bp + 14]            %@AB@%;get y0%@AE@%%@NL@%
  22542.         mov     ax,[bx]%@NL@%
  22543.         mov     y0,al%@NL@%
  22544.         mov     bx,[bp + 12]            %@AB@%;...x0%@AE@%%@NL@%
  22545.         mov     ax,[bx]%@NL@%
  22546.         mov     x0,al%@NL@%
  22547.         mov     bx,[bp + 10]            %@AB@%;...y1%@AE@%%@NL@%
  22548.         mov     ax,[bx]%@NL@%
  22549.         mov     y1,al%@NL@%
  22550.         mov     bx,[bp + 8]             %@AB@%;...x1%@AE@%%@NL@%
  22551.         mov     ax,[bx]%@NL@%
  22552.         mov     x1,al%@NL@%
  22553.         mov     bx,[bp + 6]             %@AB@%;...and the destination str desc.%@AE@%%@NL@%
  22554. %@NL@%
  22555.         push    bx%@NL@%
  22556.         call    STRINGADDRESS           %@AB@%;for both near and far string support%@AE@%%@NL@%
  22557.         mov     strdoff, ax%@NL@%
  22558.         mov     strdseg, dx%@NL@%
  22559. %@NL@%
  22560.         dec     x0                      %@AB@%;subtract 1 from%@AE@%%@NL@%
  22561.         dec     y0                      %@AB@%;all coordinates%@AE@%%@NL@%
  22562.         dec     x1                      %@AB@%;to reflect BASIC's%@AE@%%@NL@%
  22563.         dec     y1                      %@AB@%;screen base of 1 (not 0)%@AE@%%@NL@%
  22564. %@NL@%
  22565. get_chkscr:%@NL@%
  22566.         call    get_scrseg              %@AB@%;set up screen segment%@AE@%%@NL@%
  22567. %@NL@%
  22568. get_setstr:%@NL@%
  22569.         mov     al,x1%@NL@%
  22570.         sub     al,x0                   %@AB@%;find width of box%@AE@%%@NL@%
  22571.         mov     bwidth,al               %@AB@%;and save%@AE@%%@NL@%
  22572.         add     al,1                    %@AB@%;add one to width%@AE@%%@NL@%
  22573.         mov     ah,0                    %@AB@%;to find # words to move%@AE@%%@NL@%
  22574.         mov     movword,ax              %@AB@%;MovWord = (width+1)%@AE@%%@NL@%
  22575.         mov     al,y1%@NL@%
  22576.         sub     al,y0                   %@AB@%;find height of box%@AE@%%@NL@%
  22577.         mov     height,al               %@AB@%;and save%@AE@%%@NL@%
  22578.         mov     es,strdseg%@NL@%
  22579.         mov     di,strdoff              %@AB@%;string is the destination%@AE@%%@NL@%
  22580.         mov     si,offset bwidth        %@AB@%;point to width%@AE@%%@NL@%
  22581.         movsb                           %@AB@%;put width in string%@AE@%%@NL@%
  22582.         mov     si,offset height%@NL@%
  22583.         movsb                           %@AB@%;and the height, too%@AE@%%@NL@%
  22584. %@NL@%
  22585. get_movstr:%@NL@%
  22586.         mov     al,y0%@NL@%
  22587.         mov     ah,x0                   %@AB@%;put coords in AH and AL%@AE@%%@NL@%
  22588.         call    get_memxy               %@AB@%;and find offset into screen mem%@AE@%%@NL@%
  22589.         mov     si,ax                   %@AB@%;this will be the source%@AE@%%@NL@%
  22590. %@NL@%
  22591. get_domove:%@NL@%
  22592.         mov     cx,movword%@NL@%
  22593.         push    ds%@NL@%
  22594.         mov     ds,scrseg%@NL@%
  22595.         rep     movsw                   %@AB@%;move a row into the string%@AE@%%@NL@%
  22596.         pop     ds%@NL@%
  22597.         add     si,160%@NL@%
  22598.         sub     si,movword              %@AB@%;Add 160-(movword*2) to si%@AE@%%@NL@%
  22599.         sub     si,movword              %@AB@%;to point to next row%@AE@%%@NL@%
  22600.         cmp     height,0                %@AB@%;was that the last row?%@AE@%%@NL@%
  22601.         je      get_done                %@AB@%;yes, we're done%@AE@%%@NL@%
  22602.         dec     height                  %@AB@%;decrement height%@AE@%%@NL@%
  22603.         jmp     get_domove              %@AB@%;and do another row%@AE@%%@NL@%
  22604. %@NL@%
  22605. get_done:%@NL@%
  22606.         pop     di%@NL@%
  22607.         pop     si%@NL@%
  22608.         pop     es%@NL@%
  22609.         pop     ds                      %@AB@%;restore registers%@AE@%%@NL@%
  22610.         pop     bp%@NL@%
  22611.         ret     10                      %@AB@%;there were 5 parameters%@AE@%%@NL@%
  22612. %@NL@%
  22613. getcopybox      endp%@NL@%
  22614. %@NL@%
  22615. %@NL@%
  22616. %@AB@%;-----------------------------------------------------------------------------%@AE@%%@NL@%
  22617. %@AB@%;----------------------------------------This is the routine that copies the%@AE@%%@NL@%
  22618. %@AB@%;----------------------------------------information stored in the string to%@AE@%%@NL@%
  22619. %@AB@%;----------------------------------------the screen in the specified location%@AE@%%@NL@%
  22620. %@AB@%;-----------------------------------------------------------------------------%@AE@%%@NL@%
  22621.         public  putcopybox%@NL@%
  22622. putcopybox      proc    far%@NL@%
  22623. %@NL@%
  22624.         push    bp%@NL@%
  22625.         mov     bp,sp%@NL@%
  22626.         push    ds%@NL@%
  22627.         push    es%@NL@%
  22628.         push    si%@NL@%
  22629.         push    di                      %@AB@%;preserve registers%@AE@%%@NL@%
  22630. %@NL@%
  22631. %@NL@%
  22632. put_start:%@NL@%
  22633.         mov     bx,[bp + 10]            %@AB@%;get y0%@AE@%%@NL@%
  22634.         mov     ax,[bx]%@NL@%
  22635.         mov     y0,al%@NL@%
  22636.         mov     bx,[bp + 8]             %@AB@%;...x0%@AE@%%@NL@%
  22637.         mov     ax,[bx]%@NL@%
  22638.         mov     x0,al%@NL@%
  22639.         mov     bx,[bp + 6]             %@AB@%;...and the destination string%@AE@%%@NL@%
  22640. %@NL@%
  22641.         push    bx%@NL@%
  22642.         call    STRINGADDRESS           %@AB@%;for both near and far string support%@AE@%%@NL@%
  22643.         mov     strdoff, ax%@NL@%
  22644.         mov     strdseg, dx%@NL@%
  22645. %@NL@%
  22646.         dec     x0                      %@AB@%;subtract 1 from%@AE@%%@NL@%
  22647.         dec     y0                      %@AB@%;all coordinates%@AE@%%@NL@%
  22648. %@NL@%
  22649. put_chkscr:%@NL@%
  22650.         call    get_scrseg              %@AB@%;set up scrseg%@AE@%%@NL@%
  22651. %@NL@%
  22652. put_setstr:%@NL@%
  22653.         push    ds%@NL@%
  22654.         pop     es                      %@AB@%;equate ES to DS%@AE@%%@NL@%
  22655. %@NL@%
  22656.         mov     si,strdoff              %@AB@%;point DS:SI to string mem%@AE@%%@NL@%
  22657.         push    ds%@NL@%
  22658.         mov     ds,strdseg%@NL@%
  22659.         mov     di,offset bwidth%@NL@%
  22660.         movsb                           %@AB@%;get width%@AE@%%@NL@%
  22661.         mov     di,offset height%@NL@%
  22662.         movsb                           %@AB@%;and height out of string%@AE@%%@NL@%
  22663.         pop     ds%@NL@%
  22664. %@NL@%
  22665.         mov     al,bwidth%@NL@%
  22666.         add     al,1%@NL@%
  22667.         mov     ah,0%@NL@%
  22668.         mov     movword,ax              %@AB@%;set movword to (bwidth+1)%@AE@%%@NL@%
  22669. %@NL@%
  22670.         mov     ah,x0%@NL@%
  22671.         mov     al,y0                   %@AB@%;get coords%@AE@%%@NL@%
  22672.         call    get_memxy               %@AB@%;and find offset into screen mem%@AE@%%@NL@%
  22673.         mov     di,ax%@NL@%
  22674.         mov     es,scrseg               %@AB@%;ES:DI -> screen mem (UL corner)%@AE@%%@NL@%
  22675. %@NL@%
  22676. put_domove:%@NL@%
  22677.         mov     cx,movword%@NL@%
  22678.         push    ds%@NL@%
  22679.         mov     ds,strdseg%@NL@%
  22680.         rep     movsw                   %@AB@%;move a row onto the screen%@AE@%%@NL@%
  22681.         pop     ds%@NL@%
  22682.         add     di,160%@NL@%
  22683.         sub     di,movword              %@AB@%;add 160-(movword*2) to DI%@AE@%%@NL@%
  22684.         sub     di,movword              %@AB@%;to point to next row on screen%@AE@%%@NL@%
  22685.         cmp     height,0                %@AB@%;was that the last row?%@AE@%%@NL@%
  22686.         je      put_done                %@AB@%;yes, we're finished%@AE@%%@NL@%
  22687.         dec     height%@NL@%
  22688.         jmp     put_domove              %@AB@%;no, decrement and do again%@AE@%%@NL@%
  22689. %@NL@%
  22690. put_done:%@NL@%
  22691.         pop     di%@NL@%
  22692.         pop     si%@NL@%
  22693.         pop     es%@NL@%
  22694.         pop     ds                      %@AB@%;restore registers%@AE@%%@NL@%
  22695.         pop     bp%@NL@%
  22696.         ret     6                       %@AB@%;pop off 3 parameters%@AE@%%@NL@%
  22697. %@NL@%
  22698. putcopybox      endp%@NL@%
  22699. %@NL@%
  22700. %@AB@%;-----------------------------------------------------------------------------%@AE@%%@NL@%
  22701. %@AB@%;----------------------------------------This is the routine that changes%@AE@%%@NL@%
  22702. %@AB@%;----------------------------------------the colors of the box's characters%@AE@%%@NL@%
  22703. %@AB@%;-----------------------------------------------------------------------------%@AE@%%@NL@%
  22704.         public  attrbox%@NL@%
  22705. attrbox         proc    far%@NL@%
  22706. %@NL@%
  22707.         push    bp%@NL@%
  22708.         mov     bp, sp%@NL@%
  22709.         push    ds%@NL@%
  22710.         push    es%@NL@%
  22711.         push    si%@NL@%
  22712.         push    di                      %@AB@%;preserve registers%@AE@%%@NL@%
  22713. %@NL@%
  22714. atr_start:%@NL@%
  22715.         mov     bx, [bp+14]             %@AB@%;get y0%@AE@%%@NL@%
  22716.         mov     ax, [bx]%@NL@%
  22717.         mov     y0, al%@NL@%
  22718.         mov     bx, [bp+12]             %@AB@%;...x0%@AE@%%@NL@%
  22719.         mov     ax, [bx]%@NL@%
  22720.         mov     x0, al%@NL@%
  22721.         mov     bx, [bp+10]             %@AB@%;...y1%@AE@%%@NL@%
  22722.         mov     ax, [bx]%@NL@%
  22723.         mov     y1, al%@NL@%
  22724.         mov     bx, [bp+8]              %@AB@%;...x1%@AE@%%@NL@%
  22725.         mov     ax, [bx]%@NL@%
  22726.         mov     x1, al%@NL@%
  22727.         mov     bx, [bp+6]              %@AB@%;...and finally the new color value%@AE@%%@NL@%
  22728.         mov     ax, [bx]%@NL@%
  22729.         mov     attr, al%@NL@%
  22730. %@NL@%
  22731.         dec     y0                      %@AB@%;subtract 1 from%@AE@%%@NL@%
  22732.         dec     x0                      %@AB@%;all coordinates%@AE@%%@NL@%
  22733.         dec     y1                      %@AB@%;to reflect BASIC's%@AE@%%@NL@%
  22734.         dec     x1                      %@AB@%;screen base of 1 (not 0)%@AE@%%@NL@%
  22735. %@NL@%
  22736. atr_chkscr:%@NL@%
  22737.         call    get_scrseg              %@AB@%;set up screen segment%@AE@%%@NL@%
  22738. %@NL@%
  22739. atr_setup:%@NL@%
  22740.         mov     al, x1%@NL@%
  22741.         sub     al, x0                  %@AB@%;find width of box%@AE@%%@NL@%
  22742.         inc     al%@NL@%
  22743.         xor     ah, ah%@NL@%
  22744.         mov     movword, ax             %@AB@%;(width + 1 = movword)%@AE@%%@NL@%
  22745.         mov     al, y1%@NL@%
  22746.         sub     al, y0                  %@AB@%;find height of box%@AE@%%@NL@%
  22747.         mov     height, al              %@AB@%;and save%@AE@%%@NL@%
  22748. %@NL@%
  22749. atr_chgclr:%@NL@%
  22750.         mov     al, y0%@NL@%
  22751.         mov     ah, x0                  %@AB@%;put coords in AH and AL%@AE@%%@NL@%
  22752.         call    get_memxy               %@AB@%;find offset into screen memory%@AE@%%@NL@%
  22753.         mov     di, ax                  %@AB@%;(which is our destination)%@AE@%%@NL@%
  22754.         mov     es, scrseg%@NL@%
  22755.         mov     al, attr                %@AB@%;get the color value to store%@AE@%%@NL@%
  22756. %@NL@%
  22757. atr_doit:%@NL@%
  22758.         mov     cx, movword%@NL@%
  22759. atr_loop:%@NL@%
  22760.         inc     di                      %@AB@%;skip the character value%@AE@%%@NL@%
  22761.         stosb                           %@AB@%;write new color value%@AE@%%@NL@%
  22762.         loop    atr_loop                %@AB@%;cx times%@AE@%%@NL@%
  22763.         add     di, 160                 %@AB@%;add 160-(movword*2) to di%@AE@%%@NL@%
  22764.         sub     di, movword%@NL@%
  22765.         sub     di, movword%@NL@%
  22766.         cmp     height, 0               %@AB@%;was that the last row?%@AE@%%@NL@%
  22767.         je      atr_done                %@AB@%;yes, we be finished%@AE@%%@NL@%
  22768.         dec     height                  %@AB@%;no, decrement height%@AE@%%@NL@%
  22769.         jmp     atr_doit%@NL@%
  22770. %@NL@%
  22771. atr_done:%@NL@%
  22772.         pop     di%@NL@%
  22773.         pop     si%@NL@%
  22774.         pop     es%@NL@%
  22775.         pop     ds%@NL@%
  22776.         pop     bp                      %@AB@%;restore registers%@AE@%%@NL@%
  22777.         ret     10                      %@AB@%;pull off 5 paramters and return%@AE@%%@NL@%
  22778. %@NL@%
  22779. attrbox         endp%@NL@%
  22780. %@NL@%
  22781.         END%@NL@%
  22782. %@NL@%
  22783. %@NL@%
  22784. %@2@%%@AH@%UIDEMO.BAS%@AE@%%@EH@%%@NL@%
  22785. %@AS@%CD-ROM Disc Path:   \SAMPCODE\BASIC\UIDEMO.BAS%@AE@%%@NL@%
  22786. %@NL@%
  22787. %@AB@%' ===========================================================================%@AE@%%@NL@%
  22788. %@AB@%'%@AE@%%@NL@%
  22789. %@AB@%' UIDEMO.BAS Copyright (c) 1989 Microsoft Corporation%@AE@%%@NL@%
  22790. %@AB@%'%@AE@%%@NL@%
  22791. %@AB@%' ===========================================================================%@AE@%%@NL@%
  22792. %@AB@%' ===========================================================================%@AE@%%@NL@%
  22793. %@AB@%' Decls, includes, and dimensions%@AE@%%@NL@%
  22794. %@AB@%' ===========================================================================%@AE@%%@NL@%
  22795. DEFINT A-Z%@NL@%
  22796. DECLARE SUB AboutDemo ()%@NL@%
  22797. DECLARE SUB AboutUIP ()%@NL@%
  22798. DECLARE SUB AboutMouse ()%@NL@%
  22799. DECLARE SUB AboutAccess ()%@NL@%
  22800. DECLARE SUB AboutQuick ()%@NL@%
  22801. DECLARE SUB AboutWindows ()%@NL@%
  22802. DECLARE SUB ColorDisplay ()%@NL@%
  22803. DECLARE SUB DemoAlert ()%@NL@%
  22804. DECLARE SUB DemoDialog ()%@NL@%
  22805. DECLARE SUB DemoDialogEZ ()%@NL@%
  22806. DECLARE SUB DemoFileNameListBox ()%@NL@%
  22807. DECLARE SUB DemoListBox ()%@NL@%
  22808. DECLARE SUB DemoWindow ()%@NL@%
  22809. DECLARE SUB DemoScrollBar ()%@NL@%
  22810. DECLARE SUB DemoResize ()%@NL@%
  22811. DECLARE SUB MonoDisplay ()%@NL@%
  22812. DECLARE SUB SetupDesktop ()%@NL@%
  22813. DECLARE SUB SetupMenu ()%@NL@%
  22814. DECLARE FUNCTION GetFileCount% (FileSpec$)%@NL@%
  22815. %@NL@%
  22816. %@AB@%'$INCLUDE: 'general.bi'%@AE@%%@NL@%
  22817. %@AB@%'$INCLUDE: 'mouse.bi'%@AE@%%@NL@%
  22818. %@AB@%'$INCLUDE: 'menu.bi'%@AE@%%@NL@%
  22819. %@AB@%'$INCLUDE: 'window.bi'%@AE@%%@NL@%
  22820. %@NL@%
  22821. COMMON SHARED /uitools/ GloMenu           AS MenuMiscType%@NL@%
  22822. COMMON SHARED /uitools/ GloTitle()        AS MenuTitleType%@NL@%
  22823. COMMON SHARED /uitools/ GloItem()         AS MenuItemType%@NL@%
  22824. COMMON SHARED /uitools/ GloWindow()       AS windowType%@NL@%
  22825. COMMON SHARED /uitools/ GloButton()       AS buttonType%@NL@%
  22826. COMMON SHARED /uitools/ GloEdit()         AS EditFieldType%@NL@%
  22827. COMMON SHARED /uitools/ GloStorage        AS WindowStorageType%@NL@%
  22828. COMMON SHARED /uitools/ GloWindowStack()  AS INTEGER%@NL@%
  22829. COMMON SHARED /uitools/ GloBuffer$()%@NL@%
  22830. %@NL@%
  22831. DIM GloTitle(MAXMENU)           AS MenuTitleType%@NL@%
  22832. DIM GloItem(MAXMENU, MAXITEM)   AS MenuItemType%@NL@%
  22833. DIM GloWindow(MAXWINDOW)        AS windowType%@NL@%
  22834. DIM GloButton(MAXBUTTON)        AS buttonType%@NL@%
  22835. DIM GloEdit(MAXEDITFIELD)       AS EditFieldType%@NL@%
  22836. DIM GloWindowStack(MAXWINDOW)   AS INTEGER%@NL@%
  22837. DIM GloBuffer$(MAXWINDOW + 1, 2)%@NL@%
  22838. %@NL@%
  22839. DIM SHARED DisplayType          AS INTEGER%@NL@%
  22840. %@NL@%
  22841. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  22842. %@AB@%    ' Initialize Demo%@AE@%%@NL@%
  22843. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  22844. %@NL@%
  22845.     MenuInit%@NL@%
  22846.     WindowInit%@NL@%
  22847.     MouseShow%@NL@%
  22848.     MonoDisplay%@NL@%
  22849. %@NL@%
  22850. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  22851. %@AB@%    ' Show Opening alert window%@AE@%%@NL@%
  22852. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  22853. %@NL@%
  22854. %@NL@%
  22855.          a$ = "User Interface Toolbox Demo|"%@NL@%
  22856.     a$ = a$ + "for|"%@NL@%
  22857.     a$ = a$ + "Microsoft BASIC 7.0 Professional Development System|"%@NL@%
  22858.     a$ = a$ + "Copyright (c) 1989 Microsoft Corporation|"%@NL@%
  22859. %@NL@%
  22860.     x = Alert(4, a$, 9, 10, 14, 70, "Color", "Monochrome", "")%@NL@%
  22861. %@NL@%
  22862.     IF x = 1 THEN%@NL@%
  22863.         DisplayType = TRUE%@NL@%
  22864.         ColorDisplay%@NL@%
  22865.     END IF%@NL@%
  22866. %@NL@%
  22867. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  22868. %@AB@%    ' Main Loop : Stay in loop until DemoFinished set to TRUE%@AE@%%@NL@%
  22869. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  22870. %@NL@%
  22871.     DemoFinished = FALSE%@NL@%
  22872. %@NL@%
  22873.     WHILE NOT DemoFinished%@NL@%
  22874.         kbd$ = MenuInkey$%@NL@%
  22875.         WHILE MenuCheck(2)%@NL@%
  22876.             GOSUB MenuTrap%@NL@%
  22877.         WEND%@NL@%
  22878.     WEND%@NL@%
  22879. %@NL@%
  22880. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  22881. %@AB@%    ' End Program%@AE@%%@NL@%
  22882. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  22883. %@NL@%
  22884.     MouseHide%@NL@%
  22885.     COLOR 15, 0%@NL@%
  22886.     CLS%@NL@%
  22887.     END%@NL@%
  22888. %@NL@%
  22889. %@NL@%
  22890. %@NL@%
  22891. %@AB@%' ===========================================================================%@AE@%%@NL@%
  22892. %@AB@%' If a menu event occured, call the proper demo, or if Exit, set demoFinished%@AE@%%@NL@%
  22893. %@AB@%' ===========================================================================%@AE@%%@NL@%
  22894. %@NL@%
  22895. MenuTrap:%@NL@%
  22896.     menu = MenuCheck(0)%@NL@%
  22897.     item = MenuCheck(1)%@NL@%
  22898. %@NL@%
  22899.     SELECT CASE menu%@NL@%
  22900.         CASE 1%@NL@%
  22901.             SELECT CASE item%@NL@%
  22902.                 CASE 1:  DemoAlert%@NL@%
  22903.                 CASE 2:  DemoDialogEZ%@NL@%
  22904.                 CASE 3:  DemoDialog%@NL@%
  22905.                 CASE 4:  DemoListBox%@NL@%
  22906.                 CASE 5:  DemoFileNameListBox%@NL@%
  22907.                 CASE 6:  DemoScrollBar%@NL@%
  22908.                 CASE 7:  DemoWindow%@NL@%
  22909.                 CASE 8:  DemoResize%@NL@%
  22910.                 CASE 10: DemoFinished = TRUE%@NL@%
  22911.             END SELECT%@NL@%
  22912.         CASE 2%@NL@%
  22913.             SELECT CASE item%@NL@%
  22914.                 CASE 1: ColorDisplay%@NL@%
  22915.                 CASE 2: MonoDisplay%@NL@%
  22916. %@NL@%
  22917.             END SELECT%@NL@%
  22918.         CASE 3%@NL@%
  22919.             SELECT CASE item%@NL@%
  22920.                 CASE 1: AboutDemo%@NL@%
  22921.                 CASE 2: AboutUIP%@NL@%
  22922.                 CASE 3: AboutWindows%@NL@%
  22923.                 CASE 4: AboutMouse%@NL@%
  22924.                 CASE 5: AboutAccess%@NL@%
  22925.                 CASE 6: AboutQuick%@NL@%
  22926.             END SELECT%@NL@%
  22927.         CASE ELSE%@NL@%
  22928.     END SELECT%@NL@%
  22929. RETURN%@NL@%
  22930. %@NL@%
  22931. SUB AboutAccess%@NL@%
  22932.          a$ = "                      Access Keys||"%@NL@%
  22933.     a$ = a$ + "Access keys are the keys on the menu bar that are highlighted|"%@NL@%
  22934.     a$ = a$ + "when you press the Alt key. If you press a letter that is|"%@NL@%
  22935.     a$ = a$ + "highlighted in a menu title, that menu will be selected.||"%@NL@%
  22936.     a$ = a$ + "Once a pull-down menu is displayed, each menu item also has a|"%@NL@%
  22937.     a$ = a$ + "highlighted letter associated with each choice. Press the|"%@NL@%
  22938.     a$ = a$ + "letter that corresponds to the menu item you want to select.||"%@NL@%
  22939.     a$ = a$ + "If, after you press Alt, you change your mind, press the Alt|"%@NL@%
  22940.     a$ = a$ + "key again to cancel."%@NL@%
  22941. %@NL@%
  22942.     junk = Alert(1, a$, 7, 9, 20, 69, "", "", "")%@NL@%
  22943. %@NL@%
  22944. END SUB%@NL@%
  22945. %@NL@%
  22946. SUB AboutDemo%@NL@%
  22947.          a$ = "                      About This Demo||"%@NL@%
  22948.     a$ = a$ + "Running this program provides a visual demonstration of most|"%@NL@%
  22949.     a$ = a$ + "of the features implemented in the new User Interface Toolbox|"%@NL@%
  22950.     a$ = a$ + "for the BASIC Compiler 7.0.||"%@NL@%
  22951.     a$ = a$ + "In addition to serving as a demo of toolbox features, the|"%@NL@%
  22952.     a$ = a$ + "source code that makes up this program can also serve as a|"%@NL@%
  22953.     a$ = a$ + "programming example of how to implement these features in|"%@NL@%
  22954.     a$ = a$ + "your programs. While the demo is relatively simple, it does|"%@NL@%
  22955.     a$ = a$ + "illustrate almost all the features available."%@NL@%
  22956. %@NL@%
  22957.     junk = Alert(1, a$, 7, 9, 19, 69, "", "", "")%@NL@%
  22958. END SUB%@NL@%
  22959. %@NL@%
  22960. SUB AboutMouse%@NL@%
  22961.          a$ = "                      Using the Mouse||"%@NL@%
  22962.     a$ = a$ + "Virtually all operations in the User Interface Toolbox can|"%@NL@%
  22963.     a$ = a$ + "be accomplished using the mouse. Move the mouse cursor to|"%@NL@%
  22964.     a$ = a$ + "whatever you want to select and press the left button.||"%@NL@%
  22965.     a$ = a$ + "In addition to being able to make a choice with a mouse,|"%@NL@%
  22966.     a$ = a$ + "you can also perform a number of operations on windows.|"%@NL@%
  22967.     a$ = a$ + "Using the mouse you can close, move, or resize windows|"%@NL@%
  22968.     a$ = a$ + "depending on the particular features of the window that is|"%@NL@%
  22969.     a$ = a$ + "active."%@NL@%
  22970. %@NL@%
  22971.     junk = Alert(1, a$, 7, 9, 19, 69, "", "", "")%@NL@%
  22972. %@NL@%
  22973. END SUB%@NL@%
  22974. %@NL@%
  22975. SUB AboutQuick%@NL@%
  22976.          a$ = "                      Quick Keys||"%@NL@%
  22977.     a$ = a$ + "Quick keys are optional keys that you can define in addition|"%@NL@%
  22978.     a$ = a$ + "to the normal access keys that must be specified when you|"%@NL@%
  22979.     a$ = a$ + "set up the individual menu items.||"%@NL@%
  22980.     a$ = a$ + "Quick keys normally reduce selection of a menu item to one|"%@NL@%
  22981.     a$ = a$ + "keystroke. For example, this demo uses function keys F1 thru|"%@NL@%
  22982.     a$ = a$ + "F8 to select menu choices that demonstrate different features|"%@NL@%
  22983.     a$ = a$ + "of the User Interface Toolbox.  Additionally, Ctrl-X is the|"%@NL@%
  22984.     a$ = a$ + "Quick key that exits this demonstration program."%@NL@%
  22985. %@NL@%
  22986.     junk = Alert(1, a$, 7, 9, 19, 69, "", "", "")%@NL@%
  22987. %@NL@%
  22988. END SUB%@NL@%
  22989. %@NL@%
  22990. SUB AboutUIP%@NL@%
  22991.          a$ = "                 About the User Interface||"%@NL@%
  22992.     a$ = a$ + "The user interface provided with this toolbox is designed to|"%@NL@%
  22993.     a$ = a$ + "provide much the same functionality as that found in the QBX|"%@NL@%
  22994.     a$ = a$ + "programming environment. The menus, check boxes, option|"%@NL@%
  22995.     a$ = a$ + "buttons, and other interface features operate similarly to|"%@NL@%
  22996.     a$ = a$ + "their QBX counterparts. ||"%@NL@%
  22997.     a$ = a$ + "If you know how to navigate QBX, you know how to navigate|"%@NL@%
  22998.     a$ = a$ + "the interface provided by the User Interface Toolbox."%@NL@%
  22999. %@NL@%
  23000.     junk = Alert(1, a$, 7, 9, 18, 69, "", "", "")%@NL@%
  23001. END SUB%@NL@%
  23002. %@NL@%
  23003. SUB AboutWindows%@NL@%
  23004.          a$ = "                     About the Windows||"%@NL@%
  23005.     a$ = a$ + "Several border characters used by the windows in the User|"%@NL@%
  23006.     a$ = a$ + "Interface Toolbox have special significance.  Any window that|"%@NL@%
  23007.     a$ = a$ + "has a '=' in the upper-left corner can be closed by selecting|"%@NL@%
  23008.     a$ = a$ + "that character with the mouse. Windows with the '░' character|"%@NL@%
  23009.     a$ = a$ + "across the window's top row can be moved around the screen by|"%@NL@%
  23010.     a$ = a$ + "selecting that area with the mouse.  The '+' character in the|"%@NL@%
  23011.     a$ = a$ + "lower-right corner means that the window can be resized by|"%@NL@%
  23012.     a$ = a$ + "selecting the '+' character with the mouse.||"%@NL@%
  23013.     a$ = a$ + "Note that none of these features can be accessed without a|"%@NL@%
  23014.     a$ = a$ + "mouse. "%@NL@%
  23015. %@NL@%
  23016.     junk = Alert(1, a$, 7, 9, 21, 69, "", "", "")%@NL@%
  23017. %@NL@%
  23018. END SUB%@NL@%
  23019. %@NL@%
  23020. SUB ColorDisplay%@NL@%
  23021.     DisplayType = TRUE%@NL@%
  23022.     MouseHide%@NL@%
  23023.     SetupMenu%@NL@%
  23024.     MenuSetState 2, 1, 2%@NL@%
  23025.     MenuSetState 2, 2, 1%@NL@%
  23026.     SetupDesktop%@NL@%
  23027.     MenuShow%@NL@%
  23028.     MouseShow%@NL@%
  23029. END SUB%@NL@%
  23030. %@NL@%
  23031. SUB DemoAlert%@NL@%
  23032. %@NL@%
  23033. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  23034. %@AB@%    ' Simple little demo of how easy alerts are to use.%@AE@%%@NL@%
  23035. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  23036. %@NL@%
  23037.          a$ = "|"%@NL@%
  23038.     a$ = a$ + "This is an Alert Box.| |"%@NL@%
  23039.     a$ = a$ + "It was created using a simple one|"%@NL@%
  23040.     a$ = a$ + "line command.  Notice the buttons|"%@NL@%
  23041.     a$ = a$ + "below.  They are user definable|"%@NL@%
  23042.     a$ = a$ + "yet their spacing is automatic."%@NL@%
  23043. %@NL@%
  23044.     B$ = "You Selected OK"%@NL@%
  23045. %@NL@%
  23046.     C$ = "You Selected Cancel"%@NL@%
  23047. %@NL@%
  23048.     SELECT CASE Alert(4, a$, 6, 20, 15, 60, "OK", "Cancel", "")%@NL@%
  23049.         CASE 1%@NL@%
  23050.             x = Alert(4, B$, 10, 25, 12, 55, "OK", "", "")%@NL@%
  23051.         CASE 2%@NL@%
  23052.             x = Alert(4, C$, 10, 25, 12, 55, "OK", "", "")%@NL@%
  23053.     END SELECT%@NL@%
  23054. %@NL@%
  23055. END SUB%@NL@%
  23056. %@NL@%
  23057. SUB DemoDialog%@NL@%
  23058. %@NL@%
  23059. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  23060. %@AB@%    ' This is about as complex as they get.  As you can see it is still very%@AE@%%@NL@%
  23061. %@AB@%    ' simple - just a lot bigger.  This sub exactly duplicates the%@AE@%%@NL@%
  23062. %@AB@%    ' functionality of the QuickBASIC Search-Change dialog box.%@AE@%%@NL@%
  23063. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  23064. %@NL@%
  23065. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  23066. %@AB@%    ' Open Window, place a horizontal line on row 13%@AE@%%@NL@%
  23067. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  23068. %@NL@%
  23069.     WindowOpen 1, 6, 11, 19, 67, 0, 7, 0, 7, 15, FALSE, FALSE, FALSE, TRUE, 1, ""%@NL@%
  23070. %@NL@%
  23071.     WindowLine 13%@NL@%
  23072. %@NL@%
  23073. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  23074. %@AB@%    ' Print the text, and boxes for the edit fields%@AE@%%@NL@%
  23075. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  23076. %@NL@%
  23077.     WindowLocate 2, 2%@NL@%
  23078.     WindowPrint 2, "Find What:"%@NL@%
  23079.     WindowBox 1, 14, 3, 56%@NL@%
  23080. %@NL@%
  23081.     WindowLocate 5, 2%@NL@%
  23082.     WindowPrint 2, "Change To:"%@NL@%
  23083.     WindowBox 4, 14, 6, 56%@NL@%
  23084. %@NL@%
  23085. %@NL@%
  23086. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  23087. %@AB@%    ' Print the title of the window -- This overides the string in WindowOpen%@AE@%%@NL@%
  23088. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  23089. %@NL@%
  23090.     WindowLocate 0, 26%@NL@%
  23091.     WindowPrint 1, " Change "%@NL@%
  23092. %@NL@%
  23093.     WindowBox 8, 32, 12, 56%@NL@%
  23094. %@NL@%
  23095. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  23096. %@AB@%    ' Open Edit fields%@AE@%%@NL@%
  23097. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  23098. %@NL@%
  23099.     search$ = ""%@NL@%
  23100.     replace$ = ""%@NL@%
  23101.     EditFieldOpen 1, search$, 2, 15, 0, 0, 40, 39%@NL@%
  23102. %@NL@%
  23103.     EditFieldOpen 2, replace$, 5, 15, 0, 0, 40, 39%@NL@%
  23104. %@NL@%
  23105. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  23106. %@AB@%    ' Open all buttons%@AE@%%@NL@%
  23107. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  23108. %@NL@%
  23109.     ButtonOpen 1, 1, "Match Upper/Lowercase", 9, 2, 0, 0, 2%@NL@%
  23110.     ButtonOpen 2, 1, "Whole Word", 10, 2, 0, 0, 2%@NL@%
  23111.     ButtonOpen 3, 1, "1. Active Window", 9, 34, 0, 0, 3%@NL@%
  23112.     ButtonOpen 4, 2, "2. Current Module", 10, 34, 0, 0, 3%@NL@%
  23113.     ButtonOpen 5, 1, "3. All Modules", 11, 34, 0, 0, 3%@NL@%
  23114.     ButtonOpen 6, 2, "Find and Verify", 14, 2, 0, 0, 1%@NL@%
  23115.     ButtonOpen 7, 1, "Change All", 14, 22, 0, 0, 1%@NL@%
  23116.     ButtonOpen 8, 1, "Cancel", 14, 38, 0, 0, 1%@NL@%
  23117.     ButtonOpen 9, 1, "Help", 14, 49, 0, 0, 1%@NL@%
  23118. %@NL@%
  23119. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  23120. %@AB@%    ' Set initial states to match initial button settings%@AE@%%@NL@%
  23121. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  23122. %@NL@%
  23123.     MatchState = FALSE%@NL@%
  23124.     WordState = FALSE%@NL@%
  23125.     searchState = 2%@NL@%
  23126.     pushButton = 1%@NL@%
  23127.     currButton = 0%@NL@%
  23128.     currEditField = 1%@NL@%
  23129. %@NL@%
  23130. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  23131. %@AB@%    ' Do until exitFlag is set%@AE@%%@NL@%
  23132. %@AB@%    ' =======================================================================%@AE@%%@NL@%
  23133. %@NL@%
  23134.     ExitFlag = FALSE%@NL@%
  23135.     WHILE NOT ExitFlag%@NL@%
  23136.         WindowDo currButton, currEditField%@NL@%
  23137.         SELECT CASE Dialog(0)%@NL@%
  23138.             CASE 0, 3, 4, 5, 20%@NL@%
  23139. %@NL@%
  23140. %@AB@%            ' ==============================================================%@AE@%%@NL@%
  23141. %@AB@%            ' If edit field clicked, assign currEditField to Dialog(2)%@AE@%%@NL@%
  23142. %@AB@%            ' ==============================================================%@AE@%%@NL@%
  23143. %@NL@%
  23144.             CASE 2%@NL@%
  23145.                 currButton = 0%@NL@%
  23146.                 currEditField = Dialog(2)%@NL@%
  23147. %@NL@%
  23148. %@AB@%            ' ==============================================================%@AE@%%@NL@%
  23149. %@AB@%            ' If escape is hit,  set pushbutton = 0 and exit flag%@AE@%%@NL@%
  23150. %@AB@%            ' ==============================================================%@AE@%%@NL@%
  23151. %@NL@%
  23152.             CASE 9  '(Escape)%@NL@%
  23153.                 pushButton = 3%@NL@%
  23154.                 ExitFlag = TRUE%@NL@%
  23155. %@NL@%
  23156. %@AB@%            ' ==============================================================%@AE@%%@NL@%
  23157. %@AB@%            ' If return is hit, perform action based on the current button%@AE@%%@NL@%
  23158. %@AB@%            ' Button 9 is the help button.  In that case, show help, else just%@AE@%%@NL@%
  23159. %@AB@%            ' exit%@AE@%%@NL@%
  23160. %@AB@%            ' ==============================================================%@AE@%%@NL@%
  23161. %@NL@%
  23162.             CASE 6%@NL@%
  23163.                 SELECT CASE currButton%@NL@%
  23164.                     CASE 9%@NL@%
  23165.                         a$ = "Sample Help Window"%@NL@%
  23166.                         ButtonSetState pushButton + 5, 1%@NL@%
  23167.                         pushButton = 4%@NL@%
  23168.                         ButtonSetState pushButton + 5, 2%@NL@%
  23169.                         junk = Alert(4, a$, 7, 9, 19, 69, "", "", "")%@NL@%
  23170.                     CASE ELSE%@NL@%
  23171.                         ExitFlag = TRUE%@NL@%
  23172.                 END SELECT%@NL@%
  23173. %@NL@%
  23174. %@NL@%
  23175. %@AB@%            ' ==============================================================%@AE@%%@NL@%
  23176. %@AB@%            ' A Button was pushed with mouse. Perform the desired action%@AE@%%@NL@%
  23177. %@AB@%            ' based on Button%@AE@%%@NL@%
  23178. %@AB@%            ' ==============================================================%@AE@%%@NL@%
  23179. %@NL@%
  23180.             CASE 1%@NL@%
  23181.                 currButton = Dialog(1)%@NL@%
  23182.                 currEditField = 0%@NL@%
  23183.                 SELECT CASE currButton%@NL@%
  23184.                     CASE 1%@NL@%
  23185.                         MatchState = NOT MatchState%@NL@%
  23186.                         ButtonToggle 1%@NL@%
  23187.                     CASE 2%@NL@%
  23188.                         WordState = NOT WordState%@NL@%
  23189.                         ButtonToggle 2%@NL@%
  23190.                     CASE 3, 4, 5%@NL@%
  23191.                         ButtonSetState searchState + 2, 1%@NL@%
  23192.                         searchState = Dialog(1) - 2%@NL@%
  23193.                         ButtonSetState searchState + 2, 2%@NL@%
  23194.                     CASE 6, 7, 8%@NL@%
  23195.                         pushButton = Dialog(1) - 5%@NL@%
  23196.                         ExitFlag = TRUE%@NL@%
  23197.                     CASE 9%@NL@%
  23198.                         a$ = "Sample Help Window"%@NL@%
  23199.                         ButtonSetState pushButton + 5, 1%@NL@%
  23200.                         pushButton = Dialog(1) - 5%@NL@%
  23201.                         ButtonSetState pushButton + 5, 2%@NL@%
  23202.                         junk = Alert(4, a$, 7, 9, 19, 69, "", "", "")%@NL@%
  23203.                     CASE ELSE%@NL@%
  23204.                 END SELECT%@NL@%
  23205. %@NL@%
  23206. %@NL@%
  23207. %@AB@%            ' ==============================================================%@AE@%%@NL@%
  23208. %@AB@%            ' Tab was hit.  Depending upon the current button, or current edit field,%@AE@%%@NL@%
  23209. %@AB@%            ' assign the new values to currButton, and currEditField%@AE@%%@NL@%
  23210. %@AB@%            ' ==============================================================%@AE@%%@NL@%
  23211. %@NL@%
  23212.             CASE 7  'tab%@NL@%
  23213.                 SELECT CASE currButton%@NL@%
  23214.                     CASE 0%@NL@%
  23215.                         SELECT CASE currEditField%@NL@%
  23216.                             CASE 1%@NL@%
  23217.                                 currEditField = 2%@NL@%
  23218. %@NL@%
  23219.                             CASE ELSE%@NL@%
  23220.                                 currButton = 1%@NL@%
  23221.                                 currEditField = 0%@NL@%
  23222.                         END SELECT%@NL@%
  23223.                     CASE 1%@NL@%
  23224.                         currButton = 2%@NL@%
  23225.                     CASE 6, 7, 8%@NL@%
  23226.                         currButton = currButton + 1%@NL@%
  23227.                         ButtonSetState pushButton + 5, 1%@NL@%
  23228.                         pushButton = currButton - 5%@NL@%
  23229.                         ButtonSetState pushButton + 5, 2%@NL@%
  23230.                     CASE 3, 4, 5%@NL@%
  23231.                         currButton = 6%@NL@%
  23232.                     CASE 2%@NL@%
  23233.                         currButton = 2 + searchState%@NL@%
  23234.                     CASE 9%@NL@%
  23235.                         currButton = 0%@NL@%
  23236.                         ButtonSetState pushButton + 5, 1%@NL@%
  23237.                         pushButton = 1%@NL@%
  23238.                         ButtonSetState pushButton + 5, 2%@NL@%
  23239.                         currEditField = 1%@NL@%
  23240.                 END SELECT%@NL@%
  23241. %@NL@%
  23242. %@NL@%
  23243. %@AB@%            ' ==============================================================%@AE@%%@NL@%
  23244. %@AB@%            ' Same for Back Tab, only reverse.%@AE@%%@NL@%
  23245. %@AB@%            ' ==============================================================%@AE@%%@NL@%
  23246. %@NL@%
  23247.             CASE 8 'back tab%@NL@%
  23248.                 SELECT CASE currButton%@NL@%
  23249.                     CASE 0%@NL@%
  23250.                         SELECT CASE currEditField%@NL@%
  23251.                             CASE 1%@NL@%
  23252.                                 currButton = 9%@NL@%
  23253.                                 ButtonSetState pushButton + 5, 1%@NL@%
  23254.                                 pushButton = currButton -