Subversion Repositories fastphp

Rev

Rev 56 | Rev 58 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
8 daniel-mar 1
unit EditorMain;
2 daniel-mar 2
 
25 daniel-mar 3
{$Include 'FastPHP.inc'}
4
 
4 daniel-mar 5
(*
6
  This program requires
7
  - Microsoft Internet Controls (TWebBrowser)
8
    If you are using Delphi 10.1 Starter Edition, please import the ActiveX TLB
9
    "Microsoft Internet Controls"
10
  - SynEdit
11
    You can obtain SynEdit via Embarcadero GetIt
12
*)
13
 
2 daniel-mar 14
// TODO: localize
15
// TODO: wieso geht copy paste im twebbrowser nicht???
49 daniel-mar 16
// TODO: Wieso dauert webbrowser1 erste kompilierung so lange???
5 daniel-mar 17
// TODO: wieso kommt syntax fehler zweimal? einmal stderr einmal stdout?
18
// TODO: Browser titlebar (link preview)
49 daniel-mar 19
// TODO: "jump to next/prev todo" buttons/shortcuts
20
// TODO: "increase/decrease indent" buttons/shortcuts
2 daniel-mar 21
 
22
// Future ideas
31 daniel-mar 23
// - code insight
2 daniel-mar 24
// - verschiedene php versionen?
25
// - webbrowser1 nur laden, wenn man den tab anwählt?
26
// - doppelklick auf tab soll diesen schließen
5 daniel-mar 27
// - Onlinehelp (www) aufrufen
13 daniel-mar 28
// - Let all colors be adjustable
21 daniel-mar 29
// - code in bildschirmmitte (horizontal)?
2 daniel-mar 30
 
31
interface
32
 
33
uses
27 daniel-mar 34
  // TODO: "{$IFDEF USE_SHDOCVW_TLB}_TLB{$ENDIF}" does not work with Delphi 10.2
2 daniel-mar 35
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
4 daniel-mar 36
  Dialogs, StdCtrls, OleCtrls, ComCtrls, ExtCtrls, ToolWin, IniFiles,
45 daniel-mar 37
  SynEditHighlighter, SynHighlighterPHP, SynEdit, ShDocVw_TLB, FindReplace,
38
  ActnList, SynEditMiscClasses, SynEditSearch, RunPHP, ImgList, SynUnicode,
56 daniel-mar 39
  System.ImageList, System.Actions, Vcl.Menus, SHDocVw;
2 daniel-mar 40
 
23 daniel-mar 41
{.$DEFINE OnlineHelp}
42
 
2 daniel-mar 43
type
44
  TForm1 = class(TForm)
45
    PageControl1: TPageControl;
46
    PlaintextTabSheet: TTabSheet;
47
    HtmlTabSheet: TTabSheet;
48
    Memo2: TMemo;
49
    WebBrowser1: TWebBrowser;
50
    Splitter1: TSplitter;
51
    PageControl2: TPageControl;
20 daniel-mar 52
    CodeTabsheet: TTabSheet;
2 daniel-mar 53
    HelpTabsheet: TTabSheet;
54
    WebBrowser2: TWebBrowser;
55
    OpenDialog1: TOpenDialog;
56
    Panel1: TPanel;
57
    OpenDialog3: TOpenDialog;
4 daniel-mar 58
    SynEdit1: TSynEdit;
59
    SynPHPSyn1: TSynPHPSyn;
5 daniel-mar 60
    Panel2: TPanel;
61
    SynEditFocusTimer: TTimer;
62
    Button1: TButton;
63
    Button2: TButton;
64
    Button3: TButton;
13 daniel-mar 65
    Button4: TButton;
66
    Button5: TButton;
67
    Button6: TButton;
68
    ActionList: TActionList;
69
    ActionFind: TAction;
70
    ActionReplace: TAction;
71
    ActionFindNext: TAction;
72
    ActionGoto: TAction;
73
    ActionSave: TAction;
74
    ActionHelp: TAction;
75
    ActionRun: TAction;
76
    ActionESC: TAction;
77
    Button7: TButton;
15 daniel-mar 78
    ActionOpen: TAction;
79
    Button8: TButton;
22 daniel-mar 80
    Button9: TButton;
81
    ActionFindPrev: TAction;
23 daniel-mar 82
    Timer1: TTimer;
83
    ActionSpaceToTab: TAction;
84
    Button11: TButton;
24 daniel-mar 85
    SynEditSearch1: TSynEditSearch;
27 daniel-mar 86
    TreeView1: TTreeView;
26 daniel-mar 87
    Splitter2: TSplitter;
33 daniel-mar 88
    btnLint: TButton;
89
    ActionLint: TAction;
36 daniel-mar 90
    ImageList1: TImageList;
45 daniel-mar 91
    RunPopup: TPopupMenu;
92
    OpeninIDE1: TMenuItem;
93
    ActionRunConsole: TAction;
94
    Runinconsole1: TMenuItem;
56 daniel-mar 95
    SavePopup: TPopupMenu;
96
    Saveas1: TMenuItem;
97
    Save1: TMenuItem;
98
    SaveDialog1: TSaveDialog;
57 daniel-mar 99
    BtnSpecialChars: TImage;
100
    BtnSpecialCharsOff: TImage;
101
    BtnSpecialCharsOn: TImage;
2 daniel-mar 102
    procedure Run(Sender: TObject);
45 daniel-mar 103
    procedure RunConsole(Sender: TObject);
2 daniel-mar 104
    procedure FormShow(Sender: TObject);
105
    procedure FormCreate(Sender: TObject);
106
    procedure FormDestroy(Sender: TObject);
107
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
108
    procedure PageControl2Changing(Sender: TObject; var AllowChange: Boolean);
5 daniel-mar 109
    procedure Memo2DblClick(Sender: TObject);
45 daniel-mar 110
    (*
44 daniel-mar 111
    {$IFDEF USE_SHDOCVW_TLB}
45 daniel-mar 112
    *)
5 daniel-mar 113
    procedure WebBrowser1BeforeNavigate2(ASender: TObject;
27 daniel-mar 114
      const pDisp: IDispatch; const URL, Flags, TargetFrameName, PostData,
5 daniel-mar 115
      Headers: OleVariant; var Cancel: WordBool);
45 daniel-mar 116
    (*
44 daniel-mar 117
    {$ELSE}
118
    procedure WebBrowser1BeforeNavigate2(ASender: TObject;
119
      const pDisp: IDispatch; var URL, Flags, TargetFrameName, PostData,
120
      Headers: OleVariant; var Cancel: WordBool);
121
    {$ENDIF}
45 daniel-mar 122
    *)
44 daniel-mar 123
    procedure BeforeNavigate(const URL: OleVariant; var Cancel: WordBool);
5 daniel-mar 124
    procedure SynEditFocusTimerTimer(Sender: TObject);
13 daniel-mar 125
    procedure ActionFindExecute(Sender: TObject);
126
    procedure ActionReplaceExecute(Sender: TObject);
