NUMINPUT.LST 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941
  1. Listing:
  2. 1 IMPLEMENTATION MODULE NumInput;
  3. 2 (*
  4. 3 * REPERTOIRE
  5. 4 * Release 1.6
  6. 5 * By Charles Bradford and Cole Brecheen
  7. 6 * (c) Copyright 1985-1992 PMI
  8. 7 * Green Bay, Wisconsin
  9. 8 * All rights reserved
  10. 9 * (414) 468-6040
  11. 10 *
  12. 11 * $Header: D:/logfiles/mods/numinput.mov 1.4 10 Mar 1991 15:35:32 coleb $
  13. 12 *
  14. 13 *)
  15. 14
  16. 15
  17. 16 (*
  18. 17 Author: Mike Carter
  19. 18 Description:
  20. 19 Enter or edit a numeric field.
  21. 20 Replacement for PMI StrInput.ReadNumeric. Note that parameters
  22. 21 are slightly different:
  23. 22 1. PMI FloatingPoint and InDecimals parameters have been
  24. 23 removed. They simply have no meaning the way real number
  25. 24 input is now handled.
  26. 25 2. minusOK has been added - see below.
  27. 26 3. The meaning of DecimalPlaces has been changed - see
  28. 27 below.
  29. 28
  30. 29 Some of the features of this version:
  31. 30 * General editing functions are very close to PMI string
  32. 31 input. (Keys like Ins, Del, Home, End, PgUp, PgDn, Left and
  33. 32 Right Arrows, Up and Down Arrows, Backspace, Tab, Shift
  34. 33 Tab, etc. work almost the same way as they do in string
  35. 34 fields).
  36. 35 * Numbers are entered from left to right, then right-
  37. 36 justified on field exit.
  38. 37 * Both insert and overstrike modes are supported.
  39. 38 * The number of digits after the decimal place is strictly
  40. 39 enforced. The user is beeped if too many are entered; if
  41. 40 two few are entered, zeroes are appended. If there is not
  42. 41 enough room in the field, the rightmost character is thrown
  43. 42 out, the decimal point repositioned, and the user beeped.
  44. 43
  45. 44 Notes on parameters:
  46. 45 * A new field was added in ScrnTypes.InputFieldRecord called
  47. 46 "decimalPlace", with corresponding type DecimalPlaceType.
  48. 47 This was designed to be passed to this routine: a -1 value
  49. 48 indicates user-specified decimal points (or none); a 0
  50. 49 means no digits after the decimal point, a 1 one digit,
  51. 50 etc.
  52. 51 * The value of minusOK determines whether negative numbers
  53. 52 are allowed; this can be set from rMin, iMin within
  54. 53 UserOps. Must be FALSE for strings that are later to be
  55. 54 interpreted as CARDINAL.
  56. 55
  57. 56 Notes on Methodology:
  58. 57 NumInput combines state transition tables with a series of
  59. 58 rules. The three state tables reflect the current input mode
  60. 59 and the character that the cursor is under; they generate
  61. 60 actions to be taken based on each key that may be hit as well
  62. 61 as the next state. The tables are:
  63. 62 InputTable = entry on top of blanks.
  64. 63 EditOverTable = overstrike mode.
  65. 64 EditInsertTable = insert mode.
  66. 65 The entries in the state tables are formed by three-character
  67. 66 sequences. (See the initialization code at the end of this
  68. 67 module).
  69. 68
  70. 69 (1) The first character is a non-mnemonic that stands for a
  71. 70 sequence of actions to be taken if a key in that keyclass
  72. 71 is hit. See the KeyAction procedure guts to see which
  73. 72 procedures are executed for which letters. Generally,
  74. 73 these procedures are qualifying procedures that determine
  75. 74 whether or not a keystroke is legal from a given state.
  76. 75 (2) The next character specifies the action to take if the
  77. 76 qualifications are met. "I" stands for insert; "E"
  78. 77 stands for error.
  79. 78 (3) The last character in the state table triplet is the next
  80. 79 state. You'll notice that this is missing in many cases -
  81. 80 that is because of the fact that during editing, the next
  82. 81 state must be dynamically re-computed from the numeric
  83. 82 string AFTER the change has been made.
  84. 83
  85. 84 The state tables are difficult to understand without
  86. 85 diagrams, from which they were created (state transition
  87. 86 diagrams).
  88. 87
  89. 88 The rules referred to above are generally conditions that
  90. 89 would have caused the state tables to grow exponentially had
  91. 90 they been included. InsertCharacter contains a number of
  92. 91 these rules, such as what to do when you are on the last
  93. 92 character in the field under a number of circumstances.
  94. 93
  95. 94 *)
  96. 95
  97. 96 IMPORT BigSets;
  98. 97 IMPORT ErrorManager;
  99. 98 IMPORT KbdInput;
  100. 99 IMPORT Key;
  101. 100 IMPORT LowLevel;
  102. 101 IMPORT M2Strings;
  103. 102 IMPORT Numbers;
  104. 103 IMPORT PosUtils;
  105. 104 IMPORT ScrnTypes;
  106. 105 IMPORT Spkr;
  107. 106 IMPORT StrConv;
  108. 107 IMPORT StrEdit;
  109. 108 IMPORT UserOps;
  110. 109 IMPORT SYSTEM;
  111. 110 IMPORT VWindows;
  112. 111
  113. 112 VAR
  114. 113 Initialized : BOOLEAN;
  115. 114
  116. 115
  117. 116 TYPE
  118. 117 TableIndexType = (InputTable, EditOverTable, EditInsertTable);
  119. 118 (* InputTable = entry on top of blanks *)
  120. 119 (* EditOverTable = overstrike mode *)
  121. 120 (* EditInsertTable = insert mode *)
  122. 121 KeyClassType = (DigitsClass, MinusClass, DecimalPointClass, DollarClass);
  123. 122
  124. 123 CONST
  125. 124 ActionLetters = 2; (* state table action letters + next state - 1 *)
  126. 125 MaxStates = 6; (* max number of states in table *)
  127. 126
  128. 127 VAR
  129. 128 stateTable : ARRAY [InputTable..EditInsertTable],
  130. ***** ^ not supported yet
  131. ***** ^ not supported yet
  132. 129 [DigitsClass..DollarClass],
  133. 130 [0..MaxStates * (ActionLetters+1)] OF CHAR;
  134. 131 (* actions and next states *)
  135. 132
  136. 133 PROCEDURE ReadNumericField
  137. 134 ( WindowHandle : VWindows.AWindowHandle; (* in *)
  138. 135 VAR TheStr : ARRAY OF CHAR; (* in/out - field contents *)
  139. 136 col1 : CARDINAL; (* in - field loc *)
  140. 137 row1 : CARDINAL; (* in - field loc *)
  141. 138 FieldWidth : CARDINAL; (* in - # chars. in field *)
  142. 139 DecimalPlaces: ScrnTypes.DecimalPlaceType;
  143. 140 (* in - # digits after . *)
  144. 141 minusOK : BOOLEAN; (* in - "-" permitted *)
  145. 142 VAR LastKey : CARDINAL; (* in/out - last key hit *)
  146. 143 VAR ExitKeys : KbdInput.KeyNumSet (* in - keys to exit on *)
  147. 144 );
  148. 145 (*
  149. 146 This is a general-purpose numeric input routine that replaces the PMI
  150. 147 StrInput.ReadNumeric procedure. The parameters are slightly different.
  151. 148 *)
  152. 149
  153. 150 CONST
  154. 151 Minus = ORD('-'); (* numerics required due to LastKey *)
  155. 152 DecimalKey = ORD('.');
  156. 153 DollarSignKey = ORD('$');
  157. 154 ZeroKey = ORD('0');
  158. 155 NineKey = ORD('9');
  159. 156 CurrencySymbol = '$';
  160. 157 blank = ' ';
  161. 158 periodChar = '.';
  162. 159 minusChar = '-';
  163. 160 zeroChar = '0';
  164. 161 MaxFieldSize = 255;
  165. 162 ErrorState = 9999; (* arbitrary error state *)
  166. 163 LeaveLast = TRUE; (* last character in field can't be overstruck *)
  167. 164 VAR
  168. 165 (* old PMI variables still used *)
  169. 166 SavedHeight : CARDINAL;
  170. 167
  171. 168 curPos : CARDINAL; (* index to TheStr *)
  172. 169 curTable : TableIndexType; (* current state table *)
  173. 170 editInProgress : BOOLEAN; (* TRUE if editing started *)
  174. 171 escapeHit : BOOLEAN; (* ESC restores string *)
  175. 172 fieldEnd : CARDINAL; (* FieldWidth - 1 *)
  176. 173 originalStr : ARRAY [0..MaxFieldSize] OF CHAR;
  177. 174 (* copy to restore by ESC *)
  178. 175 periodOK : BOOLEAN; (* FALSE for INT and CARD *)
  179. 176 states : ARRAY [InputTable..EditInsertTable] OF CARDINAL;
  180. 177 (* state for each table *)
  181. 178
  182. 179 (*
  183. 180 The following group of procedures supports editing functions and are
  184. 181 NOT involved with the state tables.
  185. 182 *)
  186. 183 PROCEDURE DeleteCharacter;
  187. 184 (* Delete the character at the current cursor position *)
  188. 185 (* Any characters to the right of curPos move left *)
  189. 186 (* Implements part of DEL key. Doesn't move cursor position. *)
  190. 187 VAR
  191. 188 shiftIndex : CARDINAL;
  192. 189 BEGIN (* procedure DeleteCharacter *)
  193. 190 IF curPos < fieldEnd THEN
  194. 191 FOR shiftIndex := curPos TO fieldEnd DO
  195. 192 TheStr[ shiftIndex ] := TheStr[ shiftIndex + 1 ];
  196. 193 END; (* for shiftIndex *)
  197. 194 END; (* if curPos *)
  198. 195 TheStr[ fieldEnd ] := blank;
  199. 196 escapeHit := FALSE;
  200. 197 END DeleteCharacter; (* procedure *)
  201. 198
  202. 199 PROCEDURE PreviousContents;
  203. 200 (* replace current contents of field with original contents *)
  204. 201 (* Be sure to recompute table state afterwards *)
  205. 202 (* Implements ESC key in part. *)
  206. 203 BEGIN (* procedure PreviousContents *)
  207. 204 StrEdit.AssignStr( originalStr, TheStr );
  208. 205 curPos := 0;
  209. 206 END PreviousContents; (* procedure *)
  210. 207
  211. 208 PROCEDURE BlankOutField( startPos : CARDINAL );
  212. 209 (* Replace the designated portion of the field with blanks. *)
  213. 210 VAR
  214. 211 strIndex : CARDINAL;
  215. 212 BEGIN (* procedure BlankOutField *)
  216. 213 FOR strIndex := startPos TO fieldEnd DO
  217. 214 TheStr[ strIndex ] := blank;
  218. 215 END; (* for strIndex *)
  219. 216 END BlankOutField; (* procedure *)
  220. 217
  221. 218
  222. 219 PROCEDURE CleanUpTheStr(): BOOLEAN;
  223. 220 (* "Cleans up" the string in the field that the user wants to leave *)
  224. 221 (* This procedure is meant to be executed whenever field movement keys *)
  225. 222 (* have been hit. E.g. TAB, PgUp, PgDn, Shift TAB, etc. *)
  226. 223 (* Actions performed: *)
  227. 224 (* Leading Zeroes stripped. *)
  228. 225 (* Decimal point forced in if not there. *)
  229. 226 (* Trailing Zeroes added after decimal point without enough *)
  230. 227 (* digits after it. *)
  231. 228 (* Decimal point with too many digits after it causes truncation *)
  232. 229 (* of extra digits, beep, and cursor left in field. *)
  233. 230 (* Fields with no numeric digits are blanked out. *)
  234. 231 (* Be sure to recompute table state afterwards *)
  235. 232 VAR
  236. 233 strIndex, decSpot, decDigits : CARDINAL;
  237. 234 anyNumerics : BOOLEAN; (* TRUE if field contains any digits *)
  238. 235
  239. 236 PROCEDURE StopFieldExit;
  240. 237 (* An adjustment to the field has been made that requires user's *)
  241. 238 (* attention - prevent exit from the field (aborting key action). *)
  242. 239 BEGIN (* procedure StopFieldExit *)
  243. 240 (* Don't allow the field to be exited - set up as just entered *)
  244. 241 StrEdit.LeftJustify( TheStr, FieldWidth );
  245. 242 LastKey := 0;
  246. 243 curPos := 0;
  247. 244 (* And try to wake up the user that this has happened! *)
  248. 245 Spkr.Noise( Spkr.Beep, Spkr.High, Spkr.Medium );
  249. 246 END StopFieldExit; (* procedure *)
  250. 247
  251. 248 PROCEDURE NoDecimalPoint;
  252. 249 (* Process a string that has no decimal point. For Reals only. *)
  253. 250
  254. 251 PROCEDURE InsertLeftJustified
  255. 252 ( insChar : CHAR; (* character to insert *)
  256. 253 pos : CARDINAL (* position in TheStr *)
  257. 254 );
  258. 255 (* puts insChar into TheStr at location pos; rightmost char gone *)
  259. 256 VAR
  260. 257 strIndex : CARDINAL;
  261. 258 BEGIN (* procedure InsertLeftJustified *)
  262. 259 (* move what's there over; forget the leftmost character *)
  263. 260 IF fieldEnd > 0 THEN
  264. 261 FOR strIndex := fieldEnd-1 TO pos BY -1 DO
  265. 262 TheStr[ strIndex+1 ] := TheStr[ strIndex ];
  266. 263 END; (* for strIndex *)
  267. 264 TheStr[ pos ] := insChar;
  268. 265 END; (* if fieldEnd *)
  269. 266 END InsertLeftJustified; (* procedure *)
  270. 267
  271. 268 VAR
  272. 269 decPointPos : CARDINAL; (* where the decimal point goes *)
  273. 270 rightSubStr : ARRAY [0..80] OF CHAR; (* str in front of dec pt. *)
  274. 271 trailingDig : BOOLEAN; (* true if digits after dec. point *)
  275. 272
  276. 273 BEGIN (* procedure NoDecimalPoint *)
  277. 274 (* note that TheStr does not necessarily have length = FieldWidth! *)
  278. 275 StrEdit.LeftJustify( TheStr, FieldWidth );
  279. 276 (* if necessary, sacrifice the last digit to make room for '.' *)
  280. 277 decPointPos := FieldWidth-VAL(CARDINAL,DecimalPlaces)-1;
  281. 278 InsertLeftJustified( periodChar, decPointPos );
  282. 279 (* right justify with period as a boundary *)
  283. 280 IF decPointPos > 0 THEN
  284. 281 M2Strings.Copy( TheStr, 0, decPointPos, rightSubStr );
  285. 282 StrEdit.RightJustify( rightSubStr, decPointPos );
  286. 283 StrEdit.OverWrite( rightSubStr, TheStr, 0 ); (* put back in, shifted *)
  287. 284 END; (* if decPointPos *)
  288. 285 (* Fill in any gaps with zeroes. *)
  289. 286 trailingDig := FALSE;
  290. 287 FOR strIndex := decPointPos+1 TO fieldEnd DO
  291. 288 IF TheStr[ strIndex ] = blank THEN
  292. 289 TheStr[ strIndex ] := zeroChar;
  293. 290 ELSE
  294. 291 trailingDig := TRUE;
  295. 292 END; (* if TheStr *)
  296. 293 END; (* for strIndex *)
  297. 294
  298. 295 (* Alert the user only if dec. point was added in middle of digits *)
  299. 296 IF trailingDig THEN
  300. 297 StopFieldExit;
  301. 298 END; (* if trailingDig *)
  302. 299 END NoDecimalPoint; (* procedure *)
  303. 300
  304. 301
  305. 302 BEGIN (* procedure CleanUpTheStr *)
  306. 303 (* Blank fields ignored *)
  307. 304 IF PosUtils.IsBlank( TheStr ) THEN
  308. 305 RETURN( TRUE );
  309. 306 END; (* if PosUtils.IsBlank *)
  310. 307
  311. 308 (* Another check - if there were no numeric digits, blank out. *)
  312. 309 anyNumerics := FALSE;
  313. 310 FOR strIndex := 0 TO fieldEnd DO
  314. 311 anyNumerics := anyNumerics OR
  315. 312 PosUtils.IsNumericChar( TheStr[ strIndex ] )
  316. 313 END; (* for strIndex *)
  317. 314 IF NOT anyNumerics THEN
  318. 315 BlankOutField( 0 );
  319. 316 RETURN( TRUE ); (* not much point in doing anything else *)
  320. 317 END; (* if NOT *)
  321. 318
  322. 319 (* First, out with the leading zeroes. Leave last one. *)
  323. 320 (* Note also removes zeroes for -00.33 or $00.33 *)
  324. 321 strIndex := 0;
  325. 322 LOOP
  326. 323 IF TheStr[ strIndex ] = zeroChar THEN
  327. 324 TheStr[ strIndex ] := blank;
  328. 325 END; (* if TheStr *)
  329. 326 IF (strIndex = fieldEnd) OR (TheStr[strIndex] = periodChar) OR
  330. 327 ((TheStr[strIndex] # zeroChar) AND (* stop on non-zero digit *)
  331. 328 PosUtils.IsNumericChar( TheStr[strIndex] ))
  332. 329 THEN
  333. 330 EXIT;
  334. 331 END; (* if strIndex *)
  335. 332 INC( strIndex );
  336. 333 END; (* loop *)
  337. 334 (* Don't leave just a period in the field, though *)
  338. 335 IF (TheStr[strIndex] = periodChar) AND
  339. 336 (NOT PosUtils.IsNumericChar( TheStr[strIndex+1] )) THEN
  340. 337 StrEdit.InsertRightJustified( zeroChar, TheStr, strIndex );
  341. 338 END; (* if TheStr *)
  342. 339 IF PosUtils.IsBlank( TheStr ) THEN
  343. 340 TheStr[ 0 ] := zeroChar; (* at least one there *)
  344. 341 END; (* if PosUtils.IsBlank *)
  345. 342 (* Get rid of any blanks after punctuation ($ 33.) *)
  346. 343 StrEdit.DeleteChar( blank, TheStr ); (* trailing gone too *)
  347. 344
  348. 345 (* find decimal point (if real type) *)
  349. 346 (* User-specified decimal points not enforced (DecimalPlaces=-1) *)
  350. 347 IF DecimalPlaces > 0 THEN
  351. 348 IF PosUtils.PresentPos( periodChar, TheStr, decSpot ) THEN
  352. 349 (* count the number of digits after the decimal point *)
  353. 350 decDigits := 0;
  354. 351 FOR strIndex := decSpot+1 TO fieldEnd DO
  355. 352 IF PosUtils.IsNumericChar( TheStr[ strIndex ] ) THEN
  356. 353 INC( decDigits );
  357. 354 END; (* if PosUtils.IsNumericChar *)
  358. 355 END; (* for strIndex *)
  359. 356 IF VAL(INTEGER,decDigits) < DecimalPlaces THEN
  360. 357 (* not enough digits after decimal point *)
  361. 358 (* so force-feed the zeroes *)
  362. 359 FOR strIndex := decSpot+decDigits+1 TO
  363. 360 Numbers.Min( decSpot+VAL(CARDINAL,DecimalPlaces), fieldEnd ) DO
  364. 361 TheStr[ strIndex ] := zeroChar;
  365. 362 END; (* for strIndex *)
  366. 363 IF (fieldEnd - decSpot) < VAL(CARDINAL,DecimalPlaces) THEN
  367. 364 (* not enough room in field for required decimal places *)
  368. 365 (* take out the decimal point and shift it as necessary *)
  369. 366 StrEdit.DeleteChar( periodChar, TheStr );
  370. 367 NoDecimalPoint;
  371. 368 RETURN( FALSE );
  372. 369 END; (* if fieldEnd *)
  373. 370 ELSIF VAL(INTEGER,decDigits) > DecimalPlaces THEN
  374. 371 (* they typed in too many digits after the decimal point - remove *)
  375. 372 FOR strIndex := decSpot+VAL(CARDINAL,DecimalPlaces)+1 TO
  376. 373 decSpot+decDigits+1 DO
  377. 374 TheStr[ strIndex ] := blank;
  378. 375 END; (* for strIndex *)
  379. 376 StopFieldExit;
  380. 377 RETURN( FALSE ); (* Something typed was lost - notify *)
  381. 378 END; (* if decDigits *)
  382. 379 ELSE
  383. 380 NoDecimalPoint;
  384. 381 END; (* if PosUtils.PresentPos *)
  385. 382 END; (* if DecimalPlaces *)
  386. 383
  387. 384 RETURN( TRUE ); (* OK to go ahead and leave field *)
  388. 385 END CleanUpTheStr; (* procedure *)
  389. 386
  390. 387
  391. 388 PROCEDURE ComputeNextState;
  392. 389 (* Used to switch state tables from the various modes *)
  393. 390 (* (Numeric Entry, Insert Editing, Overstrike Editing) *)
  394. 391 (* Called after keys that move the cursor in editing modes *)
  395. 392 BEGIN (* procedure ComputeNextState *)
  396. 393 CASE curTable OF
  397. 394 InputTable:
  398. 395 IF NOT((TheStr[ curPos ] = blank) OR (curPos = fieldEnd)) THEN
  399. 396 (* Must change to an edit mode *)
  400. 397 IF UserOps.InsertMode THEN
  401. 398 curTable := EditInsertTable;
  402. 399 ELSE
  403. 400 curTable := EditOverTable;
  404. 401 END; (* if UserOps.InsertMode *)
  405. 402 END; (* if not *)
  406. 403 | EditInsertTable, EditOverTable:
  407. 404 (* change to InputTable if cursor is on a blank *)
  408. 405 IF (TheStr[ curPos ] = blank) THEN
  409. 406 curTable := InputTable;
  410. 407 ELSIF NOT UserOps.InsertMode THEN
  411. 408 curTable := EditOverTable;
  412. 409 ELSE
  413. 410 curTable := EditInsertTable;
  414. 411 END; (* if TheStr *)
  415. 412 END; (* case curTable *)
  416. 413 (* Now, have to figure out which state we are left in *)
  417. 414 (* This is because the editing actions change the states *)
  418. 415 (* NOTE: This is where the states are documented. Each state *)
  419. 416 (* is represented by three character positional substrings in the *)
  420. 417 (* third dimension of the stateTable array. *)
  421. 418 CASE curTable OF
  422. 419 InputTable:
  423. 420 IF PosUtils.IsBlank( TheStr ) THEN
  424. 421 states[ InputTable ] := 0; (* back to initial *)
  425. 422 ELSIF PosUtils.Present( periodChar, TheStr ) THEN
  426. 423 states[ InputTable ] := 4; (* after period *)
  427. 424 ELSIF PosUtils.Present( CurrencySymbol, TheStr ) THEN
  428. 425 states[ InputTable ] := 3; (* after currency *)
  429. 426 ELSIF PosUtils.Present( minusChar, TheStr ) THEN
  430. 427 IF PosUtils.IsNumericChar( TheStr[curPos] ) THEN
  431. 428 states[ InputTable ] := 5; (* no currency can follow *)
  432. 429 ELSE
  433. 430 states[ InputTable ] := 2; (* bare - *)
  434. 431 END; (* if PosUtils.IsNumber *)
  435. 432 ELSE
  436. 433 states[ InputTable ] := 1; (* numbers only so far *)
  437. 434 END; (* if IsBlank *)
  438. 435 | EditInsertTable, EditOverTable: (* same 4 states for both *)
  439. 436 CASE ORD( TheStr[curPos] ) OF
  440. 437 ZeroKey..NineKey : states[ curTable ] := 0;
  441. 438 | Minus : states[ curTable ] := 1;
  442. 439 | DollarSignKey : states[ curTable ] := 2;
  443. 440 | DecimalKey : states[ curTable ] := 3;
  444. 441 ELSE
  445. 442 states[ curTable ] := ErrorState;
  446. 443 END; (* case TheStr *)
  447. 444 END; (* case curTable *)
  448. 445 END ComputeNextState; (* procedure *)
  449. 446
  450. 447
  451. 448 PROCEDURE FirstSpaceOrEnd;
  452. 449 (* position cursor on first space or at end of field *)
  453. 450 BEGIN (* procedure FirstSpaceOrEnd *)
  454. 451 IF NOT( PosUtils.PresentPos( blank, TheStr, curPos )) THEN
  455. 452 curPos := fieldEnd;
  456. 453 END; (* if NOT *)
  457. 454 END FirstSpaceOrEnd; (* procedure *)
  458. 455
  459. 456
  460. 457 PROCEDURE LeftMove() : BOOLEAN;
  461. 458 (* Move the cursor to the left - TRUE if can do within field *)
  462. 459 BEGIN (* procedure LeftMove *)
  463. 460 IF curPos = 0 THEN
  464. 461 (* Change of plans - you're headed out of the field! *)
  465. 462 LastKey := Key.BackTab; (* get out of the field *)
  466. 463 IF NOT CleanUpTheStr() THEN
  467. 464 ComputeNextState;
  468. 465 ELSE
  469. 466 StrEdit.RightJustify( TheStr, FieldWidth );
  470. 467 END; (* if NOT *)
  471. 468 RETURN( FALSE );
  472. 469 ELSE
  473. 470 DEC( curPos );
  474. 471 RETURN( TRUE );
  475. 472 END; (* if curPos *)
  476. 473 END LeftMove; (* procedure *)
  477. 474
  478. 475 PROCEDURE RightMove;
  479. 476 (* Move the cursor to the right *)
  480. 477 BEGIN (* procedure RightMove *)
  481. 478 IF curPos = fieldEnd THEN
  482. 479 (* go to the next frame! *)
  483. 480 LastKey := Key.Tab;
  484. 481 StrEdit.RightJustify( TheStr, FieldWidth );
  485. 482 ELSE
  486. 483 INC( curPos );
  487. 484 END; (* if curPos *)
  488. 485 END RightMove; (* procedure *)
  489. 486
  490. 487
  491. 488 (*
  492. 489 Well, at last we've reached the end of the edit-oriented
  493. 490 procedures. What follows are the procedures to support the
  494. 491 stateTable actions and transitions. These substrings are coded
  495. 492 "AAT" in the stateTable, where AA are characters indicating
  496. 493 actions to take and T is an optional next state. Next states
  497. 494 have to be computed for both EditOver and EditInsert tables.
  498. 495 *)
  499. 496
  500. 497 PROCEDURE KeyAction( keyClass : KeyClassType );
  501. 498 (* process the key struck - keyClass indicates type of key struck *)
  502. 499 (* The current table, the current state, and the key class all *)
  503. 500 (* determine the actions to take and the next state, if any, to go to. *)
  504. 501 (*
  505. 502 Next state is only provided in input table; the edit tables
  506. 503 must compute the next state based on the character that the
  507. 504 cursor is on after the edit action; they are not input-driven.
  508. 505 *)
  509. 506 CONST
  510. 507 MaxProcs = 3; (* max number of letters for one state *)
  511. 508 VAR
  512. 509 whichLetter : CARDINAL;
  513. 510 procLetters : ARRAY [0..MaxProcs] OF CHAR;
  514. 511 passedTests : BOOLEAN; (* used during edit modes *)
  515. 512 nextState : CARDINAL;
  516. 513
  517. 514
  518. 515 PROCEDURE ErrorInKeyStroke;
  519. 516 (* What to do when an error occurs - also used for parsing errors *)
  520. 517 (* Called by 'E' command. *)
  521. 518 BEGIN (* procedure ErrorInKeyStroke *)
  522. 519 Spkr.Noise( Spkr.Beep, Spkr.Normal, Spkr.Short );
  523. 520 nextState := states[ curTable ]; (* stay where you are *)
  524. 521 END ErrorInKeyStroke; (* procedure *)
  525. 522
  526. 523 PROCEDURE InsertCharacter;
  527. 524 (* Put the keystroke into TheStr at curPos *)
  528. 525 (* If any tests done previous have failed, refuse character and beep. *)
  529. 526 (* Called by 'I' command. *)
  530. 527 VAR
  531. 528 targetPos : CARDINAL; (* for moving characters *)
  532. 529 BEGIN (* procedure InsertCharacter *)
  533. 530 (* not OK to shift out characters *)
  534. 531 IF passedTests AND NOT(UserOps.InsertMode AND (TheStr[ fieldEnd ] # blank))
  535. 532 THEN
  536. 533 IF UserOps.InsertMode THEN (* insert mode *)
  537. 534 (* move string to the right by 1, then put in character *)
  538. 535 (* NOT OK to shift right on out of the field *)
  539. 536 IF (FieldWidth >= 2) AND (curPos < fieldEnd) THEN
  540. 537 FOR targetPos := FieldWidth-2 TO curPos BY -1 DO
  541. 538 TheStr[ targetPos+1 ] := TheStr[ targetPos ];
  542. 539 END; (* for targetPos *)
  543. 540 END; (* if FieldWidth *)
  544. 541 END; (* if UserOps.InsertMode *)
  545. 542 IF (curPos = FieldWidth - 1) AND (TheStr[ curPos ] # blank)
  546. 543 AND (UserOps.InsertMode AND LeaveLast)
  547. 544 THEN
  548. 545 (* Don't replace character if you're on the last field position, *)
  549. 546 (* a non-blank character is already there, and the constant *)
  550. 547 (* LeaveLast is TRUE, and you're in insert mode. *)
  551. 548 ErrorInKeyStroke;
  552. 549 ELSE (* All other combinations generate replacement *)
  553. 550 IF (curPos = FieldWidth - 1) AND (TheStr[ curPos ] # blank) THEN
  554. 551 (* You're on the last character in the field *)
  555. 552 Spkr.Noise( Spkr.Beep, Spkr.Normal, Spkr.Short );
  556. 553 END; (* if curPos *)
  557. 554 (* replace character under cursor and move cursor right *)
  558. 555 TheStr[ curPos ] := VAL( CHAR, LastKey );
  559. 556 INC( curPos );
  560. 557 IF curPos >= FieldWidth THEN
  561. 558 curPos := FieldWidth - 1;
  562. 559 END; (* if curPos *)
  563. 560 END; (* if curpos *)
  564. 561 ELSE
  565. 562 ErrorInKeyStroke;
  566. 563 END; (* if passedTests *)
  567. 564 END InsertCharacter; (* procedure *)
  568. 565
  569. 566 PROCEDURE PresentChar;
  570. 567 (* tests to see if the key struck is already present - fails if so. *)
  571. 568 (* Called by 'P', 'A', 'B', 'F', 'G', 'H', 'J', and 'K' commands. *)
  572. 569 VAR
  573. 570 strKey : ARRAY [0..1] OF CHAR;
  574. 571 BEGIN (* procedure PresentChar *)
  575. 572 strKey[0] := CHR(LastKey);
  576. 573 strKey[1] := CHR(0);
  577. 574 passedTests := passedTests AND
  578. 575 (NOT (PosUtils.Present( strKey, TheStr )));
  579. 576 END PresentChar; (* procedure *)
  580. 577
  581. 578 PROCEDURE DigitToLeft;
  582. 579 (* Fails if there is a digit to the left of the current position *)
  583. 580 (* Called by 'D', 'A', 'C', 'F', 'J', 'K' commands. *)
  584. 581 BEGIN (* procedure DigitToLeft *)
  585. 582 IF curPos > 0 THEN
  586. 583 passedTests := passedTests AND
  587. 584 (NOT PosUtils.IsNumericChar( TheStr[curPos-1] ));
  588. 585 END; (* if curPos *)
  589. 586 END DigitToLeft; (* procedure *)
  590. 587
  591. 588 PROCEDURE LeftCurrency;
  592. 589 (* Fails if there is a currency symbol to the left of the cursor *)
  593. 590 (* Called by 'L', 'A', and 'C' commands. *)
  594. 591 BEGIN (* procedure LeftCurrency *)
  595. 592 IF curPos > 0 THEN
  596. 593 passedTests := passedTests AND
  597. 594 (NOT (TheStr[curPos-1] = CurrencySymbol ));
  598. 595 END; (* if curPos *)
  599. 596 END LeftCurrency; (* procedure *)
  600. 597
  601. 598 PROCEDURE RightCurrency;
  602. 599 (* Fails if there is a currency symbol to the right of the cursor *)
  603. 600 (* Called by 'R' and 'H' commands. *)
  604. 601 BEGIN (* procedure RightCurrency *)
  605. 602 IF curPos < fieldEnd THEN
  606. 603 passedTests := passedTests AND
  607. 604 (NOT (TheStr[curPos+1] = CurrencySymbol ));
  608. 605 END; (* if curPos *)
  609. 606 END RightCurrency; (* procedure *)
  610. 607
  611. 608 PROCEDURE PeriodToTheLeft;
  612. 609 (* Fails if there is a period to the left of the cursor *)
  613. 610 (* Called by 'Z', 'C', and 'K' commands. *)
  614. 611 BEGIN (* procedure PeriodToTheLeft *)
  615. 612 IF curPos > 0 THEN
  616. 613 passedTests := passedTests AND
  617. 614 (NOT (TheStr[curPos-1] = periodChar ));
  618. 615 END; (* if curPos *)
  619. 616 END PeriodToTheLeft; (* procedure *)
  620. 617
  621. 618 PROCEDURE WithinDecimalPlaces;
  622. 619 (* if REAL and decimal hit, have too many digits been typed? *)
  623. 620 (* Called by 'W' command. *)
  624. 621 VAR
  625. 622 strIndex : CARDINAL;
  626. 623 BEGIN (* procedure WithinDecimalPlaces *)
  627. 624 IF (DecimalPlaces > 0 ) AND
  628. 625 PosUtils.PresentPos( periodChar, TheStr, strIndex ) AND
  629. 626 (strIndex < curPos) AND
  630. 627 (VAL(INTEGER,(curPos - strIndex)) > DecimalPlaces) THEN
  631. 628 passedTests := FALSE;
  632. 629 END; (* if PosUtils.PresentPos *)
  633. 630 END WithinDecimalPlaces; (* procedure *)
  634. 631
  635. 632 PROCEDURE MinusOK;
  636. 633 (* called only when minusChar key hit. Fails if minusOK FALSE. *)
  637. 634 (* Called by 'M', 'A', 'B', 'C', and 'F' commands. *)
  638. 635 BEGIN (* procedure MinusOK *)
  639. 636 passedTests := passedTests AND minusOK;
  640. 637 END MinusOK; (* procedure *)
  641. 638
  642. 639 PROCEDURE PeriodOK;
  643. 640 (* called only when '.' key hit. Fails if periodOK FALSE. *)
  644. 641 (* Called by 'Y', 'G', and 'H' commands. *)
  645. 642 BEGIN (* procedure PeriodOK *)
  646. 643 passedTests := passedTests AND periodOK;
  647. 644 END PeriodOK; (* procedure *)
  648. 645
  649. 646 PROCEDURE GetNextState() : CARDINAL;
  650. 647 (* compute the next state from the current state and state table *)
  651. 648 BEGIN (* procedure GetNextState *)
  652. 649 IF stateTable[ curTable ][ keyClass ][ states[curTable]*MaxProcs+2 ]
  653. 650 = blank THEN
  654. 651 RETURN( states[ curTable ] ); (* no change if blank *)
  655. 652 ELSIF StrConv.StrToCardinal( stateTable[ curTable ][ keyClass ]
  656. 653 [ states[curTable]*MaxProcs+2 ], 0,
  657. 654 nextState ) THEN
  658. 655 RETURN( nextState );
  659. 656 ELSE
  660. 657 RETURN( ErrorState );
  661. 658 END; (* if stateTable *)
  662. 659 END GetNextState; (* procedure *)
  663. 660
  664. 661 BEGIN (* procedure KeyAction *)
  665. 662 (* index into the state table to pick up the two action characters *)
  666. 663 procLetters[0] := stateTable[ curTable ][ keyClass ]
  667. 664 [ states[curTable]*MaxProcs ];
  668. 665 procLetters[1] := stateTable[ curTable ][ keyClass ]
  669. 666 [ states[curTable]*MaxProcs+1 ];
  670. 667 IF states[ curTable ] = ErrorState THEN
  671. 668 (* This is an internal error *)
  672. 669 Spkr.Noise( Spkr.Beep, Spkr.RealHigh, Spkr.Long );
  673. 670 BlankOutField( 0 );
  674. 671 curPos := 0;
  675. 672 ComputeNextState;
  676. 673 ELSE
  677. 674
  678. 675 (* Ever optimistic, set up the series of edit tests *)
  679. 676 passedTests := TRUE;
  680. 677 (* Execute all the procs called for in the state table *)
  681. 678 FOR whichLetter := 0 TO MaxProcs-2 DO
  682. 679 CASE procLetters[ whichLetter ] OF
  683. 680 'A' : MinusOK; (* MPLD *)
  684. 681 PresentChar;
  685. 682 LeftCurrency;
  686. 683 DigitToLeft; |
  687. 684 'B' : MinusOK; (* MP *)
  688. 685 PresentChar; |
  689. 686 'C' : MinusOK; (* MPLDZ *)
  690. 687 PresentChar;
  691. 688 LeftCurrency;
  692. 689 DigitToLeft;
  693. 690 PeriodToTheLeft; |
  694. 691 'D' : DigitToLeft; |
  695. 692 'E' : ErrorInKeyStroke; |
  696. 693 'F' : MinusOK; (* MPD *)
  697. 694 PresentChar;
  698. 695 DigitToLeft; |
  699. 696 'G' : PeriodOK; (* YP *)
  700. 697 PresentChar; |
  701. 698 'H' : PeriodOK; (* YPR *)
  702. 699 PresentChar;
  703. 700 RightCurrency; |
  704. 701 'I' : InsertCharacter; |
  705. 702 'J' : PresentChar; (* PD *)
  706. 703 DigitToLeft; |
  707. 704 'K' : PresentChar; (* PDZ *)
  708. 705 DigitToLeft;
  709. 706 PeriodToTheLeft; |
  710. 707 'L' : LeftCurrency; |
  711. 708 'M' : MinusOK; |
  712. 709 'P' : PresentChar; |
  713. 710 'R' : RightCurrency; |
  714. 711 'W' : WithinDecimalPlaces; |
  715. 712 'Y' : PeriodOK; |
  716. 713 'Z' : PeriodToTheLeft; |
  717. 714 ' ' : ; (* do nothing on blank *)
  718. 715 ELSE
  719. 716 ErrorInKeyStroke;
  720. 717 END; (* case ord *)
  721. 718 END; (* for whichLetter *)
  722. 719 escapeHit := FALSE; (* after a real character *)
  723. 720 states[ curTable ] := GetNextState(); (* one change per keystroke *)
  724. 721 END; (* if states *)
  725. 722 END KeyAction; (* procedure *)
  726. 723
  727. 724
  728. 725 (*
  729. 726 Here is the start of ReadNumericField, proper.
  730. 727 *)
  731. 728 BEGIN
  732. 729 (* First we make sure the FieldWidth is okay. *)
  733. 730 IF FieldWidth = 0 THEN
  734. 731 FieldWidth := HIGH( TheStr ) + 1;
  735. 732 ELSE
  736. 733 FieldWidth := Numbers.Min( HIGH(TheStr) + 1, FieldWidth );
  737. 734 END;
  738. 735 FieldWidth := Numbers.Min( VWindows.EndCol(WindowHandle) - col1,
  739. 736 FieldWidth );
  740. 737 SavedHeight := VWindows.GetCursorHeight(WindowHandle);
  741. 738 IF UserOps.InsertMode THEN
  742. 739 VWindows.SetCursorHeight( WindowHandle, 6 )
  743. 740 ELSE
  744. 741 VWindows.SetCursorHeight( WindowHandle, 2);
  745. 742 END;
  746. 743
  747. 744 fieldEnd := FieldWidth - 1;
  748. 745 (* save the original string. ESC key will restore *)
  749. 746 StrEdit.AssignStr( TheStr, originalStr );
  750. 747 (* set the original states *)
  751. 748 states[ InputTable ] := 0;
  752. 749 states[ EditOverTable ] := 0;
  753. 750 states[ EditInsertTable ] := 0;
  754. 751 editInProgress := FALSE; (* must first hit editing key to start *)
  755. 752 escapeHit := TRUE; (* allow esc exit until another key *)
  756. 753 IF DecimalPlaces = 0 THEN (* Note: Real numbers with 0 decimal places *)
  757. 754 periodOK := FALSE; (* cannot have a decimal point in them. *)
  758. 755 ELSE
  759. 756 periodOK := TRUE;
  760. 757 END; (* if DecimalPlaces *)
  761. 758 (* initially in input mode unless there is something already there. *)
  762. 759 curPos := 0; (* appropriate for new entry *)
  763. 760 curTable := InputTable; (* will be adjusted if required *)
  764. 761
  765. 762 REPEAT
  766. 763 VWindows.DrawStr( WindowHandle, col1, row1, SYSTEM.ADR(TheStr), 0 );
  767. 764 VWindows.GotoXY( WindowHandle, col1 + curPos, row1 );
  768. 765 LastKey := KbdInput.KeyHit( KbdInput.AnyKeyNum );
  769. 766
  770. 767 IF NOT editInProgress THEN
  771. 768 (* completely different actions until "editing" key hit. *)
  772. 769 CASE LastKey OF
  773. 770 Key.Home, Key.End, Key.Right, Key.Del, Key.Ins:
  774. 771 StrEdit.LeftJustify( TheStr, FieldWidth );
  775. 772 editInProgress := TRUE;
  776. 773 | Key.AltD, Key.AltE, Key.Space:
  777. 774 (* perform action in the next section *)
  778. 775 editInProgress := TRUE;
  779. 776 | ZeroKey..NineKey, Minus, DecimalKey, DollarSignKey :
  780. 777 BlankOutField( 0 );
  781. 778 editInProgress := TRUE;
  782. 779 ComputeNextState;
  783. 780 ELSE
  784. 781 IF NOT BigSets.InSet( ExitKeys, LastKey ) THEN
  785. 782 Spkr.Noise( Spkr.Beep, Spkr.Normal, Spkr.Short );
  786. 783 END; (* if NOT *)
  787. 784 END; (* case Lastkey *)
  788. 785 END; (* if NOT *)
  789. 786
  790. 787 IF editInProgress THEN
  791. 788 CASE LastKey OF
  792. 789 ZeroKey..NineKey: (* ASCII values of zeroChar to '9' *)
  793. 790 KeyAction( DigitsClass );
  794. 791 IF curTable # InputTable THEN
  795. 792 ComputeNextState;
  796. 793 END; (* if curtable *)
  797. 794 | Minus: (* minusChar *)
  798. 795 KeyAction( MinusClass );
  799. 796 IF curTable # InputTable THEN
  800. 797 ComputeNextState;
  801. 798 END; (* if curtable *)
  802. 799 | DecimalKey:
  803. 800 KeyAction( DecimalPointClass );
  804. 801 IF curTable # InputTable THEN
  805. 802 ComputeNextState;
  806. 803 END; (* if curtable *)
  807. 804 | DollarSignKey:
  808. 805 KeyAction( DollarClass );
  809. 806 IF curTable # InputTable THEN
  810. 807 ComputeNextState;
  811. 808 END; (* if curtable *)
  812. 809
  813. 810 | Key.Ins:
  814. 811 UserOps.InsertMode := NOT UserOps.InsertMode;
  815. 812 IF UserOps.InsertMode THEN
  816. 813 VWindows.SetCursorHeight( WindowHandle, 6 )
  817. 814 ELSE
  818. 815 VWindows.SetCursorHeight( WindowHandle, 2);
  819. 816 END;
  820. 817 | Key.Del:
  821. 818 DeleteCharacter;
  822. 819 ComputeNextState;
  823. 820 LastKey := 0; (* Don't want it seen as exit key *)
  824. 821 | Key.BackSpace:
  825. 822 IF LeftMove() THEN
  826. 823 DeleteCharacter;
  827. 824 ComputeNextState;
  828. 825 END; (* if LeftMove *)
  829. 826 | Key.Left: (* left arrow *)
  830. 827 LastKey := 0; (* prevent leaving field *)
  831. 828 IF LeftMove() THEN
  832. 829 ComputeNextState;
  833. 830 END; (* if LeftMove *)
  834. 831 | Key.Right: (* right arrow *)
  835. 832 LastKey := 0; (* prevent leaving field *)
  836. 833 RightMove;
  837. 834 ComputeNextState;
  838. 835 | Key.Escape:
  839. 836 IF NOT escapeHit THEN (* second escape gets out of frame *)
  840. 837 PreviousContents; (* restore original value *)
  841. 838 ComputeNextState;
  842. 839 escapeHit := TRUE;
  843. 840 LastKey := 0; (* prevent frame exit *)
  844. 841 editInProgress := FALSE; (* and take out of edit mode *)
  845. 842 ELSE
  846. 843 StrEdit.RightJustify( TheStr, FieldWidth ); (* allow exit *)
  847. 844 END; (* if not escapeHit *)
  848. 845 | Key.Home:
  849. 846 curPos := 0; (* move to leftmost char in field *)
  850. 847 ComputeNextState;
  851. 848 | Key.End:
  852. 849 FirstSpaceOrEnd; (* put cursor after/on last char *)
  853. 850 ComputeNextState;
  854. 851 | Key.AltD, Key.Space: (* delete entire entry *)
  855. 852 BlankOutField( 0 );
  856. 853 curPos := 0;
  857. 854 ComputeNextState;
  858. 855 | Key.AltE: (* erase from cursor to field end *)
  859. 856 BlankOutField( curPos );
  860. 857 ComputeNextState;
  861. 858
  862. 859 ELSE
  863. 860 IF NOT BigSets.InSet( ExitKeys, LastKey ) THEN
  864. 861 Spkr.Noise( Spkr.Beep, Spkr.Normal, Spkr.Short );
  865. 862 ELSE (* always clean up before you can leave - might fail! *)
  866. 863 (* CleanUpTheStr will change LastKey if it fails - prevent exit. *)
  867. 864 IF NOT CleanUpTheStr() THEN
  868. 865 ComputeNextState;
  869. 866 ELSE
  870. 867 StrEdit.RightJustify( TheStr, FieldWidth );
  871. 868 END; (* if NOT *)
  872. 869 END; (* if NOT *)
  873. 870 END;
  874. 871 END; (* if editInProgress *)
  875. 872 UNTIL BigSets.InSet( ExitKeys, LastKey );
  876. 873 VWindows.SetCursorHeight( WindowHandle, SavedHeight );
  877. 874 END ReadNumericField;
  878. 875
  879. 876 PROCEDURE LoadTableRow
  880. 877 ( inputStr : ARRAY OF CHAR; (* action string for input *)
  881. 878 overStr : ARRAY OF CHAR; (* string for overstrike *)
  882. 879 insertStr : ARRAY OF CHAR; (* string for insert mode *)
  883. 880 keyClass : KeyClassType (* second dimension of table *)
  884. 881 );
  885. 882 (* Loads the three action strings into the state table array *)
  886. 883 (* Used to initialize the array *)
  887. 884 BEGIN (* procedure LoadTableRow *)
  888. 885 StrEdit.AssignStr( inputStr, stateTable[ InputTable ] [ keyClass ] );
  889. 886 StrEdit.AssignStr( overStr, stateTable[ EditOverTable ] [ keyClass ] );
  890. 887 StrEdit.AssignStr( insertStr, stateTable[ EditInsertTable ] [ keyClass ] );
  891. 888 END LoadTableRow; (* procedure *)
  892. 889
  893. 890 PROCEDURE InitStateTable;
  894. 891 (* Initialize the state table; called once when field entered *)
  895. 892 (* Invoke from the initialization section of the module *)
  896. 893 BEGIN (* procedure InitStateTable *)
  897. 894 LoadTableRow( " I1 I1 I5 I3WI4 I5", " I RI I I ", " I E E I ",
  898. 895 DigitsClass );
  899. 896 LoadTableRow( "MI2 E E E E E ", "AI MI BI AI ", "CI E FI AI ",
  900. 897 MinusClass );
  901. 898 LoadTableRow( "YI4YI4YI4YI4 E YI4", "GI HI GI YI ", "GI E E E ",
  902. 899 DecimalPointClass );
  903. 900 LoadTableRow( " I3 E I3 E E E ", "JI PI I JI ", "KI E E JI ",
  904. 901 DollarClass );
  905. 902 END InitStateTable; (* procedure *)
  906. 903
  907. 904
  908. 905 PROCEDURE Init();
  909. 906 BEGIN
  910. 907 IF Initialized THEN
  911. 908 RETURN;
  912. 909 ELSE
  913. 910 Initialized := TRUE;
  914. 911 END;
  915. 912 BigSets.Init();
  916. 913 ErrorManager.Init();
  917. 914 KbdInput.Init();
  918. 915 Key.Init();
  919. 916 LowLevel.Init();
  920. 917 M2Strings.Init();
  921. 918 Numbers.Init();
  922. 919 PosUtils.Init();
  923. 920 ScrnTypes.Init();
  924. 921 Spkr.Init();
  925. 922 StrConv.Init();
  926. 923 StrEdit.Init();
  927. 924 UserOps.Init();
  928. 925 VWindows.Init();
  929. 926
  930. 927 InitStateTable(); (* load the table with action strings *)
  931. 928 END Init;
  932. 929
  933. 930 BEGIN
  934. 931 Initialized := FALSE;
  935. 932 Init();
  936. 933 END NumInput.
  937. 2 errors