Subversion Repositories fastphp

Rev

Rev 21 | Rev 23 | 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
 
4 daniel-mar 3
(*
4
  This program requires
5
  - Microsoft Internet Controls (TWebBrowser)
6
    If you are using Delphi 10.1 Starter Edition, please import the ActiveX TLB
7
    "Microsoft Internet Controls"
8
  - SynEdit
9
    You can obtain SynEdit via Embarcadero GetIt
10
*)
11
 
2 daniel-mar 12
// TODO: localize
13
// TODO: wieso geht copy paste im twebbrowser nicht???
14
// Wieso dauert webbrowser1 erste kompilierung so lange???
5 daniel-mar 15
// TODO: wieso kommt syntax fehler zweimal? einmal stderr einmal stdout?
16
// TODO: Browser titlebar (link preview)
21 daniel-mar 17
// TODO: search prev
18
// TODO: wenn man schrift größer/kleiner macht, soll die bildschirmseite zentriert bleiben
19
// TODO: todo liste
2 daniel-mar 20
 
21
// Future ideas
21 daniel-mar 22
// - code explorer / code insight
2 daniel-mar 23
// - verschiedene php versionen?
24
// - webbrowser1 nur laden, wenn man den tab anwählt?
25
// - doppelklick auf tab soll diesen schließen
5 daniel-mar 26
// - Onlinehelp (www) aufrufen
13 daniel-mar 27
// - Let all colors be adjustable
21 daniel-mar 28
// - code in bildschirmmitte (horizontal)?
2 daniel-mar 29
 
30
interface
31
 
32
uses
33
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
4 daniel-mar 34
  Dialogs, StdCtrls, OleCtrls, ComCtrls, ExtCtrls, ToolWin, IniFiles,
13 daniel-mar 35
  SynEditHighlighter, SynHighlighterPHP, SynEdit, SHDocVw_TLB, FindReplace,
20 daniel-mar 36
  System.Actions, Vcl.ActnList, System.UITypes;
2 daniel-mar 37
 
38
type
39
  TForm1 = class(TForm)
40
    PageControl1: TPageControl;
41
    PlaintextTabSheet: TTabSheet;
42
    HtmlTabSheet: TTabSheet;
43
    Memo2: TMemo;
44
    WebBrowser1: TWebBrowser;
45
    Splitter1: TSplitter;
46
    PageControl2: TPageControl;
20 daniel-mar 47
    CodeTabsheet: TTabSheet;
2 daniel-mar 48
    HelpTabsheet: TTabSheet;
49
    WebBrowser2: TWebBrowser;
50
    OpenDialog1: TOpenDialog;
51
    Panel1: TPanel;
52
    OpenDialog3: TOpenDialog;
4 daniel-mar 53
    SynEdit1: TSynEdit;
54
    SynPHPSyn1: TSynPHPSyn;
5 daniel-mar 55
    Panel2: TPanel;
56
    SynEditFocusTimer: TTimer;
57
    Button1: TButton;
58
    Button2: TButton;
59
    Button3: TButton;
13 daniel-mar 60
    Button4: TButton;
61
    Button5: TButton;
62
    Button6: TButton;
63
    ActionList: TActionList;
64
    ActionFind: TAction;
65
    ActionReplace: TAction;
66
    ActionFindNext: TAction;
67
    ActionGoto: TAction;
68
    ActionSave: TAction;
69
    ActionHelp: TAction;
70
    ActionRun: TAction;
71
    ActionESC: TAction;
72
    Button7: TButton;
15 daniel-mar 73
    ActionOpen: TAction;
74
    Button8: TButton;
22 daniel-mar 75
    Button9: TButton;
76
    ActionFindPrev: TAction;
2 daniel-mar 77
    procedure Run(Sender: TObject);
78
    procedure FormShow(Sender: TObject);
79
    procedure FormCreate(Sender: TObject);
80
    procedure FormDestroy(Sender: TObject);
81
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
82
    procedure PageControl2Changing(Sender: TObject; var AllowChange: Boolean);
