Subversion Repositories fastphp

Rev

Rev 4 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4 Rev 5
1
unit Unit1;
1
unit Unit1;
2
 
2
 
3
(*
3
(*
4
  This program requires
4
  This program requires
5
  - Microsoft Internet Controls (TWebBrowser)
5
  - Microsoft Internet Controls (TWebBrowser)
6
    If you are using Delphi 10.1 Starter Edition, please import the ActiveX TLB
6
    If you are using Delphi 10.1 Starter Edition, please import the ActiveX TLB
7
    "Microsoft Internet Controls"
7
    "Microsoft Internet Controls"
8
  - SynEdit
8
  - SynEdit
9
    You can obtain SynEdit via Embarcadero GetIt
9
    You can obtain SynEdit via Embarcadero GetIt
10
*)
10
*)
11
 
11
 
12
// TODO: localize
12
// TODO: localize
13
 
13
 
14
// TODO: wieso geht copy paste im twebbrowser nicht???
14
// TODO: wieso geht copy paste im twebbrowser nicht???
15
// Wieso dauert webbrowser1 erste kompilierung so lange???
15
// Wieso dauert webbrowser1 erste kompilierung so lange???
-
 
16
// TODO: wieso kommt syntax fehler zweimal? einmal stderr einmal stdout?
-
 
17
// TODO: Browser titlebar (link preview)
-
 
18
 
-
 
19
// TODO: strg+f / h
-
 
20
// TODO: font bigger
-
 
21
// TODO: code in bildschirmmitte?
-
 
22
// TODO: regelmäßig scrap zwischenspeichern, oder bei strg+s
16
 
23
 
17
// Future ideas
24
// Future ideas
18
// - ToDo list
25
// - ToDo list
19
// - Open/Save real files
26
// - Open/Save real files
20
// - multiple scraps?
27
// - multiple scraps?
21
// - verschiedene php versionen?
28
// - verschiedene php versionen?
22
// - webbrowser1 nur laden, wenn man den tab anwählt?
29
// - webbrowser1 nur laden, wenn man den tab anwählt?
23
// - doppelklick auf tab soll diesen schließen
30
// - doppelklick auf tab soll diesen schließen
24
// - Strg+S
31
// - Strg+S
25
// - tastenkombo für "springe zu zeile"
-
 
26
// - Onlinehelp aufrufen
32
// - Onlinehelp (www) aufrufen
27
 
33
 
28
interface
34
interface
29
 
35
 
30
uses
36
uses
31
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
37
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
32
  Dialogs, StdCtrls, OleCtrls, ComCtrls, ExtCtrls, ToolWin, IniFiles,
38
  Dialogs, StdCtrls, OleCtrls, ComCtrls, ExtCtrls, ToolWin, IniFiles,
33
  SynEditHighlighter, SynHighlighterPHP, SynEdit, SHDocVw_TLB;
39
  SynEditHighlighter, SynHighlighterPHP, SynEdit, SHDocVw_TLB;
34
 
40
 
35
type
41
type
36
  TForm1 = class(TForm)
42
  TForm1 = class(TForm)
37
    PageControl1: TPageControl;
43
    PageControl1: TPageControl;
38
    PlaintextTabSheet: TTabSheet;
44
    PlaintextTabSheet: TTabSheet;
39
    HtmlTabSheet: TTabSheet;
45
    HtmlTabSheet: TTabSheet;
40
    Memo2: TMemo;
46
    Memo2: TMemo;
41
    WebBrowser1: TWebBrowser;
47
    WebBrowser1: TWebBrowser;
42
    Splitter1: TSplitter;
48
    Splitter1: TSplitter;
43
    PageControl2: TPageControl;
49
    PageControl2: TPageControl;
44
    TabSheet3: TTabSheet;
50
    TabSheet3: TTabSheet;
45
    HelpTabsheet: TTabSheet;
51
    HelpTabsheet: TTabSheet;
46
    WebBrowser2: TWebBrowser;
52
    WebBrowser2: TWebBrowser;