127
    procedure ActionFindNextExecute(Sender: TObject);
128
    procedure ActionGotoExecute(Sender: TObject);
129
    procedure ActionSaveExecute(Sender: TObject);
130
    procedure ActionHelpExecute(Sender: TObject);
131
    procedure ActionRunExecute(Sender: TObject);
132
    procedure ActionESCExecute(Sender: TObject);
133
    procedure SynEdit1MouseWheelDown(Sender: TObject; Shift: TShiftState;
134
      MousePos: TPoint; var Handled: Boolean);
135
    procedure SynEdit1MouseWheelUp(Sender: TObject; Shift: TShiftState;
136
      MousePos: TPoint; var Handled: Boolean);
15 daniel-mar 137
    procedure ActionOpenExecute(Sender: TObject);
138
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
17 daniel-mar 139
    procedure Memo2KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
22 daniel-mar 140
    procedure ActionFindPrevExecute(Sender: TObject);
23 daniel-mar 141
    procedure SynEdit1MouseCursor(Sender: TObject;
142
      const aLineCharPos: TBufferCoord; var aCursor: TCursor);
143
    procedure Timer1Timer(Sender: TObject);
144
    procedure ActionSpaceToTabExecute(Sender: TObject);
27 daniel-mar 145
    procedure TreeView1DblClick(Sender: TObject);
30 daniel-mar 146
    procedure SynEdit1GutterClick(Sender: TObject; Button: TMouseButton; X, Y,
147
      Line: Integer; Mark: TSynEditMark);
31 daniel-mar 148
    procedure SynEdit1PaintTransient(Sender: TObject; Canvas: TCanvas;
149
      TransientType: TTransientType);
33 daniel-mar 150
    procedure ActionLintExecute(Sender: TObject);
45 daniel-mar 151
    procedure ActionRunConsoleExecute(Sender: TObject);
47 daniel-mar 152
    procedure SynEdit1Change(Sender: TObject);
56 daniel-mar 153
    procedure Saveas1Click(Sender: TObject);
154
    procedure Save1Click(Sender: TObject);
57 daniel-mar 155
    procedure BtnSpecialCharsClick(Sender: TObject);
2 daniel-mar 156
  private
157
    CurSearchTerm: string;
158
    HlpPrevPageIndex: integer;
24 daniel-mar 159
    SrcRep: TSynEditFindReplace;
23 daniel-mar 160
    {$IFDEF OnlineHelp}
161
    gOnlineHelpWord: string;
162
    {$ENDIF}
2 daniel-mar 163
    procedure Help;
5 daniel-mar 164
    function MarkUpLineReference(cont: string): string;
40 daniel-mar 165
    function InputRequestCallback(var data: AnsiString): boolean;
166
    function OutputNotifyCallback(const data: AnsiString): boolean;
2 daniel-mar 167
  protected
168
    ChmIndex: TMemIniFile;
19 daniel-mar 169
    FScrapFile: string;
56 daniel-mar 170
    FSaveAsFilename: string;
27 daniel-mar 171
    codeExplorer: TRunCodeExplorer;
172
    procedure GotoLineNo(LineNo: integer);
2 daniel-mar 173
    function GetScrapFile: string;
27 daniel-mar 174
    procedure StartCodeExplorer;
47 daniel-mar 175
    procedure RefreshModifySign;
2 daniel-mar 176
  end;
177
 
178
var
179
  Form1: TForm1;
180
 
181
implementation
182
 
183
{$R *.dfm}
184
 
30 daniel-mar 185
{$R Cursors.res}
186
 
2 daniel-mar 187
uses
25 daniel-mar 188
  Functions, StrUtils, WebBrowserUtils, FastPHPUtils, Math, ShellAPI, RichEdit,
49 daniel-mar 189
  FastPHPTreeView, ImageListEx, FastPHPConfig;
2 daniel-mar 190
 
30 daniel-mar 191
const
192
  crMouseGutter = 1;
193
 
47 daniel-mar 194
procedure TForm1.RefreshModifySign;
195
var
196
  tmp: string;
197
begin
198
  tmp := Caption;
199
 
200
  tmp := StringReplace(tmp, '*', '', [rfReplaceAll]);
201
  if SynEdit1.Modified then tmp := tmp + '*';
202
 
203
  if Caption <> tmp then Caption := tmp;
204
end;
205
 
13 daniel-mar 206
procedure TForm1.ActionFindNextExecute(Sender: TObject);
207
begin
208
  SrcRep.FindNext;
209
end;
210
 
22 daniel-mar 211
procedure TForm1.ActionFindPrevExecute(Sender: TObject);
212
begin
213
  SrcRep.FindPrev;
214
end;
215
 
13 daniel-mar 216
procedure TForm1.ActionGotoExecute(Sender: TObject);
5 daniel-mar 217
var
218
  val: string;
219
  lineno: integer;
220
begin
13 daniel-mar 221
  // TODO: VK_LMENU does not work! only works with AltGr but not Alt
222
  // http://stackoverflow.com/questions/16828250/delphi-xe2-how-to-prevent-the-alt-key-stealing-focus ?
5 daniel-mar 223
 
13 daniel-mar 224
  InputQuery('Go to', 'Line number:', val);
225
  if not TryStrToInt(val, lineno) then
226
  begin
227
    if SynEdit1.CanFocus then SynEdit1.SetFocus;
228
    exit;
229
  end;
230
  GotoLineNo(lineno);
231
end;
5 daniel-mar 232
 
13 daniel-mar 233
procedure TForm1.ActionHelpExecute(Sender: TObject);
234
begin
235
  Help;
236
  if PageControl2.ActivePage = HelpTabsheet then
237
    WebBrowser2.SetFocus
20 daniel-mar 238
  else if PageControl2.ActivePage = CodeTabsheet then
13 daniel-mar 239
    SynEdit1.SetFocus;
240
end;
8 daniel-mar 241
 
33 daniel-mar 242
procedure TForm1.ActionLintExecute(Sender: TObject);
243
begin
244
  Run(Sender);
245
  SynEdit1.SetFocus;
246
end;
247
 
15 daniel-mar 248
procedure TForm1.ActionOpenExecute(Sender: TObject);
249
begin
250
  If OpenDialog3.Execute then
251
  begin
252
    ShellExecute(0, 'open', PChar(ParamStr(0)), PChar(OpenDialog3.FileName), '', SW_NORMAL);
253
  end;
254
end;
255
 
13 daniel-mar 256
procedure TForm1.ActionReplaceExecute(Sender: TObject);
257
begin
258
  SrcRep.ReplaceExecute;
259
end;
5 daniel-mar 260
 
45 daniel-mar 261
procedure TForm1.ActionRunConsoleExecute(Sender: TObject);
262
begin
263
  RunConsole(Sender);
264
  SynEdit1.SetFocus;
265
end;
266
 
13 daniel-mar 267
procedure TForm1.ActionRunExecute(Sender: TObject);
268
begin
269
  Run(Sender);