5 daniel-mar 83
    procedure Memo2DblClick(Sender: TObject);
84
    procedure WebBrowser1BeforeNavigate2(ASender: TObject;
85
      const pDisp: IDispatch; const URL, Flags, TargetFrameName, PostData,
86
      Headers: OleVariant; var Cancel: WordBool);
87
    procedure SynEditFocusTimerTimer(Sender: TObject);
13 daniel-mar 88
    procedure ActionFindExecute(Sender: TObject);
89
    procedure ActionReplaceExecute(Sender: TObject);
90
    procedure ActionFindNextExecute(Sender: TObject);
91
    procedure ActionGotoExecute(Sender: TObject);
92
    procedure ActionSaveExecute(Sender: TObject);
93
    procedure ActionHelpExecute(Sender: TObject);
94
    procedure ActionRunExecute(Sender: TObject);
95
    procedure ActionESCExecute(Sender: TObject);
96
    procedure SynEdit1MouseWheelDown(Sender: TObject; Shift: TShiftState;
97
      MousePos: TPoint; var Handled: Boolean);
98
    procedure SynEdit1MouseWheelUp(Sender: TObject; Shift: TShiftState;
99
      MousePos: TPoint; var Handled: Boolean);
15 daniel-mar 100
    procedure ActionOpenExecute(Sender: TObject);
101
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
17 daniel-mar 102
    procedure Memo2KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
22 daniel-mar 103
    procedure ActionFindPrevExecute(Sender: TObject);
2 daniel-mar 104
  private
105
    CurSearchTerm: string;
106
    HlpPrevPageIndex: integer;
13 daniel-mar 107
    SrcRep: TFindReplace;
2 daniel-mar 108
    procedure Help;
5 daniel-mar 109
    function MarkUpLineReference(cont: string): string;
2 daniel-mar 110
  protected
111
    ChmIndex: TMemIniFile;
19 daniel-mar 112
    FScrapFile: string;
5 daniel-mar 113
    procedure GotoLineNo(LineNo:integer);
2 daniel-mar 114
    function GetScrapFile: string;
115
  end;
116
 
117
var
118
  Form1: TForm1;
119
 
120
implementation
121
 
122
{$R *.dfm}
123
 
124
uses
15 daniel-mar 125
  Functions, StrUtils, WebBrowserUtils, FastPHPUtils, Math, ShellAPI;
2 daniel-mar 126
 
13 daniel-mar 127
// TODO: FindPrev ?
128
procedure TForm1.ActionFindNextExecute(Sender: TObject);
129
begin
130
  SrcRep.FindNext;
131
end;
132
 
22 daniel-mar 133
procedure TForm1.ActionFindPrevExecute(Sender: TObject);
134
begin
135
  SrcRep.FindPrev;
136
end;
137
 
13 daniel-mar 138
procedure TForm1.ActionGotoExecute(Sender: TObject);
5 daniel-mar 139
var
140
  val: string;
141
  lineno: integer;
142
begin
13 daniel-mar 143
  // TODO: VK_LMENU does not work! only works with AltGr but not Alt
144
  // http://stackoverflow.com/questions/16828250/delphi-xe2-how-to-prevent-the-alt-key-stealing-focus ?
5 daniel-mar 145
 
13 daniel-mar 146
  InputQuery('Go to', 'Line number:', val);
147
  if not TryStrToInt(val, lineno) then
148
  begin
149
    if SynEdit1.CanFocus then SynEdit1.SetFocus;
150
    exit;
151
  end;
152
  GotoLineNo(lineno);
153
end;
5 daniel-mar 154
 
13 daniel-mar 155
procedure TForm1.ActionHelpExecute(Sender: TObject);
156
begin
157
  Help;
158
  if PageControl2.ActivePage = HelpTabsheet then
159
    WebBrowser2.SetFocus
20 daniel-mar 160
  else if PageControl2.ActivePage = CodeTabsheet then
13 daniel-mar 161
    SynEdit1.SetFocus;
162
end;
8 daniel-mar 163
 