47
    OpenDialog1: TOpenDialog;
53
    OpenDialog1: TOpenDialog;
48
    Panel1: TPanel;
54
    Panel1: TPanel;
49
    OpenDialog2: TOpenDialog;
55
    OpenDialog2: TOpenDialog;
50
    OpenDialog3: TOpenDialog;
56
    OpenDialog3: TOpenDialog;
51
    SynEdit1: TSynEdit;
57
    SynEdit1: TSynEdit;
52
    SynPHPSyn1: TSynPHPSyn;
58
    SynPHPSyn1: TSynPHPSyn;
-
 
59
    Panel2: TPanel;
-
 
60
    SynEditFocusTimer: TTimer;
-
 
61
    Button1: TButton;
-
 
62
    Button2: TButton;
-
 
63
    Button3: TButton;
53
    procedure Run(Sender: TObject);
64
    procedure Run(Sender: TObject);
54
    procedure FormShow(Sender: TObject);
65
    procedure FormShow(Sender: TObject);
55
    procedure Memo1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
-
 
56
    procedure FormCreate(Sender: TObject);
66
    procedure FormCreate(Sender: TObject);
57
    procedure FormDestroy(Sender: TObject);
67
    procedure FormDestroy(Sender: TObject);
58
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
68
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
59
    procedure PageControl2Changing(Sender: TObject; var AllowChange: Boolean);
69
    procedure PageControl2Changing(Sender: TObject; var AllowChange: Boolean);
-
 
70
    procedure Memo2DblClick(Sender: TObject);
-
 
71
    procedure WebBrowser1BeforeNavigate2(ASender: TObject;
-
 
72
      const pDisp: IDispatch; const URL, Flags, TargetFrameName, PostData,
-
 
73
      Headers: OleVariant; var Cancel: WordBool);
-
 
74
    procedure SynEditFocusTimerTimer(Sender: TObject);
-
 
75
    procedure Button1Click(Sender: TObject);
-
 
76
    procedure Button2Click(Sender: TObject);
-
 
77
    procedure Button3Click(Sender: TObject);
60
  private
78
  private
61
    CurSearchTerm: string;
79
    CurSearchTerm: string;
62
    HlpPrevPageIndex: integer;
80
    HlpPrevPageIndex: integer;
63
    procedure Help;
81
    procedure Help;
64
    procedure ApplicationOnMessage(var Msg: tagMSG; var Handled: Boolean);
82
    procedure ApplicationOnMessage(var Msg: tagMSG; var Handled: Boolean);
-
 
83
    function MarkUpLineReference(cont: string): string;
65
  protected
84
  protected
66
    FastPHPConfig: TMemIniFile;
85
    FastPHPConfig: TMemIniFile;
67
    ChmIndex: TMemIniFile;
86
    ChmIndex: TMemIniFile;
-
 
87
    procedure GotoLineNo(LineNo:integer);
68
    function GetScrapFile: string;
88
    function GetScrapFile: string;
69
  end;
89
  end;
70
 
90
 
71
var
91
var
72
  Form1: TForm1;
92
  Form1: TForm1;
73
 
93
 
74
implementation
94
implementation
75
 
95
 
76
{$R *.dfm}
96
{$R *.dfm}
77
 
97
 
78
uses
98
uses
79
  Functions;
99
  Functions, StrUtils;
80
 
100
 
81
procedure TForm1.ApplicationOnMessage(var Msg: tagMSG; var Handled: Boolean);
101
procedure TForm1.ApplicationOnMessage(var Msg: tagMSG; var Handled: Boolean);
-
 
102
var
-
 
103
  val: string;
-
 
104
  lineno: integer;
82
begin                    
105
begin
83
  case Msg.message of
106
  case Msg.message of
84
    WM_KEYUP:
107
    WM_KEYUP:
85
    begin
108
    begin
86
      case Msg.wParam of
109
      case Msg.wParam of
-
 
110
        {$REGION 'Esc'}
87
        VK_ESCAPE:
111
        VK_ESCAPE:
