home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / forth / compiler / fpc / tutor / l3p170 < prev    next >
Text File  |  1990-07-15  |  8KB  |  197 lines

  1.        ╔════════════════════════════════════════════════════╗
  2.        ║ Lesson 3 Part 170  F-PC 3.5 Tutorial by Jack Brown ║
  3.        ╚════════════════════════════════════════════════════╝
  4.  
  5. \ Original Date: September 12, 1988
  6. \ Last Modified: September 28, 1988
  7. \ Author:        Jack W. Brown
  8. \ Function:      Boiler plate, Bullet proof integer numeric input.
  9. \ Usage:         <position cursor>  #IN ( -- number )
  10.  
  11. \ Overview:
  12. \ The idea is to allow only valid single signed integer input
  13. \ with editing by checking each key press as it arrives. All
  14. \ invalid key presses including function keys will be rejected.
  15. \ The value of the number is formed as valid digits are entered
  16. \ so that it is impossible to enter a number outside the range
  17. \ of -32767 through 32767.  If the cursor is first positioned
  18. \ screen entry will be limited to 6 character positions from this
  19. \ initial cursor postion.
  20.  
  21. \ Notes:
  22. \ 1) All word defintions have been author and date coded to
  23. \    reflect the date and author of the most recent change.
  24. \ 2) Revision history added to beginning of file.
  25. \    This is absolute requirement when a team of programmers
  26. \    is working on a very large application.  Any change made
  27. \    is reflected in the revision history and with the actual
  28. \    word definition.
  29. \ 3) Only non-FORTH83 word used in #OUT
  30.  
  31. \ Possible Improvements:
  32. \ 1) Modify code to allow single signed number input in any BASE.
  33. \ 2) Modify code or make a new version called D#IN for bullet proof
  34. \    input of signed double integers.
  35.  
  36. \ Revision History:
  37. \ JWB 12 09 88  Converted from F83 Blocks to *.SEQ file for F-PC
  38. \ JWB 28 09 88  Commented out test for invalid interval in (IN)
  39. \ JWB 28 09 88  Inserted comment about non standard word #OUT.
  40. \ JWB 28 09 88  Added CONSTANTs to make code more readable and
  41. \               to avoid non standard ASCII and CONTROL.
  42. \ JWB 28 09 88  Clarified operation of RUBOUT.
  43. \ JWB 28 09 88  Clarified operation of +DIGIT.
  44. \ JWB 28 09 88  Renamed RESET? to CLEAR_SIGN? for readability.
  45. \ JWB 28 09 88  Changed . to _ in CORRECT.IT and PROCESS.IT
  46. \ JWB 28 09 88  Modified NEGATIVE? to include DUP
  47. \ JWB 28 09 88  Reformated #IN and removed DUP to accomodate above.
  48.  
  49. \  Constants added for readablilty.
  50. 07 CONSTANT CONTROL_G   \ Bell character
  51. 08 CONSTANT CONTROL_H   \ Back space character.
  52. 48 CONSTANT ASCII_0     \ The digit " 0 "
  53. 57 CONSTANT ASCII_9     \ The digit " 9 "
  54. 45 CONSTANT ASCII_-     \ The minus sign character.
  55. 13 CONSTANT CONTROL_M   \ The carriage return character
  56.  
  57. \ Interval testing words. Naming convention motivated by the
  58. \ mathematical intervals (a,b) [a,b] (a,b] and [a,b).
  59. \ Would better names be  (A,B) [A,B] ... ?
  60. \ Application Note:  In VP-Planner these four words were
  61. \ implemented in machine code and saved approximately 500 bytes,
  62. \ resulted in increased execution speed and better readability
  63. \ than when actual tests were coded inline in highlevel Forth.
  64.  
  65. \ (IN)  leaves a true flag if   a < x < b
  66. : (IN)  ( x a b --  flag )  ( JWB 28 09 88 )
  67. \        2DUP < NOT ABORT" Invalid interval."
  68.          -ROT OVER < -ROT > AND ;
  69.  
  70. \ [IN]  leaves a true flag if a <= x <= b  , otherwise false.
  71. : [IN]  ( x a b --  flag ) ( JWB 02 10 85 )
  72.         1+ SWAP 1- SWAP (IN) ;
  73.  
  74. \ (IN]  leaves a true flag if a <  x <= b  , otherwise false.
  75. : (IN]  ( x a b --  flag ) ( JWB 02 10 85 )
  76.         1+ (IN) ;
  77.  
  78. \ [IN)  leaves a true flag if a <= x <  b  , otherwise false.
  79. : [IN)  ( x a b --  flag ) ( JWB 02 10 85 )
  80.         SWAP 1- SWAP (IN) ;
  81.  
  82. \ Note #OUT is not in the FORTH83 standard. ( JWB 28 09 88 )
  83. \ #OUT is a variable that contains the number of charaters output since
  84. \ the last carriage return.  Its value must be corrected so that words
  85. \ EMITing characters leave its value the same as the actual horizontal
  86. \ cursor position.  If this is not done systems like L&P F83 may produce
  87. \ auto word wrap when #OUT exceeds 80.
  88.  
  89. \ Sound alarm bell.
  90. : BELL    ( -- ) ( JWB 07 10 85 )
  91.         CONTROL_G EMIT -1 #OUT +! ;
  92.  
  93. \ Leave true flag if valid digit.
  94. : DIGIT?  ( n --  flag ) ( JWB 07 10 85 )
  95.         ASCII_0 ASCII_9 [IN] ;
  96.  
  97. \ Rub out most recent digit. Note that correction to #OUT is -4
  98. \ because three characters have been EMITed and the cursor ends
  99. \ up one character position to the left!
  100. : RUBOUT  ( -- ) ( JWB 28 09 88 )
  101.         CONTROL_H EMIT SPACE
  102.         CONTROL_H EMIT
  103.         -4 #OUT +! ;
  104.  
  105. \ Erase digit from screen, adjust number being formed and
  106. \ decrement the digit count. Note:
  107. \ count = number of digits that have currently been entered.
  108. \ n     = the value of the number currently on the screen.
  109. : -DIGIT  ( count n  --  count-1 n/10 ) ( JWB 28 09 88 )
  110.         RUBOUT        \ Remove character from screen.
  111.         SWAP 1- SWAP  \ Adjust digit count.
  112.         10 / ;        \ Adjust value of number.
  113.  
  114. \ Increment digit count and add in digit. This word is complicated
  115. \ by the fact that we must check to make sure that the digit entered
  116. \ must not allow the number formed to be outside the valid single
  117. \ signed integer range.  Note: n'= 10n+key-48
  118. : +DIGIT  ( count n key --  count+1 n'   If valid key) ( JWB 28 09 88 )
  119.           (             --  count   n    If invalid key )
  120.         SWAP 10 UM*        \ Scale number by 10 and leave as double#.
  121.         2 PICK ASCII_0 -   \ Convert key to digit value.
  122.         0 D+               \ Extend to double, add to leave new value.
  123.         32767. 2OVER DU<   \ Check for out of range single number.
  124.         IF   10 UM/MOD     \ Too big, restore original value.
  125.              NIP NIP BELL  \ remove remainder, and key.
  126.         ELSE DROP          \ convert double number to single number.
  127.              SWAP EMIT     \ Echo digit key to the screen.
  128.              SWAP 1+ SWAP  \ Increment the current digit count.
  129.         THEN ;
  130.  
  131. \ Reset sign flag to indicate non negative number if digit count
  132. \ is zero.
  133. : CLEAR_SIGN? ( flag count n --  ff count n ) ( JWB 28 09 88 )
  134.       OVER 0= IF  ROT DROP FALSE -ROT THEN ;
  135.  
  136. \ Correct an error input.
  137. : CORRECT_IT ( flag count num key --  flag count num ) ( JWB 28 09 88 )
  138.        DROP OVER  0<>         \ Is digit count non zero?
  139.        IF   -DIGIT            \ Remove most recent digit.
  140.        ELSE BELL              \ Sound warning.
  141.        THEN
  142.        CLEAR_SIGN? ; \ Clear numbers sign if count is 0.
  143.  
  144. \ Process all other keystrokes.
  145. : PROCESS_IT ( flag count num key --  flag count num ) ( JWB 28 09 88 )
  146.        DUP  DIGIT?            \ Check for digit.
  147.        IF   +DIGIT            \ Echo & convert digit, inc count
  148.        ELSE DROP BELL         \ Invalid key or overflow.
  149.        THEN ;
  150.  
  151. \ Apply sign to number.
  152. : APPLY-SIGN  ( flg count num key -- num ) ( JWB 28 09 88 )
  153.        DROP NIP SWAP          \ Drop key, nip count, get sign flag.
  154.        IF NEGATE THEN  ;      \ Apply sign to number.
  155.  
  156. \ Negative number?
  157. : NEGATIVE? ( count num key  -- count num key flag ) ( JWB 28 09 88 )
  158.        DUP ASCII_- =  3 PICK 0= AND ;
  159.  
  160. \ Set sign flag to true indicating a negative number
  161. \ is being input.
  162. : SET-FLAG  ( flg cnt num key --  flg cnt num ) ( JWB 07 10 85 )
  163.       EMIT ROT DROP TRUE -ROT   \ Set sign flag true.
  164.       SWAP 1+ SWAP  ;           \ Increment digit count.
  165.  
  166. \ This is the boiler plate, bullet proof interger number
  167. \ input routine.  It supposedly only allows input of positive
  168. \ or negative 16 bit integers.  Only valid digit keys are
  169. \ allowed.
  170. \ flag  = sign flag, true means negative number being entered.
  171. \                   false means positive number.
  172. \ count = current count of digits entered.
  173. \ number= current value of number on users screen.
  174. \ key   = key press code from users input.
  175. : #IN   ( --   number ) ( JWB 28 09 88 )
  176.       FALSE 0 0    ( flag count number )
  177.       BEGIN KEY    ( flag count number key ) \ Fetch key press.
  178.         NEGATIVE?                    \ Negative number?
  179.         IF   SET-FLAG                \ Set sign flag true.
  180.         ELSE DUP CONTROL_M =         \ Return entered?
  181.              IF   APPLY-SIGN EXIT    \ Apply sign to number and exit
  182.              THEN
  183.              DUP CONTROL_H =         \ Correct error input?
  184.              IF   CORRECT_IT         \ This does it.
  185.              ELSE PROCESS_IT         \ Process all other keys.
  186.              THEN
  187.         THEN
  188.       AGAIN ;
  189.  
  190. \ Word to test #IN
  191. : TEST ( -- )
  192.       BEGIN
  193.            CR #IN 3 SPACES DUP .
  194.       0= UNTIL ;
  195.  
  196.  
  197.