270
  SynEdit1.SetFocus;
271
end;
5 daniel-mar 272
 
13 daniel-mar 273
procedure TForm1.ActionSaveExecute(Sender: TObject);
274
begin
27 daniel-mar 275
  SynEdit1.Lines.SaveToFile(GetScrapFile);
16 daniel-mar 276
  SynEdit1.Modified := false;
47 daniel-mar 277
  RefreshModifySign;
13 daniel-mar 278
end;
279
 
23 daniel-mar 280
procedure TForm1.ActionSpaceToTabExecute(Sender: TObject);
281
 
282
    function SpacesAtBeginning(line: string): integer;
283
    begin
284
      result := 0;
44 daniel-mar 285
      if Trim(line) = '' then exit;
23 daniel-mar 286
      while line[result+1] = ' ' do
287
      begin
288
        inc(result);
289
      end;
290
    end;
291
 
44 daniel-mar 292
    function GuessIndent(lines: {$IFDEF UNICODE}TStrings{$ELSE}TUnicodeStrings{$ENDIF}): integer;
23 daniel-mar 293
      function _Check(indent: integer): boolean;
294
      var
295
        i: integer;
296
      begin
297
        result := true;
298
        for i := 0 to lines.Count-1 do
299
          if SpacesAtBeginning(lines.Strings[i]) mod indent <> 0 then
300
          begin
301
            // ShowMessageFmt('Zeile "%s" nicht durch %d teilbar!', [lines.strings[i], indent]);
44 daniel-mar 302
            result := false;
303
            exit;
23 daniel-mar 304
          end;
305
      end;
306
    var
307
      i: integer;
308
    begin
309
      for i := 8 downto 2 do
310
      begin
44 daniel-mar 311
        if _Check(i) then
312
        begin
313
          result := i;
314
          exit;
315
        end;
23 daniel-mar 316
      end;
317
      result := -1;
318
    end;
319
 
44 daniel-mar 320
    procedure SpaceToTab(lines: {$IFDEF UNICODE}TStrings{$ELSE}TUnicodeStrings{$ENDIF}; indent: integer);
23 daniel-mar 321
    var
322
      i, spaces: integer;
323
    begin
324
      for i := 0 to lines.Count-1 do
325
      begin
326
        spaces := SpacesAtBeginning(lines.Strings[i]);