88
        begin
112
        begin
-
 
113
          Handled := true;
89
          // It is necessary to use Application.OnMessage, because Form1.KeyPreview does not work when TWebBrowser has the focus
114
          // It is necessary to use Application.OnMessage, because Form1.KeyPreview does not work when TWebBrowser has the focus
90
          if (HlpPrevPageIndex <> -1) and (PageControl2.ActivePage = HelpTabSheet) and
115
          if (HlpPrevPageIndex <> -1) and (PageControl2.ActivePage = HelpTabSheet) and
91
             (HelpTabsheet.TabVisible) then
116
             (HelpTabsheet.TabVisible) then
92
          begin
117
          begin
93
            PageControl2.ActivePageIndex := HlpPrevPageIndex;
118
            PageControl2.ActivePageIndex := HlpPrevPageIndex;
94
            HelpTabsheet.TabVisible := false;
119
            HelpTabsheet.TabVisible := false;
95
          end;
120
          end;
-
 
121
        end;
-
 
122
        {$ENDREGION}
-
 
123
 
-
 
124
        {$REGION 'Ctrl+G : Go to line'}
-
 
125
        ord('G'):
-
 
126
        begin
-
 
127
          // TODO: VK_LMENU does not work! only works with AltGr but not Alt
-
 
128
          // http://stackoverflow.com/questions/16828250/delphi-xe2-how-to-prevent-the-alt-key-stealing-focus ?
-
 
129
          if (GetKeyState(VK_CONTROL) < 0) then
-
 
130
          begin
-
 
131
            Handled := true;
-
 
132
            InputQuery('Go to', 'Line number:', val);
-
 
133
            if not TryStrToInt(val, lineno) then exit;
-
 
134
            GotoLineNo(lineno);
-
 
135
          end;
-
 
136
        end;
-
 
137
        {$ENDREGION}
-
 
138
 
-
 
139
        VK_F1:
-
 
140
        begin
-
 
141
          if SynEdit1.Focused then
-
 
142
          begin
96
          Handled := true;
143
            Handled := true;
-
 
144
            Help;
-
 
145
          end;
-
 
146
        end;
-
 
147
 
-
 
148
        VK_F5:
-
 
149
        begin
-
 
150
          Run(Self);
-
 
151
        end;
-
 
152
 
-
 
153
        VK_F9:
-
 
154
        begin
-
 
155
          Run(Self);
97
        end;
156
        end;
98
      end;
157
      end;
99
    end;
158
    end;
100
  end;
159
  end;
101
end;
160
end;
102
 
161
 
103
procedure TForm1.Run(Sender: TObject);
162
procedure TForm1.Run(Sender: TObject);
104
var
163
var
105
  phpExe: string;
164
  phpExe: string;
106
begin
165
begin
-
 
166
  memo2.Lines.Text := '';
-
 
167
  BrowseContent(Webbrowser1, memo2.Lines.Text);
-
 
168
  Screen.Cursor := crHourGlass;
-
 
169
  Application.ProcessMessages;
-
 
170
 
-
 
171
  try
107
  if not FileExists(phpExe) then
172
    if not FileExists(phpExe) then
108
  begin
173
    begin
109
    phpExe := FastPHPConfig.ReadString('Paths', 'PHPInterpreter', '');
174
      phpExe := FastPHPConfig.ReadString('Paths', 'PHPInterpreter', '');
110
    if not FileExists(phpExe) then
175
      if not FileExists(phpExe) then
111
    begin
176
      begin
112
      if not OpenDialog2.Execute then exit;
177
        if not OpenDialog2.Execute then exit;
113
      if not FileExists(OpenDialog2.FileName) then exit;
178
        if not FileExists(OpenDialog2.FileName) then exit;
114
      phpExe := OpenDialog2.FileName;
179
        phpExe := OpenDialog2.FileName;
115
 
180
 
116
      if not IsValidPHPExe(phpExe) then
181
        if not IsValidPHPExe(phpExe) then
117
      begin
182
        begin
