home *** CD-ROM | disk | FTP | other *** search
/ Programmer's ROM - The Computer Language Library / programmersrom.iso / ada / forms / form2.src < prev    next >
Encoding:
Text File  |  1988-05-03  |  267.2 KB  |  8,391 lines

  1.  
  2. -------- SIMTEL20 Ada Software Repository Prologue ------------
  3. --                                                           -*
  4. -- Unit name    : User Interface Forms Generator
  5. -- Version      : 1.0
  6. -- Contact      : Lt. Colonel Falgiano
  7. --              : ESD/SCW
  8. --              : Hanscom AFB, MA  01731
  9. -- Author       : John Foreman
  10. --              : Texas Instruments, Inc.
  11. --              : P.O. Box 801 MS 8007
  12. --              : McKinney, TX  75069
  13. -- DDN Address  :
  14. -- Copyright    : (c) 1985 Texas Instruments, Inc.
  15. -- Date created : 10 November 1984
  16. -- Release date : 1 March 1985
  17. -- Last update  : 
  18. --                                                           -*
  19. ---------------------------------------------------------------
  20. --                                                           -*
  21. -- Keywords     : 
  22. ----------------:
  23. --
  24. -- Abstract     : This tool is used to seperate an application's
  25. ----------------: procedural code from the code required to 
  26. ----------------: drive a terminal.  The system will provide both
  27. ----------------: an interactive and batch interface that enables
  28. ----------------: an application programmer to design a screen
  29. ----------------: format and save the representation in a machine 
  30. ----------------: readable form.  The Form Executor package will
  31. ----------------: provide procedural and functional interfaces
  32. ----------------: that enable a program to access the output of 
  33. ----------------: the system and present it to a terminal.  This
  34. ----------------: toolset will support asynchronous ASCII                   
  35. ----------------: terminals with single character transmission
  36. ----------------: capabilities.
  37. ----------------:
  38. ----------------: This tool was developed as a precursor for 
  39. ----------------: the WMCCS Information System (WIS).  An
  40. ----------------: executable version of the tool has been 
  41. ----------------: demonstrated.  This source code has sub-
  42. ----------------: sequently been recompiled but has not under-
  43. ----------------: gone extensive testing.
  44. ----------------:
  45. --                                                           -*
  46. ------------------ Revision history ---------------------------
  47. --                                                           -*
  48. -- DATE         VERSION AUTHOR                  HISTORY 
  49. -- 03/85          1.0   John Foreman            Initial Release
  50. --                                                           -*
  51. ------------------ Distribution and Copyright -----------------
  52. --                                                           -*
  53. -- This prologue must be included in all copies of this software.
  54. -- 
  55. -- This software is copyright by the author.
  56. -- 
  57. -- This software is released to the Ada community.
  58. -- This software is released to the Public Domain (note:
  59. --   software released to the Public Domain is not subject
  60. --   to copyright protection).
  61. -- Restrictions on use or distribution:  NONE
  62. --                                                           -*
  63. ----------------- Disclaimer ----------------------------------
  64. --                                                           -*
  65. -- This software and its documentation are provided "AS IS" and
  66. -- without any expressed or implied warranties whatsoever.
  67. --
  68. -- No warranties as to performance, merchantability, or fitness
  69. -- for a particular purpose exist.
  70. --
  71. -- Because of the diversity of conditions and hardware under
  72. -- which this software may be used, no warranty of fitness for
  73. -- a particular purpose is offered.  The user is advised to 
  74. -- test the software thoroughly before relying on it.  The user
  75. -- must assume the entire risk and liability of using this 
  76. -- software.
  77. --
  78. -- In no event shall any person or organization of people be
  79. -- held responsible for any direct, indirect, consequential
  80. -- or inconsequential damages or lost profits.
  81. --                                                          -*
  82. ----------------- END-PROLOGUE -------------------------------
  83. ::::::::::
  84. --fgs_cmp.dis
  85. ::::::::::
  86. --
  87. --  Compilation order for Form Generator System
  88. --
  89.  
  90. --  Support packages
  91.  
  92. FORM_TYPES.ADA
  93. MANAGER_SPEC.ADA
  94. MANAGER_BODY.ADA
  95. TERMINAL_SPEC.ADA
  96. TERMINAL_BODY.ADA
  97. EXECUTOR_SPEC.ADA
  98. EXECUTOR_BODY.ADA
  99.  
  100. --  Batch Generator
  101.  
  102. BATCH_SPEC.ADA
  103. BATCH_BODY.ADA
  104. BATCH_GEN.ADA
  105. --  Link Batch_Gen
  106.  
  107. --  Interactive Generator
  108.  
  109. FORMS.ADA
  110. EDITOR_SPEC.ADA
  111. EDITOR_BODY.ADA
  112. COMMANDS.ADA
  113. INTERACT.ADA
  114. SUBMENUS.ADA
  115. --  Link Interact
  116. ::::::::::
  117. fgs_src.dis
  118. ::::::::::
  119. --
  120. --  Source for Form Generator System
  121. --
  122.  
  123. --  Batch_Generator_Support spec & body -
  124. BATCH_SPEC.ADA
  125. BATCH_BODY.ADA
  126. --  Batch_Gen - Batch Gen. main procedure
  127. BATCH_GEN.ADA
  128. --  Subcommands of form Editor
  129. COMMANDS.ADA
  130. --  Editor spec & body - Interactive Gen. for Editor
  131. EDITOR_BODY.ADA
  132. EDITOR_SPEC.ADA
  133. --  Form_Executor spec & body
  134. EXECUTOR_BODY.ADA
  135. EXECUTOR_SPEC.ADA
  136. --  Forms spec & body - defines Interactive Gen. menus and forms
  137. FORMS.ADA
  138. --  Form_Types spec - defines global types
  139. FORM_TYPES.ADA
  140. --  Interact - Interactive Gen. main procedure
  141. INTERACT.ADA
  142. --  Form_Manager spec & body
  143. MANAGER_BODY.ADA
  144. MANAGER_SPEC.ADA
  145. --  Submenus for Interactive Gen.
  146. SUBMENUS.ADA
  147. --  Terminal_Interface spec & body
  148. TERMINAL_BODY.ADA
  149. TERMINAL_SPEC.ADA
  150. ::::::::::
  151. BATCH_SPEC.ADA
  152. ::::::::::
  153. --------------------------------------------------------------------------
  154. -- Abstract   : This package is a support package for the Batch Generator
  155. --              program.  It defines routines to scan and syntax check
  156. --              the input form definition file.
  157. --------------------------------------------------------------------------
  158.  
  159. package BATCH_GENERATOR_SUPPORT is
  160.  
  161.     type KEYWORD is
  162.      (FIELD,
  163.       FORM,
  164.       TEXT,         -- statement keywords
  165.       CLEAR_SCREEN,
  166.       DEFAULT,
  167.       LENGTH,       -- parameter keywords
  168.       LIMITATION,
  169.       MODE,
  170.       NAME,
  171.       POSITION,
  172.       RENDITION,
  173.       SIZE,
  174.       VALUE,
  175.       YES,
  176.       NO,           -- clear options
  177.       NONE,
  178.       PRIMARY,
  179.       SECONDARY,    -- rendition options
  180.       ALPHABETIC,
  181.       ALPHANUMERIC,
  182.       NUMERIC,
  183.       NOT_LIMITED,  -- character limits
  184.       INPUT_OUTPUT,
  185.       OUTPUT_ONLY); -- input/output options
  186.  
  187.     type TOKEN is
  188.      (IDENTIFIER,        NUMBER,            TEXT_STRING,
  189.       LEFT_PARENTHESIS,  RIGHT_PARENTHESIS, ARROW,
  190.       COMMA,             SEMICOLON,         COMMENT);
  191.  
  192.     CURRENT_IDENTIFIER : STRING (1 .. 80);
  193.     CURRENT_NUMBER     : NATURAL;
  194.     IDENTIFIER_LENGTH  : NATURAL;
  195.     KEYWORD_LENGTH     : constant NATURAL := 12;
  196.     KEYWORD_TABLE      : constant array (KEYWORD)
  197.                      of STRING (1 .. KEYWORD_LENGTH) :=
  198.              ("FIELD       ", "FORM        ", "TEXT        ",
  199.               "CLEAR_SCREEN", "DEFAULT     ", "LENGTH      ",
  200.               "LIMITATION  ", "MODE        ", "NAME        ",
  201.               "POSITION    ", "RENDITION   ", "SIZE        ",
  202.               "VALUE       ", "YES         ", "NO          ",
  203.               "NONE        ", "PRIMARY     ", "REVERSE     ",
  204.               "ALPHABETIC  ", "ALPHANUMERIC", "NUMERIC     ",
  205.               "NOT_LIMITED ", "INPUT_OUTPUT", "OUTPUT_ONLY ");
  206.  
  207.     UNKNOWN_KEYWORD         : exception;
  208.     UNKNOWN_TOKEN           : exception;
  209.     INVALID_IDENTIFIER      : exception;
  210.     INVALID_NUMBER          : exception;
  211.     INVALID_STRING          : exception;
  212.     INVALID_PARAMETER       : exception;
  213.     INVALID_PARAMETER_VALUE : exception;
  214.     UNEXPECTED_TOKEN        : exception;
  215.     FILE_INIT_ERROR         : exception;
  216.     END_OF_INPUT_FILE       : exception;
  217.     ADD_FIELD_ERROR         : exception;
  218.     CREATE_FORM_ERROR       : exception;
  219.  
  220. -- 
  221. -- Supporing Routines
  222. -- 
  223.     function  LOOKUP_KEYWORD  return KEYWORD;
  224.     procedure GET_TOKEN       (NEXT_TOKEN : out TOKEN);
  225.     procedure CHECK_TOKEN     (EXPECTED_TOKEN : TOKEN);
  226.     procedure FLUSH_STATEMENT;
  227.     procedure ERROR_MESSAGE   (MESSAGE : STRING);
  228.  
  229. -- 
  230. -- Statement Processing Routines
  231. -- 
  232.     procedure FORM_STATEMENT;
  233.     procedure FIELD_STATEMENT (FORM_OPEN : BOOLEAN);
  234.     procedure TEXT_STATEMENT  (FORM_OPEN : BOOLEAN);
  235.  
  236. -- 
  237. -- File Open/Close
  238. -- 
  239.     procedure OPEN_FILES;
  240.     procedure CLOSE_FILES;
  241.  
  242. -- 
  243. -- Error Reporting
  244. -- 
  245.     procedure PRINT_COUNT_OF_ERRORS;
  246.     function  COUNT_OF_ERRORS           return NATURAL;
  247.     procedure INCREMENT_COUNT_OF_ERRORS;
  248.  
  249.  
  250. end BATCH_GENERATOR_SUPPORT;
  251. ::::::::::
  252. BATCH_BODY.ADA
  253. ::::::::::
  254. --------------------------------------------------------------------------
  255. -- Abstract   : This package body defines the routines which support the
  256. --              Batch Generator.  They provide the functions to handle
  257. --              input file processing, token scanning, statement syntax
  258. --              and semantic checking, and output listing file processing.
  259. --------------------------------------------------------------------------
  260.  
  261. with FORM_TYPES;
  262. with FORM_MANAGER;
  263. with TEXT_IO;
  264. with CALENDAR;
  265.  
  266. package body BATCH_GENERATOR_SUPPORT is
  267.  
  268. -- 
  269. -- Support for File I/O
  270. -- 
  271.     LST        : TEXT_IO.FILE_TYPE;
  272.     INPUT_FILE : TEXT_IO.FILE_TYPE;
  273.  
  274. -- 
  275. -- Support for GETCH/UNGETCH
  276. -- 
  277.     CHARACTER_PENDING : BOOLEAN := FALSE; -- initially no char pending
  278.     SAVED_CHARACTER   : CHARACTER;
  279.  
  280.     INLINE            : STRING (1 .. 256);
  281.     INLINE_POSITION   : NATURAL := 1; -- position of next char
  282.     INLINE_LAST       : NATURAL := 0; -- set for initial GET_LINE
  283.  
  284.  
  285. -- 
  286. -- Globals for FORM, FIELD, TEXT
  287. -- 
  288.     CURRENT_FORM  : FORM_MANAGER.FORM_ACCESS;
  289.     CURRENT_FIELD : FORM_MANAGER.FIELD_ACCESS;
  290.     ERROR_COUNT   : NATURAL := 0;
  291.     LINE_NUMBER   : NATURAL := 0;
  292.  
  293.  
  294. -- 
  295. -- Global Form File Name
  296. -- 
  297.     FORM_FILE_NAME : STRING (1 .. 50) := (others => ' ');
  298.     FORM_FILE_LAST : NATURAL;
  299.  
  300. -- 
  301. -- I/O for Natural and Integer Numbers
  302. -- 
  303.     package NAT_IO is new TEXT_IO.INTEGER_IO (NATURAL);
  304.     package INT_IO is new TEXT_IO.INTEGER_IO (INTEGER);
  305.  
  306. -- 
  307. --=====================================================================
  308. -- 
  309.     procedure NOTE_MESSAGE (MESSAGE : STRING) is
  310. -- 
  311. -- Print note message in listing.
  312. -- 
  313.     begin
  314.     TEXT_IO.PUT (LST, "<<<<< ");
  315.     TEXT_IO.PUT (LST, MESSAGE);
  316.     TEXT_IO.PUT_LINE (LST, " >>>>>");
  317.     end NOTE_MESSAGE;
  318.  
  319.  
  320. -- 
  321. --====================================================================
  322. -- 
  323.     procedure OPEN_FILES is
  324. -- 
  325. -- Opens the file identified by INPUT_FILE and creates the file
  326. -- identified by LST.
  327. -- 
  328.     SOURCE_FILE_NAME  : STRING (1 .. 50) := (others => ' ');
  329.     LISTING_FILE_NAME : STRING (1 .. 50) := (others => ' ');
  330.     LAST              : NATURAL;
  331. -- 
  332.     CURRENT_TIME  : CALENDAR.TIME;
  333.     CURRENT_YEAR  : CALENDAR.YEAR_NUMBER;
  334.     CURRENT_MONTH : CALENDAR.MONTH_NUMBER;
  335.     CURRENT_DAY   : CALENDAR.DAY_NUMBER;
  336. -- 
  337.     begin
  338. -- 
  339. -- Get date
  340. -- 
  341.     CURRENT_TIME := CALENDAR.CLOCK;
  342.     CURRENT_YEAR := CALENDAR.YEAR (CURRENT_TIME);
  343.     CURRENT_MONTH := CALENDAR.MONTH (CURRENT_TIME);
  344.     CURRENT_DAY := CALENDAR.DAY (CURRENT_TIME);
  345. -- 
  346. -- Print banner on console
  347. -- 
  348.     TEXT_IO.PUT ("Batch Forms Generator running on ");
  349.     INT_IO.PUT (CURRENT_MONTH, 2);
  350.     TEXT_IO.PUT ('/');
  351.     INT_IO.PUT (CURRENT_DAY, 2);
  352.     TEXT_IO.PUT ('/');
  353.     INT_IO.PUT (CURRENT_YEAR, 4);
  354.     TEXT_IO.NEW_LINE;
  355. -- 
  356. -- Get name of source file
  357. -- 
  358.     TEXT_IO.PUT ("Source  File > ");
  359.     TEXT_IO.GET_LINE (SOURCE_FILE_NAME, LAST);
  360.     TEXT_IO.OPEN (INPUT_FILE, TEXT_IO.IN_FILE,
  361.               SOURCE_FILE_NAME (1 .. LAST));
  362. -- 
  363. -- Get name of listing file
  364. -- 
  365.     TEXT_IO.PUT ("Listing File > ");
  366.     TEXT_IO.GET_LINE (LISTING_FILE_NAME, LAST);
  367.     TEXT_IO.CREATE (LST, TEXT_IO.OUT_FILE, LISTING_FILE_NAME (1 .. LAST));
  368. -- 
  369. -- Get name of Form output File for use later when form is saved
  370. -- 
  371.     TEXT_IO.PUT ("Form    File > ");
  372.     TEXT_IO.GET_LINE (FORM_FILE_NAME, FORM_FILE_LAST);
  373. -- 
  374. -- Put header on listing output (title, name of source, name of output)
  375. -- 
  376.     TEXT_IO.PUT (LST, "Batch Forms Generator running on ");
  377.     INT_IO.PUT (LST, CURRENT_MONTH, 2);
  378.     TEXT_IO.PUT (LST, '/');
  379.     INT_IO.PUT (LST, CURRENT_DAY, 2);
  380.     TEXT_IO.PUT (LST, '/');
  381.     INT_IO.PUT (LST, CURRENT_YEAR, 4);
  382.     TEXT_IO.NEW_LINE (LST);
  383.     TEXT_IO.PUT (LST, "    Input  File: ");
  384.     TEXT_IO.PUT (LST, SOURCE_FILE_NAME);
  385.     TEXT_IO.NEW_LINE (LST);
  386.     TEXT_IO.PUT (LST, "    Output File: ");
  387.     TEXT_IO.PUT (LST, FORM_FILE_NAME);
  388.     TEXT_IO.NEW_LINE (LST, 2);
  389. -- 
  390.     exception
  391.     when others => 
  392.         raise FILE_INIT_ERROR;
  393.     end OPEN_FILES;
  394.  
  395.  
  396. -- 
  397. --====================================================================
  398. -- 
  399.     procedure CLOSE_FILES is
  400. -- 
  401. -- Close the Input and Listing Files
  402. -- Close the form file if ERROR_COUNT = 0
  403. -- 
  404.     begin
  405.     TEXT_IO.CLOSE (INPUT_FILE);
  406.     if ERROR_COUNT = 0 then
  407.         FORM_MANAGER.SAVE_FORM
  408.            (CURRENT_FORM, FORM_FILE_NAME (1 .. FORM_FILE_LAST));
  409.         NOTE_MESSAGE ("Form Saved");
  410.     else
  411.         NOTE_MESSAGE ("Form NOT Saved");
  412.     end if;
  413.     TEXT_IO.CLOSE (LST);
  414.     end CLOSE_FILES;
  415.  
  416.  
  417. -- 
  418. --====================================================================
  419. -- 
  420.     procedure PRINT_COUNT_OF_ERRORS is
  421. -- 
  422. -- Print ERROR_COUNT to LST and Console
  423. -- 
  424.     begin
  425. -- 
  426. -- Print error count on console
  427. -- 
  428.     TEXT_IO.NEW_LINE;
  429.     TEXT_IO.PUT ("<<<<< ");
  430.     NAT_IO.PUT (ERROR_COUNT);
  431.     TEXT_IO.PUT_LINE (" Error(s) Detected >>>>>");
  432. -- 
  433. -- Print error count on listing
  434. -- 
  435.     TEXT_IO.NEW_LINE (LST);
  436.     TEXT_IO.PUT (LST, "<<<<< ");
  437.     NAT_IO.PUT (LST, ERROR_COUNT);
  438.     TEXT_IO.PUT_LINE (LST, " Error(s) Detected >>>>>");
  439. -- 
  440.     end PRINT_COUNT_OF_ERRORS;
  441.  
  442.  
  443. -- 
  444. --====================================================================
  445. -- 
  446.     procedure INCREMENT_COUNT_OF_ERRORS is
  447. -- 
  448. -- Increment ERROR_COUNT
  449. -- 
  450.     begin
  451.     ERROR_COUNT := ERROR_COUNT + 1;
  452.     end INCREMENT_COUNT_OF_ERRORS;
  453.  
  454.  
  455. -- 
  456. --====================================================================
  457. -- 
  458.     function COUNT_OF_ERRORS return NATURAL is
  459. -- 
  460. -- Return value of ERROR_COUNT
  461. -- 
  462.     begin
  463.     return (ERROR_COUNT);
  464.     end COUNT_OF_ERRORS;
  465.  
  466.  
  467. -- 
  468. --====================================================================
  469. -- 
  470.     function LOOKUP_KEYWORD return KEYWORD is
  471. -- 
  472. -- Searches the keyword table to determine if the current identifier
  473. -- is a keyword and returns the keyword value.
  474. -- 
  475. -- Raises UNKNOWN_KEYWORD if the CURRENT_IDENTIFIER is not a known
  476. -- keyword in KEYWORD_TABLE.
  477. -- 
  478.     KEYWORD_OUTPUT : KEYWORD;
  479.     FOUND_KEYWORD  : BOOLEAN;
  480.     -- 
  481.     -- Compare string TABLE to string ID; capitalize string ID
  482.     -- 
  483.     function LOOK_EQUAL (TABLE : STRING; ID : STRING) return BOOLEAN is
  484.         EQUAL : BOOLEAN;
  485.         -- 
  486.         function CAPS (INCHAR : CHARACTER) return CHARACTER is
  487.         begin
  488.         if INCHAR in 'a' .. 'z' then
  489.             return CHARACTER'VAL
  490.                  (CHARACTER'POS (INCHAR) - CHARACTER'POS ('a') +
  491.                   CHARACTER'POS ('A'));
  492.         else
  493.             return INCHAR;
  494.         end if;
  495.         end CAPS;
  496.         -- 
  497.     begin
  498.         EQUAL := TRUE;
  499.         for I in 1 .. KEYWORD_LENGTH loop
  500.         if TABLE (I) /= CAPS (ID (I)) then
  501.             EQUAL := FALSE;
  502.             exit;
  503.         end if;
  504.         end loop;
  505.         return EQUAL;
  506.     end LOOK_EQUAL;
  507.     -- 
  508.     -- Body of LOOKUP_KEYWORD
  509.     -- 
  510.     begin
  511.     FOUND_KEYWORD := FALSE;
  512.     for KEYWORD_INDEX in KEYWORD'FIRST .. KEYWORD'LAST loop
  513.         if LOOK_EQUAL (KEYWORD_TABLE (KEYWORD_INDEX),
  514.                CURRENT_IDENTIFIER) then
  515.         KEYWORD_OUTPUT := KEYWORD_INDEX;
  516.         FOUND_KEYWORD := TRUE;
  517.         exit;
  518.         end if;
  519.     end loop;
  520.     if not FOUND_KEYWORD then
  521.         raise UNKNOWN_KEYWORD;
  522.     end if;
  523.     return KEYWORD_OUTPUT; -- correct Ada
  524.     end LOOKUP_KEYWORD;
  525.  
  526.  
  527. -- 
  528. --====================================================================
  529. -- 
  530.     procedure FLUSH_INPUT_LINE is
  531. -- 
  532. -- Flushes rest of input line
  533. -- 
  534.     begin
  535.     INLINE_LAST := 0;
  536.     INLINE_POSITION := 1;
  537.     CHARACTER_PENDING := FALSE;
  538.     end FLUSH_INPUT_LINE;
  539.  
  540.  
  541.     procedure UNGETCH (INCHAR : CHARACTER) is
  542. -- 
  543. -- Saves the indicated character for the following GETCH
  544. -- 
  545.     begin
  546.     SAVED_CHARACTER := INCHAR;
  547.     CHARACTER_PENDING := TRUE;
  548.     end UNGETCH;
  549.  
  550.  
  551.     function GETCH return CHARACTER is
  552. -- 
  553. -- Returns the next character from the input file.  If EOL, returns
  554. -- ASCII.CR.
  555. -- 
  556.     INCHAR : CHARACTER;
  557.     begin
  558.     if CHARACTER_PENDING then
  559.         CHARACTER_PENDING := FALSE;
  560.         return SAVED_CHARACTER;
  561.     else
  562.         if INLINE_POSITION > INLINE_LAST then
  563.         TEXT_IO.GET_LINE (INPUT_FILE, INLINE, INLINE_LAST);
  564.         LINE_NUMBER := LINE_NUMBER + 1;
  565.         NAT_IO.PUT (LST, LINE_NUMBER, 5);
  566.         TEXT_IO.PUT (LST, ' ');
  567.         for I in 1 .. INLINE_LAST loop
  568.             TEXT_IO.PUT (LST, INLINE (I));
  569.         end loop;
  570.         TEXT_IO.NEW_LINE (LST);
  571.         INLINE_POSITION := 1;
  572.         return ASCII.CR;
  573.         else
  574.         INCHAR := INLINE (INLINE_POSITION);
  575.         INLINE_POSITION := INLINE_POSITION + 1;
  576.         return INCHAR;
  577.         end if;
  578.     end if;
  579.     exception
  580.     when others => 
  581.         raise END_OF_INPUT_FILE;
  582.     end GETCH;
  583.  
  584.  
  585. -- 
  586. --====================================================================
  587. -- 
  588.     procedure GET_TOKEN (NEXT_TOKEN : out TOKEN) is
  589. -- 
  590. -- Scans the input file for the next token.  A token can be an
  591. -- identifier, number, string, or special symbol.  Special symbols
  592. -- include arrow "=>", comma ",", left parenthesis "(", right
  593. -- parenthesis ")", semicolon ";", and comment "--".
  594. -- 
  595. -- Raises INVALID_IDENTIFIER, INVALID_NUMBER, INVALID_STRING, and
  596. -- UNKNOWN_TOKEN.
  597. -- 
  598.  
  599. -- 
  600. -- Global Identifiers
  601. -- 
  602.     FIRST_CHARACTER : CHARACTER;
  603.     INDEX           : NATURAL;
  604.  
  605.  
  606. -- 
  607. -- If the indicated character is a white space character (non-printing
  608. -- character in this case), return TRUE else return FALSE.
  609. -- 
  610.     function IS_WHITE_SPACE (INCHAR : CHARACTER) return BOOLEAN is
  611.     begin
  612.         if INCHAR <= ' ' or INCHAR = ASCII.DEL then
  613.         return TRUE;
  614.         else
  615.         return FALSE;
  616.         end if;
  617.     end IS_WHITE_SPACE;
  618.  
  619.  
  620. -- 
  621. -- Fill CURRENT_IDENTIFIER from INDEX+1 to end with spaces
  622. -- 
  623.     procedure FILL_IDENTIFIER is
  624.     begin
  625.         for I in INDEX + 1 .. CURRENT_IDENTIFIER'LAST loop
  626.         CURRENT_IDENTIFIER (I) := ' ';
  627.         end loop;
  628.     end FILL_IDENTIFIER;
  629.  
  630.  
  631.  
  632. -- 
  633. -- Extract identifier into CURRENT_IDENTIFIER
  634. -- 
  635.     procedure EXTRACT_IDENTIFIER is
  636.         NEXT_CHARACTER : CHARACTER;
  637.     begin
  638.         INDEX := 1;
  639.         CURRENT_IDENTIFIER (INDEX) := FIRST_CHARACTER;
  640.         loop
  641.         NEXT_CHARACTER := GETCH;
  642.         case NEXT_CHARACTER is
  643.             when 'a' .. 'z' | 'A' .. 'Z' | '_' => 
  644.             INDEX := INDEX + 1;
  645.             if INDEX > CURRENT_IDENTIFIER'LAST then
  646.                 IDENTIFIER_LENGTH := INDEX - 1;
  647.                 raise INVALID_IDENTIFIER;
  648.             end if;
  649.             CURRENT_IDENTIFIER (INDEX) := NEXT_CHARACTER;
  650.             when others => 
  651.             UNGETCH (NEXT_CHARACTER);
  652.             exit;
  653.         end case;
  654.         end loop;
  655.         IDENTIFIER_LENGTH := INDEX;
  656.         FILL_IDENTIFIER;
  657.     end EXTRACT_IDENTIFIER;
  658.  
  659.  
  660. -- 
  661. -- Store characters making up number in CURRENT_IDENTIFIER
  662. -- 
  663.     procedure EXTRACT_NUMBER is
  664.         NEXT_CHARACTER : CHARACTER;
  665.     begin
  666.         INDEX := 1;
  667.         CURRENT_IDENTIFIER (INDEX) := FIRST_CHARACTER;
  668.         loop
  669.         NEXT_CHARACTER := GETCH;
  670.         case NEXT_CHARACTER is
  671.             when '0' .. '9' => 
  672.             INDEX := INDEX + 1;
  673.             if INDEX > CURRENT_IDENTIFIER'LAST then
  674.                 IDENTIFIER_LENGTH := INDEX - 1;
  675.                 raise INVALID_NUMBER;
  676.             end if;
  677.             CURRENT_IDENTIFIER (INDEX) := NEXT_CHARACTER;
  678.             when others => 
  679.             UNGETCH (NEXT_CHARACTER);
  680.             exit;
  681.         end case;
  682.         end loop;
  683.         IDENTIFIER_LENGTH := INDEX;
  684.         FILL_IDENTIFIER;
  685.         CURRENT_NUMBER := NATURAL'VALUE (CURRENT_IDENTIFIER);
  686.     exception
  687.         when others => 
  688.         raise INVALID_NUMBER;
  689.     end EXTRACT_NUMBER;
  690.  
  691.  
  692. -- 
  693. -- Extract the string into CURRENT_IDENTIFIER
  694. -- 
  695.     procedure EXTRACT_STRING is
  696.         NEXT_CHARACTER : CHARACTER;
  697.     begin
  698.         INDEX := 0;
  699.         loop
  700.         NEXT_CHARACTER := GETCH;
  701.         case NEXT_CHARACTER is
  702.             when '"' => 
  703.             exit; -- end of string
  704.             when ASCII.CR => 
  705.             IDENTIFIER_LENGTH := INDEX;
  706.             FILL_IDENTIFIER;
  707.             raise INVALID_STRING; -- EOL error
  708.             when others => 
  709.             INDEX := INDEX + 1;
  710.             if INDEX > CURRENT_IDENTIFIER'LAST then
  711.                 IDENTIFIER_LENGTH := INDEX - 1;
  712.                 raise INVALID_STRING;
  713.             end if;
  714.             CURRENT_IDENTIFIER (INDEX) := NEXT_CHARACTER;
  715.         end case;
  716.         end loop;
  717.         IDENTIFIER_LENGTH := INDEX;
  718.         FILL_IDENTIFIER;
  719.     end EXTRACT_STRING;
  720.  
  721.  
  722. -- 
  723. -- Check to see if next character is indeed a ">" to complete the arrow "=>"
  724. -- 
  725.     procedure EXTRACT_ARROW is
  726.         NEXT_CHARACTER : CHARACTER;
  727.     begin
  728.         NEXT_CHARACTER := GETCH;
  729.         if NEXT_CHARACTER = '>' then
  730.         return; -- OK
  731.         else
  732.         UNGETCH (NEXT_CHARACTER);
  733.         raise UNKNOWN_TOKEN;
  734.         end if;
  735.     end EXTRACT_ARROW;
  736.  
  737.  
  738.  
  739. -- 
  740. -- Check to see if next character is a "-" to complete the "--"
  741. -- 
  742.     procedure EXTRACT_COMMENT is
  743.         NEXT_CHARACTER : CHARACTER;
  744.     begin
  745.         NEXT_CHARACTER := GETCH;
  746.         if NEXT_CHARACTER = '-' then
  747.         FLUSH_INPUT_LINE; -- throw away comment chars
  748.         return; -- OK
  749.         else
  750.         UNGETCH (NEXT_CHARACTER);
  751.         raise UNKNOWN_TOKEN;
  752.         end if;
  753.     end EXTRACT_COMMENT;
  754.  
  755.  
  756. -- 
  757.     begin
  758.     loop
  759.         FIRST_CHARACTER := GETCH; -- look for first char
  760.         exit when not IS_WHITE_SPACE (FIRST_CHARACTER);
  761.     end loop;
  762.     case FIRST_CHARACTER is
  763.         when 'A' .. 'Z' | 'a' .. 'z' => 
  764.         EXTRACT_IDENTIFIER;
  765.         NEXT_TOKEN := IDENTIFIER;
  766.         when '0' .. '9' => 
  767.         EXTRACT_NUMBER;
  768.         NEXT_TOKEN := NUMBER;
  769.         when '"' => 
  770.         EXTRACT_STRING;
  771.         NEXT_TOKEN := TEXT_STRING;
  772.         when '(' => 
  773.         CURRENT_IDENTIFIER := (others => ' ');
  774.         CURRENT_IDENTIFIER (1) := '(';
  775.         IDENTIFIER_LENGTH := 1;
  776.         NEXT_TOKEN := LEFT_PARENTHESIS;
  777.         when ')' => 
  778.         CURRENT_IDENTIFIER := (others => ' ');
  779.         CURRENT_IDENTIFIER (1) := ')';
  780.         IDENTIFIER_LENGTH := 1;
  781.         NEXT_TOKEN := RIGHT_PARENTHESIS;
  782.         when '=' => 
  783.         EXTRACT_ARROW;
  784.         CURRENT_IDENTIFIER := (others => ' ');
  785.         CURRENT_IDENTIFIER (1 .. 2) := "=>";
  786.         IDENTIFIER_LENGTH := 2;
  787.         NEXT_TOKEN := ARROW;
  788.         when '-' => 
  789.         EXTRACT_COMMENT;
  790.         CURRENT_IDENTIFIER := (others => ' ');
  791.         CURRENT_IDENTIFIER (1 .. 2) := "--";
  792.         IDENTIFIER_LENGTH := 2;
  793.         NEXT_TOKEN := COMMENT;
  794.         when ',' => 
  795.         CURRENT_IDENTIFIER := (others => ' ');
  796.         CURRENT_IDENTIFIER (1) := ',';
  797.         IDENTIFIER_LENGTH := 1;
  798.         NEXT_TOKEN := COMMA;
  799.         when ';' => 
  800.         CURRENT_IDENTIFIER := (others => ' ');
  801.         CURRENT_IDENTIFIER (1) := ';';
  802.         IDENTIFIER_LENGTH := 1;
  803.         NEXT_TOKEN := SEMICOLON;
  804.         when others => 
  805.         CURRENT_IDENTIFIER := (others => ' ');
  806.         CURRENT_IDENTIFIER (1) := FIRST_CHARACTER;
  807.         IDENTIFIER_LENGTH := 1;
  808.         raise UNKNOWN_TOKEN;
  809.     end case;
  810.     end GET_TOKEN;
  811.  
  812.  
  813. -- 
  814. --====================================================================
  815. -- 
  816.     procedure ERROR_MESSAGE (MESSAGE : STRING) is
  817. -- 
  818. -- Outputs an error message to the listing file following the
  819. -- statement which had the error.
  820. -- 
  821.     begin
  822.     TEXT_IO.PUT (LST, "***** ");
  823.     TEXT_IO.PUT (LST, MESSAGE);
  824.     TEXT_IO.NEW_LINE (LST);
  825.     TEXT_IO.PUT (LST, "      Error is at or near ");
  826.     for I in 1 .. IDENTIFIER_LENGTH loop
  827.         TEXT_IO.PUT (LST, CURRENT_IDENTIFIER (I));
  828.     end loop;
  829.     TEXT_IO.NEW_LINE (LST);
  830.     end ERROR_MESSAGE;
  831.  
  832.  
  833. -- 
  834. --====================================================================
  835. -- 
  836.     procedure FLUSH_STATEMENT is
  837.     NEXT_TOKEN : TOKEN;
  838.     begin
  839.     loop
  840.         GET_TOKEN (NEXT_TOKEN);
  841.         exit when NEXT_TOKEN = SEMICOLON;
  842.     end loop;
  843.     end FLUSH_STATEMENT;
  844.  
  845.  
  846. -- 
  847. --====================================================================
  848. -- 
  849.     procedure CHECK_TOKEN (EXPECTED_TOKEN : TOKEN) is
  850.     NEXT_TOKEN : TOKEN;
  851.     begin
  852. -- 
  853. -- Flush comments
  854. -- 
  855.     loop
  856.         GET_TOKEN (NEXT_TOKEN);
  857.         exit when NEXT_TOKEN /= COMMENT;
  858.     end loop;
  859. -- 
  860. -- Test and print error messages
  861. -- 
  862.     if NEXT_TOKEN /= EXPECTED_TOKEN then
  863.         case EXPECTED_TOKEN is
  864.         when IDENTIFIER => 
  865.             ERROR_MESSAGE ("Expected Identifier");
  866.         when NUMBER => 
  867.             ERROR_MESSAGE ("Expected Number");
  868.         when TEXT_STRING => 
  869.             ERROR_MESSAGE ("Expected String");
  870.         when LEFT_PARENTHESIS => 
  871.             ERROR_MESSAGE ("Expected '('");
  872.         when RIGHT_PARENTHESIS => 
  873.             ERROR_MESSAGE ("Expected ')'");
  874.         when ARROW => 
  875.             ERROR_MESSAGE ("Expected '=>'");
  876.         when COMMA => 
  877.             ERROR_MESSAGE ("Expected ','");
  878.         when SEMICOLON => 
  879.             ERROR_MESSAGE ("Expected ';'");
  880.         when others => 
  881.             null; -- not encountered
  882.         end case;
  883.         raise UNEXPECTED_TOKEN;
  884.     end if;
  885.     end CHECK_TOKEN;
  886.  
  887.  
  888. -- 
  889. --=====================================================================
  890. -- 
  891.     procedure GET_PARAMETER (PARAMETER : out KEYWORD) is
  892.     begin
  893.     CHECK_TOKEN (IDENTIFIER);
  894.     PARAMETER := LOOKUP_KEYWORD;
  895.     CHECK_TOKEN (ARROW);
  896.     end GET_PARAMETER;
  897.  
  898.  
  899. -- 
  900. --=====================================================================
  901. -- 
  902.     procedure GET_ROW_COL (ROW, COL : out NATURAL) is
  903.     begin
  904.     CHECK_TOKEN (LEFT_PARENTHESIS);
  905.     CHECK_TOKEN (NUMBER);
  906.     ROW := CURRENT_NUMBER;
  907.     CHECK_TOKEN (COMMA);
  908.     CHECK_TOKEN (NUMBER);
  909.     COL := CURRENT_NUMBER;
  910.     CHECK_TOKEN (RIGHT_PARENTHESIS);
  911.     end GET_ROW_COL;
  912.  
  913.  
  914. -- 
  915. --====================================================================
  916. -- 
  917.     procedure FORM_STATEMENT is
  918. -- 
  919. -- Parses the "FORM" statement which begins a form definition by
  920. -- giving the form size, position, and whether the screen should
  921. -- be cleared whenever the form is displayed.  If the form definition
  922. -- is correct, the form definition is saved by calling CREATE_FORM
  923. -- in the FORM_MANAGER.  The form statement definition is copied
  924. -- to the listing file including any errors that are detected.
  925. -- 
  926. -- Possible Error Messages (sent to listing file):
  927. --          Form not contained within screen display boundaries
  928. --          Incorrect position parameter syntax
  929. --          Incorrect size parameter syntax
  930. --          Invalid clear screen option
  931. --          Invalid form statement parameter
  932. -- 
  933.     PARAMETER              : KEYWORD;
  934.     VALUE                  : KEYWORD;
  935.     CLS                    : FORM_MANAGER.OPTION_TYPE;
  936.     NEXT_TOKEN             : TOKEN;
  937.     SIZE_ROW, POSITION_ROW : FORM_TYPES.ROW_RANGE;
  938.     SIZE_COL, POSITION_COL : FORM_TYPES.COLUMN_RANGE;
  939.     begin
  940. -- 
  941. -- Default Values
  942. -- 
  943.     SIZE_ROW := 24; -- number of rows and columns on form
  944.     SIZE_COL := 80;
  945.     POSITION_ROW := 1; -- at upper left
  946.     POSITION_COL := 1;
  947.     CLS := FORM_MANAGER.CLEAR; -- clear screen
  948. -- 
  949. -- Interpret parameters and extract information from them
  950. -- 
  951.     loop
  952.         GET_PARAMETER (PARAMETER);
  953.         case PARAMETER is
  954.         when SIZE => 
  955.             GET_ROW_COL (SIZE_ROW, SIZE_COL);
  956.         when POSITION => 
  957.             GET_ROW_COL (POSITION_ROW, POSITION_COL);
  958.         when CLEAR_SCREEN => 
  959.             CHECK_TOKEN (IDENTIFIER);
  960.             VALUE := LOOKUP_KEYWORD;
  961.             case VALUE is
  962.             when YES =>  CLS := FORM_MANAGER.CLEAR;
  963.             when NO =>  CLS := FORM_MANAGER.NO_CLEAR;
  964.             when others => 
  965.                 ERROR_MESSAGE ("Expected YES or NO");
  966.                 raise INVALID_PARAMETER_VALUE;
  967.             end case;
  968.         when others => 
  969.             raise INVALID_PARAMETER;
  970.         end case;
  971. -- 
  972. -- Next token should be a comma (to continue) or right paren (to stop)
  973. -- 
  974.         loop
  975.         GET_TOKEN (NEXT_TOKEN);
  976.         exit when NEXT_TOKEN /= COMMENT;
  977.         end loop;
  978.         exit when NEXT_TOKEN = RIGHT_PARENTHESIS;
  979.         if NEXT_TOKEN /= COMMA then
  980.         ERROR_MESSAGE ("Expected ',' or ')'");
  981.         raise UNEXPECTED_TOKEN;
  982.         end if;
  983.     end loop;
  984. -- 
  985. -- Proceed to create the form
  986. -- 
  987.     begin
  988.         FORM_MANAGER.CREATE_FORM
  989.            (SIZE         => (SIZE_ROW, SIZE_COL),
  990.         POSITION     => (POSITION_ROW, POSITION_COL),
  991.         CLEAR_OPTION => CLS,
  992.         FORM         => CURRENT_FORM);
  993.     exception
  994.         when others => 
  995.         raise CREATE_FORM_ERROR;
  996.     end;
  997.     end FORM_STATEMENT;
  998.  
  999.  
  1000. -- 
  1001. --====================================================================
  1002. -- 
  1003.     procedure FIELD_STATEMENT (FORM_OPEN : BOOLEAN) is
  1004. -- 
  1005. -- Parses the "FIELD" statement that defines an input or output field
  1006. -- for a form by giving the field name, position, length, display
  1007. -- rendition, character limitation, default value, and input and/or
  1008. -- output mode.  If the field definition is correct, the field is
  1009. -- saved by calling ADD_FIELD in the FORM_MANAGER.  The field statement
  1010. -- definition is copied to the listing file including any errors that
  1011. -- are detected.
  1012. -- 
  1013. -- Possible Error Messages (sent to listing file):
  1014. --          Field not contained within form boundaries
  1015. --          Incorrect default parameter syntax
  1016. --          Incorrect length parameter syntax
  1017. --          Incorrect name parameter syntax
  1018. --          Incorrect position parameter syntax
  1019. --          Invalid character limitation option
  1020. --          Invalid display mode option
  1021. --          Invalid display rendition option
  1022. --          Invalid field statement parameter
  1023. --          Length parameter must be provided
  1024. --          Name parameter must be provided
  1025. --          Position parameter must be provided
  1026. -- 
  1027.     NEXT_TOKEN     : TOKEN;
  1028.     PARAMETER      : KEYWORD;
  1029.     TEXT_VALUE     : KEYWORD;
  1030.     TEXT_RENDITION : FORM_MANAGER.FIELD_RENDITIONS;
  1031.     IO_MODE        : FORM_MANAGER.FIELD_MODE;
  1032.     TEXT_LIMITS    : FORM_MANAGER.CHAR_TYPE;
  1033.     VALUE_STRING   : STRING (1 .. 80);
  1034.     NAME_STRING    : STRING (1 .. 80);
  1035.     DEFAULT_STRING : STRING (1 .. 80) := (others => ' ');
  1036.     LENGTH_VALUE   : FORM_MANAGER.FIELD_LENGTH;
  1037.     NAME_SET       : BOOLEAN;
  1038.     LENGTH_SET     : BOOLEAN;
  1039.     POSITION_SET   : BOOLEAN;
  1040.     POSITION_ROW   : FORM_TYPES.ROW_RANGE;
  1041.     POSITION_COL   : FORM_TYPES.COLUMN_RANGE;
  1042.     begin
  1043. -- 
  1044. -- Default Parameter Values
  1045. -- 
  1046.     POSITION_SET := FALSE;
  1047.     NAME_SET := FALSE;
  1048.     LENGTH_SET := FALSE;
  1049.     TEXT_RENDITION := FORM_TYPES.PRIMARY_RENDITION;
  1050. --      DEFAULT_STRING := "   ";  -- set in declaration
  1051.     IO_MODE := FORM_MANAGER.INPUT_OUTPUT;
  1052.     TEXT_LIMITS := FORM_MANAGER.NOT_LIMITED;
  1053. -- 
  1054. -- Process each parameter in turn
  1055. -- 
  1056.     loop
  1057.         GET_PARAMETER (PARAMETER);
  1058.         case PARAMETER is
  1059.         when NAME => 
  1060.             CHECK_TOKEN (TEXT_STRING);
  1061.             NAME_STRING := CURRENT_IDENTIFIER;
  1062.             NAME_SET := TRUE;
  1063.         when POSITION => 
  1064.             GET_ROW_COL (POSITION_ROW, POSITION_COL);
  1065.             POSITION_SET := TRUE;
  1066.         when LENGTH => 
  1067.             CHECK_TOKEN (NUMBER);
  1068.             LENGTH_VALUE := CURRENT_NUMBER;
  1069.             LENGTH_SET := TRUE;
  1070.         when RENDITION => 
  1071.             CHECK_TOKEN (IDENTIFIER);
  1072.             TEXT_VALUE := LOOKUP_KEYWORD;
  1073.             case TEXT_VALUE is
  1074.             when PRIMARY => 
  1075.                 TEXT_RENDITION := FORM_TYPES.PRIMARY_RENDITION;
  1076.             when SECONDARY => 
  1077.                 TEXT_RENDITION := FORM_TYPES.REVERSE_RENDITION;
  1078.             when others => 
  1079.                 ERROR_MESSAGE ("Expected PRIMARY or REVERSE");
  1080.                 raise INVALID_PARAMETER_VALUE;
  1081.             end case;
  1082.         when LIMITATION => 
  1083.             CHECK_TOKEN (IDENTIFIER);
  1084.             TEXT_VALUE := LOOKUP_KEYWORD;
  1085.             case TEXT_VALUE is
  1086.             when ALPHABETIC => 
  1087.                 TEXT_LIMITS := FORM_MANAGER.ALPHA;
  1088.             when NUMERIC => 
  1089.                 TEXT_LIMITS := FORM_MANAGER.NUMERIC;
  1090.             when ALPHANUMERIC => 
  1091.                 TEXT_LIMITS := FORM_MANAGER.ALPHA_NUMERIC;
  1092.             when NOT_LIMITED => 
  1093.                 TEXT_LIMITS := FORM_MANAGER.NOT_LIMITED;
  1094.             when others => 
  1095.                 ERROR_MESSAGE
  1096.                    ("Expected Text Limitation Specification");
  1097.                 raise INVALID_PARAMETER_VALUE;
  1098.             end case;
  1099.         when DEFAULT => 
  1100.             CHECK_TOKEN (TEXT_STRING);
  1101.             DEFAULT_STRING := CURRENT_IDENTIFIER;
  1102.         when MODE => 
  1103.             CHECK_TOKEN (IDENTIFIER);
  1104.             TEXT_VALUE := LOOKUP_KEYWORD;
  1105.             case TEXT_VALUE is
  1106.             when OUTPUT_ONLY => 
  1107.                 IO_MODE := FORM_MANAGER.OUTPUT_ONLY;
  1108.             when INPUT_OUTPUT => 
  1109.                 IO_MODE := FORM_MANAGER.INPUT_OUTPUT;
  1110.             when others => 
  1111.                 ERROR_MESSAGE
  1112.                    ("Expected OUTPUT_ONLY or INPUT_OUTPUT");
  1113.                 raise INVALID_PARAMETER_VALUE;
  1114.             end case;
  1115.         when others => 
  1116.             raise INVALID_PARAMETER;
  1117.         end case;
  1118. -- 
  1119. -- Next token should be a comma (to continue) or right paren (to stop)
  1120. -- 
  1121.         loop
  1122.         GET_TOKEN (NEXT_TOKEN);
  1123.         exit when NEXT_TOKEN /= COMMENT;
  1124.         end loop;
  1125.         exit when NEXT_TOKEN = RIGHT_PARENTHESIS;
  1126.         if NEXT_TOKEN /= COMMA then
  1127.         ERROR_MESSAGE ("Expected ',' or ')'");
  1128.         raise UNEXPECTED_TOKEN;
  1129.         end if;
  1130.     end loop;
  1131. -- 
  1132. -- If no error, then check for all required parameters and process
  1133. -- 
  1134.     if not (NAME_SET and POSITION_SET and LENGTH_SET) then
  1135.         if not NAME_SET then
  1136.         ERROR_MESSAGE ("NAME Parameter is Missing");
  1137.         INCREMENT_COUNT_OF_ERRORS;
  1138.         end if;
  1139.         if not POSITION_SET then
  1140.         ERROR_MESSAGE ("POSITION Parameter is Missing");
  1141.         INCREMENT_COUNT_OF_ERRORS;
  1142.         end if;
  1143.         if not LENGTH_SET then
  1144.         ERROR_MESSAGE ("LENGTH Parameter is Missing");
  1145.         INCREMENT_COUNT_OF_ERRORS;
  1146.         end if;
  1147.     else
  1148.         begin
  1149.         if FORM_OPEN then
  1150.             FORM_MANAGER.ADD_FIELD
  1151.                (FORM        => CURRENT_FORM,
  1152.             NAME        => NAME_STRING,
  1153.             POSITION    => (POSITION_ROW, POSITION_COL),
  1154.             LENGTH      => LENGTH_VALUE,
  1155.             RENDITION   => TEXT_RENDITION,
  1156.             CHAR_LIMITS => TEXT_LIMITS,
  1157.             INIT_VALUE  => DEFAULT_STRING,
  1158.             MODE        => IO_MODE,
  1159.             FIELD       => CURRENT_FIELD);
  1160.         else
  1161.             NOTE_MESSAGE ("FIELD Statement Correct but FORM Not Open");
  1162.             if ERROR_COUNT = 0 then  ERROR_COUNT := 1;  end if;
  1163.         end if;
  1164.         exception
  1165.         when FORM_MANAGER.DUPLICATE_FIELD_NAME => 
  1166.             ERROR_MESSAGE ("Field name is not unique");
  1167.         when FORM_MANAGER.FIELD_EXTENDS_PAST_FORM |
  1168.              FORM_MANAGER.POSITION_OUT_OF_FORM_RANGE => 
  1169.             ERROR_MESSAGE ("Field not within form boundary");
  1170.         when FORM_MANAGER.FIELD_OVERLAP_OCCURRED => 
  1171.             ERROR_MESSAGE ("Field overlaps another field");
  1172.         when others => 
  1173.             raise ADD_FIELD_ERROR;
  1174.         end;
  1175.     end if;
  1176.     end FIELD_STATEMENT;
  1177.  
  1178.  
  1179. -- 
  1180. --====================================================================
  1181. -- 
  1182.     procedure TEXT_STATEMENT (FORM_OPEN : BOOLEAN) is
  1183. -- 
  1184. -- Parses the "TEXT" statement that defines a text label for a form
  1185. -- by giving the label text, position, and display rendition.  If
  1186. -- the text label definition is correct, the text label is saved by
  1187. -- calling ADD_FIELD in the FORM_MANAGER.  The text statement definition
  1188. -- is copied to the listing file including any errors that are
  1189. -- detected.
  1190. -- 
  1191. -- Possible Error Messages (sent to listing file):
  1192. --          Incorrect position parameter syntax
  1193. --          Incorrect value parameter syntax
  1194. --          Invalid display rendition option
  1195. --          Invalid text statement parameter
  1196. --          Position parameter must be provided
  1197. --          Text field not contained within form boundaries
  1198. --          Value parameter must be provided
  1199. -- 
  1200.     NEXT_TOKEN     : TOKEN;
  1201.     PARAMETER      : KEYWORD;
  1202.     TEXT_VALUE     : KEYWORD;
  1203.     TEXT_RENDITION : FORM_MANAGER.FIELD_RENDITIONS;
  1204.     VALUE_STRING   : STRING (1 .. 80);
  1205.     VALUE_LENGTH   : NATURAL;
  1206.     VALUE_SET      : BOOLEAN;
  1207.     POSITION_SET   : BOOLEAN;
  1208.     POSITION_ROW   : FORM_TYPES.ROW_RANGE;
  1209.     POSITION_COL   : FORM_TYPES.COLUMN_RANGE;
  1210.     begin
  1211. -- 
  1212. -- Default parameter values
  1213. -- 
  1214.     VALUE_SET := FALSE;
  1215.     POSITION_SET := FALSE;
  1216.     TEXT_RENDITION := FORM_TYPES.PRIMARY_RENDITION;
  1217. -- 
  1218. -- Process each parameter encountered in turn
  1219. -- 
  1220.     loop
  1221.         GET_PARAMETER (PARAMETER);
  1222.         case PARAMETER is
  1223.         when VALUE => 
  1224.             CHECK_TOKEN (TEXT_STRING);
  1225.             VALUE_STRING := CURRENT_IDENTIFIER;
  1226.             VALUE_LENGTH := IDENTIFIER_LENGTH;
  1227.             VALUE_SET := TRUE;
  1228.         when POSITION => 
  1229.             GET_ROW_COL (POSITION_ROW, POSITION_COL);
  1230.             POSITION_SET := TRUE;
  1231.         when RENDITION => 
  1232.             CHECK_TOKEN (IDENTIFIER);
  1233.             TEXT_VALUE := LOOKUP_KEYWORD;
  1234.             case TEXT_VALUE is
  1235.             when PRIMARY => 
  1236.                 TEXT_RENDITION := FORM_TYPES.PRIMARY_RENDITION;
  1237.             when SECONDARY => 
  1238.                 TEXT_RENDITION := FORM_TYPES.REVERSE_RENDITION;
  1239.             when others => 
  1240.                 ERROR_MESSAGE ("Expected PRIMARY or REVERSE");
  1241.                 raise INVALID_PARAMETER_VALUE;
  1242.             end case;
  1243.         when others => 
  1244.             raise INVALID_PARAMETER;
  1245.         end case;
  1246. -- 
  1247. -- Next token should be a comma (to continue) or a right paren (to stop)
  1248. -- 
  1249.         loop
  1250.         GET_TOKEN (NEXT_TOKEN);
  1251.         exit when NEXT_TOKEN /= COMMENT;
  1252.         end loop;
  1253.         exit when NEXT_TOKEN = RIGHT_PARENTHESIS;
  1254.         if NEXT_TOKEN /= COMMA then
  1255.         ERROR_MESSAGE ("Expected ',' or ')'");
  1256.         raise UNEXPECTED_TOKEN;
  1257.         end if;
  1258.     end loop;
  1259. -- 
  1260. -- If no error, then complete processing with requirements check
  1261. -- 
  1262.     if not (VALUE_SET and POSITION_SET) then
  1263.         if not VALUE_SET then
  1264.         ERROR_MESSAGE ("VALUE Parameter is Missing");
  1265.         INCREMENT_COUNT_OF_ERRORS;
  1266.         end if;
  1267.         if not POSITION_SET then
  1268.         ERROR_MESSAGE ("POSITION Parameter is Missing");
  1269.         INCREMENT_COUNT_OF_ERRORS;
  1270.         end if;
  1271.     else
  1272.         begin
  1273.         if FORM_OPEN then
  1274.             FORM_MANAGER.ADD_FIELD
  1275.                (FORM       => CURRENT_FORM,
  1276.             NAME       => "",
  1277.             POSITION   => (POSITION_ROW, POSITION_COL),
  1278.             LENGTH     => VALUE_LENGTH,
  1279.             RENDITION  => TEXT_RENDITION,
  1280.             INIT_VALUE => VALUE_STRING,
  1281.             MODE       => FORM_MANAGER.CONSTANT_TEXT,
  1282.             FIELD      => CURRENT_FIELD);
  1283.         else
  1284.             NOTE_MESSAGE ("TEXT Statement Correct but FORM Not Open");
  1285.             if ERROR_COUNT = 0 then  ERROR_COUNT := 1;  end if;
  1286.         end if;
  1287.         exception
  1288.         when FORM_MANAGER.FIELD_EXTENDS_PAST_FORM |
  1289.              FORM_MANAGER.POSITION_OUT_OF_FORM_RANGE => 
  1290.             ERROR_MESSAGE ("Text field not within form boundary");
  1291.         when FORM_MANAGER.FIELD_OVERLAP_OCCURRED => 
  1292.             ERROR_MESSAGE ("Text field overlaps another field");
  1293.         when others => 
  1294.             raise ADD_FIELD_ERROR;
  1295.         end;
  1296.     end if;
  1297.     end TEXT_STATEMENT;
  1298.  
  1299. end BATCH_GENERATOR_SUPPORT;
  1300. ::::::::::
  1301. BATCH_GEN.ADA
  1302. ::::::::::
  1303. --------------------------------------------------------------------------
  1304. -- Abstract   : This is the main procedure for the Batch Generator of
  1305. --              the Form Generator system.  It inputs a form definition
  1306. --              language file, syntax checks it, and output a form
  1307. --              definition file.
  1308. --------------------------------------------------------------------------
  1309.  
  1310. with TEXT_IO;
  1311. with BATCH_GENERATOR_SUPPORT;
  1312. use BATCH_GENERATOR_SUPPORT;
  1313. with CURRENT_EXCEPTION;
  1314.  
  1315. procedure BATCH_GEN is
  1316.  
  1317. -- 
  1318. -- Variables
  1319. -- 
  1320.     FORM_DECLARED   : BOOLEAN := FALSE; -- indicates FORM statement issued
  1321.     CURRENT_TOKEN   : TOKEN; -- token now being processed
  1322.     CURRENT_KEYWORD : KEYWORD; -- keyword now being processed
  1323.  
  1324. begin
  1325.     -- 
  1326.     -- Open input files
  1327.     -- 
  1328.     OPEN_FILES;
  1329.  
  1330.     -- 
  1331.     -- Statement Processing Loop
  1332.     -- Processes three basic statements: FORM, FIELD, TEXT
  1333.     -- 
  1334.     loop
  1335.  
  1336. -- 
  1337. -- Begin/End Block for Exceptions within main loop
  1338. -- 
  1339.     begin
  1340.  
  1341. -- 
  1342. -- Flush comments
  1343. -- 
  1344.         loop
  1345.         GET_TOKEN (CURRENT_TOKEN);
  1346.         exit when CURRENT_TOKEN /= COMMENT;
  1347.         end loop;
  1348.  
  1349.         -- 
  1350.         -- Process current token
  1351.         -- 
  1352.         if CURRENT_TOKEN = IDENTIFIER then
  1353.         -- 
  1354.         -- Current token is an identifier
  1355.         -- It must be FORM, FIELD, or TEXT
  1356.         -- 
  1357.         CURRENT_KEYWORD := LOOKUP_KEYWORD;
  1358.         -- 
  1359.         -- Process FORM, FIELD and TEXT, and other Keywords
  1360.         -- 
  1361.         case CURRENT_KEYWORD is
  1362.             when FORM => 
  1363. -- 
  1364. -- FORM may be declared only once
  1365. -- 
  1366.             if not FORM_DECLARED then
  1367.                 -- 
  1368.                 -- Left Paren must be first non-comment token
  1369.                 -- after FORM statement
  1370.                 -- 
  1371.                 CHECK_TOKEN (LEFT_PARENTHESIS);
  1372.                 FORM_STATEMENT;
  1373.                 FORM_DECLARED := TRUE;
  1374.             else
  1375.                 ERROR_MESSAGE ("Multiple FORM Statements");
  1376.                 INCREMENT_COUNT_OF_ERRORS;
  1377.                 FLUSH_STATEMENT;
  1378.             end if;
  1379.             when FIELD | TEXT => 
  1380. -- 
  1381. -- Left Paren must be first non-comment token after
  1382. -- FIELD or TEXT statements
  1383. -- 
  1384.             CHECK_TOKEN (LEFT_PARENTHESIS);
  1385.             if CURRENT_KEYWORD = FIELD then
  1386.                 FIELD_STATEMENT (FORM_DECLARED);
  1387.             else
  1388.                 TEXT_STATEMENT (FORM_DECLARED);
  1389.             end if;
  1390.             when others => 
  1391.             ERROR_MESSAGE
  1392.                ("Expected FORM, FIELD, or TEXT Statement");
  1393.             INCREMENT_COUNT_OF_ERRORS;
  1394.             FLUSH_STATEMENT;
  1395.         end case;
  1396.         else
  1397. -- 
  1398. -- Current token is not an identifier
  1399. -- It must be a semicolon; else, we have an error
  1400. -- 
  1401.         if CURRENT_TOKEN /= SEMICOLON then
  1402.             ERROR_MESSAGE ("Expected Identifier");
  1403.             INCREMENT_COUNT_OF_ERRORS;
  1404.         end if;
  1405.         end if;
  1406. -- 
  1407. -- Exception Processing for main loop
  1408. -- 
  1409.     exception
  1410.         when UNKNOWN_KEYWORD => 
  1411.         ERROR_MESSAGE ("Unrecognized Keyword Encountered");
  1412.         INCREMENT_COUNT_OF_ERRORS;
  1413.         FLUSH_STATEMENT;
  1414.         when UNKNOWN_TOKEN => 
  1415.         ERROR_MESSAGE ("Unrecognized Token Encountered");
  1416.         INCREMENT_COUNT_OF_ERRORS;
  1417.         FLUSH_STATEMENT;
  1418.         when INVALID_IDENTIFIER => 
  1419.         ERROR_MESSAGE ("Invalid Format for Identifier");
  1420.         INCREMENT_COUNT_OF_ERRORS;
  1421.         FLUSH_STATEMENT;
  1422.         when INVALID_NUMBER => 
  1423.         ERROR_MESSAGE ("Invalid Format for Number");
  1424.         INCREMENT_COUNT_OF_ERRORS;
  1425.         FLUSH_STATEMENT;
  1426.         when INVALID_STRING => 
  1427.         ERROR_MESSAGE ("Invalid Format for String");
  1428.         INCREMENT_COUNT_OF_ERRORS;
  1429.         FLUSH_STATEMENT;
  1430.         when INVALID_PARAMETER => 
  1431.         ERROR_MESSAGE ("Invalid Parameter");
  1432.         INCREMENT_COUNT_OF_ERRORS;
  1433.         FLUSH_STATEMENT;
  1434.         when INVALID_PARAMETER_VALUE => 
  1435.         INCREMENT_COUNT_OF_ERRORS;
  1436.         FLUSH_STATEMENT;
  1437.         when UNEXPECTED_TOKEN => 
  1438.         INCREMENT_COUNT_OF_ERRORS;
  1439.         FLUSH_STATEMENT;
  1440.         when END_OF_INPUT_FILE => 
  1441.         exit;
  1442.         when ADD_FIELD_ERROR => 
  1443.         ERROR_MESSAGE ("Error in Adding Field to Form");
  1444.         INCREMENT_COUNT_OF_ERRORS;
  1445.         FLUSH_STATEMENT;
  1446.         when CREATE_FORM_ERROR => 
  1447.         ERROR_MESSAGE ("Error in Creating Form");
  1448.         INCREMENT_COUNT_OF_ERRORS;
  1449.         FLUSH_STATEMENT;
  1450.         when others => 
  1451.         ERROR_MESSAGE ("Unknown Exception Raised");
  1452.         INCREMENT_COUNT_OF_ERRORS;
  1453.         FLUSH_STATEMENT;
  1454.         TEXT_IO.PUT_LINE (CURRENT_EXCEPTION.NAME); -- DEBUG
  1455.     end;
  1456.     end loop;
  1457.  
  1458.     PRINT_COUNT_OF_ERRORS;
  1459.     CLOSE_FILES;
  1460.  
  1461. exception
  1462.     when FILE_INIT_ERROR => 
  1463.     TEXT_IO.PUT_LINE ("File Name/Open/Create Error");
  1464.     when others => 
  1465.     ERROR_MESSAGE ("Abnormal Error Condition");
  1466. end BATCH_GEN;
  1467.  
  1468. pragma MAIN;
  1469. ::::::::::
  1470. COMMANDS.ADA
  1471. ::::::::::
  1472. separate (EDITOR)
  1473. procedure COM_LINE -------------------------------------------------------------------------
  1474. -- Abstract   : This procedure presents and services the Command Line of
  1475. --              of the Form Editor.  This Command Line is an alternative
  1476. --              method of invoking the editor commands.  This Command Line
  1477. --              provides command completion.  This command line can only
  1478. --              be invoked using a single keystroke operation.
  1479. -------------------------------------------------------------------------
  1480. -- Parameters : none.
  1481. -------------------------------------------------------------------------
  1482. -- Algorithm  : The command completion of this Command Line is completion
  1483. --              which is triggered by blanks or the return key.  Upon
  1484. --              encountering one of these delimiters, the command will be
  1485. --              completed as far as possible given the current input.
  1486. -------------------------------------------------------------------------
  1487.       is
  1488.  
  1489.     SIZE                    : TERMINAL_INTERFACE.SCREEN_POSITION;
  1490.     MAX_COMMAND_LINE_LENGTH : constant INTEGER := 16;
  1491.  
  1492.     subtype COMMAND_LINE_RANGE is INTEGER range 1 .. MAX_COMMAND_LINE_LENGTH;
  1493.     subtype COMMAND_STRING     is STRING (COMMAND_LINE_RANGE);
  1494.  
  1495.     COMMAND  : COMMAND_STRING := (COMMAND_LINE_RANGE => ' ');
  1496.  
  1497.     START    : COMMAND_LINE_RANGE;
  1498.     LENGTH   : NATURAL;
  1499.  
  1500.     CHAR     : CHARACTER;
  1501.     CHARTYPE : TERMINAL_INTERFACE.CHAR_ENUM;
  1502.     FUNCT    : TERMINAL_INTERFACE.FUNCTION_KEY_ENUM;
  1503.  
  1504. -------------------------------------------------------------------------
  1505. -- Abstract   : This procedure performs the actual completions of the
  1506. --              commands.
  1507. -------------------------------------------------------------------------
  1508. -- Parameters : COMMAND - The command string as currently recognized.
  1509. --              START   - The starting position for completion within
  1510. --                        this command string.  ( Portions may have
  1511. --                        already been completed. )
  1512. --              LENGTH  - The current length of the command string
  1513. --                        ( being measured from START above ).
  1514. -------------------------------------------------------------------------
  1515. -- Algorithm  : The command completion is triggered by either a blank that
  1516. --              separated the command words or by the return key.
  1517. -------------------------------------------------------------------------
  1518.     procedure COMMAND_COMPLETION (COMMAND : in out COMMAND_STRING;
  1519.                   START   : COMMAND_LINE_RANGE;
  1520.                   LENGTH  : in out NATURAL) is
  1521.  
  1522.     TEMPLATE : STRING (1 .. 9);
  1523.  
  1524.     INVALID_PREFIX : exception;
  1525.  
  1526. -------------------------------------------------------------------------
  1527.     -- This procedure is used to recognize characters within the COMMAND
  1528.     --   string starting at START until a blank is encountered and insuring
  1529.     --   that these character match one-for-one with the characters of the
  1530.     --   TEMPLATE, up until the blank was encountered.
  1531.  
  1532.     procedure ABSORB_CHARACTERS (COMMAND  : COMMAND_STRING;
  1533.                      START    : COMMAND_LINE_RANGE;
  1534.                      TEMPLATE : STRING) is
  1535.  
  1536.  
  1537.         COMMAND_INDEX  : COMMAND_LINE_RANGE := START;
  1538.         TEMPLATE_INDEX : INTEGER := 1;
  1539.  
  1540.     begin
  1541.  
  1542. -- Continue to match characters until a blank is encountered in COMMAND.
  1543.  
  1544.         while COMMAND (COMMAND_INDEX) /= ' ' loop
  1545.  
  1546. -- If the characters do not match, then raise an exception.
  1547.  
  1548.         if COMMAND (COMMAND_INDEX) /= TEMPLATE (TEMPLATE_INDEX) then
  1549.             raise INVALID_PREFIX;
  1550.         end if;
  1551.  
  1552.         if COMMAND_INDEX + 1 > MAX_COMMAND_LINE_LENGTH then
  1553.             exit;
  1554.         else
  1555.             TEMPLATE_INDEX := TEMPLATE_INDEX + 1;
  1556.             COMMAND_INDEX := COMMAND_INDEX + 1;
  1557.         end if;
  1558.         end loop;
  1559.  
  1560.     end ABSORB_CHARACTERS;
  1561.  
  1562. -------------------------------------------------------------------------
  1563.  
  1564.     begin
  1565.  
  1566. -- If there are no characters recognized so far, then simply return.
  1567.  
  1568.     if LENGTH = 0 then
  1569.         return;
  1570.     else
  1571.  
  1572.         case COMMAND (START) is
  1573.         when 'c' | 'C' => 
  1574.             COMMAND (START) := 'c';
  1575.  
  1576.             -- If there are no characters after the 'c', then send a
  1577.             -- message
  1578.             --   back to the user indicating an ambiguous condition.
  1579.  
  1580.             if LENGTH /= 1 then
  1581.  
  1582.             case COMMAND (START + 1) is
  1583.                 when 'h' | 'H' => 
  1584.  
  1585. -- The prefix for CHARACTER has been found.
  1586.  
  1587.                 COMMAND (START + 1) := 'h';
  1588.                 TEMPLATE := "character";
  1589.                 ABSORB_CHARACTERS (COMMAND, START, TEMPLATE);
  1590.  
  1591.                 -- If the rest of the user input was matched
  1592.                 -- correctly,
  1593.                 --   then substitute the completed string.
  1594.  
  1595.                 COMMAND (START .. START + 8) := "character";
  1596.                 LENGTH := 9;
  1597.                 TERMINAL_INTERFACE.PUT_FIELD
  1598.                    ((SIZE.LINE, 10 + START - 1), 9,
  1599.                     FORM_TYPES.PRIMARY_RENDITION, "character");
  1600.                 when 'o' | 'O' => 
  1601.  
  1602. -- The prefix for COPY has been found.
  1603.  
  1604.                 COMMAND (START + 1) := 'o';
  1605.                 TEMPLATE := "copy     ";
  1606.                 ABSORB_CHARACTERS (COMMAND, START, TEMPLATE);
  1607.  
  1608.                 -- If the rest of the user input was matched
  1609.                 -- correctly,
  1610.                 --   then substitute the completed string.
  1611.  
  1612.                 COMMAND (START .. START + 4) := "copy ";
  1613.                 LENGTH := 5;
  1614.                 TERMINAL_INTERFACE.PUT_FIELD
  1615.                    ((SIZE.LINE, 10 + START - 1), 5,
  1616.                     FORM_TYPES.PRIMARY_RENDITION, "copy ");
  1617.                 when 'r' | 'R' => 
  1618.  
  1619. -- The prefix for CREATE FIELD has been found.
  1620.  
  1621.                 COMMAND (START + 1) := 'r';
  1622.                 TEMPLATE := "create   ";
  1623.                 ABSORB_CHARACTERS (COMMAND, START, TEMPLATE);
  1624.  
  1625.                 -- If the rest of the user input was matched
  1626.                 -- correctly,
  1627.                 --   then substitute the completed string.
  1628.  
  1629.                 COMMAND (START .. START + 11) := "create field";
  1630.                 LENGTH := 12;
  1631.                 TERMINAL_INTERFACE.PUT_FIELD
  1632.                    ((SIZE.LINE, 10 + START - 1), 12,
  1633.                     FORM_TYPES.PRIMARY_RENDITION,
  1634.                     "create field");
  1635.                 when others => 
  1636.                 null;
  1637.  
  1638.             end case;
  1639.  
  1640.             else
  1641.             TERMINAL_INTERFACE.PUT_MESSAGE
  1642.                ("Ambiguous - CHaracter, COpy, CReate");
  1643.  
  1644.             end if;
  1645.  
  1646.  
  1647.         when 'd' | 'D' => 
  1648.  
  1649. -- The prefix for DELETE has been found.
  1650.  
  1651.             COMMAND (START) := 'd';
  1652.             TEMPLATE := "delete   ";
  1653.             ABSORB_CHARACTERS (COMMAND, START, TEMPLATE);
  1654.  
  1655.             -- If the rest of the user input was matched correctly,
  1656.             --   then substitute the completed string.
  1657.  
  1658.             COMMAND (START .. START + 6) := "delete ";
  1659.             LENGTH := 7;
  1660.             TERMINAL_INTERFACE.PUT_FIELD
  1661.                ((SIZE.LINE, 10 + START - 1), 7,
  1662.             FORM_TYPES.PRIMARY_RENDITION, "delete ");
  1663.         when 'f' | 'F' => 
  1664.  
  1665. -- The prefix for FIELD has been found.
  1666.  
  1667.             COMMAND (START) := 'f';
  1668.             TEMPLATE := "field    ";
  1669.             ABSORB_CHARACTERS (COMMAND, START, TEMPLATE);
  1670.  
  1671.             -- If the rest of the user input was matched correctly,
  1672.             --   then substitute the completed string.
  1673.  
  1674.             COMMAND (START .. START + 4) := "field";
  1675.             LENGTH := 5;
  1676.             TERMINAL_INTERFACE.PUT_FIELD
  1677.                ((SIZE.LINE, 10 + START - 1), 5,
  1678.             FORM_TYPES.PRIMARY_RENDITION, "field");
  1679.         when 'h' | 'H' => 
  1680.  
  1681. -- The prefix for HELP has been found.
  1682.  
  1683.             COMMAND (START) := 'h';
  1684.             TEMPLATE := "help     ";
  1685.             ABSORB_CHARACTERS (COMMAND, START, TEMPLATE);
  1686.  
  1687.             -- If the rest of the user input was matched correctly,
  1688.             --   then substitute the completed string.
  1689.  
  1690.             COMMAND (START .. START + 3) := "help";
  1691.             LENGTH := 4;
  1692.             TERMINAL_INTERFACE.PUT_FIELD
  1693.                ((SIZE.LINE, 10 + START - 1), 4,
  1694.             FORM_TYPES.PRIMARY_RENDITION, "help");
  1695.         when 'i' | 'I' => 
  1696.  
  1697. -- The prefix for INSERT has been found.
  1698.  
  1699.             COMMAND (START) := 'i';
  1700.             TEMPLATE := "insert   ";
  1701.             ABSORB_CHARACTERS (COMMAND, START, TEMPLATE);
  1702.  
  1703.             -- If the rest of the user input was matched correctly,
  1704.             --   then substitute the completed string.
  1705.  
  1706.             COMMAND (START .. START + 6) := "insert ";
  1707.             LENGTH := 7;
  1708.             TERMINAL_INTERFACE.PUT_FIELD
  1709.                ((SIZE.LINE, 10 + START - 1), 7,
  1710.             FORM_TYPES.PRIMARY_RENDITION, "insert ");
  1711.         when 'l' | 'L' => 
  1712.  
  1713. -- The prefix for LINE has been found.
  1714.  
  1715.             COMMAND (START) := 'l';
  1716.             TEMPLATE := "line     ";
  1717.             ABSORB_CHARACTERS (COMMAND, START, TEMPLATE);
  1718.  
  1719.             -- If the rest of the user input was matched correctly,
  1720.             --   then substitute the completed string.
  1721.  
  1722.             COMMAND (START .. START + 3) := "line";
  1723.             LENGTH := 4;
  1724.             TERMINAL_INTERFACE.PUT_FIELD
  1725.                ((SIZE.LINE, 10 + START - 1), 4,
  1726.             FORM_TYPES.PRIMARY_RENDITION, "line");
  1727.         when 'm' | 'M' => 
  1728.             COMMAND (START) := 'm';
  1729.  
  1730.             -- If there are no characters after the 'm', then send a
  1731.             -- message
  1732.             --   back to the user indicating an ambiguous condition.
  1733.  
  1734.             if LENGTH /= 1 then
  1735.             case COMMAND (START + 1) is
  1736.                 when 'o' | 'O' => 
  1737.                 COMMAND (START + 1) := 'o';
  1738.  
  1739.                 -- If there are no characters after the 'mo',
  1740.                 -- then send a message
  1741.                 --   back to the user indicating an ambiguous
  1742.                 -- condition.
  1743.  
  1744.                 if LENGTH /= 2 then
  1745.                     case COMMAND (START + 2) is
  1746.                     when 'd' | 'D' => 
  1747.  
  1748. -- The prefix for MODIFY FIELD has been found.
  1749.  
  1750.                         COMMAND (START + 2) := 'd';
  1751.                         TEMPLATE := "modify   ";
  1752.                         ABSORB_CHARACTERS
  1753.                            (COMMAND, START, TEMPLATE);
  1754.  
  1755.                         -- If the rest of the user input was
  1756.                         -- matched correctly,
  1757.                         --   then substitute the completed
  1758.                         -- string.
  1759.  
  1760.                         COMMAND (START .. START + 11) :=
  1761.                           "modify field";
  1762.                         LENGTH := 12;
  1763.                         TERMINAL_INTERFACE.PUT_FIELD
  1764.                            ((SIZE.LINE, 10 + START - 1),
  1765.                         12, FORM_TYPES
  1766.                              .PRIMARY_RENDITION,
  1767.                         "modify field");
  1768.                     when 'v' | 'V' => 
  1769.  
  1770. -- The prefix for MOVE has been found.
  1771.  
  1772.                         COMMAND (START + 2) := 'v';
  1773.                         TEMPLATE := "move     ";
  1774.                         ABSORB_CHARACTERS
  1775.                            (COMMAND, START, TEMPLATE);
  1776.  
  1777.                         -- If the rest of the user input was
  1778.                         -- matched correctly,
  1779.                         --   then substitute the completed
  1780.                         -- string.
  1781.  
  1782.                         COMMAND (START .. START + 4) :=
  1783.                           "move ";
  1784.                         LENGTH := 5;
  1785.                         TERMINAL_INTERFACE.PUT_FIELD
  1786.                            ((SIZE.LINE, 10 + START - 1),
  1787.                         5, FORM_TYPES.PRIMARY_RENDITION,
  1788.                         "move ");
  1789.                     when others => 
  1790.                         null;
  1791.  
  1792.                     end case;
  1793.  
  1794.                 else
  1795.                     TERMINAL_INTERFACE.PUT_MESSAGE
  1796.                        ("Ambiguous - MODify or MOVe ?");
  1797.  
  1798.                 end if;
  1799.  
  1800.                 when others => 
  1801.                 null;
  1802.  
  1803.             end case;
  1804.  
  1805.             else
  1806.             TERMINAL_INTERFACE.PUT_MESSAGE
  1807.                ("Ambiguous - MODify or MOVe ?");
  1808.  
  1809.             end if;
  1810.  
  1811.         when 'q' | 'Q' => 
  1812.  
  1813. -- The prefix for QUIT has been found.
  1814.  
  1815.             COMMAND (START) := 'q';
  1816.             TEMPLATE := "quit     ";
  1817.             ABSORB_CHARACTERS (COMMAND, START, TEMPLATE);
  1818.  
  1819.             -- If the rest of the user input was matched correctly,
  1820.             --   then substitute the completed string.
  1821.  
  1822.             COMMAND (START .. START + 3) := "quit";
  1823.             LENGTH := 4;
  1824.             TERMINAL_INTERFACE.PUT_FIELD
  1825.                ((SIZE.LINE, 10 + START - 1), 4,
  1826.             FORM_TYPES.PRIMARY_RENDITION, "quit");
  1827.  
  1828.         when 'r' | 'R' => 
  1829.  
  1830. -- The prefix for RUBOUT CHARACTER has been found.
  1831.  
  1832.             COMMAND (START) := 'r';
  1833.             TEMPLATE := "rubout   ";
  1834.             ABSORB_CHARACTERS (COMMAND, START, TEMPLATE);
  1835.  
  1836.             -- If the rest of the user input was matched correctly,
  1837.             --   then substitute the completed string.
  1838.  
  1839.             COMMAND (START .. START + 15) := "rubout character";
  1840.             LENGTH := 16;
  1841.             TERMINAL_INTERFACE.PUT_FIELD
  1842.                ((SIZE.LINE, 10 + START - 1), 16,
  1843.             FORM_TYPES.PRIMARY_RENDITION, "rubout character");
  1844.  
  1845.         when others => 
  1846.             null;
  1847.  
  1848.         end case;
  1849.  
  1850.     end if;
  1851.  
  1852.     exception
  1853.     when INVALID_PREFIX => 
  1854.         TERMINAL_INTERFACE.PUT_MESSAGE
  1855.            ("Command completion failed for current command string.");
  1856.  
  1857.     end COMMAND_COMPLETION;
  1858.  
  1859.  
  1860. -------------------------------------------------------------------------
  1861. -- Abstract   : This function compared two string to see if the contents
  1862. --              are identical.  The command string is allowed to have
  1863. --              trailing blanks.
  1864. -------------------------------------------------------------------------
  1865. -- Parameters : TEMPLATE - The string begin compared to.
  1866. --              COMMAND  - The command string which is being compared.
  1867. -------------------------------------------------------------------------
  1868.     function EQUAL_STRINGS (TEMPLATE, COMMAND : STRING) return BOOLEAN is
  1869.  
  1870.     INDEX : INTEGER := 1;
  1871.  
  1872.     begin
  1873.     while INDEX <= TEMPLATE'LENGTH loop
  1874.         if TEMPLATE (INDEX) /= COMMAND (INDEX) then
  1875.         return FALSE;
  1876.         end if;
  1877.         INDEX := INDEX + 1;
  1878.     end loop;
  1879.     return TRUE;
  1880.     end EQUAL_STRINGS;
  1881.  
  1882. -------------------------------------------------------------------------
  1883.  
  1884. begin
  1885.     TERMINAL_INTERFACE.SCREEN_SIZE (SIZE);
  1886.  
  1887. -- Put the command line prompt on the screen.
  1888.  
  1889.     TERMINAL_INTERFACE.PUT_FIELD
  1890.        ((SIZE.LINE, 1), 9, FORM_TYPES.PRIMARY_RENDITION, "Command: ");
  1891.     START := 1;
  1892.     LENGTH := 0;
  1893.  
  1894. -- Keep retrieving characters until the return key is encountered.
  1895.  
  1896.     loop
  1897.  
  1898.     -- Position cursor and retrieve next character.
  1899.  
  1900.     TERMINAL_INTERFACE.PUT_CURSOR ((SIZE.LINE, 10 + START + LENGTH - 1));
  1901.     TERMINAL_INTERFACE.GET_CHARACTER (CHARTYPE, CHAR, FUNCT);
  1902.  
  1903.     case CHARTYPE is
  1904.  
  1905.         when TERMINAL_INTERFACE.TIMEOUT =>  null;
  1906.  
  1907.         when TERMINAL_INTERFACE.FUNC_TYPE => 
  1908.  
  1909. -- Only the RETURN_KEY and RUBOUT function keys are legal.
  1910.  
  1911.         case FUNCT is
  1912.  
  1913. -- Exit upon receiving the return key.
  1914.  
  1915.             when TERMINAL_INTERFACE.RETURN_KEY => 
  1916.             exit;
  1917.  
  1918.             -- Rubout the previous character.
  1919.  
  1920.             when TERMINAL_INTERFACE.RUBOUT => 
  1921.             if START > 1 and then LENGTH = 1 then
  1922.                 LENGTH := START;
  1923.                 START := 1; -- Mark beginning of first command word.
  1924.             end if;
  1925.  
  1926.             if LENGTH > 0 then
  1927.                 COMMAND (START + LENGTH - 1) := ' ';
  1928.                 LENGTH := LENGTH - 1;
  1929.             end if;
  1930.  
  1931.             TERMINAL_INTERFACE.PUT_CHARACTER
  1932.                (' ', (SIZE.LINE, 10 + START + LENGTH - 1));
  1933.  
  1934.             when others =>  null;
  1935.  
  1936.         end case;
  1937.  
  1938.         when TERMINAL_INTERFACE.CHAR_TYPE => 
  1939.  
  1940. -- Only the alphabet and the blank character are legal.
  1941.  
  1942.         case CHAR is
  1943.  
  1944. -- Insert the alphabet character into the current command string.
  1945.  
  1946.             when 'a' .. 'z' | 'A' .. 'Z' => 
  1947.  
  1948.             if LENGTH + 1 > MAX_COMMAND_LINE_LENGTH then
  1949.                 TERMINAL_INTERFACE.PUT_MESSAGE
  1950.                    ("Maximum command length reached!");
  1951.             else
  1952.                 if LENGTH /= 0 and then COMMAND (LENGTH) = ' ' then
  1953.                 START := LENGTH + 1;
  1954.                 LENGTH := 1;
  1955.                 else
  1956.                 LENGTH := LENGTH + 1;
  1957.                 end if;
  1958.  
  1959.                 COMMAND (START + LENGTH - 1) := CHAR;
  1960.                 TERMINAL_INTERFACE.PUT_CHARACTER
  1961.                    (CHAR, (SIZE.LINE, 10 + START + LENGTH - 2));
  1962.             end if;
  1963.  
  1964.             -- Perform command completion upon receiving the blank
  1965.             -- character.
  1966.  
  1967.             when ' ' => 
  1968.             COMMAND_COMPLETION (COMMAND, START, LENGTH);
  1969.  
  1970.             when others =>  null;
  1971.  
  1972.         end case;
  1973.  
  1974.     end case;
  1975.  
  1976.     end loop;
  1977.  
  1978.  
  1979.     COMMAND_COMPLETION (COMMAND, START, LENGTH);
  1980.  
  1981.     TERMINAL_INTERFACE.SPLIT_DISPLAY (SIZE);
  1982.  
  1983.     TERMINAL_INTERFACE.PUT_CURSOR
  1984.        ((CURSOR.LINE + CURRENT_POSITION.LINE - 1,
  1985.      CURSOR.COLUMN + CURRENT_POSITION.COLUMN - 1));
  1986.  
  1987. -- Now, attempt to match the completed command string.  If recognized, then
  1988. --  execute the respective command.  If the command line is simply a blank,
  1989. --  then do nothing.  Otherwise, display an Invalid Command message.
  1990.  
  1991.     if EQUAL_STRINGS ("copy field", COMMAND) then
  1992.     DUPLICATE_FIELD (COPY);
  1993.  
  1994.     elsif EQUAL_STRINGS ("copy line", COMMAND) then
  1995.     DUPLICATE_LINE (COPY);
  1996.  
  1997.     elsif EQUAL_STRINGS ("create field", COMMAND) then
  1998.     MODIFY_FIELD (CREATE);
  1999.  
  2000.     elsif EQUAL_STRINGS ("delete character", COMMAND) then
  2001.     DELETE_CHARACTER;
  2002.  
  2003.     elsif EQUAL_STRINGS ("delete field", COMMAND) then
  2004.     DELETE_FIELD;
  2005.  
  2006.     elsif EQUAL_STRINGS ("delete line", COMMAND) then
  2007.     DELETE_LINE;
  2008.  
  2009.     elsif EQUAL_STRINGS ("help", COMMAND) then
  2010.     HELP;
  2011.  
  2012.     elsif EQUAL_STRINGS ("insert character", COMMAND) then
  2013.     INSERT_CHARACTER;
  2014.  
  2015.     elsif EQUAL_STRINGS ("insert line", COMMAND) then
  2016.     INSERT_LINE;
  2017.  
  2018.     elsif EQUAL_STRINGS ("modify field", COMMAND) then
  2019.     MODIFY_FIELD (MODIFY);
  2020.  
  2021.     elsif EQUAL_STRINGS ("move field", COMMAND) then
  2022.     DUPLICATE_FIELD (MOVE);
  2023.  
  2024.     elsif EQUAL_STRINGS ("move line", COMMAND) then
  2025.     DUPLICATE_LINE (MOVE);
  2026.  
  2027.     elsif EQUAL_STRINGS ("quit", COMMAND) then
  2028.     raise EDITOR_DRIVER_EXIT;
  2029.  
  2030.     elsif EQUAL_STRINGS ("rubout character", COMMAND) then
  2031.     RUBOUT_CHARACTER;
  2032.  
  2033.     elsif COMMAND (1) /= ' ' then
  2034.     TERMINAL_INTERFACE.PUT_MESSAGE ("Invalid command.");
  2035.  
  2036.     else
  2037.     null;
  2038.     end if;
  2039.  
  2040. exception
  2041.     when CONSTRAINT_ERROR => 
  2042.     TERMINAL_INTERFACE.PUT_MESSAGE
  2043.        ("Constraint error occurred in Command Line");
  2044.  
  2045. end COM_LINE;
  2046. separate (EDITOR)
  2047. procedure MODIFY_FIELD -------------------------------------------------------------------------
  2048. -- Abstract   : This procedure implements the Create Field and Modify
  2049. --              Field operations on the Form Editor.  These operations
  2050. --              are only operational when invoked with the cursor
  2051. --              positioned somewhere within a field.  The command line
  2052. --              syntax for these operations are:  CR and MOD F, respectively.
  2053. -------------------------------------------------------------------------
  2054. -- Parameters : MOD_TYPE - a tag indicating whether to execute the Create
  2055. --                         Field operation or the Modify Field operation.
  2056. -------------------------------------------------------------------------
  2057. -- Algorithm  : This procedure requests information regarding the creation
  2058. --              or modification of fields by using the Form Executor and
  2059. --              predefined forms to service the user interaction.
  2060. -------------------------------------------------------------------------
  2061.       (MOD_TYPE : FIELD_MODIFICATION_TYPE) is
  2062.  
  2063.     TEMP_FIELD                 : FORM_MANAGER.FIELD_ACCESS;
  2064.     TEMP_NAME                  : FORM_MANAGER.FIELD_NAME;
  2065.     TEMP_POS                   : FORM_MANAGER.FIELD_POSITION;
  2066.     TEMP_LEN                   : FORM_MANAGER.FIELD_LENGTH;
  2067.     TEMP_REND                  : FORM_MANAGER.FIELD_RENDITIONS;
  2068.     TEMP_LIMITS                : FORM_MANAGER.CHAR_TYPE;
  2069.     TEMP_INIT                  : FORM_MANAGER.FIELD_VALUE;
  2070.     TEMP_VAL                   : FORM_MANAGER.FIELD_VALUE;
  2071.     TEMP_MODE                  : FORM_MANAGER.FIELD_MODE;
  2072.  
  2073.     END_FIELD                  : FORM_MANAGER.FIELD_ACCESS;
  2074.  
  2075.     NEW_FIELD                  : FORM_MANAGER.FIELD_ACCESS;
  2076.     NEW_NAME                   : FORM_MANAGER.FIELD_NAME;
  2077.     NEW_POS                    : FORM_MANAGER.FIELD_POSITION;
  2078.  
  2079.     OLD_LEN                    : FORM_MANAGER.FIELD_LENGTH;
  2080.     OLD_REND                   : FORM_MANAGER.FIELD_RENDITIONS;
  2081.     OLD_LIMITS                 : FORM_MANAGER.CHAR_TYPE;
  2082.     OLD_INIT                   : FORM_MANAGER.FIELD_VALUE;
  2083.     OLD_MODE                   : FORM_MANAGER.FIELD_MODE;
  2084.  
  2085.     ADD_IT                     : BOOLEAN := true;
  2086.     NEXT_IS_NULL, PREV_IS_NULL : BOOLEAN := false;
  2087.  
  2088.     SIZE                       : TERMINAL_INTERFACE.SCREEN_POSITION;
  2089.  
  2090. begin
  2091.     TERMINAL_INTERFACE.SCREEN_SIZE (SIZE);
  2092.  
  2093.     -- If Modify Field, then save the old field's attributes and values.
  2094.  
  2095.     if MOD_TYPE = MODIFY then
  2096.     FIELD := FORM_MANAGER.GET_FIELD_POINTER (CURRENT_FORM, CURSOR);
  2097.     FORM_MANAGER.GET_FIELD_INFO
  2098.        (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS, INIT_VALUE,
  2099.         VALUE, MODE);
  2100.  
  2101.     OLD_LEN := LENGTH;
  2102.     OLD_REND := RENDITION;
  2103.     OLD_LIMITS := CHAR_LIMITS;
  2104.     OLD_INIT := INIT_VALUE;
  2105.     OLD_MODE := MODE;
  2106.  
  2107.     if MODE = FORM_MANAGER.CONSTANT_TEXT then
  2108.         raise FORM_MANAGER.FIELD_POSITION_NOT_FOUND;
  2109.     end if;
  2110.  
  2111.     -- Use the Form Executor to request the new field information
  2112.     --   from the user.
  2113.  
  2114.     FORMS.GET_FIELD_INFO
  2115.        (NAME, LENGTH, CHAR_LIMITS, MODE, RENDITION, INIT_VALUE, false);
  2116.  
  2117.     -- Delete the old field.
  2118.  
  2119.     FORM_MANAGER.DELETE_FIELD (FIELD);
  2120.  
  2121.     else
  2122.  
  2123.     -- Use the Form Executor to request the new field information
  2124.     --   from the user.
  2125.  
  2126.     FORMS.GET_FIELD_INFO
  2127.        (NAME, LENGTH, CHAR_LIMITS, MODE, RENDITION, INIT_VALUE, true);
  2128.     POSITION := CURSOR;
  2129.     end if;
  2130.  
  2131.     -- Add the new field.
  2132.  
  2133.     loop
  2134.     begin
  2135.         FORM_MANAGER.ADD_FIELD
  2136.            (CURRENT_FORM, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS,
  2137.         INIT_VALUE, MODE, FIELD);
  2138.         exit;
  2139.     exception
  2140.  
  2141. -- A duplicate field name has been found, if Create Field then
  2142. --   prompt user for another field name.
  2143.  
  2144.         when FORM_MANAGER.DUPLICATE_FIELD_NAME => 
  2145.         if MOD_TYPE = CREATE then
  2146.             TERMINAL_INTERFACE.PUT_MESSAGE
  2147.                ("Field name already exists -- choose another");
  2148.             delay 0.5;
  2149.             TERMINAL_INTERFACE.SPLIT_DISPLAY (SIZE);
  2150.             FORMS.GET_FIELD_NAME (NAME);
  2151.         else
  2152.             raise;
  2153.         end if;
  2154.     end;
  2155.     end loop;
  2156.  
  2157.     -- Redisplay the entire form.  This is to get rid of the field
  2158.     --   creation/modification menu.
  2159.  
  2160.     begin
  2161.     TERMINAL_INTERFACE.CLEAR_SCREEN;
  2162.  
  2163.     FIELD := FORM_MANAGER.GET_FIRST_FIELD (CURRENT_FORM);
  2164.     loop
  2165.         FORM_MANAGER.GET_FIELD_INFO
  2166.            (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS,
  2167.         INIT_VALUE, VALUE, MODE);
  2168.         POSITION.LINE := POSITION.LINE + CURRENT_POSITION.LINE - 1;
  2169.         POSITION.COLUMN := POSITION.COLUMN + CURRENT_POSITION.COLUMN - 1;
  2170.  
  2171.         TRANSFORM_AND_PUT_FIELD
  2172.            (POSITION, LENGTH, RENDITION, CHAR_LIMITS, INIT_VALUE, MODE);
  2173.  
  2174.         FIELD := FORM_MANAGER.GET_NEXT_FIELD (FIELD);
  2175.     end loop;
  2176.  
  2177.     exception
  2178.     when FORM_MANAGER.FIELD_NOT_FOUND =>  null;
  2179.     end;
  2180.  
  2181.  
  2182. exception
  2183.     when FORM_MANAGER.DUPLICATE_FIELD_NAME => 
  2184.  
  2185.     TERMINAL_INTERFACE.PUT_MESSAGE ("Duplicate field name encountered");
  2186.     delay 1.0;
  2187.  
  2188.     -- If Modify Field, then add the old field back.
  2189.  
  2190.     if MOD_TYPE = MODIFY then
  2191.         FORM_MANAGER.ADD_FIELD
  2192.            (CURRENT_FORM, NAME, POSITION, OLD_LEN, OLD_REND, OLD_LIMITS,
  2193.         OLD_INIT, OLD_MODE, FIELD);
  2194.     end if;
  2195.  
  2196.     -- Redisplay the entire form.
  2197.  
  2198.     begin
  2199.         TERMINAL_INTERFACE.CLEAR_SCREEN;
  2200.  
  2201.         FIELD := FORM_MANAGER.GET_FIRST_FIELD (CURRENT_FORM);
  2202.         loop
  2203.         FORM_MANAGER.GET_FIELD_INFO
  2204.            (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS,
  2205.             INIT_VALUE, VALUE, MODE);
  2206.         POSITION.LINE := POSITION.LINE + CURRENT_POSITION.LINE - 1;
  2207.         POSITION.COLUMN :=
  2208.           POSITION.COLUMN + CURRENT_POSITION.COLUMN - 1;
  2209.  
  2210.         TRANSFORM_AND_PUT_FIELD
  2211.            (POSITION, LENGTH, RENDITION, CHAR_LIMITS, INIT_VALUE, MODE);
  2212.  
  2213.         FIELD := FORM_MANAGER.GET_NEXT_FIELD (FIELD);
  2214.         end loop;
  2215.  
  2216.     exception
  2217.         when FORM_MANAGER.FIELD_NOT_FOUND =>  null;
  2218.     end;
  2219.  
  2220.  
  2221.     when FORM_MANAGER.FIELD_POSITION_NOT_FOUND => 
  2222.     TERMINAL_INTERFACE.PUT_MESSAGE ("Cursor not positioned in a field!");
  2223.     delay 1.0;
  2224.  
  2225.     -- Redisplay the entire form.
  2226.  
  2227.     begin
  2228.         TERMINAL_INTERFACE.CLEAR_SCREEN;
  2229.  
  2230.         FIELD := FORM_MANAGER.GET_FIRST_FIELD (CURRENT_FORM);
  2231.         loop
  2232.         FORM_MANAGER.GET_FIELD_INFO
  2233.            (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS,
  2234.             INIT_VALUE, VALUE, MODE);
  2235.         POSITION.LINE := POSITION.LINE + CURRENT_POSITION.LINE - 1;
  2236.         POSITION.COLUMN :=
  2237.           POSITION.COLUMN + CURRENT_POSITION.COLUMN - 1;
  2238.  
  2239.         TRANSFORM_AND_PUT_FIELD
  2240.            (POSITION, LENGTH, RENDITION, CHAR_LIMITS, INIT_VALUE, MODE);
  2241.  
  2242.         FIELD := FORM_MANAGER.GET_NEXT_FIELD (FIELD);
  2243.         end loop;
  2244.  
  2245.     exception
  2246.         when FORM_MANAGER.FIELD_NOT_FOUND =>  null;
  2247.     end;
  2248.  
  2249.  
  2250.     when FORM_MANAGER.FIELD_EXTENDS_PAST_FORM => 
  2251.     TERMINAL_INTERFACE.PUT_MESSAGE ("Field extends past form!");
  2252.     delay 1.0;
  2253.  
  2254.     -- If Modify Field, then add the old field back.
  2255.  
  2256.     if MOD_TYPE = MODIFY then
  2257.         FORM_MANAGER.ADD_FIELD
  2258.            (CURRENT_FORM, NAME, POSITION, OLD_LEN, OLD_REND, OLD_LIMITS,
  2259.         OLD_INIT, OLD_MODE, FIELD);
  2260.     end if;
  2261.  
  2262.     -- Redisplay the entire form.
  2263.  
  2264.     begin
  2265.         TERMINAL_INTERFACE.CLEAR_SCREEN;
  2266.  
  2267.         FIELD := FORM_MANAGER.GET_FIRST_FIELD (CURRENT_FORM);
  2268.         loop
  2269.         FORM_MANAGER.GET_FIELD_INFO
  2270.            (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS,
  2271.             INIT_VALUE, VALUE, MODE);
  2272.         POSITION.LINE := POSITION.LINE + CURRENT_POSITION.LINE - 1;
  2273.         POSITION.COLUMN :=
  2274.           POSITION.COLUMN + CURRENT_POSITION.COLUMN - 1;
  2275.  
  2276.         TRANSFORM_AND_PUT_FIELD
  2277.            (POSITION, LENGTH, RENDITION, CHAR_LIMITS, INIT_VALUE, MODE);
  2278.  
  2279.         FIELD := FORM_MANAGER.GET_NEXT_FIELD (FIELD);
  2280.         end loop;
  2281.  
  2282.     exception
  2283.         when FORM_MANAGER.FIELD_NOT_FOUND =>  null;
  2284.     end;
  2285.  
  2286.  
  2287.     when FORM_MANAGER.FIELD_ALLOCATION_ERROR => 
  2288.     TERMINAL_INTERFACE.PUT_MESSAGE ("Memory full");
  2289.     delay 1.0;
  2290.  
  2291.     -- Redisplay the entire form.
  2292.  
  2293.     begin
  2294.         TERMINAL_INTERFACE.CLEAR_SCREEN;
  2295.  
  2296.         FIELD := FORM_MANAGER.GET_FIRST_FIELD (CURRENT_FORM);
  2297.         loop
  2298.         FORM_MANAGER.GET_FIELD_INFO
  2299.            (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS,
  2300.             INIT_VALUE, VALUE, MODE);
  2301.         POSITION.LINE := POSITION.LINE + CURRENT_POSITION.LINE - 1;
  2302.         POSITION.COLUMN :=
  2303.           POSITION.COLUMN + CURRENT_POSITION.COLUMN - 1;
  2304.  
  2305.         TRANSFORM_AND_PUT_FIELD
  2306.            (POSITION, LENGTH, RENDITION, CHAR_LIMITS, INIT_VALUE, MODE);
  2307.  
  2308.         FIELD := FORM_MANAGER.GET_NEXT_FIELD (FIELD);
  2309.         end loop;
  2310.  
  2311.     exception
  2312.         when FORM_MANAGER.FIELD_NOT_FOUND =>  null;
  2313.     end;
  2314.  
  2315.  
  2316.     when FORM_MANAGER.FIELD_OVERLAP_OCCURRED => 
  2317.  
  2318. -- When the new field overlapped existing fields AND the existing
  2319. --   fields were only text fields, then add the new field anyway.
  2320.  
  2321.  
  2322. -- Traverse through the form field list to a point where PREV_FIELD
  2323. --   is the field just before the cursor and, at the same time,
  2324. --   NEXT_FIELD is the field just after the cursor.
  2325.  
  2326.     NEXT_FIELD := FORM_MANAGER.GET_FIRST_FIELD (CURRENT_FORM);
  2327.     FORM_MANAGER.GET_FIELD_INFO
  2328.        (NEXT_FIELD, NEXT_NAME, NEXT_POS, NEXT_LEN, NEXT_REND, NEXT_LIMITS,
  2329.         NEXT_INIT, NEXT_VAL, NEXT_MODE);
  2330.     begin
  2331.         loop
  2332.         if (POSITION.LINE > NEXT_POS.LINE or else
  2333.             (POSITION.LINE = NEXT_POS.LINE and then
  2334.              POSITION.COLUMN > NEXT_POS.COLUMN)) then
  2335.             PREV_FIELD := NEXT_FIELD;
  2336.             NEXT_FIELD := FORM_MANAGER.GET_NEXT_FIELD (PREV_FIELD);
  2337.             FORM_MANAGER.GET_FIELD_INFO
  2338.                (NEXT_FIELD, NEXT_NAME, NEXT_POS, NEXT_LEN, NEXT_REND,
  2339.             NEXT_LIMITS, NEXT_INIT, NEXT_VAL, NEXT_MODE);
  2340.         else
  2341.             exit;
  2342.         end if;
  2343.         end loop;
  2344.     exception
  2345.         when FORM_MANAGER.FIELD_NOT_FOUND => 
  2346.         null;
  2347.     end;
  2348.  
  2349.     -- Check to see if PREV_FIELD is on the same line as the cursor.
  2350.     --   If not, then PREV_IS_NULL is true.
  2351.  
  2352.     begin
  2353.         FORM_MANAGER.GET_FIELD_INFO
  2354.            (PREV_FIELD, PREV_NAME, PREV_POS, PREV_LEN, PREV_REND,
  2355.         PREV_LIMITS, PREV_INIT, PREV_VAL, PREV_MODE);
  2356.         if PREV_POS.LINE /= POSITION.LINE or else
  2357.            PREV_POS.COLUMN >= POSITION.COLUMN then
  2358.         PREV_IS_NULL := true;
  2359.         end if;
  2360.     exception
  2361.         when FORM_MANAGER.NULL_FIELD_POINTER => 
  2362.         PREV_IS_NULL := true;
  2363.     end;
  2364.  
  2365.     -- Check to see if NEXT_FIELD is on the same line as the cursor.
  2366.     --   If not, then NEXT_IS_NULL is true.
  2367.  
  2368.     begin
  2369.         FORM_MANAGER.GET_FIELD_INFO
  2370.            (NEXT_FIELD, NEXT_NAME, NEXT_POS, NEXT_LEN, NEXT_REND,
  2371.         NEXT_LIMITS, NEXT_INIT, NEXT_VAL, NEXT_MODE);
  2372.         if NEXT_POS.LINE /= POSITION.LINE then
  2373.         NEXT_IS_NULL := true;
  2374.         end if;
  2375.     exception
  2376.         when FORM_MANAGER.NULL_FIELD_POINTER => 
  2377.         NEXT_IS_NULL := true;
  2378.     end;
  2379.  
  2380.     -- Check to see if the field to be added overlaps any non-text
  2381.     --   fields, either before it or after it.
  2382.  
  2383.     if not PREV_IS_NULL and then
  2384.        (PREV_POS.COLUMN + PREV_LEN - 1) >= POSITION.COLUMN and then
  2385.        PREV_POS.LINE = POSITION.LINE and then
  2386.        PREV_MODE /= FORM_MANAGER.CONSTANT_TEXT then
  2387.         ADD_IT := false;
  2388.     else
  2389.         begin
  2390.         END_FIELD := NEXT_FIELD; -- END_FIELD indicates the last field
  2391.                      --   that FIELD overlaps
  2392.         TEMP_FIELD := NEXT_FIELD;
  2393.         FORM_MANAGER.GET_FIELD_INFO
  2394.            (TEMP_FIELD, TEMP_NAME, TEMP_POS, TEMP_LEN, TEMP_REND,
  2395.             TEMP_LIMITS, TEMP_INIT, TEMP_VAL, TEMP_MODE);
  2396.         loop
  2397.             if (POSITION.COLUMN + LENGTH - 1) >=
  2398.                TEMP_POS.COLUMN and then
  2399.                POSITION.LINE = TEMP_POS.LINE and then
  2400.                TEMP_MODE /= FORM_MANAGER.CONSTANT_TEXT then
  2401.             ADD_IT := false;
  2402.             exit;
  2403.             elsif TEMP_POS.COLUMN >
  2404.               (POSITION.COLUMN + LENGTH - 1) or else
  2405.               POSITION.LINE < TEMP_POS.LINE then
  2406.             exit;
  2407.             else
  2408.             END_FIELD := TEMP_FIELD;
  2409.             TEMP_FIELD := FORM_MANAGER.GET_NEXT_FIELD (TEMP_FIELD);
  2410.             FORM_MANAGER.GET_FIELD_INFO
  2411.                (TEMP_FIELD, TEMP_NAME, TEMP_POS, TEMP_LEN,
  2412.                 TEMP_REND, TEMP_LIMITS, TEMP_INIT, TEMP_VAL,
  2413.                 TEMP_MODE);
  2414.             end if;
  2415.         end loop;
  2416.         exception
  2417.         when FORM_MANAGER.FIELD_NOT_FOUND =>  null;
  2418.         end;
  2419.     end if;
  2420.  
  2421.     -- Check to see if it is o.k. to add the field.
  2422.  
  2423.     if ADD_IT then
  2424.         if not PREV_IS_NULL and then
  2425.            (PREV_POS.COLUMN + PREV_LEN - 1) >
  2426.            (POSITION.COLUMN + LENGTH - 1) then
  2427.         TEMP_POS.COLUMN := PREV_POS.COLUMN + PREV_LEN - 1;
  2428.  
  2429.         -- Add the new field into the middle of PREV_FIELD.
  2430.  
  2431.         TEMP_POS.LINE := PREV_POS.LINE;
  2432.         FORM_MANAGER.MODIFY_FIELD_LENGTH
  2433.            (PREV_FIELD, POSITION.COLUMN - PREV_POS.COLUMN);
  2434.  
  2435.         TEMP_INIT := PREV_INIT
  2436.                     ((POSITION.COLUMN + LENGTH) -
  2437.                  PREV_POS.COLUMN + 1 .. PREV_LEN) &
  2438.                  (TEMP_POS.COLUMN - (POSITION.COLUMN + LENGTH) +
  2439.                   2 .. FORM_MANAGER.MAX_FIELD_VALUE => ' ');
  2440.  
  2441.         FORM_MANAGER.ADD_FIELD
  2442.            (CURRENT_FORM, PREV_NAME,
  2443.             (POSITION.LINE, POSITION.COLUMN + LENGTH),
  2444.             TEMP_POS.COLUMN - (POSITION.COLUMN + LENGTH) + 1,
  2445.             PREV_REND, PREV_LIMITS, TEMP_INIT, PREV_MODE, TEMP_FIELD);
  2446.  
  2447.         TRANSFORM_AND_PUT_FIELD
  2448.            ((CURRENT_POSITION.LINE + POSITION.LINE - 1,
  2449.              CURRENT_POSITION.COLUMN + POSITION.COLUMN + LENGTH - 1),
  2450.             TEMP_POS.COLUMN - (POSITION.COLUMN + LENGTH) + 1,
  2451.             PREV_REND, PREV_LIMITS, TEMP_INIT, PREV_MODE);
  2452.  
  2453.         elsif not PREV_IS_NULL and then
  2454.           (PREV_POS.COLUMN + PREV_LEN - 1) >= POSITION.COLUMN then
  2455.  
  2456.         -- The new field overlaps with the end of PREV_FIELD only.
  2457.  
  2458.         FORM_MANAGER.MODIFY_FIELD_LENGTH
  2459.            (PREV_FIELD, POSITION.COLUMN - PREV_POS.COLUMN);
  2460.         else
  2461.  
  2462. -- The new field overlaps some of the following fields.
  2463. --   So, delete the fields that the new field entirely overlaps
  2464. --   and modify the value and length of the following field that
  2465. --   is only partially covered.
  2466.  
  2467.         while NEXT_FIELD /= END_FIELD loop
  2468.             TEMP_FIELD := FORM_MANAGER.GET_NEXT_FIELD (NEXT_FIELD);
  2469.             FORM_MANAGER.DELETE_FIELD (NEXT_FIELD);
  2470.             NEXT_FIELD := TEMP_FIELD;
  2471.         end loop;
  2472.  
  2473.         begin
  2474.             TEMP_LEN := NEXT_LEN;
  2475.             NEXT_LEN :=
  2476.               (NEXT_POS.COLUMN + NEXT_LEN) - (POSITION.COLUMN + LENGTH);
  2477.             NEXT_INIT :=
  2478.               NEXT_INIT
  2479.              (POSITION.COLUMN + LENGTH - NEXT_POS.COLUMN + 1 ..
  2480.               TEMP_LEN) &
  2481.               (NEXT_LEN + 1 .. FORM_MANAGER.MAX_FIELD_VALUE => ' ');
  2482.             FORM_MANAGER.DELETE_FIELD (NEXT_FIELD);
  2483.             FORM_MANAGER.ADD_FIELD
  2484.                (CURRENT_FORM, NEXT_NAME,
  2485.             (POSITION.LINE, POSITION.COLUMN + LENGTH), NEXT_LEN,
  2486.             NEXT_REND, NEXT_LIMITS, NEXT_INIT, NEXT_MODE,
  2487.             NEXT_FIELD);
  2488.         exception
  2489.             when CONSTRAINT_ERROR => 
  2490.             FORM_MANAGER.DELETE_FIELD (NEXT_FIELD);
  2491.         end;
  2492.         end if;
  2493.  
  2494.         FORM_MANAGER.ADD_FIELD
  2495.            (CURRENT_FORM, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS,
  2496.         INIT_VALUE, MODE, FIELD);
  2497.  
  2498.         -- Update the terminal display.
  2499.  
  2500.         NEW_POS.LINE := POSITION.LINE + CURRENT_POSITION.LINE - 1;
  2501.         NEW_POS.COLUMN := POSITION.COLUMN + CURRENT_POSITION.COLUMN - 1;
  2502.  
  2503.         TRANSFORM_AND_PUT_FIELD
  2504.            (NEW_POS, LENGTH, RENDITION, CHAR_LIMITS, INIT_VALUE, MODE);
  2505.  
  2506.     else
  2507.         TERMINAL_INTERFACE.PUT_MESSAGE
  2508.            ("New field overlaps existing fields!");
  2509.         delay 1.0;
  2510.         TERMINAL_INTERFACE.PUT_MESSAGE ("Not creating new field!!");
  2511.  
  2512.         -- If Modify Field, the add the old field back again.
  2513.  
  2514.         if MOD_TYPE = MODIFY then
  2515.         FORM_MANAGER.ADD_FIELD
  2516.            (CURRENT_FORM, NAME, POSITION, OLD_LEN, OLD_REND,
  2517.             OLD_LIMITS, OLD_INIT, OLD_MODE, FIELD);
  2518.         end if;
  2519.     end if;
  2520.  
  2521.     -- Redisplay the entire form.
  2522.  
  2523.     begin
  2524.         TERMINAL_INTERFACE.CLEAR_SCREEN;
  2525.  
  2526.         FIELD := FORM_MANAGER.GET_FIRST_FIELD (CURRENT_FORM);
  2527.         loop
  2528.         FORM_MANAGER.GET_FIELD_INFO
  2529.            (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS,
  2530.             INIT_VALUE, VALUE, MODE);
  2531.         POSITION.LINE := POSITION.LINE + CURRENT_POSITION.LINE - 1;
  2532.         POSITION.COLUMN :=
  2533.           POSITION.COLUMN + CURRENT_POSITION.COLUMN - 1;
  2534.  
  2535.         TRANSFORM_AND_PUT_FIELD
  2536.            (POSITION, LENGTH, RENDITION, CHAR_LIMITS, INIT_VALUE, MODE);
  2537.  
  2538.         FIELD := FORM_MANAGER.GET_NEXT_FIELD (FIELD);
  2539.         end loop;
  2540.  
  2541.     exception
  2542.         when FORM_MANAGER.FIELD_NOT_FOUND =>  null;
  2543.     end;
  2544.  
  2545. end MODIFY_FIELD;
  2546. separate (EDITOR)
  2547. procedure DUPLICATE_FIELD ------------------------------------------------------
  2548. -------------------
  2549. -- Abstract   : This procedure implements the Move Field and Copy Field
  2550. --              operations of the Form Editor.  The cursor must be within
  2551. --              the confines of a field before either of these operations
  2552. --              will work.  Command line syntax for these operations:
  2553. --              MOV F  and  CO F, respectively.
  2554. -------------------------------------------------------------------------
  2555. -- Parameters : DUP_TYPE - tag for determining whether to execute the
  2556. --                         Move Field or the Copy Field operation.
  2557. -------------------------------------------------------------------------
  2558.           (DUP_TYPE : FIELD_DUPLICATION_TYPE) is
  2559.  
  2560. -- Temporary field variables for inserting a field into the
  2561. --   middle of a text field.
  2562.  
  2563.     TEMP_FIELD                 : FORM_MANAGER.FIELD_ACCESS;
  2564.     TEMP_NAME                  : FORM_MANAGER.FIELD_NAME;
  2565.     TEMP_POS                   : FORM_MANAGER.FIELD_POSITION;
  2566.     TEMP_LEN                   : FORM_MANAGER.FIELD_LENGTH;
  2567.     TEMP_REND                  : FORM_MANAGER.FIELD_RENDITIONS;
  2568.     TEMP_LIMITS                : FORM_MANAGER.CHAR_TYPE;
  2569.     TEMP_INIT                  : FORM_MANAGER.FIELD_VALUE;
  2570.     TEMP_VAL                   : FORM_MANAGER.FIELD_VALUE;
  2571.     TEMP_MODE                  : FORM_MANAGER.FIELD_MODE;
  2572.  
  2573.     END_FIELD                  : FORM_MANAGER.FIELD_ACCESS;
  2574.  
  2575.     NEW_FIELD                  : FORM_MANAGER.FIELD_ACCESS;
  2576.     NEW_NAME                   : FORM_MANAGER.FIELD_NAME;
  2577.     NEW_POS                    : FORM_MANAGER.FIELD_POSITION;
  2578.  
  2579.     ADD_IT                     : BOOLEAN := true;
  2580.  
  2581.     NEXT_IS_NULL, PREV_IS_NULL : BOOLEAN := false;
  2582.  
  2583.     SIZE                       : TERMINAL_INTERFACE.SCREEN_POSITION;
  2584.  
  2585. begin
  2586.     TERMINAL_INTERFACE.SCREEN_SIZE (SIZE);
  2587.  
  2588.     -- Check to see if the cursor positioned within a field at all.
  2589.  
  2590.     FIELD := FORM_MANAGER.GET_FIELD_POINTER (CURRENT_FORM, CURSOR);
  2591.     FORM_MANAGER.GET_FIELD_INFO
  2592.        (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS, INIT_VALUE,
  2593.         VALUE, MODE);
  2594.  
  2595.     -- Also check to see if it is a non-text field.  If not, raise
  2596.     --   an exception.
  2597.  
  2598.     if MODE = FORM_MANAGER.CONSTANT_TEXT then
  2599.         raise FORM_MANAGER.FIELD_POSITION_NOT_FOUND;
  2600.     end if;
  2601.  
  2602.     -- Request user to indicate, using the arrow keys, the beginning of the
  2603.     --   new field location.
  2604.  
  2605.     TERMINAL_INTERFACE.PUT_MESSAGE
  2606.        ("Position cursor at beginning of new field position");
  2607.     delay 1.0;
  2608.     TERMINAL_INTERFACE.PUT_MESSAGE
  2609.        ("Use the arrow keys...terminate with the return key");
  2610.     GET_CURSOR_POSITION (CURSOR, NEW_POS);
  2611.  
  2612.     -- Clear message line.
  2613.  
  2614.     TERMINAL_INTERFACE.SPLIT_DISPLAY (SIZE);
  2615.  
  2616.  
  2617.     if DUP_TYPE = MOVE then
  2618.  
  2619.         -- If Move Field, then delete field at OLD location and add it back
  2620.         --   at the NEW location.
  2621.  
  2622.         FORM_MANAGER.DELETE_FIELD (FIELD);
  2623.  
  2624.         FORM_MANAGER.ADD_FIELD
  2625.            (CURRENT_FORM, NAME, NEW_POS, LENGTH, RENDITION, CHAR_LIMITS,
  2626.             INIT_VALUE, MODE, NEW_FIELD);
  2627.  
  2628.     else
  2629.  
  2630. -- If Copy Field, then request the name of the new copied field
  2631. --   and then add the new field.
  2632.  
  2633.         loop
  2634.             begin
  2635.                 FORM_EXECUTOR.PRESENT_FORM (FORMS.FIELD_NAME_MENU);
  2636.                 FORM_EXECUTOR.QUERY_FIELD
  2637.                    (FORMS.FIELD_NAME_MENU, "Field Name", NEW_NAME);
  2638.  
  2639.                 FORM_MANAGER.ADD_FIELD
  2640.                    (CURRENT_FORM, NEW_NAME, NEW_POS, LENGTH, RENDITION,
  2641.                     CHAR_LIMITS, INIT_VALUE, MODE, NEW_FIELD);
  2642.                 exit;
  2643.             exception
  2644.                 when FORM_MANAGER.DUPLICATE_FIELD_NAME =>
  2645.                     TERMINAL_INTERFACE.PUT_MESSAGE
  2646.                        ("Field name already exists - choose another");
  2647.                     delay 0.5;
  2648.                     TERMINAL_INTERFACE.SPLIT_DISPLAY (SIZE);
  2649.             end;
  2650.         end loop;
  2651.  
  2652.     end if;
  2653.  
  2654.     -- Update the cursor position to the beginning of the new field.
  2655.  
  2656.     CURSOR := NEW_POS;
  2657.  
  2658.     -- Update the terminal display.
  2659.  
  2660.     POSITION.LINE := POSITION.LINE + CURRENT_POSITION.LINE - 1;
  2661.     POSITION.COLUMN := POSITION.COLUMN + CURRENT_POSITION.COLUMN - 1;
  2662.     NEW_POS.LINE := NEW_POS.LINE + CURRENT_POSITION.LINE - 1;
  2663.     NEW_POS.COLUMN := NEW_POS.COLUMN + CURRENT_POSITION.COLUMN - 1;
  2664.  
  2665.     if DUP_TYPE = MOVE then
  2666.         TERMINAL_INTERFACE.ERASE_FIELD (POSITION, LENGTH);
  2667.     end if;
  2668.     TRANSFORM_AND_PUT_FIELD
  2669.        (NEW_POS, LENGTH, RENDITION, CHAR_LIMITS, INIT_VALUE, MODE);
  2670.  
  2671. exception
  2672.     when FORM_MANAGER.FIELD_POSITION_NOT_FOUND =>
  2673.         TERMINAL_INTERFACE.PUT_MESSAGE ("Cursor not positioned in a field!");
  2674.  
  2675.     when FORM_MANAGER.FIELD_EXTENDS_PAST_FORM =>
  2676.  
  2677.         TERMINAL_INTERFACE.PUT_MESSAGE ("New field extends past form boundary");
  2678.         delay 1.0;
  2679.         TERMINAL_INTERFACE.PUT_MESSAGE ("Not creating new field!!");
  2680.  
  2681.         -- If Move Field, then add the old field back.
  2682.  
  2683.         if DUP_TYPE = MOVE then
  2684.             FORM_MANAGER.ADD_FIELD
  2685.                (CURRENT_FORM, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS,
  2686.                 INIT_VALUE, MODE, FIELD);
  2687.         end if;
  2688.  
  2689.         delay 1.0;
  2690.         TERMINAL_INTERFACE.SPLIT_DISPLAY (SIZE);
  2691.  
  2692.  
  2693.     when FORM_MANAGER.DUPLICATE_FIELD_NAME =>
  2694.  
  2695.         TERMINAL_INTERFACE.PUT_MESSAGE ("Duplicate field name encountered");
  2696.         delay 1.0;
  2697.         TERMINAL_INTERFACE.PUT_MESSAGE ("Not creating new field!!");
  2698.  
  2699.         -- If Move Field, then add the old field back.
  2700.  
  2701.         if DUP_TYPE = MOVE then
  2702.             FORM_MANAGER.ADD_FIELD
  2703.                (CURRENT_FORM, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS,
  2704.                 INIT_VALUE, MODE, FIELD);
  2705.         end if;
  2706.  
  2707.         delay 1.0;
  2708.         TERMINAL_INTERFACE.SPLIT_DISPLAY (SIZE);
  2709.  
  2710.  
  2711.     when FORM_MANAGER.FIELD_OVERLAP_OCCURRED =>
  2712.  
  2713. -- If the added field overlapped existing fields AND these existing
  2714. --   fields were simply TEXT fields, then add the field anyway.
  2715.  
  2716.  
  2717. -- Traverse through the field list until PREV_FIELD is the field
  2718. --   whose beginning is just before the NEW_POS, while at the
  2719. --   same time, NEXT_FIELD is the field whose beginning is just
  2720. --   after the NEW_POS in the list structure.
  2721.  
  2722.         NEXT_FIELD := FORM_MANAGER.GET_FIRST_FIELD (CURRENT_FORM);
  2723.         FORM_MANAGER.GET_FIELD_INFO
  2724.            (NEXT_FIELD, NEXT_NAME, NEXT_POS, NEXT_LEN, NEXT_REND, NEXT_LIMITS,
  2725.             NEXT_INIT, NEXT_VAL, NEXT_MODE);
  2726.         begin
  2727.             loop
  2728.                 if (NEW_POS.LINE > NEXT_POS.LINE or else
  2729.                     (NEW_POS.LINE = NEXT_POS.LINE and then
  2730.                      NEW_POS.COLUMN > NEXT_POS.COLUMN)) then
  2731.                     PREV_FIELD := NEXT_FIELD;
  2732.                     NEXT_FIELD := FORM_MANAGER.GET_NEXT_FIELD (PREV_FIELD);
  2733.                     FORM_MANAGER.GET_FIELD_INFO
  2734.                        (NEXT_FIELD, NEXT_NAME, NEXT_POS, NEXT_LEN, NEXT_REND,
  2735.                         NEXT_LIMITS, NEXT_INIT, NEXT_VAL, NEXT_MODE);
  2736.                 else
  2737.                     exit;
  2738.                 end if;
  2739.             end loop;
  2740.         exception
  2741.             when FORM_MANAGER.FIELD_NOT_FOUND =>
  2742.                 null;
  2743.         end;
  2744.  
  2745.         -- Check to see if the PREV_FIELD is on the same line as the NEW_POS.
  2746.  
  2747.  
  2748.         begin
  2749.             FORM_MANAGER.GET_FIELD_INFO
  2750.                (PREV_FIELD, PREV_NAME, PREV_POS, PREV_LEN, PREV_REND,
  2751.                 PREV_LIMITS, PREV_INIT, PREV_VAL, PREV_MODE);
  2752.             if PREV_POS.LINE /= NEW_POS.LINE or else
  2753.                PREV_POS.COLUMN >= NEW_POS.COLUMN then
  2754.                 PREV_IS_NULL := true;
  2755.             end if;
  2756.         exception
  2757.             when FORM_MANAGER.NULL_FIELD_POINTER =>
  2758.                 PREV_IS_NULL := true;
  2759.         end;
  2760.  
  2761.         -- Check to see if the NEXT_FIELD is on the same line as the NEW_POS.
  2762.         --   If not, then NEXT_IS_NULL is true.
  2763.  
  2764.         begin
  2765.             FORM_MANAGER.GET_FIELD_INFO
  2766.                (NEXT_FIELD, NEXT_NAME, NEXT_POS, NEXT_LEN, NEXT_REND,
  2767.                 NEXT_LIMITS, NEXT_INIT, NEXT_VAL, NEXT_MODE);
  2768.             if NEXT_POS.LINE /= NEW_POS.LINE then
  2769.                 NEXT_IS_NULL := true;
  2770.             end if;
  2771.         exception
  2772.             when FORM_MANAGER.NULL_FIELD_POINTER =>
  2773.                 NEXT_IS_NULL := true;
  2774.         end;
  2775.  
  2776.         -- If the previous field overlaps the new field and the previous
  2777.         --   field is not text, then don't add the new field.
  2778.  
  2779.         if not PREV_IS_NULL and then
  2780.            (PREV_POS.COLUMN + PREV_LEN - 1) >= NEW_POS.COLUMN and then
  2781.            PREV_POS.LINE = NEW_POS.LINE and then
  2782.            PREV_MODE /= FORM_MANAGER.CONSTANT_TEXT then
  2783.             ADD_IT := false;
  2784.         else
  2785.  
  2786. -- Check to see if the new field overlap ANY non-text fields
  2787. --   ahead of it.
  2788.  
  2789.             begin
  2790.                 END_FIELD := NEXT_FIELD;
  2791.                 TEMP_FIELD := NEXT_FIELD;
  2792.                 FORM_MANAGER.GET_FIELD_INFO
  2793.                    (TEMP_FIELD, TEMP_NAME, TEMP_POS, TEMP_LEN, TEMP_REND,
  2794.                     TEMP_LIMITS, TEMP_INIT, TEMP_VAL, TEMP_MODE);
  2795.                 loop
  2796.                     if (NEW_POS.COLUMN + LENGTH - 1) >= TEMP_POS.COLUMN and then
  2797.                        NEW_POS.LINE = TEMP_POS.LINE and then
  2798.                        TEMP_MODE /= FORM_MANAGER.CONSTANT_TEXT then
  2799.                         ADD_IT := false;
  2800.                         exit;
  2801.                     elsif TEMP_POS.COLUMN >
  2802.                           (NEW_POS.COLUMN + LENGTH - 1) or else
  2803.                           NEW_POS.LINE < TEMP_POS.LINE then
  2804.                         exit;
  2805.                     else
  2806.                         END_FIELD := TEMP_FIELD;
  2807.                         TEMP_FIELD := FORM_MANAGER.GET_NEXT_FIELD (TEMP_FIELD);
  2808.                         FORM_MANAGER.GET_FIELD_INFO
  2809.                            (TEMP_FIELD, TEMP_NAME, TEMP_POS, TEMP_LEN,
  2810.                             TEMP_REND, TEMP_LIMITS, TEMP_INIT, TEMP_VAL,
  2811.                             TEMP_MODE);
  2812.                     end if;
  2813.                 end loop;
  2814.             exception
  2815.                 when FORM_MANAGER.FIELD_NOT_FOUND =>  null;
  2816.             end;
  2817.         end if;
  2818.  
  2819.  
  2820.         -- If it is o.k. to add it, then ADD IT!
  2821.  
  2822.         if ADD_IT then
  2823.             if not PREV_IS_NULL and then
  2824.                (PREV_POS.COLUMN + PREV_LEN - 1) >
  2825.                (NEW_POS.COLUMN + LENGTH - 1) then
  2826.  
  2827.                 -- The new field is being inserted into the middle of the
  2828.                 --   previous field AND the previous field is a text field.
  2829.  
  2830.                 TEMP_POS.COLUMN := PREV_POS.COLUMN + PREV_LEN - 1;
  2831.                 TEMP_POS.LINE := PREV_POS.LINE;
  2832.                 FORM_MANAGER.MODIFY_FIELD_LENGTH
  2833.                    (PREV_FIELD, NEW_POS.COLUMN - PREV_POS.COLUMN);
  2834.  
  2835.                 TEMP_INIT := PREV_INIT
  2836.                                 ((NEW_POS.COLUMN + LENGTH) - PREV_POS.COLUMN +
  2837.                                  1 .. PREV_LEN) &
  2838.                              (TEMP_POS.COLUMN - (NEW_POS.COLUMN + LENGTH) + 2 ..
  2839.                               FORM_MANAGER.MAX_FIELD_VALUE => ' ');
  2840.  
  2841.                 FORM_MANAGER.ADD_FIELD
  2842.                    (CURRENT_FORM, PREV_NAME,
  2843.                     (NEW_POS.LINE, NEW_POS.COLUMN + LENGTH),
  2844.                     TEMP_POS.COLUMN - (NEW_POS.COLUMN + LENGTH) + 1,
  2845.                     PREV_REND, PREV_LIMITS, TEMP_INIT, PREV_MODE, TEMP_FIELD);
  2846.  
  2847.                 TRANSFORM_AND_PUT_FIELD
  2848.                    ((CURRENT_POSITION.LINE + NEW_POS.LINE - 1,
  2849.                      CURRENT_POSITION.COLUMN + NEW_POS.COLUMN + LENGTH - 1),
  2850.                     TEMP_POS.COLUMN - (NEW_POS.COLUMN + LENGTH) + 1,
  2851.                     PREV_REND, PREV_LIMITS, TEMP_INIT, PREV_MODE);
  2852.  
  2853.             elsif not PREV_IS_NULL and then
  2854.                   (PREV_POS.COLUMN + PREV_LEN - 1) >= NEW_POS.COLUMN then
  2855.  
  2856.  
  2857.                 -- The new field is going to overlap the end of the previous
  2858.                 --   field AND the previous field is a text field.
  2859.  
  2860.                 FORM_MANAGER.MODIFY_FIELD_LENGTH
  2861.                    (PREV_FIELD, NEW_POS.COLUMN - PREV_POS.COLUMN);
  2862.             else
  2863.  
  2864. -- The new field is going to overlap some of the next fields
  2865. --   and they are all going to be text fields.
  2866.  
  2867.                 begin
  2868.                     while NEXT_FIELD /= END_FIELD loop
  2869.                         TEMP_FIELD := FORM_MANAGER.GET_NEXT_FIELD (NEXT_FIELD);
  2870.                         FORM_MANAGER.DELETE_FIELD (NEXT_FIELD);
  2871.                         NEXT_FIELD := TEMP_FIELD;
  2872.                     end loop;
  2873.  
  2874.                     TEMP_LEN := NEXT_LEN;
  2875.                     NEXT_LEN :=
  2876.                       (NEXT_POS.COLUMN + NEXT_LEN) - (NEW_POS.COLUMN + LENGTH);
  2877.                     NEXT_INIT :=
  2878.                       NEXT_INIT
  2879.                          (NEW_POS.COLUMN + LENGTH - NEXT_POS.COLUMN + 1 ..
  2880.                           TEMP_LEN) &
  2881.                       (NEXT_LEN + 1 .. FORM_MANAGER.MAX_FIELD_VALUE => ' ');
  2882.                     FORM_MANAGER.DELETE_FIELD (NEXT_FIELD);
  2883.                     FORM_MANAGER.ADD_FIELD
  2884.                        (CURRENT_FORM, NEXT_NAME,
  2885.                         (NEW_POS.LINE, NEW_POS.COLUMN + LENGTH), NEXT_LEN,
  2886.                         NEXT_REND, NEXT_LIMITS, NEXT_INIT, NEXT_MODE,
  2887.                         NEXT_FIELD);
  2888.                 exception
  2889.                     when CONSTRAINT_ERROR =>
  2890.                         FORM_MANAGER.DELETE_FIELD (NEXT_FIELD);
  2891.                 end;
  2892.             end if;
  2893.  
  2894.             if DUP_TYPE = COPY then
  2895.                 NAME := NEW_NAME;
  2896.             end if;
  2897.  
  2898.             -- Add the new field.
  2899.  
  2900.             FORM_MANAGER.ADD_FIELD
  2901.                (CURRENT_FORM, NAME, NEW_POS, LENGTH, RENDITION, CHAR_LIMITS,
  2902.                 INIT_VALUE, MODE, FIELD);
  2903.  
  2904.             -- Update the cursor position and the terminal display.
  2905.  
  2906.             CURSOR := NEW_POS;
  2907.  
  2908.             POSITION.LINE := POSITION.LINE + CURRENT_POSITION.LINE - 1;
  2909.             POSITION.COLUMN := POSITION.COLUMN + CURRENT_POSITION.COLUMN - 1;
  2910.             NEW_POS.LINE := NEW_POS.LINE + CURRENT_POSITION.LINE - 1;
  2911.             NEW_POS.COLUMN := NEW_POS.COLUMN + CURRENT_POSITION.COLUMN - 1;
  2912.  
  2913.             if DUP_TYPE = MOVE then
  2914.                 TERMINAL_INTERFACE.ERASE_FIELD (POSITION, LENGTH);
  2915.             end if;
  2916.             TRANSFORM_AND_PUT_FIELD
  2917.                (NEW_POS, LENGTH, RENDITION, CHAR_LIMITS, INIT_VALUE, MODE);
  2918.  
  2919.             -- Clear the message line.
  2920.  
  2921.             TERMINAL_INTERFACE.SPLIT_DISPLAY (SIZE);
  2922.  
  2923.         else
  2924.             TERMINAL_INTERFACE.PUT_MESSAGE
  2925.                ("New field overlaps existing fields!");
  2926.             delay 1.0;
  2927.             TERMINAL_INTERFACE.PUT_MESSAGE ("Not creating new field!!");
  2928.  
  2929.             -- If Move Field, then add the old field back.
  2930.  
  2931.             if DUP_TYPE = MOVE then
  2932.                 FORM_MANAGER.ADD_FIELD
  2933.                    (CURRENT_FORM, NAME, POSITION, LENGTH, RENDITION,
  2934.                     CHAR_LIMITS, INIT_VALUE, MODE, FIELD);
  2935.             end if;
  2936.  
  2937.             delay 1.0;
  2938.             TERMINAL_INTERFACE.SPLIT_DISPLAY (SIZE);
  2939.  
  2940.         end if;
  2941.  
  2942. end DUPLICATE_FIELD;
  2943. separate (EDITOR)
  2944. procedure DELETE_FIELD -------------------------------------------------------------------------
  2945. -- Abstract   : This procedure implements the Delete Field operation on
  2946. --              the Form Editor.  The cursor must be placed somewhere
  2947. --              within the confines of a field before this operation will
  2948. --              work.  Command Line abbreviation:  D F
  2949. -------------------------------------------------------------------------
  2950. -- Parameters : none.
  2951. -------------------------------------------------------------------------
  2952.       is
  2953.  
  2954. begin
  2955.  
  2956.     -- Check to see if the cursor is positioned within a field.
  2957.  
  2958.     FIELD := FORM_MANAGER.GET_FIELD_POINTER (CURRENT_FORM, CURSOR);
  2959.     FORM_MANAGER.GET_FIELD_INFO
  2960.        (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS, INIT_VALUE,
  2961.     VALUE, MODE);
  2962.  
  2963.     -- Also make sure that the cursor is positioned within a non-text field.
  2964.  
  2965.     if MODE = FORM_MANAGER.CONSTANT_TEXT then
  2966.     raise FORM_MANAGER.FIELD_POSITION_NOT_FOUND;
  2967.     end if;
  2968.  
  2969.     -- Delete the field from the form structure.
  2970.  
  2971.     FORM_MANAGER.DELETE_FIELD (FIELD);
  2972.  
  2973.     -- Update the terminal display.
  2974.  
  2975.     POSITION.LINE := POSITION.LINE + CURRENT_POSITION.LINE - 1;
  2976.     POSITION.COLUMN := POSITION.COLUMN + CURRENT_POSITION.COLUMN - 1;
  2977.     TERMINAL_INTERFACE.ERASE_FIELD (POSITION, LENGTH);
  2978.  
  2979. exception
  2980.     when FORM_MANAGER.FIELD_POSITION_NOT_FOUND => 
  2981.     TERMINAL_INTERFACE.PUT_MESSAGE ("Cursor not positioned in a field!");
  2982.  
  2983. end DELETE_FIELD;
  2984. separate (EDITOR)
  2985. procedure INSERT_LINE -------------------------------------------------------------------------
  2986. -- Abstract   : This procedure implements the Insert Line operation of
  2987. --              the Form Editor.  Command line abbreviation:  I L
  2988. -------------------------------------------------------------------------
  2989. -- Parameters : none.
  2990. -------------------------------------------------------------------------
  2991. -- Algorithm  : This procedure inserts a blank line above the line that
  2992. --              the cursor was positioned on.  This line and rest of the
  2993. --              lines below it are shifted down one line.  The cursor
  2994. --              will be positioned on this new blank line.  If there
  2995. --              exists any non-text fields on the last line of the form,
  2996. --              then this insert line operation will not work.
  2997. -------------------------------------------------------------------------
  2998.       is
  2999.  
  3000.     TEMP_FIELD : FORM_MANAGER.FIELD_ACCESS;
  3001.  
  3002.     FIELDS_FOUND_ON_LAST_LINE : exception;
  3003.     CLEAR_LAST_LINE           : exception;
  3004.  
  3005. begin
  3006.  
  3007.     -- Locate the first field with a line number greater than or equal
  3008.     --   to the cursor's line number.
  3009.  
  3010.     FIELD := FORM_MANAGER.GET_FIRST_FIELD (CURRENT_FORM);
  3011.     FORM_MANAGER.GET_FIELD_INFO
  3012.        (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS, INIT_VALUE,
  3013.     VALUE, MODE);
  3014.  
  3015.     while POSITION.LINE < CURSOR.LINE loop
  3016.     FIELD := FORM_MANAGER.GET_NEXT_FIELD (FIELD);
  3017.     FORM_MANAGER.GET_FIELD_INFO
  3018.        (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS, INIT_VALUE,
  3019.         VALUE, MODE);
  3020.     end loop;
  3021.  
  3022.     TEMP_FIELD := FIELD;
  3023.  
  3024.     -- Raise an exception if there exists any fields on the last line
  3025.     --   of the form.
  3026.  
  3027.     begin
  3028.     loop
  3029.         if POSITION.LINE = CURRENT_SIZE.ROWS and then
  3030.            MODE /= FORM_MANAGER.CONSTANT_TEXT then
  3031.         raise FIELDS_FOUND_ON_LAST_LINE;
  3032.         end if;
  3033.         PREV_FIELD := FIELD;
  3034.         FIELD := FORM_MANAGER.GET_NEXT_FIELD (FIELD);
  3035.         FORM_MANAGER.GET_FIELD_INFO
  3036.            (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS,
  3037.         INIT_VALUE, VALUE, MODE);
  3038.     end loop;
  3039.     exception
  3040.     when FORM_MANAGER.FIELD_NOT_FOUND => 
  3041.         null;
  3042.     end;
  3043.  
  3044.     FIELD := PREV_FIELD;
  3045.     FORM_MANAGER.GET_FIELD_INFO
  3046.        (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS, INIT_VALUE,
  3047.     VALUE, MODE);
  3048.     begin
  3049.  
  3050. -- Clear the last line of the form.
  3051.  
  3052.     while POSITION.LINE = CURRENT_SIZE.ROWS loop
  3053.         if TEMP_FIELD = FIELD then
  3054.         raise CLEAR_LAST_LINE;
  3055.         end if;
  3056.         PREV_FIELD := FORM_MANAGER.GET_PREVIOUS_FIELD (FIELD);
  3057.         TERMINAL_INTERFACE.ERASE_FIELD
  3058.            ((POSITION.LINE + CURRENT_POSITION.LINE - 1,
  3059.          POSITION.COLUMN + CURRENT_POSITION.COLUMN - 1), LENGTH);
  3060.  
  3061.         FORM_MANAGER.DELETE_FIELD (FIELD);
  3062.         FIELD := PREV_FIELD;
  3063.         FORM_MANAGER.GET_FIELD_INFO
  3064.            (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS,
  3065.         INIT_VALUE, VALUE, MODE);
  3066.     end loop;
  3067.  
  3068.     exception
  3069.     when CLEAR_LAST_LINE => 
  3070.         FORM_MANAGER.DELETE_FIELD (FIELD);
  3071.         TERMINAL_INTERFACE.ERASE_FIELD
  3072.            ((POSITION.LINE + CURRENT_POSITION.LINE - 1,
  3073.          POSITION.COLUMN + CURRENT_POSITION.COLUMN - 1), LENGTH);
  3074.  
  3075.         raise;
  3076.     end;
  3077.  
  3078.     -- Move the rest of the fields from the end form to the cursor's line
  3079.     --   down one line position.
  3080.  
  3081.     while FIELD /= TEMP_FIELD loop
  3082.     FORM_MANAGER.GET_FIELD_INFO
  3083.        (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS, INIT_VALUE,
  3084.         VALUE, MODE);
  3085.     FORM_MANAGER.MOVE_FIELD (FIELD, (POSITION.LINE + 1, POSITION.COLUMN));
  3086.  
  3087.     FIELD := FORM_MANAGER.GET_PREVIOUS_FIELD (FIELD);
  3088.     end loop;
  3089.  
  3090.     if POSITION.LINE < CURRENT_SIZE.ROWS then
  3091.     FORM_MANAGER.GET_FIELD_INFO
  3092.        (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS, INIT_VALUE,
  3093.         VALUE, MODE);
  3094.     FORM_MANAGER.MOVE_FIELD (FIELD, (POSITION.LINE + 1, POSITION.COLUMN));
  3095.     end if;
  3096.  
  3097.     -- Update the terminal display.
  3098.  
  3099.     TERMINAL_INTERFACE.SPLIT_DISPLAY
  3100.        ((CURRENT_POSITION.LINE + CURSOR.LINE - 1,
  3101.      CURRENT_POSITION.COLUMN + CURSOR.COLUMN - 1));
  3102.  
  3103. exception
  3104.     when FORM_MANAGER.FIELD_NOT_FOUND =>  null;
  3105.  
  3106.     when FIELDS_FOUND_ON_LAST_LINE => 
  3107.     TERMINAL_INTERFACE.PUT_MESSAGE ("Must clear field from last line!");
  3108.  
  3109.     when CLEAR_LAST_LINE => 
  3110.     TERMINAL_INTERFACE.SPLIT_DISPLAY
  3111.        ((CURRENT_POSITION.LINE + CURSOR.LINE - 1,
  3112.          CURRENT_POSITION.COLUMN + CURSOR.COLUMN - 1));
  3113.  
  3114. end INSERT_LINE;
  3115. separate (EDITOR)
  3116. procedure DUPLICATE_LINE -------------------------------------------------------
  3117. ------------------
  3118. -- Abstract   : This procedure implements the Move Line and Copy Line
  3119. --              operations of the Form Editor.  The syntax for these
  3120. --              commands are:  MOV L  and  CO L, respectively.
  3121. -------------------------------------------------------------------------
  3122. -- Parameters : DUP_TYPE - tag for determining whether to execute the
  3123. --                         Move Line or Copy Line command.
  3124. -------------------------------------------------------------------------
  3125. -- Algorithm  : This procedure either moves or copies a form line.
  3126. --              The move and copy operations are almost identical except
  3127. --              that the copy does not delete the copied line and it
  3128. --              also request new field names for the non-text fields of
  3129. --              the copied line.
  3130. -------------------------------------------------------------------------
  3131.           (DUP_TYPE : LINE_DUPLICATION_TYPE) is
  3132.  
  3133. -- Temporary field storage structures for storing the line that
  3134. --   is being copied or moved.
  3135.  
  3136.     type LINE_REC;
  3137.     type LINE_REC_ACCESS is access LINE_REC;
  3138.  
  3139.     type LINE_REC is
  3140.         record
  3141.             NAME        : FORM_MANAGER.FIELD_NAME;
  3142.             POSITION    : FORM_MANAGER.FIELD_POSITION;
  3143.             LENGTH      : FORM_MANAGER.FIELD_LENGTH;
  3144.             RENDITION   : FORM_MANAGER.FIELD_RENDITIONS;
  3145.             CHAR_LIMITS : FORM_MANAGER.CHAR_TYPE;
  3146.             INIT_VALUE  : FORM_MANAGER.FIELD_VALUE;
  3147.             VALUE       : FORM_MANAGER.FIELD_VALUE;
  3148.             MODE        : FORM_MANAGER.FIELD_MODE;
  3149.             NEXT_FIELD  : LINE_REC_ACCESS := null;
  3150.         end record;
  3151.  
  3152.     SIZE                : TERMINAL_INTERFACE.SCREEN_POSITION;
  3153.  
  3154.     LINE, CURRENT_FIELD : LINE_REC_ACCESS;
  3155.  
  3156.     NEW_POS             : FORM_MANAGER.FIELD_POSITION;
  3157.  
  3158.     TEMP_FIELD          : FORM_MANAGER.FIELD_ACCESS;
  3159.     TEMP_POS            : FORM_MANAGER.FIELD_POSITION;
  3160.  
  3161.     CLEAR_LAST_LINE           : exception;
  3162.     FIELDS_FOUND_ON_LAST_LINE : exception;
  3163.  
  3164. begin
  3165.     TERMINAL_INTERFACE.SCREEN_SIZE (SIZE);
  3166.  
  3167.     -- Request user to identify new line using the arrow keys.
  3168.  
  3169.     TERMINAL_INTERFACE.PUT_MESSAGE
  3170.        ("Use arrow keys to locate new line position.");
  3171.     GET_CURSOR_POSITION (CURSOR, NEW_POS);
  3172.  
  3173.     -- Clear the message line.
  3174.  
  3175.     TERMINAL_INTERFACE.SPLIT_DISPLAY (SIZE);
  3176.  
  3177.     -- Ignore everything if the newly indicated line is the same as the
  3178.     --   original cursor's line.
  3179.  
  3180.     if CURSOR.LINE /= NEW_POS.LINE then
  3181.  
  3182. -- If Copy Line, check to see if non-text fields exist on the
  3183. --   last form line.
  3184.  
  3185.         if DUP_TYPE = COPY then
  3186.             begin
  3187.                 FIELD := FORM_MANAGER.GET_FIRST_FIELD
  3188.                             (CURRENT_FORM, CURRENT_SIZE.ROWS);
  3189.                 loop
  3190.                     FORM_MANAGER.GET_FIELD_INFO
  3191.                        (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS,
  3192.                         INIT_VALUE, VALUE, MODE);
  3193.  
  3194.                     -- If so, raise an exception.
  3195.  
  3196.                     if MODE /= FORM_MANAGER.CONSTANT_TEXT then
  3197.                         raise FIELDS_FOUND_ON_LAST_LINE;
  3198.                     end if;
  3199.                     FIELD := FORM_MANAGER.GET_NEXT_FIELD (FIELD);
  3200.                 end loop;
  3201.             exception
  3202.                 when FORM_MANAGER.FIELD_NOT_FOUND =>  null;
  3203.             end;
  3204.         end if;
  3205.  
  3206.         -- Save the line that is being moved or copied in a temporary
  3207.         --   linked list storage structure.
  3208.  
  3209.         begin
  3210.             FIELD := FORM_MANAGER.GET_FIRST_FIELD (CURRENT_FORM, CURSOR.LINE);
  3211.             FORM_MANAGER.GET_FIELD_INFO
  3212.                (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS,
  3213.                 INIT_VALUE, VALUE, MODE);
  3214.             LINE := new LINE_REC;
  3215.  
  3216.             LINE.NAME := NAME;
  3217.             LINE.POSITION := POSITION;
  3218.             LINE.LENGTH := LENGTH;
  3219.             LINE.RENDITION := RENDITION;
  3220.             LINE.CHAR_LIMITS := CHAR_LIMITS;
  3221.             LINE.INIT_VALUE := INIT_VALUE;
  3222.             LINE.VALUE := VALUE;
  3223.             LINE.MODE := MODE;
  3224.  
  3225.             CURRENT_FIELD := LINE;
  3226.             begin
  3227.                 loop
  3228.                     FIELD := FORM_MANAGER.GET_NEXT_FIELD (FIELD);
  3229.                     FORM_MANAGER.GET_FIELD_INFO
  3230.                        (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS,
  3231.                         INIT_VALUE, VALUE, MODE);
  3232.  
  3233.                     if POSITION.LINE = CURSOR.LINE then
  3234.                         CURRENT_FIELD.NEXT_FIELD := new LINE_REC;
  3235.                         CURRENT_FIELD := CURRENT_FIELD.NEXT_FIELD;
  3236.  
  3237.                         CURRENT_FIELD.NAME := NAME;
  3238.                         CURRENT_FIELD.POSITION := POSITION;
  3239.                         CURRENT_FIELD.LENGTH := LENGTH;
  3240.                         CURRENT_FIELD.RENDITION := RENDITION;
  3241.                         CURRENT_FIELD.CHAR_LIMITS := CHAR_LIMITS;
  3242.                         CURRENT_FIELD.INIT_VALUE := INIT_VALUE;
  3243.                         CURRENT_FIELD.VALUE := VALUE;
  3244.                         CURRENT_FIELD.MODE := MODE;
  3245.                     end if;
  3246.                 end loop;
  3247.             exception
  3248.                 when FORM_MANAGER.FIELD_NOT_FOUND =>  null;
  3249.             end;
  3250.  
  3251.         exception
  3252.             when FORM_MANAGER.FIELD_NOT_FOUND =>
  3253.  
  3254. -- This means that there was nothing on the moved or copied line.
  3255.  
  3256.                 LINE := null;
  3257.         end;
  3258.  
  3259.         -- If Move Line, then delete the line on which the cursor was
  3260.         --   originally located.
  3261.  
  3262.         if DUP_TYPE = MOVE then
  3263.             begin
  3264.                 FIELD := FORM_MANAGER.GET_FIRST_FIELD
  3265.                             (CURRENT_FORM, CURSOR.LINE);
  3266.                 FORM_MANAGER.GET_FIELD_INFO
  3267.                    (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS,
  3268.                     INIT_VALUE, VALUE, MODE);
  3269.                 while POSITION.LINE = CURSOR.LINE loop
  3270.  
  3271.                     -- Delete cursor line's fields.
  3272.  
  3273.                     FORM_MANAGER.DELETE_FIELD (FIELD);
  3274.                     FIELD := FORM_MANAGER.GET_NEXT_FIELD (FIELD);
  3275.                     FORM_MANAGER.GET_FIELD_INFO
  3276.                        (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS,
  3277.                         INIT_VALUE, VALUE, MODE);
  3278.                 end loop;
  3279.  
  3280.                 -- Move the rest up one line.
  3281.  
  3282.                 begin
  3283.                     loop
  3284.                         FORM_MANAGER.MOVE_FIELD
  3285.                            (FIELD, (POSITION.LINE - 1, POSITION.COLUMN));
  3286.                         FIELD := FORM_MANAGER.GET_NEXT_FIELD (FIELD);
  3287.                         FORM_MANAGER.GET_FIELD_INFO
  3288.                            (FIELD, NAME, POSITION, LENGTH, RENDITION,
  3289.                             CHAR_LIMITS, INIT_VALUE, VALUE, MODE);
  3290.                     end loop;
  3291.  
  3292.                 exception
  3293.  
  3294. -- These should NEVER happen!!!
  3295.  
  3296.                     when FORM_MANAGER.FIELD_OVERLAP_OCCURRED =>
  3297.                         TERMINAL_INTERFACE.PUT_MESSAGE
  3298.                            ("Internal move line error.");
  3299.                     when FORM_MANAGER.FIELD_EXTENDS_PAST_FORM =>
  3300.                         TERMINAL_INTERFACE.PUT_MESSAGE
  3301.                            ("Internal move line error.");
  3302.                 end;
  3303.  
  3304.             exception
  3305.                 when FORM_MANAGER.FIELD_NOT_FOUND =>
  3306.                     null;
  3307.             end;
  3308.  
  3309.             if CURSOR.LINE < NEW_POS.LINE then
  3310.                 NEW_POS.LINE := NEW_POS.LINE - 1;
  3311.             end if;
  3312.  
  3313.             -- Update the terminal display to reflect the deleted line.
  3314.  
  3315.             TERMINAL_INTERFACE.CLOSE_UP_DISPLAY
  3316.                ((CURSOR.LINE + CURRENT_POSITION.LINE - 1,
  3317.                  CURSOR.COLUMN + CURRENT_POSITION.COLUMN - 1));
  3318.  
  3319.         end if;
  3320.  
  3321.         -- Now, insert a blank line above the line indicated by the new
  3322.         --   cursor position.
  3323.  
  3324.         begin
  3325.  
  3326.             -- Locate the fields at or below new cursor's line.
  3327.  
  3328.             FIELD := FORM_MANAGER.GET_FIRST_FIELD (CURRENT_FORM);
  3329.             FORM_MANAGER.GET_FIELD_INFO
  3330.                (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS,
  3331.                 INIT_VALUE, VALUE, MODE);
  3332.  
  3333.             while POSITION.LINE < NEW_POS.LINE loop
  3334.                 FIELD := FORM_MANAGER.GET_NEXT_FIELD (FIELD);
  3335.                 FORM_MANAGER.GET_FIELD_INFO
  3336.                    (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS,
  3337.                     INIT_VALUE, VALUE, MODE);
  3338.             end loop;
  3339.  
  3340.             TEMP_FIELD := FIELD; -- First field at or below new cursor's line.
  3341.  
  3342.             -- Locate last form field.
  3343.  
  3344.             begin
  3345.                 loop
  3346.                     PREV_FIELD := FIELD;
  3347.                     FIELD := FORM_MANAGER.GET_NEXT_FIELD (FIELD);
  3348.                     FORM_MANAGER.GET_FIELD_INFO
  3349.                        (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS,
  3350.                         INIT_VALUE, VALUE, MODE);
  3351.                 end loop;
  3352.             exception
  3353.                 when FORM_MANAGER.FIELD_NOT_FOUND =>
  3354.                     null;
  3355.             end;
  3356.  
  3357.             -- Delete fields located on the last form line and update the
  3358.             --   the terminal display to reflect these deletes.
  3359.             --   (Note:  if this is Move Line, then there will not be any
  3360.             --    fields on the last form line.)
  3361.  
  3362.             FIELD := PREV_FIELD;
  3363.             FORM_MANAGER.GET_FIELD_INFO
  3364.                (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS,
  3365.                 INIT_VALUE, VALUE, MODE);
  3366.  
  3367.             begin
  3368.                 while POSITION.LINE = CURRENT_SIZE.ROWS loop
  3369.  
  3370.                     if TEMP_FIELD = FIELD then
  3371.                         raise CLEAR_LAST_LINE;
  3372.                     end if;
  3373.                     PREV_FIELD := FORM_MANAGER.GET_PREVIOUS_FIELD (FIELD);
  3374.                     FORM_MANAGER.DELETE_FIELD (FIELD);
  3375.                     TERMINAL_INTERFACE.ERASE_FIELD
  3376.                        ((POSITION.LINE + CURRENT_POSITION.LINE - 1,
  3377.                          POSITION.COLUMN + CURRENT_POSITION.COLUMN - 1),
  3378.                         LENGTH);
  3379.  
  3380.                     FIELD := PREV_FIELD;
  3381.                     FORM_MANAGER.GET_FIELD_INFO
  3382.                        (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS,
  3383.                         INIT_VALUE, VALUE, MODE);
  3384.                 end loop;
  3385.  
  3386.             exception
  3387.                 when CLEAR_LAST_LINE =>
  3388.                     FORM_MANAGER.DELETE_FIELD (FIELD);
  3389.                     TERMINAL_INTERFACE.ERASE_FIELD
  3390.                        ((POSITION.LINE + CURRENT_POSITION.LINE - 1,
  3391.                          POSITION.COLUMN + CURRENT_POSITION.COLUMN - 1),
  3392.                         LENGTH);
  3393.  
  3394.                     raise;
  3395.             end;
  3396.  
  3397.             -- Move the rest of the fields from the end of the form up to
  3398.             --   the first field of the new cursor's line down one line
  3399.             --   position.
  3400.  
  3401.             FORM_MANAGER.GET_FIELD_INFO
  3402.                (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS,
  3403.                 INIT_VALUE, VALUE, MODE);
  3404.  
  3405.             while FIELD /= TEMP_FIELD loop
  3406.                 FORM_MANAGER.MOVE_FIELD
  3407.                    (FIELD, (POSITION.LINE + 1, POSITION.COLUMN));
  3408.                 FIELD := FORM_MANAGER.GET_PREVIOUS_FIELD (FIELD);
  3409.                 FORM_MANAGER.GET_FIELD_INFO
  3410.                    (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS,
  3411.                     INIT_VALUE, VALUE, MODE);
  3412.             end loop;
  3413.  
  3414.             if POSITION.LINE < CURRENT_SIZE.ROWS then
  3415.                 FORM_MANAGER.GET_FIELD_INFO
  3416.                    (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS,
  3417.                     INIT_VALUE, VALUE, MODE);
  3418.                 FORM_MANAGER.MOVE_FIELD
  3419.                    (FIELD, (POSITION.LINE + 1, POSITION.COLUMN));
  3420.             end if;
  3421.  
  3422.             -- Update the terminal display to reflect this line insert.
  3423.  
  3424.             TERMINAL_INTERFACE.SPLIT_DISPLAY
  3425.                ((CURRENT_POSITION.LINE + NEW_POS.LINE - 1,
  3426.                  CURRENT_POSITION.COLUMN + NEW_POS.COLUMN - 1));
  3427.  
  3428.         exception
  3429.             when FORM_MANAGER.FIELD_NOT_FOUND =>  null;
  3430.  
  3431.             when FIELDS_FOUND_ON_LAST_LINE =>
  3432.                 TERMINAL_INTERFACE.PUT_MESSAGE
  3433.                    ("Must clear field from last line!");
  3434.  
  3435.             when CLEAR_LAST_LINE =>
  3436.                 TERMINAL_INTERFACE.SPLIT_DISPLAY
  3437.                    ((CURRENT_POSITION.LINE + NEW_POS.LINE - 1,
  3438.                      CURRENT_POSITION.COLUMN + NEW_POS.COLUMN - 1));
  3439.  
  3440.         end;
  3441.  
  3442.  
  3443.         -- Insert the saved fields into this new blank line.
  3444.  
  3445.         CURRENT_FIELD := LINE;
  3446.         while CURRENT_FIELD /= null loop
  3447.  
  3448. -- If Copy Line, then request new names for all of the non-text
  3449. --   fields.
  3450.  
  3451.             if DUP_TYPE = COPY and then
  3452.                CURRENT_FIELD.MODE /= FORM_MANAGER.CONSTANT_TEXT then
  3453.  
  3454.                 -- Highlight the field corresponding to the requested name.
  3455.  
  3456.                 TRANSFORM_AND_PUT_FIELD
  3457.                    ((NEW_POS.LINE + CURRENT_POSITION.LINE - 1,
  3458.                      CURRENT_FIELD.POSITION.COLUMN + CURRENT_POSITION.COLUMN -
  3459.                      1), CURRENT_FIELD.LENGTH, FORM_TYPES.REVERSE_RENDITION,
  3460.                     CURRENT_FIELD.CHAR_LIMITS, CURRENT_FIELD.INIT_VALUE,
  3461.                     CURRENT_FIELD.MODE);
  3462.  
  3463.                 TERMINAL_INTERFACE.PUT_MESSAGE ("Enter name for this field.");
  3464.                 FORMS.GET_FIELD_NAME (CURRENT_FIELD.NAME);
  3465.             end if;
  3466.  
  3467.             -- Add the field to the form structure.
  3468.  
  3469.             loop
  3470.                 begin
  3471.                     FORM_MANAGER.ADD_FIELD
  3472.                        (CURRENT_FORM, CURRENT_FIELD.NAME,
  3473.                         (NEW_POS.LINE, CURRENT_FIELD.POSITION.COLUMN),
  3474.                         CURRENT_FIELD.LENGTH, CURRENT_FIELD.RENDITION,
  3475.                         CURRENT_FIELD.CHAR_LIMITS, CURRENT_FIELD.INIT_VALUE,
  3476.                         CURRENT_FIELD.MODE, TEMP_FIELD);
  3477.                     exit;
  3478.                 exception
  3479.                     when FORM_MANAGER.DUPLICATE_FIELD_NAME =>
  3480.                         if DUP_TYPE = COPY then
  3481.                             TERMINAL_INTERFACE.PUT_MESSAGE
  3482.                                ("Field name already exists -- choose another");
  3483.                             delay 1.0;
  3484.                             TERMINAL_INTERFACE.SPLIT_DISPLAY (SIZE);
  3485.                             FORMS.GET_FIELD_NAME (CURRENT_FIELD.NAME);
  3486.                         end if;
  3487.                 end;
  3488.             end loop;
  3489.  
  3490.             -- Update terminal display to reflect the new field.
  3491.  
  3492.             TRANSFORM_AND_PUT_FIELD
  3493.                ((NEW_POS.LINE + CURRENT_POSITION.LINE - 1,
  3494.                  CURRENT_FIELD.POSITION.COLUMN + CURRENT_POSITION.COLUMN - 1),
  3495.                 CURRENT_FIELD.LENGTH, CURRENT_FIELD.RENDITION,
  3496.                 CURRENT_FIELD.CHAR_LIMITS, CURRENT_FIELD.INIT_VALUE,
  3497.                 CURRENT_FIELD.MODE);
  3498.  
  3499.             CURRENT_FIELD := CURRENT_FIELD.NEXT_FIELD;
  3500.  
  3501.         end loop;
  3502.  
  3503.         -- Clear the message line.
  3504.  
  3505.         TERMINAL_INTERFACE.SPLIT_DISPLAY (SIZE);
  3506.         CURSOR := NEW_POS;
  3507.  
  3508.     end if;
  3509.  
  3510. exception
  3511.     when FIELDS_FOUND_ON_LAST_LINE =>
  3512.         TERMINAL_INTERFACE.PUT_MESSAGE ("Cannot copy -- fields on last line!");
  3513.  
  3514. end DUPLICATE_LINE;
  3515. separate (EDITOR)
  3516. procedure DELETE_LINE -------------------------------------------------------------------------
  3517. -- Abstract   : This procedure implements the Delete Line operation of
  3518. --              the Form Editor.  Command line abbreviation:  D L
  3519. -------------------------------------------------------------------------
  3520. -- Parameters : none.
  3521. -------------------------------------------------------------------------
  3522. -- Algorithm  : This procedure deletes a line of a form that the cursor
  3523. --              was positioned on.  The rest of the lines below this
  3524. --              deleted line are shifted up one line.  A blank line is
  3525. --              inserted as the new last line of the form.  A line cannot
  3526. --              be deleted if it still contains non-text fields.
  3527. -------------------------------------------------------------------------
  3528.       is
  3529.  
  3530.     SIZE       : TERMINAL_INTERFACE.SCREEN_POSITION;
  3531.  
  3532.     TEMP_POS   : FORM_MANAGER.FIELD_POSITION;
  3533.     TEMP_FIELD : FORM_MANAGER.FIELD_ACCESS;
  3534.  
  3535.     FIELDS_FOUND_ON_LINE : exception;
  3536.  
  3537. begin
  3538.  
  3539.     -- Locate first field at or below cursor's line.
  3540.  
  3541.     FIELD := FORM_MANAGER.GET_FIRST_FIELD (CURRENT_FORM);
  3542.     FORM_MANAGER.GET_FIELD_INFO
  3543.        (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS, INIT_VALUE,
  3544.     VALUE, MODE);
  3545.  
  3546.     while POSITION.LINE < CURSOR.LINE loop
  3547.     FIELD := FORM_MANAGER.GET_NEXT_FIELD (FIELD);
  3548.     FORM_MANAGER.GET_FIELD_INFO
  3549.        (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS, INIT_VALUE,
  3550.         VALUE, MODE);
  3551.     end loop;
  3552.  
  3553.     TEMP_FIELD := FIELD;
  3554.  
  3555.     -- Check cursor's line to see if it contains non-text fields.
  3556.  
  3557.     if POSITION.LINE = CURSOR.LINE then
  3558.     begin
  3559.         while POSITION.LINE = CURSOR.LINE loop
  3560.  
  3561. -- If so, raise an exception.
  3562.  
  3563.         if MODE /= FORM_MANAGER.CONSTANT_TEXT then
  3564.             raise FIELDS_FOUND_ON_LINE;
  3565.         end if;
  3566.         FIELD := FORM_MANAGER.GET_NEXT_FIELD (FIELD);
  3567.         FORM_MANAGER.GET_FIELD_INFO
  3568.            (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS,
  3569.             INIT_VALUE, VALUE, MODE);
  3570.         end loop;
  3571.     exception
  3572.         when FORM_MANAGER.FIELD_NOT_FOUND => 
  3573.         null;
  3574.     end;
  3575.     end if;
  3576.  
  3577.     FIELD := TEMP_FIELD;
  3578.     FORM_MANAGER.GET_FIELD_INFO
  3579.        (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS, INIT_VALUE,
  3580.     VALUE, MODE);
  3581.     begin
  3582.  
  3583. -- Delete the fields on the cursor's line.
  3584.  
  3585.     while POSITION.LINE = CURSOR.LINE loop
  3586.         FORM_MANAGER.DELETE_FIELD (FIELD);
  3587.         FIELD := FORM_MANAGER.GET_NEXT_FIELD (FIELD);
  3588.         FORM_MANAGER.GET_FIELD_INFO
  3589.            (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS,
  3590.         INIT_VALUE, VALUE, MODE);
  3591.     end loop;
  3592.  
  3593.     -- Move the fields below cursor's line up one line position.
  3594.  
  3595.     begin
  3596.         loop
  3597.         FORM_MANAGER.MOVE_FIELD
  3598.            (FIELD, (POSITION.LINE - 1, POSITION.COLUMN));
  3599.         FIELD := FORM_MANAGER.GET_NEXT_FIELD (FIELD);
  3600.         FORM_MANAGER.GET_FIELD_INFO
  3601.            (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS,
  3602.             INIT_VALUE, VALUE, MODE);
  3603.         end loop;
  3604.     exception
  3605.  
  3606. -- These exceptions should NEVER occur!!
  3607.  
  3608.         when FORM_MANAGER.FIELD_OVERLAP_OCCURRED => 
  3609.         TERMINAL_INTERFACE.PUT_MESSAGE ("Internal delete line error.");
  3610.         when FORM_MANAGER.FIELD_EXTENDS_PAST_FORM => 
  3611.         TERMINAL_INTERFACE.PUT_MESSAGE ("Internal delete line error.");
  3612.  
  3613.     end;
  3614.  
  3615.     exception
  3616.     when FORM_MANAGER.FIELD_NOT_FOUND => 
  3617.         null;
  3618.     end;
  3619.  
  3620.     -- Update the terminal display.
  3621.  
  3622.     TERMINAL_INTERFACE.SCREEN_SIZE (SIZE);
  3623.     TERMINAL_INTERFACE.SPLIT_DISPLAY (SIZE);
  3624.  
  3625.     TEMP_POS.LINE := CURSOR.LINE + CURRENT_POSITION.LINE - 1;
  3626.     TEMP_POS.COLUMN := CURSOR.COLUMN + CURRENT_POSITION.COLUMN - 1;
  3627.     TERMINAL_INTERFACE.CLOSE_UP_DISPLAY (TEMP_POS);
  3628.  
  3629. exception
  3630.     when FORM_MANAGER.FIELD_NOT_FOUND => 
  3631.     null;
  3632.  
  3633.     when FIELDS_FOUND_ON_LINE => 
  3634.     TERMINAL_INTERFACE.PUT_MESSAGE ("Cannot delete -- field found on line");
  3635.  
  3636.  
  3637. end DELETE_LINE;
  3638. separate (EDITOR)
  3639. procedure INSERT_CHARACTER -------------------------------------------------------------------------
  3640. -- Abstract   : This procedure implements the Insert Character operation
  3641. --              of the Form Editor.  This operation can only be used on
  3642. --              text characters.  Command line abbreviation: I CH
  3643. -------------------------------------------------------------------------
  3644. -- Parameters : none.
  3645. -------------------------------------------------------------------------
  3646. -- Algorithm  : This procedure inserts a blank into a line of a form. The
  3647. --              blank is inserted just to the left of the cursor and the
  3648. --              cursor is positioned on this new blank character.  All
  3649. --              characters and fields from the original cursor position
  3650. --              to the end of the line are shifted right one position.
  3651. -------------------------------------------------------------------------
  3652.       is
  3653.  
  3654.     TEMP_POS : FORM_MANAGER.FIELD_POSITION;
  3655.  
  3656.     NOT_IN_TEXT_FIELD : exception;
  3657.  
  3658. begin
  3659.  
  3660. -- Don't do anything is positioned in last form column.
  3661.  
  3662.     if CURSOR.COLUMN /= CURRENT_SIZE.COLUMNS then
  3663.     begin
  3664.  
  3665.         -- Check to see if a field extends TO the end of the line.
  3666.  
  3667.         TEMP_POS.LINE := CURSOR.LINE;
  3668.         TEMP_POS.COLUMN := CURRENT_SIZE.COLUMNS;
  3669.         FIELD := FORM_MANAGER.GET_FIELD_POINTER (CURRENT_FORM, TEMP_POS);
  3670.  
  3671.         FORM_MANAGER.GET_FIELD_INFO
  3672.            (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS,
  3673.         INIT_VALUE, VALUE, MODE);
  3674.  
  3675.         -- If so, raise an exception
  3676.  
  3677.         if MODE /= FORM_MANAGER.CONSTANT_TEXT then
  3678.         raise FORM_MANAGER.FIELD_EXTENDS_PAST_FORM;
  3679.         end if;
  3680.     exception
  3681.         when FORM_MANAGER.FIELD_POSITION_NOT_FOUND => 
  3682.         null;
  3683.     end;
  3684.  
  3685.     -- Make sure that the cursor is positioned in a TEXT field.
  3686.  
  3687.     begin
  3688.         FIELD := FORM_MANAGER.GET_FIELD_POINTER (CURRENT_FORM, CURSOR);
  3689.         FORM_MANAGER.GET_FIELD_INFO
  3690.            (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS,
  3691.         INIT_VALUE, VALUE, MODE);
  3692.         if MODE /= FORM_MANAGER.CONSTANT_TEXT then
  3693.         raise NOT_IN_TEXT_FIELD;
  3694.         end if;
  3695.     exception
  3696.         when FORM_MANAGER.FIELD_POSITION_NOT_FOUND =>  null;
  3697.     end;
  3698.  
  3699.     begin
  3700.  
  3701.         -- Locate the last field on the cursor's line.
  3702.  
  3703.         FIELD := FORM_MANAGER.GET_FIRST_FIELD (CURRENT_FORM, CURSOR.LINE);
  3704.         FORM_MANAGER.GET_FIELD_INFO
  3705.            (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS,
  3706.         INIT_VALUE, VALUE, MODE);
  3707.         begin
  3708.         while POSITION.LINE = CURSOR.LINE loop
  3709.             PREV_FIELD := FIELD;
  3710.             FIELD := FORM_MANAGER.GET_NEXT_FIELD (FIELD);
  3711.             FORM_MANAGER.GET_FIELD_INFO
  3712.                (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS,
  3713.             INIT_VALUE, VALUE, MODE);
  3714.         end loop;
  3715.         exception
  3716.         when FORM_MANAGER.FIELD_NOT_FOUND =>  null;
  3717.         end;
  3718.  
  3719.         -- Move the fields one position to the right.
  3720.  
  3721.         FIELD := PREV_FIELD;
  3722.         FORM_MANAGER.GET_FIELD_INFO
  3723.            (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS,
  3724.         INIT_VALUE, VALUE, MODE);
  3725.  
  3726.         begin
  3727.         while POSITION.COLUMN > CURSOR.COLUMN loop
  3728.             FORM_MANAGER.MOVE_FIELD
  3729.                (FIELD, (POSITION.LINE, POSITION.COLUMN + 1));
  3730.             FIELD := FORM_MANAGER.GET_PREVIOUS_FIELD (FIELD);
  3731.             FORM_MANAGER.GET_FIELD_INFO
  3732.                (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS,
  3733.             INIT_VALUE, VALUE, MODE);
  3734.         end loop;
  3735.  
  3736.         -- If cursor is positioned in a text field, then insert the
  3737.         --   character in this field.
  3738.  
  3739.         if POSITION.COLUMN + LENGTH >= CURSOR.COLUMN then
  3740.             INIT_VALUE
  3741.                (CURSOR.COLUMN - POSITION.COLUMN + 1 ..
  3742.             FORM_MANAGER.MAX_FIELD_VALUE) :=
  3743.               ' ' &
  3744.               INIT_VALUE
  3745.              (CURSOR.COLUMN - POSITION.COLUMN + 1 ..
  3746.               FORM_MANAGER.MAX_FIELD_VALUE - 1);
  3747.             FORM_MANAGER.MODIFY_FIELD_INIT (FIELD, INIT_VALUE);
  3748.             FORM_MANAGER.MODIFY_FIELD_LENGTH (FIELD, LENGTH + 1);
  3749.         end if;
  3750.         exception
  3751.         when FORM_MANAGER.FIELD_NOT_FOUND => 
  3752.             null;
  3753.         end;
  3754.  
  3755.         -- Insert character into the terminal display.
  3756.  
  3757.         TEMP_POS.LINE := CURSOR.LINE + CURRENT_POSITION.LINE - 1;
  3758.         TEMP_POS.COLUMN := CURSOR.COLUMN + CURRENT_POSITION.COLUMN - 1;
  3759.         TERMINAL_INTERFACE.INSERT_CHARACTER (' ', TEMP_POS);
  3760.  
  3761.     exception
  3762.         when FORM_MANAGER.FIELD_NOT_FOUND =>  null;
  3763.     end;
  3764.  
  3765.     end if;
  3766.  
  3767. exception
  3768.     when FORM_MANAGER.FIELD_EXTENDS_PAST_FORM => 
  3769.     TERMINAL_INTERFACE.PUT_MESSAGE ("No room in line to insert character!");
  3770.  
  3771.  
  3772.     when NOT_IN_TEXT_FIELD => 
  3773.     TERMINAL_INTERFACE.PUT_MESSAGE ("Cannot insert characters in a field!");
  3774. end INSERT_CHARACTER;
  3775. separate (EDITOR)
  3776. procedure DELETE_CHARACTER -------------------------------------------------------------------------
  3777. -- Abstract   : This procedure implements the Delete Character operation
  3778. --              of the Form Editor.  This operation only can be used on
  3779. --              text characters.  Command line abbreviation:  D CH
  3780. -------------------------------------------------------------------------
  3781. -- Parameters : none.
  3782. -------------------------------------------------------------------------
  3783. -- Algorithm  : This procedure deletes a character from a form line and
  3784. --              shifts all other characters and fields to the left.  The
  3785. --              cursor remains in its original position.  The character
  3786. --              located UNDER the cursor is the one that is deleted.
  3787. -------------------------------------------------------------------------
  3788.       is
  3789.  
  3790.     TEMP_FIELD   : FORM_MANAGER.FIELD_ACCESS;
  3791.     TEMP_POS     : FORM_MANAGER.FIELD_POSITION;
  3792.  
  3793.     NEXT_IS_NULL : BOOLEAN := false;
  3794.  
  3795.     DEGENERATED_FIELD : exception;
  3796.     NOT_IN_TEXT_FIELD : exception;
  3797.  
  3798. begin
  3799.  
  3800. -- Make sure that cursor is located in a TEXT field.
  3801.  
  3802.     begin
  3803.     FIELD := FORM_MANAGER.GET_FIELD_POINTER (CURRENT_FORM, CURSOR);
  3804.     FORM_MANAGER.GET_FIELD_INFO
  3805.        (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS, INIT_VALUE,
  3806.         VALUE, MODE);
  3807.  
  3808.     -- If not, raise an exception.
  3809.  
  3810.     if MODE /= FORM_MANAGER.CONSTANT_TEXT then
  3811.         raise NOT_IN_TEXT_FIELD;
  3812.     end if;
  3813.  
  3814.     -- If the field only has one character then raise the degenerated
  3815.     --   field exception.  This will simply delete the field and send
  3816.     --   a blank to the screen.
  3817.  
  3818.     if LENGTH = 1 then
  3819.         raise DEGENERATED_FIELD;
  3820.     end if;
  3821.  
  3822.     -- If the cursor is positioned on a field position, other than the
  3823.     --   LAST field position, then alter the fields contents.
  3824.  
  3825.     if CURSOR.COLUMN /= POSITION.COLUMN + LENGTH - 1 then
  3826.         INIT_VALUE
  3827.            (CURSOR.COLUMN - POSITION.COLUMN + 1 ..
  3828.         FORM_MANAGER.MAX_FIELD_VALUE) :=
  3829.           INIT_VALUE
  3830.          (CURSOR.COLUMN - POSITION.COLUMN + 2 ..
  3831.           FORM_MANAGER.MAX_FIELD_VALUE) & ' ';
  3832.         FORM_MANAGER.MODIFY_FIELD_INIT (FIELD, INIT_VALUE);
  3833.     end if;
  3834.     FORM_MANAGER.MODIFY_FIELD_LENGTH (FIELD, LENGTH - 1);
  3835.  
  3836.     -- Locate first field after the cursor position.
  3837.  
  3838.     begin
  3839.         FIELD := FORM_MANAGER.GET_NEXT_FIELD (FIELD);
  3840.         FORM_MANAGER.GET_FIELD_INFO
  3841.            (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS,
  3842.         INIT_VALUE, VALUE, MODE);
  3843.     exception
  3844.         when FORM_MANAGER.FIELD_NOT_FOUND => 
  3845.         NEXT_IS_NULL := true;
  3846.     end;
  3847.  
  3848.     exception
  3849.  
  3850. -- This is where the degenerated field case is handled.
  3851.  
  3852.     when DEGENERATED_FIELD => 
  3853.         TEMP_FIELD := FORM_MANAGER.GET_NEXT_FIELD (FIELD);
  3854.         FORM_MANAGER.DELETE_FIELD (FIELD);
  3855.         FIELD := TEMP_FIELD;
  3856.         FORM_MANAGER.GET_FIELD_INFO
  3857.            (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS,
  3858.         INIT_VALUE, VALUE, MODE);
  3859.  
  3860.         -- Since the cursor wasn't positioned in a field, then locate the
  3861.         --   first field past the cursor position.
  3862.  
  3863.     when FORM_MANAGER.FIELD_POSITION_NOT_FOUND => 
  3864.         FIELD := FORM_MANAGER.GET_FIRST_FIELD (CURRENT_FORM, CURSOR.LINE);
  3865.         FORM_MANAGER.GET_FIELD_INFO
  3866.            (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS,
  3867.         INIT_VALUE, VALUE, MODE);
  3868.         while POSITION.COLUMN <= CURSOR.COLUMN and then
  3869.           POSITION.LINE = CURSOR.LINE loop
  3870.         FIELD := FORM_MANAGER.GET_NEXT_FIELD (FIELD);
  3871.         FORM_MANAGER.GET_FIELD_INFO
  3872.            (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS,
  3873.             INIT_VALUE, VALUE, MODE);
  3874.         end loop;
  3875.     end;
  3876.  
  3877.     -- From this field to the end of the line, move the field to the left
  3878.     --   one position.
  3879.  
  3880.     begin
  3881.     loop
  3882.         if NEXT_IS_NULL or else POSITION.LINE /= CURSOR.LINE then
  3883.         exit;
  3884.         else
  3885.         FORM_MANAGER.MOVE_FIELD
  3886.            (FIELD, (POSITION.LINE, POSITION.COLUMN - 1));
  3887.         end if;
  3888.         FIELD := FORM_MANAGER.GET_NEXT_FIELD (FIELD);
  3889.         FORM_MANAGER.GET_FIELD_INFO
  3890.            (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS,
  3891.         INIT_VALUE, VALUE, MODE);
  3892.     end loop;
  3893.     exception
  3894.     when FORM_MANAGER.FIELD_NOT_FOUND => 
  3895.         null;
  3896.     end;
  3897.  
  3898.     -- Update the terminal display.
  3899.  
  3900.     TEMP_POS.LINE := CURSOR.LINE + CURRENT_POSITION.LINE - 1;
  3901.     TEMP_POS.COLUMN := CURSOR.COLUMN + CURRENT_POSITION.COLUMN - 1;
  3902.     TERMINAL_INTERFACE.ERASE_CHARACTER (TEMP_POS);
  3903.  
  3904. exception
  3905.     when NOT_IN_TEXT_FIELD => 
  3906.     TERMINAL_INTERFACE.PUT_MESSAGE ("Cannot delete a field character!");
  3907.  
  3908.     when FORM_MANAGER.FIELD_NOT_FOUND => 
  3909.     null;
  3910.  
  3911. end DELETE_CHARACTER;
  3912. separate (EDITOR)
  3913. procedure RUBOUT_CHARACTER -------------------------------------------------------------------------
  3914. -- Abstract   : This procedure implements the Rubout Character operation
  3915. --              of the Form Editor.  This operation only can be used on
  3916. --              text character.  Command line abbreviation:  R
  3917. -------------------------------------------------------------------------
  3918. -- Parameters : none
  3919. -------------------------------------------------------------------------
  3920. -- Algorithm  : This procedure replaces a text character with a blank
  3921. --              and does not shift any of the characters and fields on
  3922. --              the line.  The rubbed out characters is the one just to
  3923. --              the left of the cursor and the cursor is shifted one
  3924. --              position to the left.
  3925. -------------------------------------------------------------------------
  3926.       is
  3927.  
  3928.     TEMP_POS : FORM_MANAGER.FIELD_POSITION;
  3929.  
  3930. begin
  3931.  
  3932. -- Don't do anything if in column one.
  3933.  
  3934.     if CURSOR.COLUMN /= 1 then
  3935.  
  3936.     TEMP_POS.LINE := CURSOR.LINE;
  3937.     TEMP_POS.COLUMN := CURSOR.COLUMN - 1;
  3938.  
  3939.     FIELD := FORM_MANAGER.GET_FIELD_POINTER (CURRENT_FORM, TEMP_POS);
  3940.     FORM_MANAGER.GET_FIELD_INFO
  3941.        (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS, INIT_VALUE,
  3942.         VALUE, MODE);
  3943.  
  3944.  
  3945.     -- Raise exception if not rubbing out a text character.
  3946.  
  3947.     if MODE /= FORM_MANAGER.CONSTANT_TEXT then
  3948.         raise FORM_MANAGER.FIELD_NOT_FOUND;
  3949.     end if;
  3950.  
  3951.     -- Modify the form structure.
  3952.  
  3953.     INIT_VALUE (TEMP_POS.COLUMN - POSITION.COLUMN + 1) := ' ';
  3954.     FORM_MANAGER.MODIFY_FIELD_INIT (FIELD, INIT_VALUE);
  3955.  
  3956.     -- Modify the terminal display.
  3957.  
  3958.     CURSOR.COLUMN := CURSOR.COLUMN - 1;
  3959.     TEMP_POS.LINE := CURSOR.LINE + CURRENT_POSITION.LINE - 1;
  3960.     TEMP_POS.COLUMN := CURSOR.COLUMN + CURRENT_POSITION.COLUMN - 1;
  3961.     TERMINAL_INTERFACE.PUT_CURSOR (TEMP_POS);
  3962.     TERMINAL_INTERFACE.PUT_CHARACTER (' ');
  3963.  
  3964.     end if;
  3965.  
  3966. exception
  3967.     when FORM_MANAGER.FIELD_NOT_FOUND => 
  3968.     TERMINAL_INTERFACE.PUT_MESSAGE ("Cannot rubout a field character!");
  3969.  
  3970.     when FORM_MANAGER.FIELD_POSITION_NOT_FOUND => 
  3971.  
  3972. -- If not located in a field at all, then simply backup the
  3973. --   cursor one position on the terminal display.
  3974.  
  3975.     CURSOR.COLUMN := CURSOR.COLUMN - 1;
  3976.     TEMP_POS.LINE := CURSOR.LINE + CURRENT_POSITION.LINE - 1;
  3977.     TEMP_POS.COLUMN := CURSOR.COLUMN + CURRENT_POSITION.COLUMN - 1;
  3978.     TERMINAL_INTERFACE.PUT_CURSOR (TEMP_POS);
  3979.  
  3980. end RUBOUT_CHARACTER;
  3981. separate (EDITOR)
  3982. procedure HELP is
  3983.  
  3984.     CHARTYPE : TERMINAL_INTERFACE.CHAR_ENUM;
  3985.     CHAR     : CHARACTER;
  3986.     FUNCT    : TERMINAL_INTERFACE.FUNCTION_KEY_ENUM;
  3987.  
  3988.     function "=" (LEFT, RIGHT : TERMINAL_INTERFACE.CHAR_ENUM) return BOOLEAN
  3989.            renames TERMINAL_INTERFACE."=";
  3990.  
  3991. begin
  3992.     TERMINAL_INTERFACE.CLEAR_SCREEN;
  3993.  
  3994.     TERMINAL_INTERFACE.PUT_FIELD
  3995.        ((1, 5), 66, FORM_TYPES.PRIMARY_RENDITION,
  3996.     "This Form Editor allows editor commands to be entered in two ways:");
  3997.  
  3998.     TERMINAL_INTERFACE.PUT_FIELD
  3999.        ((2, 1), 77, FORM_TYPES.PRIMARY_RENDITION,
  4000.     "single keystroke or Command Line entry.  All of the single " &
  4001.     "keystrokes for the");
  4002.  
  4003.     TERMINAL_INTERFACE.PUT_FIELD
  4004.        ((3, 1), 78, FORM_TYPES.PRIMARY_RENDITION,
  4005.     "editor commands are mapped to keyboard keys through the TCF " &
  4006.     "file.  The Command");
  4007.  
  4008.     TERMINAL_INTERFACE.PUT_FIELD
  4009.        ((4, 1), 73, FORM_TYPES.PRIMARY_RENDITION,
  4010.     "Line provides command completion triggered by the space " &
  4011.     "character and the");
  4012.  
  4013.     TERMINAL_INTERFACE.PUT_FIELD
  4014.        ((5, 1), 78, FORM_TYPES.PRIMARY_RENDITION,
  4015.     "RETURN KEY.  The Command Line abbreviations necessary are " &
  4016.     "indicated by capital");
  4017.  
  4018.     TERMINAL_INTERFACE.PUT_FIELD
  4019.        ((6, 1), 14, FORM_TYPES.PRIMARY_RENDITION, "letters below:");
  4020.  
  4021.     TERMINAL_INTERFACE.PUT_FIELD
  4022.        ((8, 5), 61, FORM_TYPES.PRIMARY_RENDITION,
  4023.     "CReate field     - Create a new field starting at the cursor.");
  4024.  
  4025.     TERMINAL_INTERFACE.PUT_FIELD
  4026.        ((9, 5), 71, FORM_TYPES.PRIMARY_RENDITION,
  4027.     "MODify field     - Modify the value or attributes of an existing field.");
  4028.  
  4029.     TERMINAL_INTERFACE.PUT_FIELD
  4030.        ((10, 5), 44, FORM_TYPES.PRIMARY_RENDITION,
  4031.     "Delete Field     - Delete an existing field.");
  4032.  
  4033.     TERMINAL_INTERFACE.PUT_FIELD
  4034.        ((11, 5), 70, FORM_TYPES.PRIMARY_RENDITION,
  4035.     "MOVe Field       - Move a field to a position indicated by the cursor.");
  4036.  
  4037.     TERMINAL_INTERFACE.PUT_FIELD
  4038.        ((12, 5), 74, FORM_TYPES.PRIMARY_RENDITION,
  4039.     "COpy Field       - Move a field to a position " &
  4040.     "indicated by the cursor and.");
  4041.     TERMINAL_INTERFACE.PUT_FIELD
  4042.        ((13, 24), 38, FORM_TYPES.PRIMARY_RENDITION,
  4043.     "provide a new name for this new field.");
  4044.  
  4045.     TERMINAL_INTERFACE.PUT_FIELD
  4046.        ((14, 5), 71, FORM_TYPES.PRIMARY_RENDITION,
  4047.     "Insert Line      - Insert a blank line above the line the cursor is on.");
  4048.  
  4049.     TERMINAL_INTERFACE.PUT_FIELD
  4050.        ((15, 5), 75, FORM_TYPES.PRIMARY_RENDITION,
  4051.     "MOVe Line        - Move a line and insert it above " &
  4052.     "the new cursor position.");
  4053.  
  4054.     TERMINAL_INTERFACE.PUT_FIELD
  4055.        ((16, 5), 74, FORM_TYPES.PRIMARY_RENDITION,
  4056.     "COPy Line        - Copy a line and insert it " &
  4057.     "above the new cursor position");
  4058.     TERMINAL_INTERFACE.PUT_FIELD
  4059.        ((17, 24), 46, FORM_TYPES.PRIMARY_RENDITION,
  4060.     "and provide new names for the non-text fields.");
  4061.  
  4062.     TERMINAL_INTERFACE.PUT_FIELD
  4063.        ((18, 5), 68, FORM_TYPES.PRIMARY_RENDITION,
  4064.     "Delete Line      - Delete a line (as long as no fields exist on it).");
  4065.  
  4066.     TERMINAL_INTERFACE.PUT_FIELD
  4067.        ((19, 5), 60, FORM_TYPES.PRIMARY_RENDITION,
  4068.     "Insert CHaracter - Insert a blank to the left of the cursor.");
  4069.  
  4070.     TERMINAL_INTERFACE.PUT_FIELD
  4071.        ((20, 5), 57, FORM_TYPES.PRIMARY_RENDITION,
  4072.     "Delete CHaracter - Delete the character under the cursor.");
  4073.  
  4074.     TERMINAL_INTERFACE.PUT_FIELD
  4075.        ((21, 5), 73, FORM_TYPES.PRIMARY_RENDITION,
  4076.     "Rubout character - Replace the character left of the cursor with a blank.");
  4077.  
  4078.     TERMINAL_INTERFACE.PUT_FIELD
  4079.        ((22, 5), 46, FORM_TYPES.PRIMARY_RENDITION,
  4080.     "Help             - Display this help facility.");
  4081.  
  4082.  
  4083.     TERMINAL_INTERFACE.PUT_FIELD
  4084.        ((24, 1), 40, FORM_TYPES.REVERSE_RENDITION,
  4085.     "Strike any key to return to Form Editor.");
  4086.  
  4087.  
  4088.     TERMINAL_INTERFACE.GET_CHARACTER (CHARTYPE, CHAR, FUNCT);
  4089.  
  4090.     while CHARTYPE = TERMINAL_INTERFACE.TIMEOUT loop
  4091.     TERMINAL_INTERFACE.GET_CHARACTER (CHARTYPE, CHAR, FUNCT);
  4092.     end loop;
  4093.  
  4094.     begin
  4095.     TERMINAL_INTERFACE.CLEAR_SCREEN;
  4096.  
  4097.     FIELD := FORM_MANAGER.GET_FIRST_FIELD (CURRENT_FORM);
  4098.     loop
  4099.         FORM_MANAGER.GET_FIELD_INFO
  4100.            (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS,
  4101.         INIT_VALUE, VALUE, MODE);
  4102.         POSITION.LINE := POSITION.LINE + CURRENT_POSITION.LINE - 1;
  4103.         POSITION.COLUMN := POSITION.COLUMN + CURRENT_POSITION.COLUMN - 1;
  4104.         TRANSFORM_AND_PUT_FIELD
  4105.            (POSITION, LENGTH, RENDITION, CHAR_LIMITS, INIT_VALUE, MODE);
  4106.         FIELD := FORM_MANAGER.GET_NEXT_FIELD (FIELD);
  4107.     end loop;
  4108.  
  4109.     exception
  4110.     when FORM_MANAGER.FIELD_NOT_FOUND =>  null;
  4111.     end;
  4112.  
  4113. end HELP;
  4114. ::::::::::
  4115. EDITOR_BODY.ADA
  4116. ::::::::::
  4117. -------------------------------------------------------------------------
  4118. -- Abstract   : This package is the driver for the Form Editor.  Provided
  4119. --              are all of the services for characters, functions, and
  4120. --              execution of the respective commands when necessary.
  4121. -------------------------------------------------------------------------
  4122. package body EDITOR is
  4123.  
  4124.     CURRENT_FORM     : FORM_MANAGER.FORM_ACCESS;
  4125.     CURRENT_SIZE     : FORM_MANAGER.FORM_SIZE;
  4126.     CURRENT_POSITION : FORM_MANAGER.FORM_POSITION;
  4127.     CURRENT_OPTION   : FORM_MANAGER.OPTION_TYPE;
  4128.  
  4129.     type FIELD_DUPLICATION_TYPE is (MOVE, COPY);
  4130.     type FIELD_MODIFICATION_TYPE is (CREATE, MODIFY);
  4131.     type LINE_DUPLICATION_TYPE is (MOVE, COPY);
  4132.  
  4133.     EDITOR_DRIVER_EXIT : exception;
  4134.  
  4135.     CHAR                                     : CHARACTER;
  4136.     CHARTYPE                                 : TERMINAL_INTERFACE.CHAR_ENUM;
  4137.     FUNCT                                    : TERMINAL_INTERFACE
  4138.                         .FUNCTION_KEY_ENUM;
  4139.  
  4140.     CURSOR                                   : FORM_MANAGER.FIELD_POSITION;
  4141.     MERGE_RIGHT, MERGE_LEFT                  : BOOLEAN;
  4142.  
  4143.     FIELD, NEXT_FIELD, PREV_FIELD, NEW_FIELD : FORM_MANAGER.FIELD_ACCESS;
  4144.     NAME, NEXT_NAME, PREV_NAME               : FORM_MANAGER.FIELD_NAME;
  4145.     POSITION, NEXT_POS, PREV_POS             : FORM_MANAGER.FIELD_POSITION;
  4146.     LENGTH, NEXT_LEN, PREV_LEN               : FORM_MANAGER.FIELD_LENGTH;
  4147.     RENDITION, NEXT_REND, PREV_REND          : FORM_MANAGER.FIELD_RENDITIONS;
  4148.     CHAR_LIMITS, NEXT_LIMITS, PREV_LIMITS    : FORM_MANAGER.CHAR_TYPE;
  4149.     INIT_VALUE, NEXT_INIT, PREV_INIT         : FORM_MANAGER.FIELD_VALUE;
  4150.     VALUE, NEXT_VAL, PREV_VAL                : FORM_MANAGER.FIELD_VALUE;
  4151.     MODE, NEXT_MODE, PREV_MODE               : FORM_MANAGER.FIELD_MODE;
  4152.  
  4153.     function "=" (LEFT, RIGHT : TERMINAL_INTERFACE.FUNCTION_KEY_ENUM)
  4154.            return BOOLEAN renames TERMINAL_INTERFACE."=";
  4155.  
  4156.     function "=" (LEFT, RIGHT : TERMINAL_INTERFACE.CHAR_ENUM) return BOOLEAN
  4157.            renames TERMINAL_INTERFACE."=";
  4158.  
  4159.     function "=" (LEFT, RIGHT : FORM_MANAGER.FIELD_MODE) return BOOLEAN
  4160.            renames FORM_MANAGER."=";
  4161.  
  4162.     function "=" (LEFT, RIGHT : FORM_MANAGER.FIELD_ACCESS) return BOOLEAN
  4163.            renames FORM_MANAGER."=";
  4164.  
  4165. -------------------------------------------------------------------------
  4166. -- Abstract   : This function determines whether the given cursor position
  4167. --              is within the confines of a NON-TEXT field.
  4168. -------------------------------------------------------------------------
  4169. -- Parameters : CURSOR - The cursor position in question.
  4170. -------------------------------------------------------------------------
  4171.     function IN_FIELD (CURSOR : TERMINAL_INTERFACE.SCREEN_POSITION)
  4172.                 return BOOLEAN is
  4173.     begin
  4174.     FIELD := FORM_MANAGER.GET_FIELD_POINTER (CURRENT_FORM, CURSOR);
  4175.     FORM_MANAGER.GET_FIELD_INFO
  4176.        (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS, INIT_VALUE,
  4177.         VALUE, MODE);
  4178.     return (MODE /= FORM_MANAGER.CONSTANT_TEXT);
  4179.     exception
  4180.     when FORM_MANAGER.NULL_FORM_POINTER |
  4181.          FORM_MANAGER.FIELD_POSITION_NOT_FOUND => 
  4182.         return FALSE;
  4183.     end IN_FIELD;
  4184.  
  4185. -------------------------------------------------------------------------
  4186. -- Abstract   : This procedure transforms the value of a non-text field
  4187. --              for display on the terminal display.  The field is then
  4188. --              displayed on the terminal.
  4189. -------------------------------------------------------------------------
  4190. -- Parameters : POSITION  - The field's beginning screen position
  4191. --              LEN       - The field's length
  4192. --              RENDITION - The field's display rendition
  4193. --              LIMITS    - The field's character limitations
  4194. --              INIT      - The field's initial value
  4195. --              MODE      - The field's display mode
  4196. -------------------------------------------------------------------------
  4197. -- Algorithm  : If the given field is a text field then the value passed
  4198. --              in through INIT is simply displayed.  If the field is a
  4199. --              non_text field, then the INIT value is altered to reflect
  4200. --              the field's character limitations.  The character codes
  4201. --              for the limitations are as follows:
  4202. -- 
  4203. --                      a - Alphabetic
  4204. --                      n - Numeric
  4205. --                      b - Alphanumeric
  4206. --                      x - Not Limited
  4207. -- 
  4208. --              Enough of these character codes will be displayed to also
  4209. --              indicate the length of the field.
  4210. -------------------------------------------------------------------------
  4211.     procedure TRANSFORM_AND_PUT_FIELD
  4212.          (POSITION  : FORM_MANAGER.FIELD_POSITION;
  4213.           LEN       : FORM_MANAGER.FIELD_LENGTH;
  4214.           RENDITION : FORM_MANAGER.FIELD_RENDITIONS;
  4215.           LIMITS    : FORM_MANAGER.CHAR_TYPE;
  4216.           INIT      : FORM_MANAGER.FIELD_VALUE;
  4217.           MODE      : FORM_MANAGER.FIELD_MODE) is
  4218.  
  4219.     TEMP_INIT : FORM_MANAGER.FIELD_VALUE;
  4220.  
  4221.     begin
  4222.  
  4223. -- If not constant text, then transform the field's initial value.
  4224.  
  4225.     if MODE /= FORM_MANAGER.CONSTANT_TEXT then
  4226.         case LIMITS is
  4227.         when FORM_MANAGER.ALPHA => 
  4228.             TEMP_INIT (1 .. LEN) := (1 .. LEN => 'a');
  4229.  
  4230.         when FORM_MANAGER.NUMERIC => 
  4231.             TEMP_INIT (1 .. LEN) := (1 .. LEN => 'n');
  4232.  
  4233.         when FORM_MANAGER.ALPHA_NUMERIC => 
  4234.             TEMP_INIT (1 .. LEN) := (1 .. LEN => 'b');
  4235.  
  4236.         when FORM_MANAGER.NOT_LIMITED => 
  4237.             TEMP_INIT (1 .. LEN) := (1 .. LEN => 'x');
  4238.  
  4239.         end case;
  4240.     else
  4241.  
  4242.         -- Otherwise, simply display the field's original initial value.
  4243.  
  4244.         TEMP_INIT := INIT;
  4245.     end if;
  4246.  
  4247.     TERMINAL_INTERFACE.PUT_FIELD (POSITION, LEN, RENDITION, TEMP_INIT);
  4248.  
  4249.     end TRANSFORM_AND_PUT_FIELD;
  4250.  
  4251. -------------------------------------------------------------------------
  4252. -- Abstract   : This procedure allows the user to indicate a new cursor
  4253. --              position using the arrow keys.
  4254. -------------------------------------------------------------------------
  4255. -- Parameters : OLD_POS - The original cursor position.
  4256. --              NEW_POS - The cursor position indicated by the user.
  4257. -------------------------------------------------------------------------
  4258.     procedure GET_CURSOR_POSITION
  4259.          (OLD_POS : FORM_MANAGER.FIELD_POSITION;
  4260.           NEW_POS : in out FORM_MANAGER.FIELD_POSITION) is
  4261.  
  4262.     CHAR     : CHARACTER;
  4263.     CHARTYPE : TERMINAL_INTERFACE.CHAR_ENUM;
  4264.     FUNCT    : TERMINAL_INTERFACE.FUNCTION_KEY_ENUM;
  4265.  
  4266.     begin
  4267.     NEW_POS := OLD_POS;
  4268.     TERMINAL_INTERFACE.GET_CHARACTER (CHARTYPE, CHAR, FUNCT);
  4269.  
  4270.     -- Retrieve arrow keys until a RETURN_KEY is encountered.
  4271.  
  4272.     while (CHARTYPE /= TERMINAL_INTERFACE.FUNC_TYPE or else
  4273.            FUNCT /= TERMINAL_INTERFACE.RETURN_KEY) loop
  4274.         case CHARTYPE is
  4275.         when TERMINAL_INTERFACE.TIMEOUT |
  4276.              TERMINAL_INTERFACE.CHAR_TYPE => 
  4277.             null;
  4278.         when TERMINAL_INTERFACE.FUNC_TYPE => 
  4279.             case FUNCT is
  4280.  
  4281.             when TERMINAL_INTERFACE.DOWN_ARROW => 
  4282.                 if NEW_POS.LINE + 1 > CURRENT_SIZE.ROWS then
  4283.                 NEW_POS.LINE := 1;
  4284.                 else
  4285.                 NEW_POS.LINE := NEW_POS.LINE + 1;
  4286.                 end if;
  4287.                 TERMINAL_INTERFACE.PUT_CURSOR
  4288.                    ((CURRENT_POSITION.LINE + NEW_POS.LINE - 1,
  4289.                  CURRENT_POSITION.COLUMN + NEW_POS.COLUMN - 1));
  4290.  
  4291.             when TERMINAL_INTERFACE.UP_ARROW => 
  4292.                 if NEW_POS.LINE = 1 then
  4293.                 NEW_POS.LINE := CURRENT_SIZE.ROWS;
  4294.                 else
  4295.                 NEW_POS.LINE := NEW_POS.LINE - 1;
  4296.                 end if;
  4297.                 TERMINAL_INTERFACE.PUT_CURSOR
  4298.                    ((CURRENT_POSITION.LINE + NEW_POS.LINE - 1,
  4299.                  CURRENT_POSITION.COLUMN + NEW_POS.COLUMN - 1));
  4300.  
  4301.             when TERMINAL_INTERFACE.LEFT_ARROW => 
  4302.                 if NEW_POS.COLUMN = 1 then
  4303.                 NEW_POS.COLUMN := CURRENT_SIZE.COLUMNS;
  4304.                 else
  4305.                 NEW_POS.COLUMN := NEW_POS.COLUMN - 1;
  4306.                 end if;
  4307.                 TERMINAL_INTERFACE.PUT_CURSOR
  4308.                    ((CURRENT_POSITION.LINE + NEW_POS.LINE - 1,
  4309.                  CURRENT_POSITION.COLUMN + NEW_POS.COLUMN - 1));
  4310.  
  4311.             when TERMINAL_INTERFACE.RIGHT_ARROW => 
  4312.                 if NEW_POS.COLUMN + 1 > CURRENT_SIZE.COLUMNS then
  4313.                 NEW_POS.COLUMN := 1;
  4314.                 else
  4315.                 NEW_POS.COLUMN := NEW_POS.COLUMN + 1;
  4316.                 end if;
  4317.                 TERMINAL_INTERFACE.PUT_CURSOR
  4318.                    ((CURRENT_POSITION.LINE + NEW_POS.LINE - 1,
  4319.                  CURRENT_POSITION.COLUMN + NEW_POS.COLUMN - 1));
  4320.  
  4321.             when others => 
  4322.                 null;
  4323.             end case;
  4324.         end case;
  4325.  
  4326.         TERMINAL_INTERFACE.GET_CHARACTER (CHARTYPE, CHAR, FUNCT);
  4327.     end loop;
  4328.     end GET_CURSOR_POSITION;
  4329.  
  4330. -----------------------------------------------------------------------
  4331.  
  4332. -- Separate commands of the Form Editor.
  4333.  
  4334.     procedure MODIFY_FIELD (MOD_TYPE : FIELD_MODIFICATION_TYPE) is separate;
  4335.     procedure DUPLICATE_FIELD (DUP_TYPE : FIELD_DUPLICATION_TYPE) is separate;
  4336.     procedure DELETE_FIELD is separate;
  4337.     procedure INSERT_LINE is separate;
  4338.     procedure DUPLICATE_LINE (DUP_TYPE : LINE_DUPLICATION_TYPE) is separate;
  4339.     procedure DELETE_LINE is separate;
  4340.     procedure INSERT_CHARACTER is separate;
  4341.     procedure DELETE_CHARACTER is separate;
  4342.     procedure RUBOUT_CHARACTER is separate;
  4343.     procedure HELP is separate;
  4344.     procedure COM_LINE is separate;
  4345.  
  4346.  
  4347. -------------------------------------------------------------------------
  4348. -- Abstract   : This procedure is the actual body of the Editor driver.
  4349. -------------------------------------------------------------------------
  4350. -- Parameters : CURRENT - The Current Form
  4351. -------------------------------------------------------------------------
  4352.     procedure EDITOR_DRIVER (CURRENT : in out FORM_MANAGER.FORM_ACCESS) is
  4353. -- This is the driver routine for the Form Editor.  This routine fields and
  4354. --   services all user requests for the interactive creation and modificatio
  4355. --   of a form.  Fields can be created, modified, moved, copied, and deleted
  4356. --   Lines can be inserted, moved, copied, and deleted.  Text characters can
  4357. --   be inserted, deleted, and rubbed out.  A list of user commands can also
  4358.  
  4359.     begin
  4360.  
  4361.     -- Set up the Current Form attributes.
  4362.  
  4363.     CURRENT_FORM := CURRENT;
  4364.     FORM_MANAGER.GET_FORM_INFO
  4365.        (CURRENT_FORM, CURRENT_SIZE, CURRENT_POSITION, CURRENT_OPTION);
  4366.  
  4367.     -- Position cursor in upper, left-hand corner of the form.
  4368.  
  4369.     CURSOR := (1, 1);
  4370.  
  4371.     loop
  4372.         TERMINAL_INTERFACE.PUT_CURSOR
  4373.            ((CURSOR.LINE + CURRENT_POSITION.LINE - 1,
  4374.          CURSOR.COLUMN + CURRENT_POSITION.COLUMN - 1));
  4375.         TERMINAL_INTERFACE.GET_CHARACTER (CHARTYPE, CHAR, FUNCT);
  4376.  
  4377.         case CHARTYPE is
  4378.  
  4379.         when TERMINAL_INTERFACE.TIMEOUT => 
  4380.             null;
  4381.  
  4382.         when TERMINAL_INTERFACE.FUNC_TYPE => 
  4383.  
  4384.             case FUNCT is
  4385.  
  4386. -- Arrow key processing...
  4387.  
  4388.             when TERMINAL_INTERFACE.DOWN_ARROW |
  4389.                  TERMINAL_INTERFACE.RETURN_KEY => 
  4390.                 if CURSOR.LINE + 1 > CURRENT_SIZE.ROWS then
  4391.                 CURSOR.LINE := 1;
  4392.                 else
  4393.                 CURSOR.LINE := CURSOR.LINE + 1;
  4394.                 end if;
  4395.                 if FUNCT = TERMINAL_INTERFACE.RETURN_KEY then
  4396.                 CURSOR.COLUMN := 1;
  4397.                 end if;
  4398.  
  4399.             when TERMINAL_INTERFACE.UP_ARROW => 
  4400.                 if CURSOR.LINE = 1 then
  4401.                 CURSOR.LINE := CURRENT_SIZE.ROWS;
  4402.                 else
  4403.                 CURSOR.LINE := CURSOR.LINE - 1;
  4404.                 end if;
  4405.  
  4406.             when TERMINAL_INTERFACE.LEFT_ARROW => 
  4407.                 if CURSOR.COLUMN = 1 then
  4408.                 CURSOR.COLUMN := CURRENT_SIZE.COLUMNS;
  4409.                 else
  4410.                 CURSOR.COLUMN := CURSOR.COLUMN - 1;
  4411.                 end if;
  4412.  
  4413.             when TERMINAL_INTERFACE.RIGHT_ARROW => 
  4414.                 if CURSOR.COLUMN + 1 > CURRENT_SIZE.COLUMNS then
  4415.                 CURSOR.COLUMN := 1;
  4416.                 else
  4417.                 CURSOR.COLUMN := CURSOR.COLUMN + 1;
  4418.                 end if;
  4419.  
  4420.                 -- This is the only normal exit from the Form
  4421.                 -- Editor.
  4422.  
  4423.  
  4424.             when TERMINAL_INTERFACE.EXIT_FORM => 
  4425.                 raise EDITOR_DRIVER_EXIT;
  4426.  
  4427.                 -- Other Form Editor command processing...
  4428.  
  4429.             when TERMINAL_INTERFACE.COMMAND_LINE => 
  4430.                 COM_LINE;
  4431.             when TERMINAL_INTERFACE.HELP => 
  4432.                 HELP;
  4433.             when TERMINAL_INTERFACE.DEL_CHAR => 
  4434.                 DELETE_CHARACTER;
  4435.             when TERMINAL_INTERFACE.INS_CHAR => 
  4436.                 INSERT_CHARACTER;
  4437.             when TERMINAL_INTERFACE.RUBOUT => 
  4438.                 RUBOUT_CHARACTER;
  4439.             when TERMINAL_INTERFACE.COPY_LINE => 
  4440.                 DUPLICATE_LINE (COPY);
  4441.             when TERMINAL_INTERFACE.DEL_LINE => 
  4442.                 DELETE_LINE;
  4443.             when TERMINAL_INTERFACE.INS_LINE => 
  4444.                 INSERT_LINE;
  4445.             when TERMINAL_INTERFACE.MOVE_LINE => 
  4446.                 DUPLICATE_LINE (MOVE);
  4447.             when TERMINAL_INTERFACE.COPY_FIELD => 
  4448.                 DUPLICATE_FIELD (COPY);
  4449.             when TERMINAL_INTERFACE.CREATE_FIELD => 
  4450.                 MODIFY_FIELD (CREATE);
  4451.             when TERMINAL_INTERFACE.DEL_FIELD => 
  4452.                 DELETE_FIELD;
  4453.             when TERMINAL_INTERFACE.MODIFY_FIELD => 
  4454.                 MODIFY_FIELD (MODIFY);
  4455.             when TERMINAL_INTERFACE.MOVE_FIELD => 
  4456.                 DUPLICATE_FIELD (MOVE);
  4457.             when others => 
  4458.                 TERMINAL_INTERFACE.PUT_MESSAGE
  4459.                    ("Illegal function key");
  4460.  
  4461.             end case;
  4462.  
  4463.         when TERMINAL_INTERFACE.CHAR_TYPE => 
  4464.  
  4465. -- Character processing...
  4466.  
  4467.             if IN_FIELD (CURSOR) then
  4468.             TERMINAL_INTERFACE.PUT_MESSAGE
  4469.                ("Cannot enter text in field"  -- Cannot enter text
  4470.                               -- character into
  4471.                               -- fields!!
  4472.                 );
  4473.             else
  4474.  
  4475.             begin
  4476.  
  4477.                 -- Check to see if the cursor is positioned in a
  4478.                 -- text field.
  4479.                 --   If so, place the character into the text field
  4480.                 --   in overstrike mode.
  4481.  
  4482.                 FIELD := FORM_MANAGER.GET_FIELD_POINTER
  4483.                     (CURRENT_FORM, CURSOR);
  4484.                 FORM_MANAGER.GET_FIELD_INFO
  4485.                    (FIELD, NAME, POSITION, LENGTH, RENDITION,
  4486.                 CHAR_LIMITS, INIT_VALUE, VALUE, MODE);
  4487.  
  4488.                 INIT_VALUE (CURSOR.COLUMN - POSITION.COLUMN + 1) :=
  4489.                   CHAR;
  4490.                 FORM_MANAGER.MODIFY_FIELD_INIT (FIELD, INIT_VALUE);
  4491.             exception
  4492.                 when CONSTRAINT_ERROR => 
  4493.                 TERMINAL_INTERFACE.PUT_MESSAGE
  4494.                    ("Constraint error on field initial value");
  4495.  
  4496.                 when FORM_MANAGER.NULL_FORM_POINTER => 
  4497.                 TERMINAL_INTERFACE.PUT_MESSAGE
  4498.                    ("No Current Form!");
  4499.  
  4500.                 when FORM_MANAGER.FIELD_POSITION_NOT_FOUND => 
  4501.  
  4502. -- When the cursor was not positioned in a field at all, then
  4503. --   create a new field with this character in it.  Also, an
  4504. --   attempt will be made to merge this new text field with
  4505. --   other adjacent text fields.
  4506.  
  4507.                 begin
  4508.  
  4509.                     -- Add the character to the form in a field
  4510.                     -- of its own.
  4511.  
  4512.                     FORM_MANAGER.ADD_FIELD
  4513.                        (CURRENT_FORM, "", CURSOR, 1,
  4514.                     INIT_VALUE => STRING'(1 => CHAR),
  4515.                     MODE => FORM_MANAGER.CONSTANT_TEXT,
  4516.                     FIELD => FIELD);
  4517.  
  4518.                     -- Allow merging to the left if the previous
  4519.                     -- field was a
  4520.                     --   constant text field also.
  4521.  
  4522.                     begin
  4523.                     PREV_FIELD :=
  4524.                       FORM_MANAGER.GET_PREVIOUS_FIELD
  4525.                          (FIELD);
  4526.                     FORM_MANAGER.GET_FIELD_INFO
  4527.                        (PREV_FIELD, PREV_NAME, PREV_POS,
  4528.                         PREV_LEN, PREV_REND, PREV_LIMITS,
  4529.                         PREV_INIT, PREV_VAL, PREV_MODE);
  4530.                     MERGE_LEFT :=
  4531.                       (PREV_MODE =
  4532.                        FORM_MANAGER.CONSTANT_TEXT) and then
  4533.                       (PREV_POS.LINE = CURSOR.LINE);
  4534.                     exception
  4535.                     when FORM_MANAGER.FIELD_NOT_FOUND => 
  4536.                         MERGE_LEFT := FALSE;
  4537.                     end;
  4538.  
  4539.                     -- Allow merging to the right if the next
  4540.                     -- field was a
  4541.                     --   constant text field also.
  4542.  
  4543.                     begin
  4544.                     NEXT_FIELD :=
  4545.                       FORM_MANAGER.GET_NEXT_FIELD (FIELD);
  4546.                     FORM_MANAGER.GET_FIELD_INFO
  4547.                        (NEXT_FIELD, NEXT_NAME, NEXT_POS,
  4548.                         NEXT_LEN, NEXT_REND, NEXT_LIMITS,
  4549.                         NEXT_INIT, NEXT_VAL, NEXT_MODE);
  4550.                     MERGE_RIGHT :=
  4551.                       (NEXT_MODE =
  4552.                        FORM_MANAGER.CONSTANT_TEXT) and then
  4553.                       (NEXT_POS.LINE = CURSOR.LINE);
  4554.                     exception
  4555.                     when FORM_MANAGER.FIELD_NOT_FOUND => 
  4556.                         MERGE_RIGHT := FALSE;
  4557.                     end;
  4558.  
  4559.                     if MERGE_LEFT then
  4560.                     if MERGE_RIGHT then
  4561.  
  4562.                         -- Merge both the previous and the
  4563.                         -- next fields with this
  4564.                         --   single character field
  4565.                         -- resulting in one long field.
  4566.  
  4567.                         FORM_MANAGER.DELETE_FIELD (FIELD);
  4568.                         FORM_MANAGER.DELETE_FIELD
  4569.                            (NEXT_FIELD);
  4570.  
  4571.                         FORM_MANAGER.MODIFY_FIELD_LENGTH
  4572.                            (PREV_FIELD,
  4573.                         NEXT_POS.COLUMN + NEXT_LEN -
  4574.                         PREV_POS.COLUMN);
  4575.  
  4576.                         PREV_INIT
  4577.                            (CURSOR.COLUMN -
  4578.                         PREV_POS.COLUMN + 1) := CHAR;
  4579.                         PREV_INIT
  4580.                            ((NEXT_POS.COLUMN -
  4581.                          PREV_POS.COLUMN + 1) ..
  4582.                         (NEXT_POS.COLUMN + NEXT_LEN -
  4583.                          PREV_POS.COLUMN)) :=
  4584.                           NEXT_INIT (1 .. NEXT_LEN);
  4585.                         FORM_MANAGER.MODIFY_FIELD_INIT
  4586.                            (PREV_FIELD, PREV_INIT);
  4587.  
  4588.                     else
  4589.  
  4590.                         -- Merge the previous field with
  4591.                         -- this single character
  4592.                         --   field.
  4593.  
  4594.                         FORM_MANAGER.DELETE_FIELD (FIELD);
  4595.  
  4596.                         FORM_MANAGER.MODIFY_FIELD_LENGTH
  4597.                            (PREV_FIELD,
  4598.                         CURSOR.COLUMN -
  4599.                         PREV_POS.COLUMN + 1);
  4600.  
  4601.                         PREV_INIT
  4602.                            (CURSOR.COLUMN -
  4603.                         PREV_POS.COLUMN + 1) := CHAR;
  4604.                         FORM_MANAGER.MODIFY_FIELD_INIT
  4605.                            (PREV_FIELD, PREV_INIT);
  4606.  
  4607.                     end if;
  4608.                     elsif MERGE_RIGHT then
  4609.  
  4610.                     -- Merge the next field with this single
  4611.                     -- character
  4612.                     --   field.
  4613.  
  4614.                     FORM_MANAGER.DELETE_FIELD (NEXT_FIELD);
  4615.  
  4616.                     FORM_MANAGER.MODIFY_FIELD_LENGTH
  4617.                        (FIELD,
  4618.                         NEXT_POS.COLUMN + NEXT_LEN -
  4619.                         CURSOR.COLUMN);
  4620.  
  4621.                     FORM_MANAGER.MODIFY_FIELD_INIT
  4622.                        (FIELD,
  4623.                         CHAR &
  4624.                         (1 .. NEXT_POS.COLUMN -
  4625.                           CURSOR.COLUMN - 1 => ' ') &
  4626.                         NEXT_INIT &
  4627.                         (1 .. FORM_MANAGER
  4628.                            .MAX_FIELD_VALUE +
  4629.                           NEXT_LEN - NEXT_POS.COLUMN +
  4630.                           1 => ' '));
  4631.  
  4632.                     end if;
  4633.  
  4634.                 exception
  4635.                     when FORM_MANAGER.FIELD_ALLOCATION_ERROR => 
  4636.                     TERMINAL_INTERFACE.PUT_MESSAGE
  4637.                        ("Could not add field -- " &
  4638.                         "Memory full");
  4639.  
  4640.                 end;
  4641.  
  4642.             end;
  4643.  
  4644.             -- Output the character to the terminal display, and
  4645.             -- update the
  4646.             --   cursor position.
  4647.  
  4648.             TERMINAL_INTERFACE.PUT_CHARACTER
  4649.                (CHAR,
  4650.                 (CURSOR.LINE + CURRENT_POSITION.LINE - 1,
  4651.                  CURSOR.COLUMN + CURRENT_POSITION.COLUMN - 1));
  4652.  
  4653.             if CURSOR.COLUMN + 1 > CURRENT_SIZE.COLUMNS then
  4654.                 CURSOR.COLUMN := CURRENT_SIZE.COLUMNS;
  4655.             else
  4656.                 CURSOR.COLUMN := CURSOR.COLUMN + 1;
  4657.             end if;
  4658.  
  4659.             end if;
  4660.  
  4661.         end case;
  4662.  
  4663.     end loop;
  4664.  
  4665.     exception
  4666.     when EDITOR_DRIVER_EXIT =>  null;
  4667.  
  4668.     end EDITOR_DRIVER;
  4669.  
  4670. end EDITOR;
  4671. ::::::::::
  4672. EDITOR_SPEC.ADA
  4673. ::::::::::
  4674. -------------------------------------------------------------------------
  4675. -- Abstract   : This is the package specification for the driver of the
  4676. --              Form Editor.  This package only has one visible entry,
  4677. --              the procedure EDITOR_DRIVER.
  4678. -------------------------------------------------------------------------
  4679. -- Parameters : CURRENT - The Current Form
  4680. -------------------------------------------------------------------------
  4681. with FORM_MANAGER;
  4682. with TERMINAL_INTERFACE;
  4683. with FORM_EXECUTOR;
  4684. with FORM_TYPES;
  4685. with FORMS;
  4686.  
  4687. package EDITOR is
  4688.  
  4689.     procedure EDITOR_DRIVER (CURRENT : in out FORM_MANAGER.FORM_ACCESS);
  4690.  
  4691. end EDITOR;
  4692. ::::::::::
  4693. EXECUTOR_BODY.ADA
  4694. ::::::::::
  4695. --------------------------------------------------------------------------
  4696. -- Abstract   : This package defines the body of the Form Executor which
  4697. --              allows a user program interface with a form and the user.
  4698. --------------------------------------------------------------------------
  4699.  
  4700. with FORM_MANAGER,
  4701.      TERMINAL_INTERFACE;
  4702.  
  4703. use FORM_MANAGER, TERMINAL_INTERFACE;
  4704.  
  4705. package body FORM_EXECUTOR is
  4706.  
  4707.  
  4708.     OPEN_FORMS : NATURAL := 0;
  4709.  
  4710.  
  4711. --------------------------------------------------------------------------
  4712. -- Abstract   : ACCESS_FORM loads a form definition from an external file
  4713. --              and returns a pointer to the form data structure.
  4714. --------------------------------------------------------------------------
  4715. -- Parameters : PATHNAME - name of file which contains the form definition
  4716. --------------------------------------------------------------------------
  4717.     function ACCESS_FORM (PATHNAME : STRING) return FORM_PTR is
  4718.  
  4719.     FORM : FORM_PTR;    -- data base file pathname
  4720.  
  4721.     begin
  4722.  
  4723.     FORM_MANAGER.LOAD_FORM (PATHNAME, FORM);
  4724.  
  4725.     if OPEN_FORMS = 0 then
  4726.         TERMINAL_INTERFACE.OPEN;
  4727.     end if;
  4728.  
  4729.     OPEN_FORMS := OPEN_FORMS + 1;
  4730.  
  4731.     return FORM;
  4732.  
  4733.     exception
  4734.     when FORM_MANAGER.FILE_NOT_FOUND | FORM_MANAGER.FILE_ALREADY_OPEN => 
  4735.         raise FORM_ACCESS_ERROR;
  4736.  
  4737.     end ACCESS_FORM;
  4738.  
  4739.  
  4740. --------------------------------------------------------------------------
  4741. -- Abstract   : CLEAR_FORM sets the current values of each field of the
  4742. --              form to their initial value.
  4743. --------------------------------------------------------------------------
  4744. -- Parameters : FORM - pointer to the form data structure
  4745. --------------------------------------------------------------------------
  4746.     procedure CLEAR_FORM (FORM : FORM_PTR) is
  4747.  
  4748.     begin
  4749.  
  4750.     FORM_MANAGER.CLEAR_FORM (FORM);
  4751.  
  4752.     exception
  4753.     when FORM_MANAGER.NULL_FORM_POINTER => 
  4754.         raise INVALID_FORM;
  4755.  
  4756.     end CLEAR_FORM;
  4757.  
  4758.  
  4759. --------------------------------------------------------------------------
  4760. -- Abstract   : MODIFY_FIELD modifies the value of specific field of a
  4761. --              form given is name.
  4762. --------------------------------------------------------------------------
  4763. -- Parameters : FORM - form data structure pointer
  4764. --              FIELD - name of the field to be modified
  4765. --              VALUE - new value of the field when it is displayed
  4766. --------------------------------------------------------------------------
  4767.     procedure MODIFY_FIELD (FORM  : FORM_PTR;
  4768.                 FIELD : STRING;
  4769.                 VALUE : STRING) is
  4770.  
  4771.     FIELD_PTR : FORM_MANAGER.FIELD_ACCESS;
  4772.  
  4773.     begin
  4774.  
  4775.     FIELD_PTR := FORM_MANAGER.GET_FIELD_POINTER (FORM, FIELD);
  4776.     FORM_MANAGER.MODIFY_FIELD_VALUE (FIELD_PTR, VALUE);
  4777.  
  4778.     exception
  4779.     when FORM_MANAGER.NULL_FORM_POINTER => 
  4780.         raise INVALID_FORM;
  4781.     when FORM_MANAGER.CONSTANT_FIELD_ERROR |
  4782.          FORM_MANAGER.FIELD_NAME_NOT_FOUND |
  4783.          FORM_MANAGER.NULL_FIELD_POINTER => 
  4784.         raise INVALID_FIELD;
  4785.  
  4786.     end MODIFY_FIELD;
  4787.  
  4788.  
  4789. --------------------------------------------------------------------------
  4790. -- Abstract   : PRESENT_FORM displays the form on the terminal and
  4791. --              interacts with the user to modify the contents of the
  4792. --              input fields.
  4793. --------------------------------------------------------------------------
  4794. -- Parameters : FORM - form data structure
  4795. --              BELL - signal bell after form is displayed
  4796. --              FIELD - the field to position the cursor at
  4797. --------------------------------------------------------------------------
  4798. -- Algorithm  : The current value of each field is displayed, the bell
  4799. --              is optionally rung, and then input information into the
  4800. --              fields.
  4801. --------------------------------------------------------------------------
  4802.     procedure PRESENT_FORM (FORM  : FORM_PTR;
  4803.                 BELL  : BOOLEAN := FALSE;
  4804.                 FIELD : STRING := "") is
  4805.  
  4806.     CLEAR_OPTION  : FORM_MANAGER.OPTION_TYPE;
  4807.     BASE_POSITION : FORM_MANAGER.FORM_POSITION;
  4808.     SIZE          : FORM_MANAGER.FORM_SIZE;
  4809.  
  4810.     FIELD_PTR     : FORM_MANAGER.FIELD_ACCESS;
  4811.     CHAR_LIMITS   : FORM_MANAGER.CHAR_TYPE;
  4812.     LENGTH        : FORM_MANAGER.FIELD_LENGTH;
  4813.     MODE          : FORM_MANAGER.FIELD_MODE;
  4814.     NAME          : FORM_MANAGER.FIELD_NAME;
  4815.     POSITION      : FORM_MANAGER.FIELD_POSITION;
  4816.     RENDITION     : FORM_MANAGER.FIELD_RENDITIONS;
  4817.     VALUE         : FORM_MANAGER.FIELD_VALUE;
  4818.  
  4819.     procedure GET_INFO (FIELD : FORM_MANAGER.FIELD_ACCESS) is
  4820. -- get field information
  4821.     begin
  4822.         FORM_MANAGER.GET_FIELD_INFO
  4823.            (FIELD, NAME, POSITION, LENGTH, RENDITION, CHAR_LIMITS, VALUE,
  4824.         VALUE, MODE);
  4825.     end GET_INFO;
  4826.  
  4827.     procedure EDIT_FORM is
  4828. -- edit input fields of form
  4829.         CHAR     : CHARACTER;
  4830.         CHARTYPE : TERMINAL_INTERFACE.CHAR_ENUM;
  4831.         FUNCT    : TERMINAL_INTERFACE.FUNCTION_KEY_ENUM;
  4832.  
  4833.         procedure EDIT_FIELD is
  4834. -- edit the contents of a field
  4835.         I  : NATURAL;
  4836.         OK : BOOLEAN;
  4837.         begin
  4838.         POSITION.LINE := POSITION.LINE + BASE_POSITION.LINE - 1;
  4839.         POSITION.COLUMN := POSITION.COLUMN + BASE_POSITION.COLUMN - 1;
  4840.         loop
  4841.             TERMINAL_INTERFACE.EDIT_FIELD
  4842.                (POSITION, LENGTH, RENDITION, VALUE);
  4843.             OK := TRUE;
  4844.             if CHAR_LIMITS /= FORM_MANAGER.NOT_LIMITED then
  4845.             for I in 1 .. LENGTH loop
  4846.                 case VALUE (I) is
  4847.                 when ' ' =>  -- blanks ok anytime
  4848.                     null;
  4849.                 when '0' .. '9' => 
  4850.                     if CHAR_LIMITS = FORM_MANAGER.ALPHA then
  4851.                     OK := FALSE;
  4852.                     end if;
  4853.                 when 'A' .. 'Z' | 'a' .. 'z' | '_' => 
  4854.                     if CHAR_LIMITS = FORM_MANAGER.NUMERIC then
  4855.                     OK := FALSE;
  4856.                     end if;
  4857.                 when '$' | '%' | '+' => 
  4858.                     if CHAR_LIMITS /= FORM_MANAGER.NUMERIC then
  4859.                     OK := FALSE;
  4860.                     end if;
  4861.                 when ''' => 
  4862.                     if CHAR_LIMITS = FORM_MANAGER.NUMERIC then
  4863.                     OK := FALSE;
  4864.                     end if;
  4865.                 when ',' | '.' | '-' => 
  4866.                     null;
  4867.                 when others => 
  4868.                     OK := FALSE;
  4869.                 end case;
  4870.                 exit when not OK;
  4871.             end loop;
  4872.             end if;
  4873.             if not OK then
  4874.             TERMINAL_INTERFACE.GET_CHARACTER
  4875.                (CHARTYPE, CHAR, FUNCT);
  4876.             case CHAR_LIMITS is
  4877.                 when FORM_MANAGER.ALPHA => 
  4878.                 TERMINAL_INTERFACE.PUT_MESSAGE
  4879.                    ("Alphabetic Field");
  4880.                 when FORM_MANAGER.ALPHA_NUMERIC => 
  4881.                 TERMINAL_INTERFACE.PUT_MESSAGE
  4882.                    ("Alphanumeric Field");
  4883.                 when FORM_MANAGER.NUMERIC => 
  4884.                 TERMINAL_INTERFACE.PUT_MESSAGE
  4885.                    ("Numeric Field");
  4886.                 when others => 
  4887.                 null;
  4888.             end case;
  4889.             else
  4890.             exit;
  4891.             end if;
  4892.         end loop;
  4893.         FORM_MANAGER.MODIFY_FIELD_VALUE (FIELD_PTR, VALUE);
  4894.         end EDIT_FIELD;
  4895.  
  4896.         function FIRST_FIELD (FORM : FORM_MANAGER.FORM_ACCESS)
  4897.                    return FORM_MANAGER.FIELD_ACCESS is
  4898. -- get the first input field of a form
  4899.         FIELD : FORM_MANAGER.FIELD_ACCESS;
  4900.         begin
  4901.         FIELD := FORM_MANAGER.GET_FIRST_FIELD (FORM);
  4902.         loop
  4903.             GET_INFO (FIELD);
  4904.             exit when MODE = FORM_MANAGER.INPUT_OUTPUT;
  4905.             FIELD := FORM_MANAGER.GET_NEXT_FIELD (FIELD);
  4906.         end loop;
  4907.         return FIELD;
  4908.         end FIRST_FIELD;
  4909.  
  4910.         function NEXT_FIELD (FIELD : FORM_MANAGER.FIELD_ACCESS)
  4911.                   return FORM_MANAGER.FIELD_ACCESS is
  4912. -- get the next input field of a form
  4913.         NEXT : FORM_MANAGER.FIELD_ACCESS;
  4914.         begin
  4915.         NEXT := FIELD;
  4916.         loop
  4917.             NEXT := FORM_MANAGER.GET_NEXT_FIELD (NEXT);
  4918.             GET_INFO (NEXT);
  4919.             exit when MODE = FORM_MANAGER.INPUT_OUTPUT;
  4920.         end loop;
  4921.         return NEXT;
  4922.         exception
  4923.         when FORM_MANAGER.FIELD_NOT_FOUND => 
  4924.             GET_INFO (FIELD);
  4925.             return FIELD;
  4926.         end NEXT_FIELD;
  4927.  
  4928.         function PREVIOUS_FIELD (FIELD : FORM_MANAGER.FIELD_ACCESS)
  4929.                       return FORM_MANAGER.FIELD_ACCESS is
  4930. -- get the next input field of a form
  4931.         PREVIOUS : FORM_MANAGER.FIELD_ACCESS;
  4932.         begin
  4933.         PREVIOUS := FIELD;
  4934.         loop
  4935.             PREVIOUS := FORM_MANAGER.GET_PREVIOUS_FIELD (PREVIOUS);
  4936.             GET_INFO (PREVIOUS);
  4937.             exit when MODE = FORM_MANAGER.INPUT_OUTPUT;
  4938.         end loop;
  4939.         return PREVIOUS;
  4940.         exception
  4941.         when FORM_MANAGER.FIELD_NOT_FOUND => 
  4942.             GET_INFO (FIELD);
  4943.             return FIELD;
  4944.         end PREVIOUS_FIELD;
  4945.  
  4946.     begin
  4947.  
  4948.         if FIELD'LAST = 0 then
  4949.         FIELD_PTR := FIRST_FIELD (FORM);
  4950.         else
  4951.         FIELD_PTR := FORM_MANAGER.GET_FIELD_POINTER (FORM, FIELD);
  4952.         GET_INFO (FIELD_PTR);
  4953.         if MODE /= FORM_MANAGER.INPUT_OUTPUT then
  4954.             raise INVALID_FIELD;
  4955.         end if;
  4956.         end if;
  4957.  
  4958.         loop
  4959.         EDIT_FIELD;
  4960.         TERMINAL_INTERFACE.GET_CHARACTER (CHARTYPE, CHAR, FUNCT);
  4961.         if CHARTYPE = TERMINAL_INTERFACE.FUNC_TYPE then
  4962.             case FUNCT is
  4963.             when TERMINAL_INTERFACE.DOWN_ARROW |
  4964.                  TERMINAL_INTERFACE.TAB_KEY =>  -- next field
  4965.                 FIELD_PTR := NEXT_FIELD (FIELD_PTR);
  4966.             when TERMINAL_INTERFACE.UP_ARROW |
  4967.                  TERMINAL_INTERFACE.BACK_TAB =>  -- previous field
  4968.                 FIELD_PTR := PREVIOUS_FIELD (FIELD_PTR);
  4969.             when TERMINAL_INTERFACE.RETURN_KEY =>  -- accept input
  4970.                 return;
  4971.             when others => 
  4972.                 GET_INFO (FIELD_PTR);
  4973.             end case;
  4974.         else
  4975.             GET_INFO (FIELD_PTR);
  4976.         end if;
  4977.         end loop;
  4978.  
  4979.     exception
  4980.         when FORM_MANAGER.FIELD_NOT_FOUND => 
  4981.         raise INVALID_FIELD;
  4982.     end EDIT_FORM;
  4983.  
  4984.     begin
  4985.  
  4986.     FORM_MANAGER.GET_FORM_INFO (FORM, SIZE, BASE_POSITION, CLEAR_OPTION);
  4987.  
  4988.     if CLEAR_OPTION = FORM_MANAGER.CLEAR then
  4989.         TERMINAL_INTERFACE.CLEAR_SCREEN;
  4990.     end if;
  4991.  
  4992.     begin
  4993.         -- display fields
  4994.  
  4995.         FIELD_PTR := FORM_MANAGER.GET_FIRST_FIELD (FORM);
  4996.  
  4997.         loop
  4998.         GET_INFO (FIELD_PTR);
  4999.         POSITION.LINE := POSITION.LINE + BASE_POSITION.LINE - 1;
  5000.         POSITION.COLUMN := POSITION.COLUMN + BASE_POSITION.COLUMN - 1;
  5001.  
  5002.         TERMINAL_INTERFACE.PUT_FIELD
  5003.            (POSITION, LENGTH, RENDITION, VALUE);
  5004.  
  5005.         FIELD_PTR := FORM_MANAGER.GET_NEXT_FIELD (FIELD_PTR);
  5006.         end loop;
  5007.  
  5008.     exception
  5009.         when FORM_MANAGER.FIELD_NOT_FOUND => 
  5010.         null;
  5011.     end;
  5012.  
  5013.     if BELL then
  5014.         null;     -- no routine to ring bell yet
  5015.     end if;
  5016.  
  5017.     EDIT_FORM;
  5018.  
  5019.     exception
  5020.     when FORM_MANAGER.NULL_FORM_POINTER => 
  5021.         raise INVALID_FORM;
  5022.  
  5023.     end PRESENT_FORM;
  5024.  
  5025.  
  5026. --------------------------------------------------------------------------
  5027. -- Abstract   : QUERY_FIELD is used to get the current value of a field.
  5028. --------------------------------------------------------------------------
  5029. -- Parameters : FORM - pointer to the form data structure
  5030. --              FIELD - name of the field get the value for
  5031. --              VALUE - current value of the field
  5032. --------------------------------------------------------------------------
  5033.     procedure QUERY_FIELD (FORM  : FORM_PTR;
  5034.                FIELD : STRING;
  5035.                VALUE : in out STRING) is
  5036.  
  5037.     LENGTH      : NATURAL;
  5038.     LOCAL_VALUE : FORM_MANAGER.FIELD_VALUE;
  5039.  
  5040.     begin
  5041.  
  5042.     LOCAL_VALUE := FORM_MANAGER.GET_FIELD_VALUE (FORM, FIELD);
  5043.     LENGTH := VALUE'LAST - VALUE'FIRST + 1;
  5044.     VALUE (VALUE'FIRST .. VALUE'LAST) := LOCAL_VALUE (1 .. LENGTH);
  5045.  
  5046.     exception
  5047.     when FORM_MANAGER.NULL_FORM_POINTER => 
  5048.         raise INVALID_FORM;
  5049.     when FORM_MANAGER.FIELD_NAME_NOT_FOUND => 
  5050.         raise INVALID_FIELD;
  5051.  
  5052.     end QUERY_FIELD;
  5053.  
  5054.  
  5055. --------------------------------------------------------------------------
  5056. -- Abstract   : RELEASE_FORM releases the form data structure
  5057. --------------------------------------------------------------------------
  5058. -- Parameters : FORM - pointer to the form data structure
  5059. --------------------------------------------------------------------------
  5060.     procedure RELEASE_FORM (FORM : FORM_PTR) is
  5061.  
  5062.     begin
  5063.  
  5064.     FORM_MANAGER.RELEASE_FORM (FORM);
  5065.  
  5066.     OPEN_FORMS := OPEN_FORMS - 1;
  5067.  
  5068.     if OPEN_FORMS = 0 then
  5069.         TERMINAL_INTERFACE.CLOSE;
  5070.     end if;
  5071.  
  5072.     exception
  5073.     when FORM_MANAGER.NULL_FORM_POINTER => 
  5074.         raise INVALID_FORM;
  5075.  
  5076.     end RELEASE_FORM;
  5077.  
  5078.  
  5079. end FORM_EXECUTOR;
  5080. ::::::::::
  5081. EXECUTOR_SPEC.ADA
  5082. ::::::::::
  5083. --------------------------------------------------------------------------
  5084. -- Abstract   : This package defines the interfaces to the Form Executor
  5085. --              which allows a user program to load a form, display it,
  5086. --              and interface with a user at a terminal.
  5087. --------------------------------------------------------------------------
  5088.  
  5089. with FORM_MANAGER;
  5090.  
  5091. package FORM_EXECUTOR is
  5092.  
  5093.     subtype FORM_PTR is FORM_MANAGER.FORM_ACCESS;
  5094.  
  5095. -- open a new form
  5096.     function ACCESS_FORM (PATHNAME : STRING) return FORM_PTR;
  5097.  
  5098.  
  5099. -- get field
  5100.     procedure QUERY_FIELD (FORM  : FORM_PTR;
  5101.                FIELD : STRING;
  5102.                VALUE : in out STRING);
  5103.  
  5104. -- reinitialize field values
  5105.     procedure CLEAR_FORM (FORM : FORM_PTR);
  5106.  
  5107. -- modify field value
  5108.     procedure MODIFY_FIELD (FORM : FORM_PTR; FIELD : STRING; VALUE : STRING);
  5109.  
  5110. -- display form and accept input
  5111.     procedure PRESENT_FORM (FORM  : FORM_PTR;
  5112.                 BELL  : BOOLEAN := FALSE;
  5113.                 FIELD : STRING := "");
  5114.  
  5115.  
  5116. -- release form after use
  5117.     procedure RELEASE_FORM (FORM : FORM_PTR);
  5118.  
  5119. -- Exceptions
  5120.  
  5121.     FORM_ACCESS_ERROR : exception;
  5122.     INVALID_FORM      : exception;
  5123.     INVALID_FIELD     : exception;
  5124.  
  5125. end FORM_EXECUTOR;
  5126. ::::::::::
  5127. FORMS.ADA
  5128. ::::::::::
  5129. -------------------------------------------------------------------------
  5130. -- Abstract   : This package contains all of the form definitions and
  5131. --              operations necessary for executing the Interactive
  5132. --              Form Generator System.
  5133. -------------------------------------------------------------------------
  5134. with FORM_TYPES;
  5135. with FORM_MANAGER;
  5136.  
  5137. package FORMS is
  5138.  
  5139.     MAIN_MENU       : FORM_MANAGER.FORM_ACCESS;
  5140.     FIELD_MENU      : FORM_MANAGER.FORM_ACCESS;
  5141.     FIELD_NAME_MENU : FORM_MANAGER.FORM_ACCESS;
  5142.     FORM_MENU       : FORM_MANAGER.FORM_ACCESS;
  5143.     FORM_FILE_MENU  : FORM_MANAGER.FORM_ACCESS;
  5144.  
  5145.     procedure GET_FIELD_INFO
  5146.          (NAME          : in out FORM_MANAGER.FIELD_NAME;
  5147.           LENGTH        : in out FORM_MANAGER.FIELD_LENGTH;
  5148.           CHAR_LIMITS   : in out FORM_MANAGER.CHAR_TYPE;
  5149.           MODE          : in out FORM_MANAGER.FIELD_MODE;
  5150.           RENDITION     : in out FORM_MANAGER.FIELD_RENDITIONS;
  5151.           INITIAL_VALUE : in out FORM_MANAGER.FIELD_VALUE;
  5152.           CREATE_FIELD  : BOOLEAN);
  5153.  
  5154.     procedure GET_FIELD_NAME (NAME : in out FORM_MANAGER.FIELD_NAME);
  5155.  
  5156.     procedure GET_FILE_NAME (NAME : in out STRING; LOAD_FORM : BOOLEAN);
  5157.  
  5158.     procedure GET_FORM_INFO (SIZE         : in out FORM_MANAGER.FORM_SIZE;
  5159.                  POSITION     : in out FORM_MANAGER.FORM_POSITION;
  5160.                  CLEAR_OPTION : in out FORM_MANAGER.OPTION_TYPE;
  5161.                  CREATE_FORM  : BOOLEAN);
  5162.  
  5163.     procedure INITIALIZE_FORMS;
  5164.  
  5165. end FORMS;
  5166.  
  5167. -------------------------------------------------------------------------
  5168. -------------------------------------------------------------------------
  5169.  
  5170. with FORM_EXECUTOR;
  5171. with TEXT_IO;
  5172.  
  5173. package body FORMS is
  5174.  
  5175.     package INTEGER_IO is new TEXT_IO.INTEGER_IO (INTEGER);
  5176.  
  5177. -----------------------------------------------------------------------
  5178.  
  5179.     -- This procedure retrieves a field value from one of the form's fields.
  5180.  
  5181.     procedure GET_VALUE (FORM     : FORM_MANAGER.FORM_ACCESS;
  5182.              FIELD    : STRING;
  5183.              MIN, MAX : INTEGER;
  5184.              DEFAULT  : INTEGER;
  5185.              VALUE    : out INTEGER) is
  5186.     BUFFER : STRING (1 .. 3);
  5187.     LAST   : POSITIVE;
  5188.     TEMP   : INTEGER;
  5189.     begin
  5190.     FORM_EXECUTOR.QUERY_FIELD (FORM, FIELD, BUFFER);
  5191.     INTEGER_IO.GET (BUFFER, TEMP, LAST);
  5192.     if TEMP >= MIN and TEMP <= MAX then
  5193.         VALUE := TEMP;
  5194.     else
  5195.         VALUE := DEFAULT;
  5196.     end if;
  5197.  
  5198.     exception
  5199.     when TEXT_IO.DATA_ERROR | TEXT_IO.END_ERROR => 
  5200.         VALUE := DEFAULT;
  5201.     end GET_VALUE;
  5202.  
  5203. -----------------------------------------------------------------------
  5204.  
  5205.     -- This puts a new value into the field of one of the form's fields.
  5206.  
  5207.     procedure PUT_VALUE (FORM  : FORM_MANAGER.FORM_ACCESS;
  5208.              FIELD : STRING;
  5209.              VALUE : INTEGER) is
  5210.     BUFFER : STRING (1 .. 3);
  5211.     begin
  5212.     INTEGER_IO.PUT (BUFFER, VALUE);
  5213.     FORM_EXECUTOR.MODIFY_FIELD (FORM, FIELD, BUFFER);
  5214.     end PUT_VALUE;
  5215.  
  5216.  
  5217. -------------------------------------------------------------------------
  5218. -- Abstract   : This procedure presents the menu for retrieving field
  5219. --              values and attributes.
  5220. -------------------------------------------------------------------------
  5221. -- Parameters : NAME           - The field's name.
  5222. --              LENGTH         - The field's length.
  5223. --              CHAR_LIMITS    - The field's character limitations.
  5224. --              MODE           - The field's display mode.
  5225. --              RENDITION      - The field's display rendition.
  5226. --              INITIAL_VALUE  - The field's initial value.
  5227. --              CREATE_FIELD   - A flag indicating whether this field
  5228. --                               information retrieval is for a Create
  5229. --                               Field operation or a Modify Field operation.
  5230. -------------------------------------------------------------------------
  5231. -- Algorithm  : This procedure utilized the Form Executor for retrieving
  5232. --              the field's information.
  5233. -------------------------------------------------------------------------
  5234.  
  5235.     procedure GET_FIELD_INFO
  5236.          (NAME          : in out FORM_MANAGER.FIELD_NAME;
  5237.           LENGTH        : in out FORM_MANAGER.FIELD_LENGTH;
  5238.           CHAR_LIMITS   : in out FORM_MANAGER.CHAR_TYPE;
  5239.           MODE          : in out FORM_MANAGER.FIELD_MODE;
  5240.           RENDITION     : in out FORM_MANAGER.FIELD_RENDITIONS;
  5241.           INITIAL_VALUE : in out FORM_MANAGER.FIELD_VALUE;
  5242.           CREATE_FIELD  : BOOLEAN) is
  5243.  
  5244.     FIELD : FORM_MANAGER.FIELD_ACCESS;
  5245.     VALUE : INTEGER;
  5246.  
  5247.     begin
  5248.     FORM_EXECUTOR.CLEAR_FORM (FIELD_MENU);
  5249.  
  5250.     -- If this request is from Modify Field, then insert the field's
  5251.     --   values and attributes as the initial values for this
  5252.     --   FIELD_MENU.
  5253.  
  5254.     if not CREATE_FIELD then
  5255.  
  5256.         FORM_EXECUTOR.MODIFY_FIELD (FIELD_MENU, "Field Name", NAME);
  5257.         PUT_VALUE (FIELD_MENU, "Field Length", LENGTH);
  5258.  
  5259.         -- Transform character limitations to numeric codes.
  5260.  
  5261.         case CHAR_LIMITS is
  5262.         when FORM_MANAGER.ALPHA => 
  5263.             VALUE := 1;
  5264.         when FORM_MANAGER.NUMERIC => 
  5265.             VALUE := 2;
  5266.         when FORM_MANAGER.ALPHA_NUMERIC => 
  5267.             VALUE := 3;
  5268.         when FORM_MANAGER.NOT_LIMITED => 
  5269.             VALUE := 4;
  5270.         end case;
  5271.         PUT_VALUE (FIELD_MENU, "Field Limits", VALUE);
  5272.  
  5273.         -- Transform the display rendition to numeric codes.
  5274.  
  5275.         case RENDITION is
  5276.         when FORM_TYPES.PRIMARY_RENDITION => 
  5277.             VALUE := 1;
  5278.         when FORM_TYPES.SECONDARY_RENDITION => 
  5279.             VALUE := 2;
  5280.         when FORM_TYPES.REVERSE_RENDITION => 
  5281.             VALUE := 3;
  5282.         when FORM_TYPES.UNDERLINE_RENDITION => 
  5283.             VALUE := 4;
  5284.         end case;
  5285.         PUT_VALUE (FIELD_MENU, "Field Rendition", VALUE);
  5286.  
  5287.         -- Transform the display mode to numeric codes.
  5288.  
  5289.         case MODE is
  5290.         when FORM_MANAGER.INPUT_OUTPUT => 
  5291.             VALUE := 1;
  5292.         when FORM_MANAGER.OUTPUT_ONLY => 
  5293.             VALUE := 2;
  5294.         when others => 
  5295.             VALUE := 0;
  5296.         end case;
  5297.         PUT_VALUE (FIELD_MENU, "Field Mode", VALUE);
  5298.         FORM_EXECUTOR.MODIFY_FIELD
  5299.            (FIELD_MENU, "Initial Value", INITIAL_VALUE);
  5300.     end if;
  5301.  
  5302.     -- If this request is from Modify Field, then do not allow the
  5303.     --   user to modify the field's name.
  5304.  
  5305.     if not CREATE_FIELD then
  5306.         FIELD := FORM_MANAGER.GET_FIELD_POINTER (FIELD_MENU, "Field Name");
  5307.         FORM_MANAGER.MODIFY_FIELD_MODE (FIELD, FORM_MANAGER.OUTPUT_ONLY);
  5308.     end if;
  5309.  
  5310.     -- Present the form to the user.
  5311.  
  5312.     FORM_EXECUTOR.PRESENT_FORM (FIELD_MENU);
  5313.  
  5314.     -- Retrieve the inputs from the user.
  5315.  
  5316.     if CREATE_FIELD then
  5317.         FORM_EXECUTOR.QUERY_FIELD (FIELD_MENU, "Field Name", NAME);
  5318.     end if;
  5319.  
  5320.     GET_VALUE (FIELD_MENU, "Field Length", 1, 80, 10, LENGTH);
  5321.  
  5322.     -- Transform from numeric codes back to character limitations.
  5323.  
  5324.     GET_VALUE (FIELD_MENU, "Field Limits", 1, 4, 4, VALUE);
  5325.     case VALUE is
  5326.         when 1 => 
  5327.         CHAR_LIMITS := FORM_MANAGER.ALPHA;
  5328.         when 2 => 
  5329.         CHAR_LIMITS := FORM_MANAGER.NUMERIC;
  5330.         when 3 => 
  5331.         CHAR_LIMITS := FORM_MANAGER.ALPHA_NUMERIC;
  5332.         when 4 => 
  5333.         CHAR_LIMITS := FORM_MANAGER.NOT_LIMITED;
  5334.         when others => 
  5335.         CHAR_LIMITS := FORM_MANAGER.NOT_LIMITED;
  5336.     end case;
  5337.  
  5338.     -- Transform from numeric codes back to display renditions.
  5339.  
  5340.     GET_VALUE (FIELD_MENU, "Field Rendition", 1, 4, 1, VALUE);
  5341.     case VALUE is
  5342.         when 1 => 
  5343.         RENDITION := FORM_TYPES.PRIMARY_RENDITION;
  5344.         when 2 => 
  5345.         RENDITION := FORM_TYPES.SECONDARY_RENDITION;
  5346.         when 3 => 
  5347.         RENDITION := FORM_TYPES.REVERSE_RENDITION;
  5348.         when 4 => 
  5349.         RENDITION := FORM_TYPES.UNDERLINE_RENDITION;
  5350.         when others => 
  5351.         RENDITION := FORM_TYPES.PRIMARY_RENDITION;
  5352.     end case;
  5353.  
  5354.     -- Transform from numeric codes back to display modes.
  5355.  
  5356.     GET_VALUE (FIELD_MENU, "Field Mode", 1, 2, 1, VALUE);
  5357.     case VALUE is
  5358.         when 1 => 
  5359.         MODE := FORM_MANAGER.INPUT_OUTPUT;
  5360.         when 2 => 
  5361.         MODE := FORM_MANAGER.OUTPUT_ONLY;
  5362.         when others => 
  5363.         MODE := FORM_MANAGER.INPUT_OUTPUT;
  5364.     end case;
  5365.     FORM_EXECUTOR.QUERY_FIELD (FIELD_MENU, "Initial Value", INITIAL_VALUE);
  5366.  
  5367.     -- If Modify Field, then restore the mode of the Field Name field.
  5368.  
  5369.     if not CREATE_FIELD then
  5370.         FORM_MANAGER.MODIFY_FIELD_MODE (FIELD, FORM_MANAGER.INPUT_OUTPUT);
  5371.     end if;
  5372.  
  5373.     end GET_FIELD_INFO;
  5374.  
  5375. -------------------------------------------------------------------------
  5376. -- Abstract   : This procedure is used to retrieve the name of a field
  5377. --              from the user.
  5378. -------------------------------------------------------------------------
  5379. -- Parameters : NAME - The field's name.
  5380. -------------------------------------------------------------------------
  5381. -- Algorithm  : This procedure utilizes the Form Executor for retrieving
  5382. --              the field name from the user.
  5383. -------------------------------------------------------------------------
  5384.  
  5385.     procedure GET_FIELD_NAME (NAME : in out FORM_MANAGER.FIELD_NAME) is
  5386.     begin
  5387.     FORM_EXECUTOR.CLEAR_FORM (FIELD_NAME_MENU);
  5388.     FORM_EXECUTOR.PRESENT_FORM (FIELD_NAME_MENU);
  5389.     FORM_EXECUTOR.QUERY_FIELD (FIELD_NAME_MENU, "Field Name", NAME);
  5390.     end GET_FIELD_NAME;
  5391.  
  5392. -------------------------------------------------------------------------
  5393. -- Abstract   : This procedure is used to retrieve the name of a file
  5394. --              from the user.
  5395. -------------------------------------------------------------------------
  5396. -- Parameters : NAME      - The external file's name.
  5397. --              LOAD_FORM - A flag indicating whether this filename is
  5398. --                          being retrived for Load Form or Save Form.
  5399. -------------------------------------------------------------------------
  5400. -- Algorithm  : This procedure utilizes the Form Executor for retrieving
  5401. --              the file name from the user.
  5402. -------------------------------------------------------------------------
  5403.  
  5404.     procedure GET_FILE_NAME (NAME : in out STRING; LOAD_FORM : BOOLEAN) is
  5405.     begin
  5406.     FORM_EXECUTOR.CLEAR_FORM (FORM_FILE_MENU);
  5407.     if not LOAD_FORM then
  5408.         FORM_EXECUTOR.MODIFY_FIELD (FORM_FILE_MENU, "File Name", NAME);
  5409.     end if;
  5410.     FORM_EXECUTOR.PRESENT_FORM (FORM_FILE_MENU);
  5411.     FORM_EXECUTOR.QUERY_FIELD (FORM_FILE_MENU, "File Name", NAME);
  5412.     end GET_FILE_NAME;
  5413.  
  5414. -------------------------------------------------------------------------
  5415. -- Abstract   : This procedure retrieves the attribute values for a form
  5416. --              from the user.
  5417. -------------------------------------------------------------------------
  5418. -- Parameters : SIZE         - The form's size.
  5419. --              POSITION     - The form's screen position.
  5420. --              CLEAR_OPTION - The form's clear screen option.
  5421. --              CREATE_FORM  - A flag indicating whether this information
  5422. --                             is being retrieved for Create Form or
  5423. --                             Modify Form Attributes.
  5424. -------------------------------------------------------------------------
  5425. -- Algorithm  : This procedure utilizes the Form Executor for retrieving
  5426. --              the form information from the user.
  5427. -------------------------------------------------------------------------
  5428.  
  5429.     procedure GET_FORM_INFO
  5430.          (SIZE         : in out FORM_MANAGER.FORM_SIZE;
  5431.           POSITION     : in out FORM_MANAGER.FORM_POSITION;
  5432.           CLEAR_OPTION : in out FORM_MANAGER.OPTION_TYPE;
  5433.           CREATE_FORM  : BOOLEAN) is
  5434.     BUFFER : STRING (1 .. 4);
  5435.     begin
  5436.     FORM_EXECUTOR.CLEAR_FORM (FORM_MENU);
  5437.  
  5438.     -- If Modify Form Attributes is using this procedure, then
  5439.     --   initialize this menu with the form's attribute values.
  5440.  
  5441.     if not CREATE_FORM then
  5442.         PUT_VALUE (FORM_MENU, "Size Rows", SIZE.ROWS);
  5443.         PUT_VALUE (FORM_MENU, "Size Columns", SIZE.COLUMNS);
  5444.         PUT_VALUE (FORM_MENU, "Position Row", POSITION.LINE);
  5445.         PUT_VALUE (FORM_MENU, "Position Column", POSITION.COLUMN);
  5446.         case CLEAR_OPTION is
  5447.         when FORM_MANAGER.CLEAR => 
  5448.             BUFFER := "Yes ";
  5449.         when FORM_MANAGER.NO_CLEAR => 
  5450.             BUFFER := "No  ";
  5451.         when others =>  null;
  5452.         end case;
  5453.         FORM_EXECUTOR.MODIFY_FIELD (FORM_MENU, "Clear Option", BUFFER);
  5454.     end if;
  5455.  
  5456.     FORM_EXECUTOR.PRESENT_FORM (FORM_MENU);
  5457.  
  5458.     -- Retrieve the user supplied values.
  5459.  
  5460.     GET_VALUE (FORM_MENU, "Size Rows", 1, 24, 24, SIZE.ROWS);
  5461.     GET_VALUE (FORM_MENU, "Size Columns", 1, 80, 80, SIZE.COLUMNS);
  5462.     GET_VALUE (FORM_MENU, "Position Row", 1, 24, 1, POSITION.LINE);
  5463.     GET_VALUE (FORM_MENU, "Position Column", 1, 80, 1, POSITION.COLUMN);
  5464.     FORM_EXECUTOR.QUERY_FIELD (FORM_MENU, "Clear Option", BUFFER);
  5465.     case BUFFER (1) is
  5466.         when 'Y' | 'y' => 
  5467.         CLEAR_OPTION := FORM_MANAGER.CLEAR;
  5468.         when 'N' | 'n' => 
  5469.         CLEAR_OPTION := FORM_MANAGER.NO_CLEAR;
  5470.         when others =>  null;
  5471.     end case;
  5472.     end GET_FORM_INFO;
  5473.  
  5474. -------------------------------------------------------------------------
  5475. -- Abstract   : This procedure is used to simply create all of the
  5476. --              necessary forms that are used by the Interactive
  5477. --              Forms Generator System.
  5478. -------------------------------------------------------------------------
  5479. -- Parameters : none.
  5480. -------------------------------------------------------------------------
  5481.  
  5482.     procedure INITIALIZE_FORMS is
  5483.  
  5484.     FIELD : FORM_MANAGER.FIELD_ACCESS;
  5485.  
  5486. -------------------------------------------------------------------------
  5487.  
  5488.     -- Build the field values and attributes modification menu.
  5489.  
  5490.     procedure INIT_FIELD_MENU is
  5491.  
  5492.     begin
  5493.  
  5494.         -- Create the Field Menu
  5495.  
  5496.         FORM_MANAGER.CREATE_FORM
  5497.            ((8, 60), (10, 10), FORM_MANAGER.CLEAR, FIELD_MENU);
  5498.  
  5499.         FORM_MANAGER.ADD_FIELD
  5500.            (FIELD_MENU, "", (1, 8), 11, INIT_VALUE => "Field name:",
  5501.         MODE => FORM_MANAGER.CONSTANT_TEXT, FIELD => FIELD);
  5502.         FORM_MANAGER.ADD_FIELD
  5503.            (FIELD_MENU, "Field Name", (1, 20), 32,
  5504.         CHAR_LIMITS => FORM_MANAGER.ALPHA, FIELD => FIELD);
  5505.  
  5506.         FORM_MANAGER.ADD_FIELD
  5507.            (FIELD_MENU, "", (2, 6), 13, INIT_VALUE => "Field length:",
  5508.         MODE => FORM_MANAGER.CONSTANT_TEXT, FIELD => FIELD);
  5509.         FORM_MANAGER.ADD_FIELD
  5510.            (FIELD_MENU, "Field Length", (2, 20), 3,
  5511.         CHAR_LIMITS => FORM_MANAGER.NUMERIC, FIELD => FIELD);
  5512.  
  5513.         FORM_MANAGER.ADD_FIELD
  5514.            (FIELD_MENU, "", (3, 2), 17, INIT_VALUE => "Character limits:",
  5515.         MODE => FORM_MANAGER.CONSTANT_TEXT, FIELD => FIELD);
  5516.         FORM_MANAGER.ADD_FIELD
  5517.            (FIELD_MENU, "Field Limits", (3, 20), 3,
  5518.         CHAR_LIMITS => FORM_MANAGER.NUMERIC, INIT_VALUE => "  4",
  5519.         FIELD => FIELD);
  5520.         FORM_MANAGER.ADD_FIELD
  5521.            (FIELD_MENU, "", (3, 25), 27,
  5522.         INIT_VALUE => "(1-Alphabetic,   2-Numeric,",
  5523.         MODE => FORM_MANAGER.CONSTANT_TEXT, FIELD => FIELD);
  5524.         FORM_MANAGER.ADD_FIELD
  5525.            (FIELD_MENU, "", (4, 26), 30,
  5526.         INIT_VALUE => "3-Alphanumeric, 4-Not Limited)",
  5527.         MODE => FORM_MANAGER.CONSTANT_TEXT, FIELD => FIELD);
  5528.  
  5529.         FORM_MANAGER.ADD_FIELD
  5530.            (FIELD_MENU, "", (5, 1), 18,
  5531.         INIT_VALUE => "Display rendition:",
  5532.         MODE => FORM_MANAGER.CONSTANT_TEXT, FIELD => FIELD);
  5533.         FORM_MANAGER.ADD_FIELD
  5534.            (FIELD_MENU, "Field Rendition", (5, 20), 3,
  5535.         CHAR_LIMITS => FORM_MANAGER.NUMERIC, INIT_VALUE => "  1",
  5536.         FIELD => FIELD);
  5537.         FORM_MANAGER.ADD_FIELD
  5538.            (FIELD_MENU, "", (5, 25), 24,
  5539.         INIT_VALUE => "(1-Normal,  2-Secondary,",
  5540.         MODE => FORM_MANAGER.CONSTANT_TEXT, FIELD => FIELD);
  5541.         FORM_MANAGER.ADD_FIELD
  5542.            (FIELD_MENU, "", (6, 26), 23,
  5543.         INIT_VALUE => "3-Reverse, 4-Underline)",
  5544.         MODE => FORM_MANAGER.CONSTANT_TEXT, FIELD => FIELD);
  5545.  
  5546.         FORM_MANAGER.ADD_FIELD
  5547.            (FIELD_MENU, "", (7, 8), 11, INIT_VALUE => "Field mode:",
  5548.         MODE => FORM_MANAGER.CONSTANT_TEXT, FIELD => FIELD);
  5549.         FORM_MANAGER.ADD_FIELD
  5550.            (FIELD_MENU, "Field Mode", (7, 20), 3,
  5551.         CHAR_LIMITS => FORM_MANAGER.NUMERIC, INIT_VALUE => "  1",
  5552.         FIELD => FIELD);
  5553.         FORM_MANAGER.ADD_FIELD
  5554.            (FIELD_MENU, "", (7, 25), 31,
  5555.         INIT_VALUE => "(1-Input/Output, 2-Output Only)",
  5556.         MODE => FORM_MANAGER.CONSTANT_TEXT, FIELD => FIELD);
  5557.  
  5558.         FORM_MANAGER.ADD_FIELD
  5559.            (FIELD_MENU, "", (8, 5), 14, INIT_VALUE => "Initial value:",
  5560.         MODE => FORM_MANAGER.CONSTANT_TEXT, FIELD => FIELD);
  5561.         FORM_MANAGER.ADD_FIELD
  5562.            (FIELD_MENU, "Initial Value", (8, 20), 40, FIELD => FIELD);
  5563.  
  5564.     end INIT_FIELD_MENU;
  5565.  
  5566. ---------------------------------------------------------------------------
  5567.  
  5568.     -- Build the field name retrieval menu.
  5569.  
  5570.     procedure INIT_FIELD_NAME_MENU is
  5571.  
  5572.     begin
  5573.  
  5574.         -- Create the Field Name Menu
  5575.  
  5576.         FORM_MANAGER.CREATE_FORM
  5577.            ((1, 70), (24, 1), FORM_MANAGER.NO_CLEAR, FIELD_NAME_MENU);
  5578.  
  5579.         FORM_MANAGER.ADD_FIELD
  5580.            (FIELD_NAME_MENU, "", (1, 1), 18,
  5581.         INIT_VALUE => "Enter field name: ",
  5582.         MODE => FORM_MANAGER.CONSTANT_TEXT, FIELD => FIELD);
  5583.         FORM_MANAGER.ADD_FIELD
  5584.            (FIELD_NAME_MENU, "Field Name", (1, 19), 32,
  5585.         CHAR_LIMITS => FORM_MANAGER.ALPHA, FIELD => FIELD);
  5586.  
  5587.     end INIT_FIELD_NAME_MENU;
  5588.  
  5589. -------------------------------------------------------------------------
  5590.  
  5591.     -- Build the file name retrieval menu.
  5592.  
  5593.     procedure INIT_FILE_MENU is
  5594.  
  5595.     begin
  5596.  
  5597.         -- Create the Form File Menu
  5598.  
  5599.         FORM_MANAGER.CREATE_FORM
  5600.            ((1, 70), (24, 1), FORM_MANAGER.NO_CLEAR, FORM_FILE_MENU);
  5601.  
  5602.         FORM_MANAGER.ADD_FIELD
  5603.            (FORM_FILE_MENU, "", (1, 1), 17,
  5604.         INIT_VALUE => "Enter file name: ",
  5605.         MODE => FORM_MANAGER.CONSTANT_TEXT, FIELD => FIELD);
  5606.         FORM_MANAGER.ADD_FIELD
  5607.            (FORM_FILE_MENU, "File Name", (1, 18), 48, FIELD => FIELD);
  5608.  
  5609.     end INIT_FILE_MENU;
  5610.  
  5611. ---------------------------------------------------------------------------
  5612.  
  5613.     -- Build the form attributes modification menu.
  5614.  
  5615.     procedure INIT_FORM_MENU is
  5616.  
  5617.     begin
  5618.  
  5619.         -- Create the Form Menu
  5620.  
  5621.         FORM_MANAGER.CREATE_FORM
  5622.            ((3, 60), (10, 18), FORM_MANAGER.CLEAR, FORM_MENU);
  5623.  
  5624.         FORM_MANAGER.ADD_FIELD
  5625.            (FORM_MENU, "", (1, 5), 17, INIT_VALUE => "Form size - Rows:",
  5626.         MODE => FORM_MANAGER.CONSTANT_TEXT, FIELD => FIELD);
  5627.         FORM_MANAGER.ADD_FIELD
  5628.            (FORM_MENU, "Size Rows", (1, 23), 3,
  5629.         CHAR_LIMITS => FORM_MANAGER.NUMERIC, INIT_VALUE => " 24",
  5630.         FIELD => FIELD);
  5631.         FORM_MANAGER.ADD_FIELD
  5632.            (FORM_MENU, "", (1, 29), 8, INIT_VALUE => "Columns:",
  5633.         MODE => FORM_MANAGER.CONSTANT_TEXT, FIELD => FIELD);
  5634.         FORM_MANAGER.ADD_FIELD
  5635.            (FORM_MENU, "Size Columns", (1, 38), 3,
  5636.         CHAR_LIMITS => FORM_MANAGER.NUMERIC, INIT_VALUE => " 80",
  5637.         FIELD => FIELD);
  5638.  
  5639.         FORM_MANAGER.ADD_FIELD
  5640.            (FORM_MENU, "", (2, 1), 21,
  5641.         INIT_VALUE => "Form position -  Row:",
  5642.         MODE => FORM_MANAGER.CONSTANT_TEXT, FIELD => FIELD);
  5643.         FORM_MANAGER.ADD_FIELD
  5644.            (FORM_MENU, "Position Row", (2, 23), 3,
  5645.         CHAR_LIMITS => FORM_MANAGER.NUMERIC, INIT_VALUE => "  1",
  5646.         FIELD => FIELD);
  5647.         FORM_MANAGER.ADD_FIELD
  5648.            (FORM_MENU, "", (2, 30), 7, INIT_VALUE => "Column:",
  5649.         MODE => FORM_MANAGER.CONSTANT_TEXT, FIELD => FIELD);
  5650.         FORM_MANAGER.ADD_FIELD
  5651.            (FORM_MENU, "Position Column", (2, 38), 3,
  5652.         CHAR_LIMITS => FORM_MANAGER.NUMERIC, INIT_VALUE => "  1",
  5653.         FIELD => FIELD);
  5654.  
  5655.         FORM_MANAGER.ADD_FIELD
  5656.            (FORM_MENU, "", (3, 2), 20,
  5657.         INIT_VALUE => "Clear screen option:",
  5658.         MODE => FORM_MANAGER.CONSTANT_TEXT, FIELD => FIELD);
  5659.         FORM_MANAGER.ADD_FIELD
  5660.            (FORM_MENU, "Clear Option", (3, 23), 3,
  5661.         CHAR_LIMITS => FORM_MANAGER.ALPHA, INIT_VALUE => "Yes",
  5662.         FIELD => FIELD);
  5663.         FORM_MANAGER.ADD_FIELD
  5664.            (FORM_MENU, "", (3, 29), 9, INIT_VALUE => "(Yes, No)",
  5665.         MODE => FORM_MANAGER.CONSTANT_TEXT, FIELD => FIELD);
  5666.  
  5667.     end INIT_FORM_MENU;
  5668.  
  5669. --------------------------------------------------------------------------
  5670.  
  5671.     -- Build the Main Menu
  5672.  
  5673.     procedure INIT_MAIN_MENU is
  5674.  
  5675.     begin
  5676.  
  5677.         -- Create the Main Menu
  5678.  
  5679.         FORM_MANAGER.CREATE_FORM
  5680.            ((12, 40), (7, 25), FORM_MANAGER.CLEAR, MAIN_MENU);
  5681.  
  5682.         FORM_MANAGER.ADD_FIELD
  5683.            (MAIN_MENU, "", (1, 1), 30, FORM_TYPES.UNDERLINE_RENDITION,
  5684.         INIT_VALUE => "The Interactive Form Generator",
  5685.         MODE => FORM_MANAGER.CONSTANT_TEXT, FIELD => FIELD);
  5686.         FORM_MANAGER.ADD_FIELD
  5687.            (MAIN_MENU, "", (3, 1), 30,
  5688.         INIT_VALUE => "Choose ""one"" of the following:",
  5689.         MODE => FORM_MANAGER.CONSTANT_TEXT, FIELD => FIELD);
  5690.         FORM_MANAGER.ADD_FIELD
  5691.            (MAIN_MENU, "", (5, 6), 21,
  5692.         INIT_VALUE => "C - Create a new form",
  5693.         MODE => FORM_MANAGER.CONSTANT_TEXT, FIELD => FIELD);
  5694.         FORM_MANAGER.ADD_FIELD
  5695.            (MAIN_MENU, "", (6, 6), 25,
  5696.         INIT_VALUE => "L - Load an external form",
  5697.         MODE => FORM_MANAGER.CONSTANT_TEXT, FIELD => FIELD);
  5698.         FORM_MANAGER.ADD_FIELD
  5699.            (MAIN_MENU, "", (7, 6), 25,
  5700.         INIT_VALUE => "E - Edit the current form",
  5701.         MODE => FORM_MANAGER.CONSTANT_TEXT, FIELD => FIELD);
  5702.         FORM_MANAGER.ADD_FIELD
  5703.            (MAIN_MENU, "", (8, 6), 32,
  5704.         INIT_VALUE => "M - Modify the form's attributes",
  5705.         MODE => FORM_MANAGER.CONSTANT_TEXT, FIELD => FIELD);
  5706.         FORM_MANAGER.ADD_FIELD
  5707.            (MAIN_MENU, "", (9, 6), 25,
  5708.         INIT_VALUE => "S - Save the current form",
  5709.         MODE => FORM_MANAGER.CONSTANT_TEXT, FIELD => FIELD);
  5710.         FORM_MANAGER.ADD_FIELD
  5711.            (MAIN_MENU, "", (10, 6), 8, INIT_VALUE => "Q - Quit",
  5712.         MODE => FORM_MANAGER.CONSTANT_TEXT, FIELD => FIELD);
  5713.  
  5714.         FORM_MANAGER.ADD_FIELD
  5715.            (MAIN_MENU, "", (12, 6), 10, INIT_VALUE => "Selection:",
  5716.         MODE => FORM_MANAGER.CONSTANT_TEXT, FIELD => FIELD);
  5717.         FORM_MANAGER.ADD_FIELD
  5718.            (MAIN_MENU, "Response", (12, 16), 4,
  5719.         FORM_TYPES.REVERSE_RENDITION, INIT_VALUE => "____",
  5720.         FIELD => FIELD);
  5721.  
  5722.     end INIT_MAIN_MENU;
  5723.  
  5724. ---------------------------------------------------------------------------
  5725.  
  5726.     begin
  5727.  
  5728.     INIT_FIELD_MENU;
  5729.     INIT_FIELD_NAME_MENU;
  5730.     INIT_FILE_MENU;
  5731.     INIT_FORM_MENU;
  5732.     INIT_MAIN_MENU;
  5733.  
  5734.     end INITIALIZE_FORMS;
  5735.  
  5736. end FORMS;
  5737. ::::::::::
  5738. FORM_TYPES.ADA
  5739. ::::::::::
  5740. --------------------------------------------------------------------------
  5741. -- Abstract   : This package defines some of the data types for the
  5742. --              Form Generator system.  These data types are needed by
  5743. --              all packages in the system.
  5744. --------------------------------------------------------------------------
  5745.  
  5746. package FORM_TYPES is
  5747.  
  5748.     MAX_ROWS    : constant INTEGER := 24;
  5749.     MAX_COLUMNS : constant INTEGER := 80;
  5750.  
  5751.     subtype ROW_RANGE    is INTEGER range 1 .. MAX_ROWS;
  5752.     subtype COLUMN_RANGE is INTEGER range 1 .. MAX_COLUMNS;
  5753.  
  5754.     type XY_POSITION is -- defines a screen position
  5755.     record
  5756.         LINE   : ROW_RANGE;
  5757.         COLUMN : COLUMN_RANGE;
  5758.     end record;
  5759.  
  5760.     type DISPLAY_RENDITIONS is
  5761.      (PRIMARY_RENDITION,   REVERSE_RENDITION,   SECONDARY_RENDITION,
  5762.       UNDERLINE_RENDITION);
  5763.  
  5764. end FORM_TYPES;
  5765. ::::::::::
  5766. INTERACT.ADA
  5767. ::::::::::
  5768. -------------------------------------------------------------------------
  5769. -- Abstract   : This procedure is the entry point for executing the
  5770. --              Interactive Form Generator System.  This procedure
  5771. --              services the Main Menu for the system and called the
  5772. --              appropriate routines accordingly.
  5773. -------------------------------------------------------------------------
  5774. -- Parameters : none.
  5775. -------------------------------------------------------------------------
  5776. with FORMS;
  5777. with FORM_TYPES;
  5778. with FORM_EXECUTOR;
  5779. with FORM_MANAGER;
  5780. with TERMINAL_INTERFACE;
  5781. with EDITOR;
  5782.  
  5783. procedure INTERACT is
  5784.  
  5785. -- These four objects depict the Current Form.
  5786.  
  5787.     CURRENT_FORM                  : FORM_MANAGER.FORM_ACCESS;
  5788.     CURRENT_SIZE                  : FORM_MANAGER.FORM_SIZE;
  5789.     CURRENT_POSITION              : FORM_MANAGER.FORM_POSITION;
  5790.     CURRENT_OPTION                : FORM_MANAGER.OPTION_TYPE;
  5791.  
  5792.     CHAR                          : CHARACTER;
  5793.     FUNCT                         : TERMINAL_INTERFACE.FUNCTION_KEY_ENUM;
  5794.     CHARTYPE                      : TERMINAL_INTERFACE.CHAR_ENUM;
  5795.  
  5796.     RESPONSE                      : STRING (1 .. 6);
  5797.     FILENAME                      : STRING (1 .. 48);
  5798.  
  5799.     CURRENT_FORM_HAS_BEEN_ALTERED : BOOLEAN := false;
  5800.  
  5801.     CHECK_FOR_FORM_OVERWRITE : exception;
  5802.     MENU_TOO_LARGE           : exception;
  5803.  
  5804.     SIZE : TERMINAL_INTERFACE.SCREEN_POSITION;
  5805.  
  5806.     function "=" (LEFT, RIGHT : TERMINAL_INTERFACE.CHAR_ENUM) return BOOLEAN
  5807.            renames TERMINAL_INTERFACE."=";
  5808.  
  5809.     function "=" (LEFT, RIGHT : TERMINAL_INTERFACE.FUNCTION_KEY_ENUM)
  5810.            return BOOLEAN renames TERMINAL_INTERFACE."=";
  5811.  
  5812. -- These are the separate procedures that can be called using the
  5813. --   user input from the Main Menu.
  5814.  
  5815.     procedure EDIT_FORM is separate;
  5816.     procedure CREATE_FORM is separate;
  5817.     procedure LOAD_FORM is separate;
  5818.     procedure MODIFY_FORM_ATTRIBUTES is separate;
  5819.     procedure SAVE_FORM is separate;
  5820.  
  5821. -----------------------------------------------------------------
  5822. -----------------------------------------------------------------
  5823.  
  5824. --  Main menu service routine
  5825.  
  5826. -----------------------------------------------------------------
  5827. -----------------------------------------------------------------
  5828.  
  5829. -- Displays the main level menu to the user and requests that one option
  5830. --   be chosen.  The possible options to choose are:
  5831. -- 
  5832. --                  1) Create a new form,
  5833. --                  2) Edit the current form,
  5834. --                  3) Load an external form,
  5835. --                  4) Modify the current form's attributes,
  5836. --                  5) Save the current form, and
  5837. --                  6) Quit
  5838.  
  5839. begin
  5840.  
  5841.     -- Open the terminal and initialize the necessary forms.
  5842.  
  5843.     TERMINAL_INTERFACE.OPEN;
  5844.     FORMS.INITIALIZE_FORMS; -- Initialize the menu forms.
  5845.  
  5846.     -- Check terminal size.
  5847.  
  5848.     TERMINAL_INTERFACE.SCREEN_SIZE (SIZE);
  5849.     if SIZE.LINE < 12 or else SIZE.COLUMN < 40 then
  5850.     raise MENU_TOO_LARGE;
  5851.     end if;
  5852.  
  5853.     -- Clear the screen and present the Main Menu.
  5854.  
  5855.     TERMINAL_INTERFACE.CLEAR_SCREEN;
  5856.     FORM_EXECUTOR.PRESENT_FORM (FORMS.MAIN_MENU);
  5857.     FORM_EXECUTOR.QUERY_FIELD (FORMS.MAIN_MENU, "Response", RESPONSE);
  5858.  
  5859.     -- Retrieve user responses until a "quit" is encountered.  ( Only the
  5860.     --   first character of the user responses is used for determining the
  5861.     --   procedure to call. )
  5862.  
  5863.     loop
  5864.  
  5865.     loop
  5866.         begin
  5867.         case RESPONSE (1) is
  5868.             when 'C' | 'c' => 
  5869.             if CURRENT_FORM_HAS_BEEN_ALTERED then
  5870.                 raise CHECK_FOR_FORM_OVERWRITE;
  5871.             else
  5872.                 CREATE_FORM;
  5873.             end if;
  5874.  
  5875.             when 'L' | 'l' => 
  5876.             if CURRENT_FORM_HAS_BEEN_ALTERED then
  5877.                 raise CHECK_FOR_FORM_OVERWRITE;
  5878.             else
  5879.                 LOAD_FORM;
  5880.             end if;
  5881.  
  5882.             when 'E' | 'e' => 
  5883.             EDIT_FORM;
  5884.             CURRENT_FORM_HAS_BEEN_ALTERED := true;
  5885.  
  5886.             when 'M' | 'm' =>  MODIFY_FORM_ATTRIBUTES;
  5887.  
  5888.             when 'S' | 's' => 
  5889.             SAVE_FORM;
  5890.  
  5891.             when 'Q' | 'q' => 
  5892.             exit;
  5893.  
  5894.             when others => 
  5895.             TERMINAL_INTERFACE.PUT_MESSAGE
  5896.                ("Invalid Menu choice -- try again.");
  5897.         end case;
  5898.  
  5899.         exit;
  5900.  
  5901.         exception
  5902.         when CHECK_FOR_FORM_OVERWRITE => 
  5903.  
  5904.             TERMINAL_INTERFACE.PUT_MESSAGE
  5905.                ("Enter a RETURN to overwrite Current Form; any " &
  5906.             "other to abort");
  5907.  
  5908.             TERMINAL_INTERFACE.GET_CHARACTER (CHARTYPE, CHAR, FUNCT);
  5909.             while CHARTYPE = TERMINAL_INTERFACE.TIMEOUT loop
  5910.             TERMINAL_INTERFACE.GET_CHARACTER
  5911.                (CHARTYPE, CHAR, FUNCT);
  5912.             end loop;
  5913.  
  5914.             if CHARTYPE = TERMINAL_INTERFACE.FUNC_TYPE and then
  5915.                FUNCT = TERMINAL_INTERFACE.RETURN_KEY then
  5916.             CURRENT_FORM_HAS_BEEN_ALTERED := false;
  5917.             else
  5918.             exit;
  5919.             end if;
  5920.  
  5921.         end;
  5922.     end loop;
  5923.  
  5924.     if RESPONSE (1) = 'Q' or else RESPONSE (1) = 'q' then
  5925.         if CURRENT_FORM_HAS_BEEN_ALTERED then
  5926.         TERMINAL_INTERFACE.PUT_MESSAGE
  5927.            ("Enter a RETURN to exit without saving; " &
  5928.             "any other to abort this quit");
  5929.         TERMINAL_INTERFACE.GET_CHARACTER (CHARTYPE, CHAR, FUNCT);
  5930.         while CHARTYPE = TERMINAL_INTERFACE.TIMEOUT loop
  5931.             TERMINAL_INTERFACE.GET_CHARACTER (CHARTYPE, CHAR, FUNCT);
  5932.         end loop;
  5933.  
  5934.         if CHARTYPE = TERMINAL_INTERFACE.FUNC_TYPE and then
  5935.            FUNCT = TERMINAL_INTERFACE.RETURN_KEY then
  5936.             exit;
  5937.         end if;
  5938.         else
  5939.         exit;
  5940.         end if;
  5941.     end if;
  5942.  
  5943.     FORM_EXECUTOR.PRESENT_FORM (FORMS.MAIN_MENU);
  5944.     FORM_EXECUTOR.QUERY_FIELD (FORMS.MAIN_MENU, "Response", RESPONSE);
  5945.  
  5946.     end loop;
  5947.  
  5948.     -- When finished, dispose of the Current Form and close the terminal.
  5949.  
  5950.     FORM_MANAGER.RELEASE_FORM (CURRENT_FORM);
  5951.     TERMINAL_INTERFACE.CLOSE;
  5952.  
  5953.  
  5954. exception
  5955.     when MENU_TOO_LARGE => 
  5956.     TERMINAL_INTERFACE.PUT_MESSAGE
  5957.        ("Screen size is too small to display Main Menu");
  5958.  
  5959. -- These exception handlers are included so that, in the event that some
  5960. -- exception is inadvertently raised internally and not properly handled,
  5961. -- that it will not be propagated out as an unhandled exception thereby
  5962. -- giving the program user no idea what caused the problem.
  5963.  
  5964.     when CONSTRAINT_ERROR => 
  5965.     TERMINAL_INTERFACE.PUT_MESSAGE
  5966.        ("An internal CONSTRAINT_ERROR has been encountered!");
  5967.  
  5968.     when NUMERIC_ERROR => 
  5969.     TERMINAL_INTERFACE.PUT_MESSAGE
  5970.        ("An internal NUMERIC_ERROR has been encountered!");
  5971.  
  5972.     when PROGRAM_ERROR => 
  5973.     TERMINAL_INTERFACE.PUT_MESSAGE
  5974.        ("An internal PROGRAM_ERROR has been encountered!");
  5975.  
  5976.     when STORAGE_ERROR => 
  5977.     TERMINAL_INTERFACE.PUT_MESSAGE
  5978.        ("Memory is full -- STORAGE_ERROR has been encountered!");
  5979.  
  5980.     when TASKING_ERROR => 
  5981.     TERMINAL_INTERFACE.PUT_MESSAGE
  5982.        ("An internal TASKING_ERROR has been encountered!");
  5983.  
  5984. end INTERACT;
  5985. pragma MAIN;
  5986. ::::::::::
  5987. MANAGER_BODY.ADA
  5988. ::::::::::
  5989. --------------------------------------------------------------------------
  5990. -- Abstract   : This module contains the body for the Form Manager
  5991. --              which defines the routines which operate on forms and
  5992. --              fields of a form.
  5993. --------------------------------------------------------------------------
  5994.  
  5995. with TEXT_IO;
  5996.  
  5997. package body FORM_MANAGER is
  5998.  
  5999.     package CHAR_TYPE_IO is new TEXT_IO.ENUMERATION_IO (CHAR_TYPE);
  6000.     package FIELD_MODE_IO is new TEXT_IO.ENUMERATION_IO (FIELD_MODE);
  6001.     package RENDITION_IO is new TEXT_IO.ENUMERATION_IO (FIELD_RENDITIONS);
  6002.     package OPTION_TYPE_IO is new TEXT_IO.ENUMERATION_IO (OPTION_TYPE);
  6003.     package NUMBER_IO is new TEXT_IO.INTEGER_IO (NATURAL);
  6004.  
  6005. --------------------------------------------------------------------------
  6006. -- Abstract   : CREATE_FORM creates a new form data structure and
  6007. --              initializes the attributes of the form.
  6008. --------------------------------------------------------------------------
  6009. -- Parameters : SIZE - size of the form in rows and columns
  6010. --              POSITION - position of the upper left hand corner of the
  6011. --                      form on the screen in row and column
  6012. --              CLEAR_OPTION - indicates whether the screen should be
  6013. --                      cleared whenever the form is displayed
  6014. --              FORM - pointer to the form data structure which is
  6015. --                      allocated for the form information
  6016. --------------------------------------------------------------------------
  6017.     procedure CREATE_FORM (SIZE         : FORM_SIZE;
  6018.                POSITION     : FORM_POSITION;
  6019.                CLEAR_OPTION : OPTION_TYPE;
  6020.                FORM         : out FORM_ACCESS) is
  6021.     NEW_FORM : FORM_ACCESS;
  6022.     begin
  6023.     if SIZE.ROWS + POSITION.LINE - 1 > FORM_TYPES.MAX_ROWS or
  6024.        SIZE.COLUMNS + POSITION.COLUMN - 1 > FORM_TYPES.MAX_COLUMNS then
  6025.         raise FORM_TOO_BIG;
  6026.     end if;
  6027.  
  6028.     NEW_FORM := new FORM_RECORD'
  6029.               (SIZE         => (24, 80),
  6030.                POSITION     => (1, 1),
  6031.                CLEAR_OPTION => CLEAR,
  6032.                FIRST_FIELD  => null);
  6033.     NEW_FORM.SIZE := SIZE;
  6034.     NEW_FORM.POSITION := POSITION;
  6035.     NEW_FORM.CLEAR_OPTION := CLEAR_OPTION;
  6036.  
  6037.     FORM := NEW_FORM;
  6038.  
  6039.     exception
  6040.     when STORAGE_ERROR =>  -- cannot allocate form data structure
  6041.         raise FORM_ALLOCATION_ERROR;
  6042.  
  6043.     end CREATE_FORM;
  6044.  
  6045. --------------------------------------------------------------------------
  6046. -- Abstract   : GET_FORM_INFO returns the current information about a
  6047. --              specific form.  This information is obtained from the
  6048. --              form data structure.
  6049. --------------------------------------------------------------------------
  6050. -- Parameters : FORM - pointer to the form data structure
  6051. --              SIZE - size of the form in rows and columns
  6052. --              POSITION - position of the upper left hand corner of the
  6053. --                      form on the screen in row and column
  6054. --              CLEAR_OPTION - indicates whether the screen should be
  6055. --                      cleared whenever the form is displayed
  6056. --------------------------------------------------------------------------
  6057.     procedure GET_FORM_INFO (FORM         : FORM_ACCESS;
  6058.                  SIZE         : out FORM_SIZE;
  6059.                  POSITION     : out FORM_POSITION;
  6060.                  CLEAR_OPTION : out OPTION_TYPE) is
  6061.     begin
  6062.  
  6063.     SIZE := FORM.SIZE;
  6064.     POSITION := FORM.POSITION;
  6065.     CLEAR_OPTION := FORM.CLEAR_OPTION;
  6066.  
  6067.     exception
  6068.     when CONSTRAINT_ERROR => 
  6069.         if FORM = null then
  6070.         raise NULL_FORM_POINTER;
  6071.         else
  6072.         raise;
  6073.         end if;
  6074.  
  6075.     end GET_FORM_INFO;
  6076.  
  6077.  
  6078. --------------------------------------------------------------------------
  6079. -- Abstract   : MODIFY_FORM_SIZE modifies the size attribute for a form.
  6080. --------------------------------------------------------------------------
  6081. -- Parameters : FORM - pointer to the form data structure
  6082. --              SIZE - size of the form in rows and columns
  6083. --------------------------------------------------------------------------
  6084.     procedure MODIFY_FORM_SIZE (FORM : FORM_ACCESS; SIZE : FORM_SIZE) is
  6085.     begin
  6086.  
  6087.     FORM.SIZE := SIZE;
  6088.  
  6089.     exception
  6090.     when CONSTRAINT_ERROR => 
  6091.         if FORM = null then
  6092.         raise NULL_FORM_POINTER;
  6093.         else
  6094.         raise;
  6095.         end if;
  6096.  
  6097.     end MODIFY_FORM_SIZE;
  6098.  
  6099.  
  6100. --------------------------------------------------------------------------
  6101. -- Abstract   : MODIFY_FORM_POSITION modifies the position attribute for
  6102. --              a form.
  6103. --------------------------------------------------------------------------
  6104. -- Parameters : FORM - pointer to the form data structure
  6105. --              POSITION - position of the upper left hand corner of the
  6106. --                      form on the screen in row and column
  6107. --------------------------------------------------------------------------
  6108.     procedure MODIFY_FORM_POSITION (FORM     : FORM_ACCESS;
  6109.                     POSITION : FORM_POSITION) is
  6110.     begin
  6111.  
  6112.     FORM.POSITION := POSITION;
  6113.  
  6114.     exception
  6115.     when CONSTRAINT_ERROR => 
  6116.         if FORM = null then
  6117.         raise NULL_FORM_POINTER;
  6118.         else
  6119.         raise;
  6120.         end if;
  6121.  
  6122.     end MODIFY_FORM_POSITION;
  6123.  
  6124.  
  6125. --------------------------------------------------------------------------
  6126. -- Abstract   : MODIFY_FORM_OPTION modifies the clear display option
  6127. --              for a form when it is presented.
  6128. --------------------------------------------------------------------------
  6129. -- Parameters : FORM - pointer to the form data structure
  6130. --              CLEAR_OPTION - indicates whether the screen should be
  6131. --                      cleared whenever the form is displayed
  6132. --------------------------------------------------------------------------
  6133.     procedure MODIFY_FORM_OPTION (FORM         : FORM_ACCESS;
  6134.                   CLEAR_OPTION : OPTION_TYPE) is
  6135.     begin
  6136.  
  6137.     FORM.CLEAR_OPTION := CLEAR_OPTION;
  6138.  
  6139.     exception
  6140.     when CONSTRAINT_ERROR => 
  6141.         if FORM = null then
  6142.         raise NULL_FORM_POINTER;
  6143.         else
  6144.         raise;
  6145.         end if;
  6146.  
  6147.     end MODIFY_FORM_OPTION;
  6148.  
  6149.  
  6150. --------------------------------------------------------------------------
  6151. -- Abstract   : CLEAR_FORM resets the values of all the fields to their
  6152. --              initial value.
  6153. --------------------------------------------------------------------------
  6154. -- Parameters : FORM - pointer to the form data structure
  6155. --------------------------------------------------------------------------
  6156.     procedure CLEAR_FORM (FORM : FORM_ACCESS) is
  6157.     FIELD : FIELD_ACCESS;
  6158.     begin
  6159.  
  6160.     FIELD := FORM.FIRST_FIELD;
  6161.  
  6162.     while FIELD /= null loop
  6163.         FIELD.VALUE := FIELD.INIT_VALUE;
  6164.         FIELD := FIELD.NEXT_FIELD;
  6165.     end loop;
  6166.  
  6167.     exception
  6168.     when CONSTRAINT_ERROR => 
  6169.         if FORM = null then
  6170.         raise NULL_FORM_POINTER;
  6171.         else
  6172.         raise;
  6173.         end if;
  6174.  
  6175.     end CLEAR_FORM;
  6176.  
  6177.  
  6178. --------------------------------------------------------------------------
  6179. -- Abstract   : LOAD_FORM loads a form definition from an external file.
  6180. --------------------------------------------------------------------------
  6181. -- Parameters : PATHNAME - string which contains the pathname of the file
  6182. --                      to be loaded
  6183. --              FORM - pointer to the data structure for the loaded form
  6184. --------------------------------------------------------------------------
  6185. -- Algorithm  : Standard Text I/O is used to load the file definition.
  6186. --              Packages are used to read values of the enumerations.
  6187. --------------------------------------------------------------------------
  6188.     procedure LOAD_FORM (PATHNAME : STRING; FORM : out FORM_ACCESS) is
  6189.  
  6190.     INPUT        : TEXT_IO.FILE_TYPE;
  6191.     FIRST        : NATURAL;
  6192.     LAST         : NATURAL;
  6193.  
  6194.     NEW_FORM     : FORM_ACCESS;
  6195.     CLEAR_OPTION : OPTION_TYPE;
  6196.     COLUMN       : FORM_TYPES.COLUMN_RANGE;
  6197.     LINE         : FORM_TYPES.ROW_RANGE;
  6198.     SIZE         : FORM_SIZE;
  6199.  
  6200.     NEW_FIELD    : FIELD_ACCESS;
  6201.     CHAR_LIMITS  : CHAR_TYPE;
  6202.     INIT_VALUE   : FIELD_VALUE;
  6203.     LENGTH       : FIELD_LENGTH;
  6204.     MODE         : FIELD_MODE;
  6205.     NAME         : FIELD_NAME;
  6206.     RENDITION    : FIELD_RENDITIONS;
  6207.  
  6208.     begin
  6209.     FIRST := PATHNAME'FIRST;
  6210.     LAST := PATHNAME'LAST;
  6211.     while FIRST < LAST and PATHNAME (FIRST) = ' ' loop
  6212.         -- trim leading blanks
  6213.         FIRST := FIRST + 1;
  6214.     end loop;
  6215.     while FIRST < LAST and PATHNAME (LAST) = ' ' loop
  6216.         -- trim trailing blanks
  6217.         LAST := LAST - 1;
  6218.     end loop;
  6219.  
  6220.     TEXT_IO.OPEN (INPUT, TEXT_IO.IN_FILE, PATHNAME (FIRST .. LAST));
  6221.  
  6222.     NUMBER_IO.GET (INPUT, SIZE.ROWS);
  6223.     NUMBER_IO.GET (INPUT, SIZE.COLUMNS);
  6224.  
  6225.     NUMBER_IO.GET (INPUT, LINE);
  6226.     NUMBER_IO.GET (INPUT, COLUMN);
  6227.  
  6228.     OPTION_TYPE_IO.GET (INPUT, CLEAR_OPTION);
  6229.     TEXT_IO.SKIP_LINE (INPUT);
  6230.  
  6231.     CREATE_FORM (SIZE, (LINE, COLUMN), CLEAR_OPTION, NEW_FORM);
  6232.  
  6233.     while not TEXT_IO.END_OF_FILE (INPUT) loop
  6234.  
  6235.         TEXT_IO.GET (INPUT, NAME);
  6236.         TEXT_IO.SKIP_LINE (INPUT);
  6237.  
  6238.         NUMBER_IO.GET (INPUT, LINE);
  6239.         NUMBER_IO.GET (INPUT, COLUMN);
  6240.  
  6241.         NUMBER_IO.GET (INPUT, LENGTH);
  6242.  
  6243.         CHAR_TYPE_IO.GET (INPUT, CHAR_LIMITS);
  6244.  
  6245.         FIELD_MODE_IO.GET (INPUT, MODE);
  6246.  
  6247.         RENDITION_IO.GET (INPUT, RENDITION);
  6248.         TEXT_IO.SKIP_LINE (INPUT);
  6249.  
  6250.         TEXT_IO.GET (INPUT, INIT_VALUE);
  6251.         TEXT_IO.SKIP_LINE (INPUT);
  6252.  
  6253.         ADD_FIELD
  6254.            (NEW_FORM, NAME, (LINE, COLUMN), LENGTH, RENDITION,
  6255.         CHAR_LIMITS, INIT_VALUE, MODE, NEW_FIELD);
  6256.  
  6257.     end loop;
  6258.  
  6259.     TEXT_IO.CLOSE (INPUT);
  6260.  
  6261.     FORM := NEW_FORM;
  6262.  
  6263.     exception
  6264.     when TEXT_IO.NAME_ERROR => 
  6265.         raise FILE_NOT_FOUND;
  6266.     when TEXT_IO.STATUS_ERROR => 
  6267.         raise FILE_ALREADY_OPEN;
  6268.     when TEXT_IO.DATA_ERROR => 
  6269.         raise FILE_DATA_ERROR;
  6270.  
  6271.     end LOAD_FORM;
  6272.  
  6273.  
  6274. --------------------------------------------------------------------------
  6275. -- Abstract   : SAVE_FORM saves a form definition in an external file.
  6276. --------------------------------------------------------------------------
  6277. -- Parameters : FORM - pointer to the form data structure to be saved
  6278. --              PATHNAME - string which contains the pathname of the file
  6279. --                      where the form is to be saved
  6280. --------------------------------------------------------------------------
  6281. -- Algorithm  : Standard Text I/O is used to save the file definition.
  6282. --              Packages are used to write values of the enumerations.
  6283. --------------------------------------------------------------------------
  6284.     procedure SAVE_FORM (FORM : FORM_ACCESS; PATHNAME : STRING) is
  6285.  
  6286.     FIELD  : FIELD_ACCESS;
  6287.     FIRST  : NATURAL;
  6288.     LAST   : NATURAL;
  6289.     OUTPUT : TEXT_IO.FILE_TYPE;
  6290.  
  6291.     begin
  6292.  
  6293.     if FORM = null then
  6294.         raise NULL_FORM_POINTER;
  6295.     end if;
  6296.  
  6297.     FIRST := PATHNAME'FIRST;
  6298.     LAST := PATHNAME'LAST;
  6299.     while FIRST < LAST and PATHNAME (FIRST) = ' ' loop
  6300.         -- trim leading blanks
  6301.         FIRST := FIRST + 1;
  6302.     end loop;
  6303.     while FIRST < LAST and PATHNAME (LAST) = ' ' loop
  6304.         -- trim trailing blanks
  6305.         LAST := LAST - 1;
  6306.     end loop;
  6307.  
  6308.     TEXT_IO.CREATE (OUTPUT, TEXT_IO.OUT_FILE, PATHNAME (FIRST .. LAST));
  6309.  
  6310.     NUMBER_IO.PUT (OUTPUT, FORM.SIZE.ROWS, 3);
  6311.     NUMBER_IO.PUT (OUTPUT, FORM.SIZE.COLUMNS, 3);
  6312.  
  6313.     NUMBER_IO.PUT (OUTPUT, FORM.POSITION.LINE, 3);
  6314.     NUMBER_IO.PUT (OUTPUT, FORM.POSITION.COLUMN, 3);
  6315.  
  6316.     TEXT_IO.PUT (OUTPUT, ' ');
  6317.     OPTION_TYPE_IO.PUT (OUTPUT, FORM.CLEAR_OPTION);
  6318.     TEXT_IO.NEW_LINE (OUTPUT);
  6319.  
  6320.     FIELD := FORM.FIRST_FIELD;
  6321.  
  6322.     while FIELD /= null loop
  6323.  
  6324.         TEXT_IO.PUT (OUTPUT, FIELD.NAME);
  6325.         TEXT_IO.NEW_LINE (OUTPUT);
  6326.  
  6327.         NUMBER_IO.PUT (OUTPUT, FIELD.POSITION.LINE, 3);
  6328.         NUMBER_IO.PUT (OUTPUT, FIELD.POSITION.COLUMN, 3);
  6329.  
  6330.         NUMBER_IO.PUT (OUTPUT, FIELD.LENGTH, 3);
  6331.  
  6332.         TEXT_IO.PUT (OUTPUT, ' ');
  6333.         CHAR_TYPE_IO.PUT (OUTPUT, FIELD.CHAR_LIMITS);
  6334.  
  6335.         TEXT_IO.PUT (OUTPUT, ' ');
  6336.         FIELD_MODE_IO.PUT (OUTPUT, FIELD.MODE);
  6337.  
  6338.         TEXT_IO.PUT (OUTPUT, ' ');
  6339.         RENDITION_IO.PUT (OUTPUT, FIELD.RENDITION);
  6340.         TEXT_IO.NEW_LINE (OUTPUT);
  6341.  
  6342.         TEXT_IO.PUT (OUTPUT, FIELD.INIT_VALUE);
  6343.         TEXT_IO.NEW_LINE (OUTPUT);
  6344.  
  6345.         FIELD := FIELD.NEXT_FIELD;
  6346.  
  6347.     end loop;
  6348.  
  6349.     TEXT_IO.CLOSE (OUTPUT);
  6350.  
  6351.     exception
  6352.     when TEXT_IO.STATUS_ERROR => 
  6353.         raise FILE_ALREADY_OPEN;
  6354.  
  6355.     end SAVE_FORM;
  6356.  
  6357.  
  6358. --------------------------------------------------------------------------
  6359. -- Abstract   : RELEASE_FORM releases all the memory allocated for a
  6360. --              form and its fields.
  6361. --------------------------------------------------------------------------
  6362. -- Parameters : FORM - pointer to the form data structure
  6363. --------------------------------------------------------------------------
  6364. -- Algorithm  : Currently this routine does nothing because memory
  6365. --              deallocation is not supported the some versions of Ada.
  6366. --------------------------------------------------------------------------
  6367.     procedure RELEASE_FORM (FORM : FORM_ACCESS) is
  6368.     begin
  6369.  
  6370.     null; -- stub
  6371.  
  6372.     end RELEASE_FORM;
  6373.  
  6374.  
  6375.     procedure INSERT_FIELD (FIELD : FIELD_ACCESS);
  6376.  
  6377.     procedure REMOVE_FIELD (FIELD : FIELD_ACCESS);
  6378.  
  6379.  
  6380. --------------------------------------------------------------------------
  6381. -- Abstract   : ADD_FIELD adds a field to a form and initializes the
  6382. --              the field information data structure.
  6383. --------------------------------------------------------------------------
  6384. -- Parameters : FORM - pointer to the form data structure
  6385. --              NAME - name of the field as a string
  6386. --              POSITION - position of the field within the form
  6387. --              LENGTH - length of the field
  6388. --              RENDITION - rendition in which the field is displayed
  6389. --              CHAR_LIMITS - character limitation for field contents
  6390. --              INIT_VALUE - initial value of field if not modified
  6391. --              MODE - type of field (constant, output only, input/output)
  6392. --              FIELD - pointer to created field data structure
  6393. --------------------------------------------------------------------------
  6394.     procedure ADD_FIELD
  6395.          (FORM        : FORM_ACCESS;
  6396.           NAME        : STRING;
  6397.           POSITION    : FIELD_POSITION;
  6398.           LENGTH      : FIELD_LENGTH;
  6399.           RENDITION   : FIELD_RENDITIONS :=
  6400.                 FORM_TYPES.PRIMARY_RENDITION;
  6401.           CHAR_LIMITS : CHAR_TYPE := NOT_LIMITED;
  6402.           INIT_VALUE  : STRING := "";
  6403.           MODE        : FIELD_MODE := INPUT_OUTPUT;
  6404.           FIELD       : out FIELD_ACCESS) is
  6405.     NEW_FIELD     : FIELD_ACCESS;
  6406.     STRING_LENGTH : NATURAL;
  6407.     INDEX         : INTEGER;
  6408.     begin
  6409.     if NAME'LENGTH > 0 then
  6410.         begin
  6411.         -- see if field name already exists
  6412.         NEW_FIELD := GET_FIELD_POINTER (FORM, NAME);
  6413.         for INDEX in NAME'FIRST .. NAME'LAST loop
  6414.             if NAME (INDEX  -- field found
  6415.                  ) /= ' ' then
  6416.             raise DUPLICATE_FIELD_NAME;
  6417.             end if;
  6418.         end loop;
  6419.  
  6420.         exception
  6421.         when FIELD_NAME_NOT_FOUND =>  -- no field found
  6422.             null;
  6423.         end;
  6424.     end if;
  6425.  
  6426.     NEW_FIELD := new FIELD_RECORD;
  6427.  
  6428.     STRING_LENGTH := NAME'LENGTH;
  6429.     if (STRING_LENGTH > MAX_FIELD_NAME) then
  6430.         STRING_LENGTH := MAX_FIELD_NAME;
  6431.     else
  6432.         NEW_FIELD.NAME := (1 .. MAX_FIELD_NAME => ' ');
  6433.     end if;
  6434.     NEW_FIELD.NAME (1 .. STRING_LENGTH) :=
  6435.       NAME (NAME'FIRST .. NAME'FIRST + STRING_LENGTH - 1);
  6436.  
  6437.     NEW_FIELD.POSITION := POSITION;
  6438.     NEW_FIELD.LENGTH := LENGTH;
  6439.     NEW_FIELD.RENDITION := RENDITION;
  6440.     NEW_FIELD.CHAR_LIMITS := CHAR_LIMITS;
  6441.  
  6442.     STRING_LENGTH := INIT_VALUE'LENGTH;
  6443.     if (STRING_LENGTH > MAX_FIELD_VALUE) then
  6444.         STRING_LENGTH := MAX_FIELD_VALUE;
  6445.     else
  6446.         NEW_FIELD.INIT_VALUE := (1 .. MAX_FIELD_VALUE => ' ');
  6447.     end if;
  6448.     NEW_FIELD.INIT_VALUE (1 .. STRING_LENGTH) :=
  6449.       INIT_VALUE (INIT_VALUE'FIRST .. INIT_VALUE'FIRST + STRING_LENGTH - 1);
  6450.  
  6451.     NEW_FIELD.VALUE := NEW_FIELD.INIT_VALUE;
  6452.  
  6453.     NEW_FIELD.MODE := MODE;
  6454.     NEW_FIELD.FORM := FORM;
  6455.  
  6456.     INSERT_FIELD (NEW_FIELD);
  6457.  
  6458.     FIELD := NEW_FIELD;
  6459.  
  6460.     exception
  6461.     when STORAGE_ERROR => 
  6462.         raise FIELD_ALLOCATION_ERROR;
  6463.     when CONSTRAINT_ERROR => 
  6464.         if FORM = null then
  6465.         raise NULL_FORM_POINTER;
  6466.         else
  6467.         raise;
  6468.         end if;
  6469.  
  6470.     end ADD_FIELD;
  6471.  
  6472.  
  6473. --------------------------------------------------------------------------
  6474. -- Abstract   : COPY_FIELD creates a new field from information from
  6475. --              another field in the form.
  6476. --------------------------------------------------------------------------
  6477. -- Parameters : FIELD - pointer to the field data structure to be copied
  6478. --              NEW_NAME - name of the new field
  6479. --              NEW_POSITION - position of the new field with the form
  6480. --              NEW_FIELD - pointer to the create field data structure
  6481. --------------------------------------------------------------------------
  6482.     procedure COPY_FIELD (FIELD        : FIELD_ACCESS;
  6483.               NEW_NAME     : STRING;
  6484.               NEW_POSITION : FIELD_POSITION;
  6485.               NEW_FIELD    : out FIELD_ACCESS) is
  6486.     begin
  6487.  
  6488.     ADD_FIELD
  6489.        (FIELD.FORM, NEW_NAME, NEW_POSITION, FIELD.LENGTH, FIELD.RENDITION,
  6490.         FIELD.CHAR_LIMITS, FIELD.INIT_VALUE, FIELD.MODE, NEW_FIELD);
  6491.  
  6492.     exception
  6493.     when CONSTRAINT_ERROR => 
  6494.         if FIELD = null then
  6495.         raise NULL_FIELD_POINTER;
  6496.         else
  6497.         raise;
  6498.         end if;
  6499.  
  6500.     end COPY_FIELD;
  6501.  
  6502.  
  6503. --------------------------------------------------------------------------
  6504. -- Abstract   : DELETE_FIELD deletes a field from a form
  6505. --------------------------------------------------------------------------
  6506. -- Parameters : FIELD - pointer to the field data structure to be deleted
  6507. --------------------------------------------------------------------------
  6508.     procedure DELETE_FIELD (FIELD : FIELD_ACCESS) is
  6509.     begin
  6510.  
  6511.     REMOVE_FIELD (FIELD);
  6512.  
  6513.     end DELETE_FIELD;
  6514.  
  6515.  
  6516. --------------------------------------------------------------------------
  6517. -- Abstract   : INSERT_FIELD inserts a field data structure into the
  6518. --              list of fields for a form based on its position
  6519. --------------------------------------------------------------------------
  6520. -- Parameters : FIELD - pointer to the field data structure
  6521. --------------------------------------------------------------------------
  6522. -- Algorithm  : The field is inserted into the list of fields in order
  6523. --              of position within the form (left to right, top to bottom)
  6524. --------------------------------------------------------------------------
  6525.     procedure INSERT_FIELD (FIELD : FIELD_ACCESS) is
  6526.     FORM       : FORM_ACCESS;
  6527.     NEXT_FIELD : FIELD_ACCESS;
  6528.     PREV_FIELD : FIELD_ACCESS;
  6529.     begin
  6530.  
  6531.     FORM := FIELD.FORM;
  6532.  
  6533.     if FIELD.POSITION.LINE > FORM.SIZE.ROWS or
  6534.        FIELD.POSITION.COLUMN > FORM.SIZE.COLUMNS then
  6535.         raise POSITION_OUT_OF_FORM_RANGE;
  6536.     end if;
  6537.  
  6538.     if FIELD.POSITION.COLUMN + FIELD.LENGTH - 1 > FORM.SIZE.COLUMNS then
  6539.         raise FIELD_EXTENDS_PAST_FORM;
  6540.     end if;
  6541.  
  6542.     NEXT_FIELD := FORM.FIRST_FIELD;
  6543.     PREV_FIELD := null;
  6544.  
  6545.     while NEXT_FIELD /= null and then
  6546.           (FIELD.POSITION.LINE > NEXT_FIELD.POSITION.LINE or else
  6547.            (FIELD.POSITION.LINE = NEXT_FIELD.POSITION.LINE and then
  6548.         FIELD.POSITION.COLUMN > NEXT_FIELD.POSITION.COLUMN)) loop
  6549.         PREV_FIELD := NEXT_FIELD;
  6550.         NEXT_FIELD := PREV_FIELD.NEXT_FIELD;
  6551.     end loop;
  6552.  
  6553.     if PREV_FIELD /= null and then
  6554.        PREV_FIELD.POSITION.LINE = FIELD.POSITION.LINE and then
  6555.        PREV_FIELD.POSITION.COLUMN + PREV_FIELD.LENGTH >
  6556.        FIELD.POSITION.COLUMN then
  6557.         raise FIELD_OVERLAP_OCCURRED;
  6558.     end if;
  6559.  
  6560.     if NEXT_FIELD /= null and then
  6561.        FIELD.POSITION.LINE = NEXT_FIELD.POSITION.LINE and then
  6562.        FIELD.POSITION.COLUMN + FIELD.LENGTH >
  6563.        NEXT_FIELD.POSITION.COLUMN then
  6564.         raise FIELD_OVERLAP_OCCURRED;
  6565.     end if;
  6566.  
  6567.     FIELD.PREV_FIELD := PREV_FIELD;
  6568.     FIELD.NEXT_FIELD := NEXT_FIELD;
  6569.  
  6570.     if PREV_FIELD = null then
  6571.         FORM.FIRST_FIELD := FIELD;
  6572.     else
  6573.         PREV_FIELD.NEXT_FIELD := FIELD;
  6574.     end if;
  6575.  
  6576.     if NEXT_FIELD /= null then
  6577.         NEXT_FIELD.PREV_FIELD := FIELD;
  6578.     end if;
  6579.  
  6580.     exception
  6581.     when CONSTRAINT_ERROR => 
  6582.         if FIELD = null then
  6583.         raise NULL_FIELD_POINTER;
  6584.         elsif FORM = null then
  6585.         raise NULL_FORM_POINTER;
  6586.         else
  6587.         raise;
  6588.         end if;
  6589.  
  6590.     end INSERT_FIELD;
  6591.  
  6592.  
  6593. --------------------------------------------------------------------------
  6594. -- Abstract   : MOVE_FIELD moves a field from one location in the form
  6595. --              to another without changing any other attributes.
  6596. --------------------------------------------------------------------------
  6597. -- Parameters : FIELD - pointer to the field data structure to be moved
  6598. --              NEW_POSITION - position where the field is to be moved
  6599. --------------------------------------------------------------------------
  6600. -- Algorithm  : The field is removed from form and then reinserted at the
  6601. --              new location.
  6602. --------------------------------------------------------------------------
  6603.     procedure MOVE_FIELD (FIELD        : FIELD_ACCESS;
  6604.               NEW_POSITION : FIELD_POSITION) is
  6605.     begin
  6606.  
  6607.     REMOVE_FIELD (FIELD);
  6608.     FIELD.POSITION := NEW_POSITION;
  6609.     INSERT_FIELD (FIELD);
  6610.  
  6611.     end MOVE_FIELD;
  6612.  
  6613.  
  6614. --------------------------------------------------------------------------
  6615. -- Abstract   : REMOVE_FIELD removes a field from the list of fields for
  6616. --              a form.
  6617. --------------------------------------------------------------------------
  6618. -- Parameters : FIELD - pointer to the field data structure to be removed
  6619. --------------------------------------------------------------------------
  6620.     procedure REMOVE_FIELD (FIELD : FIELD_ACCESS) is
  6621.     begin
  6622.  
  6623.     if FIELD.PREV_FIELD = null then
  6624.         FIELD.FORM.FIRST_FIELD := FIELD.NEXT_FIELD;
  6625.     else
  6626.         FIELD.PREV_FIELD.NEXT_FIELD := FIELD.NEXT_FIELD;
  6627.     end if;
  6628.  
  6629.     if FIELD.NEXT_FIELD /= null then
  6630.         FIELD.NEXT_FIELD.PREV_FIELD := FIELD.PREV_FIELD;
  6631.     end if;
  6632.  
  6633.     exception
  6634.     when CONSTRAINT_ERROR => 
  6635.         if FIELD = null then
  6636.         raise NULL_FIELD_POINTER;
  6637.         else
  6638.         raise;
  6639.         end if;
  6640.  
  6641.     end REMOVE_FIELD;
  6642.  
  6643.  
  6644. --------------------------------------------------------------------------
  6645. -- Abstract   : GET_FIELD_VALUE returns the current value of a field
  6646. --              given its name.
  6647. --------------------------------------------------------------------------
  6648. -- Parameters : FORM - pointer to the form data structure
  6649. --              NAME - name of the field for which the value is desired
  6650. --------------------------------------------------------------------------
  6651.     function GET_FIELD_VALUE (FORM : FORM_ACCESS;
  6652.                   NAME : STRING) return FIELD_VALUE is
  6653.     FIELD : FIELD_ACCESS;
  6654.  
  6655.     begin
  6656.  
  6657.     FIELD := GET_FIELD_POINTER (FORM, NAME);
  6658.     return FIELD.VALUE;
  6659.  
  6660.     end GET_FIELD_VALUE;
  6661.  
  6662.  
  6663. --------------------------------------------------------------------------
  6664. -- Abstract   : GET_FIELD_POINTER returns the pointer to a field given
  6665. --              its field name.
  6666. --------------------------------------------------------------------------
  6667. -- Parameters : FORM - pointer to form data structure
  6668. --              NAME - name of the field whose pointer is desired
  6669. --------------------------------------------------------------------------
  6670. -- Algorithm  : Searches the list of fields until it comes to the
  6671. --              field whose name matches the input name.
  6672. --------------------------------------------------------------------------
  6673.     function GET_FIELD_POINTER (FORM : FORM_ACCESS;
  6674.                 NAME : STRING) return FIELD_ACCESS is
  6675.     FIELD         : FIELD_ACCESS;
  6676.  
  6677.     FULL_NAME     : FIELD_NAME;
  6678.     STRING_LENGTH : NATURAL;
  6679.     begin
  6680.  
  6681.     STRING_LENGTH := NAME'LENGTH;
  6682.     if (STRING_LENGTH > MAX_FIELD_NAME) then
  6683.         STRING_LENGTH := MAX_FIELD_NAME;
  6684.     else
  6685.         FULL_NAME := (1 .. MAX_FIELD_NAME => ' ');
  6686.     end if;
  6687.     FULL_NAME (1 .. STRING_LENGTH) :=
  6688.       NAME (NAME'FIRST .. NAME'FIRST + STRING_LENGTH - 1);
  6689.  
  6690.     FIELD := FORM.FIRST_FIELD;
  6691.  
  6692.     while FIELD /= null loop
  6693.         if FULL_NAME = FIELD.NAME then
  6694.         return FIELD;
  6695.         end if;
  6696.         FIELD := FIELD.NEXT_FIELD;
  6697.     end loop;
  6698.  
  6699.     raise FIELD_NAME_NOT_FOUND;
  6700.  
  6701.     exception
  6702.     when CONSTRAINT_ERROR => 
  6703.         if FORM = null then
  6704.         raise NULL_FORM_POINTER;
  6705.         else
  6706.         raise;
  6707.         end if;
  6708.  
  6709.     end GET_FIELD_POINTER;
  6710.  
  6711.  
  6712. --------------------------------------------------------------------------
  6713. -- Abstract   : GET_FIELD_POINTER returns the pointer to a field given
  6714. --              its field position.
  6715. --------------------------------------------------------------------------
  6716. -- Parameters : FORM - pointer to form data structure
  6717. --              POSITION - position of the field with the form
  6718. --------------------------------------------------------------------------
  6719. -- Algorithm  : Searches the list of fields until it comes to the
  6720. --              field whose position matches the input position.
  6721. --------------------------------------------------------------------------
  6722.     function GET_FIELD_POINTER (FORM     : FORM_ACCESS;
  6723.                 POSITION : FIELD_POSITION)
  6724.                  return FIELD_ACCESS is
  6725.     FIELD : FIELD_ACCESS;
  6726.     begin
  6727.  
  6728.     FIELD := FORM.FIRST_FIELD;
  6729.  
  6730.     while FIELD /= null loop
  6731.         if POSITION.LINE = FIELD.POSITION.LINE and then
  6732.            POSITION.COLUMN >= FIELD.POSITION.COLUMN and then
  6733.            POSITION.COLUMN < FIELD.POSITION.COLUMN + FIELD.LENGTH then
  6734.         return FIELD;
  6735.         end if;
  6736.         FIELD := FIELD.NEXT_FIELD;
  6737.     end loop;
  6738.  
  6739.     raise FIELD_POSITION_NOT_FOUND;
  6740.  
  6741.     exception
  6742.     when CONSTRAINT_ERROR => 
  6743.         if FORM = null then
  6744.         raise NULL_FORM_POINTER;
  6745.         else
  6746.         raise;
  6747.         end if;
  6748.  
  6749.     end GET_FIELD_POINTER;
  6750.  
  6751.  
  6752. --------------------------------------------------------------------------
  6753. -- Abstract   : GET_FIELD_INFO returns the current information for a
  6754. --              field.
  6755. --------------------------------------------------------------------------
  6756. -- Parameters : FIELD - pointer to the field data structure
  6757. --              NAME - name of the field as a string
  6758. --              POSITION - position of the field within the form
  6759. --              LENGTH - length of the field
  6760. --              RENDITION - rendition in which the field is displayed
  6761. --              CHAR_LIMITS - character limitation for field contents
  6762. --              INIT_VALUE - initial value of field if not modified
  6763. --              VALUE - current value of the field
  6764. --              MODE - type of field (constant, output only, input/output)
  6765. --------------------------------------------------------------------------
  6766.     procedure GET_FIELD_INFO (FIELD       : FIELD_ACCESS;
  6767.                   NAME        : out FIELD_NAME;
  6768.                   POSITION    : out FIELD_POSITION;
  6769.                   LENGTH      : out FIELD_LENGTH;
  6770.                   RENDITION   : out FIELD_RENDITIONS;
  6771.                   CHAR_LIMITS : out CHAR_TYPE;
  6772.                   INIT_VALUE  : out FIELD_VALUE;
  6773.                   VALUE       : out FIELD_VALUE;
  6774.                   MODE        : out FIELD_MODE) is
  6775.     begin
  6776.  
  6777.     NAME := FIELD.NAME;
  6778.     POSITION := FIELD.POSITION;
  6779.     LENGTH := FIELD.LENGTH;
  6780.     RENDITION := FIELD.RENDITION;
  6781.     CHAR_LIMITS := FIELD.CHAR_LIMITS;
  6782.     INIT_VALUE := FIELD.INIT_VALUE;
  6783.     VALUE := FIELD.VALUE;
  6784.     MODE := FIELD.MODE;
  6785.  
  6786.     exception
  6787.     when CONSTRAINT_ERROR => 
  6788.         if FIELD = null then
  6789.         raise NULL_FIELD_POINTER;
  6790.         else
  6791.         raise;
  6792.         end if;
  6793.  
  6794.     end GET_FIELD_INFO;
  6795.  
  6796.  
  6797. --------------------------------------------------------------------------
  6798. -- Abstract   : MODIFY_FIELD_LENGTH modifies the length of a field.
  6799. --------------------------------------------------------------------------
  6800. -- Parameters : FIELD - pointer to the field data structure
  6801. --              LENGTH - length of the field
  6802. --------------------------------------------------------------------------
  6803.     procedure MODIFY_FIELD_LENGTH (FIELD  : FIELD_ACCESS;
  6804.                    LENGTH : FIELD_LENGTH) is
  6805.     NEXT_FIELD : FIELD_ACCESS;
  6806.     begin
  6807.  
  6808.     if FIELD.POSITION.COLUMN + LENGTH - 1 > FIELD.FORM.SIZE.COLUMNS then
  6809.         raise FIELD_EXTENDS_PAST_FORM;
  6810.     end if;
  6811.  
  6812.     if FIELD.NEXT_FIELD /= null then
  6813.         NEXT_FIELD := FIELD.NEXT_FIELD;
  6814.         if FIELD.POSITION.LINE = NEXT_FIELD.POSITION.LINE and then
  6815.            FIELD.POSITION.COLUMN + LENGTH - 1 >
  6816.            NEXT_FIELD.POSITION.COLUMN then
  6817.         raise FIELD_OVERLAP_OCCURRED;
  6818.         end if;
  6819.     end if;
  6820.  
  6821.     FIELD.LENGTH := LENGTH;
  6822.  
  6823.     exception
  6824.     when CONSTRAINT_ERROR => 
  6825.         if FIELD = null then
  6826.         raise NULL_FIELD_POINTER;
  6827.         else
  6828.         raise;
  6829.         end if;
  6830.  
  6831.     end MODIFY_FIELD_LENGTH;
  6832.  
  6833.  
  6834. --------------------------------------------------------------------------
  6835. -- Abstract   : MODIFY_FIELD_RENDITION modifies the display rendition
  6836. --              for a field.
  6837. --------------------------------------------------------------------------
  6838. -- Parameters : FIELD - pointer to the field data structure
  6839. --              RENDITION - rendition in which the field is displayed
  6840. --------------------------------------------------------------------------
  6841.     procedure MODIFY_FIELD_RENDITION (FIELD     : FIELD_ACCESS;
  6842.                       RENDITION : FIELD_RENDITIONS) is
  6843.     begin
  6844.  
  6845.     FIELD.RENDITION := RENDITION;
  6846.  
  6847.     exception
  6848.     when CONSTRAINT_ERROR => 
  6849.         if FIELD = null then
  6850.         raise NULL_FIELD_POINTER;
  6851.         else
  6852.         raise;
  6853.         end if;
  6854.  
  6855.     end MODIFY_FIELD_RENDITION;
  6856.  
  6857.  
  6858. --------------------------------------------------------------------------
  6859. -- Abstract   : MODIFY_FIELD_LIMITS modifies the character limitation
  6860. --              for a field
  6861. --------------------------------------------------------------------------
  6862. -- Parameters : FIELD - pointer to the field data structure
  6863. --              CHAR_LIMITS - character limitation for field contents
  6864. --------------------------------------------------------------------------
  6865.     procedure MODIFY_FIELD_LIMITS (FIELD       : FIELD_ACCESS;
  6866.                    CHAR_LIMITS : CHAR_TYPE) is
  6867.     begin
  6868.  
  6869.     FIELD.CHAR_LIMITS := CHAR_LIMITS;
  6870.  
  6871.     exception
  6872.     when CONSTRAINT_ERROR => 
  6873.         if FIELD = null then
  6874.         raise NULL_FIELD_POINTER;
  6875.         else
  6876.         raise;
  6877.         end if;
  6878.  
  6879.     end MODIFY_FIELD_LIMITS;
  6880.  
  6881.  
  6882. --------------------------------------------------------------------------
  6883. -- Abstract   : MODIFY_FIELD_INIT modifies the initial value of a field
  6884. --------------------------------------------------------------------------
  6885. -- Parameters : FIELD - pointer to the field data structure
  6886. --              INIT_VALUE - initial value of field if not modified
  6887. --------------------------------------------------------------------------
  6888.     procedure MODIFY_FIELD_INIT (FIELD      : FIELD_ACCESS;
  6889.                  INIT_VALUE : STRING) is
  6890.     STRING_LENGTH : NATURAL;
  6891.     begin
  6892.  
  6893.     STRING_LENGTH := INIT_VALUE'LENGTH;
  6894.     if (STRING_LENGTH > MAX_FIELD_VALUE) then
  6895.         STRING_LENGTH := MAX_FIELD_VALUE;
  6896.     else
  6897.         FIELD.INIT_VALUE := (1 .. MAX_FIELD_VALUE => ' ');
  6898.     end if;
  6899.     FIELD.INIT_VALUE (1 .. STRING_LENGTH) :=
  6900.       INIT_VALUE (INIT_VALUE'FIRST .. INIT_VALUE'FIRST + STRING_LENGTH - 1);
  6901.  
  6902.     exception
  6903.     when CONSTRAINT_ERROR => 
  6904.         if FIELD = null then
  6905.         raise NULL_FIELD_POINTER;
  6906.         else
  6907.         raise;
  6908.         end if;
  6909.  
  6910.     end MODIFY_FIELD_INIT;
  6911.  
  6912.  
  6913. --------------------------------------------------------------------------
  6914. -- Abstract   : MODIFY_FIELD_VALUE modifies the current value of a field
  6915. --------------------------------------------------------------------------
  6916. -- Parameters : FIELD - pointer to the field data structure
  6917. --              VALUE - current value of the field
  6918. --------------------------------------------------------------------------
  6919. -- Algorithm  : Cannot change the value of a constant field.
  6920. --------------------------------------------------------------------------
  6921.     procedure MODIFY_FIELD_VALUE (FIELD : FIELD_ACCESS; VALUE : STRING) is
  6922.     STRING_LENGTH : NATURAL;
  6923.     begin
  6924.  
  6925.     if FIELD.MODE = CONSTANT_TEXT then
  6926.         raise CONSTANT_FIELD_ERROR;
  6927.     end if;
  6928.  
  6929.     STRING_LENGTH := VALUE'LENGTH;
  6930.     if (STRING_LENGTH > MAX_FIELD_VALUE) then
  6931.         STRING_LENGTH := MAX_FIELD_VALUE;
  6932.     else
  6933.         FIELD.VALUE := (1 .. MAX_FIELD_VALUE => ' ');
  6934.     end if;
  6935.     FIELD.VALUE (1 .. STRING_LENGTH) :=
  6936.       VALUE (VALUE'FIRST .. VALUE'FIRST + STRING_LENGTH - 1);
  6937.  
  6938.     exception
  6939.     when CONSTRAINT_ERROR => 
  6940.         if FIELD = null then
  6941.         raise NULL_FIELD_POINTER;
  6942.         else
  6943.         raise;
  6944.         end if;
  6945.  
  6946.     end MODIFY_FIELD_VALUE;
  6947.  
  6948.  
  6949. --------------------------------------------------------------------------
  6950. -- Abstract   : MODIFY_FIELD_MODE modifies the mode attribute of a field
  6951. --------------------------------------------------------------------------
  6952. -- Parameters : FIELD - pointer to the field data structure
  6953. --              MODE - type of field (constant, output only, input/output)
  6954. --------------------------------------------------------------------------
  6955.     procedure MODIFY_FIELD_MODE (FIELD : FIELD_ACCESS; MODE : FIELD_MODE) is
  6956.     begin
  6957.  
  6958.     FIELD.MODE := MODE;
  6959.  
  6960.     exception
  6961.     when CONSTRAINT_ERROR => 
  6962.         if FIELD = null then
  6963.         raise NULL_FIELD_POINTER;
  6964.         else
  6965.         raise;
  6966.         end if;
  6967.  
  6968.     end MODIFY_FIELD_MODE;
  6969.  
  6970.  
  6971. --------------------------------------------------------------------------
  6972. -- Abstract   : GET_FIRST_FIELD returns the first field of the form.
  6973. --------------------------------------------------------------------------
  6974. -- Parameters : FORM - pointer to the form data structure
  6975. --------------------------------------------------------------------------
  6976.     function GET_FIRST_FIELD (FORM : FORM_ACCESS) return FIELD_ACCESS is
  6977.     begin
  6978.  
  6979.     if FORM.FIRST_FIELD = null then
  6980.         raise FIELD_NOT_FOUND;
  6981.     else
  6982.         return FORM.FIRST_FIELD;
  6983.     end if;
  6984.  
  6985.     exception
  6986.     when CONSTRAINT_ERROR => 
  6987.         if FORM = null then
  6988.         raise NULL_FORM_POINTER;
  6989.         else
  6990.         raise;
  6991.         end if;
  6992.  
  6993.     end GET_FIRST_FIELD;
  6994.  
  6995.  
  6996. --------------------------------------------------------------------------
  6997. -- Abstract   : GET_FIRST_FIELD returns the first field of a row of a form
  6998. --------------------------------------------------------------------------
  6999. -- Parameters : FORM - pointer to the form data structure
  7000. --              ROW - row for which the field is desired
  7001. --------------------------------------------------------------------------
  7002.     function GET_FIRST_FIELD (FORM : FORM_ACCESS;
  7003.                   ROW  : FORM_TYPES.ROW_RANGE)
  7004.                    return FIELD_ACCESS is
  7005.     FIELD : FIELD_ACCESS;
  7006.     begin
  7007.  
  7008.     if ROW < 1 or ROW > FORM.SIZE.ROWS then
  7009.         raise INVALID_ROW_NUMBER;
  7010.     end if;
  7011.  
  7012.     FIELD := FORM.FIRST_FIELD;
  7013.  
  7014.     while FIELD /= null and then FIELD.POSITION.LINE < ROW loop
  7015.         FIELD := FIELD.NEXT_FIELD;
  7016.     end loop;
  7017.  
  7018.     if FIELD = null or else FIELD.POSITION.LINE > ROW then
  7019.         raise FIELD_NOT_FOUND;
  7020.     end if;
  7021.  
  7022.     return FIELD;
  7023.  
  7024.     exception
  7025.     when CONSTRAINT_ERROR => 
  7026.         if FORM = null then
  7027.         raise NULL_FORM_POINTER;
  7028.         else
  7029.         raise;
  7030.         end if;
  7031.  
  7032.     end GET_FIRST_FIELD;
  7033.  
  7034.  
  7035. --------------------------------------------------------------------------
  7036. -- Abstract   : GET_NEXT_FIELD returns the next field after a field.
  7037. --------------------------------------------------------------------------
  7038. -- Parameters : FIELD - pointer to the field data structure
  7039. --------------------------------------------------------------------------
  7040.     function GET_NEXT_FIELD (FIELD : FIELD_ACCESS) return FIELD_ACCESS is
  7041.     begin
  7042.  
  7043.     if FIELD.NEXT_FIELD = null then
  7044.         raise FIELD_NOT_FOUND;
  7045.     else
  7046.         return FIELD.NEXT_FIELD;
  7047.     end if;
  7048.  
  7049.     exception
  7050.     when CONSTRAINT_ERROR => 
  7051.         if FIELD = null then
  7052.         raise NULL_FIELD_POINTER;
  7053.         else
  7054.         raise;
  7055.         end if;
  7056.  
  7057.     end GET_NEXT_FIELD;
  7058.  
  7059.  
  7060. --------------------------------------------------------------------------
  7061. -- Abstract   : GET_PREVIOUS_FIELD returns the field in front of a field.
  7062. --------------------------------------------------------------------------
  7063. -- Parameters : FIELD - pointer to the field data structure
  7064. --------------------------------------------------------------------------
  7065.     function GET_PREVIOUS_FIELD (FIELD : FIELD_ACCESS) return FIELD_ACCESS is
  7066.     begin
  7067.  
  7068.     if FIELD.PREV_FIELD = null then
  7069.         raise FIELD_NOT_FOUND;
  7070.     else
  7071.         return FIELD.PREV_FIELD;
  7072.     end if;
  7073.  
  7074.     exception
  7075.     when CONSTRAINT_ERROR => 
  7076.         if FIELD = null then
  7077.         raise NULL_FIELD_POINTER;
  7078.         else
  7079.         raise;
  7080.         end if;
  7081.  
  7082.     end GET_PREVIOUS_FIELD;
  7083.  
  7084.  
  7085. end FORM_MANAGER;
  7086. ::::::::::
  7087. MANAGER_SPEC.ADA
  7088. ::::::::::
  7089. --------------------------------------------------------------------------
  7090. -- Abstract   : This package defines the types and routines to operate
  7091. --              on forms and fields of a form.
  7092. --------------------------------------------------------------------------
  7093.  
  7094. with FORM_TYPES;
  7095.  
  7096. package FORM_MANAGER is
  7097.  
  7098. -- Visible Form Types
  7099.  
  7100.     MAX_FIELD_NAME  : constant INTEGER := 32;
  7101.     MAX_FIELD_VALUE : constant INTEGER := 80;
  7102.  
  7103.     subtype FORM_POSITION is FORM_TYPES.XY_POSITION;
  7104.  
  7105.     type FORM_SIZE is -- form size record
  7106.     record
  7107.         ROWS    : FORM_TYPES.ROW_RANGE;
  7108.         COLUMNS : FORM_TYPES.COLUMN_RANGE;
  7109.     end record;
  7110.  
  7111.     type OPTION_TYPE is (CLEAR, NO_CLEAR);
  7112.  
  7113. -- Visible Field Types
  7114.  
  7115.     type CHAR_TYPE is (ALPHA, NUMERIC, ALPHA_NUMERIC, NOT_LIMITED);
  7116.  
  7117.     subtype FIELD_LENGTH is INTEGER range 1 .. FORM_TYPES.MAX_COLUMNS;
  7118.  
  7119.     type FIELD_MODE is (CONSTANT_TEXT, OUTPUT_ONLY, INPUT_OUTPUT);
  7120.  
  7121.     subtype FIELD_NAME is STRING (1 .. MAX_FIELD_NAME);
  7122.  
  7123.     subtype FIELD_POSITION is FORM_TYPES.XY_POSITION;
  7124.  
  7125.     subtype FIELD_RENDITIONS is FORM_TYPES.DISPLAY_RENDITIONS;
  7126.  
  7127.     subtype FIELD_VALUE is STRING (1 .. MAX_FIELD_VALUE);
  7128.  
  7129.  
  7130. -- Access types
  7131.  
  7132.     type FORM_ACCESS  is private;
  7133.     type FIELD_ACCESS is private;
  7134.  
  7135.  
  7136. -- Form operations
  7137.  
  7138.     procedure CREATE_FORM (SIZE         : FORM_SIZE;
  7139.                POSITION     : FORM_POSITION;
  7140.                CLEAR_OPTION : OPTION_TYPE;
  7141.                FORM         : out FORM_ACCESS);
  7142.  
  7143.     procedure GET_FORM_INFO (FORM         : FORM_ACCESS;
  7144.                  SIZE         : out FORM_SIZE;
  7145.                  POSITION     : out FORM_POSITION;
  7146.                  CLEAR_OPTION : out OPTION_TYPE);
  7147.  
  7148.     procedure MODIFY_FORM_SIZE (FORM : FORM_ACCESS; SIZE : FORM_SIZE);
  7149.  
  7150.     procedure MODIFY_FORM_POSITION (FORM     : FORM_ACCESS;
  7151.                     POSITION : FORM_POSITION);
  7152.  
  7153.     procedure MODIFY_FORM_OPTION (FORM         : FORM_ACCESS;
  7154.                   CLEAR_OPTION : OPTION_TYPE);
  7155.  
  7156.     procedure CLEAR_FORM (FORM : FORM_ACCESS);
  7157.  
  7158.     procedure LOAD_FORM (PATHNAME : STRING; FORM : out FORM_ACCESS);
  7159.  
  7160.     procedure SAVE_FORM (FORM : FORM_ACCESS; PATHNAME : STRING);
  7161.  
  7162.     procedure RELEASE_FORM (FORM : FORM_ACCESS);
  7163.  
  7164.  
  7165. -- Field operations
  7166.  
  7167.     procedure ADD_FIELD
  7168.          (FORM        : FORM_ACCESS;
  7169.           NAME        : STRING;
  7170.           POSITION    : FIELD_POSITION;
  7171.           LENGTH      : FIELD_LENGTH;
  7172.           RENDITION   : FIELD_RENDITIONS :=
  7173.                 FORM_TYPES.PRIMARY_RENDITION;
  7174.           CHAR_LIMITS : CHAR_TYPE := NOT_LIMITED;
  7175.           INIT_VALUE  : STRING := "";
  7176.           MODE        : FIELD_MODE := INPUT_OUTPUT;
  7177.           FIELD       : out FIELD_ACCESS);
  7178.  
  7179.     procedure COPY_FIELD (FIELD        : FIELD_ACCESS;
  7180.               NEW_NAME     : STRING;
  7181.               NEW_POSITION : FIELD_POSITION;
  7182.               NEW_FIELD    : out FIELD_ACCESS);
  7183.  
  7184.     procedure DELETE_FIELD (FIELD : FIELD_ACCESS);
  7185.  
  7186.     procedure MOVE_FIELD (FIELD        : FIELD_ACCESS;
  7187.               NEW_POSITION : FIELD_POSITION);
  7188.  
  7189.     function GET_FIELD_VALUE (FORM : FORM_ACCESS;
  7190.                   NAME : STRING) return FIELD_VALUE;
  7191.  
  7192.     function GET_FIELD_POINTER (FORM : FORM_ACCESS;
  7193.                 NAME : STRING) return FIELD_ACCESS;
  7194.  
  7195.     function GET_FIELD_POINTER (FORM     : FORM_ACCESS;
  7196.                 POSITION : FIELD_POSITION) return FIELD_ACCESS;
  7197.  
  7198.     procedure GET_FIELD_INFO (FIELD       : FIELD_ACCESS;
  7199.                   NAME        : out FIELD_NAME;
  7200.                   POSITION    : out FIELD_POSITION;
  7201.                   LENGTH      : out FIELD_LENGTH;
  7202.                   RENDITION   : out FIELD_RENDITIONS;
  7203.                   CHAR_LIMITS : out CHAR_TYPE;
  7204.                   INIT_VALUE  : out FIELD_VALUE;
  7205.                   VALUE       : out FIELD_VALUE;
  7206.                   MODE        : out FIELD_MODE);
  7207.  
  7208.     procedure MODIFY_FIELD_LENGTH (FIELD  : FIELD_ACCESS;
  7209.                    LENGTH : FIELD_LENGTH);
  7210.  
  7211.     procedure MODIFY_FIELD_RENDITION (FIELD     : FIELD_ACCESS;
  7212.                       RENDITION : FIELD_RENDITIONS);
  7213.  
  7214.     procedure MODIFY_FIELD_LIMITS (FIELD       : FIELD_ACCESS;
  7215.                    CHAR_LIMITS : CHAR_TYPE);
  7216.  
  7217.     procedure MODIFY_FIELD_INIT (FIELD : FIELD_ACCESS; INIT_VALUE : STRING);
  7218.  
  7219.     procedure MODIFY_FIELD_VALUE (FIELD : FIELD_ACCESS; VALUE : STRING);
  7220.  
  7221.     procedure MODIFY_FIELD_MODE (FIELD : FIELD_ACCESS; MODE : FIELD_MODE);
  7222.  
  7223.     function GET_FIRST_FIELD (FORM : FORM_ACCESS) return FIELD_ACCESS;
  7224.  
  7225.     function GET_FIRST_FIELD (FORM : FORM_ACCESS;
  7226.                   ROW  : FORM_TYPES.ROW_RANGE) return FIELD_ACCESS;
  7227.  
  7228.     function GET_NEXT_FIELD (FIELD : FIELD_ACCESS) return FIELD_ACCESS;
  7229.  
  7230.     function GET_PREVIOUS_FIELD (FIELD : FIELD_ACCESS) return FIELD_ACCESS;
  7231.  
  7232.  
  7233. -- Exceptions
  7234.  
  7235.     CONSTANT_FIELD_ERROR       : exception;
  7236.     DUPLICATE_FIELD_NAME       : exception;
  7237.     FILE_ALREADY_OPEN          : exception;
  7238.     FILE_NOT_FOUND             : exception;
  7239.     FILE_DATA_ERROR            : exception;
  7240.     FIELD_ALLOCATION_ERROR     : exception;
  7241.     FIELD_EXTENDS_PAST_FORM    : exception;
  7242.     FIELD_NAME_NOT_FOUND       : exception;
  7243.     FIELD_NOT_FOUND            : exception;
  7244.     FIELD_OVERLAP_OCCURRED     : exception;
  7245.     FIELD_POSITION_NOT_FOUND   : exception;
  7246.     FORM_ALLOCATION_ERROR      : exception;
  7247.     FORM_TOO_BIG               : exception;
  7248.     INVALID_ROW_NUMBER         : exception;
  7249.     NULL_FORM_POINTER          : exception;
  7250.     NULL_FIELD_POINTER         : exception;
  7251.     POSITION_OUT_OF_FORM_RANGE : exception;
  7252.  
  7253. private
  7254.  
  7255. -- Form structure
  7256.  
  7257.     type FORM_RECORD is
  7258.     record
  7259.         SIZE         : FORM_SIZE;
  7260.         POSITION     : FORM_POSITION;
  7261.         CLEAR_OPTION : OPTION_TYPE;
  7262.         FIRST_FIELD  : FIELD_ACCESS;
  7263.     end record;
  7264.  
  7265.     type FORM_ACCESS is access FORM_RECORD;
  7266.  
  7267. -- Field structure
  7268.  
  7269.     type FIELD_RECORD is
  7270.     record
  7271.         NAME        : FIELD_NAME;
  7272.         POSITION    : FIELD_POSITION;
  7273.         LENGTH      : FIELD_LENGTH;
  7274.         RENDITION   : FIELD_RENDITIONS;
  7275.         CHAR_LIMITS : CHAR_TYPE;
  7276.         VALUE       : FIELD_VALUE;
  7277.         INIT_VALUE  : FIELD_VALUE;
  7278.         MODE        : FIELD_MODE;
  7279.         FORM        : FORM_ACCESS;
  7280.         NEXT_FIELD  : FIELD_ACCESS;
  7281.         PREV_FIELD  : FIELD_ACCESS;
  7282.     end record;
  7283.  
  7284.     type FIELD_ACCESS is access FIELD_RECORD;
  7285.  
  7286. end FORM_MANAGER;
  7287. ::::::::::
  7288. SUBMENUS.ADA
  7289. ::::::::::
  7290. separate (INTERACT)
  7291. procedure CREATE_FORM -------------------------------------------------------------------------
  7292. -- Abstract   : This procedure creates a new blank form and enters the
  7293. --              Form Editor with this blank form.  The user is prompted
  7294. --              for the attributes of this new form.
  7295. -------------------------------------------------------------------------
  7296. -- Parameters : none.
  7297. -------------------------------------------------------------------------
  7298. -- Algorithm  : The Form Executor is utilized for retrieving the form
  7299. --              attributes from the user.
  7300. -------------------------------------------------------------------------
  7301.       is
  7302.  
  7303.     SIZE     : FORM_MANAGER.FORM_SIZE;
  7304.     POSITION : FORM_MANAGER.FORM_POSITION;
  7305.     OPTION   : FORM_MANAGER.OPTION_TYPE;
  7306.  
  7307.     FORM_SIZE_TOO_LARGE : exception;
  7308.  
  7309. begin
  7310.     FORMS.GET_FORM_INFO (SIZE, POSITION, OPTION, CREATE_FORM => TRUE);
  7311.     if SIZE.ROWS > FORM_TYPES.MAX_ROWS or else
  7312.        SIZE.COLUMNS > FORM_TYPES.MAX_COLUMNS then
  7313.     raise FORM_SIZE_TOO_LARGE;
  7314.     end if;
  7315.  
  7316.     FORM_MANAGER.CREATE_FORM (SIZE, POSITION, OPTION, CURRENT_FORM);
  7317.     FORM_MANAGER.GET_FORM_INFO
  7318.        (CURRENT_FORM, CURRENT_SIZE, CURRENT_POSITION, CURRENT_OPTION);
  7319.  
  7320.     FILENAME := (1 .. 48 => ' ');
  7321.  
  7322.     EDIT_FORM;
  7323.  
  7324.     CURRENT_FORM_HAS_BEEN_ALTERED := TRUE;
  7325.  
  7326. exception
  7327.     when FORM_SIZE_TOO_LARGE => 
  7328.     TERMINAL_INTERFACE.PUT_MESSAGE
  7329.        ("Form size is too large to fit on display!!");
  7330.     delay 1.0;
  7331.  
  7332.     when FORM_MANAGER.FORM_ALLOCATION_ERROR => 
  7333.     TERMINAL_INTERFACE.PUT_MESSAGE
  7334.        ("Storage error - form was not created.");
  7335.     delay 1.0;
  7336.  
  7337.  
  7338.     when CONSTRAINT_ERROR => 
  7339.     TERMINAL_INTERFACE.PUT_MESSAGE ("Error in retrieving form information");
  7340.     delay 1.0;
  7341.  
  7342. end CREATE_FORM;
  7343. separate (INTERACT)
  7344. procedure LOAD_FORM -------------------------------------------------------------------------
  7345. -- Abstract   : This procedure loads in a form from an external file.
  7346. --              The name of this external file is provided by the user.
  7347. --              The Form Editor is automatically entered with this loaded
  7348. --              form being displayed.
  7349. -------------------------------------------------------------------------
  7350. -- Parameters : none.
  7351. -------------------------------------------------------------------------
  7352. -- Algorithm  : The Form Executor is used for retrieving the name of the
  7353. --              external file from the user.
  7354. -------------------------------------------------------------------------
  7355.       is
  7356.  
  7357. begin
  7358.     FORMS.GET_FILE_NAME (FILENAME, LOAD_FORM => TRUE);
  7359.  
  7360.     FORM_MANAGER.LOAD_FORM (FILENAME, CURRENT_FORM);
  7361.  
  7362.     EDIT_FORM;
  7363.  
  7364.     CURRENT_FORM_HAS_BEEN_ALTERED := TRUE;
  7365.  
  7366. exception
  7367.     when FORM_MANAGER.FILE_NOT_FOUND => 
  7368.     TERMINAL_INTERFACE.PUT_MESSAGE ("File not found with the given name.");
  7369.     delay 1.0;
  7370.  
  7371.     when FORM_MANAGER.FILE_ALREADY_OPEN => 
  7372.     TERMINAL_INTERFACE.PUT_MESSAGE ("File being used by another user!");
  7373.     delay 1.0;
  7374.  
  7375.     when others => 
  7376.     TERMINAL_INTERFACE.PUT_MESSAGE
  7377.        ("File does not contain a valid form format!");
  7378.     delay 1.0;
  7379.  
  7380. end LOAD_FORM;
  7381. separate (INTERACT)
  7382. procedure EDIT_FORM -------------------------------------------------------------------------
  7383. -- Abstract   : This procedure is the initialization for the Form Editor.
  7384. --              The screen is cleared and the Current Form is displayed.
  7385. -------------------------------------------------------------------------
  7386. -- Parameters : none.
  7387. -------------------------------------------------------------------------
  7388.       is
  7389.  
  7390.     FIELD      : FORM_MANAGER.FIELD_ACCESS;
  7391.     NAME       : FORM_MANAGER.FIELD_NAME;
  7392.     POSITION   : FORM_MANAGER.FIELD_POSITION;
  7393.     LENGTH     : FORM_MANAGER.FIELD_LENGTH;
  7394.     RENDITION  : FORM_MANAGER.FIELD_RENDITIONS;
  7395.     LIMITS     : FORM_MANAGER.CHAR_TYPE;
  7396.     INIT_VALUE : FORM_MANAGER.FIELD_VALUE;
  7397.     VALUE      : FORM_MANAGER.FIELD_VALUE;
  7398.     MODE       : FORM_MANAGER.FIELD_MODE;
  7399.  
  7400.     TEMP_INIT  : FORM_MANAGER.FIELD_VALUE;
  7401.  
  7402.     SIZE       : TERMINAL_INTERFACE.SCREEN_POSITION;
  7403.  
  7404.     function "=" (LEFT, RIGHT : FORM_MANAGER.FIELD_MODE) return BOOLEAN
  7405.            renames FORM_MANAGER."=";
  7406.  
  7407. ---------------------------------------------------------------------
  7408.     procedure GET_INFO (FIELD : FORM_MANAGER.FIELD_ACCESS) is
  7409.     begin
  7410.     FORM_MANAGER.GET_FIELD_INFO
  7411.        (FIELD, NAME, POSITION, LENGTH, RENDITION, LIMITS, INIT_VALUE,
  7412.         VALUE, MODE);
  7413.     end GET_INFO;
  7414.  
  7415. ---------------------------------------------------------------------
  7416.  
  7417. begin
  7418.  
  7419.     -- Clear screen and display introductory message.
  7420.  
  7421.     TERMINAL_INTERFACE.SCREEN_SIZE (SIZE);
  7422.  
  7423.     TERMINAL_INTERFACE.CLEAR_SCREEN;
  7424.     TERMINAL_INTERFACE.PUT_FIELD
  7425.        ((SIZE.LINE, 1), 40, FORM_TYPES.REVERSE_RENDITION,
  7426.     "Entering the Interactive Form Editor....");
  7427.     delay 0.5;
  7428.  
  7429.     -- Clear the message line.
  7430.  
  7431.     TERMINAL_INTERFACE.SPLIT_DISPLAY (SIZE);
  7432.  
  7433.     -- Display the Current Form with the non-text fields coded according
  7434.     --   to the individual field's character limitations.
  7435.  
  7436.     FORM_MANAGER.GET_FORM_INFO
  7437.        (CURRENT_FORM, CURRENT_SIZE, CURRENT_POSITION, CURRENT_OPTION);
  7438.     begin
  7439.     FIELD := FORM_MANAGER.GET_FIRST_FIELD (CURRENT_FORM);
  7440.     loop
  7441.         GET_INFO (FIELD);
  7442.         POSITION.LINE := POSITION.LINE + CURRENT_POSITION.LINE - 1;
  7443.         POSITION.COLUMN := POSITION.COLUMN + CURRENT_POSITION.COLUMN - 1;
  7444.  
  7445.         TEMP_INIT := INIT_VALUE;
  7446.         if MODE /= FORM_MANAGER.CONSTANT_TEXT then
  7447.         case LIMITS is
  7448.             when FORM_MANAGER.ALPHA => 
  7449.             TEMP_INIT (1 .. LENGTH) := (1 .. LENGTH => 'a');
  7450.  
  7451.             when FORM_MANAGER.NUMERIC => 
  7452.             TEMP_INIT (1 .. LENGTH) := (1 .. LENGTH => 'n');
  7453.  
  7454.             when FORM_MANAGER.ALPHA_NUMERIC => 
  7455.             TEMP_INIT (1 .. LENGTH) := (1 .. LENGTH => 'b');
  7456.  
  7457.             when FORM_MANAGER.NOT_LIMITED => 
  7458.             TEMP_INIT (1 .. LENGTH) := (1 .. LENGTH => 'x');
  7459.  
  7460.         end case;
  7461.         end if;
  7462.  
  7463.         TERMINAL_INTERFACE.PUT_FIELD
  7464.            (POSITION, LENGTH, RENDITION, TEMP_INIT);
  7465.  
  7466.         FIELD := FORM_MANAGER.GET_NEXT_FIELD (FIELD);
  7467.     end loop;
  7468.  
  7469.     exception
  7470.     when FORM_MANAGER.FIELD_NOT_FOUND => 
  7471.         null;
  7472.     end;
  7473.  
  7474.     EDITOR.EDITOR_DRIVER (CURRENT_FORM);
  7475.  
  7476. exception
  7477.     when FORM_MANAGER.NULL_FORM_POINTER => 
  7478.     TERMINAL_INTERFACE.PUT_MESSAGE ("There is no Current Form!!");
  7479.     delay 1.0;
  7480. end EDIT_FORM;
  7481. separate (INTERACT)
  7482. procedure SAVE_FORM -------------------------------------------------------------------------
  7483. -- Abstract   : This procedure saves a form and all of its fields off
  7484. --              into an external file.  The user is prompted for this
  7485. --              external file name.  When this Save Form procedure is
  7486. --              executed, the name of the external file is initially
  7487. --              assumed if the Current Form was originally loaded in
  7488. --              using Load Form.  The user can, of course, override this
  7489. --              assumed file name.
  7490. -------------------------------------------------------------------------
  7491. -- Parameters : none.
  7492. -------------------------------------------------------------------------
  7493. -- Abstract   : The Form Executor is utilized for retrieving the name
  7494. --              of the external file name.
  7495. -------------------------------------------------------------------------
  7496.       is
  7497.  
  7498. begin
  7499.  
  7500.     FORMS.GET_FILE_NAME (FILENAME, LOAD_FORM => FALSE);
  7501.  
  7502.     FORM_MANAGER.SAVE_FORM (CURRENT_FORM, FILENAME);
  7503.  
  7504.     CURRENT_FORM_HAS_BEEN_ALTERED := FALSE;
  7505.  
  7506. exception
  7507.     when FORM_MANAGER.NULL_FORM_POINTER => 
  7508.     TERMINAL_INTERFACE.PUT_MESSAGE ("There is no Current Form!");
  7509.     delay 1.0;
  7510.  
  7511.     when FORM_MANAGER.FILE_ALREADY_OPEN => 
  7512.     TERMINAL_INTERFACE.PUT_MESSAGE
  7513.        ("File currently being used by another user.");
  7514.     delay 1.0;
  7515.  
  7516.     when others => 
  7517.     TERMINAL_INTERFACE.PUT_MESSAGE
  7518.        ("Error in attempting to save the Current Form");
  7519.     delay 1.0;
  7520.  
  7521. end SAVE_FORM;
  7522. separate (INTERACT)
  7523. procedure MODIFY_FORM_ATTRIBUTES -------------------------------------------------------------------------
  7524. -- Abstract   : This procedure retrives the attributes of a form from
  7525. --              the user.
  7526. -------------------------------------------------------------------------
  7527. -- Parameters : none.
  7528. -------------------------------------------------------------------------
  7529. -- Algorithm  : The Form Executor is used to retrieve the form attribute
  7530. --              values from the user.
  7531. -------------------------------------------------------------------------
  7532.       is
  7533.  
  7534.     OLD_SIZE     : FORM_MANAGER.FORM_SIZE;
  7535.     OLD_POSITION : FORM_MANAGER.FORM_POSITION;
  7536.     OLD_OPTION   : FORM_MANAGER.OPTION_TYPE;
  7537.  
  7538.     FORM_SIZE_TOO_LARGE : exception;
  7539.  
  7540. begin
  7541.     FORM_MANAGER.GET_FORM_INFO
  7542.        (CURRENT_FORM, CURRENT_SIZE, CURRENT_POSITION, CURRENT_OPTION);
  7543.  
  7544.     OLD_SIZE := CURRENT_SIZE;
  7545.     OLD_POSITION := CURRENT_POSITION;
  7546.     OLD_OPTION := CURRENT_OPTION;
  7547.  
  7548.     FORMS.GET_FORM_INFO
  7549.        (CURRENT_SIZE, CURRENT_POSITION, CURRENT_OPTION, CREATE_FORM => FALSE);
  7550.  
  7551.     if CURRENT_SIZE.ROWS > FORM_TYPES.MAX_ROWS or else
  7552.        CURRENT_SIZE.COLUMNS > FORM_TYPES.MAX_COLUMNS then
  7553.     raise FORM_SIZE_TOO_LARGE;
  7554.     end if;
  7555.  
  7556.     FORM_MANAGER.MODIFY_FORM_SIZE (CURRENT_FORM, CURRENT_SIZE);
  7557.     FORM_MANAGER.MODIFY_FORM_POSITION (CURRENT_FORM, CURRENT_POSITION);
  7558.     FORM_MANAGER.MODIFY_FORM_OPTION (CURRENT_FORM, CURRENT_OPTION);
  7559. exception
  7560.     when FORM_SIZE_TOO_LARGE => 
  7561.     TERMINAL_INTERFACE.PUT_MESSAGE
  7562.        ("Specified form size to too large for display!!!");
  7563.     CURRENT_SIZE := OLD_SIZE;
  7564.     CURRENT_POSITION := OLD_POSITION;
  7565.     CURRENT_OPTION := OLD_OPTION;
  7566.  
  7567.     when FORM_MANAGER.NULL_FORM_POINTER => 
  7568.     TERMINAL_INTERFACE.PUT_MESSAGE ("There is no Current Form!");
  7569.  
  7570. end MODIFY_FORM_ATTRIBUTES;
  7571. ::::::::::
  7572. TERMINAL_BODY.ADA
  7573. ::::::::::
  7574. --------------------------------------------------------------------------
  7575. -- Abstract   : This package body defines the routines which interface
  7576. --              the Form Generator to the terminal.  This version uses
  7577. --              the Virtual Terminal to provide the terminal interface.
  7578. --------------------------------------------------------------------------
  7579.  
  7580. with PAGE_TERMINAL;
  7581.  
  7582. package body TERMINAL_INTERFACE is
  7583.  
  7584. -- 
  7585. -- Global Data of Use Throughout Life of Package
  7586. -- 
  7587.     DATA                    : STRING (1 .. 40);
  7588.     LAST                    : NATURAL;
  7589.     KEYS                    : PAGE_TERMINAL.FUNCTION_KEY_DESCRIPTOR (2);
  7590.     NUMBER_OF_FUNCTION_KEYS : NATURAL;
  7591.     CHAR_INDEX              : NATURAL;
  7592.     FUNC_INDEX              : NATURAL;
  7593.     NUMBER_OF_KEYS          : NATURAL := 0; -- init to 0 for proper
  7594.                         -- initial invocation
  7595.     FKEY_ID                 : PAGE_TERMINAL.FUNCTION_KEY_ENUM;
  7596.     FKEY_POSITION           : NATURAL;
  7597.     UNGET_CHARTYPE          : CHAR_ENUM;
  7598.     UNGET_CHAR              : CHARACTER;
  7599.     UNGET_FUNC              : FUNCTION_KEY_ENUM;
  7600.     UNGET_PENDING           : BOOLEAN := FALSE;
  7601.  
  7602. -- 
  7603. -- General screen manipulation routines
  7604. -- 
  7605.  
  7606. --------------------------------------------------------------------------
  7607. -- Abstract   : OPEN initializes the terminal for processing by the
  7608. --              Form Generator.
  7609. --------------------------------------------------------------------------
  7610. -- Parameters : none
  7611. --------------------------------------------------------------------------
  7612. -- Algorithm  : It calls the Virtual Terminal Open routine with the name
  7613. --              "fgs" which is should define the terminal interface for
  7614. --              the Form Generator routines.
  7615. --------------------------------------------------------------------------
  7616.     procedure OPEN is
  7617.     begin
  7618.     PAGE_TERMINAL.OPEN ("fgs");
  7619.     end OPEN;
  7620.  
  7621. --------------------------------------------------------------------------
  7622. -- Abstract   : CLOSE terminates the connection with the terminal.
  7623. --------------------------------------------------------------------------
  7624. -- Parameters : none
  7625. --------------------------------------------------------------------------
  7626.     procedure CLOSE is
  7627.     begin
  7628.     CLEAR_SCREEN;
  7629.     PAGE_TERMINAL.CLOSE; -- close terminal
  7630.     end CLOSE;
  7631.  
  7632. --------------------------------------------------------------------------
  7633. -- Abstract   : REFRESH makes sure the the terminal displays what the
  7634. --              Form Generator routines have output to the terminal.
  7635. --------------------------------------------------------------------------
  7636. -- Parameters : none
  7637. --------------------------------------------------------------------------
  7638.     procedure REFRESH is
  7639.     begin
  7640.     PAGE_TERMINAL.REDRAW_SCREEN;
  7641.     end REFRESH;
  7642.  
  7643. --------------------------------------------------------------------------
  7644. -- Abstract   : CLEAR_SCREEN erases the text from the entire screen and
  7645. --              displays blanks.
  7646. --------------------------------------------------------------------------
  7647. -- Parameters : none
  7648. --------------------------------------------------------------------------
  7649.     procedure CLEAR_SCREEN is
  7650.     begin
  7651.     PAGE_TERMINAL.ERASE_IN_DISPLAY (PAGE_TERMINAL.ALL_POSITIONS);
  7652.     PAGE_TERMINAL.REDRAW_SCREEN;
  7653.     end CLEAR_SCREEN;
  7654.  
  7655. --------------------------------------------------------------------------
  7656. -- Abstract   : PUT_MESSAGE outputs a warning or error message at the
  7657. --              bottom right hand corner of the display in secondary
  7658. --              rendition.
  7659. --------------------------------------------------------------------------
  7660. -- Parameters : TEXT - string of message to be displayed
  7661. --              (Parameters are only required for routines)
  7662. --------------------------------------------------------------------------
  7663.     procedure PUT_MESSAGE (TEXT : STRING) is
  7664.     NEW_POSITION     : PAGE_TERMINAL.XY_POSITION;
  7665.     CURRENT_POSITION : SCREEN_POSITION;
  7666.     begin
  7667.     GET_CURSOR (CURRENT_POSITION);
  7668.  
  7669.     NEW_POSITION := PAGE_TERMINAL.SIZE;
  7670.     NEW_POSITION.COLUMN := 32;
  7671.     PAGE_TERMINAL.SET_POSITION (NEW_POSITION);
  7672.     PAGE_TERMINAL.ERASE_IN_LINE (PAGE_TERMINAL.FROM_XY_POSITION_TO_END);
  7673.  
  7674.     NEW_POSITION := PAGE_TERMINAL.SIZE; -- compute new position
  7675.     if NEW_POSITION.COLUMN > TEXT'LENGTH then
  7676.         NEW_POSITION.COLUMN := NEW_POSITION.COLUMN - TEXT'LENGTH;
  7677.     else
  7678.         NEW_POSITION.COLUMN := 1; -- live with overflow
  7679.     end if;
  7680.  
  7681.     PAGE_TERMINAL.SET_POSITION (NEW_POSITION);
  7682.     SELECT_RENDITION (FORM_TYPES.SECONDARY_RENDITION);
  7683.     PAGE_TERMINAL.PUT (TEXT);
  7684.     SELECT_RENDITION (FORM_TYPES.PRIMARY_RENDITION);
  7685.     PAGE_TERMINAL.BELL;
  7686.     PAGE_TERMINAL.UPDATE_LINE (NEW_POSITION.LINE);
  7687.  
  7688.     PUT_CURSOR (CURRENT_POSITION);
  7689.  
  7690.     end PUT_MESSAGE;
  7691.  
  7692. --------------------------------------------------------------------------
  7693. -- Abstract   : PUT_CURSOR positions the cursor to a specific location
  7694. --              on the screen.
  7695. --------------------------------------------------------------------------
  7696. -- Parameters : POSITION - desired position of cursor in row and column
  7697. --------------------------------------------------------------------------
  7698.     procedure PUT_CURSOR (POSITION : SCREEN_POSITION) is
  7699.     PAGE_POSITION : PAGE_TERMINAL.XY_POSITION;
  7700.     begin
  7701.     PAGE_POSITION.LINE := POSITION.LINE; -- translate to page terminal
  7702.     PAGE_POSITION.COLUMN := POSITION.COLUMN;
  7703.     PAGE_TERMINAL.SET_POSITION (PAGE_POSITION);
  7704.     PAGE_TERMINAL.UPDATE_CURSOR;
  7705.     end PUT_CURSOR;
  7706.  
  7707. --------------------------------------------------------------------------
  7708. -- Abstract   : GET_CURSOR returns the current position of the cursor.
  7709. --------------------------------------------------------------------------
  7710. -- Parameters : POSITION - current position of cursor in row and column
  7711. --------------------------------------------------------------------------
  7712.     procedure GET_CURSOR (POSITION : out SCREEN_POSITION) is
  7713.     PAGE_POSITION : PAGE_TERMINAL.XY_POSITION;
  7714.     begin
  7715.     PAGE_POSITION := PAGE_TERMINAL.POSITION;
  7716.     POSITION.LINE := PAGE_POSITION.LINE;
  7717.     POSITION.COLUMN := PAGE_POSITION.COLUMN;
  7718.     end GET_CURSOR;
  7719.  
  7720.  
  7721. --------------------------------------------------------------------------
  7722. -- Abstract   : SELECT_RENDITION sets the display rendition of the screen.
  7723. --------------------------------------------------------------------------
  7724. -- Parameters : RENDITION - desired display rendition
  7725. --------------------------------------------------------------------------
  7726. -- Algorithm  : Primary and Underline => Primary
  7727. --              Secondary and Reverse => Reverse
  7728. --------------------------------------------------------------------------
  7729.     procedure SELECT_RENDITION (RENDITION : GRAPHIC_TYPE) is
  7730.     PAGE_RENDITION : PAGE_TERMINAL.GRAPHIC_RENDITION_ENUMERATION;
  7731.     begin
  7732.     case RENDITION is
  7733.         when FORM_TYPES.PRIMARY_RENDITION => 
  7734.         PAGE_RENDITION := PAGE_TERMINAL.PRIMARY_RENDITION;
  7735.         when FORM_TYPES.REVERSE_RENDITION |
  7736.          FORM_TYPES.SECONDARY_RENDITION => 
  7737.         PAGE_RENDITION := PAGE_TERMINAL.REVERSE_IMAGE;
  7738.         when others => 
  7739.         PAGE_RENDITION := PAGE_TERMINAL.PRIMARY_RENDITION;
  7740.     end case;
  7741.     PAGE_TERMINAL.SELECT_GRAPHIC_RENDITION (PAGE_RENDITION);
  7742.     end SELECT_RENDITION;
  7743.  
  7744.  
  7745. --------------------------------------------------------------------------
  7746. -- Abstract   : SCREEN_SIZE returns the size of the screen display in
  7747. --              rows and columns.
  7748. --------------------------------------------------------------------------
  7749. -- Parameters : SIZE - size of screen in rows and columns
  7750. --------------------------------------------------------------------------
  7751.     procedure SCREEN_SIZE (SIZE : out SCREEN_POSITION) is
  7752.     PAGE_SIZE : PAGE_TERMINAL.XY_POSITION;
  7753.     begin
  7754.     PAGE_SIZE := PAGE_TERMINAL.SIZE;
  7755.     SIZE.LINE := PAGE_SIZE.LINE;
  7756.     SIZE.COLUMN := PAGE_SIZE.COLUMN;
  7757.     end SCREEN_SIZE;
  7758.  
  7759.  
  7760. -- 
  7761. -- Screen and line shifting routines
  7762. -- 
  7763.  
  7764. --------------------------------------------------------------------------
  7765. -- Abstract   : SPLIT_DISPLAY inserts a blank line into the display at
  7766. --              the desired cursor position and causing the current line
  7767. --              and all following lines to be scrolled down one line.
  7768. --              The last line of the display is scrolled off the display.
  7769. --------------------------------------------------------------------------
  7770. -- Parameters : POSITION - position at which the line is to be inserted
  7771. --------------------------------------------------------------------------
  7772.     procedure SPLIT_DISPLAY (POSITION : SCREEN_POSITION) is
  7773.     begin
  7774.     PUT_CURSOR (POSITION);
  7775.     PAGE_TERMINAL.INSERT_LINE (1);
  7776.     PAGE_TERMINAL.UPDATE_SCREEN (POSITION.LINE, PAGE_TERMINAL.SIZE.LINE);
  7777.     end SPLIT_DISPLAY;
  7778.  
  7779. --------------------------------------------------------------------------
  7780. -- Abstract   : CLOSE_UP_DISPLAY deletes a line of text from the display
  7781. --              and all lines below it are shifted upward to fill in the
  7782. --              line.
  7783. --------------------------------------------------------------------------
  7784. -- Parameters : POSITION - position at which the line is to be deleted
  7785. --------------------------------------------------------------------------
  7786.     procedure CLOSE_UP_DISPLAY (POSITION : SCREEN_POSITION) is
  7787.     begin
  7788.     PUT_CURSOR (POSITION);
  7789.     PAGE_TERMINAL.DELETE_LINE (1);
  7790.     PAGE_TERMINAL.UPDATE_SCREEN (POSITION.LINE, PAGE_TERMINAL.SIZE.LINE);
  7791.     end CLOSE_UP_DISPLAY;
  7792.  
  7793.  
  7794. -- 
  7795. -- Field display routines
  7796. -- 
  7797.  
  7798. --------------------------------------------------------------------------
  7799. -- Abstract   : PUT_FIELD outputs the contents of a field at a specific
  7800. --              location on the screen given the length of the field,
  7801. --              display
  7802. --------------------------------------------------------------------------
  7803. -- Parameters : POSITION - position of the beginning of the field
  7804. --              LENGTH - length of the field is number of characters
  7805. --              RENDITION - display rendition of field
  7806. --              VALUE - value to be display in field
  7807. --------------------------------------------------------------------------
  7808.     procedure PUT_FIELD (POSITION  : SCREEN_POSITION;
  7809.              LENGTH    : NATURAL;
  7810.              RENDITION : GRAPHIC_TYPE;
  7811.              VALUE     : STRING) is
  7812.     begin
  7813.     PUT_CURSOR (POSITION);
  7814.     SELECT_RENDITION (RENDITION);
  7815.     PAGE_TERMINAL.PUT (VALUE (1 .. LENGTH));
  7816.     SELECT_RENDITION (FORM_TYPES.PRIMARY_RENDITION);
  7817.     PAGE_TERMINAL.UPDATE_LINE (POSITION.LINE);
  7818.     end PUT_FIELD;
  7819.  
  7820. --------------------------------------------------------------------------
  7821. -- Abstract   : ERASE_FIELD erases the field by writing blanks into the
  7822. --              field
  7823. --------------------------------------------------------------------------
  7824. -- Parameters : POSITION - position of the beginning of the field
  7825. --              LENGTH - length of the field is number of characters
  7826. --------------------------------------------------------------------------
  7827.     procedure ERASE_FIELD (POSITION : SCREEN_POSITION; LENGTH : NATURAL) is
  7828.     begin
  7829.     PUT_CURSOR (POSITION);
  7830.     SELECT_RENDITION (FORM_TYPES.PRIMARY_RENDITION);
  7831.     PAGE_TERMINAL.PUT ((1 .. LENGTH => ' ')); -- write spaces in field
  7832.     PAGE_TERMINAL.UPDATE_LINE (POSITION.LINE);
  7833.     end ERASE_FIELD;
  7834.  
  7835. --------------------------------------------------------------------------
  7836. -- Abstract   : EDIT_FIELD handles the modification of a field value with
  7837. --              editing functions
  7838. --------------------------------------------------------------------------
  7839. -- Parameters : POSITION - position of the beginning of the field
  7840. --              LENGTH - length of the field is number of characters
  7841. --              RENDITION - display rendition of field
  7842. --              VALUE - value to be display in field
  7843. --------------------------------------------------------------------------
  7844. -- Algorithm  : LEFT_ARROW and RIGHT_ARROW - moves cursor left and right
  7845. --              DEL_CHAR - deletes the current character
  7846. --              DEL_EOLN - deletes to end of field
  7847. --              INS_CHAR - toggles insert/overtype mode
  7848. --              RUBOUT - deletes the previous character
  7849. --------------------------------------------------------------------------
  7850.     procedure EDIT_FIELD (POSITION  : SCREEN_POSITION;
  7851.               LENGTH    : NATURAL;
  7852.               RENDITION : GRAPHIC_TYPE;
  7853.               VALUE     : in out STRING) is
  7854.  
  7855.     CHAR        : CHARACTER;
  7856.     CHARTYPE    : CHAR_ENUM;
  7857.     CURSOR      : SCREEN_POSITION;
  7858.     FUNCT       : FUNCTION_KEY_ENUM;
  7859.     INDEX       : NATURAL := 1;
  7860.     INSERT_MODE : BOOLEAN := FALSE;
  7861.  
  7862.     procedure DELETE_CHAR (INDEX : NATURAL) is
  7863.         i : NATURAL;
  7864.     begin
  7865.         for i in INDEX .. LENGTH - 1 loop
  7866.         VALUE (i) := VALUE (i + 1);
  7867.         end loop;
  7868.         VALUE (LENGTH) := ' ';
  7869.         PUT_FIELD (POSITION, LENGTH, RENDITION, VALUE);
  7870.     end DELETE_CHAR;
  7871.  
  7872.     procedure DELETE_EOLN (INDEX : NATURAL) is
  7873.         i : NATURAL;
  7874.     begin
  7875.         for i in INDEX .. LENGTH loop
  7876.         VALUE (i) := ' ';
  7877.         end loop;
  7878.         PUT_FIELD (POSITION, LENGTH, RENDITION, VALUE);
  7879.     end DELETE_EOLN;
  7880.  
  7881.     procedure INSERT_CHAR (INDEX : NATURAL; CHAR : CHARACTER) is
  7882.         i : NATURAL;
  7883.     begin
  7884.         i := LENGTH;
  7885.         while i > INDEX loop
  7886.         VALUE (i) := VALUE (i - 1);
  7887.         i := i - 1;
  7888.         end loop;
  7889.         VALUE (INDEX) := CHAR;
  7890.         PUT_FIELD (POSITION, LENGTH, RENDITION, VALUE);
  7891.     end INSERT_CHAR;
  7892.  
  7893.     begin
  7894.     PUT_FIELD (POSITION, LENGTH, RENDITION, VALUE);
  7895.     CURSOR := POSITION;
  7896.  
  7897.     loop
  7898.         PUT_CURSOR (CURSOR);
  7899.         GET_CHARACTER (CHARTYPE, CHAR, FUNCT);
  7900.         case CHARTYPE is
  7901.         when TIMEOUT => 
  7902.             null; -- just wait for next character
  7903.         when FUNC_TYPE => 
  7904.             case FUNCT is
  7905.             when RIGHT_ARROW =>  -- move cursor right
  7906.                 if INDEX < LENGTH then
  7907.                 INDEX := INDEX + 1;
  7908.                 CURSOR.COLUMN := CURSOR.COLUMN + 1;
  7909.                 else
  7910.                 PAGE_TERMINAL.BELL;
  7911.                 end if;
  7912.             when LEFT_ARROW | RUBOUT =>  -- move cursor left
  7913.                 if INDEX > 1 then
  7914.                 INDEX := INDEX - 1;
  7915.                 CURSOR.COLUMN := CURSOR.COLUMN - 1;
  7916.                 if FUNCT = RUBOUT then
  7917.                     DELETE_CHAR (INDEX);
  7918.                 end if;
  7919.                 else
  7920.                 PAGE_TERMINAL.BELL;
  7921.                 end if;
  7922.             when DEL_CHAR =>  -- delete character
  7923.                 DELETE_CHAR (INDEX);
  7924.             when DEL_EOLN =>  -- delete to end-of-line
  7925.                 DELETE_EOLN (INDEX);
  7926.             when INS_CHAR =>  -- insert character
  7927.                 INSERT_MODE := not INSERT_MODE;
  7928.             when others =>  -- save for caller
  7929.                 UNGET_CHARACTER (CHARTYPE, CHAR, FUNCT);
  7930.                 return;
  7931.             end case;
  7932.         when CHAR_TYPE =>  -- add character to line
  7933.             if CHAR >= ' ' and CHAR <= '~' then
  7934.             if INDEX <= LENGTH then
  7935.                 if INSERT_MODE then
  7936.                 INSERT_CHAR (INDEX, CHAR);
  7937.                 else
  7938.                 PUT_CHARACTER (CHAR);
  7939.                 VALUE (INDEX) := CHAR;
  7940.                 end if;
  7941.                 if INDEX <= LENGTH then
  7942.                 INDEX := INDEX + 1;
  7943.                 CURSOR.COLUMN := CURSOR.COLUMN + 1;
  7944.                 end if;
  7945.             else
  7946.                 PAGE_TERMINAL.BELL;
  7947.             end if;
  7948.             else
  7949.             PAGE_TERMINAL.BELL;
  7950.             end if;
  7951.         end case;
  7952.     end loop;
  7953.  
  7954.     end EDIT_FIELD;
  7955.  
  7956. -- 
  7957. -- Key Processing routines
  7958. -- 
  7959.  
  7960. --------------------------------------------------------------------------
  7961. -- Abstract   : GET_CHARACTER returns the type and value of the next key
  7962. --              entered at the keyboard.
  7963. --------------------------------------------------------------------------
  7964. -- Parameters : CHARTYPE - type of key entered
  7965. --              CHAR - value of ASCII character if CHAR_TYPE
  7966. --              FUNC - value of function key if FUNC_TYPE
  7967. --------------------------------------------------------------------------
  7968.     procedure GET_CHARACTER (CHARTYPE : out CHAR_ENUM;
  7969.                  CHAR     : out CHARACTER;
  7970.                  FUNC     : out FUNCTION_KEY_ENUM) is
  7971.     PAGE_FKEY : PAGE_TERMINAL.FUNCTION_KEY_ENUM;
  7972.     -- 
  7973.     -- Global Variables used by GET_CHARACTER:
  7974.     -- 
  7975.     --      DATA            String of character keys input
  7976.     --      LAST            Number of character keys in DATA
  7977.     --      KEYS            Private type used by FUNCTION_COUNT and
  7978.     --                       FUNCTION_KEY
  7979.     --      NUMBER_OF_FUNCTION_KEYS
  7980.     --                      Number of function keys input
  7981.     --      CHAR_INDEX      Index (reverse order) of next character key;
  7982.     --                       LAST - CHAR_INDEX + 1 = index of next char key;
  7983.     --                       CHAR_INDEX = 0 means no more character keys
  7984.     --      FUNC_INDEX      Index (reverse order) of next function key;
  7985.     --                       NUMBER_OF_FUNCTION_KEYS - FUNC_INDEX + 1 =
  7986.     --                       index of next function key;
  7987.     --                       FUNC_INDEX = 0 means no more function keys
  7988.     --      NUMBER_OF_KEYS  Total number of keys remaining
  7989.     --                       (both char and function);
  7990.     --                        NUMBER_OF_KEYS = 0 means no more keys pending;
  7991.     --                        should be set to zero before first
  7992.     --                        GET_CHARACTER call
  7993.     --      FKEY_ID         ID of next function key (FUNCTION_KEY_ENUM)
  7994.     --      FKEY_POSITION   Position of next function key (index of char key
  7995.     --                        before it)
  7996.     -- 
  7997.  
  7998.     procedure RETURN_TIMEOUT is
  7999.     begin
  8000.         CHARTYPE := TIMEOUT;
  8001.         CHAR := ASCII.nul;
  8002.         FUNC := invalid;
  8003.     end RETURN_TIMEOUT;
  8004.  
  8005.     procedure RETURN_CHAR (INCHAR : CHARACTER) is
  8006. -- Map control characters to internal functions
  8007.     begin
  8008.         if INCHAR < ' ' or INCHAR = ASCII.DEL then
  8009.         CHARTYPE := FUNC_TYPE;
  8010.         CHAR := ASCII.nul;
  8011.         case INCHAR is
  8012.             when ASCII.STX =>  -- ctrl B
  8013.             FUNC := INS_CHAR;
  8014.             when ASCII.ETX =>  -- ctrl C
  8015.             FUNC := COMMAND_LINE;
  8016.             when ASCII.EOT =>  -- ctrl D
  8017.             FUNC := DEL_CHAR;
  8018.             when ASCII.ENQ =>  -- ctrl E
  8019.             FUNC := DEL_EOLN;
  8020.             when ASCII.BS =>  -- ctrl H
  8021.             FUNC := LEFT_ARROW;
  8022.             when ASCII.HT =>  -- ctrl I
  8023.             FUNC := TAB_KEY;
  8024.             when ASCII.LF =>  -- ctrl J
  8025.             FUNC := DOWN_ARROW;
  8026.             when ASCII.VT =>  -- ctrl K
  8027.             FUNC := UP_ARROW;
  8028.             when ASCII.FF =>  -- ctrl L
  8029.             FUNC := RIGHT_ARROW;
  8030.             when ASCII.CR =>  -- ctrl M
  8031.             FUNC := RETURN_KEY;
  8032.             when ASCII.SI =>  -- ctrl O
  8033.             FUNC := BACK_TAB;
  8034.             when ASCII.SYN =>  -- ctrl V
  8035.             FUNC := INS_CHAR;
  8036.             when ASCII.ETB =>  -- ctrl W
  8037.             FUNC := DEL_LINE;
  8038.             when ASCII.CAN =>  -- ctrl X
  8039.             FUNC := EXIT_FORM;
  8040.             when ASCII.DEL =>  -- ctrl bs
  8041.             FUNC := RUBOUT;
  8042.             when others => 
  8043.             CHARTYPE := CHAR_TYPE;
  8044.             CHAR := INCHAR;
  8045.             FUNC := invalid;
  8046.         end case;
  8047.         else
  8048.         CHARTYPE := CHAR_TYPE;
  8049.         CHAR := INCHAR;
  8050.         FUNC := invalid;
  8051.         end if;
  8052.     end RETURN_CHAR;
  8053.  
  8054.     procedure RETURN_FUNC (INFUNC : PAGE_TERMINAL.FUNCTION_KEY_ENUM) is
  8055. -- Map VT functions into internal functions
  8056.     begin
  8057.         CHARTYPE := FUNC_TYPE;
  8058.         CHAR := ASCII.nul;
  8059.         case INFUNC is
  8060.         when PAGE_TERMINAL.RIGHT_ARROW => 
  8061.             FUNC := RIGHT_ARROW;
  8062.         when PAGE_TERMINAL.LEFT_ARROW => 
  8063.             FUNC := LEFT_ARROW;
  8064.         when PAGE_TERMINAL.UP_ARROW => 
  8065.             FUNC := UP_ARROW;
  8066.         when PAGE_TERMINAL.DOWN_ARROW => 
  8067.             FUNC := DOWN_ARROW;
  8068.         when PAGE_TERMINAL.f1 => 
  8069.             FUNC := BACK_TAB;
  8070.         when PAGE_TERMINAL.f2 => 
  8071.             FUNC := COMMAND_LINE;
  8072.         when PAGE_TERMINAL.f3 => 
  8073.             FUNC := HELP;
  8074.         when PAGE_TERMINAL.f4 => 
  8075.             FUNC := RETURN_KEY;
  8076.         when PAGE_TERMINAL.f5 => 
  8077.             FUNC := TAB_KEY;
  8078.         when PAGE_TERMINAL.f6 => 
  8079.             FUNC := DEL_CHAR;
  8080.         when PAGE_TERMINAL.f7 => 
  8081.             FUNC := INS_CHAR;
  8082.         when PAGE_TERMINAL.f8 => 
  8083.             FUNC := RUBOUT;
  8084.         when PAGE_TERMINAL.f9 => 
  8085.             FUNC := EXIT_FORM;
  8086.         when PAGE_TERMINAL.f10 => 
  8087.             FUNC := COPY_LINE;
  8088.         when PAGE_TERMINAL.f11 => 
  8089.             FUNC := DEL_EOLN;
  8090.         when PAGE_TERMINAL.f12 => 
  8091.             FUNC := DEL_LINE;
  8092.         when PAGE_TERMINAL.f13 => 
  8093.             FUNC := INS_LINE;
  8094.         when PAGE_TERMINAL.f14 => 
  8095.             FUNC := MOVE_LINE;
  8096.         when PAGE_TERMINAL.f15 => 
  8097.             FUNC := COPY_FIELD;
  8098.         when PAGE_TERMINAL.f16 => 
  8099.             FUNC := CREATE_FIELD;
  8100.         when PAGE_TERMINAL.f17 => 
  8101.             FUNC := DEL_FIELD;
  8102.         when PAGE_TERMINAL.f18 => 
  8103.             FUNC := MODIFY_FIELD;
  8104.         when PAGE_TERMINAL.f19 => 
  8105.             FUNC := MOVE_FIELD;
  8106.         when others => 
  8107.             FUNC := invalid;
  8108.         end case;
  8109.     end RETURN_FUNC;
  8110.  
  8111.     begin
  8112.     if UNGET_PENDING then
  8113.         -- return values from last UNGET_CHARACTER
  8114.         UNGET_PENDING := FALSE;
  8115.         CHARTYPE := UNGET_CHARTYPE;
  8116.         CHAR := UNGET_CHAR;
  8117.         FUNC := UNGET_FUNC;
  8118.         return;
  8119.     end if;
  8120.  
  8121.     if NUMBER_OF_KEYS = 0 then
  8122.         -- get next set of keys
  8123.         PAGE_TERMINAL.GET (DATA, LAST, KEYS);
  8124.         NUMBER_OF_FUNCTION_KEYS := PAGE_TERMINAL.FUNCTION_COUNT (KEYS);
  8125.         CHAR_INDEX := LAST; -- set indices
  8126.         FUNC_INDEX := NUMBER_OF_FUNCTION_KEYS;
  8127.         NUMBER_OF_KEYS := LAST + NUMBER_OF_FUNCTION_KEYS;
  8128.         if FUNC_INDEX /= 0 then
  8129.         -- get first function key
  8130.         PAGE_TERMINAL.FUNCTION_KEY (KEYS, 1, FKEY_ID, FKEY_POSITION);
  8131.         end if;
  8132.     end if;
  8133.  
  8134.     if CHAR_INDEX = 0 then
  8135.         if FUNC_INDEX = 0 then
  8136.         -- 
  8137.         -- Scenario 1: No Character Keys and No Function Keys Remain;
  8138.         -- TIMEOUT
  8139.         -- 
  8140.         RETURN_TIMEOUT;
  8141.         else
  8142.         -- 
  8143.         -- Scenario 2: No Character Keys and Some Function Keys Remain
  8144.         -- 
  8145.         RETURN_FUNC (FKEY_ID);
  8146.         NUMBER_OF_KEYS := NUMBER_OF_KEYS - 1;
  8147.         FUNC_INDEX := FUNC_INDEX - 1;
  8148.         PAGE_TERMINAL.FUNCTION_KEY
  8149.            (KEYS,                                     -- get next
  8150.                                   -- function key
  8151.  
  8152.             NUMBER_OF_FUNCTION_KEYS - FUNC_INDEX + 1,
  8153.             FKEY_ID,
  8154.             FKEY_POSITION);
  8155.         end if;
  8156.     else
  8157.         if FUNC_INDEX = 0 then
  8158.         -- 
  8159.         -- Scenario 3: Character Keys and No Function Keys Remain
  8160.         -- 
  8161.         NUMBER_OF_KEYS := NUMBER_OF_KEYS - 1;
  8162.         RETURN_CHAR (DATA (LAST - CHAR_INDEX + 1));
  8163.         CHAR_INDEX := CHAR_INDEX - 1;
  8164.         else
  8165. -- 
  8166. -- Scenario 4: Character Keys and Function Keys Remain
  8167. -- 
  8168.         if FKEY_POSITION < LAST - CHAR_INDEX + 1 then
  8169.             -- 
  8170.             -- Next key is function key
  8171.             -- 
  8172.             RETURN_FUNC (FKEY_ID);
  8173.             FUNC_INDEX := FUNC_INDEX - 1;
  8174.             NUMBER_OF_KEYS := NUMBER_OF_KEYS - 1;
  8175.             if FUNC_INDEX > 0 then
  8176.             -- nxt fkey
  8177.             PAGE_TERMINAL.FUNCTION_KEY
  8178.                (KEYS, NUMBER_OF_FUNCTION_KEYS - FUNC_INDEX + 1,
  8179.                 FKEY_ID, FKEY_POSITION);
  8180.             end if;
  8181.         else
  8182.             -- 
  8183.             -- Next key is character key
  8184.             -- 
  8185.             NUMBER_OF_KEYS := NUMBER_OF_KEYS - 1;
  8186.             RETURN_CHAR (DATA (LAST - CHAR_INDEX + 1));
  8187.             CHAR_INDEX := CHAR_INDEX - 1;
  8188.         end if;
  8189.         end if;
  8190.     end if;
  8191.  
  8192.     end GET_CHARACTER;
  8193.  
  8194. --------------------------------------------------------------------------
  8195. -- Abstract   : UNGET_CHARACTER save the previous character for later
  8196. --              processing.
  8197. --------------------------------------------------------------------------
  8198. -- Parameters : CHARTYPE - type of key entered
  8199. --              CHAR - value of ASCII character if CHAR_TYPE
  8200. --              FUNC - value of function key if FUNC_TYPE
  8201. --------------------------------------------------------------------------
  8202.     procedure UNGET_CHARACTER (CHARTYPE : CHAR_ENUM;
  8203.                    CHAR     : CHARACTER;
  8204.                    FUNC     : FUNCTION_KEY_ENUM) is
  8205.     begin
  8206.     UNGET_PENDING := TRUE;
  8207.     UNGET_CHARTYPE := CHARTYPE;
  8208.     UNGET_CHAR := CHAR;
  8209.     UNGET_FUNC := FUNC;
  8210.     end UNGET_CHARACTER;
  8211.  
  8212. -- 
  8213. -- Text display routines
  8214. -- 
  8215.  
  8216. --------------------------------------------------------------------------
  8217. -- Abstract   : PUT_CHARACTER outputs a character at the current cursor
  8218. --              position.
  8219. --------------------------------------------------------------------------
  8220. -- Parameters : CHAR - character to be output
  8221. --------------------------------------------------------------------------
  8222.     procedure PUT_CHARACTER (CHAR : CHARACTER) is
  8223.     begin
  8224.     PAGE_TERMINAL.PUT (CHAR);
  8225.     PAGE_TERMINAL.UPDATE_LINE (PAGE_TERMINAL.POSITION.LINE);
  8226.     end PUT_CHARACTER;
  8227.  
  8228. --------------------------------------------------------------------------
  8229. -- Abstract   : PUT_CHARACTER outputs a character at a specific cursor
  8230. --              position.
  8231. --------------------------------------------------------------------------
  8232. -- Parameters : CHAR - character to be output
  8233. --              POSITION - postion where cursor is to be displayed
  8234. --------------------------------------------------------------------------
  8235.     procedure PUT_CHARACTER (CHAR : CHARACTER; POSITION : SCREEN_POSITION) is
  8236.     begin
  8237.     PUT_CURSOR (POSITION);
  8238.     PAGE_TERMINAL.PUT (CHAR);
  8239.     PAGE_TERMINAL.UPDATE_LINE (POSITION.LINE);
  8240.     end PUT_CHARACTER;
  8241.  
  8242. --------------------------------------------------------------------------
  8243. -- Abstract   : INSERT_CHARACTER outputs a character on a line while
  8244. --              moving the current characters from the cursor position
  8245. --              of the end of line right one position.
  8246. --------------------------------------------------------------------------
  8247. -- Parameters : CHAR - character to be output
  8248. --              POSITION - postion where cursor is to be inserted
  8249. --------------------------------------------------------------------------
  8250.     procedure INSERT_CHARACTER (CHAR     : CHARACTER;
  8251.                 POSITION : SCREEN_POSITION) is
  8252.     CURRENT_POSITION : SCREEN_POSITION;
  8253.     begin
  8254.     GET_CURSOR (CURRENT_POSITION);
  8255.     PUT_CURSOR (POSITION);
  8256.     PAGE_TERMINAL.ENTER_INSERT_MODE;
  8257.     PAGE_TERMINAL.PUT (CHAR);
  8258.     PAGE_TERMINAL.EXIT_INSERT_MODE;
  8259.     PAGE_TERMINAL.UPDATE_LINE (POSITION.LINE);
  8260.     PUT_CURSOR (CURRENT_POSITION);
  8261.     end INSERT_CHARACTER;
  8262.  
  8263. --------------------------------------------------------------------------
  8264. -- Abstract   : ERASE_CHARACTER erases the character at the specified
  8265. --              position and causes all characters to the end of line to
  8266. --              be move left one position.
  8267. --------------------------------------------------------------------------
  8268. -- Parameters : POSITION - position at which character is to be deleted
  8269. --------------------------------------------------------------------------
  8270.     procedure ERASE_CHARACTER (POSITION : SCREEN_POSITION) is
  8271.     CURRENT_POSITION : SCREEN_POSITION;
  8272.     begin
  8273.     GET_CURSOR (CURRENT_POSITION);
  8274.     PUT_CURSOR (POSITION);
  8275.     PAGE_TERMINAL.DELETE_CHARACTER (1);
  8276.     PAGE_TERMINAL.UPDATE_LINE (POSITION.LINE);
  8277.     PUT_CURSOR (CURRENT_POSITION);
  8278.     end ERASE_CHARACTER;
  8279.  
  8280. end TERMINAL_INTERFACE;
  8281. ::::::::::
  8282. TERMINAL_SPEC.ADA
  8283. ::::::::::
  8284. --------------------------------------------------------------------------
  8285. -- Abstract   : This package defines the routines to interface to the
  8286. --              terminal for the Form Generator system.
  8287. --------------------------------------------------------------------------
  8288. -- Algorithm  : Currently this package interfaces with the NOSC Virtual
  8289. --              Terminal, but it could be changed to go directly to any
  8290. --              terminal by changing the implementation of this package.
  8291. --------------------------------------------------------------------------
  8292.  
  8293. with FORM_TYPES;
  8294.  
  8295. package TERMINAL_INTERFACE is
  8296.  
  8297. -- 
  8298. -- CHAR_ENUM is used to GET_CHARACTER to return the next char/fct key/timeout
  8299. -- 
  8300.     type CHAR_ENUM is (CHAR_TYPE, FUNC_TYPE, TIMEOUT);
  8301.  
  8302. -- 
  8303. -- FUNCTION_KEY_ENUM maps to PAGE_TERMINAL.FUNCTION_KEY_ENUM
  8304. -- Conversion done in RETURN_FUNC in GET_CHARACTER
  8305. -- 
  8306.     type FUNCTION_KEY_ENUM is
  8307.      (DOWN_ARROW,   LEFT_ARROW,   RIGHT_ARROW,  UP_ARROW,
  8308.       BACK_TAB,     COMMAND_LINE, COPY_FIELD,   COPY_LINE,
  8309.       CREATE_FIELD, DEL_CHAR,     DEL_EOLN,     DEL_FIELD,
  8310.       DEL_LINE,     EXIT_FORM,    HELP,         INS_CHAR,
  8311.       INS_LINE,     MODIFY_FIELD, MOVE_FIELD,   MOVE_LINE,
  8312.       RETURN_KEY,   RUBOUT,       TAB_KEY,      INVALID);
  8313.  
  8314. -- 
  8315. -- SCREEN_POSITION maps to PAGE_TERMINAL.XY_POSITION
  8316. -- 
  8317.     subtype SCREEN_POSITION is FORM_TYPES.XY_POSITION;
  8318.  
  8319. -- 
  8320. -- GRAPHIS_TYPE maps to PAGE_TERMINAL.GRAPHIC_RENDITION_ENUMERATION
  8321. -- 
  8322.     subtype GRAPHIC_TYPE is FORM_TYPES.DISPLAY_RENDITIONS;
  8323.  
  8324. -- 
  8325. -- General screen manipulation routines
  8326. -- 
  8327.     procedure OPEN;
  8328.  
  8329.     procedure CLOSE;
  8330.  
  8331.     procedure REFRESH;
  8332.  
  8333.     procedure CLEAR_SCREEN;
  8334.  
  8335.     procedure PUT_MESSAGE (TEXT : STRING);
  8336.  
  8337.     procedure PUT_CURSOR (POSITION : SCREEN_POSITION);
  8338.  
  8339.     procedure GET_CURSOR (POSITION : out SCREEN_POSITION);
  8340.  
  8341.     procedure SELECT_RENDITION (RENDITION : GRAPHIC_TYPE);
  8342.  
  8343.     procedure SCREEN_SIZE (SIZE : out SCREEN_POSITION);
  8344.  
  8345.  
  8346. -- 
  8347. -- Screen shifting routines
  8348. -- 
  8349.     procedure SPLIT_DISPLAY (POSITION : SCREEN_POSITION);
  8350.  
  8351.     procedure CLOSE_UP_DISPLAY (POSITION : SCREEN_POSITION);
  8352.  
  8353.  
  8354. -- 
  8355. -- Field display routines
  8356. -- 
  8357.     procedure PUT_FIELD (POSITION  : SCREEN_POSITION;
  8358.              LENGTH    : NATURAL;
  8359.              RENDITION : GRAPHIC_TYPE;
  8360.              VALUE     : STRING);
  8361.  
  8362.     procedure ERASE_FIELD (POSITION : SCREEN_POSITION; LENGTH : NATURAL);
  8363.  
  8364.     procedure EDIT_FIELD (POSITION  : SCREEN_POSITION;
  8365.               LENGTH    : NATURAL;
  8366.               RENDITION : GRAPHIC_TYPE;
  8367.               VALUE     : in out STRING);
  8368.  
  8369.  
  8370. -- 
  8371. -- Text retrieval/display routines
  8372. -- 
  8373.     procedure GET_CHARACTER (CHARTYPE : out CHAR_ENUM;
  8374.                  CHAR     : out CHARACTER;
  8375.                  FUNC     : out FUNCTION_KEY_ENUM);
  8376.  
  8377.     procedure UNGET_CHARACTER (CHARTYPE : CHAR_ENUM;
  8378.                    CHAR     : CHARACTER;
  8379.                    FUNC     : FUNCTION_KEY_ENUM);
  8380.  
  8381.     procedure PUT_CHARACTER (CHAR : CHARACTER);
  8382.  
  8383.     procedure PUT_CHARACTER (CHAR : CHARACTER; POSITION : SCREEN_POSITION);
  8384.  
  8385.     procedure INSERT_CHARACTER (CHAR     : CHARACTER;
  8386.                 POSITION : SCREEN_POSITION);
  8387.  
  8388.     procedure ERASE_CHARACTER (POSITION : SCREEN_POSITION);
  8389.  
  8390. end TERMINAL_INTERFACE;
  8391.