Subversion Repositories fastphp

Rev

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

Rev 29 Rev 30
1
unit EditorMain;
1
unit EditorMain;
2
 
2
 
3
{$Include 'FastPHP.inc'}
3
{$Include 'FastPHP.inc'}
4
 
4
 
5
(*
5
(*
6
  This program requires
6
  This program requires
7
  - Microsoft Internet Controls (TWebBrowser)
7
  - Microsoft Internet Controls (TWebBrowser)
8
    If you are using Delphi 10.1 Starter Edition, please import the ActiveX TLB
8
    If you are using Delphi 10.1 Starter Edition, please import the ActiveX TLB
9
    "Microsoft Internet Controls"
9
    "Microsoft Internet Controls"
10
  - SynEdit
10
  - SynEdit
11
    You can obtain SynEdit via Embarcadero GetIt
11
    You can obtain SynEdit via Embarcadero GetIt
12
*)
12
*)
13
 
13
 
14
// TODO: localize
14
// TODO: localize
15
// TODO: wieso geht copy paste im twebbrowser nicht???
15
// TODO: wieso geht copy paste im twebbrowser nicht???
16
// Wieso dauert webbrowser1 erste kompilierung so lange???
16
// Wieso dauert webbrowser1 erste kompilierung so lange???
17
// TODO: wieso kommt syntax fehler zweimal? einmal stderr einmal stdout?
17
// TODO: wieso kommt syntax fehler zweimal? einmal stderr einmal stdout?
18
// TODO: Browser titlebar (link preview)
18
// TODO: Browser titlebar (link preview)
19
// TODO: todo liste
19
// TODO: todo liste
20
 
20
 
21
// Future ideas
21
// Future ideas
22
// - code explorer / code insight
22
// - code explorer / code insight
23
// - verschiedene php versionen?
23
// - verschiedene php versionen?
24
// - webbrowser1 nur laden, wenn man den tab anwählt?
24
// - webbrowser1 nur laden, wenn man den tab anwählt?
25
// - doppelklick auf tab soll diesen schließen
25
// - doppelklick auf tab soll diesen schließen
26
// - Onlinehelp (www) aufrufen
26
// - Onlinehelp (www) aufrufen
27
// - Let all colors be adjustable
27
// - Let all colors be adjustable
28
// - code in bildschirmmitte (horizontal)?
28
// - code in bildschirmmitte (horizontal)?
29
 
29
 
30
interface
30
interface
31
 
31
 
32
uses
32
uses
33
  // TODO: "{$IFDEF USE_SHDOCVW_TLB}_TLB{$ENDIF}" does not work with Delphi 10.2
33
  // TODO: "{$IFDEF USE_SHDOCVW_TLB}_TLB{$ENDIF}" does not work with Delphi 10.2
34
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
34
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
35
  Dialogs, StdCtrls, OleCtrls, ComCtrls, ExtCtrls, ToolWin, IniFiles,
35
  Dialogs, StdCtrls, OleCtrls, ComCtrls, ExtCtrls, ToolWin, IniFiles,
36
  SynEditHighlighter, SynHighlighterPHP, SynEdit, ShDocVw_TLB, FindReplace,
36
  SynEditHighlighter, SynHighlighterPHP, SynEdit, ShDocVw_TLB, FindReplace,
37
  System.Actions, Vcl.ActnList, System.UITypes, SynEditMiscClasses,
37
  System.Actions, Vcl.ActnList, System.UITypes, SynEditMiscClasses,
38
  SynEditSearch, RunPHP;
38
  SynEditSearch, RunPHP;
39
 
39
 
40
{.$DEFINE OnlineHelp}
40
{.$DEFINE OnlineHelp}
41
 
41
 
42
type
42
type
43
  TForm1 = class(TForm)
43
  TForm1 = class(TForm)
44
    PageControl1: TPageControl;
44
    PageControl1: TPageControl;
45
    PlaintextTabSheet: TTabSheet;
45
    PlaintextTabSheet: TTabSheet;
46
    HtmlTabSheet: TTabSheet;
46
    HtmlTabSheet: TTabSheet;
47
    Memo2: TMemo;
47
    Memo2: TMemo;
48
    WebBrowser1: TWebBrowser;
48
    WebBrowser1: TWebBrowser;
49
    Splitter1: TSplitter;
49
    Splitter1: TSplitter;
50
    PageControl2: TPageControl;
50
    PageControl2: TPageControl;
51
    CodeTabsheet: TTabSheet;
51
    CodeTabsheet: TTabSheet;
52
    HelpTabsheet: TTabSheet;
52
    HelpTabsheet: TTabSheet;
53
    WebBrowser2: TWebBrowser;
53
    WebBrowser2: TWebBrowser;
54
    OpenDialog1: TOpenDialog;
54
    OpenDialog1: TOpenDialog;
55
    Panel1: TPanel;
55
    Panel1: TPanel;
56
    OpenDialog3: TOpenDialog;
56
    OpenDialog3: TOpenDialog;
57
    SynEdit1: TSynEdit;
57
    SynEdit1: TSynEdit;
58
    SynPHPSyn1: TSynPHPSyn;
58
    SynPHPSyn1: TSynPHPSyn;
59
    Panel2: TPanel;
59
    Panel2: TPanel;
60
    SynEditFocusTimer: TTimer;
60
    SynEditFocusTimer: TTimer;
61
    Button1: TButton;
61
    Button1: TButton;
62
    Button2: TButton;
62
    Button2: TButton;
63
    Button3: TButton;
63
    Button3: TButton;
64
    Button4: TButton;
64
    Button4: TButton;
65
    Button5: TButton;
65
    Button5: TButton;
66
    Button6: TButton;
66
    Button6: TButton;
67
    ActionList: TActionList;
67
    ActionList: TActionList;
68
    ActionFind: TAction;
68
    ActionFind: TAction;
69
    ActionReplace: TAction;
69
    ActionReplace: TAction;
70
    ActionFindNext: TAction;
70
    ActionFindNext: TAction;
71
    ActionGoto: TAction;
71
    ActionGoto: TAction;
72
    ActionSave: TAction;
72
    ActionSave: TAction;
73
    ActionHelp: TAction;
73
    ActionHelp: TAction;
74
    ActionRun: TAction;
74
    ActionRun: TAction;
75
    ActionESC: TAction;
75
    ActionESC: TAction;
76
    Button7: TButton;
76
    Button7: TButton;
77
    ActionOpen: TAction;
77
    ActionOpen: TAction;
78
    Button8: TButton;
78
    Button8: TButton;
79
    Button9: TButton;
79
    Button9: TButton;
80
    ActionFindPrev: TAction;
80
    ActionFindPrev: TAction;
81
    Timer1: TTimer;
81
    Timer1: TTimer;
82
    ActionSpaceToTab: TAction;
82
    ActionSpaceToTab: TAction;
83
    Button11: TButton;
83
    Button11: TButton;
84
    SynEditSearch1: TSynEditSearch;
84
    SynEditSearch1: TSynEditSearch;
85
    TreeView1: TTreeView;
85
    TreeView1: TTreeView;
86
    Splitter2: TSplitter;
86
    Splitter2: TSplitter;
87
    procedure Run(Sender: TObject);
87
    procedure Run(Sender: TObject);
88
    procedure FormShow(Sender: TObject);
88
    procedure FormShow(Sender: TObject);
89
    procedure FormCreate(Sender: TObject);
89
    procedure FormCreate(Sender: TObject);
90
    procedure FormDestroy(Sender: TObject);
90
    procedure FormDestroy(Sender: TObject);
91
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
91
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
92
    procedure PageControl2Changing(Sender: TObject; var AllowChange: Boolean);
92
    procedure PageControl2Changing(Sender: TObject; var AllowChange: Boolean);
93
    procedure Memo2DblClick(Sender: TObject);