118
        ShowMessage('This is not a valid PHP executable.');
183
          ShowMessage('This is not a valid PHP executable.');
119
        exit;
184
          exit;
120
      end;
185
        end;
121
 
186
 
122
      FastPHPConfig.WriteString('Paths', 'PHPInterpreter', phpExe);
187
        FastPHPConfig.WriteString('Paths', 'PHPInterpreter', phpExe);
123
      FastPHPConfig.UpdateFile;
188
        FastPHPConfig.UpdateFile;
124
    end;
189
      end;
125
  end;
190
    end;
126
 
191
 
127
  SynEdit1.Lines.SaveToFile(GetScrapFile);
192
    SynEdit1.Lines.SaveToFile(GetScrapFile);
128
 
193
 
129
  memo2.Lines.Text := GetDosOutput('"'+phpExe+'" "'+GetScrapFile+'"', ExtractFileDir(Application.ExeName));
194
    memo2.Lines.Text := GetDosOutput('"'+phpExe+'" "'+GetScrapFile+'"', ExtractFileDir(Application.ExeName));
130
 
195
 
131
  BrowseContent(Webbrowser1, memo2.Lines.Text);
196
    BrowseContent(Webbrowser1, MarkUpLineReference(memo2.Lines.Text));
132
 
197
 
133
  if IsTextHTML(memo2.lines.text) then
198
    if IsTextHTML(memo2.lines.text) then
134
    PageControl1.ActivePage := HtmlTabSheet
199
      PageControl1.ActivePage := HtmlTabSheet
135
  else
200
    else
136
    PageControl1.ActivePage := PlaintextTabSheet;
201
      PageControl1.ActivePage := PlaintextTabSheet;
-
 
202
  finally
-
 
203
    Screen.Cursor := crDefault;
-
 
204
  end;
-
 
205
end;
-
 
206
 
-
 
207
procedure TForm1.SynEditFocusTimerTimer(Sender: TObject);
-
 
208
begin
-
 
209
  SynEditFocusTimer.Enabled := false;
-
 
210
  Button1.SetFocus; // Workaround for weird bug... This (and the timer) is necessary to get the focus to SynEdit1
-
 
211
  SynEdit1.SetFocus;
-
 
212
end;
-
 
213
 
-
 
214
procedure TForm1.WebBrowser1BeforeNavigate2(ASender: TObject;
-
 
215
  const pDisp: IDispatch; const URL, Flags, TargetFrameName, PostData,
-
 
216
  Headers: OleVariant; var Cancel: WordBool);
-
 
217
const
-
 
218
  MAG_BEGIN = 'fastphp://gotoline/';
-
 
219
var
-
 
220
  s: string;
-
 
221
  lineno: integer;
-
 
222
begin
-
 
223
  if Copy(URL, 1, length(MAG_BEGIN)) = MAG_BEGIN then
-
 
224
  begin
-
 
225
    try
-
 
226
      s := copy(URL, length(MAG_BEGIN)+1, 99);
-
 
227
      if not TryStrToInt(s, lineno) then exit;
-
 
228
      GotoLineNo(lineno);
-
 
229
      SynEditFocusTimer.Enabled := true;
-
 
230
    finally
-
 
231
      Cancel := true;
-
 
232
    end;
-
 
233
  end;
-
 
234
end;
-
 
235
 
-
 
236
procedure TForm1.Button1Click(Sender: TObject);
-
 
237
begin
-
 
238
  Run(Sender);
-
 
239
  SynEdit1.SetFocus;
-
 
240
end;
-
 
241
 
-
 
242
procedure TForm1.Button2Click(Sender: TObject);
-
 
243
begin
-
 
244
  Help;
-
 
245
  if PageControl2.ActivePage = HelpTabsheet then
-
 
246
    WebBrowser2.SetFocus
-
 
247
  else if PageControl2.ActivePage = TabSheet3{Scrap} then
-
 
248
    SynEdit1.SetFocus;
-
 
249
end;
-
 
250
 
-
 
