fptools.pas 45 KB

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