home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / DPLUS.ZIP / DIRPLUS.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1989-03-17  |  22.4 KB  |  592 lines

  1. program DirPlus;
  2. { DirPlus version 2.0                             }
  3. { Copyright, Rex Kerr, 1989                       }
  4. { The comments assume the reader is familiar with }
  5. { fmisc,fwrite,xwin,and file1, three of my own    }
  6. { units.                                          }
  7. { If you do not have them, you cannot recompile   }
  8. { DirPlus, so do not try.                         }
  9. { This program may cause snow on "snowy" CGA cards}
  10. { and it will work on EGA and VGA cards unless    }
  11. { they have their "large" screen on (more than    }
  12. { 80 by 25).                                      }
  13.  
  14. uses crt,dos,fmisc,fwrite,xwin,file1; { Units used }
  15. {$R-}{$V-}                      { Range checking and var-string checking
  16.                                   off }
  17. {$M 8000,0,37000}               { Small memory size so DOS has plenty to
  18.                                   run other programs }
  19. type string40 = string[40];     { Size of string shown on screen }
  20.      string12 = string[12];     { Size of string for holding filename }
  21. var st : string;                { String containing current directory shown }
  22.     std : dirstr;               { "Free" strings (used with FExpand) }
  23.     stn : namestr;
  24.     ste : extstr;
  25. type dirsave = record                  { Record for holding file name and }
  26.                      name : string12;  { the output seen on the screen. }
  27.                      seen : string40;
  28.                end;
  29.      dirarry = array[1..200] of dirsave;  { Array to hold filenames.  112 is
  30.                                             max for dos, but in case it
  31.                                             somehow has more ... }
  32. var ddir : dirarry;       { Directory name array }
  33.     a : integer;          { Current directory length }
  34.     choice : integer;     { Not used integer.  You may delete }
  35.     cha,chb : char;       { Free characters (for ReadKey) }
  36.     lnum,cnum,anum : integer;  { Positions in the array;
  37.                                  anum holds actual position,
  38.                                  lnum holds line number,
  39.                                  and cnum holds column number. }
  40.     sclin : byte;           { Current line on the screen }
  41.     exitnow,mono : boolean; { Mono is for determining monochrome or CGA,
  42.                               exitnow is for signaling when to exit. }
  43.  
  44. procedure cw3;   { Procedure for calling up window for some commands }
  45. begin
  46.      if existwindow(3) then removewindow(3);  { If it's there, get rid of it }
  47.      gotowindow(1);                           { Make sure you're in window 1 }
  48.      createwindow(3,1,4,80,21,7,7,'','++++++');  { Create the window }
  49. end;  { End of cw3 }
  50.  
  51. procedure vscroll(lines : shortint);  { Procedure for scrolling screen }
  52. begin
  53.      vramscroll(lines,1,1,80,19,7);   { Scroll the screen }
  54. end;
  55.  
  56. procedure bioscurshape(x,y : byte);  { Sets the cursor shape }
  57. var regs : registers;                { using BIOS }
  58. begin
  59.      regs.ch := x;        { Top line goes in ch }
  60.      regs.cl := y;        { Bottom line goes in cl }
  61.      regs.ah := $1;       { Function $1 }
  62.      intr($10,regs);      { Call interrupt }
  63. end;
  64.  
  65. procedure setcuron;     { Set the cursor on }
  66. begin
  67.      if mono then bioscurshape(12,13)   { Monochrome cursors have different }
  68.      else bioscurshape(6,7);            { lines than CGAs do }
  69. end;
  70.  
  71. procedure setcuroff;  { Turn the cursor off }
  72. begin
  73.      bioscurshape(32,0);
  74. end;
  75.  
  76. procedure biosgetcur(var x,y : byte);   { Get the cursor shape }
  77. var regs : registers;
  78. begin
  79.      regs.bh := 0;     { Video page 0 (0 is the normal one) }
  80.      regs.ah := $3;    { Function $3 }
  81.      intr($10,regs);   { Call interrupt }
  82.      x := regs.ch;     { Top line is in X }
  83.      y := regs.cl;     { Bottom line is in Y }
  84. end;
  85.  
  86. function num_st(num : longint) : string;  { Function turning longints to strings }
  87. var st : string;  { function is better than procedure sometimes }
  88. begin
  89.      str(num,st);    { Call a procedure to do the work }
  90.      num_st := st;   { Return the string }
  91. end;
  92.  
  93. procedure getdir(st : string);   { Procedure to load the files in the
  94.                                    specified directory into the variable
  95.                                    ddir }
  96. var dirinfo : searchrec;         { For FindFirst and FindNext }
  97.     ast,bst,cst : string40;      { Same type as ddir's .seen }
  98.     b : integer;                 { Free integer }
  99. begin
  100.      a := 0;                     { How many files found ? }
  101.      findfirst(st,$30,dirinfo);  { Find the first file }
  102.      while (doserror = 0) do     { While files are still there }
  103.      begin
  104.           inc(a);                { Another file found }
  105.           qfillchar(ddir[a].seen[1],40,$20);  { Fill the array with spaces. }
  106.           ddir[a].seen := dirinfo.name;   { What is shown on the screen
  107.                                             includes the name of the file }
  108.           if dirinfo.attr <> $20 then  { If the file is a directory, mark }
  109.           begin                        { it with << and >> symbols }
  110.                ddir[a].seen := #174+ddir[a].seen+#175;
  111.           end
  112.           else
  113.           begin
  114.                ddir[a].seen[0] := #15;   { If it is a file, add the size }
  115.                ddir[a].seen := ddir[a].seen + num_st(dirinfo.size);
  116.           end;
  117.           ddir[a].name := dirinfo.name;  { And then save the name for later use }
  118.           findnext(dirinfo);   { Find the next file }
  119.      end;
  120. end;
  121.  
  122. procedure sortdir(Lo,Hi: integer);  { Procedure to alphabetically sort the
  123.                                       filenames. }
  124. { I have forgotten how this works, so I won't bother putting
  125.   comments in... }
  126.  
  127. procedure sort(l,r: longint);
  128. var
  129.   i,j : word;
  130.   x : string12;
  131.   y : dirsave;
  132. begin
  133.   i:=l; j:=r; x:=(ddir[((l+r) DIV 2)].name);
  134.   repeat
  135.     while ddir[i].name<x do i:=i+1;
  136.     while x<ddir[j].name do j:=j-1;
  137.     if i<=j then
  138.     begin
  139.       y:=ddir[i]; ddir[i]:=ddir[j]; ddir[j]:=y;
  140.       i:=i+1; j:=j-1;
  141.     end;
  142.   until i>j;
  143.   if l<j then sort(l,j);
  144.   if i<r then sort(i,r);
  145. end; { Sort }
  146. begin { SortDir }
  147.   sort(Lo,Hi);
  148. end;  { SortDir }
  149.  
  150. procedure fixup(var st : string);  { Fixes up the directory path given }
  151. var pst : pathstr;
  152.     a : byte;
  153. begin
  154.      pst := st;
  155.      st := fexpand(pst);
  156.      a := length(st);
  157.      if (st[a] = '\') then st := st + '*.*';   { Account for wildcards }
  158. end;
  159.  
  160. procedure writeone(sno : byte; i : integer; attr : byte);
  161. begin  { Writes out one filename }
  162.      if (frac(i/3) > 0.5) then   { Is it the second column? }
  163.      begin
  164.           vramwrit(28,sno,attr,ddir[i].seen);   { Sno is the line }
  165.      end
  166.      else if (frac(i/3) > 0.2) then  { Is it the first one? }
  167.      begin
  168.           vramwrit(1,sno,attr,ddir[i].seen);    { Attr is the attribute }
  169.      end
  170.      else      {If it's not either of those, it must be the third. }
  171.      begin
  172.           vramwrit(53,sno,attr,ddir[i].seen); { ddir[i].seen is the string }
  173.      end;
  174. end;
  175.  
  176. procedure getnewdir(up : boolean);  { Gets a new directory and writes it
  177.                                       out.  If up is true, then it asks
  178.                                       user for input. }
  179. var pst : pathstr;
  180. procedure writesome;   { Write out as much as you can see at one time }
  181. var b,d : byte;
  182. begin
  183.      for d := 1 to 19 do clrvramline(d,7);  { Clear the screen }
  184.      d := 1; b := 1;                        { Initialize d and b }
  185.      while (b <= a) and (d < 20) do    { Stop if you get to last entry or }
  186.      begin                             { line 19. }
  187.           writeone(d,b,7);             { Write out one filename }
  188.           if (b = 1) then writeone(d,b,112);  { The current place is 1, so
  189.                                                 write that one out it
  190.                                                 reverse video. }
  191.           inc(b);                    { B holds array # }
  192.           if (b > d*3) then inc(d);  { D holds line # }
  193.      end;
  194. end;
  195. begin { GetNewDir }
  196.      if up then   { If ask user for input }
  197.      begin
  198.           cw3;         { Create a window to write in }
  199.           setcuron;    { Set the cursor on }
  200.           write('Please enter directory or path:');  { Get the input }
  201.           readln(st);
  202.           setcuroff;   { Turn of the cursor }
  203.           fixup(st);   { Fix up the directory path }
  204.      end;
  205.      getdir(st);       { Get the directory's files }
  206.      sortdir(1,a);     { Sort the directory }
  207.      lnum := 1;        { Set everything to the first line }
  208.      cnum := 1;
  209.      anum := 1;
  210.      sclin := 1;
  211.      if up then popwindow;  { If get rid of the window if it was called }
  212.      clrscr;                { Clear the screen for the files }
  213.      writesome;             { Write out the files }
  214.      if a = 0 then getnewdir(true); { If no files are found, do it again }
  215. end;
  216.  
  217. { For the next few procedures, I is the array number that holds the
  218.   filename.  It is easier to pass that way that to pass a whole string. }
  219.  
  220. procedure getdiskdir(i : integer);   { To go into a subdirectory }
  221. var sta : pathstr;
  222. begin
  223.      fsplit(st,std,stn,ste);
  224.      if ddir[i].name = '.' then exit;   { Don't do anything if you go to
  225.                                           the same directory }
  226.      if ddir[i].name = '..' then        { If you go back one, find last directory }
  227.      begin
  228.           repeat   { Go backwards until you hit a \ }
  229.                 std[0] := chr(ord(std[0])-1);
  230.           until std[ord(std[0])] = '\';
  231.           sta := std + '*.*';   { And add the wildcard }
  232.      end
  233.      else sta := std + ddir[i].name + '\*.*';  { Going in, just and the
  234.                                                  directory name & wildcard }
  235.      st := sta;                   { Set the directory path string }
  236.      getnewdir(false);         { and get the new directory }
  237. end;
  238.  
  239. procedure dorenamefile(i : integer);  { Rename a file. }
  240. var sta,stb : pathstr;
  241.     ret : byte;
  242. begin
  243.      cw3;    { User input needed, create a window for that }
  244.      fsplit(st,std,stn,ste);    { Split the directory path and }
  245.      sta := std + ddir[i].name; { add the file name, so now you have }
  246.                                 { the file name with the path. }
  247.      setcuron;                  { Set the cursor on }
  248.      write('Rename ',sta,' to: ');  { Get the input }
  249.      readln(stb);
  250.      setcuroff;                 { Turn the cursor off }
  251.      stb := std + stb;          { Add the path to the filename }
  252.      stb := fexpand(stb);       { and expand it }
  253.      renamefile(sta,stb,ret);   { Rename the file }
  254.      if (ret <> 0) then writeln('Error #',ret,' in renaming');
  255.      { If there is an error, write it out. }
  256.      popwindow;   { User's input is done, so get rid of that window; }
  257.      if (ret = 0) then getnewdir(false);  { If the renaming went right,
  258.                                             the file names have changed, so...}
  259. end;
  260.  
  261. procedure docopyfile(i : integer);  { You can figure this one out }
  262. var sta,stb : pathstr;
  263.     ret : byte;
  264. begin
  265.      cw3;
  266.      fsplit(st,std,stn,ste);
  267.      sta := std + ddir[i].name;
  268.      setcuron;
  269.      write('Copy file ',sta,' to: ');
  270.      readln(stb);
  271.      setcuroff;
  272.      stb := fexpand(stb);
  273.      copyfile(sta,stb,ret);
  274.      if (ret <> 0) then writeln('Error #',ret,' in copying');
  275.      popwindow;
  276.      if ret = 0 then getnewdir(false);
  277. end;
  278.  
  279. procedure dodeletefile(i : integer);  { And this one. }
  280. var sta : pathstr;       { Just one note:  make sure the user has at least }
  281.     ret : byte;          { one chance to change his mind about deleting }
  282.     ch : char;
  283. begin
  284.      cw3;
  285.      fsplit(st,std,stn,ste);
  286.      sta := std + ddir[i].name;
  287.      setcuron;
  288.      write('Are you sure you want to delete ',sta,'? (Y/N)');
  289.      readln(ch);
  290.      setcuroff;
  291.      ch := upcase(ch);
  292.      if (ch <> 'Y') then
  293.      begin
  294.           popwindow;
  295.           exit;
  296.      end;
  297.      erasefile(sta,ret);
  298.      if (ret <> 0) then writeln('Error #',ret,' in deleting');
  299.      popwindow;
  300.      if ret = 0 then getnewdir(false);
  301. end;
  302.  
  303. procedure dotypefile(i : integer);  { And you can figure this one out, too. }
  304. var sta : pathstr;  { The window created is typed into, in this case. }
  305.     ret : byte;
  306. begin
  307.      cw3;
  308.      fsplit(st,std,stn,ste);
  309.      sta := std + ddir[i].name;
  310.      typefile(sta,ret);
  311.      if (ret <> 0) then writeln('Error #',ret,' in typing');
  312.      writeln;
  313.      writeln;
  314.      settextattr(112);
  315.      write('Press any key to continue...');
  316.      settextattr(7);
  317.      repeat until keypressed;
  318.      ret := ord(readkey); if ret = 0 then ret := ord(readkey);
  319.      popwindow;
  320. end;
  321.  
  322. procedure dorunfile(i : integer);  { Run a file }
  323. var sta,stb : pathstr;
  324. begin
  325.      createwindow(4,1,1,80,25,7,7,'','');  { Make a big window to save the others }
  326.      fsplit(st,std,stn,ste);     { Get the name and path }
  327.      sta := std + ddir[i].name;
  328.      setcuron;                   { Set the cursor on }
  329.      write('Enter command line: ');   { Let the user enter the command line }
  330.      readln(stb);
  331.      swapvectors;      { Save interrupt vectors.  This is a standard TP practice }
  332.      exec(sta,stb);    { Run the file }
  333.      swapvectors;      { Get the interrupt vectors back again }
  334.      setcuroff;        { Turn cursor off }
  335.      popwindow;        { Get rid of that big window and recall old ones }
  336.      gotowindow(1);
  337.      getnewdir(false);  { Program may have changed files, so re-get them }
  338. end;
  339.  
  340. procedure dogetinfo;  { Get informaton about the directory. }
  341. var b,c : longint;    { Such as bytes free and used and files in it }
  342.     sta : string;     { and the default directory. }
  343. begin                 { I'll let you figure this out yourself }
  344.      cw3;
  345.      b := disksize(ord(st[1]) - 64);
  346.      c := diskfree(ord(st[1]) - 64);
  347.      system.getdir(0,sta);
  348.      writeln('Current default directory: ',sta);
  349.      writeln('Number of files: ',a);
  350.      writeln(c,' of ',b,' bytes free.');
  351.      writeln('Disk ',((1 - c/b) * 100):5:2,'% full.');
  352.      write('Press any key to continue...');
  353.      repeat until keypressed;
  354.      b := ord(readkey);
  355.      if (b = 0) then c := ord(readkey);
  356.      popwindow;
  357. end;
  358.  
  359. procedure dochangedir;  { Change the default directory. }
  360. var x,y : byte;         { See if you can figure this one out! }
  361.     sta : pathstr;
  362. begin
  363.      cw3;
  364.      setcuron;
  365.      write('Enter new default directory: ');
  366.      sta := 'The directory MUST be entered exactly right';
  367.      y := wherey;
  368.      vramwrit(lo(windmin)+1,hi(windmin)+y+1,112,sta);
  369.      readln(sta);
  370.      setcuroff;
  371.      popwindow;
  372.      {$I-}
  373.      chdir(sta);
  374.      {$I+}
  375.      if ioresult <> 0 then exit
  376.      else getnewdir(false);
  377. end;
  378.  
  379. procedure domakedir;  { Another tricky one to create a subdirectory }
  380. var x,y : byte;
  381.     sta : pathstr;
  382. begin
  383.      cw3;
  384.      setcuron;
  385.      write('Enter directory to create: '); y := wherey;
  386.      sta := 'Enter JUST the name, NOT the path';
  387.      getxy(x,y);
  388.      vramwrit(lo(windmin)+1,y+hi(windmin)+1,112,sta);
  389.      readln(sta);
  390.      setcuroff;
  391.      fsplit(st,std,stn,ste);
  392.      sta := std + sta;
  393.      {$I-}
  394.      mkdir(sta);
  395.      {$I+}
  396.      popwindow;
  397.      if ioresult <> 0 then exit
  398.      else getnewdir(false);
  399. end;
  400.  
  401. procedure doremovedir(i : integer);  { and remove a subdirectory...}
  402. var sta : pathstr;
  403. begin
  404.      fsplit(st,std,stn,ste);
  405.      sta := std + ddir[i].name;
  406.      {$I-}
  407.      rmdir(sta);
  408.      {$I+}
  409.      if ioresult <> 0 then exit
  410.      else getnewdir(false);
  411. end;
  412.  
  413. procedure linewrite(lno,i : integer);   { Write out one line of filenames }
  414. var st : string;                        { for scrolling }
  415.     w : word;
  416. begin
  417.      i := ((i-1) * 3) + 1;
  418.      qfillchar(st[1],40,$20);
  419.      st := ddir[i].seen;
  420.      if (i < a) then        { Write the filenames out, checking for the last one }
  421.      begin
  422.           st[0] := #25;
  423.           st := st + '  ' + ddir[i+1].seen;
  424.      end;
  425.      if (i+1 < a) then
  426.      begin
  427.           st[0] := #50;
  428.           st := st + '  ' + ddir[i+2].seen;
  429.      end;
  430.      vramwrit(1,lno,7,st);   { And write the line }
  431. end;
  432.  
  433. procedure uponeline; { Go up one line on request }
  434. begin
  435.      if (lnum > 1) then   { If not at beginning }
  436.      begin
  437.           writeone(sclin,anum,7);    { Erase old highlight bar }
  438.           dec(lnum);  dec(anum,3);  dec(sclin);  { Dec the 3 affected vars }
  439.           if (sclin < 1) then  { If you have gone of the top of the screen,}
  440.           begin  { Scroll the screen up one, back up the line 1, and write }
  441.                inc(sclin);  vscroll(-1);  linewrite(sclin,lnum);
  442.           end;   { Out the new line that has scrolled on }
  443.           writeone(sclin,anum,112);  { Draw the new highlight bar }
  444.      end;
  445. end;
  446.  
  447. procedure downoneline;  { Go down 1 line on request }
  448. begin
  449.      if (lnum*3 < a) then  { If you are not at the end }
  450.      begin
  451.           writeone(sclin,anum,7);  { erase the highlight bar }
  452.           inc(lnum);  inc(anum,3);  inc(sclin);  { Inc the vars }
  453.           if (anum > a) then       { If this is past the last one, }
  454.           begin
  455.                anum := a;          { go back to the last one }
  456.                if (frac(anum/3) > 0.5) then cnum := 2  { and set the column }
  457.                else if (frac(anum/3) > 0.2) then cnum := 1;  { number }
  458.           end;
  459.           if sclin > 19 then  { If you've gone off the end of the screen,}
  460.           begin   { scroll up one line }
  461.                dec(sclin);  vscroll(1); linewrite(sclin,lnum);
  462.           end;
  463.           writeone(sclin,anum,112);  { Write out the new highlight bar }
  464.      end;
  465. end;
  466.  
  467. procedure leftoneline;  { Handle cursor left }
  468. begin
  469.      if (cnum > 1) then   { If no "backwrap" needed }
  470. { Backwrap is when you are at the far left of the screen and press the
  471.   left arrow key.  You should go up one line and be at the end of the line }
  472.      begin
  473.           writeone(sclin,anum,7);
  474.           dec(cnum); dec(anum);
  475.           writeone(sclin,anum,112);
  476.      end
  477.      else if (anum > 1) then  { If "backwrap" needed }
  478.      begin
  479.           writeone(sclin,anum,7);
  480.           cnum := 3; dec(anum); dec(lnum); dec(sclin);
  481.           if (sclin < 1) then
  482.           begin
  483.                inc(sclin); vscroll(-1); linewrite(sclin,lnum);
  484.           end;
  485.           writeone(sclin,anum,112);
  486.      end;
  487. end;
  488.  
  489. procedure rightoneline;  { Handle right one }
  490. begin
  491.      if (cnum < 3) and (anum < a) then  { If no "forewrap" needed }
  492.                                         { and not at end }
  493. { Forewrap is the same thing as backwrap, just forewrap is for going to
  494.   the right.}
  495.      begin
  496.           writeone(sclin,anum,7);
  497.           inc(cnum); inc(anum);
  498.           writeone(sclin,anum,112);
  499.      end
  500.      else if (anum < a) then  { Else if not at end }
  501.      begin
  502.           writeone(sclin,anum,7);
  503.           cnum := 1; inc(anum); inc(lnum); inc(sclin);
  504.           if (sclin > 19) then
  505.           begin
  506.                dec(sclin); vscroll(1); linewrite(sclin,lnum);
  507.           end;
  508.           writeone(sclin,anum,112);
  509.      end;
  510. end;
  511.  
  512. procedure uptotop;  {Handle PgUp}
  513. begin
  514.      repeat uponeline until lnum = 1;
  515.      if (anum > 1) then repeat leftoneline until anum = 1;
  516. end;
  517.  
  518. procedure downtobottom; {Handle PgDn}
  519. var ab,ac : integer;
  520. begin
  521.      ab := anum;
  522.      repeat
  523.            downoneline;
  524.            ac := ab;
  525.            ab := anum;
  526.      until (anum = a) or (ab = ac);
  527.      if (ab = ac) then
  528.      begin
  529.           repeat
  530.                 rightoneline;
  531.           until (anum = a);
  532.      end;
  533. end;
  534.  
  535. begin  { DirPlus }
  536.      if vid_mem_start = $B000 then mono := true else mono := false; {is mono?}
  537.      createwindow(1,1,1,80,19,7,7,'','');  { Create window for filenames }
  538.      createwindow(2,1,20,80,25,7,7,' COMMANDS ','******'); { window for commands }
  539.      gotowindow(1);  { go to filenames window }
  540.      repeat  {Should not be a repeat !}  {you can cut it out}
  541.            exitnow := false;  { No exit yet }
  542.            setcuroff;         { turn cursor off }
  543.            gotowindow(2); clrscr;  { write out commands }
  544.            writeln('1 : new directory      2 : rename        3 : copy');
  545.            writeln('DEL : delete           ENTER : type      4 : run');
  546.            writeln('5 : directory info     6 : change dir    7 : make dir');
  547.              write('8 : remove dir         ESC : exit');
  548.            gotowindow(1);    { Go to filenames window }
  549.            getnewdir(true);  { Get filenames and write them out }
  550.            repeat            { Handle commands until done }
  551.                  repeat until keypressed;  { Wait for a key }
  552.                  cha := readkey;           { get it }
  553.                  if ddir[anum].seen[1] = #174 then   { if highlighted fname }
  554.                  begin    { is a subdirectory, 1, and 8 are different from }
  555.                       if cha = '1' then getdiskdir(anum);    { normal }
  556.                       if cha = '8' then doremovedir(anum);
  557.                  end
  558.                  else
  559.                  case cha of    { Only for non-subdirectory files }
  560.                       '1' : getnewdir(true);
  561.                       '2' : dorenamefile(anum);
  562.                       '3' : docopyfile(anum);
  563.                       '4' : dorunfile(anum);
  564.                  end;
  565.                  if cha = '5' then dogetinfo;    { Either is fine }
  566.                  if cha = '6' then dochangedir;
  567.                  if cha = '7' then domakedir;
  568.                  if cha = #13 then             { If enter, type }
  569.                  begin                  { Or go in if subdirectory }
  570.                       if ddir[anum].seen[1] = #174 then getdiskdir(anum)
  571.                       else dotypefile(anum);
  572.                  end;
  573.                  if cha = #27 then exitnow := true;  { ESC is exit }
  574.                  if cha = #0 then      { If extended keycode }
  575.                  begin
  576.                       chb := readkey;  { get the extended key }
  577.                       case chb of
  578.                            #72 : uponeline;     { up }
  579.                            #75 : leftoneline;   { left }
  580.                            #77 : rightoneline;  { right }
  581.                            #80 : downoneline;   { down }
  582.                            #73 : uptotop;       { PgUp }
  583.                            #81 : downtobottom;  { PgDn }
  584.                  {Del deletes a file (or subdir) }
  585.                            #83 : if ddir[anum].seen[1] = #174 then doremovedir(anum)
  586.                                     else dodeletefile(anum);
  587.                       end;
  588.                  end;
  589.            until exitnow;  { repeat unless time to exit (ESC pressed) }
  590.      until exitnow;    { Can be removed, serves no purpose }
  591.      window(1,1,80,25); settextattr(7); clrscr; setcuron;  { Leave }
  592. end.