15 daniel-mar 164
procedure TForm1.ActionOpenExecute(Sender: TObject);
165
begin
166
  If OpenDialog3.Execute then
167
  begin
168
    ShellExecute(0, 'open', PChar(ParamStr(0)), PChar(OpenDialog3.FileName), '', SW_NORMAL);
169
  end;
170
end;
171
 
13 daniel-mar 172
procedure TForm1.ActionReplaceExecute(Sender: TObject);
173
begin
174
  SrcRep.ReplaceExecute;
175
end;
5 daniel-mar 176
 
13 daniel-mar 177
procedure TForm1.ActionRunExecute(Sender: TObject);
178
begin
179
  Run(Sender);
180
  SynEdit1.SetFocus;
181
end;
5 daniel-mar 182
 
13 daniel-mar 183
procedure TForm1.ActionSaveExecute(Sender: TObject);
184
begin
185
  SynEdit1.Lines.SaveToFile(GetScrapFile);
16 daniel-mar 186
  SynEdit1.Modified := false;
13 daniel-mar 187
end;
188
 
189
procedure TForm1.ActionESCExecute(Sender: TObject);
190
begin
191
  if (HlpPrevPageIndex <> -1) and (PageControl2.ActivePage = HelpTabSheet) and
192
     (HelpTabsheet.TabVisible) then
193
  begin
194
    PageControl2.ActivePageIndex := HlpPrevPageIndex;
195
    HelpTabsheet.TabVisible := false;
2 daniel-mar 196
  end;
13 daniel-mar 197
 
198
  // Dirty hack...
22 daniel-mar 199
  SrcRep.CloseDialogs;
2 daniel-mar 200
end;
201
 
13 daniel-mar 202
procedure TForm1.ActionFindExecute(Sender: TObject);
203
begin
204
  SrcRep.FindExecute;
205
end;
206
 
16 daniel-mar 207
var
208
  firstTimeBrowserLoad: boolean = true;
2 daniel-mar 209
procedure TForm1.Run(Sender: TObject);
16 daniel-mar 210
var
211
  bakTS: TTabSheet;
2 daniel-mar 212
begin
5 daniel-mar 213
  memo2.Lines.Text := '';
16 daniel-mar 214
 
215
  if firstTimeBrowserLoad then
216
  begin
217
    bakTS := PageControl1.ActivePage;
218
    try
219
      PageControl1.ActivePage := HtmlTabSheet; // Required for the first time, otherwise, WebBrowser1.Clear will hang
220
      Webbrowser1.Clear;
221
    finally
222
      PageControl1.ActivePage := bakTS;
223
    end;
224
    firstTimeBrowserLoad := false;
225
  end
226
  else
227
    Webbrowser1.Clear;
228
 
5 daniel-mar 229
  Screen.Cursor := crHourGlass;
230
  Application.ProcessMessages;
231
 
232
  try
233
    SynEdit1.Lines.SaveToFile(GetScrapFile);
234
 
8 daniel-mar 235
    memo2.Lines.Text := RunPHPScript(GetScrapFile);
5 daniel-mar 236
 
8 daniel-mar 237
    Webbrowser1.LoadHTML(MarkUpLineReference(memo2.Lines.Text), GetScrapFile);
5 daniel-mar 238
 
239
    if IsTextHTML(memo2.lines.text) then
240
      PageControl1.ActivePage := HtmlTabSheet
241
    else
242
      PageControl1.ActivePage := PlaintextTabSheet;
243
  finally
244
    Screen.Cursor := crDefault;
2 daniel-mar 245
  end;
5 daniel-mar 246
end;
2 daniel-mar 247
 
13 daniel-mar 248
procedure TForm1.SynEdit1MouseWheelDown(Sender: TObject; Shift: TShiftState;
249
  MousePos: TPoint; var Handled: Boolean);
250
begin
251
  if ssCtrl in Shift then
252
  begin
253
    SynEdit1.Font.Size := Max(SynEdit1.Font.Size - 1, 5);
254
  end;
255
end;
256
 
257
procedure TForm1.SynEdit1MouseWheelUp(Sender: TObject; Shift: TShiftState;
258
  MousePos: TPoint; var Handled: Boolean);