327
        lines.Strings[i] := StringOfChar(#9, spaces div indent) + StringOfChar(' ', spaces mod indent) + Copy(lines.Strings[i], spaces+1, Length(lines.Strings[i])-spaces);
328
      end;
329
    end;
330
 
44 daniel-mar 331
    function SpacesAvailable(lines: {$IFDEF UNICODE}TStrings{$ELSE}TUnicodeStrings{$ENDIF}): boolean;
23 daniel-mar 332
    var
333
      i, spaces: integer;
334
    begin
335
      for i := 0 to lines.Count-1 do
336
      begin
337
        spaces := SpacesAtBeginning(lines.Strings[i]);
44 daniel-mar 338
        if spaces > 0 then
339
        begin
340
          result := true;
341
          exit;
342
        end;
23 daniel-mar 343
      end;
44 daniel-mar 344
      result := false;
345
      exit;
23 daniel-mar 346
    end;
347
 
348
var
349
  val: string;
350
  ind: integer;
351
resourcestring
352
  SNoLinesAvailable = 'No lines with spaces at the beginning available';
353
begin
354
  // TODO: if something is selected, only process the selected part
355
 
356
  if not SpacesAvailable(SynEdit1.Lines) then
357
  begin
49 daniel-mar 358
    MessageDlg(SNoLinesAvailable, mtInformation, [mbOk], 0);
23 daniel-mar 359
    exit;
360
  end;
361
 
362
  ind := GuessIndent(SynEdit1.Lines);
363
  if ind <> -1 then val := IntToStr(ind);
364
 
365
  InputQuery('Spaces to tabs', 'Indent:', val); // TODO: handle CANCEL correctly...
44 daniel-mar 366
  if TryStrToInt(Trim(val), ind) then
23 daniel-mar 367
  begin
368
    if ind = 0 then exit;
369
    SpaceToTab(SynEdit1.Lines, ind);
370
  end;
371
 
372
  if SynEdit1.CanFocus then SynEdit1.SetFocus;
373
end;
374
 
13 daniel-mar 375
procedure TForm1.ActionESCExecute(Sender: TObject);
376
begin
377
  if (HlpPrevPageIndex <> -1) and (PageControl2.ActivePage = HelpTabSheet) and
378
     (HelpTabsheet.TabVisible) then
379
  begin
380
    PageControl2.ActivePageIndex := HlpPrevPageIndex;
381
    HelpTabsheet.TabVisible := false;
2 daniel-mar 382
  end;
13 daniel-mar 383
 
384
  // Dirty hack...
22 daniel-mar 385
  SrcRep.CloseDialogs;
2 daniel-mar 386
end;
387
 
13 daniel-mar 388
procedure TForm1.ActionFindExecute(Sender: TObject);
389
begin
390
  SrcRep.FindExecute;
391
end;
392
 
16 daniel-mar 393
var
394
  firstTimeBrowserLoad: boolean = true;
2 daniel-mar 395
procedure TForm1.Run(Sender: TObject);
16 daniel-mar 396
var
397
  bakTS: TTabSheet;
2 daniel-mar 398
begin
5 daniel-mar 399
  memo2.Lines.Text := '';
16 daniel-mar 400
 
401
  if firstTimeBrowserLoad then
402
  begin
403
    bakTS := PageControl1.ActivePage;
404
    try
405
      PageControl1.ActivePage := HtmlTabSheet; // Required for the first time, otherwise, WebBrowser1.Clear will hang
406
      Webbrowser1.Clear;
407
    finally
408
      PageControl1.ActivePage := bakTS;
409
    end;
410
    firstTimeBrowserLoad := false;
411
  end
412
  else
413
    Webbrowser1.Clear;
414
 
5 daniel-mar 415
  Screen.Cursor := crHourGlass;
416
  Application.ProcessMessages;
417
 
418
  try
47 daniel-mar 419
    ActionSave.Execute; // TODO: if it is not the scrap file: do not save the file, since the user did not intended to save... better create a temporary file and run it instead.
5 daniel-mar 420
 
45 daniel-mar 421
    memo2.Lines.Text := RunPHPScript(GetScrapFile, Sender=ActionLint, False);
5 daniel-mar 422
 
8 daniel-mar 423
    Webbrowser1.LoadHTML(MarkUpLineReference(memo2.Lines.Text), GetScrapFile);
5 daniel-mar 424
 
425
    if IsTextHTML(memo2.lines.text) then
426
      PageControl1.ActivePage := HtmlTabSheet
427
    else
428
      PageControl1.ActivePage := PlaintextTabSheet;
429
  finally
430
    Screen.Cursor := crDefault;
2 daniel-mar 431
  end;
5 daniel-mar 432
end;
2 daniel-mar 433
 
45 daniel-mar 434
procedure TForm1.RunConsole(Sender: TObject);
435
begin
47 daniel-mar 436
  ActionSave.Execute; // TODO: if it is not the scrap file: do not save the file, since the user did not intended to save... better create a temporary file and run it instead.
45 daniel-mar 437
  RunPHPScript(GetScrapFile, Sender=ActionLint, True);
438
end;
439
 
47 daniel-mar 440
procedure TForm1.SynEdit1Change(Sender: TObject);
441
begin
442
  RefreshModifySign;
443
end;
444
 
30 daniel-mar 445
procedure TForm1.SynEdit1GutterClick(Sender: TObject; Button: TMouseButton; X,
446
  Y, Line: Integer; Mark: TSynEditMark);
447
begin
448
  (*
449
  TSynEdit(Sender).CaretX := 1;
450
  TSynEdit(Sender).CaretY := Line;
451
  TSynEdit(Sender).SelLength := Length(TSynEdit(Sender).LineText);
452
  *)
453
end;
454
 
23 daniel-mar 455
procedure TForm1.SynEdit1MouseCursor(Sender: TObject; const aLineCharPos: TBufferCoord; var aCursor: TCursor);
456
{$IFDEF OnlineHelp}
457
var
458
  Line: Integer;
459
  Column: Integer;
460
  word: string;
461
begin
462
  Line  := aLineCharPos.Line-1;
463
  Column := aLineCharPos.Char-1;
464
  word := GetWordUnderPos(TSynEdit(Sender), Line, Column);
465
  if word <> gOnlineHelpWord then
466
  begin
467
    gOnlineHelpWord := word;
468
    Timer1.Enabled := false;
469
    Timer1.Enabled := true;
470
  end;
471
{$ELSE}
472
begin
473
{$ENDIF}
474
end;
475
 
13 daniel-mar 476
procedure TForm1.SynEdit1MouseWheelDown(Sender: TObject; Shift: TShiftState;
477
  MousePos: TPoint; var Handled: Boolean);
478
begin
479
  if ssCtrl in Shift then
480
  begin
481
    SynEdit1.Font.Size := Max(SynEdit1.Font.Size - 1, 5);
23 daniel-mar 482
    Handled := true;
483
  end
484
  else Handled := false;
13 daniel-mar 485
end;
486
 
487
procedure TForm1.SynEdit1MouseWheelUp(Sender: TObject; Shift: TShiftState;
488
  MousePos: TPoint; var Handled: Boolean);
489
begin
490
  if ssCtrl in Shift then
491
  begin
492
    SynEdit1.Font.Size := SynEdit1.Font.Size + 1;
23 daniel-mar 493
    Handled := true;
494
  end
495
  else Handled := false;
13 daniel-mar 496
end;
497
 
31 daniel-mar 498
procedure TForm1.SynEdit1PaintTransient(Sender: TObject; Canvas: TCanvas; TransientType: TTransientType);
499
var
500
  Editor: TSynEdit;
501
  OpenChars: array of WideChar;//[0..2] of WideChar=();
502
  CloseChars: array of WideChar;//[0..2] of WideChar=();
503
 
504
  function IsCharBracket(AChar: WideChar): Boolean;
505
  begin
506
    case AChar of
507
      '{','[','(','<','}',']',')','>':
508
        Result := True;
509
      else
510
        Result := False;
511
    end;
512
  end;
513
 
514
  function CharToPixels(P: TBufferCoord): TPoint;
515
  begin
516
    Result := Editor.RowColumnToPixels(Editor.BufferToDisplayPos(P));
517
  end;
518
 
519
const
33 daniel-mar 520
  COLOR_FG = clGreen;
521
  COLOR_BG = clLime;
31 daniel-mar 522
var
523
  P: TBufferCoord;
524
  Pix: TPoint;
525
  D: TDisplayCoord;
526
  S: UnicodeString;
527
  I: Integer;
528
  Attri: TSynHighlighterAttributes;
529
  ArrayLength: Integer;
530
  start: Integer;
531
  TmpCharA, TmpCharB: WideChar;
44 daniel-mar 532
begin      
31 daniel-mar 533
  // Source: https://github.com/SynEdit/SynEdit/blob/master/Demos/OnPaintTransientDemo/Unit1.pas
534
 
535
  if TSynEdit(Sender).SelAvail then exit;
536
  Editor := TSynEdit(Sender);
537
  ArrayLength:= 3;
538
 
539
  (*
540
  if (Editor.Highlighter = shHTML) or (Editor.Highlighter = shXML) then
541
    inc(ArrayLength);
542
  *)
543
 
544
  SetLength(OpenChars, ArrayLength);
545
  SetLength(CloseChars, ArrayLength);
546
  for i := 0 to ArrayLength - 1 do
547
  begin
548
    case i of
549
      0: begin OpenChars[i] := '('; CloseChars[i] := ')'; end;
550
      1: begin OpenChars[i] := '{'; CloseChars[i] := '}'; end;
551
      2: begin OpenChars[i] := '['; CloseChars[i] := ']'; end;
552
      3: begin OpenChars[i] := '<'; CloseChars[i] := '>'; end;
553
    end;
554
  end;
555
 
556
  P := Editor.CaretXY;
557
  D := Editor.DisplayXY;
558
 
559
  Start := Editor.SelStart;
560
 
561
  if (Start > 0) and (Start <= length(Editor.Text)) then
562
    TmpCharA := Editor.Text[Start]
563
  else
564
    TmpCharA := #0;
565
 
44 daniel-mar 566
  if (Start > 0){Added by VTS} and (Start < length(Editor.Text)) then
31 daniel-mar 567
    TmpCharB := Editor.Text[Start + 1]
568
  else
569
    TmpCharB := #0;
570
 
571
  if not IsCharBracket(TmpCharA) and not IsCharBracket(TmpCharB) then exit;
572
  S := TmpCharB;
573
  if not IsCharBracket(TmpCharB) then
574
  begin
575
    P.Char := P.Char - 1;
576
    S := TmpCharA;
577
  end;
578
  Editor.GetHighlighterAttriAtRowCol(P, S, Attri);
579
 
580
  if (Editor.Highlighter.SymbolAttribute = Attri) then
581
  begin
582
    for i := low(OpenChars) to High(OpenChars) do
583
    begin
584
      if (S = OpenChars[i]) or (S = CloseChars[i]) then
585
      begin
586
        Pix := CharToPixels(P);
587
 
588
        Editor.Canvas.Brush.Style := bsSolid;//Clear;
589
        Editor.Canvas.Font.Assign(Editor.Font);
590
        Editor.Canvas.Font.Style := Attri.Style;
591
 
592
        if (TransientType = ttAfter) then
593
        begin
594
          Editor.Canvas.Font.Color := COLOR_FG;
595
          Editor.Canvas.Brush.Color := COLOR_BG;
596
        end
597
        else
598
        begin
599
          Editor.Canvas.Font.Color := Attri.Foreground;
600
          Editor.Canvas.Brush.Color := Attri.Background;
601
        end;
602
        if Editor.Canvas.Font.Color = clNone then
603
          Editor.Canvas.Font.Color := Editor.Font.Color;
604
        if Editor.Canvas.Brush.Color = clNone then
605
          Editor.Canvas.Brush.Color := Editor.Color;
606
 
607
        Editor.Canvas.TextOut(Pix.X, Pix.Y, S);
608
        P := Editor.GetMatchingBracketEx(P);
609
 
610
        if (P.Char > 0) and (P.Line > 0) then
611
        begin
612
          Pix := CharToPixels(P);
613
          if Pix.X > Editor.Gutter.Width then
614
          begin
615
            {$REGION 'Added by ViaThinkSoft'}
616
            if (TransientType = ttAfter) then
617
            begin
618
              Editor.Canvas.Font.Color := COLOR_FG;
619
              Editor.Canvas.Brush.Color := COLOR_BG;
620
            end
621
            else
622
            begin
623
              Editor.Canvas.Font.Color := Attri.Foreground;
624
              Editor.Canvas.Brush.Color := Attri.Background;
625
            end;
626
            if Editor.Canvas.Font.Color = clNone then
627
              Editor.Canvas.Font.Color := Editor.Font.Color;
628
            if Editor.Canvas.Brush.Color = clNone then
629
              Editor.Canvas.Brush.Color := Editor.Color;
630
            {$ENDREGION}
631
            if S = OpenChars[i] then
632
              Editor.Canvas.TextOut(Pix.X, Pix.Y, CloseChars[i])
633
            else Editor.Canvas.TextOut(Pix.X, Pix.Y, OpenChars[i]);
634
          end;
635
        end;
636
      end;
637
    end;
638
    Editor.Canvas.Brush.Style := bsSolid;
639
  end;
640
end;
641
 
5 daniel-mar 642
procedure TForm1.SynEditFocusTimerTimer(Sender: TObject);
643
begin
644
  SynEditFocusTimer.Enabled := false;
645
  Button1.SetFocus; // Workaround for weird bug... This (and the timer) is necessary to get the focus to SynEdit1
646
  SynEdit1.SetFocus;
647
end;
2 daniel-mar 648
 
23 daniel-mar 649
procedure TForm1.Timer1Timer(Sender: TObject);
650
begin
651
  {$IFDEF OnlineHelp}
652
  Timer1.Enabled := false;
653
 
654
  // TODO: Insert a small online help hint
655
  //Caption := gOnlineHelpWord;
656
  {$ENDIF}
657
end;
658
 
27 daniel-mar 659
procedure TForm1.TreeView1DblClick(Sender: TObject);
660
var
661
  tn: TTreeNode;
32 daniel-mar 662
  lineNo: integer;
27 daniel-mar 663
begin
664
  tn := TTreeView(Sender).Selected;
665
  if tn = nil then exit;
32 daniel-mar 666
  lineNo := Integer(tn.Data);
667
  if lineNo > 0 then GotoLineNo(lineNo);
27 daniel-mar 668
end;
669
 
45 daniel-mar 670
(*
44 daniel-mar 671
{$IFDEF USE_SHDOCVW_TLB}
45 daniel-mar 672
*)
5 daniel-mar 673
procedure TForm1.WebBrowser1BeforeNavigate2(ASender: TObject;
27 daniel-mar 674
  const pDisp: IDispatch; const URL, Flags, TargetFrameName, PostData,
5 daniel-mar 675
  Headers: OleVariant; var Cancel: WordBool);
44 daniel-mar 676
begin
677
  BeforeNavigate(URL, Cancel);
678
end;
45 daniel-mar 679
(*
44 daniel-mar 680
{$ELSE}
681
procedure TForm1.WebBrowser1BeforeNavigate2(ASender: TObject;
682
  const pDisp: IDispatch; var URL, Flags, TargetFrameName, PostData,
683
  Headers: OleVariant; var Cancel: WordBool);
684
begin
685
  BeforeNavigate(URL, Cancel);
686
end;
687
{$ENDIF}
45 daniel-mar 688
*)
44 daniel-mar 689
 
690
procedure TForm1.BeforeNavigate(const URL: OleVariant; var Cancel: WordBool);
5 daniel-mar 691
var
8 daniel-mar 692
  s, myURL: string;
5 daniel-mar 693
  lineno: integer;
7 daniel-mar 694
  p: integer;
5 daniel-mar 695
begin
7 daniel-mar 696
  {$REGION 'Line number references (PHP errors and warnings)'}
8 daniel-mar 697
  if Copy(URL, 1, length(FASTPHP_GOTO_URI_PREFIX)) = FASTPHP_GOTO_URI_PREFIX then
5 daniel-mar 698
  begin
699
    try
8 daniel-mar 700
      s := copy(URL, length(FASTPHP_GOTO_URI_PREFIX)+1, 99);
5 daniel-mar 701
      if not TryStrToInt(s, lineno) then exit;
702
      GotoLineNo(lineno);
703
      SynEditFocusTimer.Enabled := true;
704
    finally
705
      Cancel := true;
706
    end;
8 daniel-mar 707
    Exit;
5 daniel-mar 708
  end;
7 daniel-mar 709
  {$ENDREGION}
710
 
8 daniel-mar 711
  {$REGION 'Intelligent browser (executes PHP scripts)'}
7 daniel-mar 712
  if URL <> 'about:blank' then
713
  begin
714
    myUrl := URL;
715
 
8 daniel-mar 716
    p := Pos('?', myUrl);
717
    if p >= 1 then myURL := copy(myURL, 1, p-1);
7 daniel-mar 718
 
8 daniel-mar 719
    // TODO: myURL urldecode
720
    // TODO: maybe we could even open that file in the editor!
7 daniel-mar 721
 
8 daniel-mar 722
    if FileExists(myURL) and (EndsText('.php', myURL) or EndsText('.php3', myURL) or EndsText('.php4', myURL) or EndsText('.php5', myURL) or EndsText('.phps', myURL)) then
7 daniel-mar 723
    begin
27 daniel-mar 724
      WebBrowser1.LoadHTML(RunPHPScript(myURL), myUrl);
7 daniel-mar 725
      Cancel := true;
726
    end;
727
  end;
728
  {$ENDREGION}
5 daniel-mar 729
end;
2 daniel-mar 730
 
57 daniel-mar 731
procedure TForm1.BtnSpecialCharsClick(Sender: TObject);
732
var
733
  opts: TSynEditorOptions;
734
begin
735
  opts := SynEdit1.Options;
736
  if eoShowSpecialChars in SynEdit1.Options then
737
  begin
738
    BtnSpecialChars.Picture.Assign(BtnSpecialCharsOff.Picture);
739
    Exclude(opts, eoShowSpecialChars);
740
    TFastPHPConfig.SpecialChars := false;
741
  end
742
  else
743
  begin
744
    BtnSpecialChars.Picture.Assign(BtnSpecialCharsOn.Picture);
745
    Include(opts, eoShowSpecialChars);
746
    TFastPHPConfig.SpecialChars := true;
747
  end;
748
  SynEdit1.Options := opts;
749
end;
750
 
2 daniel-mar 751
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
752
begin
49 daniel-mar 753
  TFastPHPConfig.FontSize := SynEdit1.Font.Size;
2 daniel-mar 754
end;
755
 
15 daniel-mar 756
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
757
var
758
  r: integer;
759
begin
760
  if SynEdit1.Modified then
761
  begin
56 daniel-mar 762
    if (ParamStr(1) <> '') or (FSaveAsFilename <> '') then
15 daniel-mar 763
    begin
764
      r := MessageDlg('Do you want to save?', mtConfirmation, mbYesNoCancel, 0);
765
      if r = mrCancel then
766
      begin
767
        CanClose := false;
768
        Exit;
769
      end
770
      else if r = mrYes then
771
      begin
47 daniel-mar 772
        ActionSave.Execute;
15 daniel-mar 773
        CanClose := true;
774
      end;
775
    end
776
    else
777
    begin
47 daniel-mar 778
      ActionSave.Execute;
15 daniel-mar 779
      CanClose := true;
780
    end;
781
  end;
782
end;
783
 
2 daniel-mar 784
procedure TForm1.FormCreate(Sender: TObject);
44 daniel-mar 785
var
786
  exeDir: string;
2 daniel-mar 787
begin
788
  HlpPrevPageIndex := -1;
789
  CurSearchTerm := '';
13 daniel-mar 790
  Caption := Caption + ' - ' + GetScrapFile;
24 daniel-mar 791
  SrcRep := TSynEditFindReplace.Create(self);
13 daniel-mar 792
  SrcRep.Editor := SynEdit1;
29 daniel-mar 793
  SynEdit1.Gutter.Gradient := HighColorWindows;
30 daniel-mar 794
 
795
  Screen.Cursors[crMouseGutter] := LoadCursor(hInstance, 'MOUSEGUTTER');
796
  SynEdit1.Gutter.Cursor := crMouseGutter;
36 daniel-mar 797
 
44 daniel-mar 798
  exeDir := IncludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0)));
