home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / TURBOPAS / MENU456.ZIP / MENU456.PAS
Encoding:
Pascal/Delphi Source File  |  1987-11-08  |  15.6 KB  |  616 lines

  1. { This program demonstrates how choices from a menu can be made by pointing
  2.   (like Lotus' 1-2-3) instead of entering a number.
  3.   Most of the routines have been published previously in TUG Lines, I've
  4.   modified some of them to suit my preferences.
  5. }
  6.  
  7. program menu456;
  8.  
  9. const
  10.   greeting    = 'Menu 4-5-6 , Version 860205';
  11.   left_arrow  = #$88; {the values for the ADVANTAGE}
  12.   right_arrow = #$86;
  13.   up_arrow    = #$82;
  14.   down_arrow  = #$8a;
  15.   norm_video  = #$02;
  16.   rev_video   = #$01;
  17.   clr_eos     = #$0f; {clear to end of screen}
  18.   max_choices = 6;    { one less than the actual number of choices}
  19.   cr          = #$0d;
  20.   esc         = #$1b;
  21.   not_found   = $ff;
  22.   get_drive   = 25;   { CP/M BDOS calls }
  23.   set_drive   = 14;
  24.  
  25. type
  26.   string80 = string[80];
  27.   filename_type = string[14];
  28.   choice_type = record         {more information could be included here}
  29.     row           : integer;   { and that information returned by GET_CHOICE,}
  30.     column        : integer;   { instead of just the position of the choice in}
  31.     description   : string[10];{ the array}
  32.     help          : string80;
  33.   end;
  34.  
  35. var
  36.   choice : array[0..max_choices] of choice_type;
  37.   result : integer;
  38.   current_drive : char;
  39.  
  40.  
  41. procedure beep;
  42. begin
  43.   write(#$07);
  44. end;
  45.  
  46. procedure clreos;
  47. begin
  48.   write(clr_eos);
  49. end;
  50.  
  51. procedure clear_dialog;
  52. begin
  53.   gotoxy(01, 04); clreol;
  54.   writeln; clreol;
  55.   writeln; clreol;
  56.   writeln; clreol;
  57.   gotoxy(01, 04);
  58. end;
  59.  
  60. procedure clear_menu;
  61. begin
  62.   gotoxy(01, 02); clreol;
  63.   writeln; clreol;
  64. end;
  65.  
  66. procedure pause;
  67. var
  68.   c : char;
  69.  
  70. begin
  71.   gotoxy(01, 24);
  72.   write(rev_video, 'Press any key to continue', norm_video);
  73.   clreol;
  74.   read(kbd, c);
  75. end;
  76.  
  77. procedure display_greeting;
  78.  
  79. begin
  80.   clrscr;
  81.   gotoxy(20, 10);
  82.   write(greeting);
  83.   gotoxy(22, 11);
  84.   write('Public Domain Software');
  85.   gotoxy(18, 12);
  86.   write('by Abrahamsen Consulting, 1986');
  87.   pause;
  88.   clrscr;
  89. end;
  90.  
  91. function get_filename : filename_type;
  92. var
  93.   filename : filename_type;
  94.  
  95. begin
  96.   write('(D:Filename.Ext) => ');
  97.   readln(filename);
  98.   get_filename := filename;
  99. end;
  100.  
  101. procedure turn_on(choice : choice_type);  {highlights a menu choice}
  102. begin
  103.   with choice do
  104.     begin
  105.       gotoxy(column, row);
  106.       write(rev_video, description, norm_video);
  107.     end;
  108. end;
  109.  
  110. procedure turn_off(choice : choice_type); {cancels the highlighting}
  111. begin
  112.   with choice do
  113.     begin
  114.       gotoxy(column, row);
  115.       write(norm_video, description);
  116.     end;
  117. end;
  118.  
  119. procedure initialize_choices; { puts the descriptions of the menu choices}
  120.                               { and their location on the screen in the  }
  121. var                           { CHOICE array }
  122.   i : integer;
  123.  
  124. begin
  125.   with choice[0] do
  126.     begin
  127.       description := 'copy';
  128.       help := 'copy a text file and give it a new name';
  129.       row := 1;
  130.       column := 1;
  131.     end;
  132.   with choice[1] do
  133.     begin
  134.       description := 'rename';
  135.       help := 'rename any file on disk';
  136.       row := 1;
  137.       column := choice[0].column + length(choice[0].description) + 2;
  138.     end;
  139.   with choice[2] do
  140.     begin
  141.       description := 'erase';
  142.       help := 'erase any file from disk';
  143.       row := 1;
  144.       column := choice[1].column + length(choice[1].description) + 2;
  145.     end;
  146.   with choice[3] do
  147.     begin
  148.       description := 'view';
  149.       help := 'view a text file on the screen';
  150.       row := 1;
  151.       column := choice[2].column + length(choice[2].description) + 2;
  152.     end;
  153.   with choice[4] do
  154.     begin
  155.       description := 'directory';
  156.       help := 'display the directory of the selected disk drive';
  157.       row := 1;
  158.       column := choice[3].column + length(choice[3].description) + 2;
  159.     end;
  160.   with choice[5] do
  161.     begin
  162.       description := 'select';
  163.       help := 'select a new disk drive';
  164.       row := 1;
  165.       column := choice[4].column + length(choice[4].description) + 2;
  166.     end;
  167.   with choice[6] do
  168.     begin
  169.       description := 'quit';
  170.       help := 'quit this program and return to your operating system';
  171.       row := 1;
  172.       column := choice[5].column + length(choice[5].description) + 2;
  173.     end;
  174.  
  175. end;
  176.  
  177. procedure display_help(choice : choice_type);
  178.  
  179. begin
  180.   gotoxy(01, 02);
  181.   clreol;
  182.   write(choice.help);
  183. end;
  184.  
  185. procedure display_choices;
  186.  
  187. var
  188.   i : integer;
  189.   bar : string[80];
  190.  
  191. begin
  192.   clear_menu;
  193.   clear_dialog;
  194.   bar[0] := char(80);
  195.   fillchar(bar[1], 80, '=');
  196.   gotoxy(01, 03);
  197.   write(bar);
  198.   gotoxy(01, 08);
  199.   write(bar);
  200.   for i := 0 to max_choices do
  201.     with choice[i] do
  202.       begin
  203.         gotoxy(column, row);
  204.         write(description);
  205.       end;
  206.    display_help(choice[0]);
  207.    turn_on(choice[0]);
  208.  
  209. end; {display_choices}
  210.  
  211.  
  212. function get_choice : integer;
  213.  
  214. var
  215.   c : char;
  216.   i, current, last : integer;
  217.   valid_choices : set of char;
  218.  
  219. label
  220.   skip_pointing;
  221.  
  222. begin
  223.   last := 0;
  224.   current := 0;
  225.   valid_choices := [];
  226.   for i := 0 to max_choices do  { build set of valid choices }
  227.     valid_choices := valid_choices + [upcase(choice[i].description[1])];
  228.   repeat                        {loop until they hit the RETURN key}
  229.     read(kbd, c);
  230.     c := upcase(c);
  231.     if c in valid_choices then  { find index into array }
  232.       begin
  233.         turn_off(choice[0]);
  234.         current := 0;
  235.         while (c <> upcase(choice[current].description[1])) do
  236.           current := current + 1;
  237.         turn_on(choice[current]);
  238.         goto skip_pointing;
  239.       end;
  240.  
  241.     case c of
  242.       right_arrow, ^D : begin
  243.                           last := current;
  244.                           current := last + 1;
  245.                         end;
  246.  
  247.       left_arrow,  ^S : begin
  248.                           last := current;
  249.                           if last <> 0 then
  250.                             current := last - 1
  251.                           else
  252.                             current := max_choices;
  253.                         end;
  254.  
  255.        else             if c <> cr then beep;
  256.     end; {case}
  257.  
  258.     if c in [left_arrow, right_arrow, ^D, ^S] then
  259.       begin
  260.         current := current mod (max_choices + 1);
  261.         turn_off(choice[last]);
  262.         display_help(choice[current]);
  263.         turn_on(choice[current]);
  264.       end;
  265.   until c = cr; {end repeat}
  266. skip_pointing:
  267.   get_choice := current;
  268. end; {get_choice}
  269.  
  270. procedure copy_file;
  271. var
  272.   file_in, file_out : text;
  273.   filename_in, filename_out : filename_type;
  274.   ok : boolean;
  275.   line : string[80];
  276.  
  277. begin
  278.   clear_dialog;
  279.   gotoxy(01, 04);
  280.   write('Enter filename to copy FROM ');
  281.   filename_in := get_filename;
  282.   if length(filename_in) > 0 then
  283.     begin { filename_in supplied }
  284.       {$I-}
  285.       assign(file_in, filename_in);
  286.       reset(file_in);
  287.       {$I+}
  288.       if ioresult = 0 then
  289.         begin { no error opening file_in }
  290.           write('Enter filename to copy TO ');
  291.           filename_out := get_filename;
  292.           if length(filename_out) > 0 then
  293.             begin { filename_out supplied }
  294.               {$I-}
  295.               assign(file_out, filename_out);
  296.               rewrite(file_out);
  297.               {$I+}
  298.               if ioresult = 0 then
  299.                 begin { no error opening file_out }
  300.                   while not eof(file_in) do
  301.                     begin
  302.                       readln(file_in, line);
  303.                       writeln(file_out, line);
  304.                     end;
  305.                   close(file_in);
  306.                   close(file_out);
  307.                 end   { file copied }
  308.               else
  309.                 begin { error opening file_out }
  310.                   beep;
  311.                   write('File not copied');
  312.                   pause;
  313.                 end; { open error }
  314.             end; { filename_out supplied }
  315.         end; { no error opening file_in }
  316.     end;  { filename_in supplied }
  317.   clear_dialog;
  318. end; { copy file }
  319.  
  320. procedure rename_file;
  321.  
  322. var
  323.   oldfile : text;
  324.   filename : filename_type;
  325.   ok : boolean;
  326.  
  327. begin
  328.   clear_dialog;
  329.   gotoxy(01, 04);
  330.   write('Enter old filename ');
  331.   filename := get_filename;
  332.   if length(filename) > 0 then
  333.     begin
  334.       assign(oldfile, filename);
  335.       write('Enter new filename ');
  336.       filename := get_filename;
  337.       if length(filename) > 0 then
  338.         begin
  339.           {$I-}
  340.           rename(oldfile, filename);
  341.           {$I+}
  342.           ok := (ioresult = 0);
  343.           if not ok then
  344.             begin
  345.               beep;
  346.               write('File not renamed');
  347.               pause;
  348.             end;
  349.         end;
  350.     end;
  351.   clear_dialog;
  352. end;
  353.  
  354. procedure erase_file;
  355. var
  356.   oldfile : text;
  357.   filename : filename_type;
  358.   ok : boolean;
  359.  
  360. begin
  361.   clear_dialog;
  362.   gotoxy(01, 04);
  363.   write('Enter filename ');
  364.   filename := get_filename;
  365.   if length(filename) > 0 then
  366.     begin
  367.       assign(oldfile, filename);
  368.       {$I-}
  369.       close(oldfile);
  370.       erase(oldfile);
  371.       {$I+}
  372.       ok := (ioresult = 0);
  373.       if not ok then
  374.         begin
  375.           beep;
  376.           write('File not found');
  377.           pause;
  378.         end;
  379.     end;
  380. end;
  381.  
  382. procedure view_file; { this works only for text files }
  383. var
  384.   oldfile : text;
  385.   filename : filename_type;
  386.   ok : boolean;
  387.   line : string80;
  388.   lines : integer;
  389.   c : char;
  390.  
  391. begin
  392.   clear_dialog;
  393.   gotoxy(01, 04);
  394.   write('Enter filename ');
  395.   filename := get_filename;
  396.   if length(filename) > 0 then { check to see if the file is present }
  397.     begin
  398.       assign(oldfile, filename);
  399.       {$I-}
  400.       reset(oldfile);
  401.       {$I+}
  402.       ok := (ioresult = 0);
  403.       if not ok then
  404.         begin
  405.           beep;
  406.           write('File not found');
  407.           pause;
  408.        end
  409.     else
  410.       while (c <> esc) and (not eof(oldfile)) do
  411.         begin
  412.           gotoxy(01, 04);
  413.           clreos;
  414.           lines := 1;
  415.           while (lines < 21) and (not eof(oldfile)) do
  416.             begin
  417.               readln(oldfile, line);
  418.               writeln(line);
  419.               lines := lines + 1;
  420.             end;
  421.           write(rev_video, 'Press any key to continue, ESC to stop.', norm_video);
  422.           read(kbd, c);
  423.         end;
  424.     gotoxy(01,04);
  425.     clreos;
  426.   end;
  427. end;
  428.  
  429. procedure directory;
  430.  
  431. const
  432.   files_per_page = 65;
  433.   max_files      = 130; { always a multiple of files_per_page }
  434.   scan_first     = 17;
  435.   scan_next      = 18;
  436.   set_dma        = 26;
  437.   fcb_1          = $5c;
  438.   fcb_2          = $80;
  439.  
  440. type
  441.   dir_entry  = string[12];
  442.   a_dir      = array[1..max_files] of dir_entry;
  443.  
  444. var
  445.   number_of_files, number_of_pages, page_number, j, k : integer;
  446.   dma_buf : array[1..130] of byte;
  447.   dir_buf : a_dir;
  448.   c : char;
  449.  
  450. {$A-}
  451. procedure sort(left, right : integer); { sort filenames before display }
  452. var
  453.   new_left, new_right : integer;
  454.   center_value, temp : dir_entry;
  455.  
  456. begin
  457.   if ((right - left) > 1) then
  458.     begin
  459.       center_value := dir_buf[(left + right) div 2];
  460.       new_left := left;
  461.       new_right := right;
  462.       while (new_left <= new_right) do
  463.         begin
  464.           while (dir_buf[new_left] < center_value) do
  465.             new_left := succ(new_left);
  466.           while (dir_buf[new_right] > center_value) do
  467.             new_right := pred(new_right);
  468.           if (new_left <= new_right) then
  469.             begin
  470.               temp := dir_buf[new_left];
  471.               dir_buf[new_left] := dir_buf[new_right];
  472.               dir_buf[new_right] := temp;
  473.               new_left := succ(new_left);
  474.               new_right := pred(new_right);
  475.             end; { if }
  476.        end; { while (new_left <= new_right) }
  477.        sort(left, new_right);
  478.        sort(new_left, right);
  479.     end
  480.   else
  481.     if ((right - left) = 1) then
  482.       if dir_buf[right] < dir_buf[left] then
  483.         begin
  484.           temp := dir_buf[right];
  485.           dir_buf[right] := dir_buf[left];
  486.           dir_buf[left] := temp;
  487.         end;
  488. end; { sort }
  489. {$A+}
  490.  
  491. procedure display_dir_page(page_number, number_of_pages : integer);
  492. var
  493.   i, k, rows : integer;
  494.  
  495. begin
  496.   gotoxy(01, 09);
  497.   clreos;
  498.   writeln('Selected drive => ', rev_video, current_drive, norm_video);
  499.   gotoxy(50, 09);
  500.   writeln('Files: ', number_of_files:3, '  Page: ', page_number:1, ' of ', number_of_pages:1);
  501.   if page_number < number_of_pages then
  502.     rows := 13
  503.   else { this is the last page }
  504.     begin
  505.       i := number_of_files mod files_per_page; { how many files on last page }
  506.       rows := i div 5; { in how many rows to display them? }
  507.       if (i mod 5) > 0 then
  508.         rows := rows + 1;
  509.     end;
  510.   k := (page_number - 1) * files_per_page; { offset into dir_buf for this page }
  511.   for i := 1 to rows do
  512.     writeln(dir_buf[k + i],        '   ',
  513.             dir_buf[k + i + rows], '   ',
  514.             dir_buf[k + i + (2 * rows)], '   ',
  515.             dir_buf[k + i + (3 * rows)], '   ',
  516.             dir_buf[k + i + (4 * rows)]);
  517.   gotoxy(01, 24);
  518.   write(rev_video, 'next page - downarrow   prev. page - uparrow  quit - <cr>', norm_video);
  519. end;
  520.  
  521. begin
  522.   mem[fcb_1] := 0;
  523.   for j :=  1 to 11 do mem[fcb_1 + j] := ord('?');
  524.   for j := 12 to 36 do mem[fcb_1 + j] := 0;
  525.   for j :=  1 to max_files do dir_buf[j] := ' ';
  526.   number_of_files := 1;
  527.   bdos(set_dma, addr(dma_buf[1]));
  528.   j := bdos(scan_first, fcb_1);    { get first filename }
  529.   if j <> not_found then           { if no error, move filename }
  530.     begin
  531.       dma_buf[j * 32 + 1] := 11;
  532.       move(dma_buf[j * 32 + 1], dir_buf[number_of_files], 12);
  533.       j := bdos(scan_next, fcb_1); { find next filename }
  534.       while (j <> not_found) and (number_of_files <= max_files) do
  535.         begin
  536.           number_of_files := number_of_files + 1;
  537.           k := j * 32 + 1;
  538.           dma_buf[k] := 11;
  539.           move(dma_buf[k], dir_buf[number_of_files], 12);
  540.           j := bdos(scan_next, fcb_1);
  541.         end;
  542.       bdos(set_dma, fcb_2);
  543.       for j := 1 to number_of_files do insert('.', dir_buf[j], 9);
  544.       sort(1, number_of_files);
  545.       number_of_pages := number_of_files div files_per_page;
  546.       if (number_of_files mod files_per_page) > 0 then
  547.         number_of_pages := number_of_pages + 1;
  548.       page_number := 1;
  549.       repeat
  550.         display_dir_page(page_number, number_of_pages);
  551.         read(kbd, c);
  552.         if (c = down_arrow) and (page_number < number_of_pages) then
  553.           page_number := succ(page_number)
  554.         else
  555.           if (c = up_arrow) and (page_number > 1) then
  556.             page_number := pred(page_number)
  557.           else
  558.             if not (c in [cr, esc]) then beep;
  559.       until (c in [cr, esc]);
  560.     end { if first scan is okay }
  561.   else
  562.     begin
  563.       writeln;
  564.       write('No files found.');
  565.     end;
  566. end; { directory }
  567.  
  568. procedure select_drive;
  569.  
  570. var
  571.   drive : char;
  572.   valid_drives : set of char;
  573.   drive_number : integer;
  574.  
  575. begin
  576.   drive := ' ';
  577.   valid_drives := ['A', 'B'];
  578.   while not (drive in valid_drives) do
  579.     begin
  580.       clear_dialog;
  581.       write('Enter drive to select => ');
  582.       read(drive);
  583.       drive := upcase(drive);
  584.       if not (drive in valid_drives) then
  585.          begin
  586.            beep;
  587.            gotoxy(01, 24);
  588.            clreol;
  589.            write(rev_video, 'Invalid drive letter', norm_video);
  590.          end; { invalid drive entered }
  591.     end; { while }
  592.   drive_number := ord(drive) - ord('A');
  593.   current_drive := drive;
  594.   bdos(set_drive, drive_number);
  595.   directory;
  596. end;  { select drive }
  597.  
  598. begin { main }
  599.   initialize_choices;
  600.   display_greeting;
  601.   current_drive := chr(bdos(get_drive) + 65);
  602.   repeat
  603.     display_choices;
  604.     result := get_choice;
  605.     case result of
  606.       0 : copy_file;
  607.       1 : rename_file;
  608.       2 : erase_file;
  609.       3 : view_file;
  610.       4 : directory;
  611.       5 : select_drive;
  612.       6 : clrscr;
  613.     end; { case }
  614.   until (result = max_choices);
  615. end. { main }
  616.