259
begin
260
  if ssCtrl in Shift then
261
  begin
262
    SynEdit1.Font.Size := SynEdit1.Font.Size + 1;
263
  end;
264
end;
265
 
5 daniel-mar 266
procedure TForm1.SynEditFocusTimerTimer(Sender: TObject);
267
begin
268
  SynEditFocusTimer.Enabled := false;
269
  Button1.SetFocus; // Workaround for weird bug... This (and the timer) is necessary to get the focus to SynEdit1
270
  SynEdit1.SetFocus;
271
end;
2 daniel-mar 272
 
5 daniel-mar 273
procedure TForm1.WebBrowser1BeforeNavigate2(ASender: TObject;
274
  const pDisp: IDispatch; const URL, Flags, TargetFrameName, PostData,
275
  Headers: OleVariant; var Cancel: WordBool);
276
var
8 daniel-mar 277
  s, myURL: string;
5 daniel-mar 278
  lineno: integer;
7 daniel-mar 279
  p: integer;
5 daniel-mar 280
begin
7 daniel-mar 281
  {$REGION 'Line number references (PHP errors and warnings)'}
8 daniel-mar 282
  if Copy(URL, 1, length(FASTPHP_GOTO_URI_PREFIX)) = FASTPHP_GOTO_URI_PREFIX then
5 daniel-mar 283
  begin
284
    try
8 daniel-mar 285
      s := copy(URL, length(FASTPHP_GOTO_URI_PREFIX)+1, 99);
5 daniel-mar 286
      if not TryStrToInt(s, lineno) then exit;
287
      GotoLineNo(lineno);
288
      SynEditFocusTimer.Enabled := true;
289
    finally
290
      Cancel := true;
291
    end;
8 daniel-mar 292
    Exit;
5 daniel-mar 293
  end;
7 daniel-mar 294
  {$ENDREGION}
295
 
8 daniel-mar 296
  {$REGION 'Intelligent browser (executes PHP scripts)'}
7 daniel-mar 297
  if URL <> 'about:blank' then
298
  begin
299
    myUrl := URL;
300
 
8 daniel-mar 301
    p := Pos('?', myUrl);
302
    if p >= 1 then myURL := copy(myURL, 1, p-1);
7 daniel-mar 303
 
8 daniel-mar 304
    // TODO: myURL urldecode
305
    // TODO: maybe we could even open that file in the editor!
7 daniel-mar 306
 
8 daniel-mar 307
    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 308
    begin
8 daniel-mar 309
      WebBrowser1.LoadHTML(GetDosOutput('"'+GetPHPExe+'" "'+myURL+'"', ExtractFileDir(Application.ExeName)), myUrl);
7 daniel-mar 310
      Cancel := true;
311
    end;
312
  end;
313
  {$ENDREGION}
5 daniel-mar 314
end;
2 daniel-mar 315
 
316
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
317
begin
13 daniel-mar 318
  FastPHPConfig.WriteInteger('User', 'FontSize', SynEdit1.Font.Size);
2 daniel-mar 319
end;
320
 
15 daniel-mar 321
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
322
var
323
  r: integer;
324
begin
325
  if SynEdit1.Modified then
326
  begin
327
    if ParamStr(1) <> '' then
328
    begin
329
      r := MessageDlg('Do you want to save?', mtConfirmation, mbYesNoCancel, 0);
330
      if r = mrCancel then
331
      begin
332
        CanClose := false;
333
        Exit;
334
      end
335
      else if r = mrYes then
336
      begin
337
        SynEdit1.Lines.SaveToFile(GetScrapFile);
338
        CanClose := true;
339
      end;
340
    end
341
    else
342
    begin
343
      SynEdit1.Lines.SaveToFile(GetScrapFile);
344
      CanClose := true;
345
    end;
346
  end;
347
end;
348
 
2 daniel-mar 349
procedure TForm1.FormCreate(Sender: TObject);
350
begin
351
  HlpPrevPageIndex := -1;
352
  CurSearchTerm := '';