93
    procedure Memo2DblClick(Sender: TObject);
94
    procedure WebBrowser1BeforeNavigate2(ASender: TObject;
94
    procedure WebBrowser1BeforeNavigate2(ASender: TObject;
95
      const pDisp: IDispatch; const URL, Flags, TargetFrameName, PostData,
95
      const pDisp: IDispatch; const URL, Flags, TargetFrameName, PostData,
96
      Headers: OleVariant; var Cancel: WordBool);
96
      Headers: OleVariant; var Cancel: WordBool);
97
    procedure SynEditFocusTimerTimer(Sender: TObject);
97
    procedure SynEditFocusTimerTimer(Sender: TObject);
98
    procedure ActionFindExecute(Sender: TObject);
98
    procedure ActionFindExecute(Sender: TObject);
99
    procedure ActionReplaceExecute(Sender: TObject);
99
    procedure ActionReplaceExecute(Sender: TObject);
100
    procedure ActionFindNextExecute(Sender: TObject);
100
    procedure ActionFindNextExecute(Sender: TObject);
101
    procedure ActionGotoExecute(Sender: TObject);
101
    procedure ActionGotoExecute(Sender: TObject);
102
    procedure ActionSaveExecute(Sender: TObject);
102
    procedure ActionSaveExecute(Sender: TObject);
103
    procedure ActionHelpExecute(Sender: TObject);
103
    procedure ActionHelpExecute(Sender: TObject);
104
    procedure ActionRunExecute(Sender: TObject);
104
    procedure ActionRunExecute(Sender: TObject);
105
    procedure ActionESCExecute(Sender: TObject);
105
    procedure ActionESCExecute(Sender: TObject);
106
    procedure SynEdit1MouseWheelDown(Sender: TObject; Shift: TShiftState;
106
    procedure SynEdit1MouseWheelDown(Sender: TObject; Shift: TShiftState;
107
      MousePos: TPoint; var Handled: Boolean);
107
      MousePos: TPoint; var Handled: Boolean);
108
    procedure SynEdit1MouseWheelUp(Sender: TObject; Shift: TShiftState;
108
    procedure SynEdit1MouseWheelUp(Sender: TObject; Shift: TShiftState;
109
      MousePos: TPoint; var Handled: Boolean);
109
      MousePos: TPoint; var Handled: Boolean);
110
    procedure ActionOpenExecute(Sender: TObject);
110
    procedure ActionOpenExecute(Sender: TObject);
111
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
111
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
112
    procedure Memo2KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
112
    procedure Memo2KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
113
    procedure ActionFindPrevExecute(Sender: TObject);
113
    procedure ActionFindPrevExecute(Sender: TObject);
114
    procedure SynEdit1MouseCursor(Sender: TObject;
114
    procedure SynEdit1MouseCursor(Sender: TObject;
115
      const aLineCharPos: TBufferCoord; var aCursor: TCursor);
115
      const aLineCharPos: TBufferCoord; var aCursor: TCursor);
116
    procedure Timer1Timer(Sender: TObject);
116
    procedure Timer1Timer(Sender: TObject);
117
    procedure ActionSpaceToTabExecute(Sender: TObject);
117
    procedure ActionSpaceToTabExecute(Sender: TObject);
118
    procedure TreeView1DblClick(Sender: TObject);
118
    procedure TreeView1DblClick(Sender: TObject);
-
 
119
    procedure SynEdit1GutterClick(Sender: TObject; Button: TMouseButton; X, Y,
-
 
120
      Line: Integer; Mark: TSynEditMark);
119
  private
121
  private
120
    CurSearchTerm: string;
122
    CurSearchTerm: string;
121
    HlpPrevPageIndex: integer;
123
    HlpPrevPageIndex: integer;
122
    SrcRep: TSynEditFindReplace;
124
    SrcRep: TSynEditFindReplace;
123
    {$IFDEF OnlineHelp}
125
    {$IFDEF OnlineHelp}
124
    gOnlineHelpWord: string;
126
    gOnlineHelpWord: string;
125
    {$ENDIF}
127
    {$ENDIF}
126
    procedure Help;
128
    procedure Help;
127
    function MarkUpLineReference(cont: string): string;
129
    function MarkUpLineReference(cont: string): string;
128
    function InputRequestCallback: string;
130
    function InputRequestCallback: string;
129
    procedure OutputNotifyCallback(const data: string);
131
    procedure OutputNotifyCallback(const data: string);
130
  protected
132
  protected
131
    ChmIndex: TMemIniFile;
133
    ChmIndex: TMemIniFile;
132
    FScrapFile: string;
134
    FScrapFile: string;
133
    codeExplorer: TRunCodeExplorer;
135
    codeExplorer: TRunCodeExplorer;
134
    procedure GotoLineNo(LineNo: integer);
136
    procedure GotoLineNo(LineNo: integer);
135
    function GetScrapFile: string;
137
    function GetScrapFile: string;
136
    procedure StartCodeExplorer;
138
    procedure StartCodeExplorer;
137
  end;
139
  end;
138
 
140
 
139
var
141
var
140
  Form1: TForm1;
142
  Form1: TForm1;
141
 
143
 
142
implementation
144
implementation
143
 
145
 
144
{$R *.dfm}
146
{$R *.dfm}
145
 
147
 
-
 
148
{$R Cursors.res}
-
 
149
 
146
uses
150
uses
147
  Functions, StrUtils, WebBrowserUtils, FastPHPUtils, Math, ShellAPI, RichEdit,
151
  Functions, StrUtils, WebBrowserUtils, FastPHPUtils, Math, ShellAPI, RichEdit,
148
  FastPHPTreeView;
152
  FastPHPTreeView;
149
 
153
 
-
 
154
const
-
 
155
  crMouseGutter = 1;
-
 
156
 
150
// TODO: FindPrev ?
157
// TODO: FindPrev ?
151
procedure TForm1.ActionFindNextExecute(Sender: TObject);
158
procedure TForm1.ActionFindNextExecute(Sender: TObject);
152
begin
159
begin
153
  SrcRep.FindNext;
160
  SrcRep.FindNext;
154
end;
161
end;
155
 
162
 
156
procedure TForm1.ActionFindPrevExecute(Sender: TObject);
163
procedure TForm1.ActionFindPrevExecute(Sender: TObject);
157
begin
164
begin
158
  SrcRep.FindPrev;
165
  SrcRep.FindPrev;
159
end;
166
end;
160
 
167
 
161
procedure TForm1.ActionGotoExecute(Sender: TObject);
168
procedure TForm1.ActionGotoExecute(Sender: TObject);
162
var
169
var
163
  val: string;
170
  val: string;
164
  lineno: integer;
171
  lineno: integer;
165
begin
172
begin
166
  // TODO: VK_LMENU does not work! only works with AltGr but not Alt
173
  // TODO: VK_LMENU does not work! only works with AltGr but not Alt
167
  // http://stackoverflow.com/questions/16828250/delphi-xe2-how-to-prevent-the-alt-key-stealing-focus ?
174
  // http://stackoverflow.com/questions/16828250/delphi-xe2-how-to-prevent-the-alt-key-stealing-focus ?
168
 
175
 
169
  InputQuery('Go to', 'Line number:', val);
176
  InputQuery('Go to', 'Line number:', val);
170
  if not TryStrToInt(val, lineno) then
177
  if not TryStrToInt(val, lineno) then
171
  begin
178
  begin
172
    if SynEdit1.CanFocus then SynEdit1.SetFocus;
179
    if SynEdit1.CanFocus then SynEdit1.SetFocus;
173
    exit;
180
    exit;
174
  end;
181
  end;
175
  GotoLineNo(lineno);
182
  GotoLineNo(lineno);
176
end;
183
end;
177
 
184
 