251
procedure TForm1.Button3Click(Sender: TObject);
-
 
252
var
-
 
253
  val: string;
-
 
254
  lineno: integer;
-
 
255
begin
-
 
256
  InputQuery('Go to', 'Line number:', val);
-
 
257
  if not TryStrToInt(val, lineno) then exit;
-
 
258
  GotoLineNo(lineno);
137
end;
259
end;
138
 
260
 
139
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
261
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
140
begin
262
begin
141
  SynEdit1.Lines.SaveToFile(GetScrapFile);
263
  SynEdit1.Lines.SaveToFile(GetScrapFile);
142
end;
264
end;
143
 
265
 
144
procedure TForm1.FormCreate(Sender: TObject);
266
procedure TForm1.FormCreate(Sender: TObject);
145
begin
267
begin
146
  HlpPrevPageIndex := -1;
268
  HlpPrevPageIndex := -1;
147
  CurSearchTerm := '';
269
  CurSearchTerm := '';
148
  Application.OnMessage := ApplicationOnMessage;
270
  Application.OnMessage := ApplicationOnMessage;
149
 
271
 
150
  FastPHPConfig := TMemIniFile.Create(ChangeFileExt(Application.ExeName, '.ini'));
272
  FastPHPConfig := TMemIniFile.Create(ChangeFileExt(Application.ExeName, '.ini'));
151
end;
273
end;
152
 
274
 
153
procedure TForm1.FormDestroy(Sender: TObject);
275
procedure TForm1.FormDestroy(Sender: TObject);
154
begin
276
begin
155
  if Assigned(ChmIndex) then
277
  if Assigned(ChmIndex) then
156
  begin
278
  begin
157
    FreeAndNil(ChmIndex);
279
    FreeAndNil(ChmIndex);
158
  end;
280
  end;
159
 
281
 
160
  FastPHPConfig.UpdateFile;
282
  FastPHPConfig.UpdateFile;
161
  FreeAndNil(FastPHPConfig);
283
  FreeAndNil(FastPHPConfig);
162
end;
284
end;
163
 
285
 
164
procedure TForm1.FormShow(Sender: TObject);
286
procedure TForm1.FormShow(Sender: TObject);
165
var
287
var
166
  ScrapFile: string;
288
  ScrapFile: string;
167
begin
289
begin
168
  ScrapFile := GetScrapFile;
290
  ScrapFile := GetScrapFile;
169
  if ScrapFile = '' then
291
  if ScrapFile = '' then
170
  begin
292
  begin
171
    Close;
293
    Close;
172
    exit;
294
    exit;
173
  end;
295
  end;
174
  SynEdit1.Lines.LoadFromFile(ScrapFile);
296
  SynEdit1.Lines.LoadFromFile(ScrapFile);
175
 
297
 
176
  PageControl1.ActivePage := PlaintextTabSheet;
298
  PageControl1.ActivePage := PlaintextTabSheet;
177
 
299
 
178
  PageControl2.ActivePageIndex := 0; // Scraps
300
  PageControl2.ActivePageIndex := 0; // Scraps
179
  HelpTabsheet.TabVisible := false;
301
  HelpTabsheet.TabVisible := false;
-
 
302
 
-
 
303
  SynEdit1.SetFocus;
180
end;
304
end;
181
 
305
 
182
function TForm1.GetScrapFile: string;
306
function TForm1.GetScrapFile: string;
183
begin
307
begin
184
  result := FastPHPConfig.ReadString('Paths', 'ScrapFile', '');
308
  result := FastPHPConfig.ReadString('Paths', 'ScrapFile', '');
185
  if not FileExists(result) then
309
  if not FileExists(result) then
186
  begin
310
  begin
187
    if not OpenDialog3.Execute then
311
    if not OpenDialog3.Execute then
188
    begin
312
    begin
189
      result := '';
313
      result := '';
190
      exit;
314
      exit;
191
    end;
315
    end;
192
 
316
 
193
    result := OpenDialog3.FileName;
317
    result := OpenDialog3.FileName;