13 daniel-mar 353
  Caption := Caption + ' - ' + GetScrapFile;
354
  SrcRep := TFindReplace.Create(self);
355
  SrcRep.Editor := SynEdit1;
2 daniel-mar 356
end;
357
 
358
procedure TForm1.FormDestroy(Sender: TObject);
359
begin
360
  if Assigned(ChmIndex) then
361
  begin
362
    FreeAndNil(ChmIndex);
363
  end;
13 daniel-mar 364
  FreeAndNil(SrcRep);
2 daniel-mar 365
end;
366
 
367
procedure TForm1.FormShow(Sender: TObject);
368
var
369
  ScrapFile: string;
370
begin
371
  ScrapFile := GetScrapFile;
372
  if ScrapFile = '' then
373
  begin
10 daniel-mar 374
    Application.Terminate; // Close;
2 daniel-mar 375
    exit;
376
  end;
15 daniel-mar 377
  if FileExists(ScrapFile) then
378
    SynEdit1.Lines.LoadFromFile(ScrapFile)
379
  else
380
    SynEdit1.Lines.Clear;
2 daniel-mar 381
 
382
  PageControl1.ActivePage := PlaintextTabSheet;
383
 
20 daniel-mar 384
  PageControl2.ActivePage := CodeTabsheet;
2 daniel-mar 385
  HelpTabsheet.TabVisible := false;
5 daniel-mar 386
 
13 daniel-mar 387
  SynEdit1.Font.Size := FastPHPConfig.ReadInteger('User', 'FontSize', SynEdit1.Font.Size);
5 daniel-mar 388
  SynEdit1.SetFocus;
2 daniel-mar 389
end;
390
 
391
function TForm1.GetScrapFile: string;
392
begin
19 daniel-mar 393
  if FScrapFile <> '' then exit(FScrapFile);
394
 
15 daniel-mar 395
  if ParamStr(1) <> '' then
13 daniel-mar 396
    result := ParamStr(1)
397
  else
398
    result := FastPHPConfig.ReadString('Paths', 'ScrapFile', '');
2 daniel-mar 399
  if not FileExists(result) then
400
  begin
19 daniel-mar 401
    repeat
402
      if not OpenDialog3.Execute then
403
      begin
404
        Application.Terminate;
405
        exit('');
406
      end;
2 daniel-mar 407
 
19 daniel-mar 408
      if not DirectoryExists(ExtractFilePath(OpenDialog3.FileName)) then
409
      begin
410
        ShowMessage('Path does not exist! Please try again.');
411
      end
412
      else
413
      begin
414
        result := OpenDialog3.FileName;
415
      end;
416
    until result <> '';
2 daniel-mar 417
 
4 daniel-mar 418
    SynEdit1.Lines.Clear;
419
    SynEdit1.Lines.SaveToFile(result);
2 daniel-mar 420
 
421
    FastPHPConfig.WriteString('Paths', 'ScrapFile', result);
19 daniel-mar 422
    FScrapFile := result;
2 daniel-mar 423
  end;
424
end;
425
 
426
procedure TForm1.Help;
427
var
19 daniel-mar 428
  IndexFile, chmFile, w, OriginalWord, url: string;
2 daniel-mar 429
  internalHtmlFile: string;
430
begin
431
  if not Assigned(ChmIndex) then
432
  begin
433
    IndexFile := FastPHPConfig.ReadString('Paths', 'HelpIndex', '');
434
    IndexFile := ChangeFileExt(IndexFile, '.ini'); // Just to be sure. Maybe someone wrote manually the ".chm" file in there
435
    if FileExists(IndexFile) then
436
    begin
437
      ChmIndex := TMemIniFile.Create(IndexFile);
438
    end;
439
  end;
440
 
441
  if Assigned(ChmIndex) then
442
  begin
443
    IndexFile := FastPHPConfig.ReadString('Paths', 'HelpIndex', '');
444
    // We don't check if IndexFile still exists. It is not important since we have ChmIndex pre-loaded in memory
445
 
446
    chmFile := ChangeFileExt(IndexFile, '.chm');