178
procedure TForm1.ActionHelpExecute(Sender: TObject);
185
procedure TForm1.ActionHelpExecute(Sender: TObject);
179
begin
186
begin
180
  Help;
187
  Help;
181
  if PageControl2.ActivePage = HelpTabsheet then
188
  if PageControl2.ActivePage = HelpTabsheet then
182
    WebBrowser2.SetFocus
189
    WebBrowser2.SetFocus
183
  else if PageControl2.ActivePage = CodeTabsheet then
190
  else if PageControl2.ActivePage = CodeTabsheet then
184
    SynEdit1.SetFocus;
191
    SynEdit1.SetFocus;
185
end;
192
end;
186
 
193
 
187
procedure TForm1.ActionOpenExecute(Sender: TObject);
194
procedure TForm1.ActionOpenExecute(Sender: TObject);
188
begin
195
begin
189
  If OpenDialog3.Execute then
196
  If OpenDialog3.Execute then
190
  begin
197
  begin
191
    ShellExecute(0, 'open', PChar(ParamStr(0)), PChar(OpenDialog3.FileName), '', SW_NORMAL);
198
    ShellExecute(0, 'open', PChar(ParamStr(0)), PChar(OpenDialog3.FileName), '', SW_NORMAL);
192
  end;
199
  end;
193
end;
200
end;
194
 
201
 
195
procedure TForm1.ActionReplaceExecute(Sender: TObject);
202
procedure TForm1.ActionReplaceExecute(Sender: TObject);
196
begin
203
begin
197
  SrcRep.ReplaceExecute;
204
  SrcRep.ReplaceExecute;
198
end;
205
end;
199
 
206
 
200
procedure TForm1.ActionRunExecute(Sender: TObject);
207
procedure TForm1.ActionRunExecute(Sender: TObject);
201
begin
208
begin
202
  Run(Sender);
209
  Run(Sender);
203
  SynEdit1.SetFocus;
210
  SynEdit1.SetFocus;
204
end;
211
end;
205
 
212
 
206
procedure TForm1.ActionSaveExecute(Sender: TObject);
213
procedure TForm1.ActionSaveExecute(Sender: TObject);
207
begin
214
begin
208
  SynEdit1.Lines.SaveToFile(GetScrapFile);
215
  SynEdit1.Lines.SaveToFile(GetScrapFile);
209
  SynEdit1.Modified := false;
216
  SynEdit1.Modified := false;
210
end;
217
end;
211
 
218
 
212
procedure TForm1.ActionSpaceToTabExecute(Sender: TObject);
219
procedure TForm1.ActionSpaceToTabExecute(Sender: TObject);
213
 
220
 
214
    function SpacesAtBeginning(line: string): integer;
221
    function SpacesAtBeginning(line: string): integer;
215
    begin
222
    begin
216
      if line.Trim = '' then exit(0);
223
      if line.Trim = '' then exit(0);
217
      result := 0;
224
      result := 0;
218
      while line[result+1] = ' ' do
225
      while line[result+1] = ' ' do
219
      begin
226
      begin
220
        inc(result);
227
        inc(result);
221
      end;
228
      end;
222
    end;
229
    end;
223
 
230
 
224
    function GuessIndent(lines: TStrings): integer;
231
    function GuessIndent(lines: TStrings): integer;
225
      function _Check(indent: integer): boolean;
232
      function _Check(indent: integer): boolean;
226
      var
233
      var
227
        i: integer;
234
        i: integer;
228
      begin
235
      begin
229
        result := true;
236
        result := true;
230
        for i := 0 to lines.Count-1 do
237
        for i := 0 to lines.Count-1 do
231
          if SpacesAtBeginning(lines.Strings[i]) mod indent <> 0 then
238
          if SpacesAtBeginning(lines.Strings[i]) mod indent <> 0 then
232
          begin
239
          begin
233
            // ShowMessageFmt('Zeile "%s" nicht durch %d teilbar!', [lines.strings[i], indent]);
240
            // ShowMessageFmt('Zeile "%s" nicht durch %d teilbar!', [lines.strings[i], indent]);
234
            exit(false);
241
            exit(false);
235
          end;
242
          end;
236
      end;
243
      end;
237
    var
244
    var
238
      i: integer;
245
      i: integer;
239
    begin
246
    begin
240
      for i := 8 downto 2 do
247
      for i := 8 downto 2 do
241
      begin
248
      begin
242
        if _Check(i) then exit(i);
249
        if _Check(i) then exit(i);
243
      end;
250
      end;
244
      result := -1;
251
      result := -1;
245
    end;
252
    end;
246
 
253
 
247
    procedure SpaceToTab(lines: TStrings; indent: integer);
254
    procedure SpaceToTab(lines: TStrings; indent: integer);
248
    var
255
    var
249
      i, spaces: integer;
256
      i, spaces: integer;
250
    begin
257
    begin
251
      for i := 0 to lines.Count-1 do
258
      for i := 0 to lines.Count-1 do
252
      begin
259
      begin
253
        spaces := SpacesAtBeginning(lines.Strings[i]);
260
        spaces := SpacesAtBeginning(lines.Strings[i]);
