home *** CD-ROM | disk | FTP | other *** search
/ The Developer Connection…ice Driver Kit for OS/2 3 / DEV3-D1.ISO / devtools / dataflex / dfbrowse.src < prev    next >
Encoding:
Text File  |  1993-05-19  |  53.5 KB  |  1,536 lines

  1. // DFBROWSE  version 2.21
  2. // Written by Doug Goldner 10/24/1990
  3. // Using DataFlex 3.0 SDK release
  4. // 
  5. // Update to version 2.0 10/30/90
  6. // Update to version 2.1 2/13/91 - Using 3.0 final release
  7. // Update to version 2.2 12/6/91 - Added Zerofile function and help
  8. //
  9. // Invocation:  DFRUN DFBROWSE
  10. //
  11. // Use:
  12. //
  13. //   The program first starts off by allowing the user to select a file
  14. //   to "browse".  Once selected, the .TAG is read and the file definition
  15. //   determined.  The next screen appears which consists of a FIELD TITLE
  16. //   object, a FIELD DATA object, a button area, and a status object.
  17. //
  18. //   The first page of records appears and the status object reflects the
  19. //   current file.field information.  The navigation keys (UPARROW, DOWNARROW,
  20. //   LEFTARROW, RIGHTARROW, TAB, SHIFT-TAB, PgUP, PgDN, etc.) will scroll
  21. //   you around the records in your file.  TAB and SHIFT-TAB (or the arrows
  22. //   in the button area) move right or left 1 field at a time.  The scroll
  23. //   bar will scroll up or down one record at a time.
  24. //
  25. //   The REORDER button or the REORDER key (Alt+R) can be used to reorder
  26. //   the data based upon the main index of the current field.  Indexed
  27. //   fields are denoted by "<>" around their field names.
  28. //
  29. //   The ESC key exits back to the opening file selection screen.
  30. //
  31. //   The Shift+F2 key will delete the current record
  32. //
  33. //   The browser is virtual meaning only room for 15 records at a time
  34. //   is needed.
  35. //
  36. //   Version 2.0 enhancements:
  37. // 
  38. //   Ability to edit by choosing the EDIT button or Alt+E on the main
  39. //   browse screen.  This will bring up a record zoom screen.  Within
  40. //   this screen, the normal find keys (next, previous, clear, save, etc.)
  41. //   work as expected.  The buttons below the screen can be used in place
  42. //   of the keys.  The ESC key exits back to the browse screen with the
  43. //   current record displayed at the top of the list.
  44. //
  45. //   Version 2.1 enhancements:
  46. //
  47. //   Modified choose_file to work with new FILELIST.PKG
  48. //   PgUp used to stop on second record at top of file rather
  49. //   than first record. Fixed this.
  50. //   Changed MAX_LINES to 1 instead of 0 to comply with new translation.
  51. //
  52. //   Version 2.2 enhancements:
  53. //
  54. //   Added the Erase a file option to the first screen.
  55. //   Added help buttons and help keys
  56. //
  57. //   Changed version 2.2 to 2.21 to indicate use of 3.01 packages.
  58. //
  59. //   I welcome suggestions as well as modifications via CompuServe
  60. //   in the DACCESS forum.  Mail ID: 76702,1257
  61.  
  62. use UI
  63. set Application_Name to "SYSTEM"
  64. use FILELIST
  65. use ENTERR
  66. use HELP
  67.  
  68. number initial_argument_size
  69. get_argument_size to initial_argument_size
  70. set_argument_size 3000
  71. /background
  72. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░_____________________░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  73. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  74. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  75. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ░░░
  76. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ░░░
  77. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ░░░
  78. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ░░░
  79. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ░░░
  80. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ░░░
  81. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ░░░
  82. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ░░░
  83. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ░░░
  84. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ░░░
  85. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ░░░
  86. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ░░░
  87. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ░░░
  88. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ░░░
  89. ░░                                                                           ░░░
  90. ░░░_____________________░░________________░░_______________░░_____________░░░░░░
  91. ░░░░░░_________________░░░░ ____________ ░░░░______________░░_______________░░░░
  92. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░_________░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  93. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  94. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  95. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  96. /back2
  97. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░_____________________░░░░░░░░░░░░░░░░░░░░░░░░░░░
  98. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  99. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  100. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  ░░░░░░░░░
  101. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  ░░░░░░░░░
  102. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  ░░░░░░░░░
  103. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  ░░░░░░░░░
  104. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  ░░░░░░░░░
  105. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  ░░░░░░░░░
  106. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  ░░░░░░░░░
  107. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  ░░░░░░░░░
  108. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  ░░░░░░░░░
  109. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  ░░░░░░░░░
  110. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  ░░░░░░░░░
  111. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  ░░░░░░░░░
  112. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  ░░░░░░░░░
  113. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  ░░░░░░░░░
  114. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  ░░░░░░░░░
  115. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  ░░░░░░░░░
  116. ░░░░░░░░░░░░░░                                                         ░░░░░░░░░
  117. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  118. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  119. ░░░░_____________________░░_______________________░░____________░░_________░░░░░
  120. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  121. /Choose_File
  122. ╔═══════════════════════════════════════════════════════╗
  123. ║  Choose a File to BROWSE:                             ║
  124. ║                                                       ║
  125. ║     ________________________________________          ║
  126. ║     ________________________________________          ║
  127. ║     ________________________________________          ║
  128. ║     ________________________________________          ║
  129. ║     ________________________________________          ║
  130. ║     ________________________________________          ║
  131. ║     ________________________________________          ║
  132. ║     ________________________________________          ║
  133. ║     ________________________________________          ║
  134. ║     ________________________________________          ║
  135. ║                                                       ║
  136. ║                                                       ║
  137. ║                                                       ║
  138. ╚═══════════════════════════════════════════════════════╝
  139. /Enter_Rootname
  140. ╔═══════════════════════════════════════════════════════╗
  141. ║  Enter the rootname of a file to browse:              ║
  142. ║                                                       ║
  143. ║     ________________________________________          ║
  144. ║                                                       ║
  145. ║                                                       ║
  146. ║                                                       ║
  147. ╚═══════════════════════════════════════════════════════╝
  148. /Working
  149. ┌──────────────────────────────────────────────────────┐
  150. │                                                      │
  151. │    Reading File Information ... Please Wait ...      │
  152. │                                                      │
  153. └──────────────────────────────────────────────────────┘
  154. /Err_Object
  155. ┌──────────────────────────────────────────────────────┐
  156. │                                                      │
  157. │ ____________________________________________________ │
  158. │                       <__>                           │
  159. └──────────────────────────────────────────────────────┘
  160. /our_status      
  161. ┌─┤ Current Field ├──────────────────────────────────────────────────┐
  162. │Field #: __. Name: _________________ Length: ____.   Main Index: _. │
  163. └────────────────────────────────────────────────────────────────────┘
  164. /Record_Buttons
  165. ░░░_________░_________________░░_________░░____________░________░__________░░░░░
  166. ░░░░░░░░░░░░░░░░░░░░░_______________░░____________░░_________░░░░░░░░░░░░░░░░░░░
  167. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  168. /Record_Title
  169. ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ Record Edit ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  170. /Record_Divider
  171. /*
  172. string Which_File File_Root next_tag
  173. integer data_type main_index lvar100 last_field real_field
  174. integer File_Number current_position current_field field_length lvar dlast_record
  175. integer which_index max_length
  176. integer top_recnum bottom_recnum total_records
  177. indicator bad 
  178.  
  179. indicate in_scroll false
  180. #REPLACE EDIT_LENGTH 15
  181.  
  182. /record_numbers
  183. _____.
  184. /*
  185.  
  186. procedure exit_application for desktop
  187.    set_argument_size initial_argument_size
  188.    abort
  189. end_procedure
  190.  
  191. // We use OPEN AS so we need to include the .FD since the fields in the
  192. // file are referenced before the OPEN command.
  193.  
  194. #include flexerrs.fd
  195.  
  196. sub_page edit_buttons from background  2 3 4 5 6 7 8 9 10
  197. sub_page file_buttons from back2 2 3 4 5
  198.  
  199. register_object Field_Data
  200. register_object Record_Edit
  201.  
  202. // See the bottom of the program for a description of these arrays
  203.  
  204. object Record_Numbers is a LIST
  205. end_object
  206.  
  207. object Field_locator is an EDIT
  208.    set size to 1 3000
  209.    set INSERT_MODE to TRUE
  210. end_object
  211.  
  212. object Field_Numbers is an ARRAY
  213. end_object
  214.  
  215. object Field_Names is an ARRAY
  216. end_object
  217.  
  218. object Field_Start is an ARRAY
  219. end_object
  220.  
  221. object Field_End is an ARRAY
  222. end_object
  223.  
  224. object Field_Main_Index is an ARRAY
  225. end_object
  226.  
  227. object Real_Size is an ARRAY
  228. end_object
  229.  
  230. // Background image. We need to activate it but then don't want it to be
  231. // clicked on so we change its focus mode after it has been activated and
  232. // back again once deactivated.
  233.  
  234. object back2 is a message
  235.    set LOCATION to 0 0 ABSOLUTE
  236.    set object_color to 31 27
  237.    
  238.    procedure activating
  239.       set focus_mode to nonfocusable
  240.    end_procedure
  241.    
  242.    procedure deactivating
  243.       set focus_mode to focusable
  244.    end_procedure
  245.    
  246. end_object
  247.  
  248.  
  249. // Background image. We need to activate it but then don't want it to be
  250. // clicked on so we change its focus mode after it has been activated and
  251. // back again once deactivated.
  252.  
  253. object background is a message
  254.    set LOCATION to 0 0 ABSOLUTE
  255.    
  256.    procedure activating
  257.       set focus_mode to pointer_only
  258.    end_procedure
  259.    
  260.    procedure deactivating
  261.       set focus_mode to focusable
  262.    end_procedure
  263. end_object
  264.  
  265.  
  266. // Our status object which displays current file.field info. It also must
  267. // be "fooled" into being activated and then set nonfocusable.
  268.  
  269. object our_status is a message
  270.    set LOCATION to 21 5 ABSOLUTE
  271.    
  272.    set object_color to 62 48 
  273.       
  274.    procedure activating
  275.      set focus_mode to nonfocusable
  276.    end_procedure
  277.    
  278.    procedure deactivating
  279.       set focus_mode to focusable
  280.    end_procedure
  281. end_object
  282.  
  283. // A global procedure which updates our entire status object
  284.  
  285. procedure status_line
  286.    local integer current_fld current_y current_x current_record
  287.    move (hi(position(Field_Data(Desktop)))) to current_y
  288.    if current_y lt 1 move 0 to current_record
  289.    else move (value(Record_Numbers.obj,current_y )) to current_record
  290.    move (ascii(mid(value(Field_Locator.obj,current),1,low(position(Field_Data(Desktop))) + 1))) to current_fld
  291.    if ( current_fld eq last_field and Current_Record eq dlast_record) procedure_return
  292.    move current_fld to last_field
  293.    move current_Record to dlast_record
  294.    set value of our_status item 0 to (Integer_Value(Field_Numbers.obj,current_fld))
  295.    set value of our_status item 1 to (string_value(field_names.obj,current_fld))
  296.    set value of our_status item 2 to (integer_value(Field_End.obj,current_fld) - integer(value(Field_Start.obj,current_fld) + 1))
  297.    set value of our_status item 3 to (integer_value(Field_Main_Index.obj,current_fld))
  298.    send paint to our_status
  299. end_procedure
  300.  
  301. procedure status_line2
  302.    local integer current_fld current_y
  303.    move (hi(position(Record_Edit(desktop))) + 1) to current_fld
  304.    set value of our_status item 0 to (Integer_Value(Field_Numbers.obj,current_fld))
  305.    set value of our_status item 1 to (string_value(field_names.obj,current_fld))
  306.    set value of our_status item 2 to (integer_value(Field_End.obj,current_fld) - integer(value(Field_Start.obj,current_fld) + 1))
  307.    set value of our_status item 3 to (integer_value(Field_Main_Index.obj,current_fld))
  308.    send paint to our_status
  309. end_procedure  
  310.  
  311. // Some general status messages.
  312.  
  313.  
  314. object Working is a MESSAGE 
  315.    set object_color to 30 30
  316.    set LOCATION to 7 12 ABSOLUTE
  317. end_object
  318.  
  319.  
  320.  
  321. sub_page err_button from err_object 2
  322.  
  323. object err_object is a CLIENT
  324.    set RING_STATE to TRUE
  325.    
  326.    set CENTER_STATE of current_object item 0 to TRUE
  327.    set object_color to 79 79
  328.    set LOCATION to 7 12 ABSOLUTE
  329.    
  330.    procedure show_error string val
  331.       set value of current_object item 0 to val   
  332.       ui_accept current_object to windowindex
  333.    end_procedure
  334.    
  335.    object err_button is a button err_button
  336.       item_list
  337.          on_item "OK" send stop_ui
  338.       end_item_list
  339.    end_object // Err_Button
  340. end_object // Err_object
  341.  
  342. /Verify_Image
  343. ╔══════════════════════════════╗
  344. ║ ____________________________ ║
  345. ║ ┌──────────────────────────┐ ║
  346. ║ │  <__>   <______>         │ ║
  347. ║ └──────────────────────────┘ ║
  348. ╚══════════════════════════════╝
  349. /*
  350.  
  351.   Sub_Page Ok_Cancel_Prompt FROM Verify_Image 2 3
  352.  
  353.  
  354.   object Verify_It is a CLIENT Verify_Image
  355.  
  356.      set LOCATION to 7 25 ABSOLUTE
  357.      set object_color to 79 79
  358.      set CENTER_STATE of current_object item 0 to TRUE
  359.      
  360.      // Define this object (and its children) as a separate, popped up
  361.      // object with an entirely different scope. This will automatically
  362.      // turn off the mouse when in this object (you cannot click on other
  363.      // objects) and it will not send the Exit and Entry messages when this
  364.      // object is activated.
  365.      
  366.      set SCOPE_STATE to TRUE
  367.      set POPUP_STATE to TRUE
  368.      
  369.      object Ask_Ok is a button Ok_Cancel_Prompt
  370.  
  371.         item_list
  372.             On_Item "OK"     SEND Ok
  373.             On_Item "CANCEL" SEND Cancel
  374.         end_item_list
  375.      
  376.      End_Object // Ask_Ok
  377.         
  378.      function Validate_Ok string Description returns integer
  379.         local integer Return_Val
  380.         set VALUE of Verify_It item 0 to Description
  381.         ui_accept Verify_It object to Return_Val
  382.         function_return Return_Val
  383.      end_function
  384.  
  385.   End_Object // Verify_It
  386. // This object is used to allow the user to choose a file to browse.
  387.  
  388. object Enter_Rootname is a form
  389.    set object_color to 121 30
  390.    set LOCATION to 6 12 ABSOLUTE
  391.  
  392.    on_key KCANCEL send stop_ui
  393.    
  394.    procedure activating
  395.       move "" to which_file
  396.       move "" to file_root
  397.    end_procedure
  398.    
  399.    procedure chose_it
  400.       get value of current_object item 0 to which_file
  401.       move which_file to file_root
  402.       send stop_ui
  403.    end_procedure
  404.    
  405.    item_list
  406.       on_item "" send chose_it
  407.    end_item_list
  408. end_object
  409.  
  410. object Choose_File is a FILE_LIST Choose_File FOR Which_File
  411.    
  412.    
  413.    on_key KCANCEL send exit_application
  414.    on_key KEXIT_FUNCTION send exit_application
  415.    set LOCATION to 2 12 ABSOLUTE
  416.    set object_color to 121 48
  417.    set SELECT_MODE to SINGLE_SELECT
  418.    on_key KPROMPT send open_by_rootname
  419.    on_key KEY_ALT+KEY_E send erase_data_file
  420.     
  421.    procedure open_by_rootname
  422.       ui_accept enter_rootname to windowindex
  423.       if which_file ne "" send stop_ui
  424.    end_procedure
  425.    
  426.    procedure erase_Data_file
  427.       if (validate_ok(verify_it.obj,"Erase ALL data in this file?")) ne msg_ok procedure_return
  428.       get aux_value to File_Number
  429.       Filelist File_Number to File_Root
  430.       filelist PATHNAME to Which_File File_Root
  431.       move Which_File to File_Root
  432.       send Activate to Working
  433.  
  434.       // Try to open our file. We trap the "CAN'T OPEN DATA FILE ERROR" in our
  435.       // on error routine in BAD_OPEN and have that routine set the BAD
  436.       // indicator to TRUE. In this way, no error appears at the bottom but
  437.       // our program knows about the error and can recover.
  438.  
  439.       indicate bad false
  440.       on error gosub bad_open
  441.       open file_root as Flexerrs
  442.       on error off
  443.  
  444.       // If it was a bad open, put up the "Bad open" message and restart
  445.       [bad] begin
  446.          send deactivate to working
  447.          send show_error to err_object "The chosen file cannot be opened."
  448.          procedure_return
  449.       end
  450.       zerofile flexerrs
  451.       close flexerrs
  452.       send deactivate to working
  453.       send show_error to err_object "All data has been erased."
  454.    end_procedure
  455.       
  456.    procedure OK
  457.       // We set the global variable File_Root to the name of the
  458.       // file and the global Which_File to the file's filenumber upon
  459.       // exiting.
  460.     
  461.       get aux_value to File_Number
  462.       Filelist File_Number to File_Root
  463.       filelist PATHNAME to Which_File File_Root
  464.       move Which_File to File_Root
  465.       send stop_ui
  466.    end_procedure
  467.  
  468.    // The FILE_LIST class is set-up to move the currently selected
  469.    // piece of data back to the previously focused object (for a
  470.    // pop-up action). We don't want this so we dummy out the procedure
  471.    // in FILE_LIST which does this.
  472.    
  473.    procedure move_value_out
  474.    end_procedure
  475.    
  476. end_object
  477.  
  478. // The button object for our File_List object. 
  479.  
  480. object file_buttons is a button
  481.    set focus_mode to POINTER_ONLY
  482.    set object_color to 31 27
  483.  
  484.    item_list
  485.       on_item "<F4=Open by Rootname>" send open_by_rootname to choose_file
  486.       on_item "<Alt+E=Erase data file>" send erase_data_file to choose_file
  487.       on_item "<ESC=Cancel>" send exit_application
  488.       on_item "<F1=Help>" send help
  489.    end_item_list
  490. end_object
  491.  
  492.  
  493.  
  494. // The edit object that holds the names of our fields (the .TAG data).
  495.  
  496. object Tags is an Edit
  497.    set location to 1 1
  498.    set SIZE to 1 74
  499.    set RIGHT_MARGIN to 3000
  500.    set object_color to 62 62
  501.    set READ_ONLY_STATE to TRUE
  502.    
  503.    procedure activating
  504.       set FOCUS_MODE to NONFOCUSABLE
  505.    end_procedure
  506.    
  507.    procedure deactivating
  508.       set FOCUS_MODE to FOCUSABLE
  509.    end_procedure
  510.    
  511. end_object
  512.  
  513. // The object which holds our Field Data
  514.  
  515. object Field_Data is an Edit
  516.    set COLUMN_MODE to 2   
  517.    set object_color to 121 48
  518.    set location to 2 1
  519.    set SIZE to 15 74
  520.    set RIGHT_MARGIN to 3000
  521.    
  522.    on_key KCANCEL send stop_ui
  523.    
  524.    // Redefine the keys to send our own messages so we can synchronize the
  525.    // movement of the field data and the field names objects as well as
  526.    // keep the data scrolling correctly.
  527.    
  528.    on_key KRIGHTARROW send do_rightarrow
  529.    on_key KLEFTARROW send do_leftarrow
  530.    on_key KDOWNARROW send do_down
  531.    on_key KUPARROW send do_up
  532.    on_key KNEXT_ITEM send do_right_Field
  533.    on_key KPREVIOUS_ITEM send do_left_field
  534.    on_key KSCROLL_FORWARD send do_down
  535.    on_key KSCROLL_BACK send do_up
  536.    on_key KWORD_LEFT send do_left_field
  537.    on_key KWORD_RIGHT send do_right_field
  538.    on_key KBEGIN_OF_DATA send beginning_of_data
  539.    on_key KEND_OF_DATA send end_of_data
  540.    on_key KSCROLL_RIGHT send end_of_line
  541.    on_key KSCROLL_LEFT send beginning_of_line
  542.    on_key KBEGIN_OF_LINE send beginning_of_line 
  543.    on_key KEND_OF_LINE send end_of_line 
  544.    on_key KEY_ALT+KEY_R send do_reorder
  545.    on_key KEY_ALT+KEY_E send do_edit
  546.    on_key KSCROLL_BACK send do_page_up
  547.    on_key KSCROLL_FORWARD send do_page_down
  548.    on_key KDELETE_RECORD send do_delete
  549.    
  550.    // Our scroll bar is going to keep both arrows on at all times.
  551.    // Since our edit object never gets fuller than a page, the normal
  552.    // scroll bar would never have scroll-up and scroll-down arrows lit.
  553.       
  554.    object New_Scroll_Bar is a ScrollB
  555.       Procedure set arrows integer ua integer da
  556.         local integer int 
  557.         forward set arrows 1 1 int
  558.         procedure_return int
  559.       End_procedure
  560.    end_object
  561.    
  562.    set ScrollBar to (New_Scroll_Bar(Current_Object))
  563.  
  564.    // Override the standard scroll message to scroll a line at a time
  565.    // rather than a whole page.
  566.    
  567.    procedure scroll integer dir integer dist
  568.       if dir eq 0 send do_up
  569.       else send do_down
  570.    end_procedure   
  571.  
  572.    procedure do_delete
  573.       local integer current_y current_record
  574.       if (validate_ok(verify_it.obj,"Delete this record?")) ne msg_ok procedure_return
  575.       move (hi(position(Field_Data(Desktop)))) to current_y
  576.       if current_y lt 0 move 0 to current_record
  577.       else move (value(Record_Numbers.obj,current_y )) to current_record
  578.    
  579.       clear flexerrs
  580.       move current_record to flexerrs.recnum
  581.       find eq flexerrs.recnum
  582.       delete flexerrs
  583.       clear flexerrs
  584.       move top_recnum to flexerrs.recnum
  585.       find ge flexerrs.recnum
  586.       send fill_with_records to current_object 0
  587.    end_procedure
  588.    
  589.    procedure do_edit
  590.       local integer dum1 current_record current_y
  591.       send delete_Data to Record_Edit
  592.       move (hi(position(Field_Data(Desktop)))) to current_y
  593.       if current_y lt 0 move 0 to current_record
  594.       else move (value(Record_Numbers.obj,current_y )) to current_record
  595.       clear flexerrs
  596.       move current_record to flexerrs.recnum
  597.       find eq flexerrs.recnum
  598.       for dum1 from 1 to current_field
  599.          move (Integer_Value(Field_Numbers.obj,dum1)) to fieldindex
  600.          set value of Record_Edit item (dum1 - 1) to flexerrs.recnum&
  601.       loop
  602.       send Beginning_of_Data to Record_Tags
  603.       send Beginning_of_Data to Record_Edit
  604.       
  605.       send activate to Record_Title 
  606.       send activate to Record_Divider
  607.       send activate to Record_Buttons
  608.       send activate to Record_Tags
  609.       send activate to Record_Edit
  610.       send synchronize to Field_Edit
  611.       
  612.    end_procedure
  613.          
  614.    // Move the user to the field to his right. We can check the
  615.    // value of current_field to see which field we are in and then
  616.    // use the Field_End and Field_Start arrays to perform the moving.
  617.    // We use the MOVE_ABSOLUTE message to shift our field data and
  618.    // field tag edit objects.
  619.    
  620.    procedure do_right_field
  621.  
  622.       if last_field ge current_field procedure_return
  623.       send move_absolute to current_object (hi(position(current_object))) (Integer_Value(Field_End.obj,last_field + 1)  )
  624.       send move_absolute to tags 0 (Integer_Value(Field_End.obj,last_field + 1)  )
  625.       send move_absolute to current_object (hi(position(current_object))) (Integer_Value(Field_Start.obj,last_field + 1)  )
  626.       send move_absolute to tags 0 (Integer_Value(Field_Start.obj,last_field + 1)  )
  627.       send status_line
  628.     end_procedure
  629.     
  630.    
  631.    // Move the user to the field to his left. We can check the
  632.    // value of current_field to see which field we are in and then
  633.    // use the Field_End and Field_Start arrays to perform the moving.
  634.    // We use the MOVE_ABSOLUTE message to shift our field data and
  635.    // field tag edit objects.
  636.    
  637.    procedure do_left_field
  638.       if last_field lt 2 procedure_return
  639.       send move_absolute to current_object (hi(position(current_object))) (Integer_Value(Field_Start.obj,last_field - 1) )
  640.       send move_absolute to tags 0 (Integer_Value(Field_Start.obj,last_field - 1) )
  641.       send status_line
  642.     end_procedure
  643.    
  644.    // We mark the current line to show a line highlight so we need to
  645.    // insure that the user cannot unmark the line so we override the
  646.    // mouse_down message by sending a mouse_drag instead (which drags
  647.    // the mark instead of removing it).
  648.    
  649.    procedure mouse_down integer win integer position
  650.       send mouse_drag win position
  651.       send status_line
  652.    end_procedure
  653.    
  654.    procedure mouse_up integer win integer position
  655.       forward send mouse_up win position
  656.       send status_line
  657.    end_procedure
  658.  
  659.    // The next couple of procedures are used to synchronize the two
  660.    // objects: TAGS and FIELD_DATA since they both need to always be
  661.    // positioned at the same place.
  662.    
  663.    procedure beginning_of_line
  664.       forward send beginning_of_line
  665.       send beginning_of_line to tags
  666.       send status_line
  667.    end_procedure
  668.    
  669.    procedure end_of_line
  670.       forward send end_of_line
  671.       send end_of_line to tags
  672.       send status_line
  673.    end_procedure
  674.       
  675.    procedure beginning_of_Data
  676.       forward send beginning_of_data
  677.       send beginning_of_data to tags
  678.       send status_line
  679.    end_procedure
  680.    
  681.    procedure end_of_data
  682.       forward send end_of_Data
  683.       send end_of_data to tags
  684.       send status_line
  685.    end_procedure
  686.    
  687.    procedure beginning_of_panel
  688.       forward send beginning_of_panel
  689.       send beginning_of_panel to tags
  690.       send status_line
  691.    end_procedure
  692.    
  693.    procedure end_of_panel
  694.       forward send end_of_panel
  695.       send end_of_panel to tags
  696.       send status_line
  697.    end_procedure
  698.    
  699.    // This procedure is called to fill the Field_Data object with the
  700.    // first set of records.
  701.    
  702.    procedure fill_with_records integer clear_or_not
  703.       local integer loop_var
  704.       local integer loop_var2
  705.       local string total_line
  706.       // Do our updating with Dynamic_Update_State FALSE so we don't
  707.       // see stuff flying around until we set it back to TRUE.
  708.       
  709.       set dynamic_update_state to FALSE
  710.       send delete_Data
  711.       
  712.       // We are using OPEN AS on Flexerrs to address our file.
  713.       if clear_or_not eq 1 clear flexerrs
  714.      
  715.       send delete_Data to record_numbers
  716.       
  717.       for loop_var from 1 to EDIT_LENGTH
  718.          if loop_var ne 1 vfind 50 which_index 4
  719.          else vfind 50 which_index 3
  720.          [not found] begin
  721.             decrement loop_var
  722.             goto skip$55
  723.          end
  724.          if loop_var eq 1 move flexerrs.recnum to top_recnum
  725.          send add_item to record_numbers MSG_NONE flexerrs.recnum
  726.          set READ_ONLY_STATE to FALSE
  727.          
  728.          // Fill in the data from the file onto the edit object, placing
  729.          // a vertical bar between each field.
  730.          move "" to total_line
  731.          for loop_var2 from 1 to current_field
  732.             move (Integer_Value(Field_Numbers.obj,loop_var2)) to fieldindex
  733.             append total_line (pad(flexerrs.recnum&,integer_value(field_end.obj,loop_var2) - integer_value(Field_Start.obj,loop_Var2) - 1)) "│"
  734.          loop
  735.          set value of current_object item (loop_var - 1) to total_line
  736.       loop
  737.  
  738.       // I know it's a label, so shoot me!      
  739.       skip$55:
  740.       move flexerrs.recnum to bottom_recnum
  741.       
  742.       // This will mark the current line (display it in the nice color
  743.       // you see).
  744.       send mark_off
  745.       send mark_on
  746.       send beginning_of_data
  747.       set dynamic_update_state to TRUE
  748.       send paint
  749.       
  750.       // Redisplay our status line
  751.       send status_line
  752.       
  753.       // Keep a count of how many records are on the screen
  754.       move loop_var to total_records
  755.       set READ_ONLY_STATE to TRUE
  756.    end_procedure
  757.    
  758.    procedure do_page_up
  759.       local integer our_loop current_y current_record
  760.       
  761.       move (hi(position(Field_Data(Desktop)))) to current_y
  762.       if current_y lt 0 move 0 to current_record
  763.       else move (value(Record_Numbers.obj,current_y )) to current_record
  764.       clear flexerrs
  765.       move current_record to flexerrs.recnum
  766.       find eq flexerrs.recnum
  767.       
  768.       for our_loop from 1 to EDIT_LENGTH
  769.          vfind 50 which_index 0
  770.          [not found] begin
  771.             send fill_with_records to current_object 0
  772.             procedure_return
  773.          end
  774.       loop
  775.       send fill_with_records to current_object 0
  776.    end_procedure
  777.    
  778.  
  779.    procedure do_page_down
  780.       local integer our_loop current_y current_record
  781.       
  782.       move (hi(position(Field_Data(Desktop)))) to current_y
  783.       if current_y lt 0 move 0 to current_record
  784.       else move (value(Record_Numbers.obj,current_y )) to current_record
  785.       clear flexerrs
  786.       move current_record to flexerrs.recnum
  787.       find eq flexerrs.recnum
  788.       
  789.       for our_loop from 1 to EDIT_LENGTH
  790.          vfind 50 which_index 4
  791.          [not found] begin
  792.             vfind 50 which_index 0
  793.             send fill_with_records to current_object 0
  794.             procedure_return
  795.          end
  796.       loop
  797.       send fill_with_records to current_object 0
  798.    end_procedure
  799.          
  800.    // We reorder by checking the main index of the current field and
  801.    // changing the WHICH_INDEX global variable which is used as the
  802.    // index in our VFIND commands.
  803.          
  804.    procedure do_Reorder
  805.       local integer which_position origin_of_us origin_of_him
  806.       local integer lvar99
  807.  
  808.       get origin to origin_of_us      
  809.       get origin of TAGS to origin_of_him
  810.       
  811.       move (low(position(current_object))) to which_position
  812.       
  813.       move (ascii(mid(value(Field_Locator.obj,current),1,which_position + 1))) to lvar99
  814.       
  815.       // If we are on a non-indexed field, inform the user.
  816.       if (((Integer_Value(Field_Main_Index.obj,lvar99)) lt 1) and (lvar99 ne 1)) begin
  817.          send show_error to err_object "You cannot reorder on a non-indexed field."
  818.          procedure_return
  819.       end
  820.          
  821.       move (Integer_Value(Field_Main_Index.obj,lvar99)) to which_index
  822.       set dynamic_update_state to FALSE
  823.       set dynamic_update_State of TAGS to FALSE
  824.       send fill_with_records to current_object 1
  825.       set origin to (hi(origin_of_us)) (low(origin_of_us))
  826.       set origin of TAGS to (hi(origin_of_him)) (low(origin_of_him))
  827.       send move_absolute 0 which_position
  828.       send move_absolute to TAGS 0 which_position
  829.       
  830.       set dynamic_update_state to TRUE
  831.       set dynamic_update_State of TAGS to TRUE
  832.       
  833.       send status_line
  834.                 
  835.      end_procedure
  836.      
  837.       
  838.    // Move right or left while synchronizing the TAGS object
  839.       
  840.    procedure do_rightarrow
  841.       if (low(position(current_object))) ge max_length procedure_return
  842.       forward send key KRIGHTARROW
  843.       send key to Tags KRIGHTARROW
  844.       send status_line
  845.    end_procedure
  846.    
  847.    procedure do_leftarrow
  848.       if (low(position(current_object))) lt 1 procedure_return
  849.       forward send key KLEFTARROW
  850.       send key to Tags KLEFTARROW
  851.       send status_line
  852.    end_procedure
  853.  
  854.    
  855.    // Up and down work their magic by inserting or deleting lines
  856.    // in the edit object from the file.
  857.    procedure do_down
  858.       local integer pos_y pos_x lvar2 loop_var2
  859.       local string temp_string
  860.       local string total_line
  861.       local integer origin_of_us origin_of_him
  862.          move (hi(position(current_object))) to pos_y
  863.          move (low(position(current_object))) to pos_x
  864.          if ((pos_y ne (EDIT_LENGTH - 1)) and (pos_y lt total_Records - 1)) begin
  865.             send mark_off
  866.             forward send down
  867.             send mark_on
  868.             procedure_return
  869.          end
  870.          clear flexerrs
  871.          move bottom_recnum to flexerrs.recnum
  872.          find eq flexerrs.recnum
  873.          
  874.          // Variable find using our file number, the index in
  875.          // which_index and mode 4 (GT)
  876.          vfind 50 which_index 4
  877.          [not found] procedure_return
  878.          get origin to origin_of_us      
  879.          get origin of TAGS to origin_of_him
  880.          set READ_ONLY_STATE to FALSE
  881.          send mark_off
  882.          move flexerrs.recnum to bottom_Recnum
  883.          clear flexerrs
  884.          move top_recnum to flexerrs.recnum
  885.          find eq flexerrs.recnum
  886.          vfind 50 which_index 4
  887.          move flexerrs.recnum to top_recnum
  888.          clear flexerrs
  889.          move bottom_recnum to flexerrs.recnum
  890.          find eq flexerrs.recnum
  891.          send delete_item to record_numbers 0
  892.          send add_item to record_numbers MSG_NONE flexerrs.recnum
  893.          set dynamic_update_state of current_object FALSE
  894.          set dynamic_update_state of TAGS FALSE
  895.          forward send Beginning_of_Data
  896.         
  897.          // Take out our old first record
  898.          send delete_line
  899.          forward send end_of_data
  900. //         send key KENTER
  901.          
  902.          // Fill in our latest record in the edit object
  903.          move "" to total_line
  904.          for loop_var2 from 1 to current_field
  905.             move (Integer_Value(Field_Numbers.obj,loop_var2)) to fieldindex
  906.             append total_line (pad(flexerrs.recnum&,integer_value(field_end.obj,loop_var2) - integer_value(Field_Start.obj,loop_Var2) - 1)) "│"
  907. //            send insert (pad(flexerrs.recnum&,integer_value(field_end.obj,loop_var2) - integer_value(Field_Start.obj,loop_Var2) - 1))
  908. //            send insert "│"
  909.          loop
  910.          set value of current_object item (line_count(current_object)) to total_line       
  911.          // Shift the display so we are exactly where we were before
  912.          // we moved.
  913.          
  914.          set origin to (hi(origin_of_us)) (low(origin_of_us))
  915.          set origin of TAGS to (hi(origin_of_him)) (low(origin_of_him))
  916.          send MOVE_ABSOLUTE to current_object (EDIT_LENGTH - 1) pos_x
  917.          send MOVE_ABSOLUTE to TAGS 0 pos_x
  918.          send mark_on
  919.          set dynamic_update_state of current_object TRUE
  920.          set dynamic_update_state of TAGS TRUE
  921.          send PAINT
  922.          set READ_ONLY_STATE to TRUE
  923.    end_procedure
  924.  
  925.    // See the DOWN procedure above. This is almost line for line
  926.    // identical.
  927.       
  928.    procedure do_up
  929.    
  930.       local integer pos_y pos_x lvar2 loop_var2
  931.       local string temp_string
  932.       local string total_line
  933.       local integer origin_of_us origin_of_him
  934.          move (hi(position(current_object))) to pos_y
  935.          move (low(position(current_object))) to pos_x
  936.          if pos_y ne 0 begin
  937.             send mark_off
  938.             forward send up
  939.             send mark_on
  940.             procedure_return
  941.          end
  942.          clear flexerrs
  943.          move top_recnum to flexerrs.recnum
  944.          find eq flexerrs.recnum
  945.          vfind 50 which_index 0
  946.          [not found] procedure_return
  947.          get origin to origin_of_us      
  948.          get origin of TAGS to origin_of_him
  949.          set READ_ONLY_STATE to FALSE
  950.          send mark_off
  951.          set INSERT_MODE TRUE
  952.          move flexerrs.recnum to top_Recnum
  953.          clear flexerrs
  954.          move bottom_recnum to flexerrs.recnum
  955.          find eq flexerrs.recnum
  956.          if (line_count(current_object)) ge EDIT_LENGTH begin
  957.             vfind 50 which_index 0
  958.             move flexerrs.recnum to bottom_recnum
  959.          end
  960.          clear flexerrs
  961.          move top_recnum to flexerrs.recnum
  962.          find eq flexerrs.recnum
  963.          
  964.          set dynamic_update_state of TAGS FALSE
  965.          set dynamic_update_state of current_object FALSE
  966.          if (line_count(current_object)) ge EDIT_LENGTH begin
  967.             forward send end_of_Data
  968.             send delete_line
  969.             send delete_item to record_numbers (EDIT_LENGTH - 1)
  970.          end
  971.          else increment total_records
  972.          forward send beginning_of_data
  973.          move "" to total_line
  974.          for loop_var2 from 1 to current_field
  975.             move (Integer_Value(Field_Numbers.obj,loop_var2)) to fieldindex
  976.             append total_line (pad(flexerrs.recnum&,integer_value(field_end.obj,loop_var2) - integer_value(Field_Start.obj,loop_Var2) - 1)) "│"
  977.          loop
  978.          send key KENTER
  979.          set value of current_object item 0 to total_line
  980.          send insert_item to  record_numbers MSG_NONE flexerrs.recnum 0  
  981.          set origin to (hi(origin_of_us)) (low(origin_of_us))
  982.          set origin of TAGS to (hi(origin_of_him)) (low(origin_of_him))
  983.          send MOVE_ABSOLUTE to current_object 0 pos_x
  984.          send MOVE_ABSOLUTE to TAGS 0 pos_x
  985.          send mark_on
  986.          set dynamic_update_state of current_object TRUE
  987.          set dynamic_update_state of TAGS TRUE
  988.          send PAINT
  989.          set INSERT_MODE FALSE
  990.          set READ_ONLY_STATE to TRUE
  991.    end_procedure
  992.    
  993. end_object
  994.  
  995. // Our button object that appears at the bottom of the data edit screen.
  996. // Allow the user to move field right and field left with the TAB and
  997. // Shift-Tab keys or by using the arrow buttons below.
  998.  
  999. object edit_buttons is a button
  1000.    set focus_mode to pointer_only
  1001.    set object_color to 31 27
  1002.    
  1003.    item_list
  1004.       on_item "<Shift+TAB=Left Fld>" send do_left_field to Field_Data
  1005.       on_item "<PgDn=Page Down>" send do_page_down to Field_Data
  1006.       on_item "<Alt+R=Reorder>" send do_reorder to Field_Data
  1007.       on_item "<Alt+E=Edit>" send do_edit to Field_Data
  1008.       on_item "<Shift+F2=Delete>" send do_delete to Field_Data
  1009.       on_item "<Esc=Cancel>" send stop_ui
  1010.       on_item "<PgUp=Page Up>" send do_page_up to Field_Data
  1011.       on_item "<TAB=Right Fld>" send do_right_field to Field_Data
  1012.       on_item "<F1=Help>" send Help
  1013.    end_item_list
  1014.    
  1015. end_object
  1016.  
  1017. object Record_Title is a MESSAGE
  1018.    set object_color to 31 27
  1019.    procedure activating
  1020.       set focus_mode to nonfocusable
  1021.    end_procedure
  1022.    
  1023.    procedure deactivating
  1024.       set focus_mode to focusable
  1025.    end_procedure
  1026.    
  1027.    set location to 1 1
  1028. end_object
  1029.  
  1030. object Record_Divider is a MESSAGE
  1031.   set location to 2 20
  1032.    set object_color to 31 27
  1033.    procedure activating
  1034.       set focus_mode to nonfocusable
  1035.    end_procedure
  1036.    
  1037.    procedure deactivating
  1038.       set focus_mode to focusable
  1039.    end_procedure
  1040. end_object
  1041.   
  1042.  
  1043. // Our Record_Tags object holds the tag names for our record editing
  1044. // section. Record_Tags and Record_Edit are side by side edit objects.
  1045. object Record_Tags is an EDIT
  1046.    set object_color to 62 62
  1047.    set COLUMN_MODE to 2   
  1048.    set location to 2 1
  1049.    set SIZE to 15 19
  1050.    set RIGHT_MARGIN to 18
  1051.    set scroll_bar_visible_state  to FALSE
  1052.    
  1053.    procedure activating
  1054.       set focus_mode to nonfocusable
  1055.    end_procedure
  1056.    
  1057.    procedure deactivating
  1058.       set focus_mode to focusable
  1059.    end_procedure
  1060.    
  1061. end_object
  1062.  
  1063.  
  1064.  
  1065. // Record_Edit is the edit object used to display the current field
  1066. // data from the current record.
  1067.  
  1068. object Record_Edit is an EDIT
  1069.    set location to 2 21
  1070.    set object_color to 47 100
  1071.    set SIZE to 15 54
  1072.    set RIGHT_MARGIN to 3000   
  1073.       
  1074.    procedure scroll integer dir integer dist
  1075.       if dir eq 0 send do_up to Field_Edit
  1076.       else send do_down to Field_Edit
  1077.    end_procedure   
  1078.    
  1079.    procedure mouse_down integer y integer x
  1080.       if y lt 0 procedure_return // In scroll bar
  1081.       send unload to Field_Edit
  1082.       send move_absolute (y - 1) 0
  1083.       send move_absolute to Record_Tags (y - 1) 0
  1084.       send synchronize to Field_Edit
  1085.    end_procedure
  1086.    
  1087. end_object
  1088.  
  1089.  
  1090. object Record_Buttons is a BUTTON
  1091.    set location to 18 0
  1092.    set object_color to 31 27
  1093.    
  1094.    on_Key KCANCEL send do_cancel
  1095.    
  1096.    procedure activating
  1097.       set focus_mode to pointer_only
  1098.    end_procedure
  1099.    
  1100.    procedure deactivating
  1101.       set focus_mode to focusable
  1102.    end_procedure
  1103.    
  1104.    item_list
  1105.       on_item "<F2=Save>" send do_save_and_clear
  1106.       on_item "<Shift+F2=Delete>" send do_delete
  1107.       on_item "<F8=Next>" send do_find_next
  1108.       on_item "<F7=Previous>" send do_find_previous
  1109.       on_item "<F9=Find>" send do_find_eq
  1110.       on_item "<F5=Clear>" send do_clear
  1111.       on_item "<Alt+F2=Update>" send do_update
  1112.       on_item "<ESC=Cancel>" send do_cancel
  1113.       on_item "<F1=Help>" send Help
  1114.    end_item_list
  1115.  
  1116.    procedure do_find_next
  1117.       send do_find 1
  1118.    end_procedure
  1119.    
  1120.    procedure do_find_previous
  1121.       send do_find 2
  1122.    end_procedure
  1123.    
  1124.    procedure do_find_eq
  1125.       send do_find 3
  1126.    end_procedure
  1127.    
  1128.    procedure do_update
  1129.       send do_save to current_object 0
  1130.    end_procedure
  1131.    
  1132.    procedure do_save_and_clear
  1133.       send do_save to current_object 1
  1134.    end_procedure
  1135.    
  1136.    procedure do_save integer do_clear2
  1137.       local integer dum1
  1138.       send unload to Field_Edit
  1139.       reread
  1140.       for dum1 from 1 to current_field
  1141.          move (Integer_Value(Field_Numbers.obj,dum1)) to fieldindex
  1142.          move (Value(Record_Edit.obj,dum1 - 1)) to flexerrs.recnum&
  1143.       loop
  1144.       saverecord flexerrs   
  1145.       unlock
  1146.       if do_clear2 eq 1 send do_clear
  1147.    end_procedure
  1148.    
  1149.    procedure do_delete
  1150.       if not status flexerrs begin
  1151.          send show_error to err_object "No record in memory to delete."
  1152.          procedure_return
  1153.       end
  1154.       
  1155.       if (validate_ok(verify_it.obj,"Delete this record?")) ne msg_ok procedure_return
  1156.       delete flexerrs
  1157.       send do_clear
  1158.    end_procedure
  1159.  
  1160.    procedure do_clear
  1161.       local integer dum1
  1162.       clear flexerrs
  1163.       set dynamic_update_state of Record_Edit to FALSE
  1164.       send delete_data to Record_Edit
  1165.       for dum1 from 1 to current_field
  1166.          move (Integer_Value(Field_Numbers.obj,dum1)) to fieldindex
  1167.          set value of Record_Edit item (dum1 - 1) to flexerrs.recnum&
  1168.          if dum1 ne current_Field send key to Record_Edit KENTER
  1169.       loop
  1170.       send Beginning_of_Data to Record_Tags
  1171.       send Beginning_of_Data to Record_Edit
  1172.       set dynamic_update_State of Record_Edit to TRUE
  1173.       send synchronize to Field_Edit
  1174.    end_procedure
  1175.    
  1176.    procedure do_find integer which_mode
  1177.       local integer dum1 our_field old_origin
  1178.       
  1179.       move (hi(position(Record_Edit.obj)) + 1) to our_field
  1180.       if (((integer_value(Field_Main_Index.obj,our_field)) lt 1) and (our_Field ne 1)) begin
  1181.          send show_error to err_object "You cannot find by a non-indexed field."
  1182.          procedure_return
  1183.       end
  1184.  
  1185.       send unload to Field_Edit
  1186.       get origin of Record_Edit to old_origin
  1187.       move 0 to flexerrs.recnum
  1188.       
  1189.       for dum1 from 1 to current_field
  1190.          move (Integer_Value(Field_Numbers.obj,dum1)) to fieldindex
  1191.          move (Value(Record_Edit.obj,dum1 - 1)) to flexerrs.recnum&
  1192.       loop
  1193.       move (Integer_Value(Field_Numbers.obj,our_field)) to fieldindex
  1194.       if which_mode eq 1 find gt flexerrs.recnum&
  1195.       if which_mode eq 2 find lt flexerrs.recnum&
  1196.       if which_mode eq 3 find ge flexerrs.recnum&
  1197.       
  1198.       set dynamic_update_state of Record_Edit to FALSE
  1199.       send delete_data to Record_Edit
  1200.       for dum1 from 1 to current_field
  1201.          move (Integer_Value(Field_Numbers.obj,dum1)) to fieldindex
  1202.          set value of Record_Edit item (dum1 - 1) to flexerrs.recnum&
  1203.       loop
  1204.       send Beginning_of_Data to Record_Edit
  1205.       set Origin of Record_Edit to (hi(old_origin))  (low(old_origin))
  1206.       send move_absolute to Record_Edit (our_field - 1) 0
  1207.       set dynamic_update_State of Record_Edit to TRUE
  1208.       send synchronize to Field_Edit
  1209.    end_procedure
  1210.    
  1211.    procedure do_cancel
  1212.       send deactivate to Record_Divider
  1213.       send deactivate to Record_Title
  1214.       send deactivate
  1215.       send deactivate to Record_Tags
  1216.       send deactivate to Record_Edit
  1217.       send deactivate to Field_Edit
  1218.       if status flexerrs send fill_with_records to Field_Data 0
  1219.       else send fill_with_records to Field_Data 1
  1220.    end_procedure
  1221. end_object
  1222.  
  1223.  
  1224. object Field_Edit is an EDIT
  1225.    set SCOPE_STATE to TRUE
  1226.    set MAX_LINES to 1
  1227.    
  1228.    set object_Color to 110 111
  1229.  
  1230.    on_key KDOWNARROW send do_down
  1231.    on_key KUPARROW send do_up
  1232.    on_key KCANCEL send do_Cancel to Record_Buttons
  1233.    on_key KENTER send do_down
  1234.    on_key KFIND_NEXT send do_find_next to Record_Buttons
  1235.    on_key KFIND_PREVIOUS send do_find_previous to Record_Buttons
  1236.    on_key KFIND send do_find_eq to Record_Buttons
  1237.    on_key KCLEAR send do_clear to Record_Buttons
  1238.    on_key KSAVE_RECORD send do_save_and_Clear to Record_Buttons
  1239.    on_key KDELETE_RECORD send do_Delete to Record_Buttons
  1240.    on_key KEY_ALT+KEY_F2 send do_update to Record_Buttons
  1241.     
  1242.    procedure switch
  1243.    end_procedure
  1244.    
  1245.    procedure switch_back
  1246.    end_procedure
  1247.    
  1248.    procedure do_down
  1249.       if (hi(position(Record_Edit.obj)) +1) ge current_Field procedure_return
  1250.       send unload
  1251.       send DOWN to Record_Edit 
  1252.       send DOWN to Record_Tags
  1253.       send synchronize
  1254.    end_procedure
  1255.    
  1256.    procedure do_up                      
  1257.       if (hi(position(Record_Edit.obj))) lt 1 begin
  1258.          if (hi(origin(Record_Edit.obj))) le 0  procedure_return
  1259.       end
  1260.       send unload
  1261.       send UP to Record_Edit
  1262.       send UP to Record_Tags
  1263.       send synchronize
  1264.    end_procedure
  1265.       
  1266.    procedure synchronize
  1267.       local integer tot_chars
  1268.       send deactivate
  1269.       send delete_data
  1270.       move (Integer_Value(Real_Size.obj,hi(position(Record_Edit.obj)) + 1)) to tot_chars
  1271.       if (tot_chars + 1) gt 54 set size to 1 54
  1272.       else set size to 1 (tot_chars + 1)
  1273.       set right_margin to (tot_chars + 1)
  1274.       set value of current_object item 0 to (value(Record_Edit.obj,current))
  1275.       send beginning_of_data
  1276.       set location to ( hi(position(Record_Edit.obj)) - hi(origin(Record_Edit.obj)) + hi(location(Record_Edit.obj))) (low(location(Record_Edit.obj)))
  1277.       send activate
  1278.       send status_line2
  1279.    end_procedure
  1280.    
  1281.    procedure unload
  1282.       string total_line
  1283.       move (Value(Field_Edit.obj,current)) to total_line
  1284.       set value of Record_Edit item (hi(position(Record_Edit.obj))) to (pad(total_line,integer_value(Real_Size.obj,hi(position(Record_Edit.obj)) + 1)))
  1285.       send beginning_of_line to Record_Edit
  1286.       send paint to Record_Edit
  1287.       
  1288.    end_procedure
  1289.    
  1290. end_object
  1291.  
  1292.  
  1293. // Fill in the program title
  1294.    
  1295. set value of back2 item 0 to "DFBROWSE Version 2.21"
  1296.  
  1297. // Wow, another label!
  1298. again:
  1299. // This section of code initialize all of our objects so that we can
  1300. // restart and browse another file.
  1301.  
  1302. send delete_data to record_numbers
  1303. send delete_Data to field_locator
  1304. send delete_data to field_names
  1305. send delete_Data to field_main_index
  1306. send delete_Data to field_Start
  1307. send delete_data to field_end
  1308. send delete_Data to field_numbers
  1309. send delete_Data to tags
  1310.  
  1311. // Put up our background and then allow the user to choose a file
  1312. send activate to back2
  1313. send add_focus to file_buttons DESKTOP
  1314. start_ui Choose_File
  1315.  
  1316. // Put up the "Working ... Please wait" message while we open the
  1317. // file and determine its fields and data types.
  1318.  
  1319. send Activate to Working
  1320.  
  1321. // Try to open our file. We trap the "CAN'T OPEN DATA FILE ERROR" in our
  1322. // on error routine in BAD_OPEN and have that routine set the BAD
  1323. // indicator to TRUE. In this way, no error appears at the bottom but
  1324. // our program knows about the error and can recover.
  1325.  
  1326. indicate bad false
  1327. on error gosub bad_open
  1328. open file_root as Flexerrs
  1329. on error off
  1330.  
  1331. // If it was a bad open, put up the "Bad open" message and restart
  1332. [bad] begin
  1333.    send deactivate to working
  1334.    send show_error to err_object "The chosen file cannot be opened."
  1335.    goto again
  1336. end
  1337.  
  1338. // Now that the file is opened, open the .TAG and start reading in the
  1339. // field names
  1340.  
  1341. direct_input (File_Root + ".TAG")
  1342.  
  1343. // If the .TAG does not exist, put up the "Bad TAG file open" message and
  1344. // restart.
  1345.  
  1346. [seqeof] begin
  1347.    close flexerrs
  1348.    send deactivate to Working
  1349.    send show_error to err_object "The .TAG file for your file cannot be found."
  1350.    goto again
  1351. end
  1352.  
  1353. // We use a few arrays to keep track of the file information:
  1354. //    Field_Names is the array of field names
  1355. //    Field_Main_Index is the array of field main indexes
  1356. //    Field_Start is the array of field starting positions in the edit object
  1357. //    Field_End is the array of field ending positions in the edit object
  1358. //    Field_Locator is bizarre: Read on ...
  1359. //       Field Locator is an edit object that is used to store the 
  1360. //          corresponding field number for a particular location in the edit
  1361. //          object.  For example, if we wanted to know what field was at
  1362. //          position 50 in the edit object, we would look at the 50th 
  1363. //          character in field_locator.  That character contains a single
  1364. //          ASCII Character whose ASCII Value is the field at that location.
  1365. //          For example, if position 50 was for field 10, then the ASCII
  1366. //          value of the 50th character in field_locator would be 10.
  1367. //          We use this when updating the status object and when moving left
  1368. //          and right from field to field (jumping from field to field with
  1369. //          the TAB keys).  We did it this way to save space. This will at
  1370. //          most require 16K (the maximum record length).  I told you this
  1371. //          was bizarre!
  1372.  
  1373. // Initialize starting values
  1374. move 9 to current_position
  1375. move 2 to current_Field
  1376. move 1 to real_field
  1377. send delete_Data to Field_Locator
  1378. send delete_Data to Record_Tags
  1379. send delete_Data to Real_Size
  1380.  
  1381. set Array_Value of Field_Numbers item 1 to 0      
  1382. set Array_Value of Field_Main_Index item 1 to 0
  1383. set Array_Value of Field_Names item 1 to "<RECNUM>"
  1384. set Array_Value of Field_Start item 1 to 0
  1385. set Array_Value of Real_Size item 1 to 8
  1386. set Array_Value of Field_End item 1 to 9
  1387.  
  1388. // For each element in the TAG fill in the above arrays with information
  1389. // about that field.
  1390. send loadit
  1391. procedure loadit
  1392. local string total_string
  1393. move "" to total_string
  1394. for lvar100 from 0 to 8
  1395.    append total_string (character(1))
  1396. loop
  1397. repeat
  1398.    readln next_tag
  1399.    
  1400.    [seqeof] goto skip 
  1401.    
  1402.    if next_tag ne "" begin
  1403.       
  1404.       field_def 50 real_Field to data_type main_index
  1405.       
  1406.       if main_index gt 0 begin
  1407.          insert "<" in next_Tag at 0
  1408.          append next_Tag ">"
  1409.       end
  1410.       
  1411.       // Skip overlap fields
  1412.       if data_type eq 3 goto skip
  1413.       set Array_Value of Field_Numbers item current_field to real_field      
  1414.       set Array_Value of Field_Main_Index item current_field to main_index
  1415.       set Array_Value of Field_Names item current_field to next_tag
  1416.       set Array_Value of Field_Start item current_field to current_position
  1417.       
  1418.       // Determine the fields display length from its BYTE length. 
  1419.       // Remember, a numeric only needs 1/2 a BYTE for each displayed
  1420.       // character and don't forget the decimal!
  1421.       
  1422.       if data_type eq 1 move (strlen * 2 + 2) to field_length
  1423.       if data_type eq 2 move 10 to field_length
  1424.       if data_type eq 0 move strlen to field_length
  1425.       if data_Type eq 4 move strlen to field_length
  1426.       if data_type eq 5 move strlen to field_length
  1427.       if data_type eq 6 move strlen to field_length
  1428.       
  1429.       set Array_Value of Real_Size item current_field to field_length
  1430.       
  1431.       // If the .TAG entry is actually longer than the field length,
  1432.       // use the .TAG entry as the length of the field (STATE is 5
  1433.       // characters but the field may only be 2).
  1434.       
  1435.       if (length(next_Tag)) gt field_length move (length(next_Tag)) to field_length
  1436.       
  1437.       set Array_Value of Field_End item current_field to (Current_Position + field_length + 1 )
  1438.       if (current_position + field_length + 1) gt 3000 goto endit
  1439.       // Fill in the Field_Locator data (see above for a description
  1440.       // of this process)
  1441.       
  1442.       for lvar100 from (integer_value(Field_Start.obj,current_field)) to ((integer_value(Field_End.obj,current_field))  - 1)
  1443.          append total_string (character(current_field))
  1444. //         send insert to Field_Locator (character(current_Field))
  1445.       loop
  1446.       
  1447.       move (Current_Position + field_length + 1 ) to current_position
  1448.       move (current_Field + 1) to current_field
  1449.    end
  1450.    skip:
  1451.    increment real_field
  1452. until [seqeof]
  1453. endit:
  1454. // We actually incremented current_field before reading in the next field
  1455. // so we need to subtract 1 so that current_field points to maximum
  1456. // fields instead of next field.
  1457. move (Current_Field - 1) to current_field
  1458. append total_string (Character(Current_Field))
  1459. set value of field_locator to total_string
  1460. end_procedure
  1461.  
  1462. // Max_Length is a global which stores the maximum width of the file.
  1463. move current_position to max_length
  1464.  
  1465.  
  1466. // Fill in the TAGS object with the name of all of the tags along with
  1467. // a vertical bar separator.
  1468. for lvar from 1 to current_field
  1469.    send insert to Record_Tags (String_Value(Field_Names.obj,lvar))
  1470.    if lvar ne current_Field  send key to Record_Tags KENTER
  1471.    send insert to tags (pad(string_value(field_names.obj,lvar),integer_value(field_end.obj,lvar) - integer_value(Field_Start.obj,lvar) -1))
  1472.    send insert to tags "│"
  1473. loop
  1474.  
  1475. // Let's start this show ... 
  1476. send Beginning_Of_Data to tags
  1477. move 0 to which_index
  1478.  
  1479. move 0 to dlast_record
  1480.  
  1481. send Fill_With_Records to Field_Data 1
  1482. send deactivate to record_numbers
  1483.  
  1484. set value of background item 0 to "DFBROWSE Version 2.21"
  1485.  
  1486. // Remember to get rid of the object we used in the first part of the
  1487. // program.
  1488. send deactivate to Working
  1489. send deactivate to Choose_File
  1490. send deactivate to file_buttons
  1491. send deactivate to back2
  1492.  
  1493.  
  1494. send activate to background
  1495. send activate to our_status
  1496. send status_line
  1497. send add_focus to edit_buttons DESKTOP
  1498. send activate to tags
  1499.  
  1500. start_ui field_Data
  1501.  
  1502. // Get rid of the objects in the second part of the program.
  1503.  
  1504. send deactivate to field_Data
  1505. send deactivate to tags
  1506. send deactivate to edit_buttons
  1507. send deactivate to our_status
  1508. send deactivate to background
  1509.  
  1510. // Close our file since we are allowing the user to open a new one.
  1511. close flexerrs
  1512.  
  1513. goto again
  1514.  
  1515. bad_open:
  1516. indicate bad true
  1517. indicate err false
  1518. return
  1519.  
  1520.  
  1521.