1 {***************************************************************************
2 * *
3 * This source is free software; you can redistribute it and/or modify *
4 * it under the terms of the GNU General Public License as published by *
5 * the Free Software Foundation; either version 2 of the License, or *
6 * (at your option) any later version. *
7 * *
8 * This code is distributed in the hope that it will be useful, but *
9 * WITHOUT ANY WARRANTY; without even the implied warranty of *
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
11 * General Public License for more details. *
12 * *
13 * A copy of the GNU General Public License is available on the World *
14 * Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
15 * obtain it by writing to the Free Software Foundation, *
16 * Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, USA. *
17 * *
18 ***************************************************************************
19
20 Abstract:
21 Frame to edit custom options and conditionals of compiler options
22 (project+packages).
23 }
24 unit Compiler_Other_Options;
25
26 {$mode objfpc}{$H+}
27
28 interface
29
30 uses
31 Classes, SysUtils, math, Laz_AVL_Tree,
32 // LCL
33 Forms, Controls, Graphics, Dialogs, StdCtrls, ComCtrls, ExtCtrls, Buttons, LCLType,
34 // LazUtils
35 LazUTF8, LazLoggerBase,
36 // Codetools
37 CodeToolsCfgScript, KeywordFuncLists,
38 // IdeIntf
39 IDEOptionsIntf, IDEOptEditorIntf, CompOptsIntf, IDECommands,
40 // SynEdit
41 SynEdit, SynEditKeyCmds, SynCompletion,
42 // IDE
43 LazarusIDEStrConsts, CompilerOptions, Compiler, AllCompilerOptions, DefinesGui,
44 EditorOptions, PackageDefs, SourceSynEditor;
45
46 type
47
48 { TCompilerOtherOptionsFrame }
49
50 TCompilerOtherOptionsFrame = class(TAbstractIDEOptionsEditor)
51 btnDefines: TBitBtn;
52 btnAllOptions: TBitBtn;
53 btnFcUTF8: TBitBtn;
54 grpCustomOptions: TGroupBox;
55 grpConditionals: TGroupBox;
56 CondStatusbar: TStatusBar;
57 CondSynEdit: TSynEdit;
58 CustomSplitter: TSplitter;
59 memoCustomOptions: TMemo;
60 procedure btnAllOptionsClick(Sender: TObject);
61 procedure btnDefinesClick(Sender: TObject);
62 procedure btnFcUTF8Click(Sender: TObject);
63 procedure CondSynEditChange(Sender: TObject);
64 procedure CondSynEditKeyPress(Sender: TObject; var {%H-}Key: char);
65 procedure CondSynEditProcessUserCommand(Sender: TObject;
66 var Command: TSynEditorCommand; var {%H-}AChar: TUTF8Char; {%H-}Data: pointer);
67 procedure CondSynEditStatusChange(Sender: TObject; {%H-}Changes: TSynStatusChanges);
68 procedure memoCustomOptionsChange(Sender: TObject);
69 private
70 FCompOptions: TBaseCompilerOptions;
71 FIdleConnected: Boolean;
72 FIsPackage: boolean;
73 FLocalOtherDefines: TStrings;
74 FCompletionHistory: TStrings;
75 FCompletionValues: TStrings;
76 FDefaultVariables: TCTCfgScriptVariables;
77 FHighlighter: TIDESynFreePasSyn;
78 FStatusMessage: string;
79 fEngine: TIDECfgScriptEngine;
80 fSynCompletion: TSynCompletion;
81 FOptionsReader: TCompilerOptReader;
82 FOptionsThread: TCompilerOptThread;
83 FUseComments: boolean;
84 procedure SetIdleConnected(AValue: Boolean);
85 procedure SetStatusMessage(const AValue: string);
86 procedure StartCompletion;
87 procedure UpdateCompletionValues;
GetCondCursorWordnull88 function GetCondCursorWord: string;
89 procedure UpdateMessages;
90 procedure UpdateStatusBar;
91 procedure OnIdle(Sender: TObject; var {%H-}Done: Boolean);
92 procedure OnSynCompletionCancel(Sender: TObject);
93 procedure OnSynCompletionExecute(Sender: TObject);
94 procedure OnSynCompletionKeyCompletePrefix(Sender: TObject);
95 procedure OnSynCompletionKeyDelete(Sender: TObject);
96 procedure OnSynCompletionKeyDown(Sender: TObject; var Key: Word; {%H-}Shift: TShiftState);
97 procedure OnSynCompletionKeyNextChar(Sender: TObject);
98 procedure OnSynCompletionKeyPrevChar(Sender: TObject);
99 procedure OnSynCompletionSearchPosition(var Position: integer);
100 procedure OnSynCompletionUTF8KeyPress(Sender: TObject; var {%H-}UTF8Key: TUTF8Char);
101 procedure OnSynCompletionValidate(Sender: TObject; {%H-}KeyChar: TUTF8Char;
102 {%H-}Shift: TShiftState);
103 protected
104 procedure SetVisible(Value: Boolean); override;
105 public
106 constructor Create(TheOwner: TComponent); override;
107 destructor Destroy; override;
Checknull108 function Check: Boolean; override;
GetTitlenull109 function GetTitle: string; override;
110 procedure Setup({%H-}ADialog: TAbstractOptionsEditorDialog); override;
111 procedure ReadSettings(AOptions: TAbstractIDEOptions); override;
112 procedure WriteSettings(AOptions: TAbstractIDEOptions); override;
SupportedOptionsClassnull113 class function SupportedOptionsClass: TAbstractIDEOptionsClass; override;
NoUtf8RtlSupportYetnull114 function NoUtf8RtlSupportYet: Boolean;
115 property StatusMessage: string read FStatusMessage write SetStatusMessage;
116 property DefaultVariables: TCTCfgScriptVariables read FDefaultVariables;
117 property CompletionValues: TStrings read FCompletionValues;
118 property CompletionHistory: TStrings read FCompletionHistory;
119 property IdleConnected: Boolean read FIdleConnected write SetIdleConnected;
120 property OptionsReader: TCompilerOptReader read FOptionsReader;
121 end;
122
123 implementation
124
125 {$R *.lfm}
126
127 const
128 FcUTF8 = '-FcUTF8';
129
130 { TCompilerOtherOptionsFrame }
131
132 procedure TCompilerOtherOptionsFrame.btnAllOptionsClick(Sender: TObject);
133 var
134 AllOpts: TfrmAllCompilerOptions;
135 begin
136 try
137 FOptionsReader.FromCustomOptions(memoCustomOptions.Lines);
138 AllOpts := TfrmAllCompilerOptions.Create(Nil);
139 try
140 AllOpts.OptionsReader := FOptionsReader;
141 AllOpts.OptionsThread := FOptionsThread;
142 AllOpts.cbUseComments.Checked := FUseComments;
143 if AllOpts.ShowModal = mrOK then
144 begin
145 // Synchronize with custom options memo
146 FUseComments := AllOpts.cbUseComments.Checked;
147 AllOpts.ToCustomOptions(memoCustomOptions.Lines);
148 memoCustomOptions.Invalidate;
149 end;
150 finally
151 AllOpts.Free;
152 end;
153 except
154 on E: Exception do
155 ShowMessage('Error parsing custom options: '+E.Message);
156 end;
157 end;
158
159 procedure TCompilerOtherOptionsFrame.btnDefinesClick(Sender: TObject);
160 var
161 EditForm: TDefinesGuiForm;
162 begin
163 EditForm := TDefinesGuiForm.Create(Nil);
164 try
165 try
166 EditForm.OptionsReader := FOptionsReader;
167 EditForm.OptionsThread := FOptionsThread;
168 EditForm.CustomOptions := memoCustomOptions.Lines;
169 EditForm.DefinesCheckList.Items.Assign(FLocalOtherDefines);
170 EditForm.UseComments := FUseComments;
171 if EditForm.ShowModal = mrOK then
172 begin
173 FLocalOtherDefines.Assign(EditForm.DefinesCheckList.Items);
174 // Synchronize with custom options memo
175 EditForm.ToCustomOptions(memoCustomOptions.Lines);
176 memoCustomOptions.Invalidate;
177 end;
178 except
179 on E: Exception do
180 ShowMessage('Error parsing custom options: '+E.Message);
181 end;
182 finally
183 EditForm.Free;
184 end;
185 end;
186
187 procedure TCompilerOtherOptionsFrame.btnFcUTF8Click(Sender: TObject);
188 begin
189 if NoUtf8RtlSupportYet then
190 memoCustomOptions.Lines.Add(FcUTF8);
191 end;
192
NoUtf8RtlSupportYetnull193 function TCompilerOtherOptionsFrame.NoUtf8RtlSupportYet: Boolean;
194 begin
195 Result := Pos(FcUTF8, memoCustomOptions.Text) = 0;
196 end;
197
198 // Events dealing with conditionals SynEdit :
199
200 procedure TCompilerOtherOptionsFrame.memoCustomOptionsChange(Sender: TObject);
201 begin
202 btnFcUTF8.Enabled := NoUtf8RtlSupportYet;
203 end;
204
205 procedure TCompilerOtherOptionsFrame.CondSynEditChange(Sender: TObject);
206 begin
207 UpdateStatusBar;
208 IdleConnected := True;
209 end;
210
211 procedure TCompilerOtherOptionsFrame.CondSynEditKeyPress(Sender: TObject; var Key: char);
212 begin
213 //debugln(['TCompilerOtherOptionsFrame.CondSynEditKeyPress ',ord(Key)]);
214 end;
215
216 procedure TCompilerOtherOptionsFrame.CondSynEditProcessUserCommand(Sender: TObject;
217 var Command: TSynEditorCommand; var AChar: TUTF8Char; Data: pointer);
218 begin
219 if (Command=ecWordCompletion) or (Command=ecIdentCompletion) then
220 StartCompletion;
221 end;
222
223 procedure TCompilerOtherOptionsFrame.CondSynEditStatusChange(Sender: TObject;
224 Changes: TSynStatusChanges);
225 begin
226 if fSynCompletion.TheForm.Visible then
227 begin
228 //debugln(['TCompilerOtherOptionsFrame.CondSynEditStatusChange ']);
229 fSynCompletion.CurrentString := GetCondCursorWord;
230 end;
231 UpdateStatusBar;
232 end;
233
234 procedure TCompilerOtherOptionsFrame.OnSynCompletionCancel(Sender: TObject);
235 begin
236 {$IFDEF VerboseCOCondSynCompletion}
237 debugln(['TCompilerOtherOptionsFrame.OnSynCompletionCancel ',fSynCompletion.TheForm.Visible]);
238 {$ENDIF}
239 if fSynCompletion.TheForm.Visible then
240 fSynCompletion.Deactivate;
241 fSynCompletion.RemoveEditor(CondSynEdit);
242 //fSynCompletion.Editor:=nil;
243 end;
244
245 procedure TCompilerOtherOptionsFrame.OnSynCompletionExecute(Sender: TObject);
246 begin
247 {$IFDEF VerboseCOCondSynCompletion}
248 debugln(['TCompilerOtherOptionsFrame.OnSynCompletionExecute ']);
249 {$ENDIF}
250 end;
251
252 procedure TCompilerOtherOptionsFrame.OnSynCompletionKeyCompletePrefix(
253 Sender: TObject);
254 begin
255 {$IFDEF VerboseCOCondSynCompletion}
256 debugln(['TCompilerOtherOptionsFrame.OnSynCompletionKeyCompletePrefix ToDo']);
257 {$ENDIF}
258 end;
259
260 procedure TCompilerOtherOptionsFrame.OnSynCompletionKeyDelete(Sender: TObject);
261 begin
262 {$IFDEF VerboseCOCondSynCompletion}
263 debugln(['TCompilerOtherOptionsFrame.OnSynCompletionKeyDelete']);
264 {$ENDIF}
265 end;
266
267 procedure TCompilerOtherOptionsFrame.OnSynCompletionKeyDown(Sender: TObject;
268 var Key: Word; Shift: TShiftState);
269 begin
270 {$IFDEF VerboseCOCondSynCompletion}
271 debugln(['TCompilerOtherOptionsFrame.OnSynCompletionKeyDown ']);
272 {$ENDIF}
273 if Key=VK_BACK then
274 begin
275 Key:=VK_UNKNOWN;
276 if fSynCompletion.CurrentString<>'' then
277 CondSynEdit.CommandProcessor(ecDeleteLastChar,#0,nil);
278 end;
279 end;
280
281 procedure TCompilerOtherOptionsFrame.OnSynCompletionKeyNextChar(Sender: TObject);
282 var
283 XY: TPoint;
284 StartX: integer;
285 EndX: integer;
286 Line: string;
287 begin
288 {$IFDEF VerboseCOCondSynCompletion}
289 debugln(['TCompilerOtherOptionsFrame.OnSynCompletionKeyNextChar ']);
290 {$ENDIF}
291 XY:=CondSynEdit.LogicalCaretXY;
292 if XY.Y>CondSynEdit.Lines.Count then exit;
293 CondSynEdit.GetWordBoundsAtRowCol(XY,StartX,EndX);
294 if EndX<=XY.X then exit;
295 Line := CondSynEdit.Lines[XY.Y - 1];
296 inc(XY.X,UTF8CodepointSize(@Line[XY.X-1]));
297 CondSynEdit.LogicalCaretXY:=XY;
298 end;
299
300 procedure TCompilerOtherOptionsFrame.OnSynCompletionKeyPrevChar(Sender: TObject);
301 var
302 XY: TPoint;
303 StartX: integer;
304 EndX: integer;
305 Line: string;
306 begin
307 {$IFDEF VerboseCOCondSynCompletion}
308 debugln(['TCompilerOtherOptionsFrame.OnSynCompletionKeyPrevChar ']);
309 {$ENDIF}
310 XY:=CondSynEdit.LogicalCaretXY;
311 if XY.Y>CondSynEdit.Lines.Count then exit;
312 CondSynEdit.GetWordBoundsAtRowCol(XY,StartX,EndX);
313 if StartX>=XY.X then exit;
314 Line := CondSynEdit.Lines[XY.Y - 1];
315 XY.X:=UTF8FindNearestCharStart(PChar(Line),length(Line),XY.X-2)+1;
316 CondSynEdit.LogicalCaretXY:=XY;
317 end;
318
319 procedure TCompilerOtherOptionsFrame.OnSynCompletionSearchPosition(var Position: integer);
320 var
321 sl: TStringList;
322 Prefix: String;
323 s: string;
324 i: Integer;
325 begin
326 {$IFDEF VerboseCOCondSynCompletion}
327 debugln(['TCompilerOtherOptionsFrame.OnSynCompletionSearchPosition "',fSynCompletion.CurrentString,'"']);
328 {$ENDIF}
329 Prefix:=fSynCompletion.CurrentString;
330 sl:=TStringList.Create;
331 try
332 Position:=-1;
333 for i:=0 to CompletionValues.Count-1 do
334 begin
335 s:=CompletionValues[i];
336 if SysUtils.CompareText(Prefix,copy(s,1,length(Prefix)))<>0 then continue;
337 if (Position<0) or (length(Prefix)=length(s)) then
338 Position:=sl.Count;
339 sl.AddObject(s,TObject({%H-}Pointer(i)));
340 end;
341 fSynCompletion.ItemList.Assign(sl);
342 finally
343 sl.Free;
344 end;
345 end;
346
347 procedure TCompilerOtherOptionsFrame.OnSynCompletionUTF8KeyPress(Sender: TObject;
348 var UTF8Key: TUTF8Char);
349 begin
350 {$IFDEF VerboseCOCondSynCompletion}
351 debugln(['TCompilerOtherOptionsFrame.OnSynCompletionUTF8KeyPress ']);
352 {$ENDIF}
353 end;
354
355 procedure TCompilerOtherOptionsFrame.OnSynCompletionValidate(Sender: TObject;
356 KeyChar: TUTF8Char; Shift: TShiftState);
357 var
358 i: LongInt;
359 s: string;
360 p: LongInt;
361 TxtXY: TPoint;
362 TxtStartX: integer;
363 TxtEndX: integer;
364 begin
365 {$IFDEF VerboseCOCondSynCompletion}
366 debugln(['TCompilerOtherOptionsFrame.OnSynCompletionValidate ']);
367 {$ENDIF}
368 i:=fSynCompletion.Position;
369 if (i>=0) and (i<fSynCompletion.ItemList.Count) then begin
370 i:=PtrUInt(fSynCompletion.ItemList.Objects[i]);
371 if (i>=0) and (i<CompletionValues.Count) then begin
372 s:=CompletionValues[i];
373 p:=System.Pos(#9,s);
374 if p>0 then s:=copy(s,1,p-1);
375 TxtXY:=CondSynEdit.LogicalCaretXY;
376 CondSynEdit.GetWordBoundsAtRowCol(TxtXY,TxtStartX,TxtEndX);
377 CondSynEdit.BeginUndoBlock{$IFDEF SynUndoDebugBeginEnd}('TCompilerOtherOptionsFrame.OnSynCompletionValidate'){$ENDIF};
378 try
379 CondSynEdit.BlockBegin:=Point(TxtStartX,TxtXY.Y);
380 CondSynEdit.BlockEnd:=Point(TxtEndX,TxtXY.Y);
381 CondSynEdit.SelText:=s;
382 finally
383 CondSynEdit.EndUndoBlock{$IFDEF SynUndoDebugBeginEnd}('TCompilerOtherOptionsFrame.OnSynCompletionValidate'){$ENDIF};
384 end;
385 FCompletionHistory.Insert(0,s);
386 if FCompletionHistory.Count>100 then
387 FCompletionHistory.Delete(FCompletionHistory.Count-1);
388 end;
389 end;
390
391 fSynCompletion.Deactivate;
392 end;
393
394 procedure TCompilerOtherOptionsFrame.SetVisible(Value: Boolean);
395 begin
396 inherited SetVisible(Value);
397 // Read all compiler options when the page is shown for the first time.
398 if Value then begin
399 if Assigned(fOptionsThread) then
400 begin
401 fOptionsThread.EndParsing; // Make sure the thread has finished running.
402 if FOptionsReader.UpdateTargetParam then begin
403 FOptionsReader.Clear;
404 fOptionsThread.StartParsing; // Read new options.
405 end;
406 end
407 else begin
408 fOptionsThread := TCompilerOptThread.Create(FOptionsReader);
409 fOptionsThread.StartParsing;
410 end;
411 end;
412 end;
413
414 procedure TCompilerOtherOptionsFrame.SetStatusMessage(const AValue: string);
415 begin
416 if FStatusMessage=AValue then exit;
417 FStatusMessage:=AValue;
418 CondStatusbar.Panels[2].Text := FStatusMessage;
419 end;
420
421 procedure TCompilerOtherOptionsFrame.SetIdleConnected(AValue: Boolean);
422 begin
423 if csDestroying in ComponentState then
424 AValue:=false;
425 if FIdleConnected=AValue then exit;
426 FIdleConnected:=AValue;
427 if FIdleConnected then
428 Application.AddOnIdleHandler(@OnIdle)
429 else
430 Application.RemoveOnIdleHandler(@OnIdle);
431 end;
432
433 procedure TCompilerOtherOptionsFrame.StartCompletion;
434
EditorRowColumnToCompletionXYnull435 function EditorRowColumnToCompletionXY(ScreenRowCol: TPoint;
436 AboveRow: boolean): TPoint;
437 begin
438 if not AboveRow then
439 inc(ScreenRowCol.Y,1);
440 Result:=CondSynEdit.RowColumnToPixels(ScreenRowCol);
441 Result:=CondSynEdit.ClientToScreen(Result);
442 if fSynCompletion.TheForm.Parent<>nil then
443 Result:=fSynCompletion.TheForm.Parent.ScreenToClient(Result);
444 end;
445
446 var
447 LogStartX: integer;
448 LogEndX: integer;
449 LogXY: TPoint;
450 ScreenXY: TPoint;
451 XY: TPoint;
452 Line: String;
453 begin
454 {$IFDEF VerboseCOCondSynCompletion}
455 debugln(['TCompOptBuildMacrosFrame.StartCompletion START']);
456 {$ENDIF}
457 UpdateCompletionValues;
458 fSynCompletion.ItemList.Assign(CompletionValues);
459
460 // get row and column of word start at cursor
461 LogXY:=CondSynEdit.LogicalCaretXY;
462 CondSynEdit.GetWordBoundsAtRowCol(LogXY,LogStartX,LogEndX);
463 LogEndX:=Min(LogEndX,LogXY.X);
464 // convert text row,column to screen row,column
465 ScreenXY:=CondSynEdit.PhysicalToLogicalPos(Point(LogStartX,LogXY.Y));
466 // convert screen row,column to coordinates for the completion form
467 XY:=EditorRowColumnToCompletionXY(ScreenXY,false);
468
469 if XY.Y+fSynCompletion.TheForm.Height>fSynCompletion.TheForm.Parent.ClientHeight
470 then begin
471 // place completion above text
472 XY:=EditorRowColumnToCompletionXY(ScreenXY,true);
473 dec(XY.Y,fSynCompletion.TheForm.Height);
474 end;
475
476 // show completion box
477 //fSynCompletion.AddEditor(CondSynEdit);
478 fSynCompletion.Editor:=CondSynEdit;
479 Line:=CondSynEdit.LineText;
480 fSynCompletion.Execute(copy(Line,LogStartX,LogEndX-LogStartX),XY.X,XY.Y);
481 debugln(['TCompilerOtherOptionsFrame.StartCompletion XY=',dbgs(XY),' fSynCompletion.TheForm.BoundsRect=',dbgs(fSynCompletion.TheForm.BoundsRect)]);
482 end;
483
484 procedure TCompilerOtherOptionsFrame.UpdateCompletionValues;
485
HasWordnull486 function HasWord(const aName: string): Boolean;
487 var
488 i: Integer;
489 s: string;
490 p: LongInt;
491 begin
492 for i:=0 to CompletionValues.Count-1 do begin
493 s:=CompletionValues[i];
494 p:=System.Pos(#9,s);
495 if p>0 then
496 s:=copy(s,1,p-1);
497 if SysUtils.CompareText(s,aName)=0 then exit(true);
498 end;
499 Result:=false;
500 end;
501
502 procedure AddKeyword(aName: string);
503 begin
504 CompletionValues.Add(aName);
505 end;
506
507 procedure AddWord(aName: string);
508 begin
509 aName:=dbgstr(aName);
510 if aName='' then exit;
511 if HasWord(aName) then exit;
512 CompletionValues.Add(aName);
513 end;
514
515 procedure AddVar(aName, aValue: string);
516 var
517 s: String;
518 begin
519 aName:=dbgstr(aName);
520 if aName='' then exit;
521 if HasWord(aName) then exit;
522 s:=dbgstr(aValue);
523 if length(s)>50 then s:=copy(s,1,50)+'...';
524 s:=aName+#9+aValue;
525 CompletionValues.Add(s);
526 end;
527
528 var
529 Node: TAVLTreeNode;
530 V: PCTCfgScriptVariable;
531 s: String;
532 p: PChar;
533 AtomStart: PChar;
534 pcov: TParsedCompilerOptString;
535 pcouv: TParsedCompilerOptString;
536 i: Integer;
537 j: Integer;
538 Macro: TLazBuildMacro;
539 begin
540 CompletionValues.Clear;
541
542 // add default variables with values
543 Node:=DefaultVariables.Tree.FindLowest;
544 while Node<>nil do begin
545 V:=PCTCfgScriptVariable(Node.Data);
546 AddVar(V^.Name,GetCTCSVariableAsString(V));
547 Node:=DefaultVariables.Tree.FindSuccessor(Node);
548 end;
549
550 // add keywords and operands
551 AddKeyword('if');
552 AddKeyword('then');
553 AddKeyword('else');
554 AddKeyword('begin');
555 AddKeyword('end');
556 AddKeyword('not');
557 AddKeyword('and');
558 AddKeyword('or');
559 AddKeyword('xor');
560 AddKeyword('undefine');
561 AddKeyword('defined');
562 AddKeyword('undefined');
563 AddKeyword('integer');
564 AddKeyword('int64');
565 AddKeyword('string');
566 AddKeyword('true');
567 AddKeyword('false');
568
569 // add IDE functions
570 AddWord('GetIDEValue(''OS'')');
571 AddWord('GetIDEValue(''CPU'')');
572 AddWord('GetIDEValue(''SrcOS'')');
573 AddWord('GetIDEValue(''SrcOS2'')');
574 AddWord('GetIDEValue(''LCLWidgetType'')');
575 AddWord('GetEnv(''USER'')');
576 AddWord('GetEnv(''HOME'')');
577 if FCompOptions is TPkgCompilerOptions then
578 AddWord('GetProjValue(''FPC_FULLVERSION'')');
579
580 // add result variables
581 for pcov:=low(ParsedCompilerOptsVars) to high(ParsedCompilerOptsVars) do
582 AddWord(ParsedCompilerOptsVars[pcov]);
583 if FIsPackage then
584 for pcouv:=low(ParsedCompilerOptsUsageVars) to high(ParsedCompilerOptsUsageVars) do
585 AddWord(ParsedCompilerOptsUsageVars[pcouv]);
586
587 // add build macros and values
588 if FCompOptions.BuildMacros<>nil then begin
589 for i:=0 to FCompOptions.BuildMacros.Count-1 do
590 begin
591 Macro:=FCompOptions.BuildMacros[i];
592 AddWord(Macro.Identifier);
593 for j:=0 to Macro.Values.Count-1 do
594 AddWord(Macro.Values[j]);
595 end;
596 end;
597
598 // add words in text
599 s:=CondSynEdit.Lines.Text;
600 if s<>'' then begin
601 p:=PChar(s);
602 repeat
603 AtomStart:=p;
604 while (AtomStart^<>#0) and not IsIdentStartChar[AtomStart^] do
605 inc(AtomStart);
606 if (AtomStart^=#0) then break;
607 p:=AtomStart;
608 while IsIdentChar[p^] do inc(p);
609 AddWord(copy(s,AtomStart-PChar(s)+1,p-AtomStart));
610 until false;
611 end;
612
613 // sort alphabetically
614 TStringList(FCompletionValues).Sort;
615
616 // push recently used words upwards
617 for i:=CompletionHistory.Count-1 downto 0 do begin
618 j:=CompletionValues.IndexOf(CompletionHistory[i]);
619 if j>0 then
620 CompletionValues.Move(j,0);
621 end;
622
623 // set index
624 for i:=0 to CompletionValues.Count-1 do
625 CompletionValues.Objects[i]:=TObject({%H-}Pointer(i));
626
627 //debugln(['TCompOptBuildMacrosFrame.UpdateCompletionValues ',CompletionValues.Text]);
628 end;
629
TCompilerOtherOptionsFrame.GetCondCursorWordnull630 function TCompilerOtherOptionsFrame.GetCondCursorWord: string;
631 var
632 XY: TPoint;
633 StartX: integer;
634 EndX: integer;
635 Line: string;
636 begin
637 XY := CondSynEdit.LogicalCaretXY;
638 if (XY.Y>=1) and (XY.Y<=CondSynEdit.Lines.Count) then
639 begin
640 CondSynEdit.GetWordBoundsAtRowCol(XY,StartX,EndX);
641 //debugln(['TCompOptBuildMacrosFrame.GetCondCursorWord ',StartX,' ',EndX,' ',XY.X]);
642 EndX := Min(EndX,XY.X);
643 Line := CondSynEdit.Lines[XY.Y - 1];
644 Result := Copy(Line, StartX, EndX - StartX);
645 end else
646 Result := '';
647 //debugln(['TCompOptBuildMacrosFrame.GetCondCursorWord "',Result,'"']);
648 end;
649
650 procedure TCompilerOtherOptionsFrame.UpdateMessages;
651 begin
652 fEngine.Variables.Assign(DefaultVariables);
653 fEngine.Execute(CondSynEdit.Lines.Text,1);
654 if fEngine.ErrorCount>0 then begin
655 StatusMessage:=fEngine.GetErrorStr(0);
656 end else begin
657 StatusMessage:='';
658 end;
659 end;
660
661 procedure TCompilerOtherOptionsFrame.UpdateStatusBar;
662 var
663 PanelCharMode: String;
664 PanelXY: String;
665 begin
666 PanelXY := Format(' %6d:%4d',[CondSynEdit.CaretY,CondSynEdit.CaretX]);
667 if CondSynEdit.InsertMode then
668 PanelCharMode := uepIns
669 else
670 PanelCharMode := uepOvr;
671
672 CondStatusbar.Panels[0].Text := PanelXY;
673 CondStatusbar.Panels[1].Text := PanelCharMode;
674 end;
675
676 procedure TCompilerOtherOptionsFrame.OnIdle(Sender: TObject; var Done: Boolean);
677 begin
678 IdleConnected := False;
679 UpdateMessages;
680 end;
681
682 constructor TCompilerOtherOptionsFrame.Create(TheOwner: TComponent);
683 begin
684 inherited Create(TheOwner);
685 FLocalOtherDefines:=TStringList.Create;
686 FCompletionValues:=TStringList.Create;
687 FCompletionHistory:=TStringList.Create;
688 fDefaultVariables:=TCTCfgScriptVariables.Create;
689 fEngine:=TIDECfgScriptEngine.Create;
690
691 CondSynEdit.OnStatusChange:=@CondSynEditStatusChange;
692
693 fSynCompletion:=TSynCompletion.Create(Self);
694 fSynCompletion.ShowSizeDrag:=true;
695 fSynCompletion.TheForm.Parent:=Self;
696 fSynCompletion.OnExecute:=@OnSynCompletionExecute;
697 fSynCompletion.OnCancel:=@OnSynCompletionCancel;
698 fSynCompletion.OnValidate:=@OnSynCompletionValidate;
699 fSynCompletion.OnSearchPosition:=@OnSynCompletionSearchPosition;
700 fSynCompletion.OnKeyCompletePrefix:=@OnSynCompletionKeyCompletePrefix;
701 fSynCompletion.OnUTF8KeyPress:=@OnSynCompletionUTF8KeyPress;
702 fSynCompletion.OnKeyNextChar:=@OnSynCompletionKeyNextChar;
703 fSynCompletion.OnKeyPrevChar:=@OnSynCompletionKeyPrevChar;
704 fSynCompletion.OnKeyDelete:=@OnSynCompletionKeyDelete;
705 fSynCompletion.OnKeyDown:=@OnSynCompletionKeyDown;
706
707 FOptionsReader := TCompilerOptReader.Create;
708 end;
709
710 destructor TCompilerOtherOptionsFrame.Destroy;
711 begin
712 IdleConnected:=false;
713 FreeAndNil(fOptionsThread);
714 FreeAndNil(FOptionsReader);
715 FreeAndNil(fEngine);
716 FreeAndNil(fDefaultVariables);
717 FreeAndNil(FCompletionHistory);
718 FreeAndNil(FCompletionValues);
719 FreeAndNil(FLocalOtherDefines);
720 inherited Destroy;
721 end;
722
Checknull723 function TCompilerOtherOptionsFrame.Check: Boolean;
724 begin
725 Result := True;
726 end;
727
TCompilerOtherOptionsFrame.GetTitlenull728 function TCompilerOtherOptionsFrame.GetTitle: string;
729 begin
730 Result := lisCustomOptions3;
731 end;
732
733 procedure TCompilerOtherOptionsFrame.Setup(ADialog: TAbstractOptionsEditorDialog);
734 begin
735 grpCustomOptions.Caption := lisCustomOptions2;
736 memoCustomOptions.Hint := lisCustomOptHint;
737 grpConditionals.Caption := lisConditionals;
738 btnAllOptions.Caption := lisDlgAllOptions;
739 btnDefines.Caption := lisDlgDefines;
740 btnFcUTF8.Caption := lisAddFcUTF8;
741 btnFcUTF8.Hint := lisAddFcUTF8Hint;
742 end;
743
744 procedure TCompilerOtherOptionsFrame.ReadSettings(AOptions: TAbstractIDEOptions);
745 var
746 Vars: TCTCfgScriptVariables;
747 begin
748 FCompOptions := AOptions as TBaseCompilerOptions;
749 FIsPackage := FCompOptions is TPkgCompilerOptions;
750 //debugln(['TCompilerOtherOptionsFrame.ReadSettings ',dbgs(Pointer(FCompOptions)),' ',FCompOptions=Project1.CompilerOptions]);
751
752 CondSynEdit.Lines.Text := FCompOptions.Conditionals;
753 if FHighlighter=nil then
754 begin
755 FHighlighter := TPreviewPasSyn.Create(Self);
756 CondSynEdit.Highlighter:=FHighlighter;
757 end;
758 EditorOpts.ReadHighlighterSettings(FHighlighter, '');
759 EditorOpts.GetSynEditSettings(CondSynEdit);
760
761 Vars := GetBuildMacroValues(FCompOptions,false);
762 if Vars<>nil then
763 DefaultVariables.Assign(Vars)
764 else
765 DefaultVariables.Clear;
766
767 // Custom Options
768 memoCustomOptions.Text := FCompOptions.CustomOptions;
769 memoCustomOptions.OnChange(Nil);
770 FUseComments := FCompOptions.UseCommentsInCustomOptions;
771 FLocalOtherDefines.Assign(FCompOptions.OtherDefines);
772
773 UpdateStatusBar;
774 end;
775
776 procedure TCompilerOtherOptionsFrame.WriteSettings(AOptions: TAbstractIDEOptions);
777 var
778 CurOptions: TBaseCompilerOptions;
779 begin
780 //debugln(['TCompilerOtherOptionsFrame.WriteSettings ',DbgSName(AOptions)]);
781 CurOptions := AOptions as TBaseCompilerOptions;
782 CurOptions.Conditionals := CondSynEdit.Lines.Text;
783 CurOptions.CustomOptions := memoCustomOptions.Text;
784 CurOptions.UseCommentsInCustomOptions := FUseComments;
785 if not CurOptions.OtherDefines.Equals(FLocalOtherDefines) then
786 begin
787 CurOptions.OtherDefines.Assign(FLocalOtherDefines);
788 CurOptions.IncreaseChangeStamp;
789 end;
790 end;
791
TCompilerOtherOptionsFrame.SupportedOptionsClassnull792 class function TCompilerOtherOptionsFrame.SupportedOptionsClass: TAbstractIDEOptionsClass;
793 begin
794 Result := TBaseCompilerOptions;
795 end;
796
797 initialization
798 RegisterIDEOptionsEditor(GroupCompiler, TCompilerOtherOptionsFrame,
799 CompilerOptionsOther);
800 RegisterIDEOptionsEditor(GroupPkgCompiler, TCompilerOtherOptionsFrame,
801 CompilerOptionsOther);
802
803 end.
804
805