home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 June / MacFormat 25.iso / Shareware City / Developers / ICAppSourceKit1.0 / ICMiscSubs.p < prev    next >
Encoding:
Text File  |  1994-11-27  |  18.3 KB  |  757 lines  |  [TEXT/PJMM]

  1. unit ICMiscSubs;
  2.  
  3. interface
  4.  
  5.     const
  6.         nulChar = 0;
  7.         homeChar = $01;
  8.         enterChar = $03;
  9.         endChar = $04;
  10.         helpChar = $05;
  11.         backSpaceChar = $08;
  12.         tabChar = $09;
  13.         lfChar = $0A;
  14.         pageUpChar = $0b;
  15.         pageDownChar = $0c;
  16.         crChar = $0D;
  17.         escChar = $1b;
  18.         escKey = $35;
  19.         clearChar = $1b;
  20.         clearKey = $47;
  21.         leftArrowChar = $1c;
  22.         rightArrowChar = $1d;
  23.         upArrowChar = $1e;
  24.         downArrowChar = $1f;
  25.         spaceChar = $20;
  26.         delChar = $7f;
  27.         bulletChar = $a5;
  28.         undoKey = $7a;
  29.         cutKey = $78;
  30.         copyKey = $63;
  31.         pasteKey = $76;
  32.  
  33.     const
  34.         kReturnKeyCode = 36;
  35.         kTabKeyCode = 48;
  36.         kSpaceKeyCode = 49;
  37.         KDeleteKeyCode = 51;
  38.         kEnterKeyCode = 52;
  39.         kCommandKeyCode = 55;
  40.         kShiftKeyCode = 56;
  41.         kCapsLockKeyCode = 57;
  42.         kOptionKeyCode = 58;
  43.         kClearKeyCode = 71;
  44.  
  45.     const
  46.         owner_id = -16096;
  47.         machine_id = -16413;
  48.  
  49.     procedure InitMiscSubs;
  50.  
  51.     function GetVolInfo (var name: str63; var vrn: integer; index: integer; var CrDate: longInt): OSErr;
  52.     function MyGetAPPL (sig: OSType; var fs: FSSpec): OSErr;
  53.     function FSpGetCatInfo (var fs: FSSpec; index: integer; var pb: CInfoPBRec): OSErr;
  54.     function GetWindowContentRegion (theWindow: WindowPtr): RgnHandle;
  55.     function GetWindowStructureRegion (theWindow: WindowPtr): RgnHandle;
  56.     function TitleBarOnScreen (wp: WindowPtr): boolean;
  57.     procedure GetWindowPortRect (theWindow: WindowPtr; var portRect: rect);
  58.     procedure GetWindowRect (theWindow: WindowPtr; var r: rect);
  59.     procedure CentreRect (inside_rect: Rect; var res_rect: Rect);
  60.     procedure CentreAlert (id: integer);
  61.     function GetAString (id, index: integer): Str255;
  62.     procedure Assert (b: boolean);
  63.     procedure SetItemEnable (mh: menuHandle; item: integer; enable: boolean);
  64.     function DirtyKey (ch: char): boolean;
  65.     procedure DoArrowKey (lh: ListHandle; uparrow: boolean);
  66.  
  67.     function IsKeyDown (keycode: integer): boolean;
  68.     function SelectedLine (lh: ListHandle): integer;
  69.  
  70.     function FSWriteQ (refnum: integer; count: longint; buf: Ptr): OSErr;
  71.     function FSReadQ (refnum: integer; count: longint; buf: Ptr): OSErr;
  72.  
  73.     procedure DrawIcon (id: integer; r: Rect; highlighted: boolean);
  74.  
  75.     function FileLocked (fss: FSSpec): boolean;
  76.  
  77.     procedure DoListKey (list: ListHandle; modifiers: integer; ch: char; getentryname: ProcPtr);
  78. {  function GetEntryName (list: ListHandle; c: cell): str255;}
  79.  
  80.     function DecStr (l: longint): Str255;
  81.     function CopyFile (source, dest: FSSpec): OSErr;
  82.  
  83.     function GetOwnerName: str255;
  84.     function GetMachineName: str255;
  85.  
  86. implementation
  87.  
  88.     uses
  89.         IconFamilies, Errors, IconFamilies, 
  90.  
  91.         ICGlobals;
  92.  
  93.     var
  94.         typed_chars: str31;
  95.         typed_time: longInt;
  96.         typed_lh: ListHandle;
  97.  
  98.     procedure InitMiscSubs;
  99.     begin
  100.         typed_chars := '';
  101.         typed_time := 0;
  102.         typed_lh := nil;
  103.     end;
  104.  
  105.     procedure DrawIcon (id: integer; r: Rect; highlighted: boolean);
  106.         var
  107.             suite: Handle;
  108.             iconh: Handle;
  109.             junk: OSErr;
  110.             transform: integer;
  111.     begin
  112.         if system7 & (GetIconSuite(suite, id, svAllLargeData) = noErr) then begin
  113.             if highlighted then begin
  114.                 transform := ttSelected;
  115.             end
  116.             else begin
  117.                 transform := ttNone;
  118.             end; (* if *)
  119.             junk := PlotIconSuite(r, 0, transform, suite);
  120.             junk := DisposeIconSuite(suite, false);
  121.         end
  122.         else begin
  123.             iconh := Get1Resource('ICN#', id);
  124.             if iconh <> nil then begin
  125.                 PlotIcon(r, iconh);
  126.             end; (* if *)
  127.         end; (* if *)
  128.     end; (* if *)
  129.  
  130.     function FSWriteQ (refnum: integer; count: longint; buf: Ptr): OSErr;
  131.     begin
  132.         FSWriteQ := FSWrite(refnum, count, buf);
  133.     end; (* FSWriteQ *)
  134.  
  135.     function FSReadQ (refnum: integer; count: longint; buf: Ptr): OSErr;
  136.     begin
  137.         FSReadQ := FSRead(refnum, count, buf);
  138.     end; (* FSReadQ *)
  139.  
  140.     function SelectedLine (lh: ListHandle): integer;
  141.         var
  142.             acell: Cell;
  143.     begin
  144.         SetPt(acell, 0, 0);
  145.         if LGetSelect(true, acell, lh) then begin
  146.             SelectedLine := acell.v;
  147.         end
  148.         else begin
  149.             SelectedLine := -1;
  150.         end; (* if *)
  151.     end; (* SelectedLine *)
  152.  
  153.     function IsKeyDown (keycode: integer): boolean;
  154.         var
  155.             mykeys: KeyMap;
  156.     begin
  157.         GetKeys(mykeys);
  158.         IsKeyDown := mykeys[keycode];
  159.     end; (* IsKeyDown *)
  160.  
  161.     function GetVolInfo (var name: str63; var vrn: integer; index: integer; var CrDate: longInt): OSErr;
  162.         var
  163.             pb: paramBlockRec;
  164.             oe: OSErr;
  165.     begin
  166.         if (name <> '') & (name[length(name)] <> ':') then
  167.             name := concat(name, ':');
  168.         pb.ioNamePtr := @name;
  169.         pb.ioVRefNum := vrn;
  170.         pb.ioVolIndex := index;
  171.         oe := PBGetVInfo(@pb, false);
  172.         if oe = noErr then begin
  173.             vrn := pb.ioVRefNum;
  174.             CrDate := pb.ioVCrDate;
  175.         end;
  176.         GetVolInfo := oe;
  177.     end;
  178.  
  179.     function MyGetAPPL (sig: OSType; var fs: FSSpec): OSErr;
  180.         var
  181.             i: integer;
  182.             pbdt: DTPBRec;
  183.             crdate: longInt;
  184.             oe: OSErr;
  185.             found: boolean;
  186.     begin
  187.         found := false;
  188.         if system7 then begin
  189.             i := 1;
  190.             repeat
  191.                 fs.vRefNum := 0;
  192.                 fs.name := '';
  193.                 oe := GetVolInfo(fs.name, fs.vRefNum, i, crdate);
  194.                 i := i + 1;
  195.                 if oe = noErr then begin
  196.                     with pbdt do begin
  197.                         fs.name := '';
  198.                         ioNamePtr := @fs.name;
  199.                         ioVRefNum := fs.vRefNum;
  200.                         oe := PBDTGetPath(@pbdt);
  201.                         if oe = noErr then begin
  202.                             ioIndex := 0;
  203.                             ioFileCreator := sig;
  204.                             oe := PBDTGetAPPLSync(@pbdt);
  205.                             if oe = noErr then
  206.                                 found := true;
  207.                         end;
  208.                     end;
  209.                     oe := noErr;
  210.                 end;
  211.             until found or (oe <> noErr);
  212.         end;
  213.         if found then begin
  214.             oe := noErr;
  215.             fs.parID := pbdt.ioAPPLParID;
  216.         end
  217.         else begin
  218.             oe := afpItemNotFound;
  219.             fs.vRefNum := 0;
  220.             fs.parID := 2;
  221.             fs.name := '';
  222.         end;
  223.         MyGetAPPL := oe;
  224.     end;
  225.  
  226.     function FSpGetCatInfo (var fs: FSSpec; index: integer; var pb: CInfoPBRec): OSErr;
  227.     begin
  228.         pb.ioVRefNum := fs.vRefNum;
  229.         pb.ioDirID := fs.parID;
  230.         pb.ioNamePtr := @fs.name;
  231.         pb.ioFDirIndex := index;
  232.         FSpGetCatInfo := PBGetCatInfoSync(@pb);
  233.     end;
  234.  
  235.     function GetWindowContentRegion (theWindow: WindowPtr): RgnHandle;
  236.     begin
  237.         GetWindowContentRegion := WindowPeek(theWindow)^.contRgn;
  238.     end;
  239.  
  240.     function GetWindowStructureRegion (theWindow: WindowPtr): RgnHandle;
  241.     begin
  242.         GetWindowStructureRegion := WindowPeek(theWindow)^.strucRgn;
  243.     end;
  244.  
  245.     function TitleBarOnScreen (wp: WindowPtr): boolean;
  246.         var
  247.             rgn: RgnHandle;
  248.     begin
  249.         rgn := NewRgn;
  250.         CopyRgn(GetWindowStructureRegion(wp), rgn);
  251.         DiffRgn(rgn, GetWindowContentRegion(wp), rgn);
  252.         SectRgn(rgn, GetGrayRgn, rgn);
  253.         TitleBarOnScreen := not EmptyRgn(rgn);
  254.         DisposeRgn(rgn);
  255.     end;
  256.  
  257.     procedure GetWindowPortRect (theWindow: WindowPtr; var portRect: rect);
  258.     begin
  259.         portRect := WindowPeek(theWindow)^.port.portRect;
  260.     end;
  261.  
  262.     procedure GetWindowRect (theWindow: WindowPtr; var r: rect);
  263.     begin
  264.         SetPort(theWindow);
  265.         GetWindowPortRect(theWindow, r);
  266.         LocalToGlobal(r.topleft);
  267.         LocalToGlobal(r.botright);
  268.     end;
  269.  
  270.     procedure CentreRect (inside_rect: Rect; var res_rect: Rect);
  271.         var
  272.             stat_siz: Point;
  273.     begin
  274.         stat_siz := inside_rect.botright;
  275.         SubPt(inside_rect.topleft, stat_siz);
  276.         OffsetRect(res_rect, -res_rect.left, -res_rect.top);
  277.         SubPt(res_rect.botright, stat_siz);
  278.         stat_siz.h := stat_siz.h div 2;
  279.         stat_siz.v := stat_siz.v div 2;
  280.         AddPt(inside_rect.topleft, stat_siz);
  281.         OffsetRect(res_rect, stat_siz.h, stat_siz.v);
  282.     end; (* CentreRect *)
  283.  
  284.     procedure CentreAlert (id: integer);
  285.         var
  286.             alerth: AlertTHndl;
  287.             bounds: Rect;
  288.     begin
  289.         alerth := AlertTHndl(GetResource('ALRT', id));
  290.         if alerth <> nil then begin
  291.             bounds := screenBits.bounds;
  292.             bounds.bottom := (bounds.bottom - bounds.top) * 2 div 3 + bounds.top;
  293.             HLock(Handle(alerth));
  294.             CentreRect(bounds, alerth^^.boundsRect);
  295.             HUnlock(Handle(alerth));
  296.         end; (* if *)
  297.     end; (* CentreAlert *)
  298.  
  299.     function GetAString (id, index: integer): Str255;
  300.         var
  301.             res: Str255;
  302.     begin
  303.         GetIndString(res, id, index);
  304.         GetAString := res;
  305.     end; (* GetAString *)
  306.  
  307.     procedure Assert (b: boolean);
  308.     begin
  309.         if not b then begin
  310.             DebugStr('Assertion failure ; sc');
  311.         end; (* if *)
  312.     end;
  313.  
  314.     procedure SetItemEnable (mh: menuHandle; item: integer; enable: boolean);
  315.     begin
  316.         if enable then begin
  317.             EnableItem(mh, item);
  318.         end
  319.         else begin
  320.             DisableItem(mh, item);
  321.         end;
  322.     end;
  323.  
  324.     function DirtyKey (ch: char): boolean;
  325.     begin
  326.         case ord(ch) of
  327.             homeChar, endChar, helpChar, pageUpChar, pageDownChar, leftArrowChar, rightArrowChar, upArrowChar, downArrowChar: 
  328.                 DirtyKey := false;
  329.             otherwise
  330.                 DirtyKey := true;
  331.         end;
  332.     end;
  333.  
  334.     function IsVolumeWriteable (vRefNum: integer): OSErr;
  335.         var
  336.             pb: HParamBlockRec;
  337.             err: OSErr;
  338.     begin
  339.         pb.ioVRefNum := vRefNum;
  340.         pb.ioNamePtr := nil;
  341.         pb.ioVolIndex := 0;
  342.         err := PBHGetVInfoSync(@pb);
  343.  
  344.         if err = noErr then begin
  345.             if BAND(pb.ioVAtrb, $0080) <> 0 then begin
  346.                 err := wPrErr;        { volume locked by hardware }
  347.             end
  348.             else if BAND(pb.ioVAtrb, $8000) <> 0 then begin
  349.                 err := vLckdErr;    { volume locked by software }
  350.             end;
  351.         end;
  352.  
  353.         IsVolumeWriteable := err;
  354.     end;
  355.  
  356.     function IsFileWriteable (fs: FSSpec): OSErr;
  357.         var
  358.             pb: CInfoPBRec;
  359.             err: OSErr;
  360.     begin
  361.         pb.ioNamePtr := @fs.name;
  362.         pb.ioVRefNum := fs.vRefNum;
  363.         pb.ioDirID := fs.parID;
  364.         pb.ioFDirIndex := 0;    { use ioNamePtr and ioDirID }
  365.         err := PBGetCatInfoSync(@pb);
  366.  
  367.         if err = noErr then begin
  368.             if BAND(pb.ioFlAttrib, $01) <> 0 then begin
  369.                 err := fLckdErr;
  370.             end;
  371.         end;
  372.         IsFileWriteable := err;
  373.     end;
  374.  
  375.     function HGetDirAccess (vRefNum: integer; dirID: longInt; name: StringPtr; var ownerID, groupID, accessRights: longInt): OSErr;
  376.         var
  377.             pb: HParamBlockRec;
  378.             err: OSErr;
  379.     begin
  380.         pb.ioNamePtr := name;
  381.         pb.ioVRefNum := vRefNum;
  382.         pb.ioDirID := dirID;
  383.         err := PBHGetDirAccessSync(@pb);
  384.         ownerID := pb.ioACOwnerID;
  385.         groupID := pb.ioACGroupID;
  386.         accessRights := pb.ioACAccess;
  387.         HGetDirAccess := err;
  388.     end;
  389.  
  390.     function FileLocked (fss: FSSpec): boolean;
  391.         var
  392.             locked: boolean;
  393.             junk: longint;
  394.             access: longint;
  395.     begin
  396.         locked := (IsVolumeWriteable(fss.vRefNum) <> noErr);
  397.         if not locked then begin
  398.             locked := (IsFileWriteable(fss) <> noErr);
  399.         end; (* if *)
  400.         if not locked then begin
  401.             if HGetDirAccess(fss.vRefNum, fss.parID, nil, junk, junk, access) = noErr then begin
  402.                 locked := not btst(access, 26);
  403.             end; (* if *)
  404.         end; (* if *)
  405.         FileLocked := locked;
  406.     end; (* FileLocked *)
  407.  
  408.     procedure LSetSingleSelection (list: ListHandle; v: integer);
  409.         var
  410.             c: Cell;
  411.     begin
  412.         c.h := 0;
  413.         c.v := v;
  414.         LSetSelect(true, c, list);
  415.         c.v := 0;
  416.         c.h := 0;
  417.         while LGetSelect(true, c, list) do begin
  418.             if c.v <> v then begin
  419.                 LSetSelect(false, c, list);
  420.             end;
  421.             c.v := c.v + 1;
  422.             c.h := 0;
  423.         end;
  424.         LAutoScroll(list);
  425.     end;
  426.  
  427.     function LGetEntryNameProc (list: ListHandle; c: cell; getentryname: ProcPtr): str255;
  428.     inline
  429.         $205F, $4E90;
  430.  
  431.     function LGetUniqueEntryName (list: ListHandle; c: cell; getentryname: ProcPtr): str255;
  432.         var
  433.             s: str255;
  434.     begin
  435.         s := '';
  436.         if getentryname <> nil then begin
  437.             s := LGetEntryNameProc(list, c, getentryname);
  438.         end;
  439.         LGetUniqueEntryName := concat(s, chr(0), chr(c.v div 256), chr(c.v mod 256));
  440.     end;
  441.  
  442.     function LGetFirstSelection (list: ListHandle; var c: Cell; getentryname: ProcPtr): boolean;
  443.         var
  444.             best, n: str255;
  445.             index: integer;
  446.     begin
  447.         LGetFirstSelection := false;
  448.         c.h := 0;
  449.         c.v := 0;
  450.         best := concat(chr(255), chr(255));
  451.         while LGetSelect(true, c, list) do begin
  452.             LGetFirstSelection := true;
  453.             n := LGetUniqueEntryName(list, c, getentryname);
  454.             if IUCompString(n, best) < 0 then begin
  455.                 index := c.v;
  456.             end;
  457.             c.v := c.v + 1;
  458.         end;
  459.         c.h := 0;
  460.         c.v := index;
  461.     end;
  462.  
  463.     function LSelectFirstBefore (list: ListHandle; s: str255; getentryname: ProcPtr): boolean;
  464.         var
  465.             i, index: integer;
  466.             c: Cell;
  467.             best, n: str255;
  468.             good: boolean;
  469.     begin
  470.         good := false;
  471.         index := 0;
  472.         best := '';
  473.         for i := 0 to list^^.databounds.bottom - 1 do begin
  474.             c.h := 0;
  475.             c.v := i;
  476.             n := LGetUniqueEntryName(list, c, getentryname);
  477.             if (IUCompString(s, n) > 0) & (IUCompString(n, best) > 0) then begin
  478.                 best := n;
  479.                 index := c.v;
  480.                 good := true;
  481.             end;
  482.         end;
  483.         if good then begin
  484.             LSetSingleSelection(list, index);
  485.         end;
  486.         LSelectFirstBefore := good;
  487.     end;
  488.  
  489.     function LGetLastSelection (list: ListHandle; var c: Cell; getentryname: ProcPtr): boolean;
  490.         var
  491.             best, n: str255;
  492.             index: integer;
  493.     begin
  494.         LGetLastSelection := false;
  495.         c.h := 0;
  496.         c.v := 0;
  497.         best := '';
  498.         while LGetSelect(true, c, list) do begin
  499.             LGetLastSelection := true;
  500.             n := LGetUniqueEntryName(list, c, getentryname);
  501.             if IUCompString(n, best) > 0 then begin
  502.                 index := c.v;
  503.                 best := n;
  504.             end;
  505.             c.v := c.v + 1;
  506.         end;
  507.         c.h := 0;
  508.         c.v := index;
  509.     end;
  510.  
  511.     function LSelectFirstAfter (list: ListHandle; s: str255; getentryname: ProcPtr): boolean;
  512.         var
  513.             i, index: integer;
  514.             c: Cell;
  515.             best, n: str255;
  516.             good: boolean;
  517.     begin
  518.         good := false;
  519.         best := concat(chr(255), chr(255));
  520.         for i := 0 to list^^.databounds.bottom - 1 do begin
  521.             c.h := 0;
  522.             c.v := i;
  523.             n := LGetUniqueEntryName(list, c, getentryname);
  524.             if (IUCompString(s, n) < 0) & (IUCompString(n, best) < 0) then begin
  525.                 best := n;
  526.                 index := c.v;
  527.                 good := true;
  528.             end;
  529.         end;
  530.         if good then begin
  531.             LSetSingleSelection(list, index);
  532.         end;
  533.         LSelectFirstAfter := good;
  534.     end;
  535.  
  536.     procedure DoListKey (list: ListHandle; modifiers: integer; ch: char; getentryname: ProcPtr);
  537.         var
  538.             c: Cell;
  539.             index: integer;
  540.             dummy: boolean;
  541.             curticks: longInt;
  542.     begin
  543.         curticks := TickCount;
  544.         if (typed_lh <> list) or (ch < ' ') then begin
  545.             typed_time := 0;
  546.             typed_lh := list;
  547.         end;
  548.         case ord(ch) of
  549.             downArrowChar:  begin
  550.                 c.h := 0;
  551.                 c.v := 0;
  552.                 index := 0;
  553.                 while LGetSelect(true, c, list) do begin
  554.                     c.v := c.v + 1;
  555.                     index := c.v;
  556.                 end;
  557.                 if index >= list^^.dataBounds.bottom then begin
  558.                     index := list^^.dataBounds.bottom - 1;
  559.                 end;
  560.                 LSetSingleSelection(list, index);
  561.                 LAutoScroll(list);
  562.             end;
  563.             upArrowChar:  begin
  564.                 c.h := 0;
  565.                 c.v := 0;
  566.                 if not LGetSelect(true, c, list) then begin
  567.                     c.v := list^^.dataBounds.bottom;
  568.                 end;
  569.                 if c.v > 0 then begin
  570.                     c.v := c.v - 1;
  571.                 end;
  572.                 LSetSingleSelection(list, c.v);
  573.                 LAutoScroll(list);
  574.             end;
  575.             homeChar:  begin
  576.                 LScroll(0, -list^^.dataBounds.bottom, list);
  577.             end;
  578.             endChar:  begin
  579.                 LScroll(0, list^^.dataBounds.bottom, list);
  580.             end;
  581.             pageUpChar:  begin
  582.                 LScroll(0, -(list^^.visible.bottom - list^^.visible.top - 2), list);
  583.             end;
  584.             pageDownChar:  begin
  585.                 LScroll(0, (list^^.visible.bottom - list^^.visible.top - 2), list);
  586.             end;
  587.             tabChar:  begin
  588.                 if BAND(modifiers, shiftKey) <> 0 then begin
  589.                     if not LGetFirstSelection(list, c, getentryname) | not LSelectFirstBefore(list, LGetUniqueEntryName(list, c, getentryname), getentryname) then begin
  590.                         dummy := LSelectFirstBefore(list, chr(255), getentryname);
  591.                     end;
  592.                 end
  593.                 else begin
  594.                     if not LGetLastSelection(list, c, getentryname) | not LSelectFirstAfter(list, LGetUniqueEntryName(list, c, getentryname), getentryname) then begin
  595.                         dummy := LSelectFirstAfter(list, '', getentryname);
  596.                     end;
  597.                 end;
  598.             end;
  599.             otherwise begin
  600.                 if ch >= ' ' then begin
  601.                     if curticks - typed_time > 60 then begin
  602.                         typed_chars := '';
  603.                     end;
  604.                     typed_time := curticks;
  605.                     typed_chars := concat(typed_chars, ch);
  606.                     if not LSelectFirstAfter(list, typed_chars, getentryname) then begin
  607.                         dummy := LSelectFirstBefore(list, chr(255), getentryname);
  608.                     end;
  609.                 end;
  610.             end;
  611.         end;
  612.     end;
  613.  
  614.     function DecStr (l: longint): Str255;
  615.     begin
  616.         DecStr := StringOf(l : 1);
  617.     end; (* DecStr *)
  618.  
  619.     function GetDirName (fs: FSSpec): OSErr;
  620.         var
  621.             pb: CInfoPBRec;
  622.     begin
  623.         pb.ioNamePtr := @fs.name;
  624.         pb.ioVRefNum := fs.vRefNum;
  625.         pb.ioDirID := fs.parID;
  626.         pb.ioFDirIndex := -1;    {* get information about ioDirID *}
  627.         GetDirName := PBGetCatInfoSync(@pb);
  628.     end;
  629.  
  630.     function CopyFork (srn, drn: integer; len: longInt): OSErr;
  631.         var
  632.             err: OSErr;
  633.             p: ptr;
  634.             size: longInt;
  635.             count: longInt;
  636.     begin
  637.         err := noErr;
  638.         size := 65536;
  639.         p := nil;
  640.         repeat
  641.             p := NewPtr(size);
  642.             if p <> nil then begin
  643.                 size := size div 2;
  644.             end;
  645.         until (p <> nil) or (size < 512);
  646.         if p = nil then begin
  647.             err := memFullErr;
  648.         end;
  649.         while (err = noErr) & (len > 0) do begin
  650.             count := size;
  651.             if count > len then begin
  652.                 count := len;
  653.             end;
  654.             err := FSRead(srn, count, p);
  655.             if (err = noErr) & (count = 0) then begin
  656.                 err := eofErr;
  657.             end;
  658.             if err = noErr then begin
  659.                 len := len - count;
  660.                 err := FSWrite(drn, count, p);
  661.             end;
  662.         end;
  663.         if p <> nil then begin
  664.             DisposePtr(p);
  665.         end;
  666.         CopyFork := err;
  667.     end;
  668.  
  669.     function CopyFile (source, dest: FSSpec): OSErr;
  670.         var
  671.             err, oerr, junk: OSErr;
  672.             pb: CInfoPBRec;
  673.             srrn, sdrn, drrn, ddrn: integer;
  674.     begin
  675.         junk := HDelete(dest.vRefNum, dest.parID, dest.name);
  676.         err := FSpGetCatInfo(source, 0, pb);
  677.         if err = noErr then begin
  678.             err := HCreate(dest.vRefNum, dest.parID, dest.name, pb.ioFlFndrInfo.fdCreator, pb.ioFlFndrInfo.fdType);
  679.             if err = noErr then begin
  680.                 err := HOpen(dest.vRefNum, dest.parID, dest.name, fsWrPerm, ddrn);
  681.                 if err = noErr then begin
  682.                     err := HOpenRF(dest.vRefNum, dest.parID, dest.name, fsWrPerm, drrn);
  683.                     if err = noErr then begin
  684.                         err := HOpen(source.vRefNum, source.parID, source.name, fsRdPerm, sdrn);
  685.                         if err = noErr then begin
  686.                             err := HOpenRF(source.vRefNum, source.parID, source.name, fsRdPerm, srrn);
  687.                             if err = noErr then begin
  688.                                 err := CopyFork(sdrn, ddrn, pb.ioFlLgLen);
  689.                                 if err = noErr then begin
  690.                                     err := CopyFork(srrn, drrn, pb.ioFlRLgLen);
  691.                                 end;
  692.                                 junk := FSClose(srrn);
  693.                             end;
  694.                             junk := FSClose(sdrn);
  695.                         end;
  696.                         oerr := FSClose(drrn);
  697.                         if err = noErr then begin
  698.                             err := oerr;
  699.                         end;
  700.                     end;
  701.                     oerr := FSClose(ddrn);
  702.                     if err = noErr then begin
  703.                         err := oerr;
  704.                     end;
  705.                 end;
  706.             end;
  707.         end;
  708.         if err <> noErr then begin
  709.             junk := HDelete(dest.vRefNum, dest.parID, dest.name);
  710.         end;
  711.         CopyFile := err;
  712.     end; (* CopyFile *)
  713.  
  714.     function GetName (id1, id2: integer): str255;
  715.         var
  716.             sh: stringHandle;
  717.     begin
  718.         sh := GetString(id1);
  719.         if sh = nil then
  720.             sh := GetString(id2);
  721.         if sh <> nil then
  722.             GetName := sh^^ { Don't release it, someone else may be using it }
  723.         else
  724.             GetName := 'unnamed';
  725.     end;
  726.  
  727.     function GetOwnerName: str255;
  728.     begin
  729.         GetOwnerName := GetName(owner_id, machine_id);
  730.     end;
  731.  
  732.     function GetMachineName: str255;
  733.     begin
  734.         GetMachineName := GetName(machine_id, owner_id);
  735.     end;
  736.  
  737. end.
  738. function CopyFile (source, dest: FSSpec): OSErr;
  739.     var
  740.         err: OSErr;
  741.         destdir: FSSpec;
  742.         pb: CInfoPBRec;
  743.         tmpfss: FSSpec;
  744. begin
  745.     err := HDelete(dest.vRefNum, dest.parID, dest.name);
  746.     destdir.vRefNum := dest.vRefNum;
  747.     tmpfss := dest;
  748.     err := FSpGetCatInfo(tmpfss, -1, pb);
  749.     if err = noErr then begin
  750.         destdir.parID := pb.ioDrParID;
  751.         err := GetDirName(dest);
  752.     end; (* if *)
  753.     if err = noErr then begin
  754.         err := FileCopy(source.vRefNum, source.parID, source.name, destdir.vRefNum, destdir.parID, @destdir.name, @dest.name, nil, 0, true);
  755.     end; (* if *)
  756.     CopyFile := err;
  757. end; (* CopyFile *)