home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PROGRAMS / UTILS / DOS_HELP / PC_HELP2.ZIP / HELP.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1986-01-21  |  25.1 KB  |  638 lines

  1. {******************************************************************************
  2. *                                                                             *
  3. *                     IBM PERSONAL COMPUTER ON-LINE HELP                      *
  4. *                         V5.1 by D.N.Ikle' 01/20/85                          *
  5. *                         For public domain use only                          *
  6. *                                                                             *
  7. *       This Turbo Pascal V3.0 program displays HELP screens for the          *
  8. *       commands and utilities on a hard disk system. The screens are         *
  9. *       stored as text files of the same name as the command with the         *
  10. *       extension .### in sub-directories accessed through the public         *
  11. *       utility DPATH.  This version contains numerous improvements over      *
  12. *       earlier versions that make program execution faster and simplify      *
  13. *       its structure.  In addition, the instruction screen is stored         *
  14. *       internally as an array, the heap is used to save and restore the      *
  15. *       initial display screen, all writing to the screen is done             *
  16. *       through the video memory, and the keyword entry field on the          *
  17. *       main menu can be edited and is limited to 8 characters.  The          *
  18. *       program has been tested on an IBM PC/XT, an IBM AT, and on            *
  19. *       several PC clones with both color and monochrome monitors.            *
  20. *                                                                             *
  21. *       Copyright 1985 by David N. Ikle'.  All rights reserved.               *
  22. *                                                                             *
  23. *                              David N. Ikle'                                 *
  24. *                              1671 Newport St.                               *
  25. *                              Denver, CO 80220                               *
  26. *                              303-333-9322                                   *
  27. *                                                                             *
  28. ******************************************************************************}
  29. {NOTE: Compiled with maximum free dynamic memory = $0800 paragraphs}
  30. program help;
  31. type
  32.   regpack               = record
  33.                           ax,bx,cx,dx,bp,si,di,ds,es,flags : integer;
  34.                           end;
  35.   string80              = string[80];
  36.   string68              = string[68];
  37.   string12              = string[12];
  38.   string8               = string[8];
  39.   text_array            = array[1..184] of string80;
  40.   menu_array            = array[1..11] of string80;
  41.   help_array            = array[1..23] of string80;
  42.   stack                 = array[1..25] of string[160];
  43. var
  44.   terminate             : boolean;
  45.   arg_number            : integer;
  46.   row,line_count        : integer;
  47.   start_last_page       : integer;
  48.   text_buffer           : text_array;
  49.   key_char,key_scan     : byte;
  50.   help_name             : string8;
  51.   display               : string12;
  52.   cursor_x,cursor_y     : integer;
  53.   mono_screen           : char absolute $B000:$0000;
  54.   colo_screen           : char absolute $B800:$0000;
  55.   screen_stack          : ^stack;
  56.   attr_hi,attr_lo       : byte;
  57. const
  58.   max_rows  : integer   = 23;    {max number of text lines in the display}
  59.   max_lines : integer   = 184;   {max number of lines in the text files}
  60.   message : string68 =
  61.     'Press Ent to return; Esc to exit; Up,Dn,PgUp,PgDn,Home,End to scroll';
  62.   menu : menu_array =
  63.     ('                                              ',
  64.      '      IBM PERSONAL COMPUTER ON-LINE HELP      ',
  65.      '          V5.1 by D.N.Ikle'' 01/20/85          ',
  66.      '          For public domain use only          ',
  67.      '                                              ',
  68.      '                                              ',
  69.      '                                              ',
  70.      '  Keywords are names of commands or features  ',
  71.      '       Enter ? or HELP for instructions       ',
  72.      '             Press Enter to quit              ',
  73.      '                                              ');
  74.   help : help_array =
  75. ('                     IBM PERSONAL COMPUTER ON-LINE HELP                     ',
  76.  '                                                                            ',
  77.  '                         Usage : HELP [keyword ...]                         ',
  78.  '                                                                            ',
  79.  'The optional keyword can be ?  (to display this screen), the name of a DOS  ',
  80.  'or other system command or utility, or the name of certain system features. ',
  81.  'The keyword HELP provides a detailed description of the HELP facility and a ',
  82.  'list of the keywords that describe the system features.  The keyword        ',
  83.  'COMMANDS displays a list of all the commands on the system.  Entry of HELP  ',
  84.  'with no keywords displays a keyword entry menu from which the Lt, Rt, Home, ',
  85.  'End, Ins, Del, Back, and Esc keys can be used to edit the eight character   ',
  86.  'keyword entry field.  Invalid keywords entered on the command line or on the',
  87.  'entry menu produce a speaker tone, and the keyword entry menu is displayed  ',
  88.  'with the invalid entry to be edited.  Following entry of a valid keyword, up',
  89.  'to 8 screens of text are displayed from the file that describes the command,',
  90.  'utility, or feature.  From any HELP screen, press Enter to return to the    ',
  91.  'entry menu or to display HELP for the next keyword on the command line, or  ',
  92.  'press Escape to return to the operating system.  The cursor control keys Up,',
  93.  'Dn, PgUp, PgDn, Home and End can be used to scroll the file a line or a page',
  94.  'at a time or to display the first or last page of the file.  Line 25 of the ',
  95.  'display summarizes these functions and identifies the end of the file.      ',
  96.  '                                                                            ',
  97. '                         Press any key to continue                          ');
  98. {*****************************************************************************}
  99. procedure set_display;            {identifies monitor and sets attributes}
  100.                                   (* requires types string12, regpack *)
  101.                                   (* requires variables attr_hi, attr_lo,
  102.                                      and dsiplay *)
  103. var
  104.   regs : regpack;
  105. begin
  106.   intr ($11,regs);
  107.   if regs.ax and 48 = 48
  108.     then
  109.       begin
  110.         display := 'monochrome';
  111.         attr_hi := 15;
  112.         attr_lo := 07;
  113.       end
  114.     else
  115.       begin
  116.         display := 'color';
  117.         attr_hi := 12;
  118.         attr_lo := 10;
  119.       end;
  120. end; {set_display}
  121. {*****************************************************************************}
  122. procedure cursor_off;             {sets cursor to blank}
  123.                                   {adapted from procedure by Mark Brown}
  124.                                   (* requires type regpack *)
  125. var
  126.   regs : regpack;
  127. begin
  128.   with regs do
  129.     begin
  130.       ax := $0100;
  131.       bx := 0;
  132.       cx := $100 * 32;
  133.       intr ($10,regs);
  134.     end;
  135. end; {cursor_off}
  136. {*****************************************************************************}
  137. procedure cursor_on;              {sets cursor to normal}
  138.                                   {adapted from procedure by Mark Brown}
  139.                                   (* requires type regpack *)
  140.                                   (* requires variable display *)
  141. var
  142.   regs : regpack;
  143. begin
  144.   with regs do
  145.     begin
  146.       ax := $0100;
  147.       bx := 0;
  148.       if display = 'monochrome' then
  149.         cx := 13 + $100 * 12
  150.       else
  151.         cx := 7 + $100 * 6;
  152.       intr ($10,regs);
  153.     end;
  154. end; {cursor_on}
  155. {*****************************************************************************}
  156. procedure inkey                   {interprets keyboard scan codes}
  157.   (var key_char,key_scan : byte); {ASCII and extended code of keyboard key}
  158. var
  159.   regs : regpack;
  160. begin
  161.   with regs do
  162.     begin
  163.       ax := $0000;
  164.       intr($16,regs);
  165.       key_char := lo(ax);
  166.       key_scan := hi(ax);
  167.     end;
  168. end; {inkey}
  169. {*****************************************************************************}
  170. procedure push_screen;            {save display contents when HELP called}
  171.                                   (* requires variables display,screen_stack^,
  172.                                      mono_screen, and colo_screen *)
  173. begin
  174.   if display = 'monochrome' then
  175.     move(mono_screen,screen_stack^,4000)
  176.   else
  177.     move(colo_screen,screen_stack^,4000);
  178. end; {push_screen}
  179. {*****************************************************************************}
  180. procedure pop_screen;             {restore display to when HELP called}
  181.                                   (* requires variables display,screen_stack^,
  182.                                      mono_screen, and colo_screen *)
  183. begin
  184.   if display = 'monochrome' then
  185.     move(screen_stack^,mono_screen,4000)
  186.   else
  187.     move(screen_stack^,colo_screen,4000);
  188. end; {pop_screen}
  189. {*****************************************************************************}
  190. procedure fastwrite               {writes lines of text to the screen buffer}
  191.   (col,row,attrib : byte;         {display position and attribute}
  192.    str            : string80);    {character string to be displayed}
  193.                                   {procedure provided by Marshall Brain}
  194.                                   (* requires type string80 *)
  195. begin
  196.   col := col - 1;
  197.   row := row - 1;
  198.   inline
  199.     ($1E/$1E/$8A/$86/row/$B3/$50/$F6/$E3/$2B/$DB/$8A/$9E/col/
  200.      $03/$C3/$03/$C0/$8B/$F8/$be/$00/$00/$8A/$BE/attrib/
  201.      $8a/$8e/str/$22/$c9/$74/$3e/$2b/$c0/$8E/$D8/$A0/$49/$04/
  202.      $1F/$2C/$07/$74/$22/$BA/$00/$B8/$8E/$DA/$BA/$DA/$03/$46/
  203.      $8a/$9A/str/$EC/$A8/$01/$75/$FB/$FA/$EC/$A8/$01/$74/$FB/
  204.      $89/$1D/$47/$47/$E2/$Ea/$2A/$C0/$74/$10/$BA/$00/$B0/
  205.      $8E/$DA/$46/$8a/$9A/str/$89/$1D/$47/$47/$E2/$F5/$1F);
  206. end; {fastwrite}
  207. {*****************************************************************************}
  208. procedure beep                    {sounds a tone on the system speaker}
  209.   (tone,time:integer);            {frequency and duration of tone}
  210. begin
  211.   sound(tone);
  212.   delay(time);
  213.   nosound;
  214. end; {beep}
  215. {*****************************************************************************}
  216. procedure drawbox                 {draws a box connecting specified points}
  217.   (x1,y1,x2,y2   : integer);      {coordinates of upper-left and lower-right}
  218.                                   (* requires procedure fastwrite *)
  219.                                   (* requires constant attr_hi *)
  220. var
  221.   i  : integer;
  222. const
  223.   ch_lr : char = #186;            {left and right sides}
  224.   ch_tr : char = #187;            {top right corner}
  225.   ch_br : char = #188;            {bottom right corner}
  226.   ch_bl : char = #200;            {bottom left corner}
  227.   ch_tl : char = #201;            {top left corner}
  228.   ch_tb : char = #205;            {top and bottom sides}
  229. begin
  230.   fastwrite(x1,y1,attr_hi,ch_tl);
  231.   for i := x1+1 to x2-1 do fastwrite(i,y1,attr_hi,ch_tb);
  232.   fastwrite(x2,y1,attr_hi,ch_tr);
  233.   for i := y1+1 to y2-1 do
  234.     begin
  235.       fastwrite(x1,i,attr_hi,ch_lr);
  236.       fastwrite(x2,i,attr_hi,ch_lr);
  237.     end;
  238.   fastwrite(x1,y2,attr_hi,ch_bl);
  239.   for i := x1+1 to x2-1 do fastwrite(i,y2,attr_hi,ch_tb);
  240.   fastwrite(x2,y2,attr_hi,ch_br);
  241. end; {drawbox}
  242. {*****************************************************************************}
  243. procedure get_string              {input character string with edit control}
  244.   (var answer       : string8);   {character string to be input}
  245.                                   {adapted from procedures by Brenston Worrell}
  246.                                   (* requires procedures inkey and beep *)
  247. var
  248.   ch                : char;
  249.   row,col,cloc      : integer;
  250.   cur_string        : string8;
  251.   key_char,key_scan : byte;
  252. const
  253.   anslen : integer = 8;
  254.   blank = '        ';
  255. procedure invalid_key;
  256.   begin
  257.     beep(150,75);
  258.   end; {invalid_key}
  259. procedure write_string;
  260.   begin
  261.     gotoxy(col,row);
  262.     write(cur_string + copy(blank,1,anslen-length(cur_string)));
  263.     gotoxy(cloc,row);
  264.   end; {write_string}
  265. procedure write_char;
  266.   begin
  267.     if (cloc - col + 1) <= anslen then
  268.       begin
  269.         write(ch);
  270.         cur_string := copy(cur_string,1,cloc-col) + ch +
  271.                       copy(cur_string,cloc-col+2,anslen);
  272.         cloc := cloc + 1;
  273.       end
  274.     else
  275.       invalid_key;
  276.   end; {write_char}
  277. procedure back_space;
  278.   begin
  279.     if cloc <= col then
  280.       invalid_key
  281.     else
  282.       begin
  283.         delete(cur_string,cloc-col,1);
  284.         cloc := cloc - 1;
  285.         write_string;
  286.       end;
  287.   end; {back_space}
  288. procedure rt_arrow;
  289.   begin
  290.     if cloc < (col + anslen -1) then
  291.       begin
  292.         cloc := cloc + 1;
  293.         gotoxy(cloc,row);
  294.       end
  295.     else
  296.       invalid_key;
  297.   end; {rt_arrow}
  298. procedure lt_arrow;
  299.   begin
  300.     if cloc > col then
  301.       begin
  302.         cloc := cloc - 1;
  303.         gotoxy(cloc,row);
  304.       end
  305.     else
  306.       invalid_key;
  307.   end; {lt_arrow}
  308. procedure insert_char;
  309.   begin
  310.     if (length(cur_string) < anslen) and
  311.        ((cloc - col +1) <= length(cur_string)) then
  312.       begin
  313.         insert(' ',cur_string,cloc-col+1);
  314.         write_string;
  315.       end
  316.     else
  317.       invalid_key;
  318.   end; {insert_char}
  319. procedure delete_char;
  320.   begin
  321.     if (cloc - col + 1) <= length(cur_string) then
  322.       begin
  323.         delete(cur_string,cloc-col+1,1);
  324.         write_string;
  325.       end
  326.     else
  327.       invalid_key;
  328.   end; {delete_char}
  329. begin
  330.   col := wherex;
  331.   row := wherey;
  332.   cloc := col;
  333.   cur_string := answer;
  334.   repeat
  335.     inkey(key_char,key_scan);
  336.     ch := chr(key_char);
  337.     case key_char of
  338.        0 : begin                  {extended key codes}
  339.              case key_scan of
  340.                71 : begin                                {home key}
  341.                       cloc := col;
  342.                       gotoxy(cloc,row);
  343.                     end;
  344.                75 : lt_arrow;                            {left arrow}
  345.                77 : rt_arrow;                            {right arrow}
  346.                79 : begin                                {end key}
  347.                       cloc := col + length(cur_string);
  348.                       gotoxy(cloc,row);
  349.                     end;
  350.                82 : insert_char;                         {insert}
  351.                83 : delete_char;                         {delete}
  352.              else
  353.                invalid_key;
  354.              end;
  355.            end;
  356.        8 : back_space;                                   {back space}
  357.       13 : answer := cur_string;                         {enter}
  358.       27 : begin                                         {escape}
  359.              cloc := col;
  360.              cur_string := '';
  361.              write_string;
  362.            end;
  363.       65..90  : write_char;                              {upper case letters}
  364.       97..122 : write_char;                              {lower case letters}
  365.       48..57  : write_char;                              {numeric digits}
  366.       33,35..41,45,63,64,95,96,123,125 : write_char;     {special characters}
  367.     else
  368.       invalid_key;
  369.     end;
  370.   until key_char = 13;
  371. end; {get_string}
  372. {*****************************************************************************}
  373. procedure get_file                {reads a text file into an array}
  374.   (file_name       : string12;    {name of text file}
  375.    var file_exist  : boolean);    {true, if file exists; false, otherwise}
  376.                                   (* requires procedure beep *)
  377.                                   (* requires types text_array, string12
  378.                                      and string80 *)
  379.                                   (* requires variables line_count,
  380.                                      start_last_page and text_buffer *)
  381.                                   (* requires constant max_lines *)
  382. type
  383.   text_file        = text[$800];
  384. var
  385.   infile           : text_file;
  386.   cur_line,blank   : string80;
  387. const
  388.   blank1 = '                                        ';
  389.   blank2 = '                                        ';
  390. begin
  391.   blank := blank1 + blank2;
  392.   file_exist := false;
  393.   assign (infile,file_name);
  394.   {$I-} reset (infile) {$I+};
  395.   if ioresult <> 0 then
  396.     beep(200,400)
  397.   else
  398.     begin
  399.       file_exist := true;
  400.       line_count := 0;
  401.       repeat
  402.         line_count := line_count + 1;
  403.         readln(infile,cur_line);
  404.         text_buffer[line_count] := cur_line +
  405.           copy(blank,1,80-length(cur_line));
  406.       until (line_count >= max_lines) or eof(infile);
  407.       close (infile);
  408.       if line_count <= max_rows then
  409.         start_last_page := 1
  410.       else
  411.         start_last_page := line_count - max_rows + 1;
  412.     end;
  413. end; {get_file}
  414. {******************************************************************************}
  415. procedure input_menu              {inputs HELP names from the main menu}
  416.   (var help_name    : string8;    {name of requested HELP}
  417.        edit_mode    : boolean);   {true, if editing invalid entry on the
  418.                                    command line; false, otherwise}
  419.                                   (* requires procedures fatswrite, drawbox,
  420.                                      get_string, get_file *)
  421.                                   (* requires types string8,text_array and
  422.                                      menu_array *)
  423.                                   (* requires variables text_buffer, and
  424.                                      line_count *)
  425.                                   (* requires constants attr_hi, attr_lo,
  426.                                      and menu *)
  427. var
  428.   row             : integer;
  429.   valid_name      : boolean;
  430.   file_name       : string12;
  431. begin
  432.   cursor_on;
  433.   valid_name := false;
  434.   drawbox(17,6,64,18);
  435.   for row := 1 to 11 do fastwrite(18,row+6,attr_lo,menu[row]);
  436.   gotoxy (28,12);
  437.   textcolor(attr_hi);
  438.   write ('Enter keyword ==> ');
  439.   if edit_mode then
  440.     write(help_name)
  441.   else
  442.     help_name := '';
  443.   repeat
  444.     gotoxy(46,12);
  445.     get_string(help_name);
  446.     file_name := help_name + '.###';
  447.     if (help_name = '') or (help_name = '?') then
  448.       valid_name := true
  449.     else
  450.       get_file(file_name,valid_name);
  451.   until valid_name;
  452.   textcolor(attr_lo);
  453.   cursor_off;
  454. end; {input_menu}
  455. {*****************************************************************************}
  456. procedure input_parm              {inputs HELP names from the command line}
  457.   (var arg_number   : integer;    {number of arguement on the command line}
  458.    var help_name    : string8);   {name of requested HELP}
  459.                                   (* requires procedures get_file, pop_screen,
  460.                                      and input_menu *)
  461.                                   (* requires types string8,string12 *)
  462. var
  463.   valid_name      : boolean;
  464.   file_name       : string12;
  465. begin
  466.   repeat
  467.     valid_name := false;
  468.     arg_number := arg_number + 1;
  469.     help_name := paramstr(arg_number);
  470.     if help_name <> '?' then
  471.       begin
  472.         file_name := help_name + '.###';
  473.         get_file(file_name,valid_name);
  474.         if not valid_name then
  475.           begin
  476.             pop_screen;
  477.             input_menu(help_name,true);
  478.           end;
  479.       end;
  480.   until (help_name <> '') or (arg_number >= paramcount);
  481. end; {input_parm}
  482. {*****************************************************************************}
  483. procedure get_key                 {interprets key codes from the HELP screen}
  484.   (var first_line   : integer;    {number of first line to be displayed}
  485.    var enter_key    : boolean;    {true, if enter pressed; false, otherwise}
  486.    var escape_key   : boolean);   {true, if escape pressed; false, otherwise}
  487.                                   (* requires procedures inkey and beep *)
  488.                                   (* requires variable start_last_page *)
  489.                                   (* requires constant max_rows *)
  490. var
  491.   key_char,key_scan : byte;
  492.   valid_key         : boolean;
  493. function min(x,y:integer):integer;
  494.  begin
  495.     min := x;
  496.     if y < x then min := y;
  497.   end; {min}
  498. function max(x,y:integer):integer;
  499.   begin
  500.     max := x;
  501.     if y > x then max := y;
  502.   end; {max}
  503. procedure invalid_key;
  504.   begin
  505.     beep(150,75);
  506.     valid_key := false;
  507.   end; {invalid_key}
  508. begin
  509.   repeat
  510.     inkey(key_char,key_scan);
  511.     valid_key := true;
  512.     case key_char of
  513.        0 : begin                    {extended key codes}
  514.              case key_scan of
  515.                72 : if first_line <= 1 then                     {up arrow}
  516.                       invalid_key
  517.                     else
  518.                       first_line := first_line - 1;
  519.                80 : if first_line >= start_last_page then       {down arrow}
  520.                       invalid_key
  521.                     else
  522.                       first_line := first_line + 1;
  523.                73 : if first_line <= 1 then                     {page up}
  524.                       invalid_key
  525.                     else
  526.                       first_line := max(1,first_line-max_rows);
  527.                81 : if first_line >= start_last_page then       {page down}
  528.                       invalid_key
  529.                     else
  530.                       first_line := min(start_last_page,first_line+max_rows);
  531.                71 : if first_line <= 1 then                     {home key}
  532.                       invalid_key
  533.                     else
  534.                       first_line := 1;
  535.                79 : if first_line >= start_last_page then       {end key}
  536.                       invalid_key
  537.                     else
  538.                       first_line := start_last_page;
  539.              else
  540.                invalid_key;
  541.              end;
  542.            end;
  543.       13 : enter_key := true;                    {enter}
  544.       27 : escape_key := true;                   {escape}
  545.     else
  546.       invalid_key
  547.     end;
  548.   until valid_key;
  549. end; {get_key}
  550. {*****************************************************************************}
  551. procedure display_help            {displays individual HELP screens}
  552.   (var escape_key   : boolean);   {true, if escape pressed; false, otherwise}
  553.                                   (* requires procedures fastwrite,get_key *)
  554.                                   (* requires types string80, string68 and
  555.                                      text_array *)
  556.                                   (* requires variables text_buffer,
  557.                                      and line_count *)
  558.                                   (* requires constants max_rows,message *)
  559. var
  560.   enter_key       : boolean;
  561.   first_line      : integer;
  562.   line, row       : integer;
  563.   line_25         : string80;
  564. begin
  565.   enter_key := false;
  566.   first_line := 1;
  567.   clrscr;
  568.   repeat
  569.     row := 0;
  570.     repeat
  571.       row := row + 1;
  572.       line := first_line + row - 1;
  573.       fastwrite(1,row,attr_lo,text_buffer[line]);
  574.     until (row >= max_rows) or (line >= line_count);
  575.     if line >= line_count then
  576.       line_25 := message + ' <EndOfFile>'
  577.     else
  578.       line_25 := message + ' <Continued>';
  579.     fastwrite(1,25,attr_hi,line_25);
  580.     get_key(first_line,enter_key,escape_key);
  581.   until enter_key or escape_key;
  582. end; {display_help}
  583. {*****************************************************************************}
  584. begin
  585.   if (memavail < 0) or (memavail >= 256) then
  586.     begin
  587.       arg_number := 0;                        {initialize variables}
  588.       terminate := false;
  589.       set_display;
  590.       cursor_x := wherex;
  591.       cursor_y := wherey;
  592.       new(screen_stack);
  593.       push_screen;
  594.       cursor_off;                             {remove cursor}
  595.       repeat
  596.         if (paramcount > 0) and (arg_number < paramcount) then
  597.           begin                               {input from command line}
  598.             input_parm(arg_number,help_name);
  599.             if (help_name = '') and (arg_number >= paramcount) then
  600.               terminate := true;
  601.           end
  602.         else
  603.           begin                               {input from main menu}
  604.             pop_screen;
  605.             input_menu(help_name,false);
  606.             if help_name = '' then terminate := true;
  607.           end;
  608.         if terminate then
  609.           begin                               {exit to original screen}
  610.             pop_screen;
  611.             gotoxy(cursor_x,cursor_y-1);
  612.           end
  613.         else                                  {display requested HELP}
  614.           begin
  615.             if help_name = '?' then           {display ? screen}
  616.               begin
  617.                 clrscr;
  618.                 drawbox(1,1,80,25);
  619.                 for row := 1 to 23 do fastwrite(3,row+1,attr_lo,help[row]);
  620.                 inkey(key_char,key_scan);
  621.               end
  622.             else                              {display HELP screens}
  623.               display_help(terminate);
  624.             if terminate then
  625.               begin                           {exit on line 25}
  626.                 gotoxy (1,25);
  627.                 delline;
  628.                 gotoxy (1,24);
  629.               end;
  630.           end;
  631.       until terminate;
  632.     end
  633.   else                                        {terminate if insufficient heap}
  634.       writeln ('Insufficient Heap Space (',memavail*16,
  635.                 ' bytes) - HELP Terminated');
  636.   cursor_on;                                  {restore cursor}
  637. end. {help}
  638.