799
  if FileExists(exeDir + 'codeexplorer.bmp') then ImageList1.LoadAndSplitImages(exeDir + 'codeexplorer.bmp');
2 daniel-mar 800
end;
801
 
802
procedure TForm1.FormDestroy(Sender: TObject);
803
begin
804
  if Assigned(ChmIndex) then
805
  begin
806
    FreeAndNil(ChmIndex);
807
  end;
13 daniel-mar 808
  FreeAndNil(SrcRep);
27 daniel-mar 809
 
810
  if Assigned(codeExplorer) then
811
  begin
812
    codeExplorer.Terminate;
813
    codeExplorer.WaitFor;
814
    FreeAndNil(codeExplorer);
815
  end;
2 daniel-mar 816
end;
817
 
818
procedure TForm1.FormShow(Sender: TObject);
819
var
820
  ScrapFile: string;
49 daniel-mar 821
  tmpFontSize: integer;
57 daniel-mar 822
  opts: TSynEditorOptions;
2 daniel-mar 823
begin
824
  ScrapFile := GetScrapFile;
825
  if ScrapFile = '' then
826
  begin
10 daniel-mar 827
    Application.Terminate; // Close;
2 daniel-mar 828
    exit;
829
  end;
57 daniel-mar 830
 
831
  opts := SynEdit1.Options;
