123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745 |
- {*******************************************************}
- { Free Vision Runtime Library }
- { StdDlg Unit }
- { Version: 0.1.0 }
- { Release Date: July 23, 1998 }
- { }
- {*******************************************************}
- { }
- { This unit is a port of Borland International's }
- { StdDlg.pas unit. It is for distribution with the }
- { Free Pascal (FPK) Compiler as part of the 32-bit }
- { Free Vision library. The unit is still fully }
- { functional under BP7 by using the tp compiler }
- { directive when rebuilding the library. }
- { }
- {*******************************************************}
- { Revision History
- 1.1a (97/12/29)
- - fixed bug in TFileDialog.HandleEvent that prevented the user from being
- able to have an action taken automatically when the FileList was
- selected and kbEnter pressed
- 1.1
- - modified OpenNewFile to take a history list ID
- - implemented OpenNewFile
- 1.0 (1992)
- - original implementation }
- unit StdDlg;
- {
- This unit has been modified to make some functions global, apply patches
- from version 3.1 of the TVBUGS list, added TEditChDirDialog, and added
- several new global functions and procedures.
- }
- {$i platform.inc}
- {$ifdef PPC_FPC}
- {$H-}
- {$else}
- {$F+,O+,E+,N+}
- {$endif}
- {$X+,R-,I-,Q-,V-}
- {$ifndef OS_UNIX}
- {$S-}
- {$endif}
- {$ifdef OS_DOS}
- {$define HAS_DOS_DRIVES}
- {$endif}
- {$ifdef OS_WINDOWS}
- {$define HAS_DOS_DRIVES}
- {$endif}
- {$ifdef OS_OS2}
- {$define HAS_DOS_DRIVES}
- {$endif}
- interface
- uses
- FVConsts, Objects, Drivers, Views, Dialogs, Validate, Dos;
- const
- {$ifdef PPC_FPC}
- MaxDir = 255; { Maximum length of a DirStr. }
- MaxFName = 255; { Maximum length of a FNameStr. }
- {$ifdef OS_Unix}
- DirSeparator : Char = '/';
- {$else}
- DirSeparator : Char = '\';
- {$endif}
- {$else}
- MaxDir = 67; { Maximum length of a DirStr. }
- MaxFName = 79; { Maximum length of a FNameStr. }
- DirSeparator: Char = '\';
- {$endif}
- type
- { TSearchRec }
- { Record used to store directory information by TFileDialog
- This is a part of Dos.Searchrec for Bp !! }
- TSearchRec = packed record
- Attr: Longint;
- Time: Longint;
- Size: Longint;
- {$ifdef PPC_FPC}
- Name: string[255];
- {$else not PPC_FPC}
- Name: string[12];
- {$endif not PPC_FPC}
- end;
- PSearchRec = ^TSearchRec;
- type
- { TFileInputLine is a special input line that is used by }
- { TFileDialog that will update its contents in response to a }
- { cmFileFocused command from a TFileList. }
- PFileInputLine = ^TFileInputLine;
- TFileInputLine = object(TInputLine)
- constructor Init(var Bounds: TRect; AMaxLen: Sw_Integer);
- procedure HandleEvent(var Event: TEvent); virtual;
- end;
- { TFileCollection is a collection of TSearchRec's. }
- PFileCollection = ^TFileCollection;
- TFileCollection = object(TSortedCollection)
- function Compare(Key1, Key2: Pointer): Sw_Integer; virtual;
- procedure FreeItem(Item: Pointer); virtual;
- function GetItem(var S: TStream): Pointer; virtual;
- procedure PutItem(var S: TStream; Item: Pointer); virtual;
- end;
- {#Z+}
- PFileValidator = ^TFileValidator;
- {#Z-}
- TFileValidator = Object(TValidator)
- end; { of TFileValidator }
- { TSortedListBox is a TListBox that assumes it has a }
- { TStoredCollection instead of just a TCollection. It will }
- { perform an incremental search on the contents. }
- PSortedListBox = ^TSortedListBox;
- TSortedListBox = object(TListBox)
- SearchPos: Byte;
- {ShiftState: Byte;}
- HandleDir : boolean;
- constructor Init(var Bounds: TRect; ANumCols: Sw_Word;
- AScrollBar: PScrollBar);
- procedure HandleEvent(var Event: TEvent); virtual;
- function GetKey(var S: String): Pointer; virtual;
- procedure NewList(AList: PCollection); virtual;
- end;
- { TFileList is a TSortedList box that assumes it contains }
- { a TFileCollection as its collection. It also communicates }
- { through broadcast messages to TFileInput and TInfoPane }
- { what file is currently selected. }
- PFileList = ^TFileList;
- TFileList = object(TSortedListBox)
- constructor Init(var Bounds: TRect; AScrollBar: PScrollBar);
- destructor Done; virtual;
- function DataSize: Sw_Word; virtual;
- procedure FocusItem(Item: Sw_Integer); virtual;
- procedure GetData(var Rec); virtual;
- function GetText(Item,MaxLen: Sw_Integer): String; virtual;
- function GetKey(var S: String): Pointer; virtual;
- procedure HandleEvent(var Event: TEvent); virtual;
- procedure ReadDirectory(AWildCard: PathStr);
- procedure SetData(var Rec); virtual;
- end;
- { TFileInfoPane is a TView that displays the information }
- { about the currently selected file in the TFileList }
- { of a TFileDialog. }
- PFileInfoPane = ^TFileInfoPane;
- TFileInfoPane = object(TView)
- S: TSearchRec;
- constructor Init(var Bounds: TRect);
- procedure Draw; virtual;
- function GetPalette: PPalette; virtual;
- procedure HandleEvent(var Event: TEvent); virtual;
- end;
- { TFileDialog is a standard file name input dialog }
- TWildStr = PathStr;
- const
- fdOkButton = $0001; { Put an OK button in the dialog }
- fdOpenButton = $0002; { Put an Open button in the dialog }
- fdReplaceButton = $0004; { Put a Replace button in the dialog }
- fdClearButton = $0008; { Put a Clear button in the dialog }
- fdHelpButton = $0010; { Put a Help button in the dialog }
- fdNoLoadDir = $0100; { Do not load the current directory }
- { contents into the dialog at Init. }
- { This means you intend to change the }
- { WildCard by using SetData or store }
- { the dialog on a stream. }
- type
- PFileHistory = ^TFileHistory;
- TFileHistory = object(THistory)
- CurDir : PString;
- procedure HandleEvent(var Event: TEvent);virtual;
- destructor Done; virtual;
- procedure AdaptHistoryToDir(Dir : string);
- end;
- PFileDialog = ^TFileDialog;
- TFileDialog = object(TDialog)
- FileName: PFileInputLine;
- FileList: PFileList;
- FileHistory: PFileHistory;
- WildCard: TWildStr;
- Directory: PString;
- constructor Init(AWildCard: TWildStr; const ATitle,
- InputName: String; AOptions: Word; HistoryId: Byte);
- constructor Load(var S: TStream);
- destructor Done; virtual;
- procedure GetData(var Rec); virtual;
- procedure GetFileName(var S: PathStr);
- procedure HandleEvent(var Event: TEvent); virtual;
- procedure SetData(var Rec); virtual;
- procedure Store(var S: TStream);
- function Valid(Command: Word): Boolean; virtual;
- private
- procedure ReadDirectory;
- end;
- { TDirEntry }
- PDirEntry = ^TDirEntry;
- TDirEntry = record
- DisplayText: PString;
- Directory: PString;
- end; { of TDirEntry }
- { TDirCollection is a collection of TDirEntry's used by }
- { TDirListBox. }
- PDirCollection = ^TDirCollection;
- TDirCollection = object(TCollection)
- function GetItem(var S: TStream): Pointer; virtual;
- procedure FreeItem(Item: Pointer); virtual;
- procedure PutItem(var S: TStream; Item: Pointer); virtual;
- end;
- { TDirListBox displays a tree of directories for use in the }
- { TChDirDialog. }
- PDirListBox = ^TDirListBox;
- TDirListBox = object(TListBox)
- Dir: DirStr;
- Cur: Word;
- constructor Init(var Bounds: TRect; AScrollBar: PScrollBar);
- destructor Done; virtual;
- function GetText(Item,MaxLen: Sw_Integer): String; virtual;
- procedure HandleEvent(var Event: TEvent); virtual;
- function IsSelected(Item: Sw_Integer): Boolean; virtual;
- procedure NewDirectory(var ADir: DirStr);
- procedure SetState(AState: Word; Enable: Boolean); virtual;
- end;
- { TChDirDialog is a standard change directory dialog. }
- const
- cdNormal = $0000; { Option to use dialog immediately }
- cdNoLoadDir = $0001; { Option to init the dialog to store on a stream }
- cdHelpButton = $0002; { Put a help button in the dialog }
- type
- PChDirDialog = ^TChDirDialog;
- TChDirDialog = object(TDialog)
- DirInput: PInputLine;
- DirList: PDirListBox;
- OkButton: PButton;
- ChDirButton: PButton;
- constructor Init(AOptions: Word; HistoryId: Sw_Word);
- constructor Load(var S: TStream);
- function DataSize: Sw_Word; virtual;
- procedure GetData(var Rec); virtual;
- procedure HandleEvent(var Event: TEvent); virtual;
- procedure SetData(var Rec); virtual;
- procedure Store(var S: TStream);
- function Valid(Command: Word): Boolean; virtual;
- private
- procedure SetUpDialog;
- end;
- PEditChDirDialog = ^TEditChDirDialog;
- TEditChDirDialog = Object(TChDirDialog)
- { TEditChDirDialog allows setting/getting the starting directory. The
- transfer record is a DirStr. }
- function DataSize : Sw_Word; virtual;
- procedure GetData (var Rec); virtual;
- procedure SetData (var Rec); virtual;
- end; { of TEditChDirDialog }
- {#Z+}
- PDirValidator = ^TDirValidator;
- {#Z-}
- TDirValidator = Object(TFilterValidator)
- constructor Init;
- function IsValid(const S: string): Boolean; virtual;
- function IsValidInput(var S: string; SuppressFill: Boolean): Boolean;
- virtual;
- end; { of TDirValidator }
- FileConfirmFunc = function (AFile : FNameStr) : Boolean;
- { Functions of type FileConfirmFunc's are used to prompt the end user for
- confirmation of an operation.
- FileConfirmFunc's should ask the user whether to perform the desired
- action on the file named AFile. If the user elects to perform the
- function FileConfirmFunc's return True, otherwise they return False.
- Using FileConfirmFunc's allows routines to be coded independant of the
- user interface implemented. OWL and TurboVision are supported through
- conditional defines. If you do not use either user interface you must
- compile this unit with the conditional define cdNoMessages and set all
- FileConfirmFunc variables to a valid function prior to calling any
- routines in this unit. }
- {#X ReplaceFile DeleteFile }
- var
- ReplaceFile : FileConfirmFunc;
- { ReplaceFile returns True if the end user elects to replace the existing
- file with the new file, otherwise it returns False.
- ReplaceFile is only called when #CheckOnReplace# is True. }
- {#X DeleteFile }
- DeleteFile : FileConfirmFunc;
- { DeleteFile returns True if the end user elects to delete the file,
- otherwise it returns False.
- DeleteFile is only called when #CheckOnDelete# is True. }
- {#X ReplaceFile }
- const
- CInfoPane = #30;
- { TStream registration records }
- function Contains(S1, S2: String): Boolean;
- { Contains returns true if S1 contains any characters in S2. }
- function DriveValid(Drive: Char): Boolean;
- { DriveValid returns True if Drive is a valid DOS drive. Drive valid works
- by attempting to change the current directory to Drive, then restoring
- the original directory. }
- function ExtractDir(AFile: FNameStr): DirStr;
- { ExtractDir returns the path of AFile terminated with a trailing '\'. If
- AFile contains no directory information, an empty string is returned. }
- function ExtractFileName(AFile: FNameStr): NameStr;
- { ExtractFileName returns the file name without any directory or file
- extension information. }
- function Equal(const S1, S2: String; Count: Sw_word): Boolean;
- { Equal returns True if S1 equals S2 for up to Count characters. Equal is
- case-insensitive. }
- function FileExists (AFile : FNameStr) : Boolean;
- { FileExists looks for the file specified in AFile. If AFile is present
- FileExists returns true, otherwise FileExists returns False.
- The search is performed relative to the current system directory, but
- other directories may be searched by prefacing a file name with a valid
- directory path.
- There is no check for a vaild file name or drive. Errrors are handled
- internally and not reported in DosError. Critical errors are left to
- the system's critical error handler. }
- {#X OpenFile }
- function GetCurDir: DirStr;
- { GetCurDir returns the current directory. The directory returned always
- ends with a trailing backslash '\'. }
- function GetCurDrive: Char;
- { GetCurDrive returns the letter of the current drive as reported by the
- operating system. }
- function IsWild(const S: String): Boolean;
- { IsWild returns True if S contains a question mark (?) or asterix (*). }
- function IsList(const S: String): Boolean;
- { IsList returns True if S contains list separator (;) char }
- function IsDir(const S: String): Boolean;
- { IsDir returns True if S is a valid DOS directory. }
- procedure MakeResources;
- { MakeResources places a language specific version of all resources
- needed for the StdDlg unit to function on the RezFile using the string
- constants and variables in the Resource unit. The Resource unit and the
- appropriate string lists must be initialized prior to calling this
- procedure. }
- function NoWildChars(S: String): String;
- { NoWildChars deletes the wild card characters ? and * from the string S
- and returns the result. }
- function OpenFile (var AFile : FNameStr; HistoryID : Byte) : Boolean;
- { OpenFile prompts the user to select a file using the file specifications
- in AFile as the starting file and path. Wildcards are accepted. If the
- user accepts a file OpenFile returns True, otherwise OpenFile returns
- False.
- Note: The file returned may or may not exist. }
- function OpenNewFile (var AFile: FNameStr; HistoryID: Byte): Boolean;
- { OpenNewFile allows the user to select a directory from disk and enter a
- new file name. If the file name entered is an existing file the user is
- optionally prompted for confirmation of replacing the file based on the
- value in #CheckOnReplace#. If a file name is successfully entered,
- OpenNewFile returns True. }
- {#X OpenFile }
- function PathValid(var Path: PathStr): Boolean;
- { PathValid returns True if Path is a valid DOS path name. Path may be a
- file or directory name. Trailing '\'s are removed. }
- procedure RegisterStdDlg;
- { RegisterStdDlg registers all objects in the StdDlg unit for stream
- usage. }
- function SaveAs (var AFile : FNameStr; HistoryID : Word) : Boolean;
- { SaveAs prompts the user for a file name using AFile as a template. If
- AFile already exists and CheckOnReplace is True, the user is prompted
- to replace the file.
- If a valid file name is entered SaveAs returns True, other SaveAs returns
- False. }
- function SelectDir (var ADir : DirStr; HistoryID : Byte) : Boolean;
- { SelectDir prompts the user to select a directory using ADir as the
- starting directory. If a directory is selected, SelectDir returns True.
- The directory returned is gauranteed to exist. }
- function ShrinkPath (AFile : FNameStr; MaxLen : Byte) : FNameStr;
- { ShrinkPath returns a file name with a maximu length of MaxLen.
- Internal directories are removed and replaced with elipses as needed to
- make the file name fit in MaxLen.
- AFile must be a valid path name. }
- function StdDeleteFile (AFile : FNameStr) : Boolean;
- { StdDeleteFile returns True if the end user elects to delete the file,
- otherwise it returns False.
- DeleteFile is only called when CheckOnDelete is True. }
- function StdReplaceFile (AFile : FNameStr) : Boolean;
- { StdReplaceFile returns True if the end user elects to replace the existing
- AFile with the new AFile, otherwise it returns False.
- ReplaceFile is only called when CheckOnReplace is True. }
- function ValidFileName(var FileName: PathStr): Boolean;
- { ValidFileName returns True if FileName is a valid DOS file name. }
- const
- CheckOnReplace : Boolean = True;
- { CheckOnReplace is used by file functions. If a file exists, it is
- optionally replaced based on the value of CheckOnReplace.
- If CheckOnReplace is False the file is replaced without asking the
- user. If CheckOnReplace is True, the end user is asked to replace the
- file using a call to ReplaceFile.
- CheckOnReplace is set to True by default. }
- CheckOnDelete : Boolean = True;
- { CheckOnDelete is used by file and directory functions. If a file
- exists, it is optionally deleted based on the value of CheckOnDelete.
- If CheckOnDelete is False the file or directory is deleted without
- asking the user. If CheckOnDelete is True, the end user is asked to
- delete the file/directory using a call to DeleteFile.
- CheckOnDelete is set to True by default. }
- const
- RFileInputLine: TStreamRec = (
- ObjType: idFileInputLine;
- VmtLink: Ofs(TypeOf(TFileInputLine)^);
- Load: @TFileInputLine.Load;
- Store: @TFileInputLine.Store
- );
- RFileCollection: TStreamRec = (
- ObjType: idFileCollection;
- VmtLink: Ofs(TypeOf(TFileCollection)^);
- Load: @TFileCollection.Load;
- Store: @TFileCollection.Store
- );
- RFileList: TStreamRec = (
- ObjType: idFileList;
- VmtLink: Ofs(TypeOf(TFileList)^);
- Load: @TFileList.Load;
- Store: @TFileList.Store
- );
- RFileInfoPane: TStreamRec = (
- ObjType: idFileInfoPane;
- VmtLink: Ofs(TypeOf(TFileInfoPane)^);
- Load: @TFileInfoPane.Load;
- Store: @TFileInfoPane.Store
- );
- RFileDialog: TStreamRec = (
- ObjType: idFileDialog;
- VmtLink: Ofs(TypeOf(TFileDialog)^);
- Load: @TFileDialog.Load;
- Store: @TFileDialog.Store
- );
- RDirCollection: TStreamRec = (
- ObjType: idDirCollection;
- VmtLink: Ofs(TypeOf(TDirCollection)^);
- Load: @TDirCollection.Load;
- Store: @TDirCollection.Store
- );
- RDirListBox: TStreamRec = (
- ObjType: idDirListBox;
- VmtLink: Ofs(TypeOf(TDirListBox)^);
- Load: @TDirListBox.Load;
- Store: @TDirListBox.Store
- );
- RChDirDialog: TStreamRec = (
- ObjType: idChDirDialog;
- VmtLink: Ofs(TypeOf(TChDirDialog)^);
- Load: @TChDirDialog.Load;
- Store: @TChDirDialog.Store
- );
- RSortedListBox: TStreamRec = (
- ObjType: idSortedListBox;
- VmtLink: Ofs(TypeOf(TSortedListBox)^);
- Load: @TSortedListBox.Load;
- Store: @TSortedListBox.Store
- );
- REditChDirDialog : TStreamRec = (
- ObjType : idEditChDirDialog;
- VmtLink : Ofs(TypeOf(TEditChDirDialog)^);
- Load : @TEditChDirDialog.Load;
- Store : @TEditChDirDialog.Store);
- implementation
- {****************************************************************************}
- { Local Declarations }
- {****************************************************************************}
- uses
- App, Memory, HistList, MsgBox, Resource;
- type
- PStringRec = record
- { PStringRec is needed for properly displaying PStrings using
- MessageBox. }
- AString : PString;
- end;
- {****************************************************************************}
- { PathValid }
- {****************************************************************************}
- {$ifdef go32v2}
- {$define NetDrive}
- {$endif go32v2}
- {$ifdef win32}
- {$define NetDrive}
- {$endif win32}
- procedure RemoveDoubleDirSep(var ExpPath : PathStr);
- var
- p: longint;
- {$ifdef NetDrive}
- OneDirSepRemoved: boolean;
- {$endif NetDrive}
- begin
- p:=pos(DirSeparator+DirSeparator,ExpPath);
- {$ifdef NetDrive}
- if p=1 then
- begin
- ExpPath:=Copy(ExpPath,1,high(ExpPath));
- OneDirSepRemoved:=true;
- p:=pos(DirSeparator+DirSeparator,ExpPath);
- end
- else
- OneDirSepRemoved:=false;
- {$endif NetDrive}
- while p>0 do
- begin
- ExpPath:=Copy(ExpPath,1,p)+Copy(ExpPath,p+2,high(ExpPath));
- p:=pos(DirSeparator+DirSeparator,ExpPath);
- end;
- {$ifdef NetDrive}
- if OneDirSepRemoved then
- ExpPath:=DirSeparator+ExpPath;
- {$endif NetDrive}
- end;
- function PathValid (var Path: PathStr): Boolean;
- var
- ExpPath: PathStr;
- SR: SearchRec;
- begin
- RemoveDoubleDirSep(Path);
- ExpPath := FExpand(Path);
- {$ifdef HAS_DOS_DRIVES}
- if (Length(ExpPath) <= 3) then
- PathValid := DriveValid(ExpPath[1])
- else
- {$endif}
- begin
- { do not change '/' into '' }
- if (Length(ExpPath)>1) and (ExpPath[Length(ExpPath)] = DirSeparator) then
- Dec(ExpPath[0]);
- FindFirst(ExpPath, Directory, SR);
- PathValid := (DosError = 0) and (SR.Attr and Directory <> 0);
- {$ifdef NetDrive}
- if (DosError<>0) and (length(ExpPath)>2) and
- (ExpPath[1]='\') and (ExpPath[2]='\')then
- begin
- { Checking '\\machine\sharedfolder' directly always fails..
- rather try '\\machine\sharedfolder\*' PM }
- {$ifdef fpc}
- FindClose(SR);
- {$endif}
- FindFirst(ExpPath+'\*',AnyFile,SR);
- PathValid:=(DosError = 0);
- end;
- {$endif NetDrive}
- {$ifdef fpc}
- FindClose(SR);
- {$endif}
- end;
- end;
- {****************************************************************************}
- { TDirValidator Object }
- {****************************************************************************}
- {****************************************************************************}
- { TDirValidator.Init }
- {****************************************************************************}
- constructor TDirValidator.Init;
- const { What should this list be? The commented one doesn't allow home,
- end, right arrow, left arrow, Ctrl+XXXX, etc. }
- Chars: TCharSet = ['A'..'Z','a'..'z','.','~',':','_','-'];
- { Chars: TCharSet = [#0..#255]; }
- begin
- Chars := Chars + [DirSeparator];
- if not inherited Init(Chars) then
- Fail;
- end;
- {****************************************************************************}
- { TDirValidator.IsValid }
- {****************************************************************************}
- function TDirValidator.IsValid(const S: string): Boolean;
- begin
- { IsValid := False; }
- IsValid := True;
- end;
- {****************************************************************************}
- { TDirValidator.IsValidInput }
- {****************************************************************************}
- function TDirValidator.IsValidInput(var S: string; SuppressFill: Boolean): Boolean;
- begin
- { IsValid := False; }
- IsValidInput := True;
- end;
- {****************************************************************************}
- { TFileInputLine Object }
- {****************************************************************************}
- {****************************************************************************}
- { TFileInputLine.Init }
- {****************************************************************************}
- constructor TFileInputLine.Init(var Bounds: TRect; AMaxLen: Sw_Integer);
- begin
- TInputLine.Init(Bounds, AMaxLen);
- EventMask := EventMask or evBroadcast;
- end;
- {****************************************************************************}
- { TFileInputLine.HandleEvent }
- {****************************************************************************}
- procedure TFileInputLine.HandleEvent(var Event: TEvent);
- begin
- TInputLine.HandleEvent(Event);
- if (Event.What = evBroadcast) and (Event.Command = cmFileFocused) and
- (State and sfSelected = 0) then
- begin
- if PSearchRec(Event.InfoPtr)^.Attr and Directory <> 0 then
- begin
- Data^ := PSearchRec(Event.InfoPtr)^.Name + DirSeparator +
- PFileDialog(Owner)^.WildCard;
- { PFileDialog(Owner)^.FileHistory^.AdaptHistoryToDir(
- PSearchRec(Event.InfoPtr)^.Name+DirSeparator);}
- end
- else Data^ := PSearchRec(Event.InfoPtr)^.Name;
- DrawView;
- end;
- end;
- {****************************************************************************}
- { TFileCollection Object }
- {****************************************************************************}
- {****************************************************************************}
- { TFileCollection.Compare }
- {****************************************************************************}
- function uppername(const s : string) : string;
- var
- i : Sw_integer;
- in_name : boolean;
- begin
- in_name:=true;
- for i:=length(s) downto 1 do
- if in_name and (s[i] in ['a'..'z']) then
- uppername[i]:=char(byte(s[i])-32)
- else
- begin
- uppername[i]:=s[i];
- if s[i] = DirSeparator then
- in_name:=false;
- end;
- uppername[0]:=s[0];
- end;
- function TFileCollection.Compare(Key1, Key2: Pointer): Sw_Integer;
- begin
- if PSearchRec(Key1)^.Name = PSearchRec(Key2)^.Name then Compare := 0
- else if PSearchRec(Key1)^.Name = '..' then Compare := 1
- else if PSearchRec(Key2)^.Name = '..' then Compare := -1
- else if (PSearchRec(Key1)^.Attr and Directory <> 0) and
- (PSearchRec(Key2)^.Attr and Directory = 0) then Compare := 1
- else if (PSearchRec(Key2)^.Attr and Directory <> 0) and
- (PSearchRec(Key1)^.Attr and Directory = 0) then Compare := -1
- else if UpperName(PSearchRec(Key1)^.Name) > UpperName(PSearchRec(Key2)^.Name) then
- Compare := 1
- {$ifdef unix}
- else if UpperName(PSearchRec(Key1)^.Name) < UpperName(PSearchRec(Key2)^.Name) then
- Compare := -1
- else if PSearchRec(Key1)^.Name > PSearchRec(Key2)^.Name then
- Compare := 1
- {$endif def unix}
- else
- Compare := -1;
- end;
- {****************************************************************************}
- { TFileCollection.FreeItem }
- {****************************************************************************}
- procedure TFileCollection.FreeItem(Item: Pointer);
- begin
- Dispose(PSearchRec(Item));
- end;
- {****************************************************************************}
- { TFileCollection.GetItem }
- {****************************************************************************}
- function TFileCollection.GetItem(var S: TStream): Pointer;
- var
- Item: PSearchRec;
- begin
- New(Item);
- S.Read(Item^, SizeOf(TSearchRec));
- GetItem := Item;
- end;
- {****************************************************************************}
- { TFileCollection.PutItem }
- {****************************************************************************}
- procedure TFileCollection.PutItem(var S: TStream; Item: Pointer);
- begin
- S.Write(Item^, SizeOf(TSearchRec));
- end;
- {*****************************************************************************
- TFileList
- *****************************************************************************}
- const
- ListSeparator=';';
- function MatchesMask(What, Mask: string): boolean;
- function upper(const s : string) : string;
- var
- i : Sw_integer;
- begin
- for i:=1 to length(s) do
- if s[i] in ['a'..'z'] then
- upper[i]:=char(byte(s[i])-32)
- else
- upper[i]:=s[i];
- upper[0]:=s[0];
- end;
- Function CmpStr(const hstr1,hstr2:string):boolean;
- var
- found : boolean;
- i1,i2 : Sw_integer;
- begin
- i1:=0;
- i2:=0;
- if hstr1='' then
- begin
- CmpStr:=(hstr2='');
- exit;
- end;
- found:=true;
- repeat
- inc(i2);
- inc(i1);
- if (i1>length(hstr1)) or (i2>length(hstr2)) then
- break;
- case hstr1[i1] of
- '?' :
- found:=true;
- '*' :
- begin
- found:=true;
- if (i1=length(hstr1)) then
- i2:=length(hstr2)
- else
- if (i1<length(hstr1)) and (hstr1[i1+1]<>hstr2[i2]) then
- begin
- if i2<length(hstr2) then
- dec(i1)
- end
- else
- if i2>1 then
- dec(i2);
- end;
- else
- found:=(hstr1[i1]=hstr2[i2]) or (hstr2[i2]='?');
- end;
- until (not found);
- if found then
- found:=(i1>=length(hstr1)) and (i2>=length(hstr2));
- CmpStr:=found;
- end;
- var
- D1,D2 : DirStr;
- N1,N2 : NameStr;
- E1,E2 : Extstr;
- begin
- {$ifdef Unix}
- FSplit(What,D1,N1,E1);
- FSplit(Mask,D2,N2,E2);
- {$else}
- FSplit(Upper(What),D1,N1,E1);
- FSplit(Upper(Mask),D2,N2,E2);
- {$endif}
- MatchesMask:=CmpStr(N2,N1) and CmpStr(E2,E1);
- end;
- function MatchesMaskList(What, MaskList: string): boolean;
- var P: integer;
- Match: boolean;
- begin
- Match:=false;
- if What<>'' then
- repeat
- P:=Pos(ListSeparator, MaskList);
- if P=0 then P:=length(MaskList)+1;
- Match:=MatchesMask(What,copy(MaskList,1,P-1));
- Delete(MaskList,1,P);
- until Match or (MaskList='');
- MatchesMaskList:=Match;
- end;
- constructor TFileList.Init(var Bounds: TRect; AScrollBar: PScrollBar);
- begin
- TSortedListBox.Init(Bounds, 2, AScrollBar);
- end;
- destructor TFileList.Done;
- begin
- if List <> nil then Dispose(List, Done);
- TListBox.Done;
- end;
- function TFileList.DataSize: Sw_Word;
- begin
- DataSize := 0;
- end;
- procedure TFileList.FocusItem(Item: Sw_Integer);
- begin
- TSortedListBox.FocusItem(Item);
- if (List^.Count > 0) then
- Message(Owner, evBroadcast, cmFileFocused, List^.At(Item));
- end;
- procedure TFileList.GetData(var Rec);
- begin
- end;
- function TFileList.GetKey(var S: String): Pointer;
- const
- SR: TSearchRec = ();
- procedure UpStr(var S: String);
- var
- I: Sw_Integer;
- begin
- for I := 1 to Length(S) do S[I] := UpCase(S[I]);
- end;
- begin
- if (HandleDir{ShiftState and $03 <> 0}) or ((S <> '') and (S[1]='.')) then
- SR.Attr := Directory
- else SR.Attr := 0;
- SR.Name := S;
- {$ifndef Unix}
- UpStr(SR.Name);
- {$endif Unix}
- GetKey := @SR;
- end;
- function TFileList.GetText(Item,MaxLen: Sw_Integer): String;
- var
- S: String;
- SR: PSearchRec;
- begin
- SR := PSearchRec(List^.At(Item));
- S := SR^.Name;
- if SR^.Attr and Directory <> 0 then
- begin
- S[Length(S)+1] := DirSeparator;
- Inc(S[0]);
- end;
- GetText := S;
- end;
- procedure TFileList.HandleEvent(var Event: TEvent);
- var
- S : String;
- K : pointer;
- Value : Sw_integer;
- begin
- if (Event.What = evMouseDown) and (Event.Double) then
- begin
- Event.What := evCommand;
- Event.Command := cmOK;
- PutEvent(Event);
- ClearEvent(Event);
- end
- else if (Event.What = evKeyDown) and (Event.CharCode='<') then
- begin
- { select '..' }
- S := '..';
- K := GetKey(S);
- If PSortedCollection(List)^.Search(K, Value) then
- FocusItem(Value);
- end
- else TSortedListBox.HandleEvent(Event);
- end;
- procedure TFileList.ReadDirectory(AWildCard: PathStr);
- const
- FindAttr = ReadOnly + Archive;
- {$ifdef Unix}
- AllFiles = '*';
- {$else}
- AllFiles = '*.*';
- {$endif}
- PrevDir = '..';
- var
- S: SearchRec;
- P: PSearchRec;
- FileList: PFileCollection;
- NumFiles: Word;
- FindStr,
- WildName : string;
- Dir: DirStr;
- Ext: ExtStr;
- Name: NameStr;
- Event : TEvent;
- Tmp: PathStr;
- begin
- NumFiles := 0;
- FileList := New(PFileCollection, Init(5, 5));
- AWildCard := FExpand(AWildCard);
- FSplit(AWildCard, Dir, Name, Ext);
- if pos(ListSeparator,AWildCard)>0 then
- begin
- WildName:=Copy(AWildCard,length(Dir)+1,255);
- FindStr:=Dir+AllFiles;
- end
- else
- begin
- WildName:=Name+Ext;
- FindStr:=AWildCard;
- end;
- FindFirst(FindStr, FindAttr, S);
- P := PSearchRec(@P);
- while assigned(P) and (DosError = 0) do
- begin
- if (S.Attr and Directory = 0) and
- MatchesMaskList(S.Name,WildName) then
- begin
- P := MemAlloc(SizeOf(P^));
- if assigned(P) then
- begin
- P^.Attr:=S.Attr;
- P^.Time:=S.Time;
- P^.Size:=S.Size;
- P^.Name:=S.Name;
- FileList^.Insert(P);
- end;
- end;
- FindNext(S);
- end;
- {$ifdef fpc}
- FindClose(S);
- {$endif}
- Tmp := Dir + AllFiles;
- FindFirst(Tmp, Directory, S);
- while (P <> nil) and (DosError = 0) do
- begin
- if (S.Attr and Directory <> 0) and (S.Name <> '.') and (S.Name <> '..') then
- begin
- P := MemAlloc(SizeOf(P^));
- if P <> nil then
- begin
- P^.Attr:=S.Attr;
- P^.Time:=S.Time;
- P^.Size:=S.Size;
- P^.Name:=S.Name;
- FileList^.Insert(P);
- end;
- end;
- FindNext(S);
- end;
- {$ifdef fpc}
- FindClose(S);
- {$endif}
- {$ifndef Unix}
- if Length(Dir) > 4 then
- {$endif not Unix}
- begin
- P := MemAlloc(SizeOf(P^));
- if P <> nil then
- begin
- FindFirst(Tmp, Directory, S);
- FindNext(S);
- if (DosError = 0) and (S.Name = PrevDir) then
- begin
- P^.Attr:=S.Attr;
- P^.Time:=S.Time;
- P^.Size:=S.Size;
- P^.Name:=S.Name;
- end
- else
- begin
- P^.Name := PrevDir;
- P^.Size := 0;
- P^.Time := $210000;
- P^.Attr := Directory;
- end;
- FileList^.Insert(PSearchRec(P));
- {$ifdef fpc}
- FindClose(S);
- {$endif}
- end;
- end;
- if P = nil then
- MessageBox(strings^.get(sTooManyFiles), nil, mfOkButton + mfWarning);
- NewList(FileList);
- if List^.Count > 0 then
- begin
- Event.What := evBroadcast;
- Event.Command := cmFileFocused;
- Event.InfoPtr := List^.At(0);
- Owner^.HandleEvent(Event);
- end;
- end;
- procedure TFileList.SetData(var Rec);
- begin
- with PFileDialog(Owner)^ do
- Self.ReadDirectory(Directory^ + WildCard);
- end;
- {****************************************************************************}
- { TFileInfoPane Object }
- {****************************************************************************}
- {****************************************************************************}
- { TFileInfoPane.Init }
- {****************************************************************************}
- constructor TFileInfoPane.Init(var Bounds: TRect);
- begin
- TView.Init(Bounds);
- FillChar(S,SizeOf(S),#0);
- EventMask := EventMask or evBroadcast;
- end;
- {****************************************************************************}
- { TFileInfoPane.Draw }
- {****************************************************************************}
- procedure TFileInfoPane.Draw;
- var
- B: TDrawBuffer;
- D: String[9];
- M: String[3];
- PM: Boolean;
- Color: Word;
- Time: DateTime;
- Path: PathStr;
- FmtId: String;
- Params: array[0..7] of LongInt;
- Str: String[80];
- const
- sDirectoryLine = ' %-12s %-9s %3s %2d, %4d %2d:%02d%cm';
- sFileLine = ' %-12s %-9d %3s %2d, %4d %2d:%02d%cm';
- InValidFiles : array[0..2] of string[12] = ('','.','..');
- var
- Month: array[1..12] of String[3];
- begin
- Month[1] := Strings^.Get(smJan);
- Month[2] := Strings^.Get(smFeb);
- Month[3] := Strings^.Get(smMar);
- Month[4] := Strings^.Get(smApr);
- Month[5] := Strings^.Get(smMay);
- Month[6] := Strings^.Get(smJun);
- Month[7] := Strings^.Get(smJul);
- Month[8] := Strings^.Get(smAug);
- Month[9] := Strings^.Get(smSep);
- Month[10] := Strings^.Get(smOct);
- Month[11] := Strings^.Get(smNov);
- Month[12] := Strings^.Get(smDec);
- { Display path }
- if (PFileDialog(Owner)^.Directory <> nil) then
- Path := PFileDialog(Owner)^.Directory^
- else Path := '';
- Path := FExpand(Path+PFileDialog(Owner)^.WildCard);
- { avoid B Buffer overflow PM }
- Path := ShrinkPath(Path, Size.X - 1);
- Color := GetColor($01);
- MoveChar(B, ' ', Color, Size.X); { fill with empty spaces }
- WriteLine(0, 0, Size.X, Size.Y, B);
- MoveStr(B[1], Path, Color);
- WriteLine(0, 0, Size.X, 1, B);
- if (S.Name = InValidFiles[0]) or (S.Name = InValidFiles[1]) or
- (S.Name = InValidFiles[2]) then
- Exit;
- { Display file }
- Params[0] := LongInt(@S.Name);
- if S.Attr and Directory <> 0 then
- begin
- FmtId := sDirectoryLine;
- D := Strings^.Get(sDirectory);
- Params[1] := LongInt(@D);
- end else
- begin
- FmtId := sFileLine;
- Params[1] := S.Size;
- end;
- UnpackTime(S.Time, Time);
- M := Month[Time.Month];
- Params[2] := LongInt(@M);
- Params[3] := Time.Day;
- Params[4] := Time.Year;
- PM := Time.Hour >= 12;
- Time.Hour := Time.Hour mod 12;
- if Time.Hour = 0 then Time.Hour := 12;
- Params[5] := Time.Hour;
- Params[6] := Time.Min;
- if PM then
- Params[7] := Byte('p')
- else Params[7] := Byte('a');
- FormatStr(Str, FmtId, Params);
- MoveStr(B, Str, Color);
- WriteLine(0, 1, Size.X, 1, B);
- { Fill in rest of rectangle }
- MoveChar(B, ' ', Color, Size.X);
- WriteLine(0, 2, Size.X, Size.Y-2, B);
- end;
- function TFileInfoPane.GetPalette: PPalette;
- const
- P: String[Length(CInfoPane)] = CInfoPane;
- begin
- GetPalette := PPalette(@P);
- end;
- procedure TFileInfoPane.HandleEvent(var Event: TEvent);
- begin
- TView.HandleEvent(Event);
- if (Event.What = evBroadcast) and (Event.Command = cmFileFocused) then
- begin
- S := PSearchRec(Event.InfoPtr)^;
- DrawView;
- end;
- end;
- {****************************************************************************
- TFileHistory
- ****************************************************************************}
- function LTrim(const S: String): String;
- var
- I: Sw_Integer;
- begin
- I := 1;
- while (I < Length(S)) and (S[I] = ' ') do Inc(I);
- LTrim := Copy(S, I, 255);
- end;
- function RTrim(const S: String): String;
- var
- I: Sw_Integer;
- begin
- I := Length(S);
- while S[I] = ' ' do Dec(I);
- RTrim := Copy(S, 1, I);
- end;
- function RelativePath(var S: PathStr): Boolean;
- begin
- S := LTrim(RTrim(S));
- RelativePath := not ((S <> '') and ((S[1] = DirSeparator) or (S[2] = ':')));
- end;
- { try to reduce the length of S+dir as a file path+pattern }
- function Simplify (var S,Dir : string) : string;
- var i : sw_integer;
- begin
- if RelativePath(Dir) then
- begin
- if (S<>'') and (Copy(Dir,1,3)='..'+DirSeparator) then
- begin
- i:=Length(S);
- for i:=Length(S)-1 downto 1 do
- if S[i]=DirSeparator then
- break;
- if S[i]=DirSeparator then
- Simplify:=Copy(S,1,i)+Copy(Dir,4,255)
- else
- Simplify:=S+Dir;
- end
- else
- Simplify:=S+Dir;
- end
- else
- Simplify:=Dir;
- end;
- {****************************************************************************}
- { TFileHistory.HandleEvent }
- {****************************************************************************}
- procedure TFileHistory.HandleEvent(var Event: TEvent);
- var
- HistoryWindow: PHistoryWindow;
- R,P: TRect;
- C: Word;
- Rslt: String;
- begin
- TView.HandleEvent(Event);
- if (Event.What = evMouseDown) or
- ((Event.What = evKeyDown) and (CtrlToArrow(Event.KeyCode) = kbDown) and
- (Link^.State and sfFocused <> 0)) then
- begin
- if not Link^.Focus then
- begin
- ClearEvent(Event);
- Exit;
- end;
- if assigned(CurDir) then
- Rslt:=CurDir^
- else
- Rslt:='';
- Rslt:=Simplify(Rslt,Link^.Data^);
- RemoveDoubleDirSep(Rslt);
- If IsWild(Rslt) then
- RecordHistory(Rslt);
- Link^.GetBounds(R);
- Dec(R.A.X); Inc(R.B.X); Inc(R.B.Y,7); Dec(R.A.Y,1);
- Owner^.GetExtent(P);
- R.Intersect(P);
- Dec(R.B.Y,1);
- HistoryWindow := InitHistoryWindow(R);
- if HistoryWindow <> nil then
- begin
- C := Owner^.ExecView(HistoryWindow);
- if C = cmOk then
- begin
- Rslt := HistoryWindow^.GetSelection;
- if Length(Rslt) > Link^.MaxLen then Rslt[0] := Char(Link^.MaxLen);
- Link^.Data^ := Rslt;
- Link^.SelectAll(True);
- Link^.DrawView;
- end;
- Dispose(HistoryWindow, Done);
- end;
- ClearEvent(Event);
- end
- else if (Event.What = evBroadcast) then
- if ((Event.Command = cmReleasedFocus) and (Event.InfoPtr = Link))
- or (Event.Command = cmRecordHistory) then
- begin
- if assigned(CurDir) then
- Rslt:=CurDir^
- else
- Rslt:='';
- Rslt:=Simplify(Rslt,Link^.Data^);
- RemoveDoubleDirSep(Rslt);
- If IsWild(Rslt) then
- RecordHistory(Rslt);
- end;
- end;
- procedure TFileHistory.AdaptHistoryToDir(Dir : string);
- var S,S2 : String;
- i,Count : Sw_word;
- begin
- if assigned(CurDir) then
- begin
- S:=CurDir^;
- if S=Dir then
- exit;
- DisposeStr(CurDir);
- end
- else
- S:='';
- CurDir:=NewStr(Simplify(S,Dir));
- Count:=HistoryCount(HistoryId);
- for i:=1 to count do
- begin
- S2:=HistoryStr(HistoryId,1);
- HistoryRemove(HistoryId,1);
- if RelativePath(S2) then
- if S<>'' then
- S2:=S+S2
- else
- S2:=FExpand(S2);
- { simply full path
- we should simplify relative to Dir ! }
- HistoryAdd(HistoryId,S2);
- end;
- end;
- destructor TFileHistory.Done;
- begin
- If assigned(CurDir) then
- DisposeStr(CurDir);
- Inherited Done;
- end;
- {****************************************************************************
- TFileDialog
- ****************************************************************************}
- constructor TFileDialog.Init(AWildCard: TWildStr; const ATitle,
- InputName: String; AOptions: Word; HistoryId: Byte);
- var
- Control: PView;
- R: TRect;
- Opt: Word;
- begin
- R.Assign(15,1,64,20);
- TDialog.Init(R, ATitle);
- Options := Options or ofCentered;
- WildCard := AWildCard;
- R.Assign(3,3,31,4);
- FileName := New(PFileInputLine, Init(R, 79));
- FileName^.Data^ := WildCard;
- Insert(FileName);
- R.Assign(2,2,3+CStrLen(InputName),3);
- Control := New(PLabel, Init(R, InputName, FileName));
- Insert(Control);
- R.Assign(31,3,34,4);
- FileHistory := New(PFileHistory, Init(R, FileName, HistoryId));
- Insert(FileHistory);
- R.Assign(3,14,34,15);
- Control := New(PScrollBar, Init(R));
- Insert(Control);
- R.Assign(3,6,34,14);
- FileList := New(PFileList, Init(R, PScrollBar(Control)));
- Insert(FileList);
- R.Assign(2,5,8,6);
- Control := New(PLabel, Init(R, labels^.get(slFiles), FileList));
- Insert(Control);
- R.Assign(35,3,46,5);
- Opt := bfDefault;
- if AOptions and fdOpenButton <> 0 then
- begin
- Insert(New(PButton, Init(R,labels^.get(slOpen), cmFileOpen, Opt)));
- Opt := bfNormal;
- Inc(R.A.Y,3); Inc(R.B.Y,3);
- end;
- if AOptions and fdOkButton <> 0 then
- begin
- Insert(New(PButton, Init(R,labels^.get(slOk), cmFileOpen, Opt)));
- Opt := bfNormal;
- Inc(R.A.Y,3); Inc(R.B.Y,3);
- end;
- if AOptions and fdReplaceButton <> 0 then
- begin
- Insert(New(PButton, Init(R, labels^.get(slReplace),cmFileReplace, Opt)));
- Opt := bfNormal;
- Inc(R.A.Y,3); Inc(R.B.Y,3);
- end;
- if AOptions and fdClearButton <> 0 then
- begin
- Insert(New(PButton, Init(R, labels^.get(slClear),cmFileClear, Opt)));
- Opt := bfNormal;
- Inc(R.A.Y,3); Inc(R.B.Y,3);
- end;
- Insert(New(PButton, Init(R, labels^.get(slCancel), cmCancel, bfNormal)));
- Inc(R.A.Y,3); Inc(R.B.Y,3);
- if AOptions and fdHelpButton <> 0 then
- begin
- Insert(New(PButton, Init(R,labels^.get(slHelp),cmHelp, bfNormal)));
- Inc(R.A.Y,3); Inc(R.B.Y,3);
- end;
- R.Assign(1,16,48,18);
- Control := New(PFileInfoPane, Init(R));
- Insert(Control);
- SelectNext(False);
- if AOptions and fdNoLoadDir = 0 then ReadDirectory;
- end;
- constructor TFileDialog.Load(var S: TStream);
- begin
- if not TDialog.Load(S) then
- Fail;
- S.Read(WildCard, SizeOf(WildCard));
- if (S.Status <> stOk) then
- begin
- TDialog.Done;
- Fail;
- end;
- GetSubViewPtr(S, FileName);
- GetSubViewPtr(S, FileList);
- GetSubViewPtr(S, FileHistory);
- ReadDirectory;
- if (DosError <> 0) then
- begin
- TDialog.Done;
- Fail;
- end;
- end;
- destructor TFileDialog.Done;
- begin
- DisposeStr(Directory);
- TDialog.Done;
- end;
- procedure TFileDialog.GetData(var Rec);
- begin
- GetFilename(PathStr(Rec));
- end;
- procedure TFileDialog.GetFileName(var S: PathStr);
- var
- Path: PathStr;
- Name: NameStr;
- Ext: ExtStr;
- TWild : string;
- TPath: PathStr;
- TName: NameStr;
- TExt: NameStr;
- i : Sw_integer;
- begin
- S := FileName^.Data^;
- if RelativePath(S) then
- begin
- if (Directory <> nil) then
- S := FExpand(Directory^ + S);
- end
- else
- S := FExpand(S);
- if Pos(ListSeparator,S)=0 then
- begin
- If FileExists(S) then
- exit;
- FSplit(S, Path, Name, Ext);
- if ((Name = '') or (Ext = '')) and not IsDir(S) then
- begin
- TWild:=WildCard;
- repeat
- i:=Pos(ListSeparator,TWild);
- if i=0 then
- i:=length(TWild)+1;
- FSplit(Copy(TWild,1,i-1), TPath, TName, TExt);
- if ((Name = '') and (Ext = '')) then
- S := Path + TName + TExt
- else
- if Name = '' then
- S := Path + TName + Ext
- else
- if Ext = '' then
- begin
- if IsWild(Name) then
- S := Path + Name + TExt
- else
- S := Path + Name + NoWildChars(TExt);
- end;
- if FileExists(S) then
- break;
- System.Delete(TWild,1,i);
- until TWild='';
- if TWild='' then
- S := Path + Name + Ext;
- end;
- end;
- end;
- procedure TFileDialog.HandleEvent(var Event: TEvent);
- begin
- if (Event.What and evBroadcast <> 0) and
- (Event.Command = cmListItemSelected) then
- begin
- EndModal(cmFileOpen);
- ClearEvent(Event);
- end;
- TDialog.HandleEvent(Event);
- if Event.What = evCommand then
- case Event.Command of
- cmFileOpen, cmFileReplace, cmFileClear:
- begin
- EndModal(Event.Command);
- ClearEvent(Event);
- end;
- end;
- end;
- procedure TFileDialog.SetData(var Rec);
- begin
- TDialog.SetData(Rec);
- if (PathStr(Rec) <> '') and (IsWild(TWildStr(Rec))) then
- begin
- Valid(cmFileInit);
- FileName^.Select;
- end;
- end;
- procedure TFileDialog.ReadDirectory;
- begin
- FileList^.ReadDirectory(WildCard);
- FileHistory^.AdaptHistoryToDir(GetCurDir);
- Directory := NewStr(GetCurDir);
- end;
- procedure TFileDialog.Store(var S: TStream);
- begin
- TDialog.Store(S);
- S.Write(WildCard, SizeOf(WildCard));
- PutSubViewPtr(S, FileName);
- PutSubViewPtr(S, FileList);
- PutSubViewPtr(S, FileHistory);
- end;
- function TFileDialog.Valid(Command: Word): Boolean;
- var
- FName: PathStr;
- Dir: DirStr;
- Name: NameStr;
- Ext: ExtStr;
- function CheckDirectory(var S: PathStr): Boolean;
- begin
- if not PathValid(S) then
- begin
- MessageBox(Strings^.Get(sInvalidDriveOrDir), nil, mfError + mfOkButton);
- FileName^.Select;
- CheckDirectory := False;
- end else CheckDirectory := True;
- end;
- function CompleteDir(const Path: string): string;
- begin
- { keep c: untouched PM }
- if (Path<>'') and (Path[Length(Path)]<>DirSeparator) and
- (Path[Length(Path)]<>':') then
- CompleteDir:=Path+DirSeparator
- else
- CompleteDir:=Path;
- end;
- function NormalizeDir(const Path: string): string;
- var Root: boolean;
- begin
- Root:=false;
- {$ifdef Unix}
- if Path=DirSeparator then Root:=true;
- {$else}
- if (length(Path)=3) and (Upcase(Path[1]) in['A'..'Z']) and
- (Path[2]=':') and (Path[3]=DirSeparator) then
- Root:=true;
- {$endif}
- if (Root=false) and (copy(Path,length(Path),1)=DirSeparator) then
- NormalizeDir:=copy(Path,1,length(Path)-1)
- else
- NormalizeDir:=Path;
- end;
- function NormalizeDirF(var S: openstring): boolean;
- begin
- S:=NormalizeDir(S);
- NormalizeDirF:=true;
- end;
- begin
- if Command = 0 then
- begin
- Valid := True;
- Exit;
- end
- else Valid := False;
- if TDialog.Valid(Command) then
- begin
- GetFileName(FName);
- if (Command <> cmCancel) and (Command <> cmFileClear) then
- begin
- if IsWild(FName) or IsList(FName) then
- begin
- FSplit(FName, Dir, Name, Ext);
- if CheckDirectory(Dir) then
- begin
- FileHistory^.AdaptHistoryToDir(Dir);
- DisposeStr(Directory);
- Directory := NewStr(Dir);
- if Pos(ListSeparator,FName)>0 then
- WildCard:=Copy(FName,length(Dir)+1,255)
- else
- WildCard := Name+Ext;
- if Command <> cmFileInit then
- FileList^.Select;
- FileList^.ReadDirectory(Directory^+WildCard);
- end;
- end
- else
- if NormalizeDirF(FName) then
- { ^^ this is just a dummy if construct (the func always returns true,
- it's just there, 'coz I don't want to rearrange the following "if"s... }
- if IsDir(FName) then
- begin
- if CheckDirectory(FName) then
- begin
- FileHistory^.AdaptHistoryToDir(CompleteDir(FName));
- DisposeStr(Directory);
- Directory := NewSTr(CompleteDir(FName));
- if Command <> cmFileInit then FileList^.Select;
- FileList^.ReadDirectory(Directory^+WildCard);
- end
- end
- else
- if ValidFileName(FName) then
- Valid := True
- else
- begin
- MessageBox(^C + Strings^.Get(sInvalidFileName), nil, mfError + mfOkButton);
- Valid := False;
- end;
- end
- else Valid := True;
- end;
- end;
- { TDirCollection }
- function TDirCollection.GetItem(var S: TStream): Pointer;
- var
- DirItem: PDirEntry;
- begin
- New(DirItem);
- DirItem^.DisplayText := S.ReadStr;
- DirItem^.Directory := S.ReadStr;
- GetItem := DirItem;
- end;
- procedure TDirCollection.FreeItem(Item: Pointer);
- var
- DirItem: PDirEntry absolute Item;
- begin
- DisposeStr(DirItem^.DisplayText);
- DisposeStr(DirItem^.Directory);
- Dispose(DirItem);
- end;
- procedure TDirCollection.PutItem(var S: TStream; Item: Pointer);
- var
- DirItem: PDirEntry absolute Item;
- begin
- S.WriteStr(DirItem^.DisplayText);
- S.WriteStr(DirItem^.Directory);
- end;
- { TDirListBox }
- const
- DrivesS: String = '';
- Drives: PString = @DrivesS;
- constructor TDirListBox.Init(var Bounds: TRect; AScrollBar:
- PScrollBar);
- begin
- DrivesS := strings^.get(sDrives);
- TListBox.Init(Bounds, 1, AScrollBar);
- Dir := '';
- end;
- destructor TDirListBox.Done;
- begin
- if (List <> nil) then
- Dispose(List,Done);
- TListBox.Done;
- end;
- function TDirListBox.GetText(Item,MaxLen: Sw_Integer): String;
- begin
- GetText := PDirEntry(List^.At(Item))^.DisplayText^;
- end;
- procedure TDirListBox.HandleEvent(var Event: TEvent);
- begin
- case Event.What of
- evMouseDown:
- if Event.Double then
- begin
- Event.What := evCommand;
- Event.Command := cmChangeDir;
- PutEvent(Event);
- ClearEvent(Event);
- end;
- evKeyboard:
- if (Event.CharCode = ' ') and
- (PSearchRec(List^.At(Focused))^.Name = '..') then
- NewDirectory(PSearchRec(List^.At(Focused))^.Name);
- end;
- TListBox.HandleEvent(Event);
- end;
- function TDirListBox.IsSelected(Item: Sw_Integer): Boolean;
- begin
- { IsSelected := Item = Cur; }
- IsSelected := Inherited IsSelected(Item);
- end;
- procedure TDirListBox.NewDirectory(var ADir: DirStr);
- const
- PathDir = 'ÀÄÂ';
- FirstDir = 'ÀÂÄ';
- MiddleDir = ' ÃÄ';
- LastDir = ' ÀÄ';
- IndentSize = ' ';
- var
- AList: PCollection;
- NewDir, Dirct: DirStr;
- C, OldC: Char;
- S, Indent: String[80];
- P: PString;
- NewCur: Word;
- isFirst: Boolean;
- SR: SearchRec;
- I: Sw_Integer;
- function NewDirEntry(const DisplayText, Directory: String): PDirEntry;{$ifdef PPC_BP}near;{$endif}
- var
- DirEntry: PDirEntry;
- begin
- New(DirEntry);
- DirEntry^.DisplayText := NewStr(DisplayText);
- If Directory='' then
- DirEntry^.Directory := NewStr(DirSeparator)
- else
- DirEntry^.Directory := NewStr(Directory);
- NewDirEntry := DirEntry;
- end;
- begin
- Dir := ADir;
- AList := New(PDirCollection, Init(5,5));
- {$ifdef HAS_DOS_DRIVES}
- AList^.Insert(NewDirEntry(Drives^,Drives^));
- if Dir = Drives^ then
- begin
- isFirst := True;
- OldC := ' ';
- for C := 'A' to 'Z' do
- begin
- if (C < 'C') or DriveValid(C) then
- begin
- if OldC <> ' ' then
- begin
- if isFirst then
- begin
- S := FirstDir + OldC;
- isFirst := False;
- end
- else S := MiddleDir + OldC;
- AList^.Insert(NewDirEntry(S, OldC + ':' + DirSeparator));
- end;
- if C = GetCurDrive then NewCur := AList^.Count;
- OldC := C;
- end;
- end;
- if OldC <> ' ' then
- AList^.Insert(NewDirEntry(LastDir + OldC, OldC + ':' + DirSeparator));
- end
- else
- {$endif HAS_DOS_DRIVES}
- begin
- Indent := IndentSize;
- NewDir := Dir;
- {$ifdef HAS_DOS_DRIVES}
- Dirct := Copy(NewDir,1,3);
- AList^.Insert(NewDirEntry(PathDir + Dirct, Dirct));
- NewDir := Copy(NewDir,4,255);
- {$else HAS_DOS_DRIVES}
- Dirct := '';
- {$endif HAS_DOS_DRIVES}
- while NewDir <> '' do
- begin
- I := Pos(DirSeparator,NewDir);
- if I <> 0 then
- begin
- S := Copy(NewDir,1,I-1);
- Dirct := Dirct + S;
- AList^.Insert(NewDirEntry(Indent + PathDir + S, Dirct));
- NewDir := Copy(NewDir,I+1,255);
- end
- else
- begin
- Dirct := Dirct + NewDir;
- AList^.Insert(NewDirEntry(Indent + PathDir + NewDir, Dirct));
- NewDir := '';
- end;
- Indent := Indent + IndentSize;
- Dirct := Dirct + DirSeparator;
- end;
- NewCur := AList^.Count-1;
- isFirst := True;
- NewDir := Dirct + '*.*';
- FindFirst(NewDir, Directory, SR);
- while DosError = 0 do
- begin
- if (SR.Attr and Directory <> 0) and
- {$ifdef FPC}
- (SR.Name <> '.') and (SR.Name <> '..') then
- {$else : not FPC}
- (SR.Name[1] <> '.') then
- {$endif not FPC}
- begin
- if isFirst then
- begin
- S := FirstDir;
- isFirst := False;
- end else S := MiddleDir;
- AList^.Insert(NewDirEntry(Indent + S + SR.Name, Dirct + SR.Name));
- end;
- FindNext(SR);
- end;
- {$ifdef fpc}
- FindClose(SR);
- {$endif}
- P := PDirEntry(AList^.At(AList^.Count-1))^.DisplayText;
- I := Pos('À',P^);
- if I = 0 then
- begin
- I := Pos('Ã',P^);
- if I <> 0 then P^[I] := 'À';
- end else
- begin
- P^[I+1] := 'Ä';
- P^[I+2] := 'Ä';
- end;
- end;
- NewList(AList);
- FocusItem(NewCur);
- Cur:=NewCur;
- end;
- procedure TDirListBox.SetState(AState: Word; Enable: Boolean);
- begin
- TListBox.SetState(AState, Enable);
- if AState and sfFocused <> 0 then
- PChDirDialog(Owner)^.ChDirButton^.MakeDefault(Enable);
- end;
- {****************************************************************************}
- { TChDirDialog Object }
- {****************************************************************************}
- {****************************************************************************}
- { TChDirDialog.Init }
- {****************************************************************************}
- constructor TChDirDialog.Init(AOptions: Word; HistoryId: Sw_Word);
- var
- R: TRect;
- Control: PView;
- begin
- R.Assign(16, 2, 64, 20);
- TDialog.Init(R,strings^.get(sChangeDirectory));
- Options := Options or ofCentered;
- R.Assign(3, 3, 30, 4);
- DirInput := New(PInputLine, Init(R, 68));
- Insert(DirInput);
- R.Assign(2, 2, 17, 3);
- Control := New(PLabel, Init(R,labels^.get(slDirectoryName), DirInput));
- Insert(Control);
- R.Assign(30, 3, 33, 4);
- Control := New(PHistory, Init(R, DirInput, HistoryId));
- Insert(Control);
- R.Assign(32, 6, 33, 16);
- Control := New(PScrollBar, Init(R));
- Insert(Control);
- R.Assign(3, 6, 32, 16);
- DirList := New(PDirListBox, Init(R, PScrollBar(Control)));
- Insert(DirList);
- R.Assign(2, 5, 17, 6);
- Control := New(PLabel, Init(R, labels^.get(slDirectoryTree), DirList));
- Insert(Control);
- R.Assign(35, 6, 45, 8);
- OkButton := New(PButton, Init(R, labels^.get(slOk), cmOK, bfDefault));
- Insert(OkButton);
- Inc(R.A.Y,3); Inc(R.B.Y,3);
- ChDirButton := New(PButton,Init(R,labels^.get(slChDir),cmChangeDir,
- bfNormal));
- Insert(ChDirButton);
- Inc(R.A.Y,3); Inc(R.B.Y,3);
- Insert(New(PButton, Init(R,labels^.get(slRevert), cmRevert, bfNormal)));
- if AOptions and cdHelpButton <> 0 then
- begin
- Inc(R.A.Y,3); Inc(R.B.Y,3);
- Insert(New(PButton, Init(R,labels^.get(slHelp), cmHelp, bfNormal)));
- end;
- if AOptions and cdNoLoadDir = 0 then SetUpDialog;
- SelectNext(False);
- end;
- {****************************************************************************}
- { TChDirDialog.Load }
- {****************************************************************************}
- constructor TChDirDialog.Load(var S: TStream);
- begin
- TDialog.Load(S);
- GetSubViewPtr(S, DirList);
- GetSubViewPtr(S, DirInput);
- GetSubViewPtr(S, OkButton);
- GetSubViewPtr(S, ChDirbutton);
- SetUpDialog;
- end;
- {****************************************************************************}
- { TChDirDialog.DataSize }
- {****************************************************************************}
- function TChDirDialog.DataSize: Sw_Word;
- begin
- DataSize := 0;
- end;
- {****************************************************************************}
- { TChDirDialog.GetData }
- {****************************************************************************}
- procedure TChDirDialog.GetData(var Rec);
- begin
- end;
- {****************************************************************************}
- { TChDirDialog.HandleEvent }
- {****************************************************************************}
- procedure TChDirDialog.HandleEvent(var Event: TEvent);
- var
- CurDir: DirStr;
- P: PDirEntry;
- begin
- TDialog.HandleEvent(Event);
- case Event.What of
- evCommand:
- begin
- case Event.Command of
- cmRevert: GetDir(0,CurDir);
- cmChangeDir:
- begin
- P := DirList^.List^.At(DirList^.Focused);
- if (P^.Directory^ = Drives^)
- or DriveValid(P^.Directory^[1]) then
- CurDir := P^.Directory^
- else Exit;
- end;
- else
- Exit;
- end;
- if (Length(CurDir) > 3) and
- (CurDir[Length(CurDir)] = DirSeparator) then
- CurDir := Copy(CurDir,1,Length(CurDir)-1);
- DirList^.NewDirectory(CurDir);
- DirInput^.Data^ := CurDir;
- DirInput^.DrawView;
- DirList^.Select;
- ClearEvent(Event);
- end;
- end;
- end;
- {****************************************************************************}
- { TChDirDialog.SetData }
- {****************************************************************************}
- procedure TChDirDialog.SetData(var Rec);
- begin
- end;
- {****************************************************************************}
- { TChDirDialog.SetUpDialog }
- {****************************************************************************}
- procedure TChDirDialog.SetUpDialog;
- var
- CurDir: DirStr;
- begin
- if DirList <> nil then
- begin
- CurDir := GetCurDir;
- DirList^.NewDirectory(CurDir);
- if (Length(CurDir) > 3) and (CurDir[Length(CurDir)] = DirSeparator) then
- CurDir := Copy(CurDir,1,Length(CurDir)-1);
- if DirInput <> nil then
- begin
- DirInput^.Data^ := CurDir;
- DirInput^.DrawView;
- end;
- end;
- end;
- {****************************************************************************}
- { TChDirDialog.Store }
- {****************************************************************************}
- procedure TChDirDialog.Store(var S: TStream);
- begin
- TDialog.Store(S);
- PutSubViewPtr(S, DirList);
- PutSubViewPtr(S, DirInput);
- PutSubViewPtr(S, OkButton);
- PutSubViewPtr(S, ChDirButton);
- end;
- {****************************************************************************}
- { TChDirDialog.Valid }
- {****************************************************************************}
- function TChDirDialog.Valid(Command: Word): Boolean;
- var
- P: PathStr;
- begin
- Valid := True;
- if Command = cmOk then
- begin
- P := FExpand(DirInput^.Data^);
- if (Length(P) > 3) and (P[Length(P)] = DirSeparator) then
- Dec(P[0]);
- {$I-}
- ChDir(P);
- if (IOResult <> 0) then
- begin
- MessageBox(Strings^.Get(sInvalidDirectory), nil, mfError + mfOkButton);
- Valid := False;
- end;
- {$I+}
- end;
- end;
- {****************************************************************************}
- { TEditChDirDialog Object }
- {****************************************************************************}
- {****************************************************************************}
- { TEditChDirDialog.DataSize }
- {****************************************************************************}
- function TEditChDirDialog.DataSize : Sw_Word;
- begin
- DataSize := SizeOf(DirStr);
- end;
- {****************************************************************************}
- { TEditChDirDialog.GetData }
- {****************************************************************************}
- procedure TEditChDirDialog.GetData (var Rec);
- var
- CurDir : DirStr absolute Rec;
- begin
- if (DirInput = nil) then
- CurDir := ''
- else begin
- CurDir := DirInput^.Data^;
- if (CurDir[Length(CurDir)] <> DirSeparator) then
- CurDir := CurDir + DirSeparator;
- end;
- end;
- {****************************************************************************}
- { TEditChDirDialog.SetData }
- {****************************************************************************}
- procedure TEditChDirDialog.SetData (var Rec);
- var
- CurDir : DirStr absolute Rec;
- begin
- if DirList <> nil then
- begin
- DirList^.NewDirectory(CurDir);
- if DirInput <> nil then
- begin
- if (Length(CurDir) > 3) and (CurDir[Length(CurDir)] = DirSeparator) then
- DirInput^.Data^ := Copy(CurDir,1,Length(CurDir)-1)
- else DirInput^.Data^ := CurDir;
- DirInput^.DrawView;
- end;
- end;
- end;
- {****************************************************************************}
- { TSortedListBox Object }
- {****************************************************************************}
- {****************************************************************************}
- { TSortedListBox.Init }
- {****************************************************************************}
- constructor TSortedListBox.Init(var Bounds: TRect; ANumCols: Sw_Word;
- AScrollBar: PScrollBar);
- begin
- TListBox.Init(Bounds, ANumCols, AScrollBar);
- SearchPos := 0;
- ShowCursor;
- SetCursor(1,0);
- end;
- {****************************************************************************}
- { TSortedListBox.HandleEvent }
- {****************************************************************************}
- procedure TSortedListBox.HandleEvent(var Event: TEvent);
- const
- SpecialChars: set of Char = [#0,#9,#27];
- var
- CurString, NewString: String;
- K: Pointer;
- Value : Sw_integer;
- OldPos, OldValue: Sw_Integer;
- T: Boolean;
- begin
- OldValue := Focused;
- TListBox.HandleEvent(Event);
- if (OldValue <> Focused) or
- ((Event.What = evBroadcast) and (Event.InfoPtr = @Self) and
- (Event.Command = cmReleasedFocus)) then
- SearchPos := 0;
- if Event.What = evKeyDown then
- begin
- { patched to prevent error when no or empty list or Escape pressed }
- if (not (Event.CharCode in SpecialChars)) and
- (List <> nil) and (List^.Count > 0) then
- begin
- Value := Focused;
- if Value < Range then
- CurString := GetText(Value, 255)
- else
- CurString := '';
- OldPos := SearchPos;
- if Event.KeyCode = kbBack then
- begin
- if SearchPos = 0 then Exit;
- Dec(SearchPos);
- if SearchPos = 0 then
- HandleDir:= ((GetShiftState and $3) <> 0) or (Event.CharCode in ['A'..'Z']);
- CurString[0] := Char(SearchPos);
- end
- else if (Event.CharCode = '.') then
- SearchPos := Pos('.',CurString)
- else
- begin
- Inc(SearchPos);
- if SearchPos = 1 then
- HandleDir := ((GetShiftState and 3) <> 0) or (Event.CharCode in ['A'..'Z']);
- CurString[0] := Char(SearchPos);
- CurString[SearchPos] := Event.CharCode;
- end;
- K := GetKey(CurString);
- T := PSortedCollection(List)^.Search(K, Value);
- if Value < Range then
- begin
- if Value < Range then
- NewString := GetText(Value, 255)
- else
- NewString := '';
- if Equal(NewString, CurString, SearchPos) then
- begin
- if Value <> OldValue then
- begin
- FocusItem(Value);
- { Assumes ListControl will set the cursor to the first character }
- { of the sfFocused item }
- SetCursor(Cursor.X+SearchPos, Cursor.Y);
- end
- else
- SetCursor(Cursor.X+(SearchPos-OldPos), Cursor.Y);
- end
- else
- SearchPos := OldPos;
- end
- else SearchPos := OldPos;
- if (SearchPos <> OldPos) or (Event.CharCode in ['A'..'Z','a'..'z']) then
- ClearEvent(Event);
- end;
- end;
- end;
- function TSortedListBox.GetKey(var S: String): Pointer;
- begin
- GetKey := @S;
- end;
- procedure TSortedListBox.NewList(AList: PCollection);
- begin
- TListBox.NewList(AList);
- SearchPos := 0;
- end;
- {****************************************************************************}
- { Global Procedures and Functions }
- {****************************************************************************}
- {****************************************************************************}
- { Contains }
- {****************************************************************************}
- function Contains(S1, S2: String): Boolean;
- { Contains returns true if S1 contains any characters in S2. }
- var
- i : Byte;
- begin
- Contains := True;
- i := 1;
- while ((i < Length(S2)) and (i < Length(S1))) do
- if (Upcase(S1[i]) = Upcase(S2[i])) then
- Exit
- else Inc(i);
- Contains := False;
- end;
- {****************************************************************************}
- { StdDeleteFile }
- {****************************************************************************}
- function StdDeleteFile (AFile : FNameStr) : Boolean;
- var
- Rec : PStringRec;
- begin
- if CheckOnDelete then
- begin
- AFile := ShrinkPath(AFile,33);
- Rec.AString := PString(@AFile);
- StdDeleteFile := (MessageBox(^C + Strings^.Get(sDeleteFile),
- @Rec,mfConfirmation or mfOkCancel) = cmOk);
- end
- else StdDeleteFile := False;
- end;
- {****************************************************************************}
- { DriveValid }
- {****************************************************************************}
- function DriveValid(Drive: Char): Boolean;
- {$ifdef HAS_DOS_DRIVES}
- var
- D: Char;
- begin
- D := GetCurDrive;
- {$I-}
- ChDir(Drive+':');
- if (IOResult = 0) then
- begin
- DriveValid := True;
- ChDir(D+':')
- end
- else DriveValid := False;
- {$I+}
- end;
- {$else HAS_DOS_DRIVES}
- begin
- DriveValid:=true;
- end;
- {$endif HAS_DOS_DRIVES}
- {****************************************************************************}
- { Equal }
- {****************************************************************************}
- function Equal(const S1, S2: String; Count: Sw_word): Boolean;
- var
- i: Sw_Word;
- begin
- Equal := False;
- if (Length(S1) < Count) or (Length(S2) < Count) then
- Exit;
- for i := 1 to Count do
- if UpCase(S1[I]) <> UpCase(S2[I]) then
- Exit;
- Equal := True;
- end;
- {****************************************************************************}
- { ExtractDir }
- {****************************************************************************}
- function ExtractDir(AFile: FNameStr): DirStr;
- { ExtractDir returns the path of AFile terminated with a trailing '\'. If
- AFile contains no directory information, an empty string is returned. }
- var
- D: DirStr;
- N: NameStr;
- E: ExtStr;
- begin
- FSplit(AFile,D,N,E);
- if D = '' then
- begin
- ExtractDir := '';
- Exit;
- end;
- if D[Byte(D[0])] <> DirSeparator then
- D := D + DirSeparator;
- ExtractDir := D;
- end;
- {****************************************************************************}
- { ExtractFileName }
- {****************************************************************************}
- function ExtractFileName(AFile: FNameStr): NameStr;
- var
- D: DirStr;
- N: NameStr;
- E: ExtStr;
- begin
- FSplit(AFile,D,N,E);
- ExtractFileName := N;
- end;
- {****************************************************************************}
- { FileExists }
- {****************************************************************************}
- function FileExists (AFile : FNameStr) : Boolean;
- begin
- FileExists := (FSearch(AFile,'') <> '');
- end;
- {****************************************************************************}
- { GetCurDir }
- {****************************************************************************}
- function GetCurDir: DirStr;
- var
- CurDir: DirStr;
- begin
- GetDir(0, CurDir);
- if (Length(CurDir) > 3) then
- begin
- Inc(CurDir[0]);
- CurDir[Length(CurDir)] := DirSeparator;
- end;
- GetCurDir := CurDir;
- end;
- {****************************************************************************}
- { GetCurDrive }
- {****************************************************************************}
- function GetCurDrive: Char;
- {$ifdef go32v2}
- var
- Regs : Registers;
- begin
- Regs.AH := $19;
- Intr($21,Regs);
- GetCurDrive := Char(Regs.AL + Byte('A'));
- end;
- {$else not go32v2}
- var
- D : DirStr;
- begin
- D:=GetCurDir;
- if (Length(D)>1) and (D[2]=':') then
- begin
- if (D[1]>='a') and (D[1]<='z') then
- GetCurDrive:=Char(Byte(D[1])+Byte('A')-Byte('a'))
- else
- GetCurDrive:=D[1];
- end
- else
- GetCurDrive:='C';
- end;
- {$endif not go32v2}
- {****************************************************************************}
- { IsDir }
- {****************************************************************************}
- function IsDir(const S: String): Boolean;
- var
- SR: SearchRec;
- Is: boolean;
- begin
- Is:=false;
- {$ifdef Unix}
- Is:=(S=DirSeparator); { handle root }
- {$else}
- Is:=(length(S)=3) and (Upcase(S[1]) in['A'..'Z']) and (S[2]=':') and (S[3]=DirSeparator);
- { handle root dirs }
- {$endif}
- if Is=false then
- begin
- FindFirst(S, Directory, SR);
- if DosError = 0 then
- Is := (SR.Attr and Directory) <> 0
- else
- Is := False;
- {$ifdef fpc}
- FindClose(SR);
- {$endif}
- end;
- IsDir:=Is;
- end;
- {****************************************************************************}
- { IsWild }
- {****************************************************************************}
- function IsWild(const S: String): Boolean;
- begin
- IsWild := (Pos('?',S) > 0) or (Pos('*',S) > 0);
- end;
- {****************************************************************************}
- { IsList }
- {****************************************************************************}
- function IsList(const S: String): Boolean;
- begin
- IsList := (Pos(ListSeparator,S) > 0);
- end;
- {****************************************************************************}
- { MakeResources }
- {****************************************************************************}
- procedure MakeResources;
- var
- Dlg : PDialog;
- Key : String;
- i : Word;
- begin
- for i := 0 to 1 do
- begin
- case i of
- 0 : begin
- Key := reOpenDlg;
- Dlg := New(PFileDialog,Init('*.*',strings^.get(sOpen),
- labels^.get(slName),
- fdOkButton or fdHelpButton or fdNoLoadDir,0));
- end;
- 1 : begin
- Key := reSaveAsDlg;
- Dlg := New(PFileDialog,Init('*.*',strings^.get(sSaveAs),
- labels^.get(slName),
- fdOkButton or fdHelpButton or fdNoLoadDir,0));
- end;
- 2 : begin
- Key := reEditChDirDialog;
- Dlg := New(PEditChDirDialog,Init(cdHelpButton,
- hiCurrentDirectories));
- end;
- end;
- if Dlg = nil then
- begin
- PrintStr('Error initializing dialog ' + Key);
- Halt;
- end
- else begin
- RezFile^.Put(Dlg,Key);
- if (RezFile^.Stream^.Status <> stOk) then
- begin
- PrintStr('Error writing dialog ' + Key + ' to the resource file.');
- Halt;
- end;
- end;
- end;
- end;
- {****************************************************************************}
- { NoWildChars }
- {****************************************************************************}
- function NoWildChars(S: String): String;
- const
- WildChars : array[0..1] of Char = ('?','*');
- var
- i : Sw_Word;
- begin
- repeat
- i := Pos('?',S);
- if (i > 0) then
- System.Delete(S,i,1);
- until (i = 0);
- repeat
- i := Pos('*',S);
- if (i > 0) then
- System.Delete(S,i,1);
- until (i = 0);
- NoWildChars:=S;
- end;
- {****************************************************************************}
- { OpenFile }
- {****************************************************************************}
- function OpenFile (var AFile : FNameStr; HistoryID : Byte) : Boolean;
- var
- Dlg : PFileDialog;
- begin
- {$ifdef cdResource}
- Dlg := PFileDialog(RezFile^.Get(reOpenDlg));
- {$else}
- Dlg := New(PFileDialog,Init('*.*',strings^.get(sOpen),labels^.get(slName),
- fdOkButton or fdHelpButton,0));
- {$endif cdResource}
- { this might not work }
- PHistory(Dlg^.FileName^.Next^.Next)^.HistoryID := HistoryID;
- OpenFile := (Application^.ExecuteDialog(Dlg,@AFile) = cmFileOpen);
- end;
- {****************************************************************************}
- { OpenNewFile }
- {****************************************************************************}
- function OpenNewFile (var AFile: FNameStr; HistoryID: Byte): Boolean;
- { OpenNewFile allows the user to select a directory from disk and enter a
- new file name. If the file name entered is an existing file the user is
- optionally prompted for confirmation of replacing the file based on the
- value in #CheckOnReplace#. If a file name is successfully entered,
- OpenNewFile returns True. }
- {#X OpenFile }
- begin
- OpenNewFile := False;
- if OpenFile(AFile,HistoryID) then
- begin
- if not ValidFileName(AFile) then
- Exit;
- if FileExists(AFile) then
- if (not CheckOnReplace) or (not ReplaceFile(AFile)) then
- Exit;
- OpenNewFile := True;
- end;
- end;
- {****************************************************************************}
- { RegisterStdDlg }
- {****************************************************************************}
- procedure RegisterStdDlg;
- begin
- RegisterType(RFileInputLine);
- RegisterType(RFileCollection);
- RegisterType(RFileList);
- RegisterType(RFileInfoPane);
- RegisterType(RFileDialog);
- RegisterType(RDirCollection);
- RegisterType(RDirListBox);
- RegisterType(RSortedListBox);
- RegisterType(RChDirDialog);
- end;
- {****************************************************************************}
- { StdReplaceFile }
- {****************************************************************************}
- function StdReplaceFile (AFile : FNameStr) : Boolean;
- var
- Rec : PStringRec;
- begin
- if CheckOnReplace then
- begin
- AFile := ShrinkPath(AFile,33);
- Rec.AString := PString(@AFile);
- StdReplaceFile :=
- (MessageBox(^C + Strings^.Get(sReplaceFile),
- @Rec,mfConfirmation or mfOkCancel) = cmOk);
- end
- else StdReplaceFile := True;
- end;
- {****************************************************************************}
- { SaveAs }
- {****************************************************************************}
- function SaveAs (var AFile : FNameStr; HistoryID : Word) : Boolean;
- var
- Dlg : PFileDialog;
- begin
- SaveAs := False;
- {$ifdef cdResource}
- Dlg := PFileDialog(RezFile^.Get(reSaveAsDlg));
- {$else}
- Dlg := New(PFileDialog,Init('*.*',strings^.get(sSaveAs),
- labels^.get(slSaveAs),
- fdOkButton or fdHelpButton,0));
- {$endif cdResource}
- { this might not work }
- PHistory(Dlg^.FileName^.Next^.Next)^.HistoryID := HistoryID;
- Dlg^.HelpCtx := hcSaveAs;
- if (Application^.ExecuteDialog(Dlg,@AFile) = cmFileOpen) and
- ((not FileExists(AFile)) or ReplaceFile(AFile)) then
- SaveAs := True;
- end;
- {****************************************************************************}
- { SelectDir }
- {****************************************************************************}
- function SelectDir (var ADir : DirStr; HistoryID : Byte) : Boolean;
- var
- Dir: DirStr;
- Dlg : PEditChDirDialog;
- Rec : DirStr;
- begin
- {$I-}
- GetDir(0,Dir);
- {$I+}
- Rec := FExpand(ADir);
- {$ifdef cdResource}
- Dlg := PEditChDirDialog(RezFile^.Get(reEditChDirDialog));
- {$else}
- Dlg := New(PEditChDirDialog,Init(cdHelpButton,HistoryID));
- {$endif cdResource}
- if (Application^.ExecuteDialog(Dlg,@Rec) = cmOk) then
- begin
- SelectDir := True;
- ADir := Rec;
- end
- else SelectDir := False;
- {$I-}
- ChDir(Dir);
- {$I+}
- end;
- {****************************************************************************}
- { ShrinkPath }
- {****************************************************************************}
- function ShrinkPath (AFile : FNameStr; MaxLen : Byte) : FNameStr;
- var
- Filler: string;
- D1 : DirStr;
- N1 : NameStr;
- E1 : ExtStr;
- i : Sw_Word;
- begin
- if Length(AFile) > MaxLen then
- begin
- FSplit(FExpand(AFile),D1,N1,E1);
- AFile := Copy(D1,1,3) + '..' + DirSeparator;
- i := Pred(Length(D1));
- while (i > 0) and (D1[i] <> DirSeparator) do
- Dec(i);
- if (i = 0) then
- AFile := AFile + D1
- else AFile := AFile + Copy(D1,Succ(i),Length(D1)-i);
- if AFile[Length(AFile)] <> DirSeparator then
- AFile := AFile + DirSeparator;
- if Length(AFile)+Length(N1)+Length(E1) <= MaxLen then
- AFile := AFile + N1 + E1
- else
- begin
- Filler := '...' + DirSeparator;
- AFile:=Copy(Afile,1,MaxLen-Length(Filler)-Length(N1)-Length(E1))
- +Filler+N1+E1;
- end;
- end;
- ShrinkPath := AFile;
- end;
- {****************************************************************************}
- { ValidFileName }
- {****************************************************************************}
- function ValidFileName(var FileName: PathStr): Boolean;
- var
- IllegalChars: string[12];
- Dir: DirStr;
- Name: NameStr;
- Ext: ExtStr;
- begin
- {$ifdef PPC_FPC}
- {$ifdef go32v2}
- { spaces are allowed if LFN is supported }
- if LFNSupport then
- IllegalChars := ';,=+<>|"[]'+DirSeparator
- else
- IllegalChars := ';,=+<>|"[] '+DirSeparator;
- {$else not go32v2}
- {$ifdef win32}
- IllegalChars := ';,=+<>|"[]'+DirSeparator;
- {$else not go32v2 and not win32 }
- IllegalChars := ';,=+<>|"[] '+DirSeparator;
- {$endif not win32}
- {$endif not go32v2}
- {$else not PPC_FPC}
- IllegalChars := ';,=+<>|"[] '+DirSeparator;
- {$endif PPC_FPC}
- ValidFileName := True;
- FSplit(FileName, Dir, Name, Ext);
- if not ((Dir = '') or PathValid(Dir)) or
- Contains(Name, IllegalChars) or
- Contains(Dir, IllegalChars) then
- ValidFileName := False;
- end;
- {****************************************************************************}
- { Unit Initialization Section }
- {****************************************************************************}
- begin
- {$ifdef PPC_BP}
- ReplaceFile := StdReplaceFile;
- DeleteFile := StdDeleteFile;
- {$else}
- ReplaceFile := @StdReplaceFile;
- DeleteFile := @StdDeleteFile;
- {$endif PPC_BP}
- end.
|