fptools.pas 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732
  1. {
  2. $Id$
  3. This file is part of the Free Pascal Integrated Development Environment
  4. Copyright (c) 1998 by Berczi Gabor
  5. Tool support for the IDE
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program 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.
  11. **********************************************************************}
  12. {$I globdir.inc}
  13. unit FPTools;
  14. interface
  15. uses Objects,Drivers,Views,Dialogs,Validate,
  16. BrowCol,
  17. WViews,
  18. FPViews;
  19. const
  20. MsgFilterSign = 'BI#PIP#OK'#0;
  21. type
  22. TCaptureTarget = (capNone,capMessageWindow,capEditWindow,capNoSwap);
  23. PTool = ^TTool;
  24. TTool = object(TObject)
  25. constructor Init(const ATitle, AProgramPath, ACommandLine: string; AHotKey: word);
  26. function GetTitle: string; virtual;
  27. procedure GetParams(var ATitle, AProgramPath, ACommandLine: string; var AHotKey: word); virtual;
  28. procedure SetParams(const ATitle, AProgramPath, ACommandLine: string; const AHotKey: word); virtual;
  29. destructor Done; virtual;
  30. private
  31. Title : PString;
  32. ProgramPath : PString;
  33. CommandLine : PString;
  34. HotKey : word;
  35. end;
  36. PToolCollection = ^TToolCollection;
  37. TToolCollection = object(TCollection)
  38. function At(Index: sw_Integer): PTool;
  39. end;
  40. PToolListBox = ^TToolListBox;
  41. TToolListBox = object(TAdvancedListBox)
  42. function GetText(Item,MaxLen: Sw_Integer): String; virtual;
  43. end;
  44. PToolParamValidator = ^TToolParamValidator;
  45. TToolParamValidator = object(TValidator)
  46. function IsValid(const S: string): Boolean; virtual;
  47. procedure Error; virtual;
  48. private
  49. ErrorPos: integer;
  50. end;
  51. PToolItemDialog = ^TToolItemDialog;
  52. TToolItemDialog = object(TCenterDialog)
  53. constructor Init(ATool: PTool);
  54. function Execute: Word; virtual;
  55. private
  56. Tool : PTool;
  57. TitleIL : PInputLine;
  58. ProgramIL: PInputLine;
  59. ParamIL : PInputLine;
  60. HotKeyRB : PRadioButtons;
  61. end;
  62. PToolsDialog = ^TToolsDialog;
  63. TToolsDialog = object(TCenterDialog)
  64. constructor Init;
  65. function Execute: Word; virtual;
  66. procedure HandleEvent(var Event: TEvent); virtual;
  67. private
  68. ToolsLB : PToolListBox;
  69. procedure Add;
  70. procedure Edit;
  71. procedure Delete;
  72. end;
  73. PToolMessage = ^TToolMessage;
  74. TToolMessage = object(TMessageItem)
  75. constructor Init(AModule: PString; ALine: string; ARow, ACol: sw_integer);
  76. function GetText(MaxLen: Sw_integer): string; virtual;
  77. end;
  78. PToolMessageListBox = ^TToolMessageListBox;
  79. TToolMessageListBox = object(TMessageListBox)
  80. procedure NewList(AList: PCollection); virtual;
  81. procedure Clear; virtual;
  82. procedure Update; virtual;
  83. function GetPalette: PPalette; virtual;
  84. constructor Load(var S: TStream);
  85. procedure Store(var S: TStream);
  86. destructor Done; virtual;
  87. end;
  88. PMessagesWindow = ^TMessagesWindow;
  89. TMessagesWindow = object(TFPWindow)
  90. constructor Init;
  91. procedure Update; virtual;
  92. procedure HandleEvent(var Event: TEvent); virtual;
  93. function GetPalette: PPalette; virtual;
  94. constructor Load(var S: TStream);
  95. procedure Store(var S: TStream);
  96. destructor Done; virtual;
  97. procedure FocusItem(i : sw_integer);
  98. procedure SizeLimits(var Min, Max: TPoint); virtual;
  99. private
  100. MsgLB : PToolMessageListBox;
  101. end;
  102. procedure InitTools;
  103. function GetToolCount: sw_integer;
  104. function GetToolName(Idx: sw_integer): string;
  105. function AddTool(Title, ProgramPath, Params: string; HotKey: word): sw_integer;
  106. procedure GetToolParams(Idx: sw_integer; var Title, ProgramPath, Params: string; var HotKey: word);
  107. procedure SetToolParams(Idx: sw_integer; Title, ProgramPath, Params: string; HotKey: word);
  108. procedure DoneTools;
  109. function GetHotKeyName(Key: word): string;
  110. function ParseToolParams(var Params: string; CheckOnly: boolean): integer;
  111. function ProcessMessageFile(const MsgFileName: string): boolean;
  112. procedure AddToolCommand(Command: string);
  113. procedure AddToolMessage(ModuleName, Text: string; Row, Col: longint);
  114. procedure ClearToolMessages;
  115. procedure DoneToolMessages;
  116. procedure UpdateToolMessages;
  117. procedure InitToolTempFiles;
  118. procedure DoneToolTempFiles;
  119. const
  120. ToolFilter : string[{$ifndef GABOR}128{$else}40{$endif}] = '';
  121. ToolOutput : string[{$ifndef GABOR}128{$else}40{$endif}] = '';
  122. CaptureToolTo : TCaptureTarget = capNone;
  123. ToolMessages : PCollection = nil;
  124. ToolModuleNames: PStoreCollection = nil;
  125. MessagesWindow : PMessagesWindow = nil;
  126. LastToolMessageFocused : PToolMessage = nil;
  127. LongestTool : sw_integer = 0;
  128. procedure RegisterFPTools;
  129. implementation
  130. uses Dos,
  131. {$ifdef FVISION}
  132. FVConsts,
  133. {$else}
  134. Commands,
  135. {$endif}
  136. App,MsgBox,
  137. WConsts,WUtils,WINI,WEditor,
  138. FPConst,FPString,FPVars,FPUtils;
  139. {$ifndef NOOBJREG}
  140. const
  141. RToolMessageListBox: TStreamRec = (
  142. ObjType: 1600;
  143. VmtLink: Ofs(TypeOf(TToolMessageListBox)^);
  144. Load: @TToolMessageListBox.Load;
  145. Store: @TToolMessageListBox.Store
  146. );
  147. RMessagesWindow: TStreamRec = (
  148. ObjType: 1601;
  149. VmtLink: Ofs(TypeOf(TMessagesWindow)^);
  150. Load: @TMessagesWindow.Load;
  151. Store: @TMessagesWindow.Store
  152. );
  153. {$endif}
  154. type
  155. THotKeyDef = record
  156. Name : string[12];
  157. KeyCode : word;
  158. end;
  159. const
  160. HotKeys : array[0..9] of THotKeyDef =
  161. ( (Name : '~U~nassigned' ; KeyCode : kbNoKey ),
  162. (Name : 'Shift+F~2~' ; KeyCode : kbShiftF2 ),
  163. (Name : 'Shift+F~3~' ; KeyCode : kbShiftF3 ),
  164. (Name : 'Shift+F~4~' ; KeyCode : kbShiftF4 ),
  165. (Name : 'Shift+F~5~' ; KeyCode : kbShiftF5 ),
  166. (Name : 'Shift+F~6~' ; KeyCode : kbShiftF6 ),
  167. (Name : 'Shift+F~7~' ; KeyCode : kbShiftF7 ),
  168. (Name : 'Shift+F~8~' ; KeyCode : kbShiftF8 ),
  169. (Name : 'Shift+F~9~' ; KeyCode : kbShiftF9 ),
  170. (Name : 'Shift+F~1~0' ; KeyCode : kbShiftF10));
  171. Tools : PToolCollection = nil;
  172. AbortTool : boolean = false;
  173. ToolTempFiles: PUnsortedStringCollection = nil;
  174. function GetHotKeyCount: integer;
  175. begin
  176. GetHotKeyCount:=ord(High(HotKeys))-ord(Low(HotKeys))+1;
  177. end;
  178. function GetHotKeyNameByIdx(Idx: integer): string;
  179. begin
  180. GetHotKeyNameByIdx:=HotKeys[Idx].Name;
  181. end;
  182. function HotKeyToIdx(Key: word): integer;
  183. var Count,I: integer;
  184. Found: boolean;
  185. begin
  186. Count:=GetHotKeyCount; Found:=false;
  187. I:=0;
  188. while (I<Count) and (Found=false) do
  189. begin
  190. Found:=HotKeys[I].KeyCode=Key;
  191. if Found=false then
  192. Inc(I);
  193. end;
  194. if Found=false then I:=-1;
  195. HotKeyToIdx:=I;
  196. end;
  197. function IdxToHotKey(Idx: integer): word;
  198. var Count: integer;
  199. Key: word;
  200. begin
  201. Count:=GetHotKeyCount;
  202. if (0<=Idx) and (Idx<Count) then
  203. Key:=HotKeys[Idx].KeyCode
  204. else
  205. Key:=kbNoKey;
  206. IdxToHotKey:=Key;
  207. end;
  208. function GetHotKeyName(Key: word): string;
  209. var Idx: integer;
  210. S: string;
  211. begin
  212. Idx:=HotKeyToIdx(Key);
  213. if Idx=0 then S:='' else
  214. if Idx=-1 then S:='???' else
  215. S:=GetHotKeyNameByIdx(Idx);
  216. GetHotKeyName:=S;
  217. end;
  218. function WriteToolMessagesToFile(FileName: string): boolean;
  219. var OK: boolean;
  220. f: text;
  221. M: PToolMessage;
  222. I: sw_integer;
  223. begin
  224. I:=0;
  225. Assign(f,FileName);
  226. {$I-}
  227. Rewrite(f);
  228. OK:=EatIO=0;
  229. if Assigned(ToolMessages) then
  230. while OK and (I<ToolMessages^.Count) do
  231. begin
  232. M:=ToolMessages^.At(I);
  233. writeln(f,GetStr(M^.Module)+#0+GetStr(M^.Text)+#0+IntToStr(M^.Row)+#0+IntToStr(M^.Col));
  234. Inc(I);
  235. OK:=EatIO=0;
  236. end;
  237. Close(f);
  238. EatIO;
  239. {$I+}
  240. WriteToolMessagesToFile:=OK;
  241. end;
  242. constructor TTool.Init(const ATitle, AProgramPath, ACommandLine: string; AHotKey: word);
  243. begin
  244. inherited Init;
  245. SetParams(ATitle,AProgramPath,ACommandLine,AHotKey);
  246. end;
  247. function TTool.GetTitle: string;
  248. begin
  249. GetTitle:=KillTilde(GetStr(Title));
  250. end;
  251. procedure TTool.GetParams(var ATitle, AProgramPath, ACommandLine: string; var AHotKey: word);
  252. begin
  253. ATitle:=GetStr(Title); AProgramPath:=GetStr(ProgramPath);
  254. ACommandLine:=GetStr(CommandLine);
  255. AHotKey:=HotKey;
  256. end;
  257. procedure TTool.SetParams(const ATitle, AProgramPath, ACommandLine: string; const AHotKey: word);
  258. begin
  259. if Title<>nil then DisposeStr(Title); Title:=nil;
  260. if ProgramPath<>nil then DisposeStr(ProgramPath); ProgramPath:=nil;
  261. if CommandLine<>nil then DisposeStr(CommandLine); CommandLine:=nil;
  262. Title:=NewStr(ATitle); ProgramPath:=NewStr(AProgramPath);
  263. CommandLine:=NewStr(ACommandLine);
  264. HotKey:=AHotKey;
  265. end;
  266. destructor TTool.Done;
  267. begin
  268. inherited Done;
  269. if Title<>nil then DisposeStr(Title);
  270. if ProgramPath<>nil then DisposeStr(ProgramPath);
  271. if CommandLine<>nil then DisposeStr(CommandLine);
  272. end;
  273. function TToolCollection.At(Index: sw_Integer): PTool;
  274. begin
  275. At:=inherited At(Index);
  276. end;
  277. function TToolListBox.GetText(Item,MaxLen: sw_integer): String;
  278. var S: string;
  279. P: PTool;
  280. begin
  281. P:=List^.At(Item);
  282. S:=P^.GetTitle;
  283. GetText:=copy(S,1,MaxLen);
  284. end;
  285. procedure InitTools;
  286. begin
  287. if Tools<>nil then DoneTools;
  288. New(Tools, Init(10,20));
  289. end;
  290. function GetToolCount: sw_integer;
  291. var Count: integer;
  292. begin
  293. if Tools=nil then Count:=0 else
  294. Count:=Tools^.Count;
  295. GetToolCount:=Count;
  296. end;
  297. function GetToolName(Idx: sw_integer): string;
  298. var S1,S2: string;
  299. W: word;
  300. begin
  301. GetToolParams(Idx,S1,S2,S2,W);
  302. GetToolName:=KillTilde(S1);
  303. end;
  304. function AddTool(Title, ProgramPath, Params: string; HotKey: word): sw_integer;
  305. var P: PTool;
  306. begin
  307. if Tools=nil then InitTools;
  308. New(P, Init(Title,ProgramPath,Params,HotKey));
  309. Tools^.Insert(P);
  310. AddTool:=Tools^.IndexOf(P);
  311. end;
  312. procedure GetToolParams(Idx: sw_integer; var Title, ProgramPath, Params: string; var HotKey: word);
  313. var P: PTool;
  314. begin
  315. P:=Tools^.At(Idx);
  316. P^.GetParams(Title,ProgramPath,Params,HotKey);
  317. end;
  318. procedure SetToolParams(Idx: sw_integer; Title, ProgramPath, Params: string; HotKey: word);
  319. var P: PTool;
  320. begin
  321. P:=Tools^.At(Idx);
  322. P^.GetParams(Title,ProgramPath,Params,HotKey);
  323. end;
  324. procedure DoneTools;
  325. begin
  326. if Tools<>nil then Dispose(Tools, Done); Tools:=nil;
  327. end;
  328. procedure TToolParamValidator.Error;
  329. begin
  330. MsgParms[1].Long:=ErrorPos;
  331. ErrorBox(msg_errorparsingparametersatpos,@MsgParms);
  332. end;
  333. function TToolParamValidator.IsValid(const S: string): Boolean;
  334. var P: string;
  335. begin
  336. P:=S;
  337. ErrorPos:=ParseToolParams(P,true);
  338. IsValid:=ErrorPos=0;
  339. end;
  340. constructor TToolItemDialog.Init(ATool: PTool);
  341. var R,R2,R3: TRect;
  342. Items: PSItem;
  343. I,KeyCount: sw_integer;
  344. begin
  345. KeyCount:=GetHotKeyCount;
  346. R.Assign(0,0,60,Max(3+KeyCount,12));
  347. inherited Init(R,dialog_modifynewtool);
  348. Tool:=ATool;
  349. GetExtent(R); R.Grow(-3,-2); R3.Copy(R);
  350. Inc(R.A.Y); R.B.Y:=R.A.Y+1; R.B.X:=R.A.X+36;
  351. New(TitleIL, Init(R, 128)); Insert(TitleIL);
  352. R2.Copy(R); R2.Move(-1,-1); Insert(New(PLabel, Init(R2, label_toolprop_title, TitleIL)));
  353. R.Move(0,3);
  354. New(ProgramIL, Init(R, 128)); Insert(ProgramIL);
  355. R2.Copy(R); R2.Move(-1,-1); Insert(New(PLabel, Init(R2, label_toolprop_programpath, ProgramIL)));
  356. R.Move(0,3);
  357. New(ParamIL, Init(R, 128)); Insert(ParamIL);
  358. ParamIL^.SetValidator(New(PToolParamValidator, Init));
  359. R2.Copy(R); R2.Move(-1,-1); Insert(New(PLabel, Init(R2, label_toolprop_commandline, ParamIL)));
  360. R.Copy(R3); Inc(R.A.X,38); R.B.Y:=R.A.Y+KeyCount;
  361. Items:=nil;
  362. for I:=KeyCount-1 downto 0 do
  363. Items:=NewSItem(GetHotKeyNameByIdx(I), Items);
  364. New(HotKeyRB, Init(R, Items));
  365. Insert(HotKeyRB);
  366. InsertButtons(@Self);
  367. TitleIL^.Select;
  368. end;
  369. function TToolItemDialog.Execute: Word;
  370. var R: word;
  371. S1,S2,S3: string;
  372. W: word;
  373. L: longint;
  374. begin
  375. Tool^.GetParams(S1,S2,S3,W);
  376. TitleIL^.SetData(S1); ProgramIL^.SetData(S2); ParamIL^.SetData(S3);
  377. L:=HotKeyToIdx(W); if L=-1 then L:=255;
  378. HotKeyRB^.SetData(L);
  379. R:=inherited Execute;
  380. if R=cmOK then
  381. begin
  382. TitleIL^.GetData(S1); ProgramIL^.GetData(S2); ParamIL^.GetData(S3);
  383. HotKeyRB^.GetData(L); W:=IdxToHotKey(L);
  384. Tool^.SetParams(S1,S2,S3,W);
  385. end;
  386. Execute:=R;
  387. end;
  388. constructor TToolsDialog.Init;
  389. var R,R2,R3: TRect;
  390. SB: PScrollBar;
  391. begin
  392. R.Assign(0,0,46,16);
  393. inherited Init(R,dialog_tools);
  394. HelpCtx:=hcTools;
  395. GetExtent(R); R.Grow(-3,-2); Inc(R.A.Y); R3.Copy(R); Dec(R.B.X,12);
  396. R2.Copy(R); R2.Move(1,0); R2.A.X:=R2.B.X-1;
  397. New(SB, Init(R2)); Insert(SB);
  398. New(ToolsLB, Init(R,1,SB));
  399. Insert(ToolsLB);
  400. R2.Copy(R); R2.Move(0,-1); R2.B.Y:=R2.A.Y+1; Dec(R2.A.X);
  401. Insert(New(PLabel, Init(R2, label_tools_programtitles, ToolsLB)));
  402. R.Copy(R3); R.A.X:=R.B.X-10; R.B.Y:=R.A.Y+2;
  403. Insert(New(PButton, Init(R, button_OK, cmOK, bfNormal)));
  404. R.Move(0,2);
  405. Insert(New(PButton, Init(R, button_Edit, cmEditItem, bfDefault)));
  406. R.Move(0,2);
  407. Insert(New(PButton, Init(R, button_New, cmAddItem, bfNormal)));
  408. R.Move(0,2);
  409. Insert(New(PButton, Init(R, button_Delete, cmDeleteItem, bfNormal)));
  410. R.Move(0,2);
  411. Insert(New(PButton, Init(R, button_Cancel, cmCancel, bfNormal)));
  412. SelectNext(false);
  413. end;
  414. procedure TToolsDialog.HandleEvent(var Event: TEvent);
  415. var DontClear: boolean;
  416. begin
  417. case Event.What of
  418. evKeyDown :
  419. begin
  420. DontClear:=false;
  421. case Event.KeyCode of
  422. kbIns :
  423. Message(@Self,evCommand,cmAddItem,nil);
  424. kbDel :
  425. Message(@Self,evCommand,cmDeleteItem,nil);
  426. else DontClear:=true;
  427. end;
  428. if DontClear=false then ClearEvent(Event);
  429. end;
  430. evBroadcast :
  431. case Event.Command of
  432. cmListItemSelected :
  433. if Event.InfoPtr=pointer(ToolsLB) then
  434. Message(@Self,evCommand,cmEditItem,nil);
  435. end;
  436. evCommand :
  437. begin
  438. DontClear:=false;
  439. case Event.Command of
  440. cmAddItem : Add;
  441. cmDeleteItem : Delete;
  442. cmEditItem : Edit;
  443. else DontClear:=true;
  444. end;
  445. if DontClear=false then ClearEvent(Event);
  446. end;
  447. end;
  448. inherited HandleEvent(Event);
  449. end;
  450. function TToolsDialog.Execute: Word;
  451. var R: word;
  452. C: PToolCollection;
  453. I: integer;
  454. S1,S2,S3: string;
  455. W: word;
  456. begin
  457. New(C, Init(10,20));
  458. if Tools<>nil then
  459. for I:=0 to Tools^.Count-1 do
  460. begin
  461. Tools^.At(I)^.GetParams(S1,S2,S3,W);
  462. C^.Insert(New(PTool, Init(S1,S2,S3,W)));
  463. end;
  464. ToolsLB^.NewList(C);
  465. R:=inherited Execute;
  466. if R=cmOK then
  467. begin
  468. if Tools<>nil then Dispose(Tools, Done);
  469. Tools:=C;
  470. Message(Application,evBroadcast,cmUpdateTools,nil);
  471. end
  472. else
  473. Dispose(C, Done);
  474. Execute:=R;
  475. end;
  476. procedure TToolsDialog.Add;
  477. var P: PTool;
  478. IC: boolean;
  479. S1,S2,S3: string;
  480. W: word;
  481. begin
  482. if ToolsLB^.Range>=MaxToolCount then
  483. begin InformationBox(msg_cantinstallmoretools,nil); Exit; end;
  484. IC:=ToolsLB^.Range=0;
  485. if IC=false then
  486. begin
  487. P:=ToolsLB^.List^.At(ToolsLB^.Focused);
  488. P^.GetParams(S1,S2,S3,W);
  489. end
  490. else
  491. begin
  492. S1:=''; S2:=''; S3:=''; W:=0;
  493. end;
  494. New(P, Init(S1,S2,S3,W));
  495. if Application^.ExecuteDialog(New(PToolItemDialog, Init(P)), nil)=cmOK then
  496. begin
  497. ToolsLB^.List^.Insert(P);
  498. ToolsLB^.SetRange(ToolsLB^.List^.Count);
  499. ReDraw;
  500. end
  501. else
  502. Dispose(P, Done);
  503. end;
  504. procedure TToolsDialog.Edit;
  505. var P: PTool;
  506. begin
  507. if ToolsLB^.Range=0 then Exit;
  508. P:=ToolsLB^.List^.At(ToolsLB^.Focused);
  509. Application^.ExecuteDialog(New(PToolItemDialog, Init(P)), nil);
  510. ReDraw;
  511. end;
  512. procedure TToolsDialog.Delete;
  513. begin
  514. if ToolsLB^.Range=0 then Exit;
  515. ToolsLB^.List^.AtFree(ToolsLB^.Focused);
  516. ToolsLB^.SetRange(ToolsLB^.List^.Count);
  517. ReDraw;
  518. end;
  519. (*procedure ReplaceStr(var S: string; const What,NewS: string);
  520. var I : integer;
  521. begin
  522. repeat
  523. I:=Pos(What,S);
  524. if I>0 then
  525. begin
  526. Delete(S,I,length(What));
  527. Insert(NewS,S,I);
  528. end;
  529. until I=0;
  530. end;
  531. procedure ReplaceStrI(var S: string; What: string; const NewS: string);
  532. var I : integer;
  533. UpcaseS: string;
  534. begin
  535. UpcaseS:=UpcaseStr(S); What:=UpcaseStr(What);
  536. repeat
  537. I:=Pos(What,UpcaseS);
  538. if I>0 then
  539. begin
  540. Delete(S,I,length(What));
  541. Insert(NewS,S,I);
  542. end;
  543. until I=0;
  544. end;*)
  545. function GetCoordEntry(F: PINIFile; Section, Entry: string; var P: TPoint): boolean;
  546. var OK: boolean;
  547. S: string;
  548. Px: integer;
  549. begin
  550. S:=F^.GetEntry(Section,Entry,'');
  551. S:=Trim(S);
  552. OK:=(S<>'') and (S[1]='(') and (S[length(S)]=')');
  553. if OK then S:=copy(S,2,length(S)-2);
  554. Px:=Pos(',',S);
  555. OK:=OK and (Px>0);
  556. if OK then P.X:=StrToInt(copy(S,1,Px-1));
  557. OK:=OK and (LastStrToIntResult=0);
  558. if OK then P.Y:=StrToInt(copy(S,Px+1,High(S)));
  559. OK:=OK and (LastStrToIntResult=0);
  560. GetCoordEntry:=OK;
  561. end;
  562. function ExecutePromptDialog(const FileName: string; var Params: string): boolean;
  563. const
  564. MaxViews = 20;
  565. MaxViewNameLen = 40;
  566. MaxValueLen = 80;
  567. secMain = 'MAIN';
  568. { Main section entries }
  569. tmeTitle = 'TITLE';
  570. tmeCommandLine = 'COMMANDLINE';
  571. tmeSize = 'SIZE';
  572. tmeDefaultView = 'DEFAULT';
  573. { View section entries }
  574. tieType = 'TYPE';
  575. tieOrigin = 'ORIGIN';
  576. tieSize = 'SIZE';
  577. {*} tieDefault = 'DEFAULT';
  578. tieValue = 'VALUE';
  579. { Additional CheckBox view section entries }
  580. tieName = 'NAME';
  581. tieOnParm = 'ON';
  582. tieOffParm = 'OFF';
  583. { Additional CheckBox view section entries }
  584. tieItem = 'ITEM';
  585. tieParam = 'PARAM';
  586. { Additional InputLine view section entries }
  587. tieMaxLen = 'MAXLEN';
  588. { Additional Label view section entries }
  589. tieLink = 'LINK';
  590. tieText = 'TEXT';
  591. { Additional Memo view section entries }
  592. tieFileName = 'FILENAME';
  593. { View types }
  594. vtCheckBox = 1;
  595. vtRadioButton = 2;
  596. vtInputLine = 3;
  597. vtMemo = 4;
  598. vtLabel = 127;
  599. vtsCheckBox = 'CHECKBOX';
  600. vtsRadioButton = 'RADIOBUTTON';
  601. vtsInputLine = 'INPUTLINE';
  602. vtsLabel = 'LABEL';
  603. vtsMemo = 'MEMO';
  604. var Title : string;
  605. DSize : TPoint;
  606. CmdLine : string;
  607. ViewCount : Sw_integer;
  608. ViewNames : array[0..MaxViews-1] of string[MaxViewNameLen];
  609. ViewTypes : array[0..MaxViews-1] of byte;
  610. ViewBounds : array[0..MaxViews-1] of TRect;
  611. ViewPtrs : array[0..MaxViews-1] of PView;
  612. ViewValues : array[0..MaxViews-1] of string[MaxValueLen];
  613. ViewItemCount: array[0..MaxViews-1] of sw_integer;
  614. function BuildPromptDialogInfo(F: PINIFile): boolean;
  615. var
  616. OK: boolean;
  617. _IS: PINISection;
  618. procedure ProcessSection(Sec: PINISection);{$ifndef FPC}far;{$endif}
  619. var P1,P2: TPoint;
  620. Typ: string;
  621. Count: sw_integer;
  622. begin
  623. if (OK=false) or
  624. ( (UpcaseStr(Sec^.GetName)=secMain) or
  625. (UpcaseStr(Sec^.GetName)=UpcaseStr(MainSectionName)) ) then
  626. Exit;
  627. ViewItemCount[ViewCount]:=0;
  628. OK:=(Sec^.SearchEntry(tieType)<>nil) and
  629. (Sec^.SearchEntry(tieOrigin)<>nil) and
  630. (Sec^.SearchEntry(tieSize)<>nil);
  631. if OK=false then
  632. begin ErrorBox(FormatStrStr(msg_requiredparametermissingin,Sec^.GetName),nil); Exit; end;
  633. Typ:=UpcaseStr(Trim(F^.GetEntry(Sec^.GetName,tieType,'')));
  634. if Typ=vtsCheckBox then ViewTypes[ViewCount]:=vtCheckBox else
  635. if Typ=vtsRadioButton then ViewTypes[ViewCount]:=vtRadioButton else
  636. if Typ=vtsInputLine then ViewTypes[ViewCount]:=vtInputLine else
  637. if Typ=vtsLabel then ViewTypes[ViewCount]:=vtLabel else
  638. if Typ=vtsMemo then ViewTypes[ViewCount]:=vtMemo else
  639. begin OK:=false; ErrorBox(FormatStrStr(msg_unknowntypein,Sec^.GetName),nil); Exit; end;
  640. ViewNames[ViewCount]:=Sec^.GetName;
  641. GetCoordEntry(F,Sec^.GetName,tieOrigin,P1);
  642. GetCoordEntry(F,Sec^.GetName,tieSize,P2);
  643. ViewBounds[ViewCount].Assign(P1.X,P1.Y,P1.X+P2.X,P1.Y+P2.Y);
  644. { allow conversion of $EDNAME for instance in
  645. default values PM }
  646. Typ:=F^.GetEntry(Sec^.GetName,tieValue,'');
  647. ParseToolParams(Typ,true);
  648. ViewValues[ViewCount]:=Typ;
  649. case ViewTypes[ViewCount] of
  650. vtLabel :
  651. begin
  652. OK:=OK and (Sec^.SearchEntry(tieLink)<>nil) and
  653. (Sec^.SearchEntry(tieText)<>nil);
  654. if OK=false then
  655. begin ErrorBox(FormatStrStr(msg_requiredpropertymissingin,Sec^.GetName),nil); Exit; end;
  656. end;
  657. vtInputLine : ;
  658. vtMemo : ;
  659. vtCheckBox :
  660. begin
  661. OK:=OK and (Sec^.SearchEntry(tieName)<>nil);
  662. if OK=false then
  663. begin ErrorBox(FormatStrStr2(msg_propertymissingin,tieName,Sec^.GetName),nil); Exit; end;
  664. end;
  665. vtRadioButton:
  666. begin
  667. Count:=0;
  668. while Sec^.SearchEntry(tieItem+IntToStr(Count+1))<>nil do
  669. Inc(Count);
  670. ViewItemCount[ViewCount]:=Count;
  671. OK:=Count>0;
  672. if OK=false then
  673. begin ErrorBox(FormatStrStr(msg_invaliditemsin,Sec^.GetName),nil); Exit; end;
  674. end;
  675. end;
  676. if OK then Inc(ViewCount);
  677. end;
  678. begin
  679. BuildPromptDialogInfo:=false;
  680. _IS:=F^.SearchSection(secMain);
  681. OK:=_IS<>nil;
  682. if OK then OK:=(_IS^.SearchEntry(tmeTitle)<>nil) and
  683. (_IS^.SearchEntry(tmeSize)<>nil) and
  684. (_IS^.SearchEntry(tmeCommandLine)<>nil);
  685. if OK then
  686. begin
  687. Title:=F^.GetEntry(secMain,tmeTitle,'');
  688. OK:=OK and GetCoordEntry(F,secMain,tmeSize,DSize);
  689. CmdLine:=F^.GetEntry(secMain,tmeCommandLine,'');
  690. OK:=OK and (CmdLine<>'');
  691. end;
  692. if OK=false then
  693. begin ErrorBox(FormatStrStr(msg_requiredpropertymissingin,_IS^.GetName),nil); Exit; end;
  694. if OK then
  695. begin
  696. ViewCount:=0;
  697. F^.ForEachSection(@ProcessSection);
  698. end;
  699. BuildPromptDialogInfo:=OK;
  700. end;
  701. function SearchViewByName(Name: string): integer;
  702. var I,Idx: Sw_integer;
  703. begin
  704. Idx:=-1; Name:=UpcaseStr(Name);
  705. for I:=0 to ViewCount-1 do
  706. if UpcaseStr(ViewNames[I])=Name then
  707. begin
  708. Idx:=I;
  709. Break;
  710. end;
  711. SearchViewByName:=Idx;
  712. end;
  713. function GetParamValueStr(F: PINIFile; Idx: integer): string;
  714. var S: string;
  715. Entry: string[20];
  716. begin
  717. S:='???';
  718. case ViewTypes[Idx] of
  719. vtLabel :
  720. S:='';
  721. vtMemo :
  722. begin
  723. S:=F^.GetEntry(ViewNames[Idx],tieFileName,'');
  724. if S='' then S:=GenTempFileName;
  725. ToolTempFiles^.InsertStr(S);
  726. if PFPMemo(ViewPtrs[Idx])^.SaveToFile(S)=false then
  727. ErrorBox(FormatStrStr(msg_errorsavingfile,S),nil);
  728. end;
  729. vtInputLine :
  730. S:=PInputLine(ViewPtrs[Idx])^.Data^;
  731. vtCheckBox :
  732. with PCheckBoxes(ViewPtrs[Idx])^ do
  733. begin
  734. if Mark(0) then Entry:=tieOnParm else Entry:=tieOffParm;
  735. S:=F^.GetEntry(ViewNames[Idx],Entry,'');
  736. end;
  737. vtRadioButton :
  738. with PRadioButtons(ViewPtrs[Idx])^ do
  739. begin
  740. Entry:=tieParam+IntToStr(Value+1);
  741. S:=F^.GetEntry(ViewNames[Idx],Entry,'');
  742. end;
  743. end;
  744. GetParamValueStr:=S;
  745. end;
  746. function ExtractPromptDialogParams(F: PINIFile; var Params: string): boolean;
  747. function ReplacePart(StartP,EndP: integer; const S: string): integer;
  748. begin
  749. Params:=copy(Params,1,StartP-1)+S+copy(Params,EndP+1,255);
  750. ReplacePart:=length(S)-(EndP-StartP+1);
  751. end;
  752. var OptName: string;
  753. OK: boolean;
  754. C: char;
  755. OptStart: integer;
  756. InOpt: boolean;
  757. I,Idx: integer;
  758. S: string;
  759. begin
  760. Params:=CmdLine;
  761. I:=1; InOpt:=false; OK:=true;
  762. while OK and (I<=length(Params)) do
  763. begin
  764. C:=Params[I];
  765. if C='%' then
  766. begin
  767. InOpt:=not InOpt;
  768. if InOpt then
  769. begin
  770. OptName:='';
  771. OptStart:=I;
  772. end
  773. else
  774. begin
  775. OptName:=UpcaseStr(OptName);
  776. Idx:=SearchViewByName(OptName);
  777. OK:=Idx<>-1;
  778. if OK then
  779. begin
  780. S:=GetParamValueStr(F,Idx);
  781. if (S='') and (Params[I+1]=' ') then Inc(I);
  782. I:=I+ReplacePart(OptStart,I,S);
  783. end;
  784. end;
  785. end
  786. else
  787. if InOpt then
  788. OptName:=OptName+C;
  789. Inc(I);
  790. end;
  791. ExtractPromptDialogParams:=OK;
  792. end;
  793. function ExecPromptDialog(F: PINIFile): boolean;
  794. var R: TRect;
  795. PromptDialog: PCenterDialog;
  796. Re: integer;
  797. OK: boolean;
  798. I,J,MaxLen: integer;
  799. Memo: PFPMemo;
  800. IL: PInputLine;
  801. CB: PCheckBoxes;
  802. RB: PRadioButtons;
  803. LV: PLabel;
  804. SI: PSItem;
  805. S: string;
  806. P: PView;
  807. begin
  808. OK:=true;
  809. R.Assign(0,0,DSize.X,DSize.Y);
  810. New(PromptDialog, Init(R, Title));
  811. with PromptDialog^ do
  812. begin
  813. for I:=0 to ViewCount-1 do
  814. begin
  815. case ViewTypes[I] of
  816. vtLabel :
  817. begin
  818. S:=F^.GetEntry(ViewNames[I],tieLink,'');
  819. J:=SearchViewByName(S);
  820. if J=-1 then P:=nil else
  821. P:=ViewPtrs[J];
  822. S:=F^.GetEntry(ViewNames[I],tieText,'');
  823. New(LV, Init(ViewBounds[I], S, P));
  824. ViewPtrs[I]:=LV;
  825. end;
  826. vtInputLine :
  827. begin
  828. MaxLen:=F^.GetIntEntry(ViewNames[I],tieMaxLen,80);
  829. New(IL, Init(ViewBounds[I], MaxLen));
  830. IL^.Data^:=ViewValues[I];
  831. ViewPtrs[I]:=IL;
  832. end;
  833. vtMemo :
  834. begin
  835. { MaxLen:=F^.GetIntEntry(ViewNames[I],tieMaxLen,80);}
  836. New(Memo, Init(ViewBounds[I],nil,nil,nil));
  837. if ViewValues[I]<>'' then
  838. Memo^.AddLine(ViewValues[I]);
  839. ViewPtrs[I]:=Memo;
  840. end;
  841. vtCheckBox :
  842. begin
  843. New(CB, Init(ViewBounds[I],
  844. NewSItem(
  845. F^.GetEntry(ViewNames[I],tieName,''),
  846. nil)));
  847. if StrToInt(ViewValues[I])=1 then
  848. CB^.Press(0);
  849. ViewPtrs[I]:=CB;
  850. end;
  851. vtRadioButton :
  852. begin
  853. SI:=nil;
  854. for J:=ViewItemCount[I] downto 1 do
  855. SI:=NewSItem(F^.GetEntry(ViewNames[I],tieItem+IntToStr(J),''),SI);
  856. New(RB, Init(ViewBounds[I], SI));
  857. RB^.Press(StrToInt(ViewValues[I]));
  858. ViewPtrs[I]:=RB;
  859. end;
  860. end;
  861. Insert(ViewPtrs[I]);
  862. end;
  863. end;
  864. InsertButtons(PromptDialog);
  865. S:=F^.GetEntry(secMain,tmeDefaultView,'');
  866. if S<>'' then
  867. begin
  868. S:=UpcaseStr(S);
  869. I:=0;
  870. while (I<ViewCount) and (UpcaseStr(ViewNames[I])<>S) do
  871. Inc(I);
  872. if UpcaseStr(ViewNames[I])=S then
  873. ViewPtrs[I]^.Select;
  874. end;
  875. Re:=Desktop^.ExecView(PromptDialog);
  876. OK:=OK and (Re=cmOK);
  877. AbortTool:=(Re<>cmOK);
  878. if OK then OK:=ExtractPromptDialogParams(F,Params);
  879. if PromptDialog<>nil then Dispose(PromptDialog, Done);
  880. ExecPromptDialog:=OK;
  881. end;
  882. var OK: boolean;
  883. F: PINIFile;
  884. Fn : string;
  885. begin
  886. Fn:=LocateFile(FileName);
  887. if Fn='' then
  888. Fn:=FileName;
  889. if not ExistsFile(Fn) then
  890. ErrorBox('Can''t read '+Fn,nil)
  891. else
  892. begin
  893. New(F, Init(Fn));
  894. OK:=F<>nil;
  895. if OK then
  896. begin
  897. OK:=BuildPromptDialogInfo(F);
  898. if OK then
  899. OK:=ExecPromptDialog(F);
  900. end;
  901. if F<>nil then Dispose(F, Done);
  902. end;
  903. ExecutePromptDialog:=OK;
  904. end;
  905. function ParseToolParams(var Params: string; CheckOnly: boolean): integer;
  906. var Err: integer;
  907. W: PSourceWindow;
  908. procedure ParseParams(Pass: sw_integer);
  909. var I: sw_integer;
  910. function IsAlpha(Ch: char): boolean;
  911. begin
  912. IsAlpha:=(Upcase(Ch) in['A'..'Z','_','$']);
  913. end;
  914. function ReplacePart(StartP,EndP: integer; const S: string): integer;
  915. begin
  916. Params:=copy(Params,1,StartP-1)+S+copy(Params,EndP+1,255);
  917. ReplacePart:=length(S)-(EndP-StartP+1);
  918. end;
  919. function Consume(Ch: char): boolean;
  920. var OK: boolean;
  921. begin
  922. OK:=Params[I]=Ch;
  923. if OK then Inc(I);
  924. Consume:=OK;
  925. end;
  926. function ReadTill(var S: string; C: char): boolean;
  927. var Found: boolean;
  928. begin
  929. Found:=false; S:='';
  930. while (I<=length(Params)) and (Found=false) do
  931. begin
  932. Found:=Params[I]=C;
  933. if Found=false then
  934. begin
  935. S:=S+Params[I];
  936. Inc(I);
  937. end;
  938. end;
  939. ReadTill:=Found;
  940. end;
  941. var C,PrevC: char;
  942. WordS: string;
  943. LastWordStart: sw_integer;
  944. L: longint;
  945. S: string;
  946. D: DirStr; N: NameStr; E: ExtStr;
  947. begin
  948. I:=1; WordS:=''; LastWordStart:=I; PrevC:=' ';
  949. while (I<=length(Params)+1) and (Err=0) do
  950. begin
  951. if I<=length(Params) then C:=Params[I];
  952. if (I<=length(Params)) and IsAlpha(C) then
  953. begin
  954. if (I=1) or (IsAlpha(PrevC)=false) then
  955. begin WordS:=''; LastWordStart:=I; end;
  956. { if IsAlpha(C) then ForceConcat:=false;}
  957. WordS:=WordS+C;
  958. end
  959. else
  960. begin
  961. WordS:=UpcaseStr(Trim(WordS));
  962. if WordS<>'' then
  963. if (WordS='$CAP') then
  964. begin
  965. if (Pass=0) then
  966. if (Params[I]=' ') and (I<=High(Params)) then Params[I]:='_';
  967. end else
  968. if (WordS='$CAP_MSG') then
  969. begin
  970. if (Pass=2) then
  971. if Consume('(')=false then Err:=I else
  972. if ReadTill(S,')')=false then Err:=I else
  973. begin
  974. Consume(')');
  975. I:=I+ReplacePart(LastWordStart,I-1,'')-1;
  976. ToolFilter:=S;
  977. CaptureToolTo:=capMessageWindow;
  978. end;
  979. end else
  980. if (WordS='$CAP_EDIT') then
  981. begin
  982. if (Pass=3) then
  983. begin
  984. if Consume('(')=false then
  985. I:=I+ReplacePart(LastWordStart,I-1,'')-1
  986. else if ReadTill(S,')')=false then Err:=I else
  987. begin
  988. Consume(')');
  989. I:=I+ReplacePart(LastWordStart,I-1,'')-1;
  990. ToolOutput:=S;
  991. end;
  992. CaptureToolTo:=capEditWindow;
  993. end;
  994. end else
  995. if (WordS='$COL') then
  996. begin
  997. if (Pass=1) then
  998. begin
  999. if W=nil then L:=0 else
  1000. L:=W^.Editor^.CurPos.X+1;
  1001. I:=I+ReplacePart(LastWordStart,I-1,IntToStr(L))-1;
  1002. end;
  1003. end else
  1004. if (WordS='$CONFIG') then
  1005. begin
  1006. if (Pass=1) then
  1007. I:=I+ReplacePart(LastWordStart,I-1,IniFileName)-1;
  1008. end else
  1009. if (WordS='$DIR') then
  1010. begin
  1011. if (Pass=2) then
  1012. if Consume('(')=false then Err:=I else
  1013. if ReadTill(S,')')=false then Err:=I else
  1014. begin
  1015. Consume(')');
  1016. FSplit(S,D,N,E);
  1017. L:=Pos(':',D);if L>0 then Delete(D,1,L);
  1018. I:=I+ReplacePart(LastWordStart,I-1,D)-1;
  1019. end;
  1020. end else
  1021. if (WordS='$DRIVE') then
  1022. begin
  1023. if (Pass=2) then
  1024. if Consume('(')=false then Err:=I else
  1025. if ReadTill(S,')')=false then Err:=I else
  1026. begin
  1027. Consume(')');
  1028. FSplit(S,D,N,E);
  1029. L:=Pos(':',D);
  1030. D:=copy(D,1,L);
  1031. I:=I+ReplacePart(LastWordStart,I-1,D)-1;
  1032. end;
  1033. end else
  1034. if (WordS='$EDNAME') then
  1035. begin
  1036. if (Pass=1) then
  1037. begin
  1038. if W=nil then S:='' else
  1039. S:=W^.Editor^.FileName;
  1040. I:=I+ReplacePart(LastWordStart,I-1,S)-1;
  1041. end;
  1042. end else
  1043. if (WordS='$EXENAME') then
  1044. begin
  1045. if (Pass=1) then
  1046. I:=I+ReplacePart(LastWordStart,I-1,EXEFile)-1;
  1047. end else
  1048. if (WordS='$EXT') then
  1049. begin
  1050. if (Pass=2) then
  1051. if Consume('(')=false then Err:=I else
  1052. if ReadTill(S,')')=false then Err:=I else
  1053. begin
  1054. Consume(')');
  1055. FSplit(S,D,N,E); E:=copy(E,2,High(E));
  1056. I:=I+ReplacePart(LastWordStart,I-1,E)-1;
  1057. end;
  1058. end else
  1059. if (WordS='$LINE') then
  1060. begin
  1061. if (Pass=1) then
  1062. begin
  1063. if W=nil then L:=0 else
  1064. L:=W^.Editor^.CurPos.Y+1;
  1065. I:=I+ReplacePart(LastWordStart,I-1,IntToStr(L))-1;
  1066. end;
  1067. end else
  1068. if (WordS='$NAME') then
  1069. begin
  1070. if (Pass=2) then
  1071. if Consume('(')=false then Err:=I else
  1072. if ReadTill(S,')')=false then Err:=I else
  1073. begin
  1074. Consume(')');
  1075. FSplit(S,D,N,E);
  1076. I:=I+ReplacePart(LastWordStart,I-1,N)-1;
  1077. end;
  1078. end else
  1079. if (WordS='$NAMEEXT') then
  1080. begin
  1081. if (Pass=2) then
  1082. if Consume('(')=false then Err:=I else
  1083. if ReadTill(S,')')=false then Err:=I else
  1084. begin
  1085. Consume(')');
  1086. FSplit(S,D,N,E);
  1087. I:=I+ReplacePart(LastWordStart,I-1,N+E)-1;
  1088. end;
  1089. end else
  1090. if (WordS='$NOSWAP') then
  1091. begin
  1092. if (Pass=1) then
  1093. begin
  1094. I:=I+ReplacePart(LastWordStart,I-1,'')-1;
  1095. CaptureToolTo:=capNoSwap;
  1096. end;
  1097. end else
  1098. if (WordS='$DRIVE') then
  1099. begin
  1100. if (Pass=2) then
  1101. if Consume('(')=false then Err:=I else
  1102. if ReadTill(S,')')=false then Err:=I else
  1103. begin
  1104. Consume(')');
  1105. FSplit(S,D,N,E);
  1106. L:=Pos(':',D); if L=0 then L:=-1;
  1107. D:=copy(D,1,L+1);
  1108. I:=I+ReplacePart(LastWordStart,I-1,D)-1;
  1109. end;
  1110. end else
  1111. if (WordS='$PROMPT') then
  1112. begin
  1113. if (Pass=3) then
  1114. if Params[I]='(' then
  1115. begin
  1116. if Consume('(')=false then Err:=I else
  1117. if ReadTill(S,')')=false then Err:=I else
  1118. begin
  1119. Consume(')');
  1120. if S='' then Err:=I-1 else
  1121. if CheckOnly=false then
  1122. if ExecutePromptDialog(S,S)=false then
  1123. Err:=I
  1124. else
  1125. I:=I+ReplacePart(LastWordStart,I-1,S)-1;
  1126. end;
  1127. end
  1128. else { just prompt for parms }
  1129. begin
  1130. I:=I+ReplacePart(LastWordStart,I-1,'')-1;
  1131. if CheckOnly=false then
  1132. begin
  1133. S:=copy(Params,I+1,High(Params));
  1134. if InputBox(dialog_programarguments, label_enterprogramargument,
  1135. S,High(Params)-I+1)=cmOK then
  1136. begin
  1137. ReplacePart(LastWordStart,255,S);
  1138. I:=255;
  1139. end
  1140. else
  1141. Err:=-1;
  1142. end;
  1143. end;
  1144. end else
  1145. if (WordS='$SAVE') then
  1146. begin
  1147. if (Pass=0) then
  1148. if (Params[I]=' ') and (I<=High(Params)) then Params[I]:='_';
  1149. end else
  1150. if (WordS='$SAVE_ALL') then
  1151. begin
  1152. if (Pass=2) then
  1153. begin
  1154. I:=I+ReplacePart(LastWordStart,I-1,'')-1;
  1155. Message(Application,evCommand,cmSaveAll,nil);
  1156. end;
  1157. end else
  1158. if (WordS='$SAVE_CUR') then
  1159. begin
  1160. if (Pass=2) then
  1161. begin
  1162. I:=I+ReplacePart(LastWordStart,I-1,'')-1;
  1163. Message(W,evCommand,cmSave,nil);
  1164. end;
  1165. end else
  1166. if (WordS='$SAVE_PROMPT') then
  1167. begin
  1168. if (Pass=2) then
  1169. begin
  1170. I:=I+ReplacePart(LastWordStart,I-1,'')-1;
  1171. if W<>nil then
  1172. if W^.Editor^.SaveAsk(true)=false then
  1173. Err:=-1;
  1174. end;
  1175. end else
  1176. if (WordS='$WRITEMSG') then
  1177. begin
  1178. if (Pass=2) then
  1179. if Consume('(')=false then Err:=I else
  1180. if ReadTill(S,')')=false then Err:=I else
  1181. begin
  1182. Consume(')');
  1183. I:=I+ReplacePart(LastWordStart,I-1,'')-1;
  1184. if CheckOnly=false then
  1185. WriteToolMessagesToFile(S);
  1186. end;
  1187. end else
  1188. if copy(WordS,1,1)='$' then
  1189. Err:=LastWordStart;
  1190. WordS:='';
  1191. end;
  1192. PrevC:=C;
  1193. Inc(I);
  1194. end;
  1195. end;
  1196. var Pass: sw_integer;
  1197. begin
  1198. AbortTool:=false;
  1199. CaptureToolTo:=capNone;
  1200. ToolFilter:='';
  1201. W:=FirstEditorWindow;
  1202. Err:=0;
  1203. for Pass:=0 to 3 do
  1204. begin
  1205. ParseParams(Pass);
  1206. if Err<>0 then Break;
  1207. end;
  1208. if AbortTool then Err:=-1;
  1209. ParseToolParams:=Err;
  1210. end;
  1211. function ProcessMessageFile(const MsgFileName: string): boolean;
  1212. var OK,Done: boolean;
  1213. S: PBufStream;
  1214. C: char;
  1215. Sign: array[1..10] of char;
  1216. InFileName,InReference: boolean;
  1217. AddChar: boolean;
  1218. FileName,Line: string;
  1219. Row,Col: longint;
  1220. procedure AddLine;
  1221. begin
  1222. Row:=ord(Line[1])+ord(Line[2]) shl 8;
  1223. Col:=ord(Line[3])+ord(Line[4]) shl 8;
  1224. AddToolMessage(FileName,copy(Line,5,High(Line)),Row,Col);
  1225. end;
  1226. begin
  1227. New(S, Init(MsgFileName, stOpenRead, 4096));
  1228. OK:=(S<>nil) and (S^.Status=stOK);
  1229. if OK then S^.Read(Sign,SizeOf(Sign));
  1230. OK:=OK and (Sign=MsgFilterSign);
  1231. Done:=false; InFileName:=false; InReference:=false;
  1232. while OK and (Done=false) do
  1233. begin
  1234. S^.Read(C,SizeOf(C));
  1235. OK:=(S^.Status=stOK);
  1236. AddChar:=false;
  1237. if OK then
  1238. case C of
  1239. #0 : if InFileName then
  1240. begin InFileName:=false end else
  1241. if InReference then
  1242. begin
  1243. if (length(Line)>4) then
  1244. begin
  1245. AddLine;
  1246. InReference:=false;
  1247. end
  1248. else
  1249. AddChar:=true;
  1250. end else
  1251. begin InFileName:=true; FileName:=''; end;
  1252. #1 : if InReference then AddChar:=true else
  1253. begin InReference:=true; Line:=''; end;
  1254. #127 : if InReference then AddChar:=true else
  1255. Done:=true;
  1256. else AddChar:=true;
  1257. end;
  1258. if AddChar then
  1259. if InFileName then
  1260. FileName:=FileName+C else
  1261. if InReference then
  1262. Line:=Line+C;
  1263. end;
  1264. if S<>nil then Dispose(S, Done);
  1265. ProcessMessageFile:=OK;
  1266. end;
  1267. procedure InitToolTempFiles;
  1268. begin
  1269. if not Assigned(ToolTempFiles) then
  1270. New(ToolTempFiles, Init(10,10));
  1271. end;
  1272. procedure DoneToolTempFiles;
  1273. procedure DeleteIt(P: PString); {$ifndef FPC}far;{$endif}
  1274. begin
  1275. DeleteFile(GetStr(P));
  1276. end;
  1277. begin
  1278. if not Assigned(ToolTempFiles) then Exit;
  1279. ToolTempFiles^.ForEach(@DeleteIt);
  1280. Dispose(ToolTempFiles, Done); ToolTempFiles:=nil;
  1281. end;
  1282. constructor TToolMessage.Init(AModule: PString; ALine: string; ARow, ACol: sw_integer);
  1283. begin
  1284. inherited Init(0,ALine,AModule,ARow,ACol);
  1285. if LongestTool<Length(Aline)+Length(GetStr(AModule))+4 then
  1286. LongestTool:=Length(Aline)+Length(GetStr(AModule))+4;
  1287. end;
  1288. function TToolMessage.GetText(MaxLen: Sw_integer): string;
  1289. var S: string;
  1290. begin
  1291. if Module=nil then
  1292. S:=GetStr(Text)
  1293. else
  1294. S:=NameAndExtOf(GetModuleName)+
  1295. '('+IntToStr(Row)+'): '+GetStr(Text);
  1296. GetText:=copy(S,1,MaxLen);
  1297. end;
  1298. procedure AddToolCommand(Command: string);
  1299. begin
  1300. AddToolMessage('',Command,0,0);
  1301. LastToolMessageFocused:=ToolMessages^.At(ToolMessages^.Count-1);
  1302. end;
  1303. procedure AddToolMessage(ModuleName, Text: string; Row, Col: longint);
  1304. var MN: PString;
  1305. begin
  1306. if ToolMessages=nil then
  1307. New(ToolMessages, Init(500,1000));
  1308. if ToolModuleNames=nil then
  1309. New(ToolModuleNames, Init(50,100));
  1310. MN:=ToolModuleNames^.Add(ModuleName);
  1311. ToolMessages^.Insert(New(PToolMessage, Init(MN,Text,Row,Col)));
  1312. end;
  1313. procedure ClearToolMessages;
  1314. begin
  1315. If assigned(ToolMessages) then
  1316. ToolMessages^.FreeAll;
  1317. If assigned(ToolModuleNames) then
  1318. ToolModuleNames^.FreeAll;
  1319. LastToolMessageFocused:=nil;
  1320. LongestTool:=0;
  1321. end;
  1322. procedure DoneToolMessages;
  1323. begin
  1324. If assigned(ToolMessages) then
  1325. begin
  1326. Dispose(ToolMessages,Done);
  1327. ToolMessages:=nil;
  1328. end;
  1329. If assigned(ToolModuleNames) then
  1330. begin
  1331. Dispose(ToolModuleNames,Done);
  1332. ToolModuleNames:=nil;
  1333. end;
  1334. LastToolMessageFocused:=nil;
  1335. LongestTool:=0;
  1336. end;
  1337. procedure UpdateToolMessages;
  1338. begin
  1339. if Assigned(MessagesWindow) then
  1340. MessagesWindow^.Update;
  1341. end;
  1342. procedure TToolMessageListBox.Update;
  1343. var P: PMessageItem;
  1344. Idx: integer;
  1345. begin
  1346. P:=LastToolMessageFocused;
  1347. NewList(ToolMessages);
  1348. if assigned(HScrollBar) then
  1349. HScrollbar^.SetRange(0,LongestTool);
  1350. if (Range>0) and (P<>nil) then
  1351. begin
  1352. Idx:=List^.IndexOf(P);
  1353. if Idx>=0 then
  1354. begin
  1355. FocusItem(Idx);
  1356. DrawView;
  1357. end;
  1358. end;
  1359. DrawView;
  1360. end;
  1361. procedure TToolMessageListBox.NewList(AList: PCollection);
  1362. begin
  1363. if (List=ToolMessages) or (ToolMessages=nil) then
  1364. begin List:=nil; SetRange(0); end;
  1365. inherited NewList(AList);
  1366. end;
  1367. procedure TToolMessageListBox.Clear;
  1368. begin
  1369. ClearToolMessages;
  1370. Update;
  1371. Message(Application,evBroadcast,cmClearLineHighlights,@Self);
  1372. end;
  1373. function TToolMessageListBox.GetPalette: PPalette;
  1374. const
  1375. P: string[length(CBrowserListBox)] = CBrowserListBox;
  1376. begin
  1377. GetPalette:=@P;
  1378. end;
  1379. constructor TToolMessageListBox.Load(var S: TStream);
  1380. begin
  1381. inherited Load(S);
  1382. end;
  1383. procedure TToolMessageListBox.Store(var S: TStream);
  1384. var OL: PCollection;
  1385. begin
  1386. OL:=List;
  1387. New(List, Init(1,1));
  1388. inherited Store(S);
  1389. Dispose(List, Done);
  1390. List:=OL;
  1391. end;
  1392. destructor TToolMessageListBox.Done;
  1393. begin
  1394. HScrollBar:=nil; VScrollBar:=nil;
  1395. if List=ToolMessages then begin List:=nil; SetRange(0); end;
  1396. inherited Done;
  1397. end;
  1398. constructor TMessagesWindow.Init;
  1399. var R: TRect;
  1400. HSB,VSB: PScrollBar;
  1401. begin
  1402. Desktop^.GetExtent(R); R.A.Y:=R.B.Y-7;
  1403. inherited Init(R,dialog_messages,SearchFreeWindowNo);
  1404. HelpCtx:=hcMessagesWindow;
  1405. HSB:=StandardScrollBar(sbHorizontal+sbHandleKeyboard); Insert(HSB);
  1406. VSB:=StandardScrollBar(sbVertical+sbHandleKeyboard); Insert(VSB);
  1407. VSB^.SetStep(R.B.Y-R.A.Y-2,1);
  1408. HSB^.SetStep(R.B.X-R.A.X-2,1);
  1409. GetExtent(R); R.Grow(-1,-1);
  1410. New(MsgLB, Init(R, HSB, VSB));
  1411. Insert(MsgLB);
  1412. Update;
  1413. MessagesWindow:=@Self;
  1414. end;
  1415. procedure TMessagesWindow.Update;
  1416. begin
  1417. MsgLB^.Update;
  1418. end;
  1419. procedure TMessagesWindow.FocusItem(i : sw_integer);
  1420. begin
  1421. MsgLB^.FocusItem(i);
  1422. end;
  1423. procedure TMessagesWindow.HandleEvent(var Event: TEvent);
  1424. begin
  1425. case Event.What of
  1426. evBroadcast :
  1427. case Event.Command of
  1428. cmListFocusChanged :
  1429. if Event.InfoPtr=MsgLB then
  1430. begin
  1431. LastToolMessageFocused:=MsgLB^.List^.At(MsgLB^.Focused);
  1432. Message(Application,evBroadcast,cmClearLineHighlights,@Self);
  1433. end;
  1434. end;
  1435. end;
  1436. inherited HandleEvent(Event);
  1437. end;
  1438. procedure TMessagesWindow.SizeLimits(var Min, Max: TPoint);
  1439. begin
  1440. inherited SizeLimits(Min,Max);
  1441. Min.X:=20;
  1442. Min.Y:=4;
  1443. end;
  1444. function TMessagesWindow.GetPalette: PPalette;
  1445. const S: string[length(CBrowserWindow)] = CBrowserWindow;
  1446. begin
  1447. GetPalette:=@S;
  1448. end;
  1449. constructor TMessagesWindow.Load(var S: TStream);
  1450. begin
  1451. inherited Load(S);
  1452. GetSubViewPtr(S,MsgLB);
  1453. Update;
  1454. MessagesWindow:=@Self;
  1455. end;
  1456. procedure TMessagesWindow.Store(var S: TStream);
  1457. begin
  1458. inherited Store(S);
  1459. PutSubViewPtr(S,MsgLB);
  1460. end;
  1461. destructor TMessagesWindow.Done;
  1462. begin
  1463. MessagesWindow:=nil;
  1464. inherited Done;
  1465. end;
  1466. procedure RegisterFPTools;
  1467. begin
  1468. {$ifndef NOOBJREG}
  1469. RegisterType(RToolMessageListBox);
  1470. RegisterType(RMessagesWindow);
  1471. {$endif}
  1472. end;
  1473. END.
  1474. {
  1475. $Log$
  1476. Revision 1.2 2001-08-05 02:01:48 peter
  1477. * FVISION define to compile with fvision units
  1478. Revision 1.1 2001/08/04 11:30:24 peter
  1479. * ide works now with both compiler versions
  1480. Revision 1.1.2.5 2001/03/20 00:20:42 pierre
  1481. * fix some memory leaks + several small enhancements
  1482. Revision 1.1.2.4 2001/03/14 17:57:37 pierre
  1483. * handle NOSWAP correctly
  1484. Revision 1.1.2.3 2001/03/08 16:43:01 pierre
  1485. + add $CAP EDIT(filename) capability
  1486. * fix horizontal scrolling
  1487. Revision 1.1.2.2 2000/11/23 16:33:32 pierre
  1488. * fix Alt-X problem and set HelpCtx for most dialogs
  1489. Revision 1.1.2.1 2000/07/20 11:02:15 michael
  1490. + Fixes from gabor. See fixes.txt
  1491. Revision 1.1 2000/07/13 09:48:36 michael
  1492. + Initial import
  1493. Revision 1.20 2000/06/22 09:07:12 pierre
  1494. * Gabor changes: see fixes.txt
  1495. Revision 1.19 2000/05/02 08:42:29 pierre
  1496. * new set of Gabor changes: see fixes.txt
  1497. Revision 1.18 2000/04/25 08:42:33 pierre
  1498. * New Gabor changes : see fixes.txt
  1499. Revision 1.17 2000/04/18 11:42:37 pierre
  1500. lot of Gabor changes : see fixes.txt
  1501. Revision 1.16 2000/03/13 20:31:54 pierre
  1502. * INIPath removed
  1503. Revision 1.15 2000/02/07 12:00:41 pierre
  1504. Gabor's changes
  1505. Revision 1.14 1999/10/27 10:43:06 pierre
  1506. * avoid dispose problems for ToolMessages
  1507. Revision 1.13 1999/08/03 20:22:37 peter
  1508. + TTab acts now on Ctrl+Tab and Ctrl+Shift+Tab...
  1509. + Desktop saving should work now
  1510. - History saved
  1511. - Clipboard content saved
  1512. - Desktop saved
  1513. - Symbol info saved
  1514. * syntax-highlight bug fixed, which compared special keywords case sensitive
  1515. (for ex. 'asm' caused asm-highlighting, while 'ASM' didn't)
  1516. * with 'whole words only' set, the editor didn't found occourences of the
  1517. searched text, if the text appeared previously in the same line, but didn't
  1518. satisfied the 'whole-word' condition
  1519. * ^QB jumped to (SelStart.X,SelEnd.X) instead of (SelStart.X,SelStart.Y)
  1520. (ie. the beginning of the selection)
  1521. * when started typing in a new line, but not at the start (X=0) of it,
  1522. the editor inserted the text one character more to left as it should...
  1523. * TCodeEditor.HideSelection (Ctrl-K+H) didn't update the screen
  1524. * Shift shouldn't cause so much trouble in TCodeEditor now...
  1525. * Syntax highlight had problems recognizing a special symbol if it was
  1526. prefixed by another symbol character in the source text
  1527. * Auto-save also occours at Dos shell, Tool execution, etc. now...
  1528. Revision 1.12 1999/07/28 23:11:24 peter
  1529. * fixes from gabor
  1530. Revision 1.11 1999/07/12 13:14:21 pierre
  1531. * LineEnd bug corrected, now goes end of text even if selected
  1532. + Until Return for debugger
  1533. + Code for Quit inside GDB Window
  1534. Revision 1.10 1999/06/28 19:32:24 peter
  1535. * fixes from gabor
  1536. Revision 1.9 1999/05/22 13:44:32 peter
  1537. * fixed couple of bugs
  1538. Revision 1.8 1999/04/07 21:55:54 peter
  1539. + object support for browser
  1540. * html help fixes
  1541. * more desktop saving things
  1542. * NODEBUG directive to exclude debugger
  1543. Revision 1.7 1999/03/23 15:11:35 peter
  1544. * desktop saving things
  1545. * vesa mode
  1546. * preferences dialog
  1547. Revision 1.6 1999/03/16 12:38:14 peter
  1548. * tools macro fixes
  1549. + tph writer
  1550. + first things for resource files
  1551. Revision 1.5 1999/03/08 14:58:12 peter
  1552. + prompt with dialogs for tools
  1553. Revision 1.4 1999/03/01 15:42:04 peter
  1554. + Added dummy entries for functions not yet implemented
  1555. * MenuBar didn't update itself automatically on command-set changes
  1556. * Fixed Debugging/Profiling options dialog
  1557. * TCodeEditor converts spaces to tabs at save only if efUseTabChars is set
  1558. * efBackSpaceUnindents works correctly
  1559. + 'Messages' window implemented
  1560. + Added '$CAP MSG()' and '$CAP EDIT' to available tool-macros
  1561. + Added TP message-filter support (for ex. you can call GREP thru
  1562. GREP2MSG and view the result in the messages window - just like in TP)
  1563. * A 'var' was missing from the param-list of THelpFacility.TopicSearch,
  1564. so topic search didn't work...
  1565. * In FPHELP.PAS there were still context-variables defined as word instead
  1566. of THelpCtx
  1567. * StdStatusKeys() was missing from the statusdef for help windows
  1568. + Topic-title for index-table can be specified when adding a HTML-files
  1569. Revision 1.3 1999/02/22 02:15:19 peter
  1570. + default extension for save in the editor
  1571. + Separate Text to Find for the grep dialog
  1572. * fixed redir crash with tp7
  1573. Revision 1.2 1999/02/19 15:43:21 peter
  1574. * compatibility fixes for FV
  1575. Revision 1.1 1999/01/21 11:54:25 peter
  1576. + tools menu
  1577. + speedsearch in symbolbrowser
  1578. * working run command
  1579. Revision 1.0 1999/01/16 10:43:31 gabor
  1580. Original implementation
  1581. }