447
    if not FileExists(chmFile) then
448
    begin
449
      FreeAndNil(ChmIndex);
450
    end;
451
  end;
452
 
453
  if not Assigned(ChmIndex) then
454
  begin
455
    if not OpenDialog1.Execute then exit;
456
 
457
    chmFile := OpenDialog1.FileName;
458
    if not FileExists(chmFile) then exit;
459
 
460
    IndexFile := ChangeFileExt(chmFile, '.ini');
461
 
462
    if not FileExists(IndexFile) then
463
    begin
464
      Panel1.Align := alClient;
465
      Panel1.Visible := true;
466
      Panel1.BringToFront;
467
      Screen.Cursor := crHourGlass;
468
      Application.ProcessMessages;
469
      try
470
        if not ParseCHM(chmFile) then
471
        begin
472
          ShowMessage('The CHM file is not a valid PHP documentation. Cannot use help.');
473
          exit;
474
        end;
475
      finally
476
        Screen.Cursor := crDefault;
477
        Panel1.Visible := false;
478
      end;
479
 
480
      if not FileExists(IndexFile) then
481
      begin
482
        ShowMessage('Unknown error. Cannot use help.');
483
        exit;
484
      end;
485
    end;
486
 
487
    FastPHPConfig.WriteString('Paths', 'HelpIndex', IndexFile);
488
    FastPHPConfig.UpdateFile;
489
 
490
    ChmIndex := TMemIniFile.Create(IndexFile);
491
  end;
492
 
4 daniel-mar 493
  w := GetWordUnderCaret(SynEdit1);
2 daniel-mar 494
  if w = '' then exit;
8 daniel-mar 495
  if CharInSet(w[1], ['0'..'9']) then exit;
19 daniel-mar 496
 
497
  Originalword := w;
498
//  w := StringReplace(w, '_', '-', [rfReplaceAll]);
2 daniel-mar 499
  w := LowerCase(w);
500
  CurSearchTerm := w;
501
 
502
  internalHtmlFile := ChmIndex.ReadString('_HelpWords_', CurSearchTerm, '');
503
  if internalHtmlFile = '' then
504
  begin
505
    HelpTabsheet.TabVisible := false;
506
    HlpPrevPageIndex := -1;
19 daniel-mar 507
    ShowMessageFmt('No help for "%s" available', [Originalword]);
2 daniel-mar 508
    Exit;
509
  end;
510
 
511
  url := 'mk:@MSITStore:'+ChmFile+'::'+internalHtmlFile;
512
 
513
  HlpPrevPageIndex := PageControl2.ActivePageIndex; // Return by pressing ESC
514
  HelpTabsheet.TabVisible := true;
515
  PageControl2.ActivePage := HelpTabsheet;
8 daniel-mar 516
  WebBrowser2.Navigate(url);
517
  WebBrowser2.Wait;
2 daniel-mar 518
end;
519
 
5 daniel-mar 520
procedure TForm1.GotoLineNo(LineNo:integer);
521
var
522
  line: string;
523
  i: integer;
2 daniel-mar 524
begin
5 daniel-mar 525
  SynEdit1.GotoLineAndCenter(LineNo);
526
 
527
  // Skip indent
528
  line := SynEdit1.Lines[SynEdit1.CaretY];
529
  for i := 1 to Length(line) do
530
  begin
