tabs.pas 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730
  1. {
  2. Tabbed group for TV/FV dialogs
  3. Copyright 2000-4 by Free Pascal core team
  4. This library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Library General Public
  6. License as published by the Free Software Foundation; either
  7. version 2 of the License, or (at your option) any later version.
  8. This library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Library General Public License for more details.
  12. You should have received a copy of the GNU Library General Public
  13. License along with this library; if not, write to the Free
  14. Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************}
  16. unit tabs;
  17. interface
  18. uses
  19. objects, drivers, views, fvconsts;
  20. {$I platform.inc} (* Multi-platform support defines *)
  21. type
  22. PTabItem = ^TTabItem;
  23. TTabItem = record
  24. Next : PTabItem;
  25. View : PView;
  26. Dis : boolean;
  27. end;
  28. PTabDef = ^TTabDef;
  29. TTabDef = record
  30. Next : PTabDef;
  31. Name : PString;
  32. Items : PTabItem;
  33. DefItem : PView;
  34. ShortCut : char;
  35. end;
  36. PTab = ^TTab;
  37. TTab = object(TGroup)
  38. TabDefs : PTabDef;
  39. ActiveDef : integer;
  40. DefCount : word;
  41. constructor Init(var Bounds: TRect; ATabDef: PTabDef);
  42. constructor Load (var S: TStream);
  43. function AtTab(Index: integer): PTabDef; virtual;
  44. procedure SelectTab(Index: integer); virtual;
  45. procedure Store (var S: TStream);
  46. function TabCount: integer;
  47. function Valid(Command: Word): Boolean; virtual;
  48. procedure ChangeBounds(var Bounds: TRect); virtual;
  49. procedure HandleEvent(var Event: TEvent); virtual;
  50. function GetPalette: PPalette; virtual;
  51. procedure Draw; virtual;
  52. function DataSize: sw_word;virtual;
  53. procedure SetData(var Rec);virtual;
  54. procedure GetData(var Rec);virtual;
  55. procedure SetState(AState: Word; Enable: Boolean); virtual;
  56. destructor Done; virtual;
  57. private
  58. InDraw: boolean;
  59. function FirstSelectable: PView;
  60. function LastSelectable: PView;
  61. end;
  62. function NewTabItem(AView: PView; ANext: PTabItem): PTabItem;
  63. procedure DisposeTabItem(P: PTabItem);
  64. function NewTabDef(AName: string; ADefItem: PView; AItems: PTabItem; ANext: PTabDef): PTabDef;
  65. procedure DisposeTabDef(P: PTabDef);
  66. procedure RegisterTab;
  67. const
  68. RTab: TStreamRec = (
  69. ObjType: idTab;
  70. {$IFDEF BP_VMTLink} { BP style VMT link }
  71. VmtLink: Ofs (TypeOf (TTab)^);
  72. {$ELSE BP_VMTLink} { Alt style VMT link }
  73. VmtLink: TypeOf (TTab);
  74. {$ENDIF BP_VMTLink}
  75. Load: @TTab.Load;
  76. Store: @TTab.Store
  77. );
  78. implementation
  79. uses
  80. FvCommon,dialogs;
  81. constructor TTab.Init(var Bounds: TRect; ATabDef: PTabDef);
  82. begin
  83. inherited Init(Bounds);
  84. Options:=Options or ofSelectable or ofFirstClick or ofPreProcess or ofPostProcess;
  85. GrowMode:=gfGrowHiX+gfGrowHiY+gfGrowRel;
  86. TabDefs:=ATabDef;
  87. ActiveDef:=-1;
  88. SelectTab(0);
  89. ReDraw;
  90. end;
  91. constructor TTab.Load (var S: TStream);
  92. function DoLoadTabItems (var XDefItem: PView; ActItem: longint): PTabItem;
  93. var
  94. Count: longint;
  95. Cur, First: PTabItem;
  96. Last: ^PTabItem;
  97. begin
  98. Cur := nil; { Preset nil }
  99. Last := @First; { Start on first item }
  100. S.Read (Count, SizeOf(Count)); { Read item count }
  101. while (Count > 0) do
  102. begin
  103. New (Cur); { New status item }
  104. Last^ := Cur; { First chain part }
  105. if (Cur <> nil) then { Check pointer valid }
  106. begin
  107. Last := @Cur^.Next; { Chain complete }
  108. S.Read (Cur^.Dis, SizeOf (Cur^.Dis));
  109. Cur^.View := PView (S.Get);
  110. if ActItem = 0 then
  111. XDefItem := Cur^.View; { Find default view }
  112. end;
  113. Dec (Count); { One item loaded }
  114. Dec (ActItem);
  115. end;
  116. Last^ := nil; { Now chain end }
  117. DoLoadTabItems := First; { Return the list }
  118. end;
  119. function DoLoadTabDefs: PTabDef;
  120. var
  121. Count: longint;
  122. Cur, First: PTabDef;
  123. Last: ^PTabDef;
  124. ActItem: longint;
  125. begin
  126. Last := @First; { Start on first }
  127. Count := DefCount;
  128. while (Count > 0) do
  129. begin
  130. New (Cur); { New status def }
  131. Last^ := Cur; { First part of chain }
  132. if (Cur <> nil) then { Check pointer valid }
  133. begin
  134. Last := @Cur^.Next; { Chain complete }
  135. Cur^.Name := S.ReadStr; { Read name }
  136. S.Read (Cur^.ShortCut, SizeOf (Cur^.ShortCut));
  137. S.Read (ActItem, SizeOf (ActItem));
  138. Cur^.Items := DoLoadTabItems (Cur^.DefItem, ActItem); { Set pointer }
  139. end;
  140. Dec (Count); { One item loaded }
  141. end;
  142. Last^ := nil; { Now chain ends }
  143. DoLoadTabDefs := First; { Return item list }
  144. end;
  145. begin
  146. inherited Load (S);
  147. S.Read (DefCount, SizeOf (DefCount));
  148. S.Read (ActiveDef, SizeOf (ActiveDef));
  149. TabDefs := DoLoadTabDefs;
  150. end;
  151. procedure TTab.Store (var S: TStream);
  152. procedure DoStoreTabItems (Cur: PTabItem; XDefItem: PView);
  153. var
  154. Count: longint;
  155. T: PTabItem;
  156. ActItem: longint;
  157. begin
  158. Count := 0; { Clear count }
  159. T := Cur; { Start on current }
  160. while (T <> nil) do
  161. begin
  162. if T^.View = XDefItem then { Current = active? }
  163. ActItem := Count; { => set order }
  164. Inc (Count); { Count items }
  165. T := T^.Next; { Next item }
  166. end;
  167. S.Write (ActItem, SizeOf (ActItem));
  168. S.Write (Count, SizeOf (Count)); { Write item count }
  169. while (Cur <> nil) do
  170. begin
  171. S.Write (Cur^.Dis, SizeOf (Cur^.Dis));
  172. S.Put (Cur^.View);
  173. end;
  174. end;
  175. procedure DoStoreTabDefs (Cur: PTabDef);
  176. begin
  177. while (Cur <> nil) do
  178. begin
  179. with Cur^ do
  180. begin
  181. S.WriteStr (Cur^.Name); { Write name }
  182. S.Write (Cur^.ShortCut, SizeOf (Cur^.ShortCut));
  183. DoStoreTabItems (Items, DefItem); { Store the items }
  184. end;
  185. Cur := Cur^.Next; { Next status item }
  186. end;
  187. end;
  188. begin
  189. inherited Store (S);
  190. S.Write (DefCount, SizeOf (DefCount));
  191. S.Write (ActiveDef, SizeOf (ActiveDef));
  192. DoStoreTabDefs (TabDefs);
  193. end;
  194. function TTab.TabCount: integer;
  195. var i: integer;
  196. P: PTabDef;
  197. begin
  198. I:=0; P:=TabDefs;
  199. while (P<>nil) do
  200. begin
  201. Inc(I);
  202. P:=P^.Next;
  203. end;
  204. TabCount:=I;
  205. end;
  206. function TTab.AtTab(Index: integer): PTabDef;
  207. var i: integer;
  208. P: PTabDef;
  209. begin
  210. i:=0; P:=TabDefs;
  211. while (I<Index) do
  212. begin
  213. if P=nil then RunError($AA);
  214. P:=P^.Next;
  215. Inc(i);
  216. end;
  217. AtTab:=P;
  218. end;
  219. procedure TTab.SelectTab(Index: integer);
  220. var P: PTabItem;
  221. V: PView;
  222. begin
  223. if ActiveDef<>Index then
  224. begin
  225. if Owner<>nil then Owner^.Lock;
  226. Lock;
  227. { --- Update --- }
  228. if TabDefs<>nil then
  229. begin
  230. DefCount:=1;
  231. while AtTab(DefCount-1)^.Next<>nil do Inc(DefCount);
  232. end
  233. else DefCount:=0;
  234. if ActiveDef<>-1 then
  235. begin
  236. P:=AtTab(ActiveDef)^.Items;
  237. while P<>nil do
  238. begin
  239. if P^.View<>nil then Delete(P^.View);
  240. P:=P^.Next;
  241. end;
  242. end;
  243. ActiveDef:=Index;
  244. P:=AtTab(ActiveDef)^.Items;
  245. while P<>nil do
  246. begin
  247. if P^.View<>nil then Insert(P^.View);
  248. P:=P^.Next;
  249. end;
  250. V:=AtTab(ActiveDef)^.DefItem;
  251. if V<>nil then V^.Select;
  252. ReDraw;
  253. { --- Update --- }
  254. UnLock;
  255. if Owner<>nil then Owner^.UnLock;
  256. DrawView;
  257. end;
  258. end;
  259. procedure TTab.ChangeBounds(var Bounds: TRect);
  260. var D: TPoint;
  261. procedure DoCalcChange(P: PView); {$ifndef FPC}far;{$endif}
  262. var
  263. R: TRect;
  264. begin
  265. if P^.Owner=nil then Exit; { it think this is a bug in TV }
  266. P^.CalcBounds(R, D);
  267. P^.ChangeBounds(R);
  268. end;
  269. var
  270. P: PTabItem;
  271. I: integer;
  272. begin
  273. D.X := Bounds.B.X - Bounds.A.X - Size.X;
  274. D.Y := Bounds.B.Y - Bounds.A.Y - Size.Y;
  275. inherited ChangeBounds(Bounds);
  276. for I:=0 to TabCount-1 do
  277. if I<>ActiveDef then
  278. begin
  279. P:=AtTab(I)^.Items;
  280. while P<>nil do
  281. begin
  282. if P^.View<>nil then DoCalcChange(P^.View);
  283. P:=P^.Next;
  284. end;
  285. end;
  286. end;
  287. function TTab.FirstSelectable: PView;
  288. var
  289. FV : PView;
  290. begin
  291. FV := First;
  292. while (FV<>nil) and ((FV^.Options and ofSelectable)=0) and (FV<>Last) do
  293. FV:=FV^.Next;
  294. if FV<>nil then
  295. if (FV^.Options and ofSelectable)=0 then FV:=nil;
  296. FirstSelectable:=FV;
  297. end;
  298. function TTab.LastSelectable: PView;
  299. var
  300. LV : PView;
  301. begin
  302. LV := Last;
  303. while (LV<>nil) and ((LV^.Options and ofSelectable)=0) and (LV<>First) do
  304. LV:=LV^.Prev;
  305. if LV<>nil then
  306. if (LV^.Options and ofSelectable)=0 then LV:=nil;
  307. LastSelectable:=LV;
  308. end;
  309. procedure TTab.HandleEvent(var Event: TEvent);
  310. var Index : integer;
  311. I : integer;
  312. X : integer;
  313. Len : byte;
  314. P : TPoint;
  315. V : PView;
  316. CallOrig: boolean;
  317. LastV : PView;
  318. FirstV: PView;
  319. begin
  320. if (Event.What and evMouseDown)<>0 then
  321. begin
  322. MakeLocal(Event.Where,P);
  323. if P.Y<3 then
  324. begin
  325. Index:=-1; X:=1;
  326. for i:=0 to DefCount-1 do
  327. begin
  328. Len:=CStrLen(AtTab(i)^.Name^);
  329. if (P.X>=X) and (P.X<=X+Len+1) then Index:=i;
  330. X:=X+Len+3;
  331. end;
  332. if Index<>-1 then
  333. SelectTab(Index);
  334. end;
  335. end;
  336. if Event.What=evKeyDown then
  337. begin
  338. Index:=-1;
  339. case Event.KeyCode of
  340. kbTab,kbShiftTab :
  341. if GetState(sfSelected) then
  342. begin
  343. if Current<>nil then
  344. begin
  345. LastV:=LastSelectable; FirstV:=FirstSelectable;
  346. if ((Current=LastV) or (Current=PLabel(LastV)^.Link)) and (Event.KeyCode=kbShiftTab) then
  347. begin
  348. if Owner<>nil then Owner^.SelectNext(true);
  349. end else
  350. if ((Current=FirstV) or (Current=PLabel(FirstV)^.Link)) and (Event.KeyCode=kbTab) then
  351. begin
  352. Lock;
  353. if Owner<>nil then Owner^.SelectNext(false);
  354. UnLock;
  355. end else
  356. SelectNext(Event.KeyCode=kbShiftTab);
  357. ClearEvent(Event);
  358. end;
  359. end;
  360. else
  361. for I:=0 to DefCount-1 do
  362. begin
  363. if Upcase(GetAltChar(Event.KeyCode))=AtTab(I)^.ShortCut
  364. then begin
  365. Index:=I;
  366. ClearEvent(Event);
  367. Break;
  368. end;
  369. end;
  370. end;
  371. if Index<>-1 then
  372. begin
  373. Select;
  374. SelectTab(Index);
  375. V:=AtTab(ActiveDef)^.DefItem;
  376. if V<>nil then V^.Focus;
  377. end;
  378. end;
  379. CallOrig:=true;
  380. if Event.What=evKeyDown then
  381. begin
  382. if ((Owner<>nil) and (Owner^.Phase=phPostProcess) and (GetAltChar(Event.KeyCode)<>#0)) or GetState(sfFocused)
  383. then
  384. else CallOrig:=false;
  385. end;
  386. if CallOrig then inherited HandleEvent(Event);
  387. end;
  388. function TTab.GetPalette: PPalette;
  389. begin
  390. GetPalette:=nil;
  391. end;
  392. procedure TTab.Draw;
  393. var B : TDrawBuffer;
  394. i : integer;
  395. C1,C2,C3,C : word;
  396. HeaderLen : integer;
  397. X,X2 : integer;
  398. Name : PString;
  399. ActiveKPos : integer;
  400. ActiveVPos : integer;
  401. FC : char;
  402. procedure SWriteBuf(X,Y,W,H: integer; var Buf);
  403. var i: integer;
  404. begin
  405. if Y+H>Size.Y then H:=Size.Y-Y;
  406. if X+W>Size.X then W:=Size.X-X;
  407. if Buffer=nil then WriteBuf(X,Y,W,H,Buf)
  408. else for i:=1 to H do
  409. Move(Buf,Buffer^[X+(Y+i-1)*Size.X],W*2);
  410. end;
  411. procedure ClearBuf;
  412. begin
  413. MoveChar(B,' ',C1,Size.X);
  414. end;
  415. begin
  416. if InDraw then Exit;
  417. InDraw:=true;
  418. { - Start of TGroup.Draw - }
  419. { if Buffer = nil then
  420. begin
  421. GetBuffer;
  422. end; }
  423. { - Start of TGroup.Draw - }
  424. C1:=GetColor(1);
  425. C2:=(GetColor(7) and $f0 or $08)+GetColor(9)*256;
  426. C3:=GetColor(8)+GetColor({9}8)*256;
  427. { Calculate the size of the headers }
  428. HeaderLen:=0;
  429. for i:=0 to DefCount-1 do
  430. HeaderLen:=HeaderLen+CStrLen(AtTab(i)^.Name^)+3;
  431. Dec(HeaderLen);
  432. if HeaderLen>Size.X-2 then HeaderLen:=Size.X-2;
  433. { --- 1. sor --- }
  434. ClearBuf; MoveChar(B[0],'³',C1,1); MoveChar(B[HeaderLen+1],'³',C1,1);
  435. X:=1;
  436. for i:=0 to DefCount-1 do
  437. begin
  438. Name:=AtTab(i)^.Name; X2:=CStrLen(Name^);
  439. if i=ActiveDef
  440. then begin
  441. ActiveKPos:=X-1;
  442. ActiveVPos:=X+X2+2;
  443. if GetState(sfFocused) then C:=C3 else C:=C2;
  444. end
  445. else C:=C2;
  446. MoveCStr(B[X],' '+Name^+' ',C); X:=X+X2+3;
  447. MoveChar(B[X-1],'³',C1,1);
  448. end;
  449. SWriteBuf(0,1,Size.X,1,B);
  450. { --- 0. sor --- }
  451. ClearBuf; MoveChar(B[0],'Ú',C1,1);
  452. X:=1;
  453. for i:=0 to DefCount-1 do
  454. begin
  455. if I<ActiveDef then FC:='Ú'
  456. else FC:='¿';
  457. X2:=CStrLen(AtTab(i)^.Name^)+2;
  458. MoveChar(B[X+X2],{'Â'}FC,C1,1);
  459. if i=DefCount-1 then X2:=X2+1;
  460. if X2>0 then
  461. MoveChar(B[X],'Ä',C1,X2);
  462. X:=X+X2+1;
  463. end;
  464. MoveChar(B[HeaderLen+1],'¿',C1,1);
  465. MoveChar(B[ActiveKPos],'Ú',C1,1); MoveChar(B[ActiveVPos],'¿',C1,1);
  466. SWriteBuf(0,0,Size.X,1,B);
  467. { --- 2. sor --- }
  468. MoveChar(B[1],'Ä',C1,Max(HeaderLen,0)); MoveChar(B[HeaderLen+2],'Ä',C1,Max(Size.X-HeaderLen-3,0));
  469. MoveChar(B[Size.X-1],'¿',C1,1);
  470. MoveChar(B[ActiveKPos],'Ù',C1,1);
  471. if ActiveDef=0 then MoveChar(B[0],'³',C1,1)
  472. else MoveChar(B[0],{'Ã'}'Ú',C1,1);
  473. MoveChar(B[HeaderLen+1],'Ä'{'Á'},C1,1); MoveChar(B[ActiveVPos],'À',C1,1);
  474. MoveChar(B[ActiveKPos+1],' ',C1,Max(ActiveVPos-ActiveKPos-1,0));
  475. SWriteBuf(0,2,Size.X,1,B);
  476. { --- marad‚k sor --- }
  477. ClearBuf; MoveChar(B[0],'³',C1,1); MoveChar(B[Size.X-1],'³',C1,1);
  478. {SWriteBuf(0,3,Size.X,Size.Y-4,B);}
  479. for i:=3 to Size.Y-1 do
  480. SWriteBuf(0,i,Size.X,1,B);
  481. { --- Size.X . sor --- }
  482. MoveChar(B[0],'À',C1,1); MoveChar(B[1],'Ä',C1,Max(Size.X-2,0)); MoveChar(B[Size.X-1],'Ù',C1,1);
  483. SWriteBuf(0,Size.Y-1,Size.X,1,B);
  484. { - End of TGroup.Draw - }
  485. if Buffer <> nil then
  486. begin
  487. Lock;
  488. Redraw;
  489. UnLock;
  490. end;
  491. if Buffer <> nil then
  492. WriteBuf(0, 0, Size.X, Size.Y, Buffer^)
  493. else
  494. Redraw;
  495. { - End of TGroup.Draw - }
  496. InDraw:=false;
  497. end;
  498. function TTab.Valid(Command: Word): Boolean;
  499. var PT : PTabDef;
  500. PI : PTabItem;
  501. OK : boolean;
  502. begin
  503. OK:=true;
  504. PT:=TabDefs;
  505. while (PT<>nil) and (OK=true) do
  506. begin
  507. PI:=PT^.Items;
  508. while (PI<>nil) and (OK=true) do
  509. begin
  510. if PI^.View<>nil then OK:=OK and PI^.View^.Valid(Command);
  511. PI:=PI^.Next;
  512. end;
  513. PT:=PT^.Next;
  514. end;
  515. Valid:=OK;
  516. end;
  517. procedure TTab.SetData(var Rec);
  518. type
  519. Bytes = array[0..65534] of Byte;
  520. var
  521. I: Sw_Word;
  522. PT : PTabDef;
  523. PI : PTabItem;
  524. begin
  525. I := 0;
  526. PT:=TabDefs;
  527. while (PT<>nil) do
  528. begin
  529. PI:=PT^.Items;
  530. while (PI<>nil) do
  531. begin
  532. if PI^.View<>nil then
  533. begin
  534. PI^.View^.SetData(Bytes(Rec)[I]);
  535. Inc(I, PI^.View^.DataSize);
  536. end;
  537. PI:=PI^.Next;
  538. end;
  539. PT:=PT^.Next;
  540. end;
  541. end;
  542. function TTab.DataSize: sw_word;
  543. var
  544. I: Sw_Word;
  545. PT : PTabDef;
  546. PI : PTabItem;
  547. begin
  548. I := 0;
  549. PT:=TabDefs;
  550. while (PT<>nil) do
  551. begin
  552. PI:=PT^.Items;
  553. while (PI<>nil) do
  554. begin
  555. if PI^.View<>nil then
  556. begin
  557. Inc(I, PI^.View^.DataSize);
  558. end;
  559. PI:=PI^.Next;
  560. end;
  561. PT:=PT^.Next;
  562. end;
  563. DataSize:=i;
  564. end;
  565. procedure TTab.GetData(var Rec);
  566. type
  567. Bytes = array[0..65534] of Byte;
  568. var
  569. I: Sw_Word;
  570. PT : PTabDef;
  571. PI : PTabItem;
  572. begin
  573. I := 0;
  574. PT:=TabDefs;
  575. while (PT<>nil) do
  576. begin
  577. PI:=PT^.Items;
  578. while (PI<>nil) do
  579. begin
  580. if PI^.View<>nil then
  581. begin
  582. PI^.View^.GetData(Bytes(Rec)[I]);
  583. Inc(I, PI^.View^.DataSize);
  584. end;
  585. PI:=PI^.Next;
  586. end;
  587. PT:=PT^.Next;
  588. end;
  589. end;
  590. procedure TTab.SetState(AState: Word; Enable: Boolean);
  591. var
  592. LastV : PView;
  593. begin
  594. inherited SetState(AState,Enable);
  595. { Select first item }
  596. if (AState and sfSelected)<>0 then
  597. begin
  598. LastV:=LastSelectable;
  599. if LastV<>nil then
  600. LastV^.Select;
  601. end;
  602. end;
  603. destructor TTab.Done;
  604. var P,X: PTabDef;
  605. procedure DeleteViews(P: PView); {$ifndef FPC}far;{$endif}
  606. begin
  607. if P<>nil then Delete(P);
  608. end;
  609. begin
  610. ForEach(@DeleteViews);
  611. inherited Done;
  612. P:=TabDefs;
  613. while P<>nil do
  614. begin
  615. X:=P^.Next;
  616. DisposeTabDef(P);
  617. P:=X;
  618. end;
  619. end;
  620. function NewTabItem(AView: PView; ANext: PTabItem): PTabItem;
  621. var P: PTabItem;
  622. begin
  623. New(P); FillChar(P^,SizeOf(P^),0);
  624. P^.Next:=ANext; P^.View:=AView;
  625. NewTabItem:=P;
  626. end;
  627. procedure DisposeTabItem(P: PTabItem);
  628. begin
  629. if P<>nil then
  630. begin
  631. if P^.View<>nil then Dispose(P^.View, Done);
  632. Dispose(P);
  633. end;
  634. end;
  635. function NewTabDef(AName: string; ADefItem: PView; AItems: PTabItem; ANext: PTabDef): PTabDef;
  636. var P: PTabDef;
  637. x: byte;
  638. begin
  639. New(P);
  640. P^.Next:=ANext; P^.Name:=NewStr(AName); P^.Items:=AItems;
  641. x:=pos('~',AName);
  642. if (x<>0) and (x<length(AName)) then P^.ShortCut:=Upcase(AName[x+1])
  643. else P^.ShortCut:=#0;
  644. P^.DefItem:=ADefItem;
  645. NewTabDef:=P;
  646. end;
  647. procedure DisposeTabDef(P: PTabDef);
  648. var PI,X: PTabItem;
  649. begin
  650. DisposeStr(P^.Name);
  651. PI:=P^.Items;
  652. while PI<>nil do
  653. begin
  654. X:=PI^.Next;
  655. DisposeTabItem(PI);
  656. PI:=X;
  657. end;
  658. Dispose(P);
  659. end;
  660. procedure RegisterTab;
  661. begin
  662. RegisterType (RTab);
  663. end;
  664. begin
  665. RegisterTab;
  666. end.