832
  if TFastPHPConfig.SpecialChars then
833
  begin
834
    BtnSpecialChars.Picture.Assign(BtnSpecialCharsOn.Picture);
835
    Include(opts, eoShowSpecialChars);
836
  end
837
  else
838
  begin
839
    BtnSpecialChars.Picture.Assign(BtnSpecialCharsOff.Picture);
840
    Exclude(opts, eoShowSpecialChars);
841
  end;
842
  SynEdit1.Options := opts;
843
 
15 daniel-mar 844
  if FileExists(ScrapFile) then
845
    SynEdit1.Lines.LoadFromFile(ScrapFile)
846
  else
847
    SynEdit1.Lines.Clear;
2 daniel-mar 848
 
849
  PageControl1.ActivePage := PlaintextTabSheet;
850
 
20 daniel-mar 851
  PageControl2.ActivePage := CodeTabsheet;
2 daniel-mar 852
  HelpTabsheet.TabVisible := false;
5 daniel-mar 853
 
49 daniel-mar 854
  tmpFontSize := TFastPHPConfig.FontSize;
855
  if tmpFontSize <> -1 then SynEdit1.Font.Size := tmpFontSize;
5 daniel-mar 856
  SynEdit1.SetFocus;
27 daniel-mar 857
 
858
  DoubleBuffered := true;
859
  StartCodeExplorer;
2 daniel-mar 860
end;
861
 
56 daniel-mar 862
procedure TForm1.Save1Click(Sender: TObject);
863
begin
864
  Button7.Click;
865
end;
866
 
867
procedure TForm1.Saveas1Click(Sender: TObject);
868
begin
869
  if SaveDialog1.Execute then
870
  begin
871
    FSaveAsFilename := SaveDialog1.FileName;
872
    Caption := Copy(Caption, 1, Pos(' - ', Caption)-1) + ' - ' + FSaveAsFilename;
873
    Button7.Click;
874
  end;
875
end;
876
 
27 daniel-mar 877
procedure TForm1.StartCodeExplorer;
878
begin
879
  codeExplorer := TRunCodeExplorer.Create(true);
880
  codeExplorer.InputRequestCallback := InputRequestCallback;
881
  codeExplorer.OutputNotifyCallback := OutputNotifyCallback;
882
  codeExplorer.PhpExe := GetPHPExe;
883
  codeExplorer.PhpFile := IncludeTrailingPathDelimiter(ExtractFileDir(Application.ExeName)) + 'codeexplorer.php'; // GetScrapFile;
884
  codeExplorer.WorkDir := ExtractFileDir(Application.ExeName);
44 daniel-mar 885
  codeExplorer.Resume;
27 daniel-mar 886
end;
887
 
2 daniel-mar 888
function TForm1.GetScrapFile: string;
49 daniel-mar 889
var
890
  tmpPath: string;
2 daniel-mar 891
begin
56 daniel-mar 892
  if FSaveAsFilename <> '' then
893
  begin
894
    result := FSaveAsFilename;
895
    exit;
896
  end;
897
 
44 daniel-mar 898
  if FScrapFile <> '' then
899
  begin
900
    result := FScrapFile;
901
    exit;
902
  end;
19 daniel-mar 903
 
15 daniel-mar 904
  if ParamStr(1) <> '' then
49 daniel-mar 905
  begin
906
    // Program was started with a filename
907
 
908
    result := ParamStr(1);
909
 
910
    if not FileExists(result) then
911
    begin