194
 
318
 
195
    if not DirectoryExists(ExtractFilePath(result)) then
319
    if not DirectoryExists(ExtractFilePath(result)) then
196
    begin
320
    begin
197
      ShowMessage('Path does not exist!');
321
      ShowMessage('Path does not exist!');
198
      result := '';
322
      result := '';
199
      exit;
323
      exit;
200
    end;
324
    end;
201
 
325
 
202
    SynEdit1.Lines.Clear;
326
    SynEdit1.Lines.Clear;
203
    SynEdit1.Lines.SaveToFile(result);
327
    SynEdit1.Lines.SaveToFile(result);
204
 
328
 
205
    FastPHPConfig.WriteString('Paths', 'ScrapFile', result);
329
    FastPHPConfig.WriteString('Paths', 'ScrapFile', result);
206
  end;
330
  end;
207
end;
331
end;
208
 
332
 
209
procedure TForm1.Help;
333
procedure TForm1.Help;
210
var
334
var
211
  IndexFile, chmFile, w, url: string;
335
  IndexFile, chmFile, w, url: string;
212
  internalHtmlFile: string;
336
  internalHtmlFile: string;
213
begin
337
begin
214
  if not Assigned(ChmIndex) then
338
  if not Assigned(ChmIndex) then
215
  begin
339
  begin
216
    IndexFile := FastPHPConfig.ReadString('Paths', 'HelpIndex', '');
340
    IndexFile := FastPHPConfig.ReadString('Paths', 'HelpIndex', '');
217
    IndexFile := ChangeFileExt(IndexFile, '.ini'); // Just to be sure. Maybe someone wrote manually the ".chm" file in there
341
    IndexFile := ChangeFileExt(IndexFile, '.ini'); // Just to be sure. Maybe someone wrote manually the ".chm" file in there
218
    if FileExists(IndexFile) then
342
    if FileExists(IndexFile) then
219
    begin
343
    begin
220
      ChmIndex := TMemIniFile.Create(IndexFile);
344
      ChmIndex := TMemIniFile.Create(IndexFile);
221
    end;
345
    end;
222
  end;
346
  end;
223
 
347
 
224
  if Assigned(ChmIndex) then
348
  if Assigned(ChmIndex) then
225
  begin
349
  begin
226
    IndexFile := FastPHPConfig.ReadString('Paths', 'HelpIndex', '');
350
    IndexFile := FastPHPConfig.ReadString('Paths', 'HelpIndex', '');
227
    // We don't check if IndexFile still exists. It is not important since we have ChmIndex pre-loaded in memory
351
    // We don't check if IndexFile still exists. It is not important since we have ChmIndex pre-loaded in memory
228
 
352
 
229
    chmFile := ChangeFileExt(IndexFile, '.chm');
353
    chmFile := ChangeFileExt(IndexFile, '.chm');
230
    if not FileExists(chmFile) then
354
    if not FileExists(chmFile) then
231
    begin
355
    begin
232
      FreeAndNil(ChmIndex);
356
      FreeAndNil(ChmIndex);
233
    end;
357
    end;
234
  end;
358
  end;
235
 
359
 
236
  if not Assigned(ChmIndex) then
360
  if not Assigned(ChmIndex) then
237
  begin
361
  begin
238
    if not OpenDialog1.Execute then exit;
362
    if not OpenDialog1.Execute then exit;
239
 
363
 
240
    chmFile := OpenDialog1.FileName;
364
    chmFile := OpenDialog1.FileName;
241
    if not FileExists(chmFile) then exit;
365
    if not FileExists(chmFile) then exit;
242
 
366
 
243
    IndexFile := ChangeFileExt(chmFile, '.ini');
367
    IndexFile := ChangeFileExt(chmFile, '.ini');
244
 
368
 
245
    if not FileExists(IndexFile) then
369
    if not FileExists(IndexFile) then
246
    begin
370
    begin
247
      Panel1.Align := alClient;
371
      Panel1.Align := alClient;