254
        lines.Strings[i] := StringOfChar(#9, spaces div indent) + StringOfChar(' ', spaces mod indent) + Copy(lines.Strings[i], spaces+1, Length(lines.Strings[i])-spaces);
261
        lines.Strings[i] := StringOfChar(#9, spaces div indent) + StringOfChar(' ', spaces mod indent) + Copy(lines.Strings[i], spaces+1, Length(lines.Strings[i])-spaces);
255
      end;
262
      end;
256
    end;
263
    end;
257
 
264
 
258
    function SpacesAvailable(lines: TStrings): boolean;
265
    function SpacesAvailable(lines: TStrings): boolean;
259
    var
266
    var
260
      i, spaces: integer;
267
      i, spaces: integer;
261
    begin
268
    begin
262
      for i := 0 to lines.Count-1 do
269
      for i := 0 to lines.Count-1 do
263
      begin
270
      begin
264
        spaces := SpacesAtBeginning(lines.Strings[i]);
271
        spaces := SpacesAtBeginning(lines.Strings[i]);
265
        if spaces > 0 then exit(true);
272
        if spaces > 0 then exit(true);
266
      end;
273
      end;
267
      exit(false);
274
      exit(false);
268
    end;
275
    end;
269
 
276
 
270
var
277
var
271
  val: string;
278
  val: string;
272
  ind: integer;
279
  ind: integer;
273
resourcestring
280
resourcestring
274
  SNoLinesAvailable = 'No lines with spaces at the beginning available';
281
  SNoLinesAvailable = 'No lines with spaces at the beginning available';
275
begin
282
begin
276
  // TODO: if something is selected, only process the selected part
283
  // TODO: if something is selected, only process the selected part
277
 
284
 
278
  if not SpacesAvailable(SynEdit1.Lines) then
285
  if not SpacesAvailable(SynEdit1.Lines) then
279
  begin
286
  begin
280
    ShowMessage(SNoLinesAvailable);
287
    ShowMessage(SNoLinesAvailable);
281
    exit;
288
    exit;
282
  end;
289
  end;
283
 
290
 
284
  ind := GuessIndent(SynEdit1.Lines);
291
  ind := GuessIndent(SynEdit1.Lines);
285
  if ind <> -1 then val := IntToStr(ind);
292
  if ind <> -1 then val := IntToStr(ind);
286
 
293
 
287
  InputQuery('Spaces to tabs', 'Indent:', val); // TODO: handle CANCEL correctly...
294
  InputQuery('Spaces to tabs', 'Indent:', val); // TODO: handle CANCEL correctly...
288
  if TryStrToInt(val.Trim, ind) then
295
  if TryStrToInt(val.Trim, ind) then
289
  begin
296
  begin
290
    if ind = 0 then exit;
297
    if ind = 0 then exit;
291
    SpaceToTab(SynEdit1.Lines, ind);
298
    SpaceToTab(SynEdit1.Lines, ind);
292
  end;
299
  end;
293
 
300
 
294
  if SynEdit1.CanFocus then SynEdit1.SetFocus;
301
  if SynEdit1.CanFocus then SynEdit1.SetFocus;
295
end;
302
end;
296
 
303
 
297
procedure TForm1.ActionESCExecute(Sender: TObject);
304
procedure TForm1.ActionESCExecute(Sender: TObject);
298
begin
305
begin
299
  if (HlpPrevPageIndex <> -1) and (PageControl2.ActivePage = HelpTabSheet) and
306
  if (HlpPrevPageIndex <> -1) and (PageControl2.ActivePage = HelpTabSheet) and
300
     (HelpTabsheet.TabVisible) then
307
     (HelpTabsheet.TabVisible) then
301
  begin
308
  begin
302
    PageControl2.ActivePageIndex := HlpPrevPageIndex;
309
    PageControl2.ActivePageIndex := HlpPrevPageIndex;
303
    HelpTabsheet.TabVisible := false;
310
    HelpTabsheet.TabVisible := false;
304
  end;
311
  end;
305
 
312
 
306
  // Dirty hack...
313
  // Dirty hack...
307
  SrcRep.CloseDialogs;
314
  SrcRep.CloseDialogs;
308
end;
315
end;
309
 
316
 
310
procedure TForm1.ActionFindExecute(Sender: TObject);
317
procedure TForm1.ActionFindExecute(Sender: TObject);
311
begin
318
begin
312
  SrcRep.FindExecute;
319
  SrcRep.FindExecute;
313
end;
320
end;
314
 
321
 
315
var
322
var
316
  firstTimeBrowserLoad: boolean = true;
323
  firstTimeBrowserLoad: boolean = true;
317
procedure TForm1.Run(Sender: TObject);
324
procedure TForm1.Run(Sender: TObject);
318
var
325
var
319
  bakTS: TTabSheet;
326
  bakTS: TTabSheet;
320
begin
327
begin
321
  memo2.Lines.Text := '';
328
  memo2.Lines.Text := '';
322
 
329
 
323
  if firstTimeBrowserLoad then
330
  if firstTimeBrowserLoad then
324
  begin
331
  begin
325
    bakTS := PageControl1.ActivePage;
332
    bakTS := PageControl1.ActivePage;
326
    try
333
    try
327
      PageControl1.ActivePage := HtmlTabSheet; // Required for the first time, otherwise, WebBrowser1.Clear will hang
334
      PageControl1.ActivePage := HtmlTabSheet; // Required for the first time, otherwise, WebBrowser1.Clear will hang
328
      Webbrowser1.Clear;
335
      Webbrowser1.Clear;
329
    finally
336
    finally
330
      PageControl1.ActivePage := bakTS;
337
      PageControl1.ActivePage := bakTS;
331
    end;
338
    end;
332
    firstTimeBrowserLoad := false;
339
    firstTimeBrowserLoad := false;
333
  end
340
  end
334
  else
341
  else
335
    Webbrowser1.Clear;
342
    Webbrowser1.Clear;
336
 
343
 
337
  Screen.Cursor := crHourGlass;
344
  Screen.Cursor := crHourGlass;
338
  Application.ProcessMessages;
345
  Application.ProcessMessages;
339
 
346
 
340
  try
347
  try
341
    SynEdit1.Lines.SaveToFile(GetScrapFile);
348
    SynEdit1.Lines.SaveToFile(GetScrapFile);
342
 
349
 
343
    memo2.Lines.Text := RunPHPScript(GetScrapFile);
350
    memo2.Lines.Text := RunPHPScript(GetScrapFile);
344
 
351
 
345
    Webbrowser1.LoadHTML(MarkUpLineReference(memo2.Lines.Text), GetScrapFile);
352
    Webbrowser1.LoadHTML(MarkUpLineReference(memo2.Lines.Text), GetScrapFile);
346
 
353
 
347
    if IsTextHTML(memo2.lines.text) then
354
    if IsTextHTML(memo2.lines.text) then
348
      PageControl1.ActivePage := HtmlTabSheet
355
      PageControl1.ActivePage := HtmlTabSheet
349
    else
356
    else
350
      PageControl1.ActivePage := PlaintextTabSheet;
357
      PageControl1.ActivePage := PlaintextTabSheet;
351
  finally
358
  finally
352
    Screen.Cursor := crDefault;
359
    Screen.Cursor := crDefault;
353
  end;
360
  end;
354
end;
361
end;
355
 
362
 
-
 
363
procedure TForm1.SynEdit1GutterClick(Sender: TObject; Button: TMouseButton; X,
-
 
364
  Y, Line: Integer; Mark: TSynEditMark);
-
 
365
begin
-
 
366
  (*
-
 
367
  TSynEdit(Sender).CaretX := 1;
-
 
368
  TSynEdit(Sender).CaretY := Line;
-
 
369
  TSynEdit(Sender).SelLength := Length(TSynEdit(Sender).LineText);
-
 
370
  *)
-
 
371
end;
-
 
372
 
356
procedure TForm1.SynEdit1MouseCursor(Sender: TObject; const aLineCharPos: TBufferCoord; var aCursor: TCursor);
373
procedure TForm1.SynEdit1MouseCursor(Sender: TObject; const aLineCharPos: TBufferCoord; var aCursor: TCursor);
357
{$IFDEF OnlineHelp}
374
{$IFDEF OnlineHelp}
358
var
375
var
359
  Line: Integer;
376
  Line: Integer;
360
  Column: Integer;
377
  Column: Integer;
361
  word: string;
378
  word: string;
362
begin
379
begin
363
  Line  := aLineCharPos.Line-1;
380
  Line  := aLineCharPos.Line-1;
364
  Column := aLineCharPos.Char-1;
381
  Column := aLineCharPos.Char-1;
365
  word := GetWordUnderPos(TSynEdit(Sender), Line, Column);
382
  word := GetWordUnderPos(TSynEdit(Sender), Line, Column);
366
  if word <> gOnlineHelpWord then
383
  if word <> gOnlineHelpWord then
367
  begin
384
  begin
368
    gOnlineHelpWord := word;
385
    gOnlineHelpWord := word;
369
    Timer1.Enabled := false;
386
    Timer1.Enabled := false;
370
    Timer1.Enabled := true;
387
    Timer1.Enabled := true;
371
  end;
388
  end;
372
{$ELSE}
389
{$ELSE}
373
begin
390
begin
374
{$ENDIF}
391
{$ENDIF}
375
end;
392
end;
376
 
393
 
377
procedure TForm1.SynEdit1MouseWheelDown(Sender: TObject; Shift: TShiftState;
394
procedure TForm1.SynEdit1MouseWheelDown(Sender: TObject; Shift: TShiftState;
378
  MousePos: TPoint; var Handled: Boolean);
395
  MousePos: TPoint; var Handled: Boolean);
379
begin
396
begin
380
  if ssCtrl in Shift then
397
  if ssCtrl in Shift then
381
  begin
398
  begin
382
    SynEdit1.Font.Size := Max(SynEdit1.Font.Size - 1, 5);
399
    SynEdit1.Font.Size := Max(SynEdit1.Font.Size - 1, 5);
383
    Handled := true;
400
    Handled := true;
384
  end
401
  end
385
  else Handled := false;
402
  else Handled := false;
386
end;
403
end;
387
 
404
 
388
procedure TForm1.SynEdit1MouseWheelUp(Sender: TObject; Shift: TShiftState;
405
procedure TForm1.SynEdit1MouseWheelUp(Sender: TObject; Shift: TShiftState;
389
  MousePos: TPoint; var Handled: Boolean);
406
  MousePos: TPoint; var Handled: Boolean);
390
begin
407
begin
391
  if ssCtrl in Shift then
408
  if ssCtrl in Shift then
392
  begin
409
  begin
393
    SynEdit1.Font.Size := SynEdit1.Font.Size + 1;
410
    SynEdit1.Font.Size := SynEdit1.Font.Size + 1;
394
    Handled := true;
411
    Handled := true;
395
  end
412
  end
396
  else Handled := false;
413
  else Handled := false;
397
end;
414
end;
398
 
415
 
399
procedure TForm1.SynEditFocusTimerTimer(Sender: TObject);
416
procedure TForm1.SynEditFocusTimerTimer(Sender: TObject);
400
begin
417
begin
401
  SynEditFocusTimer.Enabled := false;
418
  SynEditFocusTimer.Enabled := false;
402
  Button1.SetFocus; // Workaround for weird bug... This (and the timer) is necessary to get the focus to SynEdit1
419
  Button1.SetFocus; // Workaround for weird bug... This (and the timer) is necessary to get the focus to SynEdit1
403
  SynEdit1.SetFocus;
420
  SynEdit1.SetFocus;
404
end;
421
end;
405
 
422
 
406
procedure TForm1.Timer1Timer(Sender: TObject);
423
procedure TForm1.Timer1Timer(Sender: TObject);
407
begin
424
begin
408
  {$IFDEF OnlineHelp}
425
  {$IFDEF OnlineHelp}
409
  Timer1.Enabled := false;
426
  Timer1.Enabled := false;
410
 
427
 
411
  // TODO: Insert a small online help hint
428
  // TODO: Insert a small online help hint
412
  //Caption := gOnlineHelpWord;
429
  //Caption := gOnlineHelpWord;
413
  {$ENDIF}
430
  {$ENDIF}
414
end;
431
end;
415
 
432
 
416
procedure TForm1.TreeView1DblClick(Sender: TObject);
433
procedure TForm1.TreeView1DblClick(Sender: TObject);
417
var
434
var
418
  tn: TTreeNode;
435
  tn: TTreeNode;
419
begin
436
begin
420
  tn := TTreeView(Sender).Selected;
437
  tn := TTreeView(Sender).Selected;
421
  if tn = nil then exit;
438
  if tn = nil then exit;
422
  GotoLineNo(Integer(tn.Data));
439
  GotoLineNo(Integer(tn.Data));
423
end;
440
end;
424
 
441
 
425
procedure TForm1.WebBrowser1BeforeNavigate2(ASender: TObject;
442
procedure TForm1.WebBrowser1BeforeNavigate2(ASender: TObject;
426
  const pDisp: IDispatch; const URL, Flags, TargetFrameName, PostData,
443
  const pDisp: IDispatch; const URL, Flags, TargetFrameName, PostData,
427
  Headers: OleVariant; var Cancel: WordBool);
444
  Headers: OleVariant; var Cancel: WordBool);
428
var
445
var
429
  s, myURL: string;
446
  s, myURL: string;
430
  lineno: integer;
447
  lineno: integer;
431
  p: integer;
448
  p: integer;
432
begin
449
begin
433
  {$REGION 'Line number references (PHP errors and warnings)'}
450
  {$REGION 'Line number references (PHP errors and warnings)'}
434
  if Copy(URL, 1, length(FASTPHP_GOTO_URI_PREFIX)) = FASTPHP_GOTO_URI_PREFIX then
451
  if Copy(URL, 1, length(FASTPHP_GOTO_URI_PREFIX)) = FASTPHP_GOTO_URI_PREFIX then
435
  begin
452
  begin
436
    try
453
    try
437
      s := copy(URL, length(FASTPHP_GOTO_URI_PREFIX)+1, 99);
454
      s := copy(URL, length(FASTPHP_GOTO_URI_PREFIX)+1, 99);
438
      if not TryStrToInt(s, lineno) then exit;
455
      if not TryStrToInt(s, lineno) then exit;
439
      GotoLineNo(lineno);
456
      GotoLineNo(lineno);
440
      SynEditFocusTimer.Enabled := true;
457
      SynEditFocusTimer.Enabled := true;
441
    finally
458
    finally
442
      Cancel := true;
459
      Cancel := true;
443
    end;
460
    end;
444
    Exit;
461
    Exit;
445
  end;
462
  end;
446
  {$ENDREGION}
463
  {$ENDREGION}
447
 
464
 
448
  {$REGION 'Intelligent browser (executes PHP scripts)'}
465
  {$REGION 'Intelligent browser (executes PHP scripts)'}
449
  if URL <> 'about:blank' then
466
  if URL <> 'about:blank' then
450
  begin
467
  begin
451
    myUrl := URL;
468
    myUrl := URL;
452
 
469
 
453
    p := Pos('?', myUrl);
470
    p := Pos('?', myUrl);
454
    if p >= 1 then myURL := copy(myURL, 1, p-1);
471
    if p >= 1 then myURL := copy(myURL, 1, p-1);
455
 
472
 
456
    // TODO: myURL urldecode
473
    // TODO: myURL urldecode
457
    // TODO: maybe we could even open that file in the editor!
474
    // TODO: maybe we could even open that file in the editor!
458
 
475
 
459
    if FileExists(myURL) and (EndsText('.php', myURL) or EndsText('.php3', myURL) or EndsText('.php4', myURL) or EndsText('.php5', myURL) or EndsText('.phps', myURL)) then
476
    if FileExists(myURL) and (EndsText('.php', myURL) or EndsText('.php3', myURL) or EndsText('.php4', myURL) or EndsText('.php5', myURL) or EndsText('.phps', myURL)) then
460
    begin
477
    begin
461
      WebBrowser1.LoadHTML(RunPHPScript(myURL), myUrl);
478
      WebBrowser1.LoadHTML(RunPHPScript(myURL), myUrl);
462
      Cancel := true;
479
      Cancel := true;
463
    end;
480
    end;
464
  end;
481
  end;
465
  {$ENDREGION}
482
  {$ENDREGION}
466
end;
483
end;
467
 
484
 
468
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
485
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
469
begin
486
begin
470
  FastPHPConfig.WriteInteger('User', 'FontSize', SynEdit1.Font.Size);
487
  FastPHPConfig.WriteInteger('User', 'FontSize', SynEdit1.Font.Size);
471
end;
488
end;
472
 
489
 
473
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
490
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
474
var
491
var
475
  r: integer;
492
  r: integer;
476
begin
493
begin
477
  if SynEdit1.Modified then
494
  if SynEdit1.Modified then
478
  begin
495
  begin
479
    if ParamStr(1) <> '' then
496
    if ParamStr(1) <> '' then
480
    begin
497
    begin
481
      r := MessageDlg('Do you want to save?', mtConfirmation, mbYesNoCancel, 0);
498
      r := MessageDlg('Do you want to save?', mtConfirmation, mbYesNoCancel, 0);
482
      if r = mrCancel then
499
      if r = mrCancel then
483
      begin
500
      begin
484
        CanClose := false;
501
        CanClose := false;
485
        Exit;
502
        Exit;
486
      end
503
      end
487
      else if r = mrYes then
504
      else if r = mrYes then
488
      begin
505
      begin
489
        SynEdit1.Lines.SaveToFile(GetScrapFile);
506
        SynEdit1.Lines.SaveToFile(GetScrapFile);
490
        CanClose := true;
507
        CanClose := true;
491
      end;
508
      end;
492
    end
509
    end
493
    else
510
    else
494
    begin
511
    begin
495
      SynEdit1.Lines.SaveToFile(GetScrapFile);
512
      SynEdit1.Lines.SaveToFile(GetScrapFile);
496
      CanClose := true;
513
      CanClose := true;
497
    end;
514
    end;
498
  end;
515
  end;
499
end;
516
end;
500
 
517
 
501
procedure TForm1.FormCreate(Sender: TObject);
518
procedure TForm1.FormCreate(Sender: TObject);
502
begin
519
begin
503
  HlpPrevPageIndex := -1;
520
  HlpPrevPageIndex := -1;
504
  CurSearchTerm := '';
521
  CurSearchTerm := '';
505
  Caption := Caption + ' - ' + GetScrapFile;
522
  Caption := Caption + ' - ' + GetScrapFile;
506
  SrcRep := TSynEditFindReplace.Create(self);
523
  SrcRep := TSynEditFindReplace.Create(self);
507
  SrcRep.Editor := SynEdit1;
524
  SrcRep.Editor := SynEdit1;
508
  SynEdit1.Gutter.Gradient := HighColorWindows;
525
  SynEdit1.Gutter.Gradient := HighColorWindows;
-
 
526
 
-
 
527
  Screen.Cursors[crMouseGutter] := LoadCursor(hInstance, 'MOUSEGUTTER');
-
 
528
  SynEdit1.Gutter.Cursor := crMouseGutter;
509
end;
529
end;
510
 
530
 
511
procedure TForm1.FormDestroy(Sender: TObject);
531
procedure TForm1.FormDestroy(Sender: TObject);
512
begin
532
begin
513
  if Assigned(ChmIndex) then
533
  if Assigned(ChmIndex) then
514
  begin
534
  begin
515
    FreeAndNil(ChmIndex);
535
    FreeAndNil(ChmIndex);
516
  end;
536
  end;
517
  FreeAndNil(SrcRep);
537
  FreeAndNil(SrcRep);
518
 
538
 
519
  if Assigned(codeExplorer) then
539
  if Assigned(codeExplorer) then
520
  begin
540
  begin
521
    codeExplorer.Terminate;
541
    codeExplorer.Terminate;
522
    codeExplorer.WaitFor;
542
    codeExplorer.WaitFor;
523
    FreeAndNil(codeExplorer);
543
    FreeAndNil(codeExplorer);
524
  end;
544
  end;
525
end;
545
end;
526
 
546
 
527
procedure TForm1.FormShow(Sender: TObject);
547
procedure TForm1.FormShow(Sender: TObject);
528
var
548
var
529
  ScrapFile: string;
549
  ScrapFile: string;
530
begin
550
begin
531
  ScrapFile := GetScrapFile;
551
  ScrapFile := GetScrapFile;
532
  if ScrapFile = '' then
552
  if ScrapFile = '' then
533
  begin
553
  begin
534
    Application.Terminate; // Close;
554
    Application.Terminate; // Close;
535
    exit;
555
    exit;
536
  end;
556
  end;
537
  if FileExists(ScrapFile) then
557
  if FileExists(ScrapFile) then
538
    SynEdit1.Lines.LoadFromFile(ScrapFile)
558
    SynEdit1.Lines.LoadFromFile(ScrapFile)
539
  else
559
  else
540
    SynEdit1.Lines.Clear;
560
    SynEdit1.Lines.Clear;
541
 
561
 
542
  PageControl1.ActivePage := PlaintextTabSheet;
562
  PageControl1.ActivePage := PlaintextTabSheet;
543
 
563
 
544
  PageControl2.ActivePage := CodeTabsheet;
564
  PageControl2.ActivePage := CodeTabsheet;
545
  HelpTabsheet.TabVisible := false;
565
  HelpTabsheet.TabVisible := false;
546
 
566
 
547
  SynEdit1.Font.Size := FastPHPConfig.ReadInteger('User', 'FontSize', SynEdit1.Font.Size);
567
  SynEdit1.Font.Size := FastPHPConfig.ReadInteger('User', 'FontSize', SynEdit1.Font.Size);
548
  SynEdit1.SetFocus;
568
  SynEdit1.SetFocus;
549
 
569
 
550
  DoubleBuffered := true;
570
  DoubleBuffered := true;
551
  StartCodeExplorer;
571
  StartCodeExplorer;
552
end;
572
end;
553
 
573
 
554
procedure TForm1.StartCodeExplorer;
574
procedure TForm1.StartCodeExplorer;
555
begin
575
begin
556
  codeExplorer := TRunCodeExplorer.Create(true);
576
  codeExplorer := TRunCodeExplorer.Create(true);
557
  codeExplorer.InputRequestCallback := InputRequestCallback;
577
  codeExplorer.InputRequestCallback := InputRequestCallback;
558
  codeExplorer.OutputNotifyCallback := OutputNotifyCallback;
578
  codeExplorer.OutputNotifyCallback := OutputNotifyCallback;
559
  codeExplorer.PhpExe := GetPHPExe;
579
  codeExplorer.PhpExe := GetPHPExe;
560
  codeExplorer.PhpFile := IncludeTrailingPathDelimiter(ExtractFileDir(Application.ExeName)) + 'codeexplorer.php'; // GetScrapFile;
580
  codeExplorer.PhpFile := IncludeTrailingPathDelimiter(ExtractFileDir(Application.ExeName)) + 'codeexplorer.php'; // GetScrapFile;
561
  codeExplorer.WorkDir := ExtractFileDir(Application.ExeName);
581
  codeExplorer.WorkDir := ExtractFileDir(Application.ExeName);
562
  codeExplorer.Start;
582
  codeExplorer.Start;
563
end;
583
end;
564
 
584
 
565
function TForm1.GetScrapFile: string;
585
function TForm1.GetScrapFile: string;
566
begin
586
begin
567
  if FScrapFile <> '' then exit(FScrapFile);
587
  if FScrapFile <> '' then exit(FScrapFile);
568
 
588
 
569
  if ParamStr(1) <> '' then
589
  if ParamStr(1) <> '' then
570
    result := ParamStr(1)
590
    result := ParamStr(1)
571
  else
591
  else
572
    result := FastPHPConfig.ReadString('Paths', 'ScrapFile', '');
592
    result := FastPHPConfig.ReadString('Paths', 'ScrapFile', '');
573
  if not FileExists(result) then
593
  if not FileExists(result) then
574
  begin
594
  begin
575
    repeat
595
    repeat
576
      if not OpenDialog3.Execute then
596
      if not OpenDialog3.Execute then
577
      begin
597
      begin
578
        Application.Terminate;
598
        Application.Terminate;
579
        exit('');
599
        exit('');
580
      end;
600
      end;
581
 
601
 
582
      if not DirectoryExists(ExtractFilePath(OpenDialog3.FileName)) then
602
      if not DirectoryExists(ExtractFilePath(OpenDialog3.FileName)) then
583
      begin
603
      begin
584
        ShowMessage('Path does not exist! Please try again.');
604
        ShowMessage('Path does not exist! Please try again.');
585
      end
605
      end
586
      else
606
      else
587
      begin
607
      begin
588
        result := OpenDialog3.FileName;
608
        result := OpenDialog3.FileName;
589
      end;
609
      end;
590
    until result <> '';
610
    until result <> '';
591
 
611
 
592
    SynEdit1.Lines.Clear;
612
    SynEdit1.Lines.Clear;
593
    SynEdit1.Lines.SaveToFile(result);
613
    SynEdit1.Lines.SaveToFile(result);
594
 
614
 
595
    FastPHPConfig.WriteString('Paths', 'ScrapFile', result);
615
    FastPHPConfig.WriteString('Paths', 'ScrapFile', result);
596
    FScrapFile := result;
616
    FScrapFile := result;
597
  end;
617
  end;
598
end;
618
end;
599
 
619
 
600
procedure TForm1.Help;
620
procedure TForm1.Help;
601
var
621
var
602
  IndexFile, chmFile, w, OriginalWord, url: string;
622
  IndexFile, chmFile, w, OriginalWord, url: string;
603
  internalHtmlFile: string;
623
  internalHtmlFile: string;
604
begin
624
begin
605
  if not Assigned(ChmIndex) then
625
  if not Assigned(ChmIndex) then
606
  begin
626
  begin
607
    IndexFile := FastPHPConfig.ReadString('Paths', 'HelpIndex', '');
627
    IndexFile := FastPHPConfig.ReadString('Paths', 'HelpIndex', '');
608
    IndexFile := ChangeFileExt(IndexFile, '.ini'); // Just to be sure. Maybe someone wrote manually the ".chm" file in there
628
    IndexFile := ChangeFileExt(IndexFile, '.ini'); // Just to be sure. Maybe someone wrote manually the ".chm" file in there
609
    if FileExists(IndexFile) then
629
    if FileExists(IndexFile) then
610
    begin
630
    begin
611
      ChmIndex := TMemIniFile.Create(IndexFile);
631
      ChmIndex := TMemIniFile.Create(IndexFile);
612
    end;
632
    end;
613
  end;
633
  end;
614
 
634
 
615
  if Assigned(ChmIndex) then
635
  if Assigned(ChmIndex) then
616
  begin
636
  begin
617
    IndexFile := FastPHPConfig.ReadString('Paths', 'HelpIndex', '');
637
    IndexFile := FastPHPConfig.ReadString('Paths', 'HelpIndex', '');
618
    // We don't check if IndexFile still exists. It is not important since we have ChmIndex pre-loaded in memory
638
    // We don't check if IndexFile still exists. It is not important since we have ChmIndex pre-loaded in memory
619
 
639
 
620
    chmFile := ChangeFileExt(IndexFile, '.chm');
640
    chmFile := ChangeFileExt(IndexFile, '.chm');
621
    if not FileExists(chmFile) then
641
    if not FileExists(chmFile) then
622
    begin
642
    begin
623
      FreeAndNil(ChmIndex);
643
      FreeAndNil(ChmIndex);
624
    end;
644
    end;
625
  end;
645
  end;
626
 
646
 
627
  if not Assigned(ChmIndex) then
647
  if not Assigned(ChmIndex) then
628
  begin
648
  begin
629
    if not OpenDialog1.Execute then exit;
649
    if not OpenDialog1.Execute then exit;
630
 
650
 
631
    chmFile := OpenDialog1.FileName;
651
    chmFile := OpenDialog1.FileName;
632
    if not FileExists(chmFile) then exit;
652
    if not FileExists(chmFile) then exit;
633
 
653
 
634
    IndexFile := ChangeFileExt(chmFile, '.ini');
654
    IndexFile := ChangeFileExt(chmFile, '.ini');
635
 
655
 
636
    if not FileExists(IndexFile) then
656
    if not FileExists(IndexFile) then
637
    begin
657
    begin
638
      Panel1.Align := alClient;
658
      Panel1.Align := alClient;
639
      Panel1.Visible := true;
659
      Panel1.Visible := true;
640
      Panel1.BringToFront;
660
      Panel1.BringToFront;
641
      Screen.Cursor := crHourGlass;
661
      Screen.Cursor := crHourGlass;
642
      Application.ProcessMessages;
662
      Application.ProcessMessages;
643
      try
663
      try
644
        if not ParseCHM(chmFile) then
664
        if not ParseCHM(chmFile) then
645
        begin
665
        begin
646
          ShowMessage('The CHM file is not a valid PHP documentation. Cannot use help.');
666
          ShowMessage('The CHM file is not a valid PHP documentation. Cannot use help.');
647
          exit;
667
          exit;
648
        end;
668
        end;
649
      finally
669
      finally
650
        Screen.Cursor := crDefault;
670
        Screen.Cursor := crDefault;
651
        Panel1.Visible := false;
671
        Panel1.Visible := false;
652
      end;
672
      end;
653
 
673
 
654
      if not FileExists(IndexFile) then
674
      if not FileExists(IndexFile) then
655
      begin
675
      begin
656
        ShowMessage('Unknown error. Cannot use help.');
676
        ShowMessage('Unknown error. Cannot use help.');
657
        exit;
677
        exit;
658
      end;
678
      end;
659
    end;
679
    end;
660
 
680
 
661
    FastPHPConfig.WriteString('Paths', 'HelpIndex', IndexFile);
681
    FastPHPConfig.WriteString('Paths', 'HelpIndex', IndexFile);
662
    FastPHPConfig.UpdateFile;
682
    FastPHPConfig.UpdateFile;
663
 
683
 
664
    ChmIndex := TMemIniFile.Create(IndexFile);
684
    ChmIndex := TMemIniFile.Create(IndexFile);
665
  end;
685
  end;
666
 
686
 
667
  w := GetWordUnderCaret(SynEdit1);
687
  w := GetWordUnderCaret(SynEdit1);
668
  if w = '' then exit;
688
  if w = '' then exit;
669
  if CharInSet(w[1], ['0'..'9']) then exit;
689
  if CharInSet(w[1], ['0'..'9']) then exit;
670
 
690
 
671
  Originalword := w;
691
  Originalword := w;
672
//  w := StringReplace(w, '_', '-', [rfReplaceAll]);
692
//  w := StringReplace(w, '_', '-', [rfReplaceAll]);
673
  w := LowerCase(w);
693
  w := LowerCase(w);
674
  CurSearchTerm := w;
694
  CurSearchTerm := w;
675
 
695
 
676
  internalHtmlFile := ChmIndex.ReadString('_HelpWords_', CurSearchTerm, '');
696
  internalHtmlFile := ChmIndex.ReadString('_HelpWords_', CurSearchTerm, '');
677
  if internalHtmlFile = '' then
697
  if internalHtmlFile = '' then
678
  begin
698
  begin
679
    HelpTabsheet.TabVisible := false;
699
    HelpTabsheet.TabVisible := false;
680
    HlpPrevPageIndex := -1;
700
    HlpPrevPageIndex := -1;
681
    ShowMessageFmt('No help for "%s" available', [Originalword]);
701
    ShowMessageFmt('No help for "%s" available', [Originalword]);
682
    Exit;
702
    Exit;
683
  end;
703
  end;
684
 
704
 
685
  url := 'mk:@MSITStore:'+ChmFile+'::'+internalHtmlFile;
705
  url := 'mk:@MSITStore:'+ChmFile+'::'+internalHtmlFile;
686
 
706
 
687
  HlpPrevPageIndex := PageControl2.ActivePageIndex; // Return by pressing ESC
707
  HlpPrevPageIndex := PageControl2.ActivePageIndex; // Return by pressing ESC
688
  HelpTabsheet.TabVisible := true;
708
  HelpTabsheet.TabVisible := true;
689
  PageControl2.ActivePage := HelpTabsheet;
709
  PageControl2.ActivePage := HelpTabsheet;
690
  WebBrowser2.Navigate(url);
710
  WebBrowser2.Navigate(url);
691
  WebBrowser2.Wait;
711
  WebBrowser2.Wait;
692
end;
712
end;
693
 
713
 
694
procedure TForm1.GotoLineNo(LineNo:integer);
714
procedure TForm1.GotoLineNo(LineNo:integer);
695
var
715
var
696
  line: string;
716
  line: string;
697
  i: integer;
717
  i: integer;
698
begin
718
begin
699
  SynEdit1.GotoLineAndCenter(LineNo);
719
  SynEdit1.GotoLineAndCenter(LineNo);
700
 
720
 
701
  // Skip indent
721
  // Skip indent
702
  line := SynEdit1.Lines[SynEdit1.CaretY];
722
  line := SynEdit1.Lines[SynEdit1.CaretY];
703
  for i := 1 to Length(line) do
723
  for i := 1 to Length(line) do
704
  begin
724
  begin
705
    if not CharInSet(line[i], [' ', #9]) then
725
    if not CharInSet(line[i], [' ', #9]) then
706
    begin
726
    begin
707
      SynEdit1.CaretX := i-1;
727
      SynEdit1.CaretX := i-1;
708
      break;
728
      break;
709
    end;
729
    end;
710
  end;
730
  end;
711
 
731
 
712
  PageControl2.ActivePage := CodeTabsheet;
732
  PageControl2.ActivePage := CodeTabsheet;
713
  if SynEdit1.CanFocus then SynEdit1.SetFocus;
733
  if SynEdit1.CanFocus then SynEdit1.SetFocus;
714
end;
734
end;
715
 
735
 
716
procedure TForm1.PageControl2Changing(Sender: TObject;
736
procedure TForm1.PageControl2Changing(Sender: TObject;
717
  var AllowChange: Boolean);
737
  var AllowChange: Boolean);
718
begin
738
begin
719
  if PageControl2.ActivePage = HelpTabsheet then
739
  if PageControl2.ActivePage = HelpTabsheet then
720
    HlpPrevPageIndex := -1
740
    HlpPrevPageIndex := -1
721
  else
741
  else
722
    HlpPrevPageIndex := PageControl2.ActivePageIndex;
742
    HlpPrevPageIndex := PageControl2.ActivePageIndex;
723
 
743
 
724
  AllowChange := true;
744
  AllowChange := true;
725
end;
745
end;
726
 
746
 
727
procedure TForm1.Memo2DblClick(Sender: TObject);
747
procedure TForm1.Memo2DblClick(Sender: TObject);
728
var
748
var
729
  line: string;
749
  line: string;
730
 
750
 
731
  procedure _process(toFind: string);
751
  procedure _process(toFind: string);
732
  var
752
  var
733
    p, lineno: integer;
753
    p, lineno: integer;
734
  begin
754
  begin
735
    if FileSystemCaseSensitive then
755
    if FileSystemCaseSensitive then
736
      p := Pos(toFind, line)
756
      p := Pos(toFind, line)
737
    else
757
    else
738
      p := Pos(toFind.ToLower, line.ToLower);
758
      p := Pos(toFind.ToLower, line.ToLower);
739
    if p <> 0 then
759
    if p <> 0 then
740
    begin
760
    begin
741
      line := copy(line, p+length(toFind), 99);
761
      line := copy(line, p+length(toFind), 99);
742
      if not TryStrToInt(line, lineno) then exit;
762
      if not TryStrToInt(line, lineno) then exit;
743
      GotoLineNo(lineno);
763
      GotoLineNo(lineno);
744
    end;
764
    end;
745
  end;
765
  end;
746
 
766
 
747
begin
767
begin
748
  line := memo2.Lines.Strings[Memo2.CaretPos.Y];
768
  line := memo2.Lines.Strings[Memo2.CaretPos.Y];
749
 
769
 
750
  {$REGION 'Possibility 1: filename.php:lineno'}
770
  {$REGION 'Possibility 1: filename.php:lineno'}
751
  _process(ExtractFileName(GetScrapFile) + ':');
771
  _process(ExtractFileName(GetScrapFile) + ':');
752
  {$ENDREGION}
772
  {$ENDREGION}
753
 
773
 
754
  {$REGION 'Possibility 2: on line xx'}
774
  {$REGION 'Possibility 2: on line xx'}
755
  _process(ExtractFileName(GetScrapFile) + ' on line ');
775
  _process(ExtractFileName(GetScrapFile) + ' on line ');
756
  {$ENDREGION}
776
  {$ENDREGION}
757
end;
777
end;
758
 
778
 
759
procedure TForm1.Memo2KeyDown(Sender: TObject; var Key: Word;
779
procedure TForm1.Memo2KeyDown(Sender: TObject; var Key: Word;
760
  Shift: TShiftState);
780
  Shift: TShiftState);
761
begin
781
begin
762
  if ((ssCtrl in Shift) and (Key = 65)) then TMemo(Sender).SelectAll;
782
  if ((ssCtrl in Shift) and (Key = 65)) then TMemo(Sender).SelectAll;
763
end;
783
end;
764
 
784
 
765
function TForm1.MarkUpLineReference(cont: string): string;
785
function TForm1.MarkUpLineReference(cont: string): string;
766
 
786
 
767
  procedure _process(toFind: string);
787
  procedure _process(toFind: string);
768
  var
788
  var
769
    p, a, b: integer;
789
    p, a, b: integer;
770
    num: integer;
790
    num: integer;
771
    insert_a, insert_b: string;
791
    insert_a, insert_b: string;
772
  begin
792
  begin
773
    if FileSystemCaseSensitive then
793
    if FileSystemCaseSensitive then
774
      p := Pos(toFind, cont)
794
      p := Pos(toFind, cont)
775
    else
795
    else
776
      p := Pos(toFind.ToLower, cont.ToLower);
796
      p := Pos(toFind.ToLower, cont.ToLower);
777
    while p >= 1 do
797
    while p >= 1 do
778
    begin
798
    begin
779
      a := p;
799
      a := p;
780
      b := p + length(toFind);
800
      b := p + length(toFind);
781
      num := 0;
801
      num := 0;
782
      while CharInSet(cont[b], ['0'..'9']) do
802
      while CharInSet(cont[b], ['0'..'9']) do
783
      begin
803
      begin
784
        num := num*10 + StrToInt(cont[b]);
804
        num := num*10 + StrToInt(cont[b]);
785
        inc(b);
805
        inc(b);
786
      end;
806
      end;
787
 
807
 
788
      insert_b := '</a>';
808
      insert_b := '</a>';
789
      insert_a := '<a href="' + FASTPHP_GOTO_URI_PREFIX + IntToStr(num) + '">';
809
      insert_a := '<a href="' + FASTPHP_GOTO_URI_PREFIX + IntToStr(num) + '">';
790
 
810
 
791
      insert(insert_b, cont, b);
811
      insert(insert_b, cont, b);
792
      insert(insert_a, cont, a);
812
      insert(insert_a, cont, a);
793
 
813
 
794
      p := b + Length(insert_a) + Length(insert_b);
814
      p := b + Length(insert_a) + Length(insert_b);
795
 
815
 
796
      p := PosEx(toFind, cont, p+1);
816
      p := PosEx(toFind, cont, p+1);
797
    end;
817
    end;
798
  end;
818
  end;
799
 
819
 
800
begin
820
begin
801
  {$REGION 'Possibility 1: filename.php:lineno'}
821
  {$REGION 'Possibility 1: filename.php:lineno'}
802
  _process(ExtractFileName(GetScrapFile) + ':');
822
  _process(ExtractFileName(GetScrapFile) + ':');
803
  {$ENDREGION}
823
  {$ENDREGION}
804
 
824
 
805
  {$REGION 'Possibility 2: on line xx'}
825
  {$REGION 'Possibility 2: on line xx'}
806
  _process(ExtractFileName(GetScrapFile) + ' on line ');
826
  _process(ExtractFileName(GetScrapFile) + ' on line ');
807
  {$ENDREGION}
827
  {$ENDREGION}
808
 
828
 
809
  result := cont;
829
  result := cont;
810
end;
830
end;
811
 
831
 
812
function TForm1.InputRequestCallback: string;
832
function TForm1.InputRequestCallback: string;
813
begin
833
begin
814
  result := SynEdit1.Text;
834
  result := SynEdit1.Text;
815
end;
835
end;
816
 
836
 
817
procedure TForm1.OutputNotifyCallback(const data: string);
837
procedure TForm1.OutputNotifyCallback(const data: string);
818
begin
838
begin
819
  TreeView1.FillWithFastPHPData(data);
839
  TreeView1.FillWithFastPHPData(data);
820
end;
840
end;
821
 
841
 
822
end.
842
end.
823
 
843