flist.pas 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  1. {
  2. $Id$
  3. This file is a Free Pascal example
  4. Copyright (C) 2005 by Marco van de Voort
  5. member of the Free Pascal development team.
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. A set of simple dirscanning routines for the lister.
  9. See the file COPYING.FPC, included in this distribution,
  10. for details about the copyright.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  14. **********************************************************************}
  15. Unit FList;
  16. {$Mode Delphi}
  17. Interface
  18. Uses Classes{$ifdef Win32},Registry {$endif};
  19. Const NoMarkNoSelect=0;
  20. MarkNoSelect =1;
  21. NoMarkSelect =2;
  22. MarkSelect =3;
  23. Type
  24. TDirList = Class
  25. private
  26. ACursor, // Entry (0-based) the cursor is on.
  27. APosition, // Entry (0-based) the homespot occupies
  28. ATotalEnt, // Total number of entries (dirs.count+files.count)
  29. wdth, // width of a column (width of screen div col)+1 in chars
  30. Amaxent, // number of entries that fit on the screen
  31. Acolh, // height of a column in entries.
  32. botRightCol : Integer; // When past this char, we are in bottombar
  33. TopBar,
  34. BottomBar : Integer; // lines below/above not for display
  35. AColumns : Integer; // amount of columns
  36. TheDirs : TStringList; // \
  37. TheFiles : TStringList; // The current entries
  38. Marked : TBits; // Which entries are selected?
  39. DirMax : Integer; // Can be used for autoscaling
  40. Filemax : Integer; // likewise
  41. ScrWidth,
  42. ScrHeight : Integer;
  43. function GetEntry(I:Integer;index:Integer):String;
  44. function GetDirCount:Integer;
  45. public
  46. Directory : String; // Current dir we are looking at.
  47. Constructor Create;
  48. Destructor Destroy; override;
  49. Procedure PopulateList(Const FileSpec:String);
  50. Procedure CalcScreenStats;
  51. Procedure Mark(x:integer);
  52. Procedure UnMark(x:integer);
  53. Procedure Toggle(x:integer);
  54. {$ifdef Debug}
  55. Procedure PrintDirs;
  56. Procedure PrintFiles;
  57. {$endif}
  58. property Entries[i:Integer]:String index 0 read GetEntry; Default;
  59. property Directories[i:Integer]:String index 1 Read GetEntry;
  60. property Files[i:Integer]:String index 2 Read GetEntry;
  61. property DirCount:Integer read GetDirCount;
  62. property Position: Integer read APosition write APosition;
  63. property Columns: Integer read AColumns write AColumns;
  64. property Cursor: Integer read ACursor write ACursor;
  65. property Colh: Integer read AColh write AColh;
  66. property MaxEnt: Integer read AMaxEnt write AMaxEnt;
  67. property TotalEnt: Integer read ATotalEnt write ATotalEnt;
  68. End;
  69. TVidDirList = Class(TDirList)
  70. {$ifdef Win32}
  71. Reg:TRegistry;
  72. {$endif}
  73. Attributes : Array[0..3] Of Integer;
  74. Constructor Create();
  75. Destructor Destroy; override;
  76. Procedure BuildDisplay;
  77. procedure ClearArea;
  78. Procedure Hilight(Curs,Home,Onx:Integer);
  79. {$ifdef Win32}
  80. Function CheckAssociation(ext:String):String;
  81. {$endif}
  82. End;
  83. Procedure TextOut(X,Y : Integer;Const S : String);
  84. Procedure textclear(x,y,Count :Integer);
  85. {$ifdef debug}
  86. var f : Text;
  87. {$endif}
  88. Implementation
  89. Uses SysUtils,Video;
  90. // comes from vidutl in the video examples area.
  91. Procedure TextOut(X,Y : Integer;Const S : String);
  92. Var
  93. P,I,M : Integer;
  94. begin
  95. P:=((X-1)+(Y-1)*ScreenWidth);
  96. M:=Length(S);
  97. If P+M>ScreenWidth*ScreenHeight then
  98. M:=ScreenWidth*ScreenHeight-P;
  99. For I:=1 to M do
  100. VideoBuf^[P+I-1]:=Ord(S[i])+($07 shl 8);
  101. end;
  102. Procedure textclear(x,y,Count :Integer);
  103. begin
  104. FillWord(VideoBuf[((X-1)+(Y-1)*ScreenWidth)],count,$07 shl 8);
  105. end;
  106. Constructor TDirList.Create;
  107. Begin
  108. TheDirs:=TStringList.Create;
  109. TheFiles:=TStringList.Create;
  110. Marked:=TBits.Create(1000);
  111. TheDirs.Sorted:=True;
  112. TheFiles.Sorted:=True;
  113. TopBar:=1;
  114. BottomBar:=1;
  115. Columns:=4;
  116. Inherited Create;
  117. End;
  118. function TDirList.GetDirCount:Integer;
  119. Begin
  120. Result:=TheDirs.Count;
  121. End;
  122. Destructor TDirList.Destroy;
  123. Begin
  124. TheDirs.Free;
  125. TheFiles.Free;
  126. Marked.Free;
  127. inherited destroy;
  128. End;
  129. Procedure TDirList.Mark(x:integer);
  130. Begin
  131. Marked.Seton(x);
  132. End;
  133. Procedure TDirList.UnMark(x:integer);
  134. Begin
  135. Marked.Clear(x);
  136. End;
  137. Procedure TDirList.Toggle(x:integer);
  138. {$ifdef Debug}
  139. var s:String;
  140. I:longint;
  141. {$endif}
  142. Begin
  143. Marked[x]:=NOT Marked[x];
  144. {$ifdef Debug}
  145. Writeln(F,'after marked:',marked.size);
  146. SetLength(S,51);
  147. For I:=0 To 50 Do
  148. If Marked[i] Then
  149. S[i+1]:=#49
  150. else
  151. S[I+1]:=#48;
  152. TextOut(1,1,S);
  153. Writeln(F,'after textout:',marked.size);
  154. {$endif}
  155. End;
  156. Function TDirList.GetEntry(I:Integer;Index:Integer):String;
  157. Begin
  158. {$ifdef Debug}
  159. Writeln(F,'i:',i,' ',index);
  160. {$endif}
  161. Case Index Of
  162. 0 : If I<TheDirs.Count Then
  163. Result:=TheDirs[I]
  164. Else
  165. Result:=TheFiles[I-TheDirs.Count];
  166. 1 : Result:=TheDirs[I];
  167. 2 : Result:=TheFiles[I];
  168. End;
  169. End;
  170. Procedure TDirList.PopulateList;
  171. Var Info : TSearchRec;
  172. Len : Integer;
  173. Procedure DoSearch(Const fs:String; Attr : Integer;AddFiles:Boolean);
  174. Begin
  175. If FindFirst (Directory+FS,Attr,Info)=0 then
  176. Repeat
  177. Len:=Length(Info.Name);
  178. If (Info.Attr and faDirectory) = faDirectory then
  179. Begin
  180. TheDirs.Add(Info.Name);
  181. If Len>DirMax Then
  182. DirMax:=Len;
  183. End
  184. Else
  185. Begin
  186. If AddFiles Then
  187. Begin
  188. TheFiles.Add(Info.Name);
  189. If Len>FileMax Then
  190. FileMax:=Len;
  191. End;
  192. End;
  193. Until FindNext(info)<>0;
  194. FindClose(Info);
  195. End;
  196. Begin
  197. DirMax:=0;
  198. FileMax:=0;
  199. TheDirs.Clear;
  200. TheFiles.Clear;
  201. Directory:=IncludeTrailingPathDelimiter(Directory);
  202. If FileSpec='*.*' Then
  203. Begin
  204. DoSearch(FileSpec,faAnyFile and faDirectory,True);
  205. End
  206. Else
  207. Begin
  208. DoSearch('*.*',faDirectory,False);
  209. DoSearch(FileSpec,faAnyFile,True);
  210. End;
  211. If (TheDirs.Count>0) And (TheDirs[0]='.') Then
  212. TheDirs.Delete(0);
  213. TotalEnt:=TheDirs.count+TheFiles.count;
  214. Position:=0;
  215. Cursor:=0;
  216. If Marked.Size<TotalEnt THEN
  217. Marked.Grow(TotalEnt);
  218. Marked.ClearAll;
  219. End;
  220. {$ifdef debug}
  221. Procedure TDirList.PrintDirs;
  222. Var I:Integer;
  223. Begin
  224. Writeln(f,Thedirs.count, ' ', thefiles.count, ' ',thedirs.count+thefiles.count);
  225. If theDirs.Count>0 Then
  226. For I:=0 To theDirs.Count-1 DO
  227. Writeln(f,theDirs[I]);
  228. End;
  229. Procedure TDirList.PrintFiles;
  230. Var I:Integer;
  231. Begin
  232. If TheFiles.Count>0 Then
  233. For I:=0 To TheFiles.Count-1 DO
  234. Writeln(f,TheFiles[I]);
  235. Writeln(f,'----');
  236. End;
  237. {$endif}
  238. Procedure TDirList.CalcScreenStats;
  239. Begin
  240. // Calc width of columns, minus one for the space inbetween
  241. wdth:=(ScrWidth DIV Columns)-1;
  242. // effective height of a column
  243. colh:=(ScrHeight-TopBar-BottomBar);
  244. // Max amount Filenames we can store in one screen;
  245. maxent:=colh*Columns;
  246. // If we write beyond this character, we would be wrong.
  247. BotRightCol:=(ScrHeight-BottomBar)*ScrWidth;
  248. End;
  249. Constructor TVidDirList.Create;
  250. Begin
  251. inherited Create;
  252. ScrWidth:=ScreenWidth;
  253. ScrHeight:=ScreenHeight;
  254. CalcScreenStats;
  255. {$Ifdef Win32}
  256. Reg:=TRegistry.Create;
  257. Reg.RootKey:=HKEY_CLASSES_ROOT;
  258. {$endif}
  259. End;
  260. Destructor TVidDirList.Destroy;
  261. Begin
  262. {$ifdef Win32}
  263. Reg.Free;
  264. {$endif}
  265. End;
  266. Procedure TVidDirList.BuildDisplay;
  267. Var
  268. O,I,M,X,
  269. TopLeftCol,
  270. totalc,
  271. lpos,
  272. dirc : Integer;
  273. S : String;
  274. begin
  275. {$ifdef debug}
  276. // Writeln(f,'entering');
  277. {$endif}
  278. dirc:=Thedirs.count;
  279. totalc:=TotalEnt;
  280. TopLeftCol:=TopBar*ScreenWidth;
  281. X:=TopLeftCol;
  282. lpos:=position+maxent;
  283. // First the dirs;
  284. i:=Position;
  285. If I<Totalc THen
  286. Begin
  287. REPEAT
  288. If I<dirc Then
  289. S:=TheDirs[I]
  290. Else
  291. S:=TheFiles[I-dirc];
  292. m:=Length(s);
  293. if m>wdth Then
  294. m:=wdth;
  295. For o:=0 to m-1 do
  296. VideoBuf^[X+O]:=Ord(S[o+1])+(Attributes[ORD(Marked[I])] shl 8);
  297. inc(X,screenwidth);
  298. If X>=botrightcol Then
  299. Begin
  300. TopLeftCol:=TopLeftCol+wdth+1;
  301. x:=TopLeftCol;
  302. End;
  303. Inc(I);
  304. Until (i>=lpos) or (I>=totalc);
  305. {$ifdef debug}
  306. // Writeln(F,'lpos :',lpos);
  307. // writeln(F,'i :',i);
  308. // writeln(F,'totalc:',totalc);
  309. {$endif}
  310. End;
  311. end;
  312. Procedure TVidDirList.Hilight(Curs,Home:Integer;Onx:Integer);
  313. Var I : Integer;
  314. Posx : Integer;
  315. L : PWord;
  316. Attr : Integer;
  317. Begin
  318. Attr:=Attributes[ORD(Marked[Curs])+Onx shl 1] shl 8;
  319. Posx:=Curs-Home;
  320. L:=@VideoBuf[(Posx DIV Colh)*(wdth+1) + (TopBar+ Posx MOD Colh)*screenWidth];
  321. For I:= 0 TO wdth-1 DO
  322. Begin
  323. L^:=(L^ And 255) + Attr;
  324. Inc(L);
  325. End;
  326. End;
  327. procedure TVidDirList.ClearArea;
  328. Begin
  329. TextClear(1,2,screenwidth*(screenheight-topbar-bottombar));
  330. End;
  331. {$ifdef Win32}
  332. Function TVidDirList.CheckAssociation(ext:String):String;
  333. Var S : String;
  334. Begin
  335. if Reg.OpenKey(ext, false) then
  336. begin
  337. Reg.CloseKey;
  338. // Reg.Free;
  339. Exit('');
  340. end;
  341. Reg.OpenKey('\'+ext, True);
  342. S:=Reg.readString('');
  343. Reg.closekey;
  344. Reg.OpenKey('\'+S+'\Shell\Open\Command', True);
  345. Result:=Reg.ReadString('');
  346. reg.closekey;
  347. End;
  348. {$endif}
  349. end.
  350. {
  351. $Log$
  352. Revision 1.2 2005-04-06 20:16:48 marco
  353. * deletefile support
  354. Revision 1.1 2005/04/06 08:54:16 marco
  355. * new Unix demo: lister
  356. }