248
      Panel1.Visible := true;
372
      Panel1.Visible := true;
249
      Panel1.BringToFront;
373
      Panel1.BringToFront;
250
      Screen.Cursor := crHourGlass;
374
      Screen.Cursor := crHourGlass;
251
      Application.ProcessMessages;
375
      Application.ProcessMessages;
252
      try
376
      try
253
        if not ParseCHM(chmFile) then
377
        if not ParseCHM(chmFile) then
254
        begin
378
        begin
255
          ShowMessage('The CHM file is not a valid PHP documentation. Cannot use help.');
379
          ShowMessage('The CHM file is not a valid PHP documentation. Cannot use help.');
256
          exit;
380
          exit;
257
        end;
381
        end;
258
      finally
382
      finally
259
        Screen.Cursor := crDefault;
383
        Screen.Cursor := crDefault;
260
        Panel1.Visible := false;
384
        Panel1.Visible := false;
261
      end;
385
      end;
262
 
386
 
263
      if not FileExists(IndexFile) then
387
      if not FileExists(IndexFile) then
264
      begin
388
      begin
265
        ShowMessage('Unknown error. Cannot use help.');
389
        ShowMessage('Unknown error. Cannot use help.');
266
        exit;
390
        exit;
267
      end;
391
      end;
268
    end;
392
    end;
269
 
393
 
270
    FastPHPConfig.WriteString('Paths', 'HelpIndex', IndexFile);
394
    FastPHPConfig.WriteString('Paths', 'HelpIndex', IndexFile);
271
    FastPHPConfig.UpdateFile;
395
    FastPHPConfig.UpdateFile;
272
 
396
 
273
    ChmIndex := TMemIniFile.Create(IndexFile);
397
    ChmIndex := TMemIniFile.Create(IndexFile);
274
  end;
398
  end;
275
 
399
 
276
  w := GetWordUnderCaret(SynEdit1);
400
  w := GetWordUnderCaret(SynEdit1);
277
  if w = '' then exit;
401
  if w = '' then exit;
278
  if w[1] in ['0'..'9'] then exit;  
402
  if w[1] in ['0'..'9'] then exit;  
279
  w := StringReplace(w, '_', '-', [rfReplaceAll]);
403
  w := StringReplace(w, '_', '-', [rfReplaceAll]);
280
  w := LowerCase(w);
404
  w := LowerCase(w);
281
  CurSearchTerm := w;
405
  CurSearchTerm := w;
282
 
406
 
283
  internalHtmlFile := ChmIndex.ReadString('_HelpWords_', CurSearchTerm, '');
407
  internalHtmlFile := ChmIndex.ReadString('_HelpWords_', CurSearchTerm, '');
284
  if internalHtmlFile = '' then
408
  if internalHtmlFile = '' then
285
  begin
409
  begin
286
    HelpTabsheet.TabVisible := false;
410
    HelpTabsheet.TabVisible := false;
287
    HlpPrevPageIndex := -1;
411
    HlpPrevPageIndex := -1;
288
    ShowMessage('No help for "'+CurSearchTerm+'" available');
412
    ShowMessage('No help for "'+CurSearchTerm+'" available');
289
    Exit;
413
    Exit;
290
  end;
414
  end;
291
 
415
 
292
  url := 'mk:@MSITStore:'+ChmFile+'::'+internalHtmlFile;
416
  url := 'mk:@MSITStore:'+ChmFile+'::'+internalHtmlFile;
293
 
417
 
294
  HlpPrevPageIndex := PageControl2.ActivePageIndex; // Return by pressing ESC
418
  HlpPrevPageIndex := PageControl2.ActivePageIndex; // Return by pressing ESC
295
  HelpTabsheet.TabVisible := true;
419
  HelpTabsheet.TabVisible := true;
296
  PageControl2.ActivePage := HelpTabsheet;
420
  PageControl2.ActivePage := HelpTabsheet;
297
  BrowseURL(WebBrowser2, url);
421
  BrowseURL(WebBrowser2, url);