912
      case MessageDlg(Format('File %s does not exist. Create it?', [result]), mtConfirmation, mbYesNoCancel, 0) of
913
        mrYes:
914
          try
915
            SynEdit1.Lines.SaveToFile(result);
916
          except
917
            on E: Exception do
918
            begin
919
              MessageDlg(E.Message, mtError, [mbOk], 0);
920
              Application.Terminate;
921
              result := '';
922
              exit;
923
            end;
924
          end;
925
        mrNo:
926
          begin
927
            Application.Terminate;
928
            result := '';
929
            exit;
930
          end;
931
        mrCancel:
932
          begin
933
            Application.Terminate;
934
            result := '';
935
            exit;
936
          end;
937
      end;
938
    end;
939
  end
13 daniel-mar 940
  else
2 daniel-mar 941
  begin
49 daniel-mar 942
    // Program is started without filename -> use scrap file
2 daniel-mar 943
 
49 daniel-mar 944
    result := TFastPHPConfig.ScrapFile;
945
 
946
    if not FileExists(result) then
947
    begin
948
      repeat
949
        {$REGION 'Determinate opendialog initial directory'}
950
        if result <> '' then
951
        begin
952
          tmpPath := ExtractFilePath(result);
953
          if DirectoryExists(tmpPath) then
954
          begin
955
            OpenDialog3.InitialDir := tmpPath;
956
            OpenDialog3.FileName := Result;
957
          end
958
          else
959
          begin
960
            OpenDialog3.InitialDir := GetMyDocumentsFolder;
961
          end;
962
        end
963
        else
964
        begin
965
          OpenDialog3.InitialDir := GetMyDocumentsFolder;
966
        end;
967
        {$ENDREGION}
968
 
969
        if not OpenDialog3.Execute then
970
        begin
971
          Application.Terminate;
972
          result := '';
973
          exit;
974
        end;
975
 
976
        if not DirectoryExists(ExtractFilePath(OpenDialog3.FileName)) then
977
        begin
978
          MessageDlg('Path does not exist! Please try again.', mtWarning, [mbOk], 0);
979
        end
980
        else
981
        begin
982
          result := OpenDialog3.FileName;
983
        end;
984
      until result <> '';
985
 
986
      if not FileExists(result) then
19 daniel-mar 987
      begin
49 daniel-mar 988
        try
989
          // Try saving the file; check if we have permissions
990
          //SynEdit1.Lines.Clear;
991
          SynEdit1.Lines.SaveToFile(result);
992
        except
993
          on E: Exception do
994
          begin
995
            MessageDlg(E.Message, mtError, [mbOk], 0);
996
            Application.Terminate;
997
            result := '';
998
            exit;
999
          end;
1000
        end;
19 daniel-mar 1001
      end;
2 daniel-mar 1002
 
49 daniel-mar 1003
      TFastPHPConfig.ScrapFile := result;
1004
      FScrapFile := result;
1005
    end;
2 daniel-mar 1006
  end;
1007
end;
1008
 
1009
procedure TForm1.Help;
1010
var
19 daniel-mar 1011
  IndexFile, chmFile, w, OriginalWord, url: string;
2 daniel-mar 1012
  internalHtmlFile: string;
1013
begin
1014
  if not Assigned(ChmIndex) then
1015
  begin
49 daniel-mar 1016
    IndexFile := TFastPHPConfig.HelpIndex;
2 daniel-mar 1017
    IndexFile := ChangeFileExt(IndexFile, '.ini'); // Just to be sure. Maybe someone wrote manually the ".chm" file in there
1018
    if FileExists(IndexFile) then
1019
    begin
1020
      ChmIndex := TMemIniFile.Create(IndexFile);
1021
    end;
1022
  end;
1023
 
1024
  if Assigned(ChmIndex) then
1025
  begin
49 daniel-mar 1026
    IndexFile := TFastPHPConfig.HelpIndex;
2 daniel-mar 1027
    // We don't check if IndexFile still exists. It is not important since we have ChmIndex pre-loaded in memory
1028
 
1029
    chmFile := ChangeFileExt(IndexFile, '.chm');
1030
    if not FileExists(chmFile) then
1031
    begin
1032
      FreeAndNil(ChmIndex);
1033
    end;
1034
  end;
1035
 
1036
  if not Assigned(ChmIndex) then
1037
  begin
1038
    if not OpenDialog1.Execute then exit;
1039
 
1040
    chmFile := OpenDialog1.FileName;
1041
    if not FileExists(chmFile) then exit;
1042
 
1043
    IndexFile := ChangeFileExt(chmFile, '.ini');
1044
 
1045
    if not FileExists(IndexFile) then
1046
    begin
1047
      Panel1.Align := alClient;
1048
      Panel1.Visible := true;
1049
      Panel1.BringToFront;
1050
      Screen.Cursor := crHourGlass;
1051
      Application.ProcessMessages;
1052
      try
1053
        if not ParseCHM(chmFile) then
1054
        begin
49 daniel-mar 1055
          MessageDlg('The CHM file is not a valid PHP documentation. Cannot use help.', mtError, [mbOk], 0);
2 daniel-mar 1056
          exit;
1057
        end;
1058
      finally
1059
        Screen.Cursor := crDefault;
1060
        Panel1.Visible := false;
1061
      end;
1062
 
1063
      if not FileExists(IndexFile) then
1064
      begin
49 daniel-mar 1065
        MessageDlg('Unknown error. Cannot use help.', mtError, [mbOk], 0);
2 daniel-mar 1066
        exit;
1067
      end;
1068
    end;
1069
 
49 daniel-mar 1070
    TFastPHPConfig.HelpIndex := IndexFile;
2 daniel-mar 1071
 
1072
    ChmIndex := TMemIniFile.Create(IndexFile);
1073
  end;
1074
 
4 daniel-mar 1075
  w := GetWordUnderCaret(SynEdit1);
2 daniel-mar 1076
  if w = '' then exit;
44 daniel-mar 1077
  {$IFDEF UNICODE}
8 daniel-mar 1078
  if CharInSet(w[1], ['0'..'9']) then exit;
44 daniel-mar 1079
  {$ELSE}
1080
  if w[1] in ['0'..'9'] then exit;
1081
  {$ENDIF}
19 daniel-mar 1082
 
1083
  Originalword := w;
1084
//  w := StringReplace(w, '_', '-', [rfReplaceAll]);
2 daniel-mar 1085
  w := LowerCase(w);
1086
  CurSearchTerm := w;
1087
 
1088
  internalHtmlFile := ChmIndex.ReadString('_HelpWords_', CurSearchTerm, '');
1089
  if internalHtmlFile = '' then
1090
  begin
1091
    HelpTabsheet.TabVisible := false;
1092
    HlpPrevPageIndex := -1;
19 daniel-mar 1093
    ShowMessageFmt('No help for "%s" available', [Originalword]);
2 daniel-mar 1094
    Exit;
1095
  end;
1096
 
1097
  url := 'mk:@MSITStore:'+ChmFile+'::'+internalHtmlFile;
