home *** CD-ROM | disk | FTP | other *** search
/ PC Open 19 / pcopen19.iso / Zipped / CALMIR21.ZIP / SOURCE.ZIP / SRC / REFERENC.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1998-02-20  |  14.9 KB  |  521 lines

  1. {**************************************************************************}
  2. {                                                                          }
  3. {    Calmira shell for Microsoft« Windows(TM) 3.1                          }
  4. {    Source Release 2.1                                                    }
  5. {    Copyright (C) 1997-1998 Li-Hsin Huang                                 }
  6. {                                                                          }
  7. {    This program is free software; you can redistribute it and/or modify  }
  8. {    it under the terms of the GNU General Public License as published by  }
  9. {    the Free Software Foundation; either version 2 of the License, or     }
  10. {    (at your option) any later version.                                   }
  11. {                                                                          }
  12. {    This program is distributed in the hope that it will be useful,       }
  13. {    but WITHOUT ANY WARRANTY; without even the implied warranty of        }
  14. {    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         }
  15. {    GNU General Public License for more details.                          }
  16. {                                                                          }
  17. {    You should have received a copy of the GNU General Public License     }
  18. {    along with this program; if not, write to the Free Software           }
  19. {    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.             }
  20. {                                                                          }
  21. {**************************************************************************}
  22.  
  23. unit Referenc;
  24.  
  25. { TReference is a class used to unify shortcuts and aliases.
  26.   Each shortcut and alias contains a reference object, which points
  27.   to a file, folder or disk drive, and handles most of the action.
  28.  
  29.   There are 5 string properties, which require a lot of memory,
  30.   so instead of using 5 string fields, each property maps to
  31.   a function which assigns and maintains a dynamic string.
  32.   Empty strings don't take up any memory.
  33.  
  34.   BeginUpdate, EndUpdate - ensures that the OnChange event is
  35.     not triggered while the fields are being modified.
  36.  
  37.   Edit - creates a property dialog to edit the reference, executes
  38.     it and returns the result of the edit, either mrOK or mrCancel.
  39.  
  40.   LoadFromStream, SaveToStream - this uses a TStreamer object to
  41.     read and write the reference.
  42.  
  43.   Reference objects do not maintain icons themselves, but have
  44.   an AssignIcon function that sets a TIcon to a suitable image that
  45.   reflects the object.
  46. }
  47.  
  48.  
  49. interface
  50.  
  51. uses Classes, Graphics, SysUtils, IniFiles, Forms, Streamer;
  52.  
  53. type
  54.  
  55. TReferenceKind = (rkDrive, rkFolder, rkFile, rkInternet);
  56.  
  57. TReference = class
  58. private
  59.   FKind : TReferenceKind;
  60.   FShowMode : Integer;
  61.   FUseDocFolder : Boolean;
  62.   FIconIndex : Integer;
  63.   FOnChange : TNotifyEvent;
  64.   FUpdates : Integer;
  65.   FStringBuf : array[0..4] of PString;
  66.   FLeft, FTop : Integer;
  67.   procedure SetKind(value : TReferenceKind);
  68.   procedure SetStringProp(i: Integer; const s: string);
  69.   function GetStringProp(i: Integer): string;
  70. protected
  71.   procedure Change; virtual;
  72.   procedure SetAsLast;
  73. public
  74.   constructor Create;
  75.   destructor Destroy; override;
  76.   procedure Open;
  77.   procedure DragDrop(Source : TObject);
  78.   procedure AcceptFiles(files : TStrings);
  79.   function Edit: TModalResult;
  80.   procedure AssignIcon(Icon : TIcon);
  81.   procedure BeginUpdate;
  82.   procedure EndUpdate;
  83.   procedure LoadFromStream(s : TStreamer);
  84.   procedure SaveToStream(s : TStreamer);
  85.   procedure LoadFromIni(ini : TIniFile; const section: string);
  86.   procedure SaveToIni(ini : TIniFile; const section: string);
  87.   function AssignFromExternal: Boolean;
  88.   property Left : Integer read FLeft write FLeft;
  89.   property Top : Integer read FTop write FTop;
  90.   property Kind : TReferenceKind read FKind write FKind;
  91.   property Target : string index 0 read GetStringProp write SetStringProp;
  92.   property Params : string index 1 read GetStringProp write SetStringProp;
  93.   property WorkingFolder : string index 2 read GetStringProp write SetStringProp;
  94.   property ShowMode : Integer read FShowMode write FShowMode;
  95.   property UseDocFolder : Boolean read FUseDocFolder write FUseDocFolder;
  96.   property Caption : string index 3 read GetStringProp write SetStringProp;
  97.   property IconFile : string index 4 read GetStringProp write SetStringProp;
  98.   property IconIndex : Integer read FIconIndex write FIconIndex;
  99.   property OnChange : TNotifyEvent read FOnChange write FOnChange;
  100. end;
  101.  
  102. { The two subclasses are only used to distinguish between shortcuts
  103.   and aliases at run-time }
  104.  
  105. TShortcutReference = class(TReference);
  106. TAliasReference = class(TReference);
  107.  
  108. var
  109.   { Preset references pointing to a drive, folder or file.  These can be
  110.     used freely, but remember that there is no locking mechanism for
  111.     mutual exclusion }
  112.  
  113.   DriveRef, FolderRef, FileRef : TReference;
  114.  
  115.   { The Lastxxxx variables hold information about the most recent program
  116.     executed.  This is used to provide a suitable icon for the taskbar }
  117. const
  118.   LastInstance : Word = 0;
  119.   LastIconFile : TFilename = '';
  120.   LastIconIndex: Integer = 0;
  121.  
  122.  
  123. implementation
  124.  
  125. uses Controls, IconWin, Desk, Files, RefEdit, Strings, FileFind, MiscUtil,
  126.   WinTypes, ShellAPI, Resource, Drives, WasteBin, FileMan, MultiGrd, Settings,
  127.   FourDOS, TabNotBk, Environs, Clipbrd, FileCtrl, Dialogs, CompSys, Internet,
  128.   WinProcs, Locale;
  129.  
  130.  
  131. constructor TReference.Create;
  132. var i: Integer;
  133. begin
  134.   inherited Create;
  135.   for i := 0 to High(FStringBuf) do FStringBuf[i] := NullStr;
  136. end;
  137.  
  138. destructor TReference.Destroy;
  139. var i: Integer;
  140. begin
  141.   for i := 0 to High(FStringBuf) do DisposeStr(FStringBuf[i]);
  142.   inherited Destroy;
  143. end;
  144.  
  145.  
  146. procedure TReference.SetStringProp(i: Integer; const s: string);
  147. begin
  148.   if FStringBuf[i]^ <> s then begin
  149.     AssignStr(FStringBuf[i], s);
  150.     if i = 3 then Change;  { caption field }
  151.   end;
  152. end;
  153.  
  154. function TReference.GetStringProp(i: Integer): string;
  155. begin
  156.   Result := FStringBuf[i]^;
  157. end;
  158.  
  159.  
  160. procedure TReference.Open;
  161. begin
  162.   case Kind of
  163.     rkDrive, rkFolder :
  164.       Desktop.OpenFolderRefresh(ExpandFoldername(EnvironSubst(Target), WinPath[1]));
  165.     rkFile  :
  166.       begin
  167.         SetAsLast;
  168.         LastInstance := DefaultExec(Target, Params, WorkingFolder,
  169.           ShowCmdsEx(ShowMode));
  170.       end;
  171.     rkInternet : DefaultExec(Target, '', '', SW_SHOW);
  172.   end;
  173. end;
  174.  
  175.  
  176. procedure TReference.DragDrop(Source : TObject);
  177. var
  178.   f, win : TIconWindow;
  179.   files: TStringList;
  180. begin
  181.   if Source is TMultiGrid then begin
  182.     win := TMultiGrid(Source).Owner as TIconWindow;
  183.  
  184.     if Kind in [rkDrive, rkFolder] then begin
  185.  
  186.       if GetAsyncKeyState(VK_SHIFT) < 0 then begin
  187.         win.DropAsAliases(Target);
  188.         Exit;
  189.       end;
  190.  
  191.       f := Desktop.WindowOf(Target);
  192.       if f = nil then begin
  193.         { Since there is no TDirectory to transfer file descriptions
  194.           to, a separate object must be used to load them }
  195.  
  196.         if UseDescriptions then
  197.           SharedDesc.LoadFromPath(MakePath(Target));
  198.         try
  199.           win.DropInFolder(Target);
  200.         finally
  201.           if UseDescriptions then
  202.             SharedDesc.SaveToPath(MakePath(Target));
  203.         end;
  204.       end
  205.       else win.DropInWindow(f.Dir);
  206.     end
  207.     else begin
  208.       files := win.CompileFilenames;
  209.       try AcceptFiles(files);
  210.       finally files.Free;
  211.       end;
  212.     end;
  213.   end
  214.  
  215.   else if (Source = Bin.Listbox) and (Kind <> rkFile) then
  216.     Bin.RestoreTo(MakeDirname(Target))
  217.  
  218.   else if Source = FindList then
  219.     AcceptFiles(FindForm.CompileSelection)
  220.  
  221.   else if Source is TStrings then
  222.     AcceptFiles(TStrings(Source));
  223. end;
  224.  
  225.  
  226. procedure TReference.AcceptFiles(files : TStrings);
  227. var
  228.   i : Integer;
  229.   d : TFilename;
  230.   p : string;
  231. begin
  232.   if Kind in [rkFolder, rkDrive] then
  233.     { This should only be used to handle file drops from other programs,
  234.       since file descriptions are not updated.  TIconWindow has
  235.       DropInWindow and DropInFolder methods to handle normal file transfer. }
  236.  
  237.     ProcessFiles(files, Target)
  238.  
  239.   else begin
  240.     { Drop files into a program }
  241.  
  242.     p := Params;
  243.  
  244.     if UseDocFolder and (Files.Count > 0) then begin
  245.       { Get rid of the pathnames }
  246.       d := ExtractFileDir(files[0]);
  247.       for i := 0 to files.Count-1 do
  248.         files[i] := ExtractFilename(files[i]);
  249.     end
  250.     else d := WorkingFolder;
  251.  
  252.     { If no drop position is specified, add them to the end of the params }
  253.  
  254.     if Pos('%DROPPEDFILES%', Uppercase(params)) = 0 then
  255.       AppendStr(p, ' %DROPPEDFILES%');
  256.  
  257.     Environment.Values['DROPPEDFILES'] := FileParams(files);
  258.  
  259.     LastInstance := DefaultExec(Target, p, d, ShowCmdsEx(ShowMode));
  260.  
  261.     if LastInstance <= 32 then
  262.       ErrorMsgResFmt(SCannotOpenTarget, [Target])
  263.     else
  264.       SetAsLast;
  265.  
  266.     Environment.Values['DROPPEDFILES'] := '';
  267.   end;
  268. end;
  269.  
  270.  
  271.  
  272. procedure TReference.AssignIcon(Icon : TIcon);
  273. var
  274.   h: HIcon;
  275.   s : TFilename;
  276.  
  277. procedure AssignDefault;
  278. var ext : string[3];
  279. begin
  280.   s := EnvironSubst(Target);
  281.   case Kind of
  282.     rkDrive  : Icon.Assign(icons.Drive[GuessDriveType(s[1])]);
  283.     rkFolder : Icon.Assign(foldericon);
  284.     rkFile   : begin
  285.                  ext := Copy(ExtractFileExt(s), 2, 3);
  286.                  if ExtensionIn(ext, IconStrings) then begin
  287.                    h := ExtractIcon(HInstance, StringAsPChar(s), 0);
  288.                    if h > 1 then Icon.Handle := h
  289.                    else if ExtensionIn(ext, programs) then
  290.                      case h of
  291.                        0 : Icon.Assign(WindowsIcon);
  292.                        1 : Icon.Assign(DOSIcon);
  293.                      end
  294.                    else
  295.                      Icon.Assign(icons.Get(ext))
  296.                  end
  297.                  else
  298.                    Icon.Assign(icons.Get(ext));
  299.                end;
  300.     rkInternet: Icon.Assign(icons.Get('Internet'));
  301.   end;
  302. end;
  303.  
  304. begin
  305.   if IconFile > '' then begin
  306.     s := EnvironSubst(IconFile);
  307.     h := ExtractIcon(HInstance, StringAsPChar(s), IconIndex);
  308.     if h > 1 then Icon.Handle := h
  309.     else AssignDefault;
  310.   end
  311.   else AssignDefault;
  312. end;
  313.  
  314.  
  315. procedure TReference.BeginUpdate;
  316. begin
  317.   Inc(FUpdates);
  318. end;
  319.  
  320. procedure TReference.EndUpdate;
  321. begin
  322.   if FUpdates > 0 then begin
  323.     Dec(FUpdates);
  324.     if FUpdates = 0 then Change;
  325.   end;
  326. end;
  327.  
  328.  
  329. procedure TReference.SetKind(value : TReferenceKind);
  330. begin
  331.   Kind := value;
  332.   Change;
  333. end;
  334.  
  335.  
  336. procedure TReference.Change;
  337. begin
  338.   if (FUpdates = 0) and Assigned(FOnChange) then FOnChange(self);
  339. end;
  340.  
  341.  
  342. function TReference.Edit: TModalResult;
  343. const
  344.   Captions : array[Boolean] of Word = (SShortcutProperties, SAliasProperties);
  345. var
  346.   buf: TFilename;
  347. begin
  348.   ShowHourglass;
  349.   Result := mrCancel;
  350.  
  351.   RefEditDlg := TRefEditDlg.Create(Application);
  352.  
  353.   with RefEditDlg do begin
  354.  
  355.   Caption := LoadStr(Captions[self is TAliasReference]);
  356.  
  357.   RefKind := Kind;
  358.   TargetEdit.Text := Target;
  359.   CapEdit.Text := self.Caption;
  360.   if IconFile > '' then
  361.     IconEdit.Text := Format('%s(%d)', [IconFile, IconIndex]);
  362.  
  363.   if Kind = rkFile then begin
  364.     ParamEdit.Text := Params;
  365.     FolderEdit.Text := WorkingFolder;
  366.     ShowGroup.ItemIndex := ShowMode;
  367.     DocFolder.Checked := UseDocFolder;
  368.   end;
  369.  
  370.   try
  371.     if ShowModal = mrOK then begin
  372.       Result := mrOK;
  373.       Kind := RefKind;
  374.       Target := TargetEdit.Text;
  375.       self.Caption := CapEdit.Text;
  376.  
  377.       IconFile := ExtractIconFile(IconEdit.Text);
  378.       IconIndex := ExtractIconIndex(IconEdit.Text);
  379.  
  380.       if Kind = rkFile then begin
  381.         Params := ParamEdit.Text;
  382.         WorkingFolder := FolderEdit.Text;
  383.         ShowMode := ShowGroup.ItemIndex;
  384.         UseDocFolder := DocFolder.Checked;
  385.       end;
  386.       Change;
  387.     end;
  388.   finally
  389.     RefEditDlg.Free;
  390.     RefEditDlg := nil;
  391.   end;
  392.   end;
  393. end;
  394.  
  395.  
  396. procedure TReference.SetAsLast;
  397. begin
  398.   LastIconFile := IconFile;
  399.   LastIconIndex := IconIndex;
  400. end;
  401.  
  402.  
  403. procedure TReference.LoadFromStream(s : TStreamer);
  404. begin
  405.   BeginUpdate;
  406.   with s do begin
  407.     FLeft := ReadInteger;
  408.     FTop := ReadInteger;
  409.     Kind := TReferenceKind(ReadInteger);
  410.     Target := ReadString;
  411.     Caption := ReadString;
  412.     IconFile := ReadString;
  413.     IconIndex := ReadInteger;
  414.     Params := ReadString;
  415.     WorkingFolder := ReadString;
  416.     ShowMode := ReadInteger;
  417.     UseDocFolder := ReadBoolean;
  418.   end;
  419.   EndUpdate;
  420. end;
  421.  
  422.  
  423. procedure TReference.SaveToStream(s: TStreamer);
  424. begin
  425.   with s do begin
  426.     WriteInteger(FLeft);
  427.     WriteInteger(FTop);
  428.     WriteInteger(Integer(Kind));
  429.     WriteString(Target);
  430.     WriteString(Caption);
  431.     WriteString(IconFile);
  432.     WriteInteger(IconIndex);
  433.     WriteString(Params);
  434.     WriteString(WorkingFolder);
  435.     WriteInteger(ShowMode);
  436.     WriteBoolean(UseDocFolder);
  437.   end;
  438. end;
  439.  
  440.  
  441. procedure TReference.LoadFromIni(ini : TIniFile; const section: string);
  442. begin
  443.   BeginUpdate;
  444.   with ini do begin
  445.     Kind := TReferenceKind(ini.ReadInteger(section, 'Kind', 0));
  446.     Target := ReadString(section, 'Target', 'c:\');
  447.     Caption := ReadString(section, 'Caption', 'Drive C:');
  448.     IconFile := ReadString(section, 'IconFile', '');
  449.     IconIndex := ReadInteger(section, 'IconIndex', 0);
  450.     Params := ReadString(section, 'Params', '');
  451.     WorkingFolder := ReadString(section, 'WorkingFolder', '');
  452.     ShowMode := ReadInteger(section, 'ShowMode', 0);
  453.     UseDocFolder := ReadBool(section, 'UseDocFolder', True);
  454.  end;
  455.  EndUpdate;
  456. end;
  457.  
  458.  
  459. procedure TReference.SaveToIni(ini : TIniFile; const section: string);
  460. begin
  461.   with ini do begin
  462.     WriteInteger(section, 'Kind', Integer(Kind));
  463.     WriteString(section, 'Target', Target);
  464.     WriteString(section, 'Caption', Caption);
  465.     WriteString(section, 'IconFile', IconFile);
  466.     WriteInteger(section, 'IconIndex', IconIndex);
  467.     WriteString(section, 'Params', Params);
  468.     WriteString(section, 'WorkingFolder', WorkingFolder);
  469.     WriteInteger(section, 'ShowMode', ShowMode);
  470.     WriteBool(section, 'UseDocFolder', UseDocFolder);
  471.   end;
  472. end;
  473.  
  474.  
  475.  
  476.  
  477. function TReference.AssignFromExternal: Boolean;
  478. var
  479.   location, url: string;
  480. begin
  481.   if (Kind = rkInternet) and
  482.     Computer.BrowserLink.CaptureLocation(location, url) then begin
  483.     Caption := location;
  484.     Target := url;
  485.   end
  486.   else if ClipBoard.HasFormat(CF_TEXT) then
  487.     Target := Lowercase(Clipboard.AsText)
  488.   else
  489.     Target := '';
  490.  
  491.   case Kind of
  492.     rkDrive    : Result := IsDriveString(Target);
  493.     rkFolder   : Result := HDirectoryExists(Target);
  494.     rkFile     : Result := FileExists(Target);
  495.     rkInternet : Result := IsURL(Target);
  496.   end;
  497.  
  498.   if not Result then Target := '';
  499.  
  500.   Result := (Edit = mrOK) and ((Kind <> rkFolder) or
  501.     (HDirectoryExists(Target) or (ConfirmFolder(Target) <> mrCancel)));
  502. end;
  503.  
  504.  
  505.  
  506. procedure DoneReference; far;
  507. begin
  508.   FolderRef.Free;
  509.   FileRef.Free;
  510. end;
  511.  
  512. initialization
  513.   AddExitProc(DoneReference);
  514.  
  515.   FolderRef := TReference.Create;
  516.   FolderRef.Kind := rkFolder;
  517.  
  518.   FileRef := TReference.Create;
  519.   FileRef.Kind := rkFile;
  520. end.c
  521.