Subversion Repositories fastphp

Rev

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

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