1098
 
1099
  HlpPrevPageIndex := PageControl2.ActivePageIndex; // Return by pressing ESC
1100
  HelpTabsheet.TabVisible := true;
1101
  PageControl2.ActivePage := HelpTabsheet;
8 daniel-mar 1102
  WebBrowser2.Navigate(url);
1103
  WebBrowser2.Wait;
2 daniel-mar 1104
end;
1105
 
5 daniel-mar 1106
procedure TForm1.GotoLineNo(LineNo:integer);
1107
var
1108
  line: string;
1109
  i: integer;
2 daniel-mar 1110
begin
5 daniel-mar 1111
  SynEdit1.GotoLineAndCenter(LineNo);
1112
 
1113
  // Skip indent
1114
  line := SynEdit1.Lines[SynEdit1.CaretY];
1115
  for i := 1 to Length(line) do
1116
  begin
44 daniel-mar 1117
    {$IFDEF UNICODE}
8 daniel-mar 1118
    if not CharInSet(line[i], [' ', #9]) then
44 daniel-mar 1119
    {$ELSE}
1120
    if not (line[i] in [' ', #9]) then
1121
    {$ENDIF}
5 daniel-mar 1122
    begin
1123
      SynEdit1.CaretX := i-1;
1124
      break;
1125
    end;
1126
  end;
1127
 
20 daniel-mar 1128
  PageControl2.ActivePage := CodeTabsheet;
5 daniel-mar 1129
  if SynEdit1.CanFocus then SynEdit1.SetFocus;
2 daniel-mar 1130
end;
1131
 
8 daniel-mar 1132
procedure TForm1.PageControl2Changing(Sender: TObject;
1133
  var AllowChange: Boolean);
1134
begin
1135
  if PageControl2.ActivePage = HelpTabsheet then
1136
    HlpPrevPageIndex := -1
1137
  else
1138
    HlpPrevPageIndex := PageControl2.ActivePageIndex;
1139
 
1140
  AllowChange := true;
1141
end;
1142
 
5 daniel-mar 1143
procedure TForm1.Memo2DblClick(Sender: TObject);
1144
var
22 daniel-mar 1145
  line: string;
1146
 
1147
  procedure _process(toFind: string);
1148
  var
1149
    p, lineno: integer;
1150
  begin
1151
    if FileSystemCaseSensitive then
1152
      p := Pos(toFind, line)
1153
    else
44 daniel-mar 1154
      p := Pos(LowerCase(toFind), LowerCase(line));
22 daniel-mar 1155
    if p <> 0 then
1156
    begin
1157
      line := copy(line, p+length(toFind), 99);
1158
      if not TryStrToInt(line, lineno) then exit;
1159
      GotoLineNo(lineno);
1160
    end;
1161
  end;
1162
 
5 daniel-mar 1163
begin
1164
  line := memo2.Lines.Strings[Memo2.CaretPos.Y];
16 daniel-mar 1165
 
18 daniel-mar 1166
  {$REGION 'Possibility 1: filename.php:lineno'}
22 daniel-mar 1167
  _process(ExtractFileName(GetScrapFile) + ':');
18 daniel-mar 1168
  {$ENDREGION}
16 daniel-mar 1169
 
18 daniel-mar 1170
  {$REGION 'Possibility 2: on line xx'}
22 daniel-mar 1171
  _process(ExtractFileName(GetScrapFile) + ' on line ');
18 daniel-mar 1172
  {$ENDREGION}
5 daniel-mar 1173
end;
1174
 
17 daniel-mar 1175
procedure TForm1.Memo2KeyDown(Sender: TObject; var Key: Word;
1176
  Shift: TShiftState);
1177
begin
1178
  if ((ssCtrl in Shift) and (Key = 65)) then TMemo(Sender).SelectAll;
1179
end;
1180
 
5 daniel-mar 1181
function TForm1.MarkUpLineReference(cont: string): string;
18 daniel-mar 1182
 
1183
  procedure _process(toFind: string);
22 daniel-mar 1184
  var
1185
    p, a, b: integer;
1186
    num: integer;
1187
    insert_a, insert_b: string;
5 daniel-mar 1188
  begin
22 daniel-mar 1189
    if FileSystemCaseSensitive then
1190
      p := Pos(toFind, cont)
1191
    else
44 daniel-mar 1192
      p := Pos(LowerCase(toFind), LowerCase(cont));
18 daniel-mar 1193
    while p >= 1 do
5 daniel-mar 1194
    begin
22 daniel-mar 1195
      a := p;
1196
      b := p + length(toFind);
18 daniel-mar 1197
      num := 0;
44 daniel-mar 1198
      {$IFDEF UNICODE}
18 daniel-mar 1199
      while CharInSet(cont[b], ['0'..'9']) do
44 daniel-mar 1200
      {$ELSE}
1201
      while cont[b] in ['0'..'9'] do
1202
      {$ENDIF}
18 daniel-mar 1203
      begin
1204
        num := num*10 + StrToInt(cont[b]);
1205
        inc(b);
1206
      end;
5 daniel-mar 1207
 
18 daniel-mar 1208
      insert_b := '</a>';
22 daniel-mar 1209
      insert_a := '<a href="' + FASTPHP_GOTO_URI_PREFIX + IntToStr(num) + '">';
5 daniel-mar 1210
 
18 daniel-mar 1211
      insert(insert_b, cont, b);
1212
      insert(insert_a, cont, a);
5 daniel-mar 1213
 
18 daniel-mar 1214
      p := b + Length(insert_a) + Length(insert_b);
5 daniel-mar 1215
 
18 daniel-mar 1216
      p := PosEx(toFind, cont, p+1);
1217
    end;
5 daniel-mar 1218
  end;
22 daniel-mar 1219
 
18 daniel-mar 1220
begin
1221
  {$REGION 'Possibility 1: filename.php:lineno'}
22 daniel-mar 1222
  _process(ExtractFileName(GetScrapFile) + ':');
18 daniel-mar 1223
  {$ENDREGION}
5 daniel-mar 1224
 
18 daniel-mar 1225
  {$REGION 'Possibility 2: on line xx'}
22 daniel-mar 1226
  _process(ExtractFileName(GetScrapFile) + ' on line ');
18 daniel-mar 1227
  {$ENDREGION}
1228
 
5 daniel-mar 1229
  result := cont;
1230
end;
1231
 
40 daniel-mar 1232
function TForm1.InputRequestCallback(var data: AnsiString): boolean;
27 daniel-mar 1233
begin
40 daniel-mar 1234
  data := UTF8Encode(SynEdit1.Text);
1235
  result := true;
27 daniel-mar 1236
end;
1237
 
40 daniel-mar 1238
function TForm1.OutputNotifyCallback(const data: AnsiString): boolean;
27 daniel-mar 1239
begin
40 daniel-mar 1240
  result := TreeView1.FillWithFastPHPData(data);
27 daniel-mar 1241
end;
1242
 
2 daniel-mar 1243
end.