flist.pas 10 KB

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