home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / d / drcpas10.zip / DOSTOOLS.PAS < prev    next >
Pascal/Delphi Source File  |  1992-11-17  |  12KB  |  504 lines

  1. {$A+,B-,D-,F-,I+,L-,N-,O-,R-,S+,V-}
  2. Unit DosTools;
  3.  
  4. (* by David R. Conrad, for Turbo Pascal 5.5
  5.  
  6.    This code is not copyrighted, you may use it freely.
  7.    There are no guarantees, either expressed or implied,
  8.    as to either merchantability or fitness for a particular
  9.    purpose.  The author's liability is limited to the amount
  10.    you paid for it.
  11.  
  12.    David R. Conrad, 17 Nov 92
  13.    David_Conrad@mts.cc.wayne.edu
  14.    dave@michigan.com
  15. *)
  16.  
  17. Interface
  18.  
  19. Uses Dos;
  20.  
  21. type
  22.   (* like namestr, extstr *)
  23.   filestr = string[12];
  24.  
  25. const
  26.   (* for use with CrtMode, to detect monochrome *)
  27.   mono       = 7;
  28.   (* for use with Boot, to select boot type *)
  29.   WarmBoot   = 0;
  30.   ColdBoot   = 1;
  31.   ResetBoot  = 2;
  32.   (* for use with the printer functions *)
  33.   PrnNotBusy = $80;
  34.   PrnAck     = $40;
  35.   PrnNoPaper = $20;
  36.   PrnSelect  = $10;
  37.   PrnIOError = $08;
  38.   PrnTimeout = $01;
  39.   (* for use with PrtScStat, status of last Print Screen operation *)
  40.   PrtScOn    = $00;          (* PrtSc ready *)
  41.   PrtScOff   = $01;          (* PrtSc busy (in progress) *)
  42.   PrtScErr   = $FF;          (* an error occurred *)
  43.  
  44. var
  45.   CrtMode   : Byte Absolute $0040:$0049;
  46.   PrtScStat : Byte Absolute $0050:$0000;
  47.  
  48. (* all routines are documented in the implementation section *)
  49.  
  50. Function Ampm : String;
  51. Function Ampmn : String;
  52. Procedure Boot (BootType : Integer);
  53. Procedure Call (Proc : Pointer);
  54. Procedure CursBlock;
  55. Procedure CursHalf;
  56. Procedure Cursoff;
  57. Procedure Curson;
  58. Procedure Cursor (a,b : byte);
  59. Function Date : String;
  60. Function Datec : String;
  61. Procedure DiskAlloc (    Drive : Byte;
  62.                      var Cluster : Integer; var Free, Cap, Used : Longint);
  63. Procedure DisableInterrupts; Inline ($FA); {CLI}
  64. Procedure EnableInterrupts;  Inline ($FB); {STI}
  65. Function Exist (FN : Pathstr) : Boolean;
  66. Function Exists (FN : Pathstr) : Boolean;
  67. Function IsDir (FN : Pathstr) : Boolean;
  68. Function IsLabel (FN : Pathstr) : Boolean;
  69. Function IsWritable (FN : Pathstr) : Boolean;
  70. Function GetLabel (Drive : Char) : FileStr;
  71. Function GetCursor : Word;
  72. Procedure InitRegisters (var Reg : Registers);
  73. Function PrnOnline (PrinterNumber : Byte) : Boolean;
  74. Function PrnReady (PrinterNumber : Byte) : Boolean;
  75. Function PrnStatus (PrinterNumber : Byte) : Byte;
  76. Function PrnErr (Err : Byte) : String;
  77. Function Time : String;
  78. Function Timen : String;
  79. Function WeekDay : String;
  80.  
  81. Implementation
  82.  
  83. Function Ampm : String;
  84. (* time in the format '09:30:47 pm' *)
  85. var
  86.   h,m,s,w,ap : string;
  87.   hour,min,sec,sec100,
  88.   i : word;
  89. begin
  90.   GetTime (hour,min,sec,sec100);
  91.   ap := 'am';
  92.   If hour > 11 then ap := 'pm';
  93.   If hour > 12 then
  94.     hour := hour - 12;
  95.   str (hour:2,h);
  96.   str (min:2,m);
  97.   str (sec:2,s);
  98.   If h = ' 0' then h := '12';
  99.   w := h + ':' + m + ':' + s + ' ' + ap;
  100.   for i := 2 to length(w) - 3 do if w[i]=' ' then w[i]:='0';
  101.   ampm := w;
  102. end;
  103.  
  104. Function Ampmn : String;
  105. (* time in the format '09:30 pm' *)
  106. var
  107.   h,m,w,ap : string;
  108.   hour,min,sec,sec100,
  109.   i : word;
  110. begin
  111.   GetTime (hour,min,sec,sec100);
  112.   ap := 'am';
  113.   If hour > 11 then ap := 'pm';
  114.   If hour > 12 then
  115.     hour := hour - 12;
  116.   str (hour:2,h);
  117.   str (min:2,m);
  118.   If h = ' 0' then h := '12';
  119.   w := h + ':' + m + ' ' + ap;
  120.   for i := 2 to length(w) - 3 do if w[i]=' ' then w[i]:='0';
  121.   ampmn := w;
  122. end;
  123.  
  124. Procedure Boot (BootType : Integer);
  125. (* reboot the computer, flushing caches first *)
  126. const
  127.   bootwarm = $1234;
  128.   bootcold = 0;
  129. var
  130.   reg : registers;
  131.   bootaddr : pointer;
  132.   warmcold : word absolute $40:$72;
  133.   shifts : byte absolute $40:$17;
  134. begin
  135.   initregisters (reg);
  136.   bootaddr := ptr($FFFF,0);
  137.   if (BootType < 0) or (BootType > 2) then exit;
  138.   case boottype of
  139.     warmboot : warmcold := bootwarm;
  140.     coldboot : warmcold := bootcold;
  141.   end;
  142.   reg.ah := $0D;
  143.   intr ($21, reg);
  144.   shifts := (4 OR 8);                  {Ctrl-Alt}
  145.   repeat
  146.     reg.flags := FCarry;
  147.     reg.ax := $4F53;                   {Translate scan codes, Del}
  148.     intr ($15, reg);
  149.   until (reg.flags AND FCarry) = FCarry;
  150.   case boottype of
  151.     warmboot  : call (bootaddr);       {One call we won't be returning from}
  152.     coldboot  : call (bootaddr);
  153.     resetboot : begin
  154.                   DisableInterrupts;
  155.                   port[$64] := $FE;    {Tell keyboard to reset processor}
  156.                   while (true) do;     {Wait for it}
  157.                 end;
  158.   end;
  159. end;
  160.  
  161. var
  162.   CallAddr : Pointer;
  163.  
  164. Procedure Call (Proc : Pointer);
  165. (* call a procedure with no parameters *)
  166.  
  167.   Procedure CallProc; Inline ($FF/$1E/CallAddr);
  168.                              {CALL DWORD PTR CallAddr}
  169. begin
  170.   CallAddr := Proc;
  171.   CallProc;
  172. end;
  173.  
  174. Procedure CursBlock;
  175. (* change the cursor to a full-height block *)
  176. var
  177.   reg : Registers;
  178. begin
  179.   initregisters (reg);
  180.   If crtmode = mono then
  181.     reg.cx := $00C
  182.   else
  183.     reg.cx := $007;
  184.   reg.bx := 0;
  185.   reg.ax := $0100;
  186.   intr ($10,reg);
  187. end;
  188.  
  189. Procedure CursHalf;
  190. (* change the cursor to a half-height block *)
  191. var
  192.   reg : Registers;
  193. begin
  194.   initregisters (reg);
  195.   If crtmode = mono then
  196.     reg.cx := $070C
  197.   else
  198.     reg.cx := $0407;
  199.   reg.bx := 0;
  200.   reg.ax := $0100;
  201.   intr ($10,reg);
  202. end;
  203.  
  204. Procedure Cursoff;
  205. (* turn the cursor off *)
  206. var
  207.   reg : Registers;
  208. begin
  209.   initregisters (reg);
  210.   reg.cx := $2000;
  211.   reg.bx := 0;
  212.   reg.ax := $0100;
  213.   intr ($10,reg);
  214. end;
  215.  
  216. Procedure Curson;
  217. (* set the cursor to its normal (underline) form *)
  218. var
  219.   reg : Registers;
  220. begin
  221.   initregisters (reg);
  222.   If crtmode = mono then
  223.     reg.cx := $B0C
  224.   else
  225.     reg.cx := $607;
  226.   reg.bx := 0;
  227.   reg.ax := $0100;
  228.   intr ($10,reg);
  229. end;
  230.  
  231. Procedure Cursor (a,b : byte);
  232. (* set the cursor to extend from scan line a to scan line b *)
  233. var
  234.   reg : Registers;
  235. begin
  236.   initregisters (reg);
  237.   reg.ch := a;
  238.   reg.cl := b;
  239.   reg.bx := 0;
  240.   reg.ax := $0100;
  241.   intr ($10,reg);
  242. end;
  243.  
  244. Function Date : String;
  245. (* the date in the format 'MM/DD/YY' *)
  246. var
  247.   y,m,d,w : string;
  248.   Year,Month,Day,DayofWeek,
  249.   i : word;
  250. begin
  251.   GetDate (Year,Month,Day,DayofWeek);
  252.   str (year:4,y);
  253.   delete (y,1,2);
  254.   str (month:2,m);
  255.   str (day:2,d);
  256.   w := m + '/' + d + '/' + y;
  257.   for i := 2 to length(w) do if w[i]=' ' then w[i] := '0';
  258.   date := w;
  259. end;
  260.  
  261. Function Datec : String;
  262. (* the date in the format 'MM/DD/YYYY' *)
  263. var
  264.   y,m,d,w : string;
  265.   Year,Month,Day,DayofWeek,
  266.   i : word;
  267. begin
  268.   GetDate (Year,Month,Day,DayofWeek);
  269.   str (year:4,y);
  270.   str (month:2,m);
  271.   str (day:2,d);
  272.   w := m + '/' + d + '/' + y;
  273.   for i := 2 to length(w) do if w[i]=' ' then w[i] := '0';
  274.   datec := w;
  275. end;
  276.  
  277. Procedure DiskAlloc (    Drive : Byte;
  278.                      var Cluster : Integer; var Free, Cap, Used : Longint);
  279. (* get allocation info. for a drive, -1 on error *)
  280. (* cluster size, free space, capacity and space used *)
  281. var
  282.   r : registers;
  283. begin
  284.   initregisters (r);
  285.   r.ah := $36;
  286.   r.dl := drive;
  287.   intr ($21, r);
  288.   if r.ax = $ffff then
  289.     begin
  290.       cluster := -1;
  291.       free := -1;
  292.       cap := -1;
  293.       used := -1;
  294.     end
  295.   else
  296.     begin
  297.       cluster := r.ax*r.cx;
  298.       free := r.bx*longint(cluster);
  299.       cap := r.dx*longint(cluster);
  300.       used := cap - free;
  301.     end;
  302. end;
  303.  
  304. Function Exist (FN : Pathstr) : Boolean;
  305. (* does a file exist? *)
  306. var
  307.   f  : file;
  308.   a : word;
  309. begin
  310.   Assign (f,FN);
  311.   GetFAttr (f,a);
  312.   Exist := (DosError = 0) and ((a AND (Directory OR VolumeID)) = 0);
  313.   (* NOTE: volume labels cannot actually be detected this way;
  314.            included for compatibility with future versions of DOS *)
  315. end;
  316.  
  317. Function Exists (FN : Pathstr) : Boolean;
  318. (* does a string exist in the namespace of files? (including directories) *)
  319. var
  320.   f  : file;
  321.   a : word;
  322. begin
  323.   Assign (f,FN);
  324.   GetFAttr (f,a);
  325.   Exists := (DosError = 0);
  326. end;
  327.  
  328. Function IsDir (FN : Pathstr) : Boolean;
  329. (* is a filename a directory? *)
  330. var
  331.   f  : file;
  332.   a : word;
  333. begin
  334.   Assign (f,FN);
  335.   GetFAttr (f,a);
  336.   IsDir := (DosError = 0) and ((a AND Directory) = Directory);
  337. end;
  338.  
  339. Function IsLabel (FN : Pathstr) : Boolean;
  340. (* is a filename a volume label? *)
  341. (* NOTE: FN should refer to the root directory of a drive, the only
  342.          place where volume labels are legal. *)
  343. var
  344.   s : searchrec;
  345. begin
  346.   FindFirst (FN, VolumeID, s);
  347.   IsLabel := DosError = 0;
  348. end;
  349.  
  350. Function IsWritable (FN : Pathstr) : Boolean;
  351. (* is a file writable? *)
  352. var
  353.   f  : file;
  354.   a : word;
  355. begin
  356.   Assign (f,FN);
  357.   GetFAttr (f,a);
  358.   IsWritable := (DosError = 0) and
  359.                 ((a AND (Directory OR VolumeID OR ReadOnly)) = 0);
  360.   (* NOTE: volume labels cannot actually be detected this way;
  361.            included for compatibility with future versions of DOS *)
  362. end;
  363.  
  364. Function GetLabel (Drive : Char) : FileStr;
  365. (* get volume label of a drive *)
  366. var
  367.   s : searchrec;
  368. begin
  369.   FindFirst (Drive+':*.*', VolumeID, s);
  370.   If DosError = 0 then
  371.     begin
  372.       if length(s.name) > 8 then
  373.         delete (s.name, 9, 1);
  374.       GetLabel := s.name;
  375.     end
  376.   else
  377.     GetLabel := '';
  378. end;
  379.  
  380. Function GetCursor : Word;
  381. (* return current cursor size (restore with Cursor (hi(curs), lo(curs)) *)
  382. var
  383.   reg : registers;
  384. begin
  385.   initregisters (reg);
  386.   reg.ah := $03;
  387.   reg.bh := 0;
  388.   Intr ($10, reg);
  389.   GetCursor := reg.cx;
  390. end;
  391.  
  392. Procedure InitRegisters (var Reg : Registers);
  393. (* initialize variable of type registers: slightly anal-retentive *)
  394. begin
  395.   fillchar (reg, sizeof(reg), 0);
  396.   reg.ds := dseg;
  397.   reg.es := dseg;
  398. end;
  399.  
  400. Function PrnOnline (Printernumber : Byte) : Boolean;
  401. (* Is LPT(Printernumber) online? *)
  402. var
  403.   reg : Registers;
  404. begin
  405.   initregisters (reg);
  406.   reg.ah := 2;
  407.   reg.dx := pred(printernumber);
  408.   Intr ($17,reg);
  409.   PrnOnline := (reg.ah AND PrnSelect) = PrnSelect;
  410. end;
  411.  
  412. Function PrnReady (Printernumber : Byte) : Boolean;
  413. (* Is LPTn ready to accept output (not busy or error)? *)
  414. var
  415.   reg : Registers;
  416. begin
  417.   initregisters (reg);
  418.   reg.ah := 2;
  419.   reg.dx := pred(printernumber);
  420.   Intr ($17,reg);
  421.   PrnReady :=
  422.     ((reg.ah AND (PrnNotBusy OR PrnSelect)) = (PrnNotBusy OR PrnSelect))
  423.     and ((reg.ah AND (PrnIOError AND PrnNoPaper AND PrnTimeout)) = 0);
  424. end;
  425.  
  426. Function PrnStatus (Printernumber : Byte) : Byte;
  427. (* return status of LPTn with undefined bits masked off *)
  428. var
  429.   reg : Registers;
  430. begin
  431.   initregisters (reg);
  432.   reg.ah := 2;
  433.   reg.dx := pred(printernumber);
  434.   Intr ($17,reg);
  435.   PrnStatus := (reg.ah AND $F9);  (* mask off the two unused bits *)
  436. end;
  437.  
  438. Function PrnErr (Err : Byte) : String;
  439. (* attempt to produce error message from status of printer *)
  440. begin
  441.   PrnErr := '';
  442.   if (Err AND PrnNoPaper) = PrnNoPaper then PrnErr := 'Out of Paper'
  443.   else
  444.     if (Err AND PrnTimeout) = PrnTimeout then PrnErr := 'Timeout'
  445.     else
  446.       if (Err AND PrnSelect) = 0 then PrnErr := 'Off Line'
  447.       else
  448.         if (Err AND PrnIOError) = PrnIOError then PrnErr := 'I/O Error'
  449.         else
  450.           if (Err AND PrnNotBusy) = 0 then PrnErr := 'Busy';
  451. end;
  452.  
  453. Function Time : String;
  454. (* time in the format '20:44:32' *)
  455. var
  456.   h,m,s,w : string;
  457.   hour,min,sec,sec100,
  458.   i : word;
  459. begin
  460.   GetTime (hour,min,sec,sec100);
  461.   str (hour:2,h);
  462.   str (min:2,m);
  463.   str (sec:2,s);
  464.   w := h + ':' + m + ':' + s;
  465.   for i := 2 to length(w) do if w[i]=' ' then w[i]:='0';
  466.   time := w;
  467. end;
  468.  
  469. Function Timen : String;
  470. (* time in the format '20:44' *)
  471. var
  472.   h,m,w : string;
  473.   hour,min,sec,sec100,
  474.   i : word;
  475. begin
  476.   GetTime (hour,min,sec,sec100);
  477.   str (hour:2,h);
  478.   str (min:2,m);
  479.   w := h + ':' + m;
  480.   for i := 2 to length(w) do if w[i]=' ' then w[i]:='0';
  481.   timen := w;
  482. end;
  483.  
  484. Function WeekDay : String;
  485. (* return the current day of week in English *)
  486. var
  487.   Year,Month,Day,DayOfWeek : word;
  488. begin
  489.   GetDate (Year,Month,Day,DayOfWeek);
  490.   case DayOfWeek of
  491.     0 : WeekDay := 'Sunday';
  492.     1 : WeekDay := 'Monday';
  493.     2 : WeekDay := 'Tuesday';
  494.     3 : WeekDay := 'Wednesday';
  495.     4 : WeekDay := 'Thursday';
  496.     5 : WeekDay := 'Friday';
  497.     6 : WeekDay := 'Saturday';
  498.   else
  499.     WeekDay := '';
  500.   end;
  501. end;
  502.  
  503. End.
  504.