298
end;
422
end;
299
 
423
 
300
procedure TForm1.Memo1KeyDown(Sender: TObject; var Key: Word;
424
procedure TForm1.GotoLineNo(LineNo:integer);
-
 
425
var
-
 
426
  line: string;
301
  Shift: TShiftState);
427
  i: integer;
302
begin
428
begin
303
  if (Key = VK_F9) or (Key = VK_F5) then
429
  SynEdit1.GotoLineAndCenter(LineNo);
-
 
430
 
304
    Run(Sender)
431
  // Skip indent
-
 
432
  line := SynEdit1.Lines[SynEdit1.CaretY];
-
 
433
  for i := 1 to Length(line) do
-
 
434
  begin
305
  else if Key = VK_F1 then
435
    if not (line[i] in [' ', #9]) then
-
 
436
    begin
-
 
437
      SynEdit1.CaretX := i-1;
-
 
438
      break;
306
    Help;
439
    end;
-
 
440
  end;
-
 
441
 
-
 
442
  PageControl2.ActivePage := TabSheet3{Scrap};
-
 
443
  if SynEdit1.CanFocus then SynEdit1.SetFocus;
-
 
444
end;
-
 
445
 
-
 
446
procedure TForm1.Memo2DblClick(Sender: TObject);
-
 
447
var
-
 
448
  line: string;
-
 
449
  p, lineno: integer;
-
 
450
begin
-
 
451
  line := memo2.Lines.Strings[Memo2.CaretPos.Y];
-
 
452
  p := Pos(' on line ', line);
-
 
453
  if p = 0 then exit;
-
 
454
  line := copy(line, p+length(' on line '), 99);
-
 
455
  if not TryStrToInt(line, lineno) then exit;
-
 
456
  GotoLineNo(lineno);
307
end;
457
end;
308
 
458
 
309
procedure TForm1.PageControl2Changing(Sender: TObject;
459
procedure TForm1.PageControl2Changing(Sender: TObject;
310
  var AllowChange: Boolean);
460
  var AllowChange: Boolean);
311
begin
461
begin
312
  if PageControl2.ActivePage = HelpTabsheet then
462
  if PageControl2.ActivePage = HelpTabsheet then
313
    HlpPrevPageIndex := -1
463
    HlpPrevPageIndex := -1
314
  else
464
  else
315
    HlpPrevPageIndex := PageControl2.ActivePageIndex;
465
    HlpPrevPageIndex := PageControl2.ActivePageIndex;
316
 
466
 
317
  AllowChange := true;
467
  AllowChange := true;
318
end;
468
end;
-
 
469
 
-
 
470
function TForm1.MarkUpLineReference(cont: string): string;
-
 
471
var
-
 
472
  p, a, b: integer;
-
 
473
  num: integer;
-
 
474
  insert_a, insert_b: string;
-
 
475
begin
-
 
476
  // TODO: make it more specific to PHP error messages. "on line" is too broad.
-
 
477
  p := Pos(' on line ', cont);
-
 
478
  while p >= 1 do
-
 
479
  begin
-
 
480
    a := p+1;
-
 
481
    b := p+length(' on line ');
-
 
482
    num := 0;
-
 
483
    while cont[b] in ['0'..'9'] do
-
 
484
    begin
-
 
485
      num := num*10 + StrToInt(cont[b]);
-
 
486
      inc(b);
-
 
487
    end;
-
 
488
 
-
 
489
    insert_b := '</a>';
-
 
490
    insert_a := '<a href="fastphp://gotoline/'+IntToStr(num)+'">';
-
 
491
 
-
 
492
    insert(insert_b, cont, b);
-
 
493
    insert(insert_a, cont, a);
-
 
494
 
-
 
495
    p := b + Length(insert_a) + Length(insert_b);
-
 
496
 
-
 
497
    p := PosEx(' on line ', cont, p+1);
-
 
498
  end;
-
 
499
 
-
 
500
  result := cont;
-
 
501
end;
319
 
502
 
320
end.
503
end.
321
 
504