8 daniel-mar 531
    if not CharInSet(line[i], [' ', #9]) then
5 daniel-mar 532
    begin
533
      SynEdit1.CaretX := i-1;
534
      break;
535
    end;
536
  end;
537
 
20 daniel-mar 538
  PageControl2.ActivePage := CodeTabsheet;
5 daniel-mar 539
  if SynEdit1.CanFocus then SynEdit1.SetFocus;
2 daniel-mar 540
end;
541
 
8 daniel-mar 542
procedure TForm1.PageControl2Changing(Sender: TObject;
543
  var AllowChange: Boolean);
544
begin
545
  if PageControl2.ActivePage = HelpTabsheet then
546
    HlpPrevPageIndex := -1
547
  else
548
    HlpPrevPageIndex := PageControl2.ActivePageIndex;
549
 
550
  AllowChange := true;
551
end;
552
 
5 daniel-mar 553
procedure TForm1.Memo2DblClick(Sender: TObject);
554
var
22 daniel-mar 555
  line: string;
556
 
557
  procedure _process(toFind: string);
558
  var
559
    p, lineno: integer;
560
  begin
561
    if FileSystemCaseSensitive then
562
      p := Pos(toFind, line)
563
    else
564
      p := Pos(toFind.ToLower, line.ToLower);
565
    if p <> 0 then
566
    begin
567
      line := copy(line, p+length(toFind), 99);
568
      if not TryStrToInt(line, lineno) then exit;
569
      GotoLineNo(lineno);
570
    end;
571
  end;
572
 
5 daniel-mar 573
begin
574
  line := memo2.Lines.Strings[Memo2.CaretPos.Y];
16 daniel-mar 575
 
18 daniel-mar 576
  {$REGION 'Possibility 1: filename.php:lineno'}
22 daniel-mar 577
  _process(ExtractFileName(GetScrapFile) + ':');
18 daniel-mar 578
  {$ENDREGION}
16 daniel-mar 579
 
18 daniel-mar 580
  {$REGION 'Possibility 2: on line xx'}
22 daniel-mar 581
  _process(ExtractFileName(GetScrapFile) + ' on line ');
18 daniel-mar 582
  {$ENDREGION}
5 daniel-mar 583
end;
584
 
17 daniel-mar 585
procedure TForm1.Memo2KeyDown(Sender: TObject; var Key: Word;
586
  Shift: TShiftState);
587
begin
588
  if ((ssCtrl in Shift) and (Key = 65)) then TMemo(Sender).SelectAll;
589
end;
590
 
5 daniel-mar 591
function TForm1.MarkUpLineReference(cont: string): string;
18 daniel-mar 592
 
593
  procedure _process(toFind: string);
22 daniel-mar 594
  var
595
    p, a, b: integer;
596
    num: integer;
597
    insert_a, insert_b: string;
5 daniel-mar 598
  begin
22 daniel-mar 599
    if FileSystemCaseSensitive then
600
      p := Pos(toFind, cont)
601
    else
602
      p := Pos(toFind.ToLower, cont.ToLower);
18 daniel-mar 603
    while p >= 1 do
5 daniel-mar 604
    begin
22 daniel-mar 605
      a := p;
606
      b := p + length(toFind);
18 daniel-mar 607
      num := 0;
608
      while CharInSet(cont[b], ['0'..'9']) do
609
      begin
610
        num := num*10 + StrToInt(cont[b]);
611
        inc(b);
612
      end;
5 daniel-mar 613
 
18 daniel-mar 614
      insert_b := '</a>';
22 daniel-mar 615
      insert_a := '<a href="' + FASTPHP_GOTO_URI_PREFIX + IntToStr(num) + '">';
5 daniel-mar 616
 
18 daniel-mar 617
      insert(insert_b, cont, b);
618
      insert(insert_a, cont, a);
5 daniel-mar 619
 
18 daniel-mar 620
      p := b + Length(insert_a) + Length(insert_b);
5 daniel-mar 621
 
18 daniel-mar 622
      p := PosEx(toFind, cont, p+1);
623
    end;
5 daniel-mar 624
  end;
22 daniel-mar 625
 
18 daniel-mar 626
begin
627
  {$REGION 'Possibility 1: filename.php:lineno'}
22 daniel-mar 628
  _process(ExtractFileName(GetScrapFile) + ':');
18 daniel-mar 629
  {$ENDREGION}
5 daniel-mar 630
 
18 daniel-mar 631
  {$REGION 'Possibility 2: on line xx'}
22 daniel-mar 632
  _process(ExtractFileName(GetScrapFile) + ' on line ');
18 daniel-mar 633
  {$ENDREGION}
634
 
5 daniel-mar 635
  result := cont;
636
end;
637
 
2 daniel-mar 638
end.