Subversion Repositories fastphp

Rev

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

Rev 89 Rev 91
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: "DragAcceptFiles" does not work with Delphi Dark Design Template !!!
14
// TODO: "crHourGlass" does not work if F9 is pressed!
15
 
-
 
16
// TODO: if a scrapfile is already open, create a new scrap file (scrap2.php)
15
// TODO: if a scrapfile is already open, create a new scrap file (scrap2.php)
17
// TODO: localize
16
// TODO: localize
18
// TODO: wieso geht copy paste im twebbrowser nicht???
17
// TODO: wieso geht copy paste im twebbrowser nicht???
19
// TODO: Wieso dauert webbrowser1 erste kompilierung so lange???
18
// TODO: Wieso dauert webbrowser1 erste kompilierung so lange???
20
// TODO: wieso kommt syntax fehler zweimal? einmal stderr einmal stdout?
19
// TODO: wieso kommt syntax fehler zweimal? einmal stderr einmal stdout?
21
// TODO: Browser titlebar (link preview)
20
// TODO: Browser titlebar (link preview)
22
// TODO: "jump to next/prev todo" buttons/shortcuts
21
// TODO: "jump to next/prev todo" buttons/shortcuts
23
// TODO: "increase/decrease indent" buttons/shortcuts
22
// TODO: "increase/decrease indent" buttons/shortcuts
24
 
23
 
-
 
24
// In regards Unicode:
-
 
25
// - Solve compiler warnings
-
 
26
// - If you place Unicode symbols in a ANSI file, they will be replaced during saving
-
 
27
//   by "?" without asking the user if the code should be converted to Unicode!
-
 
28
// - FastPHP can only read a UTF-8 file correctly if it has a BOM
-
 
29
//   However, the PSR-1 standard requires that files have UTF-8 without BOM!
-
 
30
//   So we need auto-detect (since many people are working with ANSI!)
-
 
31
// - When a file is correctly loaded with UTF-8/BOM,
-
 
32
//   the run output (Plaintext and HTML) will show UTF-8 instead of Unicode
-
 
33
//   (that COULD be intended since the Windows CMD is not Unicode ready?)
-
 
34
//   But HTML is also shown as UTF-8 even though I have added <meta charset="UTF-8"> ?!
-
 
35
// - Is it possible that UTF8 BOM automatically gets removed by FastPHP, generating pure ANSI?
-
 
36
 
25
// Small things:
37
// Small things:
26
// - The scroll bars of SynEdit are not affected by the dark theme
38
// - The scroll bars of SynEdit are not affected by the dark theme
27
 
39
 
28
// Future ideas
40
// Future ideas
29
// - code insight
41
// - code insight
30
// - verschiedene php versionen?
42
// - verschiedene php versionen?
31
// - webbrowser1 nur laden, wenn man den tab anwählt?
43
// - webbrowser1 nur laden, wenn man den tab anwählt?
32
// - doppelklick auf tab soll diesen schließen
44
// - doppelklick auf tab soll diesen schließen
33
// - Onlinehelp (www) aufrufen
45
// - Onlinehelp (www) aufrufen oder CHM datei
34
// - Let all colors be adjustable
46
// - Let all colors be adjustable
35
// - code in bildschirmmitte (horizontal)?
47
// - code in bildschirmmitte (horizontal)?
36
// - search in files of a directory
48
// - search in files of a directory
37
// - multi tab?
49
// - Files in multiple tabs?
38
// - DDE (drag n drop)
50
// - Configurable tabulator display-width
39
 
51
 
40
interface
52
interface
41
 
53
 
42
uses
54
uses
43
  // TODO: "{$IFDEF USE_SHDOCVW_TLB}_TLB{$ENDIF}" does not work with Delphi 10.2
55
  // TODO: "{$IFDEF USE_SHDOCVW_TLB}_TLB{$ENDIF}" does not work with Delphi 10.2
44
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
56
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
45
  Dialogs, StdCtrls, OleCtrls, ComCtrls, ExtCtrls, ToolWin, IniFiles,
57
  Dialogs, StdCtrls, OleCtrls, ComCtrls, ExtCtrls, ToolWin, IniFiles,
46
  SynEditHighlighter, SynHighlighterPHP, SynEdit, ShDocVw, FindReplace,
58
  SynEditHighlighter, SynHighlighterPHP, SynEdit, ShDocVw, FindReplace,
47
  ActnList, SynEditMiscClasses, SynEditSearch, RunPHP, ImgList, SynUnicode,
59
  ActnList, SynEditMiscClasses, SynEditSearch, RunPHP, ImgList, SynUnicode,
48
  System.ImageList, System.Actions, Vcl.Menus, Vcl.Themes, System.UITypes;
60
  System.ImageList, System.Actions, Vcl.Menus, Vcl.Themes, System.UITypes;
49
 
61
 
50
{.$DEFINE OnlineHelp}
62
{.$DEFINE OnlineHelp}
51
 
63
 
52
type
64
type
53
  TForm1 = class(TForm)
65
  TForm1 = class(TForm)
54
    PageControl1: TPageControl;
66
    PageControl1: TPageControl;
55
    PlaintextTabSheet: TTabSheet;
67
    PlaintextTabSheet: TTabSheet;
56
    HtmlTabSheet: TTabSheet;
68
    HtmlTabSheet: TTabSheet;
57
    Memo2: TMemo;
69
    Memo2: TMemo;
58
    WebBrowser1: TWebBrowser;
70
    WebBrowser1: TWebBrowser;
59
    Splitter1: TSplitter;
71
    Splitter1: TSplitter;
60
    PageControl2: TPageControl;
72
    PageControl2: TPageControl;
61
    CodeTabsheet: TTabSheet;
73
    CodeTabsheet: TTabSheet;
62
    HelpTabsheet: TTabSheet;
74
    HelpTabsheet: TTabSheet;
63
    WebBrowser2: TWebBrowser;
75
    WebBrowser2: TWebBrowser;
64
    OpenDialog1: TOpenDialog;
76
    OpenDialog1: TOpenDialog;
65
    Panel1: TPanel;
77
    Panel1: TPanel;
66
    OpenDialog3: TOpenDialog;
78
    OpenDialog3: TOpenDialog;
67
    SynEdit1: TSynEdit;
79
    SynEdit1: TSynEdit;
68
    SynPHPSyn1: TSynPHPSyn;
80
    SynPHPSyn1: TSynPHPSyn;
69
    Panel2: TPanel;
81
    Panel2: TPanel;
70
    SynEditFocusTimer: TTimer;
82
    SynEditFocusTimer: TTimer;
71
    Button1: TButton;
83
    Button1: TButton;
72
    Button2: TButton;
84
    Button2: TButton;
73
    Button3: TButton;
85
    Button3: TButton;
74
    Button4: TButton;
86
    Button4: TButton;
75
    Button5: TButton;
87
    Button5: TButton;
76
    Button6: TButton;
88
    Button6: TButton;
77
    ActionList: TActionList;
89
    ActionList: TActionList;
78
    ActionFind: TAction;
90
    ActionFind: TAction;
79
    ActionReplace: TAction;
91
    ActionReplace: TAction;
80
    ActionFindNext: TAction;
92
    ActionFindNext: TAction;
81
    ActionGoto: TAction;
93
    ActionGoto: TAction;
82
    ActionSave: TAction;
94
    ActionSave: TAction;
83
    ActionHelp: TAction;
95
    ActionHelp: TAction;
84
    ActionRun: TAction;
96
    ActionRun: TAction;
85
    ActionESC: TAction;
97
    ActionESC: TAction;
86
    Button7: TButton;
98
    Button7: TButton;
87
    ActionOpen: TAction;
99
    ActionOpen: TAction;
88
    Button8: TButton;
100
    Button8: TButton;
89
    Button9: TButton;
101
    Button9: TButton;
90
    ActionFindPrev: TAction;
102
    ActionFindPrev: TAction;
91
    Timer1: TTimer;
103
    Timer1: TTimer;
92
    ActionSpaceToTab: TAction;
104
    ActionSpaceToTab: TAction;
93
    Button11: TButton;
105
    Button11: TButton;
94
    SynEditSearch1: TSynEditSearch;
106
    SynEditSearch1: TSynEditSearch;
95
    TreeView1: TTreeView;
107
    TreeView1: TTreeView;
96
    Splitter2: TSplitter;
108
    Splitter2: TSplitter;
97
    btnLint: TButton;
109
    btnLint: TButton;
98
    ActionLint: TAction;
110
    ActionLint: TAction;
99
    ImageList1: TImageList;
111
    ImageList1: TImageList;
100
    RunPopup: TPopupMenu;
112
    RunPopup: TPopupMenu;
101
    OpeninIDE1: TMenuItem;
113
    OpeninIDE1: TMenuItem;
102
    ActionRunConsole: TAction;
114
    ActionRunConsole: TAction;
103
    Runinconsole1: TMenuItem;
115
    Runinconsole1: TMenuItem;
104
    SavePopup: TPopupMenu;
116
    SavePopup: TPopupMenu;
105
    Saveas1: TMenuItem;
117
    Saveas1: TMenuItem;
106
    Save1: TMenuItem;
118
    Save1: TMenuItem;
107
    SaveDialog1: TSaveDialog;
119
    SaveDialog1: TSaveDialog;
108
    BtnSpecialChars: TImage;
120
    BtnSpecialChars: TImage;
109
    BtnSpecialCharsOff: TImage;
121
    BtnSpecialCharsOff: TImage;
110
    BtnSpecialCharsOn: TImage;
122
    BtnSpecialCharsOn: TImage;
111
    BtnLightOn: TImage;
123
    BtnLightOn: TImage;
112
    BtnLightOff: TImage;
124
    BtnLightOff: TImage;
113
    BtnLight: TImage;
125
    BtnLight: TImage;
114
    StartUpTimer: TTimer;
126
    StartUpTimer: TTimer;
115
    FileModTimer: TTimer;
127
    FileModTimer: TTimer;
116
    GotoPHPdir1: TMenuItem;
128
    GotoPHPdir1: TMenuItem;
117
    PHPShell1: TMenuItem;
129
    PHPShell1: TMenuItem;
-
 
130
    ActionSaveAs: TAction;
-
 
131
    ActionGoToPHPDir: TAction;
-
 
132
    ActionPHPInteractiveShell: TAction;
118
    procedure Run(Sender: TObject);
133
    procedure Run(Sender: TObject);
119
    procedure RunConsole(Sender: TObject);
134
    procedure RunConsole(Sender: TObject);
120
    procedure FormShow(Sender: TObject);
135
    procedure FormShow(Sender: TObject);
121
    procedure FormCreate(Sender: TObject);
136
    procedure FormCreate(Sender: TObject);
122
    procedure FormDestroy(Sender: TObject);
137
    procedure FormDestroy(Sender: TObject);
123
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
138
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
124
    procedure PageControl2Changing(Sender: TObject; var AllowChange: Boolean);
139
    procedure PageControl2Changing(Sender: TObject; var AllowChange: Boolean);
125
    procedure Memo2DblClick(Sender: TObject);
140
    procedure Memo2DblClick(Sender: TObject);
126
    (*
141
    (*
127
    {$IFDEF USE_SHDOCVW_TLB}
142
    {$IFDEF USE_SHDOCVW_TLB}
128
    *)
143
    *)
129
    procedure WebBrowser1BeforeNavigate2(ASender: TObject;
144
    procedure WebBrowser1BeforeNavigate2(ASender: TObject;
130
      const pDisp: IDispatch; const URL, Flags, TargetFrameName, PostData,
145
      const pDisp: IDispatch; const URL, Flags, TargetFrameName, PostData,
131
      Headers: OleVariant; var Cancel: WordBool);
146
      Headers: OleVariant; var Cancel: WordBool);
132
    (*
147
    (*
133
    {$ELSE}
148
    {$ELSE}
134
    procedure WebBrowser1BeforeNavigate2(ASender: TObject;
149
    procedure WebBrowser1BeforeNavigate2(ASender: TObject;
135
      const pDisp: IDispatch; var URL, Flags, TargetFrameName, PostData,
150
      const pDisp: IDispatch; var URL, Flags, TargetFrameName, PostData,
136
      Headers: OleVariant; var Cancel: WordBool);
151
      Headers: OleVariant; var Cancel: WordBool);
137
    {$ENDIF}
152
    {$ENDIF}
138
    *)
153
    *)
139
    procedure BeforeNavigate(const URL: OleVariant; var Cancel: WordBool);
154
    procedure BeforeNavigate(const URL: OleVariant; var Cancel: WordBool);
140
    procedure SynEditFocusTimerTimer(Sender: TObject);
155
    procedure SynEditFocusTimerTimer(Sender: TObject);
141
    procedure ActionFindExecute(Sender: TObject);
156
    procedure ActionFindExecute(Sender: TObject);
142
    procedure ActionReplaceExecute(Sender: TObject);
157
    procedure ActionReplaceExecute(Sender: TObject);
143
    procedure ActionFindNextExecute(Sender: TObject);
158
    procedure ActionFindNextExecute(Sender: TObject);
144
    procedure ActionGotoExecute(Sender: TObject);
159
    procedure ActionGotoExecute(Sender: TObject);
145
    procedure ActionSaveExecute(Sender: TObject);
160
    procedure ActionSaveExecute(Sender: TObject);
146
    procedure ActionHelpExecute(Sender: TObject);
161
    procedure ActionHelpExecute(Sender: TObject);
147
    procedure ActionRunExecute(Sender: TObject);
162
    procedure ActionRunExecute(Sender: TObject);
148
    procedure ActionESCExecute(Sender: TObject);
163
    procedure ActionESCExecute(Sender: TObject);
149
    procedure SynEdit1MouseWheelDown(Sender: TObject; Shift: TShiftState;
164
    procedure SynEdit1MouseWheelDown(Sender: TObject; Shift: TShiftState;
150
      MousePos: TPoint; var Handled: Boolean);
165
      MousePos: TPoint; var Handled: Boolean);
151
    procedure SynEdit1MouseWheelUp(Sender: TObject; Shift: TShiftState;
166
    procedure SynEdit1MouseWheelUp(Sender: TObject; Shift: TShiftState;
152
      MousePos: TPoint; var Handled: Boolean);
167
      MousePos: TPoint; var Handled: Boolean);
153
    procedure ActionOpenExecute(Sender: TObject);
168
    procedure ActionOpenExecute(Sender: TObject);
154
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
169
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
155
    procedure Memo2KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
170
    procedure Memo2KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
156
    procedure ActionFindPrevExecute(Sender: TObject);
171
    procedure ActionFindPrevExecute(Sender: TObject);
157
    procedure SynEdit1MouseCursor(Sender: TObject;
172
    procedure SynEdit1MouseCursor(Sender: TObject;
158
      const aLineCharPos: TBufferCoord; var aCursor: TCursor);
173
      const aLineCharPos: TBufferCoord; var aCursor: TCursor);
159
    procedure Timer1Timer(Sender: TObject);
174
    procedure Timer1Timer(Sender: TObject);
160
    procedure ActionSpaceToTabExecute(Sender: TObject);
175
    procedure ActionSpaceToTabExecute(Sender: TObject);
161
    procedure TreeView1DblClick(Sender: TObject);
176
    procedure TreeView1DblClick(Sender: TObject);
162
    procedure SynEdit1GutterClick(Sender: TObject; Button: TMouseButton; X, Y,
177
    procedure SynEdit1GutterClick(Sender: TObject; Button: TMouseButton; X, Y,
163
      Line: Integer; Mark: TSynEditMark);
178
      Line: Integer; Mark: TSynEditMark);
164
    procedure SynEdit1PaintTransient(Sender: TObject; Canvas: TCanvas;
179
    procedure SynEdit1PaintTransient(Sender: TObject; Canvas: TCanvas;
165
      TransientType: TTransientType);
180
      TransientType: TTransientType);
166
    procedure ActionLintExecute(Sender: TObject);
181
    procedure ActionLintExecute(Sender: TObject);
167
    procedure ActionRunConsoleExecute(Sender: TObject);
182
    procedure ActionRunConsoleExecute(Sender: TObject);
168
    procedure SynEdit1Change(Sender: TObject);
183
    procedure SynEdit1Change(Sender: TObject);
169
    procedure Saveas1Click(Sender: TObject);
-
 
170
    procedure Save1Click(Sender: TObject);
-
 
171
    procedure BtnSpecialCharsClick(Sender: TObject);
184
    procedure BtnSpecialCharsClick(Sender: TObject);
172
    procedure WebBrowser1WindowClosing(ASender: TObject;
185
    procedure WebBrowser1WindowClosing(ASender: TObject;
173
      IsChildWindow: WordBool; var Cancel: WordBool);
186
      IsChildWindow: WordBool; var Cancel: WordBool);
174
    procedure BtnLightClick(Sender: TObject);
187
    procedure BtnLightClick(Sender: TObject);
175
    procedure StartUpTimerTimer(Sender: TObject);
188
    procedure StartUpTimerTimer(Sender: TObject);
176
    procedure FileModTimerTimer(Sender: TObject);
189
    procedure FileModTimerTimer(Sender: TObject);
177
    procedure GotoPHPdir1Click(Sender: TObject);
-
 
178
    procedure PHPShell1Click(Sender: TObject);
-
 
179
    procedure SynEdit1DropFiles(Sender: TObject; X, Y: Integer;
190
    procedure SynEdit1DropFiles(Sender: TObject; X, Y: Integer;
180
      AFiles: TStrings);
191
      AFiles: TStrings);
-
 
192
    procedure ActionSaveAsExecute(Sender: TObject);
-
 
193
    procedure ActionGoToPHPDirExecute(Sender: TObject);
-
 
194
    procedure ActionPHPInteractiveShellExecute(Sender: TObject);
181
  private
195
  private
182
    hMutex: THandle;
196
    hMutex: THandle;
183
    CurSearchTerm: string;
197
    CurSearchTerm: string;
184
    HlpPrevPageIndex: integer;
198
    HlpPrevPageIndex: integer;
185
    SrcRep: TSynEditFindReplace;
199
    SrcRep: TSynEditFindReplace;
186
    {$IFDEF OnlineHelp}
200
    {$IFDEF OnlineHelp}
187
    gOnlineHelpWord: string;
201
    gOnlineHelpWord: string;
188
    {$ENDIF}
202
    {$ENDIF}
189
    FileModLast: TDateTime;
203
    FileModLast: TDateTime;
-
 
204
    FormShowRanOnce: boolean;
-
 
205
    BrowserLoadedOnce: boolean;
190
    procedure Help;
206
    procedure Help;
191
    function InputRequestCallback(var data: AnsiString): boolean;
207
    function InputRequestCallback(var data: AnsiString): boolean;
192
    function OutputNotifyCallback(const data: AnsiString): boolean;
208
    function OutputNotifyCallback(const data: AnsiString): boolean;
193
    procedure RightTrimAll;
209
    procedure RightTrimAll;
194
  protected
210
  protected
195
    ChmIndex: TMemIniFile;
211
    ChmIndex: TMemIniFile;
196
    FScrapFile: string;
212
    FScrapFile: string;
197
    FSaveAsFilename: string;
213
    FSaveAsFilename: string;
198
    codeExplorer: TRunCodeExplorer;
214
    codeExplorer: TRunCodeExplorer;
199
    procedure GotoLineNo(LineNo: integer);
215
    procedure GotoLineNo(LineNo: integer);
200
    function GetScrapFile: string;
216
    function GetScrapFile: string;
201
    procedure StartCodeExplorer;
217
    procedure StartCodeExplorer;
202
    procedure RefreshModifySign;
218
    procedure RefreshModifySign;
203
    procedure Theme_Light;
219
    procedure Theme_Light;
204
    procedure Theme_Dark;
220
    procedure Theme_Dark;
205
    function IsThemeDark: boolean;
221
    function IsThemeDark: boolean;
206
    function MarkUpLineReference(cont: string): string;
222
    function MarkUpLineReference(cont: string): string;
207
    procedure SaveToFile(filename: string);
223
    procedure SaveToFile(filename: string);
208
  end;
224
  end;
209
 
225
 
210
var
226
var
211
  Form1: TForm1;
227
  Form1: TForm1;
212
 
228
 
213
implementation
229
implementation
214
 
230
 
215
{$R *.dfm}
231
{$R *.dfm}
216
 
232
 
217
{$R Cursors.res}
233
{$R Cursors.res}
218
 
234
 
219
uses
235
uses
220
  Functions, StrUtils, WebBrowserUtils, FastPHPUtils, Math, ShellAPI, RichEdit,
236
  Functions, StrUtils, WebBrowserUtils, FastPHPUtils, Math, ShellAPI, RichEdit,
221
  FastPHPTreeView, ImageListEx, FastPHPConfig;
237
  FastPHPTreeView, ImageListEx, FastPHPConfig;
222
 
238
 
223
const
239
const
224
  crMouseGutter = 1;
240
  crMouseGutter = 1;
225
 
241
 
226
procedure TForm1.RefreshModifySign;
242
procedure TForm1.RefreshModifySign;
227
var
243
var
228
  tmp: string;
244
  tmp: string;
229
begin
245
begin
230
  tmp := Caption;
246
  tmp := Caption;
231
 
247
 
232
  tmp := StringReplace(tmp, '*', '', [rfReplaceAll]);
248
  tmp := StringReplace(tmp, '*', '', [rfReplaceAll]);
233
  if SynEdit1.Modified then tmp := tmp + '*';
249
  if SynEdit1.Modified then tmp := tmp + '*';
234
 
250
 
235
  if Caption <> tmp then Caption := tmp;
251
  if Caption <> tmp then Caption := tmp;
236
end;
252
end;
237
 
253
 
238
procedure TForm1.ActionFindNextExecute(Sender: TObject);
254
procedure TForm1.ActionFindNextExecute(Sender: TObject);
239
begin
255
begin
240
  SrcRep.FindNext;
256
  SrcRep.FindNext;
241
end;
257
end;
242
 
258
 
243
procedure TForm1.ActionFindPrevExecute(Sender: TObject);
259
procedure TForm1.ActionFindPrevExecute(Sender: TObject);
244
begin
260
begin
245
  SrcRep.FindPrev;
261
  SrcRep.FindPrev;
246
end;
262
end;
247
 
263
 
248
procedure TForm1.ActionGotoExecute(Sender: TObject);
264
procedure TForm1.ActionGotoExecute(Sender: TObject);
249
var
265
var
250
  val: string;
266
  val: string;
251
  lineno: integer;
267
  lineno: integer;
-
 
268
resourcestring
-
 
269
  SGoTo = 'Go to';
-
 
270
  SLineNumber = 'Line number:';
252
begin
271
begin
253
  // TODO: VK_LMENU does not work! only works with AltGr but not Alt
272
  // TODO: VK_LMENU does not work! only works with AltGr but not Alt
254
  // http://stackoverflow.com/questions/16828250/delphi-xe2-how-to-prevent-the-alt-key-stealing-focus ?
273
  // http://stackoverflow.com/questions/16828250/delphi-xe2-how-to-prevent-the-alt-key-stealing-focus ?
255
 
274
 
256
  InputQuery('Go to', 'Line number:', val);
275
  if not InputQuery(SGoTo, SLineNumber, val) or
257
  if not TryStrToInt(val, lineno) then
276
     not TryStrToInt(val, lineno) then
258
  begin
277
  begin
259
    if SynEdit1.CanFocus then SynEdit1.SetFocus;
278
    if SynEdit1.CanFocus then SynEdit1.SetFocus;
260
    exit;
279
    exit;
261
  end;
280
  end;
262
  GotoLineNo(lineno);
281
  GotoLineNo(lineno);
263
end;
282
end;
264
 
283
 
-
 
284
procedure TForm1.ActionGoToPHPDirExecute(Sender: TObject);
-
 
285
var
-
 
286
  phpExe: string;
-
 
287
begin
-
 
288
  phpExe := GetPHPExe;
-
 
289
  if phpExe <> '' then
-
 
290
    ShellExecute(Handle, 'open', 'explorer.exe', PChar(ExtractFilePath(phpExe)), '', SW_NORMAL);
-
 
291
end;
-
 
292
 
265
procedure TForm1.ActionHelpExecute(Sender: TObject);
293
procedure TForm1.ActionHelpExecute(Sender: TObject);
266
begin
294
begin
267
  Help;
295
  Help;
268
  if PageControl2.ActivePage = HelpTabsheet then
296
  if PageControl2.ActivePage = HelpTabsheet then
269
    WebBrowser2.SetFocus
297
    WebBrowser2.SetFocus
270
  else if PageControl2.ActivePage = CodeTabsheet then
298
  else if PageControl2.ActivePage = CodeTabsheet then
271
    SynEdit1.SetFocus;
299
    SynEdit1.SetFocus;
272
end;
300
end;
273
 
301
 
274
procedure TForm1.ActionLintExecute(Sender: TObject);
302
procedure TForm1.ActionLintExecute(Sender: TObject);
275
begin
303
begin
276
  Run(Sender);
304
  Run(Sender);
277
  SynEdit1.SetFocus;
305
  SynEdit1.SetFocus;
278
end;
306
end;
279
 
307
 
280
procedure TForm1.ActionOpenExecute(Sender: TObject);
308
procedure TForm1.ActionOpenExecute(Sender: TObject);
281
begin
309
begin
282
  If OpenDialog3.Execute then
310
  If OpenDialog3.Execute then
283
  begin
311
  begin
284
    ShellExecute(0, 'open', PChar(ParamStr(0)), PChar('"' + OpenDialog3.FileName + '"'), '', SW_NORMAL);
312
    ShellExecute(0, 'open', PChar(ParamStr(0)), PChar('"' + OpenDialog3.FileName + '"'), '', SW_NORMAL);
285
  end;
313
  end;
286
end;
314
end;
287
 
315
 
-
 
316
procedure TForm1.ActionPHPInteractiveShellExecute(Sender: TObject);
-
 
317
var
-
 
318
  phpExe: string;
-
 
319
begin
-
 
320
  phpExe := GetPHPExe;
-
 
321
  if phpExe <> '' then
-
 
322
    ShellExecute(Handle, 'open', PChar(phpExe), '-a', PChar(ExtractFilePath(phpExe)), SW_NORMAL);
-
 
323
end;
-
 
324
 
288
procedure TForm1.ActionReplaceExecute(Sender: TObject);
325
procedure TForm1.ActionReplaceExecute(Sender: TObject);
289
begin
326
begin
290
  SrcRep.ReplaceExecute;
327
  SrcRep.ReplaceExecute;
291
end;
328
end;
292
 
329
 
293
procedure TForm1.ActionRunConsoleExecute(Sender: TObject);
330
procedure TForm1.ActionRunConsoleExecute(Sender: TObject);
294
begin
331
begin
295
  RunConsole(Sender);
332
  RunConsole(Sender);
296
  SynEdit1.SetFocus;
333
  SynEdit1.SetFocus;
297
end;
334
end;
298
 
335
 
299
procedure TForm1.ActionRunExecute(Sender: TObject);
336
procedure TForm1.ActionRunExecute(Sender: TObject);
300
begin
337
begin
301
  Run(Sender);
338
  Run(Sender);
302
  SynEdit1.SetFocus;
339
  SynEdit1.SetFocus;
303
end;
340
end;
304
 
341
 
305
procedure TForm1.RightTrimAll;
342
procedure TForm1.RightTrimAll;
306
var
343
var
307
  i: integer;
344
  i: integer;
308
begin
345
begin
309
  for i := 0 to SynEdit1.Lines.Count-1 do
346
  for i := 0 to SynEdit1.Lines.Count-1 do
310
  begin
347
  begin
311
    SynEdit1.Lines.Strings[i] := TrimRight(SynEdit1.Lines.Strings[i]);
348
    SynEdit1.Lines.Strings[i] := TrimRight(SynEdit1.Lines.Strings[i]);
312
  end;
349
  end;
313
 
350
 
314
  (*
351
  (*
315
  while (SynEdit1.Lines.Count > 0) and (SynEdit1.Lines.Strings[SynEdit1.Lines.Count-1] = '') do
352
  while (SynEdit1.Lines.Count > 0) and (SynEdit1.Lines.Strings[SynEdit1.Lines.Count-1] = '') do
316
  begin
353
  begin
317
    SynEdit1.Lines.Delete(SynEdit1.Lines.Count-1);
354
    SynEdit1.Lines.Delete(SynEdit1.Lines.Count-1);
318
  end;
355
  end;
319
  if SynEdit1.SelStart > Length(SynEdit1.Text)-1 then
356
  if SynEdit1.SelStart > Length(SynEdit1.Text)-1 then
320
  begin
357
  begin
321
    // TODO: This code does not work...
358
    // TODO: This code does not work...
322
    SynEdit1.SelStart := Length(SynEdit1.Text)-1;
359
    SynEdit1.SelStart := Length(SynEdit1.Text)-1;
323
    SynEdit1.SelEnd   := Length(SynEdit1.Text)-1;
360
    SynEdit1.SelEnd   := Length(SynEdit1.Text)-1;
324
  end;
361
  end;
325
  *)
362
  *)
326
end;
363
end;
327
 
364
 
-
 
365
procedure TForm1.ActionSaveAsExecute(Sender: TObject);
-
 
366
var
-
 
367
  hMutexNew: THandle;
-
 
368
resourcestring
-
 
369
  SCannotSaveBecauseMutex = 'Cannot save because file "%s", because it is alrady open in another FastPHP window!';
-
 
370
begin
-
 
371
  if SaveDialog1.Execute then
-
 
372
  begin
-
 
373
    {$REGION 'Switch mutex'}
-
 
374
    hMutexNew := CreateMutex(nil, True, PChar('FastPHP'+md5(UpperCase(SaveDialog1.FileName))));
-
 
375
    if GetLastError = ERROR_ALREADY_EXISTS then
-
 
376
    begin
-
 
377
      ShowMessageFmt(SCannotSaveBecauseMutex, [SaveDialog1.FileName]);
-
 
378
      Close;
-
 
379
    end;
-
 
380
 
-
 
381
    if hMutex <> 0 then CloseHandle(hMutex); // Note: ReleaseMutex does not work as expected!
-
 
382
    hMutex := hMutexNew;
-
 
383
    {$ENDREGION}
-
 
384
 
-
 
385
    FSaveAsFilename := SaveDialog1.FileName;
-
 
386
    Caption := Copy(Caption, 1, Pos(' - ', Caption)-1) + ' - ' + FSaveAsFilename;
-
 
387
    Application.Title := Format('%s - FastPHP', [ExtractFileName(FSaveAsFilename)]); // do not translate!
-
 
388
    Button7.Click;
-
 
389
  end;
-
 
390
end;
-
 
391
 
328
procedure TForm1.ActionSaveExecute(Sender: TObject);
392
procedure TForm1.ActionSaveExecute(Sender: TObject);
329
begin
393
begin
330
  RightTrimAll;
394
  RightTrimAll;
331
  SaveToFile(GetScrapFile);
395
  SaveToFile(GetScrapFile);
332
  SynEdit1.Modified := false;
396
  SynEdit1.Modified := false;
333
  RefreshModifySign;
397
  RefreshModifySign;
334
  if SynEdit1.CanFocus then SynEdit1.SetFocus;
398
  if SynEdit1.CanFocus then SynEdit1.SetFocus;
335
end;
399
end;
336
 
400
 
337
procedure TForm1.ActionSpaceToTabExecute(Sender: TObject);
401
procedure TForm1.ActionSpaceToTabExecute(Sender: TObject);
338
 
402
 
339
    function SpacesAtBeginning(line: string): integer;
403
    function SpacesAtBeginning(line: string): integer;
340
    begin
404
    begin
341
      result := 0;
405
      result := 0;
342
      if Trim(line) = '' then exit;
406
      if Trim(line) = '' then exit;
343
      while line[result+1] = ' ' do
407
      while line[result+1] = ' ' do
344
      begin
408
      begin
345
        inc(result);
409
        inc(result);
346
      end;
410
      end;
347
    end;
411
    end;
348
 
412
 
349
    function GuessIndent(lines: {$IFDEF UNICODE}TStrings{$ELSE}TUnicodeStrings{$ENDIF}): integer;
413
    function GuessIndent(lines: {$IFDEF UNICODE}TStrings{$ELSE}TUnicodeStrings{$ENDIF}): integer;
350
      function _Check(indent: integer): boolean;
414
      function _Check(indent: integer): boolean;
351
      var
415
      var
352
        i: integer;
416
        i: integer;
353
      begin
417
      begin
354
        result := true;
418
        result := true;
355
        for i := 0 to lines.Count-1 do
419
        for i := 0 to lines.Count-1 do
356
          if SpacesAtBeginning(lines.Strings[i]) mod indent <> 0 then
420
          if SpacesAtBeginning(lines.Strings[i]) mod indent <> 0 then
357
          begin
421
          begin
358
            // ShowMessageFmt('Zeile "%s" nicht durch %d teilbar!', [lines.strings[i], indent]);
422
            // ShowMessageFmt('Zeile "%s" nicht durch %d teilbar!', [lines.strings[i], indent]);
359
            result := false;
423
            result := false;
360
            exit;
424
            exit;
361
          end;
425
          end;
362
      end;
426
      end;
363
    var
427
    var
364
      i: integer;
428
      i: integer;
365
    begin
429
    begin
366
      for i := 8 downto 2 do
430
      for i := 8 downto 2 do
367
      begin
431
      begin
368
        if _Check(i) then
432
        if _Check(i) then
369
        begin
433
        begin
370
          result := i;
434
          result := i;
371
          exit;
435
          exit;
372
        end;
436
        end;
373
      end;
437
      end;
374
      result := -1;
438
      result := -1;
375
    end;
439
    end;
376
 
440
 
377
    procedure SpaceToTab(lines: {$IFDEF UNICODE}TStrings{$ELSE}TUnicodeStrings{$ENDIF}; indent: integer);
441
    procedure SpaceToTab(lines: {$IFDEF UNICODE}TStrings{$ELSE}TUnicodeStrings{$ENDIF}; indent: integer);
378
    var
442
    var
379
      i, spaces: integer;
443
      i, spaces: integer;
380
    begin
444
    begin
381
      for i := 0 to lines.Count-1 do
445
      for i := 0 to lines.Count-1 do
382
      begin
446
      begin
383
        spaces := SpacesAtBeginning(lines.Strings[i]);
447
        spaces := SpacesAtBeginning(lines.Strings[i]);
384
        lines.Strings[i] := StringOfChar(#9, spaces div indent) + StringOfChar(' ', spaces mod indent) + Copy(lines.Strings[i], spaces+1, Length(lines.Strings[i])-spaces);
448
        lines.Strings[i] := StringOfChar(#9, spaces div indent) + StringOfChar(' ', spaces mod indent) + Copy(lines.Strings[i], spaces+1, Length(lines.Strings[i])-spaces);
385
      end;
449
      end;
386
    end;
450
    end;
387
 
451
 
388
    function SpacesAvailable(lines: {$IFDEF UNICODE}TStrings{$ELSE}TUnicodeStrings{$ENDIF}): boolean;
452
    function SpacesAvailable(lines: {$IFDEF UNICODE}TStrings{$ELSE}TUnicodeStrings{$ENDIF}): boolean;
389
    var
453
    var
390
      i, spaces: integer;
454
      i, spaces: integer;
391
    begin
455
    begin
392
      for i := 0 to lines.Count-1 do
456
      for i := 0 to lines.Count-1 do
393
      begin
457
      begin
394
        spaces := SpacesAtBeginning(lines.Strings[i]);
458
        spaces := SpacesAtBeginning(lines.Strings[i]);
395
        if spaces > 0 then
459
        if spaces > 0 then
396
        begin
460
        begin
397
          result := true;
461
          result := true;
398
          exit;
462
          exit;
399
        end;
463
        end;
400
      end;
464
      end;
401
      result := false;
465
      result := false;
402
      exit;
466
      exit;
403
    end;
467
    end;
404
 
468
 
405
var
469
var
406
  val: string;
470
  val: string;
407
  ind: integer;
471
  ind: integer;
408
resourcestring
472
resourcestring
409
  SNoLinesAvailable = 'No lines with spaces at the beginning available';
473
  SNoLinesAvailable = 'No lines with spaces at the beginning available';
-
 
474
  SSpacesToLabs = 'Spaces to tabs';
-
 
475
  SIndent = 'Indent:';
410
begin
476
begin
411
  // TODO: if something is selected, only process the selected part
477
  // TODO: if something is selected, only process the selected part
412
 
478
 
413
  if not SpacesAvailable(SynEdit1.Lines) then
479
  if not SpacesAvailable(SynEdit1.Lines) then
414
  begin
480
  begin
415
    MessageDlg(SNoLinesAvailable, mtInformation, [mbOk], 0);
481
    MessageDlg(SNoLinesAvailable, mtInformation, [mbOk], 0);
416
    exit;
482
    exit;
417
  end;
483
  end;
418
 
484
 
419
  ind := GuessIndent(SynEdit1.Lines);
485
  ind := GuessIndent(SynEdit1.Lines);
420
  if ind <> -1 then val := IntToStr(ind);
486
  if ind <> -1 then val := IntToStr(ind);
421
 
487
 
422
  InputQuery('Spaces to tabs', 'Indent:', val); // TODO: handle CANCEL correctly...
488
  if not InputQuery(SSpacesToLabs, SIndent, val) or
423
  if TryStrToInt(Trim(val), ind) then
489
     not TryStrToInt(Trim(val), ind) then
424
  begin
490
  begin
425
    if ind = 0 then exit;
491
    if SynEdit1.CanFocus then SynEdit1.SetFocus;
426
    SpaceToTab(SynEdit1.Lines, ind);
492
    exit;
427
  end;
493
  end;
428
 
494
 
-
 
495
  if ind = 0 then exit;
429
  if SynEdit1.CanFocus then SynEdit1.SetFocus;
496
  SpaceToTab(SynEdit1.Lines, ind);
430
end;
497
end;
431
 
498
 
432
procedure TForm1.ActionESCExecute(Sender: TObject);
499
procedure TForm1.ActionESCExecute(Sender: TObject);
433
begin
500
begin
434
  if (HlpPrevPageIndex <> -1) and (PageControl2.ActivePage = HelpTabSheet) and
501
  if (HlpPrevPageIndex <> -1) and (PageControl2.ActivePage = HelpTabSheet) and
435
     (HelpTabsheet.TabVisible) then
502
     (HelpTabsheet.TabVisible) then
436
  begin
503
  begin
437
    PageControl2.ActivePageIndex := HlpPrevPageIndex;
504
    PageControl2.ActivePageIndex := HlpPrevPageIndex;
438
    HelpTabsheet.TabVisible := false;
505
    HelpTabsheet.TabVisible := false;
439
  end;
506
  end;
440
 
507
 
441
  // Dirty hack...
508
  // Dirty hack...
442
  SrcRep.CloseDialogs;
509
  SrcRep.CloseDialogs;
443
end;
510
end;
444
 
511
 
445
procedure TForm1.ActionFindExecute(Sender: TObject);
512
procedure TForm1.ActionFindExecute(Sender: TObject);
446
begin
513
begin
447
  SrcRep.FindExecute;
514
  SrcRep.FindExecute;
448
end;
515
end;
449
 
516
 
450
var
-
 
451
  firstTimeBrowserLoad: boolean = true;
-
 
452
procedure TForm1.Run(Sender: TObject);
517
procedure TForm1.Run(Sender: TObject);
453
var
518
var
454
  bakTS: TTabSheet;
519
  bakTS: TTabSheet;
455
  //ss: TStringStream;
520
  //ss: TStringStream;
456
  //bakPos: Int64;
521
  //bakPos: Int64;
457
begin
522
begin
458
  memo2.Lines.Text := '';
523
  memo2.Lines.Text := '';
459
 
524
 
460
  if firstTimeBrowserLoad then
525
  if not BrowserLoadedOnce then
461
  begin
526
  begin
462
    bakTS := PageControl1.ActivePage;
527
    bakTS := PageControl1.ActivePage;
463
    try
528
    try
464
      PageControl1.ActivePage := HtmlTabSheet; // Required for the first time, otherwise, WebBrowser1.Clear will hang
529
      PageControl1.ActivePage := HtmlTabSheet; // Required for the first time, otherwise, WebBrowser1.Clear will hang
465
      Webbrowser1.Clear;
530
      Webbrowser1.Clear;
466
    finally
531
    finally
467
      PageControl1.ActivePage := bakTS;
532
      PageControl1.ActivePage := bakTS;
468
    end;
533
    end;
469
    firstTimeBrowserLoad := false;
534
    BrowserLoadedOnce := true;
470
  end
535
  end
471
  else
536
  else
472
    Webbrowser1.Clear;
537
    Webbrowser1.Clear;
473
 
538
 
474
  Screen.Cursor := crHourGlass;
539
  Screen.Cursor := crHourGlass; // TODO: Doesn't work with F9
475
  Application.ProcessMessages;
540
  Application.ProcessMessages;
476
 
541
 
477
  try
542
  try
478
    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.
543
    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.
479
 
544
 
480
    // TODO 70421 * <fastphp> flush() mittels ContentCallBack implementieren... ich möchte bei langen scripts statusanzeigen realisieren können mit javascript das stück für stück geladen wird !!!!!!!!
545
    // TODO 70421 * <fastphp> flush() mittels ContentCallBack implementieren... ich möchte bei langen scripts statusanzeigen realisieren können mit javascript das stück für stück geladen wird !!!!!!!!
481
    // TODO 70422 * <fastphp> wenn ein script hängt, soll man es abwürgen dürfen!!!!!!
546
    // TODO 70422 * <fastphp> wenn ein script hängt, soll man es abwürgen dürfen!!!!!!
482
    memo2.Lines.Text := RunPHPScript(GetScrapFile, Sender=ActionLint, False);
547
    memo2.Lines.Text := RunPHPScript(GetScrapFile, Sender=ActionLint, False);
483
 
548
 
484
    {$REGION 'Show in Web Browser'}
549
    {$REGION 'Show in Web Browser'}
485
    Webbrowser1.LoadHTML(MarkUpLineReference(memo2.Lines.Text), GetScrapFile);
550
    Webbrowser1.LoadHTML(MarkUpLineReference(memo2.Lines.Text), GetScrapFile);
486
 
551
 
487
    // Alternatively:
552
    // Alternatively:
488
    (*
553
    (*
489
    ss := TstringStream.Create;
554
    ss := TstringStream.Create;
490
    ss.WriteString(MarkUpLineReference(memo2.Lines.Text));
555
    ss.WriteString(MarkUpLineReference(memo2.Lines.Text));
491
    ss.Position := 0;
556
    ss.Position := 0;
492
    Webbrowser1.LoadStream(ss, GetScrapFile);
557
    Webbrowser1.LoadStream(ss, GetScrapFile);
493
    Webbrowser1.Wait;
558
    Webbrowser1.Wait;
494
    ss.Free;
559
    ss.Free;
495
    *)
560
    *)
496
    {$ENDREGION}
561
    {$ENDREGION}
497
 
562
 
498
    if IsTextHTML(memo2.lines.text) then
563
    if IsTextHTML(memo2.lines.text) then
499
      PageControl1.ActivePage := HtmlTabSheet
564
      PageControl1.ActivePage := HtmlTabSheet
500
    else
565
    else
501
      PageControl1.ActivePage := PlaintextTabSheet;
566
      PageControl1.ActivePage := PlaintextTabSheet;
502
  finally
567
  finally
503
    Screen.Cursor := crDefault;
568
    Screen.Cursor := crDefault;
504
  end;
569
  end;
505
end;
570
end;
506
 
571
 
507
procedure TForm1.RunConsole(Sender: TObject);
572
procedure TForm1.RunConsole(Sender: TObject);
508
begin
573
begin
509
  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.
574
  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.
510
  RunPHPScript(GetScrapFile, Sender=ActionLint, True);
575
  RunPHPScript(GetScrapFile, Sender=ActionLint, True);
511
end;
576
end;
512
 
577
 
513
procedure TForm1.SynEdit1Change(Sender: TObject);
578
procedure TForm1.SynEdit1Change(Sender: TObject);
514
begin
579
begin
515
  RefreshModifySign;
580
  RefreshModifySign;
516
end;
581
end;
517
 
582
 
518
procedure TForm1.SynEdit1DropFiles(Sender: TObject; X, Y: Integer;
583
procedure TForm1.SynEdit1DropFiles(Sender: TObject; X, Y: Integer;
519
  AFiles: TStrings);
584
  AFiles: TStrings);
520
var
585
var
521
  FileName: string;
586
  FileName: string;
522
const
587
const
523
  WARN_FILE_COUNT = 10;
588
  WARN_FILE_COUNT = 10;
-
 
589
resourcestring
-
 
590
  SAreYouSure = 'Are you sure you want to open %d files?';
524
begin
591
begin
525
  if AFiles.Count > WARN_FILE_COUNT then
592
  if AFiles.Count > WARN_FILE_COUNT then
526
  begin
593
  begin
527
    if not MessageDlg(Format('Are you sure you want to open %d files?', [WARN_FILE_COUNT]), mtConfirmation, mbYesNoCancel, 0) <> mrYes then
594
    if not MessageDlg(Format(SAreYouSure, [WARN_FILE_COUNT]), mtConfirmation, mbYesNoCancel, 0) <> mrYes then
528
      exit;
595
      exit;
529
  end;
596
  end;
530
 
597
 
531
  for FileName in AFiles do
598
  for FileName in AFiles do
532
  begin
599
  begin
533
    ShellExecute(0, 'open', PChar(ParamStr(0)), PChar('"' + FileName + '"'), '', SW_NORMAL);
600
    ShellExecute(0, 'open', PChar(ParamStr(0)), PChar('"' + FileName + '"'), '', SW_NORMAL);
534
  end;
601
  end;
535
end;
602
end;
536
 
603
 
537
procedure TForm1.SynEdit1GutterClick(Sender: TObject; Button: TMouseButton; X,
604
procedure TForm1.SynEdit1GutterClick(Sender: TObject; Button: TMouseButton; X,
538
  Y, Line: Integer; Mark: TSynEditMark);
605
  Y, Line: Integer; Mark: TSynEditMark);
539
begin
606
begin
540
  (*
607
  (*
541
  TSynEdit(Sender).CaretX := 1;
608
  TSynEdit(Sender).CaretX := 1;
542
  TSynEdit(Sender).CaretY := Line;
609
  TSynEdit(Sender).CaretY := Line;
543
  TSynEdit(Sender).SelLength := Length(TSynEdit(Sender).LineText);
610
  TSynEdit(Sender).SelLength := Length(TSynEdit(Sender).LineText);
544
  *)
611
  *)
545
end;
612
end;
546
 
613
 
547
procedure TForm1.SynEdit1MouseCursor(Sender: TObject; const aLineCharPos: TBufferCoord; var aCursor: TCursor);
614
procedure TForm1.SynEdit1MouseCursor(Sender: TObject; const aLineCharPos: TBufferCoord; var aCursor: TCursor);
548
{$IFDEF OnlineHelp}
615
{$IFDEF OnlineHelp}
549
var
616
var
550
  Line: Integer;
617
  Line: Integer;
551
  Column: Integer;
618
  Column: Integer;
552
  word: string;
619
  word: string;
553
begin
620
begin
554
  Line  := aLineCharPos.Line-1;
621
  Line  := aLineCharPos.Line-1;
555
  Column := aLineCharPos.Char-1;
622
  Column := aLineCharPos.Char-1;
556
  word := GetWordUnderPos(TSynEdit(Sender), Line, Column);
623
  word := GetWordUnderPos(TSynEdit(Sender), Line, Column);
557
  if word <> gOnlineHelpWord then
624
  if word <> gOnlineHelpWord then
558
  begin
625
  begin
559
    gOnlineHelpWord := word;
626
    gOnlineHelpWord := word;
560
    Timer1.Enabled := false;
627
    Timer1.Enabled := false;
561
    Timer1.Enabled := true;
628
    Timer1.Enabled := true;
562
  end;
629
  end;
563
{$ELSE}
630
{$ELSE}
564
begin
631
begin
565
{$ENDIF}
632
{$ENDIF}
566
end;
633
end;
567
 
634
 
568
procedure TForm1.SynEdit1MouseWheelDown(Sender: TObject; Shift: TShiftState;
635
procedure TForm1.SynEdit1MouseWheelDown(Sender: TObject; Shift: TShiftState;
569
  MousePos: TPoint; var Handled: Boolean);
636
  MousePos: TPoint; var Handled: Boolean);
570
begin
637
begin
571
  if ssCtrl in Shift then
638
  if ssCtrl in Shift then
572
  begin
639
  begin
573
    SynEdit1.Font.Size := Max(SynEdit1.Font.Size - 1, 5);
640
    SynEdit1.Font.Size := Max(SynEdit1.Font.Size - 1, 5);
574
    Handled := true;
641
    Handled := true;
575
  end
642
  end
576
  else Handled := false;
643
  else Handled := false;
577
end;
644
end;
578
 
645
 
579
procedure TForm1.SynEdit1MouseWheelUp(Sender: TObject; Shift: TShiftState;
646
procedure TForm1.SynEdit1MouseWheelUp(Sender: TObject; Shift: TShiftState;
580
  MousePos: TPoint; var Handled: Boolean);
647
  MousePos: TPoint; var Handled: Boolean);
581
begin
648
begin
582
  if ssCtrl in Shift then
649
  if ssCtrl in Shift then
583
  begin
650
  begin
584
    SynEdit1.Font.Size := SynEdit1.Font.Size + 1;
651
    SynEdit1.Font.Size := SynEdit1.Font.Size + 1;
585
    Handled := true;
652
    Handled := true;
586
  end
653
  end
587
  else Handled := false;
654
  else Handled := false;
588
end;
655
end;
589
 
656
 
590
procedure TForm1.SynEdit1PaintTransient(Sender: TObject; Canvas: TCanvas; TransientType: TTransientType);
657
procedure TForm1.SynEdit1PaintTransient(Sender: TObject; Canvas: TCanvas; TransientType: TTransientType);
591
var
658
var
592
  Editor: TSynEdit;
659
  Editor: TSynEdit;
593
  OpenChars: array of WideChar;//[0..2] of WideChar=();
660
  OpenChars: array of WideChar;//[0..2] of WideChar=();
594
  CloseChars: array of WideChar;//[0..2] of WideChar=();
661
  CloseChars: array of WideChar;//[0..2] of WideChar=();
595
 
662
 
596
  function IsCharBracket(AChar: WideChar): Boolean;
663
  function IsCharBracket(AChar: WideChar): Boolean;
597
  begin
664
  begin
598
    case AChar of
665
    case AChar of
599
      '{','[','(','<','}',']',')','>':
666
      '{','[','(','<','}',']',')','>':
600
        Result := True;
667
        Result := True;
601
      else
668
      else
602
        Result := False;
669
        Result := False;
603
    end;
670
    end;
604
  end;
671
  end;
605
 
672
 
606
  function CharToPixels(P: TBufferCoord): TPoint;
673
  function CharToPixels(P: TBufferCoord): TPoint;
607
  begin
674
  begin
608
    Result := Editor.RowColumnToPixels(Editor.BufferToDisplayPos(P));
675
    Result := Editor.RowColumnToPixels(Editor.BufferToDisplayPos(P));
609
  end;
676
  end;
610
 
677
 
611
var
678
var
612
  COLOR_FG: TColor;
679
  COLOR_FG: TColor;
613
  COLOR_BG: TColor;
680
  COLOR_BG: TColor;
614
  P: TBufferCoord;
681
  P: TBufferCoord;
615
  Pix: TPoint;
682
  Pix: TPoint;
616
  D: TDisplayCoord;
683
  D: TDisplayCoord;
617
  S: UnicodeString;
684
  S: UnicodeString;
618
  I: Integer;
685
  I: Integer;
619
  Attri: TSynHighlighterAttributes;
686
  Attri: TSynHighlighterAttributes;
620
  ArrayLength: Integer;
687
  ArrayLength: Integer;
621
  start: Integer;
688
  start: Integer;
622
  TmpCharA, TmpCharB: WideChar;
689
  TmpCharA, TmpCharB: WideChar;
623
begin
690
begin
624
  // Source: https://github.com/SynEdit/SynEdit/blob/master/Demos/OnPaintTransientDemo/Unit1.pas
691
  // Source: https://github.com/SynEdit/SynEdit/blob/master/Demos/OnPaintTransientDemo/Unit1.pas
625
 
692
 
626
  if IsThemeDark then
693
  if IsThemeDark then
627
  begin
694
  begin
628
    COLOR_FG := clLime;
695
    COLOR_FG := clLime;
629
    COLOR_BG := clGreen;
696
    COLOR_BG := clGreen;
630
  end
697
  end
631
  else
698
  else
632
  begin
699
  begin
633
    COLOR_FG := clGreen;
700
    COLOR_FG := clGreen;
634
    COLOR_BG := clLime;
701
    COLOR_BG := clLime;
635
  end;
702
  end;
636
 
703
 
637
  if TSynEdit(Sender).SelAvail then exit;
704
  if TSynEdit(Sender).SelAvail then exit;
638
  Editor := TSynEdit(Sender);
705
  Editor := TSynEdit(Sender);
639
  ArrayLength:= 3;
706
  ArrayLength:= 3;
640
 
707
 
641
  (*
708
  (*
642
  if (Editor.Highlighter = shHTML) or (Editor.Highlighter = shXML) then
709
  if (Editor.Highlighter = shHTML) or (Editor.Highlighter = shXML) then
643
    inc(ArrayLength);
710
    inc(ArrayLength);
644
  *)
711
  *)
645
 
712
 
646
  SetLength(OpenChars, ArrayLength);
713
  SetLength(OpenChars, ArrayLength);
647
  SetLength(CloseChars, ArrayLength);
714
  SetLength(CloseChars, ArrayLength);
648
  for i := 0 to ArrayLength - 1 do
715
  for i := 0 to ArrayLength - 1 do
649
  begin
716
  begin
650
    case i of
717
    case i of
651
      0: begin OpenChars[i] := '('; CloseChars[i] := ')'; end;
718
      0: begin OpenChars[i] := '('; CloseChars[i] := ')'; end;
652
      1: begin OpenChars[i] := '{'; CloseChars[i] := '}'; end;
719
      1: begin OpenChars[i] := '{'; CloseChars[i] := '}'; end;
653
      2: begin OpenChars[i] := '['; CloseChars[i] := ']'; end;
720
      2: begin OpenChars[i] := '['; CloseChars[i] := ']'; end;
654
      3: begin OpenChars[i] := '<'; CloseChars[i] := '>'; end;
721
      3: begin OpenChars[i] := '<'; CloseChars[i] := '>'; end;
655
    end;
722
    end;
656
  end;
723
  end;
657
 
724
 
658
  P := Editor.CaretXY;
725
  P := Editor.CaretXY;
659
  D := Editor.DisplayXY;
726
  D := Editor.DisplayXY;
660
 
727
 
661
  Start := Editor.SelStart;
728
  Start := Editor.SelStart;
662
 
729
 
663
  if (Start > 0) and (Start <= length(Editor.Text)) then
730
  if (Start > 0) and (Start <= length(Editor.Text)) then
664
    TmpCharA := Editor.Text[Start]
731
    TmpCharA := Editor.Text[Start]
665
  else
732
  else
666
    TmpCharA := #0;
733
    TmpCharA := #0;
667
 
734
 
668
  if (Start > 0){Added by VTS} and (Start < length(Editor.Text)) then
735
  if (Start > 0){Added by VTS} and (Start < length(Editor.Text)) then
669
    TmpCharB := Editor.Text[Start + 1]
736
    TmpCharB := Editor.Text[Start + 1]
670
  else
737
  else
671
    TmpCharB := #0;
738
    TmpCharB := #0;
672
 
739
 
673
  if not IsCharBracket(TmpCharA) and not IsCharBracket(TmpCharB) then exit;
740
  if not IsCharBracket(TmpCharA) and not IsCharBracket(TmpCharB) then exit;
674
  S := TmpCharB;
741
  S := TmpCharB;
675
  if not IsCharBracket(TmpCharB) then
742
  if not IsCharBracket(TmpCharB) then
676
  begin
743
  begin
677
    P.Char := P.Char - 1;
744
    P.Char := P.Char - 1;
678
    S := TmpCharA;
745
    S := TmpCharA;
679
  end;
746
  end;
680
  Editor.GetHighlighterAttriAtRowCol(P, S, Attri);
747
  Editor.GetHighlighterAttriAtRowCol(P, S, Attri);
681
 
748
 
682
  if (Editor.Highlighter.SymbolAttribute = Attri) then
749
  if (Editor.Highlighter.SymbolAttribute = Attri) then
683
  begin
750
  begin
684
    for i := low(OpenChars) to High(OpenChars) do
751
    for i := low(OpenChars) to High(OpenChars) do
685
    begin
752
    begin
686
      if (S = OpenChars[i]) or (S = CloseChars[i]) then
753
      if (S = OpenChars[i]) or (S = CloseChars[i]) then
687
      begin
754
      begin
688
        Pix := CharToPixels(P);
755
        Pix := CharToPixels(P);
689
 
756
 
690
        Editor.Canvas.Brush.Style := bsSolid;//Clear;
757
        Editor.Canvas.Brush.Style := bsSolid;//Clear;
691
        Editor.Canvas.Font.Assign(Editor.Font);
758
        Editor.Canvas.Font.Assign(Editor.Font);
692
        Editor.Canvas.Font.Style := Attri.Style;
759
        Editor.Canvas.Font.Style := Attri.Style;
693
 
760
 
694
        if (TransientType = ttAfter) then
761
        if (TransientType = ttAfter) then
695
        begin
762
        begin
696
          Editor.Canvas.Font.Color := COLOR_FG;
763
          Editor.Canvas.Font.Color := COLOR_FG;
697
          Editor.Canvas.Brush.Color := COLOR_BG;
764
          Editor.Canvas.Brush.Color := COLOR_BG;
698
        end
765
        end
699
        else
766
        else
700
        begin
767
        begin
701
          Editor.Canvas.Font.Color := Attri.Foreground;
768
          Editor.Canvas.Font.Color := Attri.Foreground;
702
          Editor.Canvas.Brush.Color := Attri.Background;
769
          Editor.Canvas.Brush.Color := Attri.Background;
703
        end;
770
        end;
704
        if Editor.Canvas.Font.Color = clNone then
771
        if Editor.Canvas.Font.Color = clNone then
705
          Editor.Canvas.Font.Color := Editor.Font.Color;
772
          Editor.Canvas.Font.Color := Editor.Font.Color;
706
        if Editor.Canvas.Brush.Color = clNone then
773
        if Editor.Canvas.Brush.Color = clNone then
707
          Editor.Canvas.Brush.Color := Editor.Color;
774
          Editor.Canvas.Brush.Color := Editor.Color;
708
 
775
 
709
        Editor.Canvas.TextOut(Pix.X, Pix.Y, S);
776
        Editor.Canvas.TextOut(Pix.X, Pix.Y, S);
710
        P := Editor.GetMatchingBracketEx(P);
777
        P := Editor.GetMatchingBracketEx(P);
711
 
778
 
712
        if (P.Char > 0) and (P.Line > 0) then
779
        if (P.Char > 0) and (P.Line > 0) then
713
        begin
780
        begin
714
          Pix := CharToPixels(P);
781
          Pix := CharToPixels(P);
715
          if Pix.X > Editor.Gutter.Width then
782
          if Pix.X > Editor.Gutter.Width then
716
          begin
783
          begin
717
            {$REGION 'Added by ViaThinkSoft'}
784
            {$REGION 'Added by ViaThinkSoft'}
718
            if (TransientType = ttAfter) then
785
            if (TransientType = ttAfter) then
719
            begin
786
            begin
720
              Editor.Canvas.Font.Color := COLOR_FG;
787
              Editor.Canvas.Font.Color := COLOR_FG;
721
              Editor.Canvas.Brush.Color := COLOR_BG;
788
              Editor.Canvas.Brush.Color := COLOR_BG;
722
            end
789
            end
723
            else
790
            else
724
            begin
791
            begin
725
              Editor.Canvas.Font.Color := Attri.Foreground;
792
              Editor.Canvas.Font.Color := Attri.Foreground;
726
              Editor.Canvas.Brush.Color := Attri.Background;
793
              Editor.Canvas.Brush.Color := Attri.Background;
727
            end;
794
            end;
728
            if Editor.Canvas.Font.Color = clNone then
795
            if Editor.Canvas.Font.Color = clNone then
729
              Editor.Canvas.Font.Color := Editor.Font.Color;
796
              Editor.Canvas.Font.Color := Editor.Font.Color;
730
            if Editor.Canvas.Brush.Color = clNone then
797
            if Editor.Canvas.Brush.Color = clNone then
731
              Editor.Canvas.Brush.Color := Editor.Color;
798
              Editor.Canvas.Brush.Color := Editor.Color;
732
            {$ENDREGION}
799
            {$ENDREGION}
733
            if S = OpenChars[i] then
800
            if S = OpenChars[i] then
734
              Editor.Canvas.TextOut(Pix.X, Pix.Y, CloseChars[i])
801
              Editor.Canvas.TextOut(Pix.X, Pix.Y, CloseChars[i])
735
            else Editor.Canvas.TextOut(Pix.X, Pix.Y, OpenChars[i]);
802
            else Editor.Canvas.TextOut(Pix.X, Pix.Y, OpenChars[i]);
736
          end;
803
          end;
737
        end;
804
        end;
738
      end;
805
      end;
739
    end;
806
    end;
740
    Editor.Canvas.Brush.Style := bsSolid;
807
    Editor.Canvas.Brush.Style := bsSolid;
741
  end;
808
  end;
742
end;
809
end;
743
 
810
 
744
procedure TForm1.SynEditFocusTimerTimer(Sender: TObject);
811
procedure TForm1.SynEditFocusTimerTimer(Sender: TObject);
745
begin
812
begin
746
  SynEditFocusTimer.Enabled := false;
813
  SynEditFocusTimer.Enabled := false;
747
  Button1.SetFocus; // Workaround for weird bug... This (and the timer) is necessary to get the focus to SynEdit1
814
  Button1.SetFocus; // Workaround for weird bug... This (and the timer) is necessary to get the focus to SynEdit1
748
  SynEdit1.SetFocus;
815
  SynEdit1.SetFocus;
749
end;
816
end;
750
 
817
 
751
procedure TForm1.Theme_Dark;
818
procedure TForm1.Theme_Dark;
752
begin
819
begin
753
  if IsThemeDark then exit;
820
  if IsThemeDark then exit;
754
  TStyleManager.TrySetStyle('Windows10 SlateGray');
821
  TStyleManager.TrySetStyle('Windows10 SlateGray'); // do not translate
755
  Color := 1316887;
822
  Color := 1316887;
756
  Font.Color := clCream;
823
  Font.Color := clCream;
757
  //Memo2.Font.Color := clCream;
824
  //Memo2.Font.Color := clCream;
758
  //Memo2.ParentColor := true;
825
  //Memo2.ParentColor := true;
759
  SynEdit1.ActiveLineColor := 2238502;
826
  SynEdit1.ActiveLineColor := 2238502;
760
  SynEdit1.Color := 1316887;
827
  SynEdit1.Color := 1316887;
761
  SynEdit1.Font.Color := clCream;
828
  SynEdit1.Font.Color := clCream;
762
  SynEdit1.Gutter.Color := 1316887;
829
  SynEdit1.Gutter.Color := 1316887;
763
  SynEdit1.Gutter.Font.Color := clCream;
830
  SynEdit1.Gutter.Font.Color := clCream;
764
  SynEdit1.Gutter.GradientStartColor := 2238502;
831
  SynEdit1.Gutter.GradientStartColor := 2238502;
765
  SynEdit1.Gutter.GradientEndColor := 1316887;
832
  SynEdit1.Gutter.GradientEndColor := 1316887;
766
  SynPHPSyn1.CommentAttri.Foreground := $00837B82;
833
  SynPHPSyn1.CommentAttri.Foreground := $00837B82;
767
  SynPHPSyn1.IdentifierAttri.Foreground := 9627120;
834
  SynPHPSyn1.IdentifierAttri.Foreground := 9627120;
768
  SynPHPSyn1.KeyAttri.Foreground := 4157595;
835
  SynPHPSyn1.KeyAttri.Foreground := 4157595;
769
  SynPHPSyn1.NumberAttri.Foreground := 5008079;
836
  SynPHPSyn1.NumberAttri.Foreground := 5008079;
770
  SynPHPSyn1.StringAttri.Foreground := 6987151;
837
  SynPHPSyn1.StringAttri.Foreground := 6987151;
771
  SynPHPSyn1.SymbolAttri.Foreground := 8769754;
838
  SynPHPSyn1.SymbolAttri.Foreground := 8769754;
772
  SynPHPSyn1.VariableAttri.Foreground := 6924493;
839
  SynPHPSyn1.VariableAttri.Foreground := 6924493;
773
end;
840
end;
774
 
841
 
775
procedure TForm1.Theme_Light;
842
procedure TForm1.Theme_Light;
776
begin
843
begin
777
  if not IsThemeDark then exit;
844
  if not IsThemeDark then exit;
778
  TStyleManager.TrySetStyle('Windows');
845
  TStyleManager.TrySetStyle('Windows'); // do not translate
779
  Color := clBtnFace;
846
  Color := clBtnFace;
780
  Font.Color := clWindowText;
847
  Font.Color := clWindowText;
781
  //Memo2.Font.Color := clWindowText;
848
  //Memo2.Font.Color := clWindowText;
782
  SynEdit1.ActiveLineColor := 14680010;
849
  SynEdit1.ActiveLineColor := 14680010;
783
  SynEdit1.Color := clWindow;
850
  SynEdit1.Color := clCream;
784
  SynEdit1.Font.Color := clWindowText;
851
  SynEdit1.Font.Color := clWindowText;
785
  SynEdit1.Gutter.Color := clBtnFace;
852
  SynEdit1.Gutter.Color := clBtnFace;
786
  SynEdit1.Gutter.Font.Color := clWindowText;
853
  SynEdit1.Gutter.Font.Color := clWindowText;
787
  SynEdit1.Gutter.GradientStartcolor := cl3dLight;
854
  SynEdit1.Gutter.GradientStartcolor := cl3dLight;
788
  SynEdit1.Gutter.GradientEndColor := clBtnFace;;
855
  SynEdit1.Gutter.GradientEndColor := clBtnFace;;
789
  SynPHPSyn1.CommentAttri.Foreground := 33023;
856
  SynPHPSyn1.CommentAttri.Foreground := 33023;
790
  SynPHPSyn1.IdentifierAttri.Foreground := 4194304;
857
  SynPHPSyn1.IdentifierAttri.Foreground := 4194304;
791
  SynPHPSyn1.KeyAttri.Foreground := 4227072;
858
  SynPHPSyn1.KeyAttri.Foreground := 4227072;
792
  SynPHPSyn1.NumberAttri.Foreground := 213;
859
  SynPHPSyn1.NumberAttri.Foreground := 213;
793
  SynPHPSyn1.StringAttri.Foreground := 13762560;
860
  SynPHPSyn1.StringAttri.Foreground := 13762560;
794
  SynPHPSyn1.SymbolAttri.Foreground := 4227072;
861
  SynPHPSyn1.SymbolAttri.Foreground := 4227072;
795
  SynPHPSyn1.VariableAttri.Foreground := 213;
862
  SynPHPSyn1.VariableAttri.Foreground := 213;
796
end;
863
end;
797
 
864
 
798
procedure TForm1.Timer1Timer(Sender: TObject);
865
procedure TForm1.Timer1Timer(Sender: TObject);
799
begin
866
begin
800
  {$IFDEF OnlineHelp}
867
  {$IFDEF OnlineHelp}
801
  Timer1.Enabled := false;
868
  Timer1.Enabled := false;
802
 
869
 
803
  // TODO: Insert a small online help hint
870
  // TODO: Insert a small online help hint
804
  //Caption := gOnlineHelpWord;
871
  //Caption := gOnlineHelpWord;
805
  {$ENDIF}
872
  {$ENDIF}
806
end;
873
end;
807
 
874
 
808
procedure TForm1.TreeView1DblClick(Sender: TObject);
875
procedure TForm1.TreeView1DblClick(Sender: TObject);
809
var
876
var
810
  tn: TTreeNode;
877
  tn: TTreeNode;
811
  lineNo: integer;
878
  lineNo: integer;
812
begin
879
begin
813
  tn := TTreeView(Sender).Selected;
880
  tn := TTreeView(Sender).Selected;
814
  if tn = nil then exit;
881
  if tn = nil then exit;
815
  lineNo := Integer(tn.Data);
882
  lineNo := Integer(tn.Data);
816
  if lineNo > 0 then GotoLineNo(lineNo);
883
  if lineNo > 0 then GotoLineNo(lineNo);
817
end;
884
end;
818
 
885
 
819
(*
886
(*
820
{$IFDEF USE_SHDOCVW_TLB}
887
{$IFDEF USE_SHDOCVW_TLB}
821
*)
888
*)
822
procedure TForm1.WebBrowser1BeforeNavigate2(ASender: TObject;
889
procedure TForm1.WebBrowser1BeforeNavigate2(ASender: TObject;
823
  const pDisp: IDispatch; const URL, Flags, TargetFrameName, PostData,
890
  const pDisp: IDispatch; const URL, Flags, TargetFrameName, PostData,
824
  Headers: OleVariant; var Cancel: WordBool);
891
  Headers: OleVariant; var Cancel: WordBool);
825
begin
892
begin
826
  BeforeNavigate(URL, Cancel);
893
  BeforeNavigate(URL, Cancel);
827
end;
894
end;
828
(*
895
(*
829
{$ELSE}
896
{$ELSE}
830
procedure TForm1.WebBrowser1BeforeNavigate2(ASender: TObject;
897
procedure TForm1.WebBrowser1BeforeNavigate2(ASender: TObject;
831
  const pDisp: IDispatch; var URL, Flags, TargetFrameName, PostData,
898
  const pDisp: IDispatch; var URL, Flags, TargetFrameName, PostData,
832
  Headers: OleVariant; var Cancel: WordBool);
899
  Headers: OleVariant; var Cancel: WordBool);
833
begin
900
begin
834
  BeforeNavigate(URL, Cancel);
901
  BeforeNavigate(URL, Cancel);
835
end;
902
end;
836
{$ENDIF}
903
{$ENDIF}
837
*)
904
*)
838
 
905
 
839
procedure TForm1.WebBrowser1WindowClosing(ASender: TObject;
906
procedure TForm1.WebBrowser1WindowClosing(ASender: TObject;
840
  IsChildWindow: WordBool; var Cancel: WordBool);
907
  IsChildWindow: WordBool; var Cancel: WordBool);
841
resourcestring
908
resourcestring
842
  LNG_CLOSE_REQUEST = 'A script has requested the window to be closed. The window of a standalone script would now close.';
909
  SCloseRequest = 'A script has requested the window to be closed. The window of a standalone script would now close.';
843
begin
910
begin
844
  ShowMessage(LNG_CLOSE_REQUEST);
911
  ShowMessage(SCloseRequest);
845
  TWebBrowser(ASender).Clear;
912
  TWebBrowser(ASender).Clear;
846
  Cancel := true;
913
  Cancel := true;
847
end;
914
end;
848
 
915
 
849
procedure TForm1.BeforeNavigate(const URL: OleVariant; var Cancel: WordBool);
916
procedure TForm1.BeforeNavigate(const URL: OleVariant; var Cancel: WordBool);
850
var
917
var
851
  s, myURL: string;
918
  s, myURL: string;
852
  lineno: integer;
919
  lineno: integer;
853
  p: integer;
920
  p: integer;
854
begin
921
begin
855
  {$REGION 'Line number references (PHP errors and warnings)'}
922
  {$REGION 'Line number references (PHP errors and warnings)'}
856
  if Copy(URL, 1, length(FASTPHP_GOTO_URI_PREFIX)) = FASTPHP_GOTO_URI_PREFIX then
923
  if Copy(URL, 1, length(FASTPHP_GOTO_URI_PREFIX)) = FASTPHP_GOTO_URI_PREFIX then
857
  begin
924
  begin
858
    try
925
    try
859
      s := copy(URL, length(FASTPHP_GOTO_URI_PREFIX)+1, 99);
926
      s := copy(URL, length(FASTPHP_GOTO_URI_PREFIX)+1, 99);
860
      if not TryStrToInt(s, lineno) then exit;
927
      if not TryStrToInt(s, lineno) then exit;
861
      GotoLineNo(lineno);
928
      GotoLineNo(lineno);
862
      SynEditFocusTimer.Enabled := true;
929
      SynEditFocusTimer.Enabled := true;
863
    finally
930
    finally
864
      Cancel := true;
931
      Cancel := true;
865
    end;
932
    end;
866
    Exit;
933
    Exit;
867
  end;
934
  end;
868
  {$ENDREGION}
935
  {$ENDREGION}
869
 
936
 
870
  {$REGION 'Intelligent browser (executes PHP scripts which are clicked in a hyperlink)'}
937
  {$REGION 'Intelligent browser (executes PHP scripts which are clicked in a hyperlink)'}
871
  if URL <> 'about:blank' then
938
  if URL <> 'about:blank' then
872
  begin
939
  begin
873
    myUrl := URL;
940
    myUrl := URL;
874
 
941
 
875
    p := Pos('?', myUrl);
942
    p := Pos('?', myUrl);
876
    if p >= 1 then myURL := copy(myURL, 1, p-1);
943
    if p >= 1 then myURL := copy(myURL, 1, p-1);
877
 
944
 
878
    // TODO: myURL urldecode
945
    // TODO: myURL urldecode
879
    // TODO: maybe we could even open that file in the editor!
946
    // TODO: maybe we could even open that file in the editor!
880
    // TODO: ?parameter=....
947
    // TODO: ?parameter=....
881
 
948
 
882
    if FileExists(myURL) and (EndsText('.php', myURL) or EndsText('.php3', myURL) or EndsText('.php4', myURL) or EndsText('.php5', myURL) or EndsText('.phps', myURL)) then
949
    if FileExists(myURL) and (EndsText('.php', myURL) or EndsText('.php3', myURL) or EndsText('.php4', myURL) or EndsText('.php5', myURL) or EndsText('.phps', myURL)) then
883
    begin
950
    begin
884
      WebBrowser1.LoadHTML(RunPHPScript(myURL), myUrl);
951
      WebBrowser1.LoadHTML(RunPHPScript(myURL), myUrl);
885
      Cancel := true;
952
      Cancel := true;
886
    end;
953
    end;
887
  end;
954
  end;
888
  {$ENDREGION}
955
  {$ENDREGION}
889
end;
956
end;
890
 
957
 
891
procedure TForm1.BtnLightClick(Sender: TObject);
958
procedure TForm1.BtnLightClick(Sender: TObject);
892
var
959
var
893
  CanClose: boolean;
960
  CanClose: boolean;
894
begin
961
begin
895
  FormCloseQuery(Form1, CanClose);
962
  FormCloseQuery(Form1, CanClose);
896
  if not CanClose then exit;
963
  if not CanClose then exit;
897
 
964
 
898
  if IsThemeDark then
965
  if IsThemeDark then
899
  begin
966
  begin
900
    BtnLight.Picture.Assign(BtnLightOn.Picture);
967
    BtnLight.Picture.Assign(BtnLightOn.Picture);
901
    Theme_Light;
968
    Theme_Light;
902
    TFastPHPConfig.DarkTheme := false;
969
    TFastPHPConfig.DarkTheme := false;
903
  end
970
  end
904
  else
971
  else
905
  begin
972
  begin
906
    BtnLight.Picture.Assign(BtnLightOff.Picture);
973
    BtnLight.Picture.Assign(BtnLightOff.Picture);
907
    Theme_Dark;
974
    Theme_Dark;
908
    TFastPHPConfig.DarkTheme := true;
975
    TFastPHPConfig.DarkTheme := true;
909
  end;
976
  end;
910
end;
977
end;
911
 
978
 
912
procedure TForm1.BtnSpecialCharsClick(Sender: TObject);
979
procedure TForm1.BtnSpecialCharsClick(Sender: TObject);
913
var
980
var
914
  opts: TSynEditorOptions;
981
  opts: TSynEditorOptions;
915
begin
982
begin
916
  opts := SynEdit1.Options;
983
  opts := SynEdit1.Options;
917
  if eoShowSpecialChars in SynEdit1.Options then
984
  if eoShowSpecialChars in SynEdit1.Options then
918
  begin
985
  begin
919
    BtnSpecialChars.Picture.Assign(BtnSpecialCharsOff.Picture);
986
    BtnSpecialChars.Picture.Assign(BtnSpecialCharsOff.Picture);
920
    Exclude(opts, eoShowSpecialChars);
987
    Exclude(opts, eoShowSpecialChars);
921
    TFastPHPConfig.SpecialChars := false;
988
    TFastPHPConfig.SpecialChars := false;
922
  end
989
  end
923
  else
990
  else
924
  begin
991
  begin
925
    BtnSpecialChars.Picture.Assign(BtnSpecialCharsOn.Picture);
992
    BtnSpecialChars.Picture.Assign(BtnSpecialCharsOn.Picture);
926
    Include(opts, eoShowSpecialChars);
993
    Include(opts, eoShowSpecialChars);
927
    TFastPHPConfig.SpecialChars := true;
994
    TFastPHPConfig.SpecialChars := true;
928
  end;
995
  end;
929
  SynEdit1.Options := opts;
996
  SynEdit1.Options := opts;
930
end;
997
end;
931
 
998
 
932
procedure TForm1.FileModTimerTimer(Sender: TObject);
999
procedure TForm1.FileModTimerTimer(Sender: TObject);
-
 
1000
resourcestring
-
 
1001
  SChangeConflict = 'The file was changed in a different application BUT IT WAS ALSO MODIFIED HERE! Reload file AND LOSE CHANGES HERE?';
-
 
1002
  SChangeNotify = 'The file was changed in a different application! Reload file?';
933
begin
1003
begin
934
  FileModTimer.Enabled := false;
1004
  FileModTimer.Enabled := false;
935
  if FileModLast <> FileAge(GetScrapFile) then
1005
  if FileModLast <> FileAge(GetScrapFile) then
936
  begin
1006
  begin
937
    FileModLast := FileAge(GetScrapFile);
1007
    FileModLast := FileAge(GetScrapFile);
938
    if SynEdit1.Modified then
1008
    if SynEdit1.Modified then
939
    begin
1009
    begin
940
      if MessageDlg('The file was changed in a different application BUT IT WAS ALSO MODIFIED HERE! Reload file AND LOSE CHANGES HERE?', mtWarning, mbYesNoCancel, 0) = mrYes then
1010
      if MessageDlg(SChangeConflict, mtWarning, mbYesNoCancel, 0) = mrYes then
941
      begin
1011
      begin
942
        SynEdit1.Lines.LoadFromFile(GetScrapFile);
1012
        SynEdit1.Lines.LoadFromFile(GetScrapFile);
943
      end;
1013
      end;
944
    end
1014
    end
945
    else
1015
    else
946
    begin
1016
    begin
947
      if MessageDlg('The file was changed in a different application! Reload file?', mtConfirmation, mbYesNoCancel, 0) = mrYes then
1017
      if MessageDlg(SChangeNotify, mtConfirmation, mbYesNoCancel, 0) = mrYes then
948
      begin
1018
      begin
949
        SynEdit1.Lines.LoadFromFile(GetScrapFile);
1019
        SynEdit1.Lines.LoadFromFile(GetScrapFile);
950
      end;
1020
      end;
951
    end;
1021
    end;
952
  end;
1022
  end;
953
  FileModTimer.Enabled := true;
1023
  FileModTimer.Enabled := true;
954
end;
1024
end;
955
 
1025
 
956
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
1026
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
957
begin
1027
begin
958
  DragAcceptFiles(Handle, False);
1028
  DragAcceptFiles(Handle, False);
959
  TFastPHPConfig.FontSize := SynEdit1.Font.Size;
1029
  TFastPHPConfig.FontSize := SynEdit1.Font.Size;
960
end;
1030
end;
961
 
1031
 
962
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
1032
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
963
var
1033
var
964
  r: integer;
1034
  r: integer;
-
 
1035
resourcestring
-
 
1036
  SWantToSave = 'Do you want to save?';
965
begin
1037
begin
966
  if SynEdit1.Modified then
1038
  if SynEdit1.Modified then
967
  begin
1039
  begin
968
    if (ParamStr(1) <> '') or (FSaveAsFilename <> '') then
1040
    if (ParamStr(1) <> '') or (FSaveAsFilename <> '') then
969
    begin
1041
    begin
970
      r := MessageDlg('Do you want to save?', mtConfirmation, mbYesNoCancel, 0);
1042
      r := MessageDlg(SWantToSave, mtConfirmation, mbYesNoCancel, 0);
971
      if r = mrCancel then
1043
      if r = mrCancel then
972
      begin
1044
      begin
973
        CanClose := false;
1045
        CanClose := false;
974
        Exit;
1046
        Exit;
975
      end
1047
      end
976
      else if r = mrYes then
1048
      else if r = mrYes then
977
      begin
1049
      begin
978
        ActionSave.Execute;
1050
        ActionSave.Execute;
979
        CanClose := true;
1051
        CanClose := true;
980
      end;
1052
      end;
981
    end
1053
    end
982
    else
1054
    else
983
    begin
1055
    begin
984
      ActionSave.Execute;
1056
      ActionSave.Execute;
985
      CanClose := true;
1057
      CanClose := true;
986
    end;
1058
    end;
987
  end;
1059
  end;
988
end;
1060
end;
989
 
1061
 
990
procedure TForm1.FormCreate(Sender: TObject);
1062
procedure TForm1.FormCreate(Sender: TObject);
991
var
1063
var
992
  exeDir: string;
1064
  exeDir: string;
993
  sScrapFile: string;
1065
  sScrapFile: string;
994
begin
1066
begin
995
  HlpPrevPageIndex := -1;
1067
  HlpPrevPageIndex := -1;
996
  CurSearchTerm := '';
1068
  CurSearchTerm := '';
997
  sScrapFile := GetScrapFile;
1069
  sScrapFile := GetScrapFile;
998
  Caption := Caption + ' - ' + sScrapFile;
1070
  Caption := Caption + ' - ' + sScrapFile;
999
  Application.Title := Format('%s - FastPHP', [ExtractFileName(sScrapFile)]);
1071
  Application.Title := Format('%s - FastPHP', [ExtractFileName(sScrapFile)]); // do not translate!
1000
  SrcRep := TSynEditFindReplace.Create(self);
1072
  SrcRep := TSynEditFindReplace.Create(self);
1001
  SrcRep.Editor := SynEdit1;
1073
  SrcRep.Editor := SynEdit1;
1002
  SynEdit1.Gutter.Gradient := HighColorWindows;
1074
  SynEdit1.Gutter.Gradient := HighColorWindows;
1003
 
1075
 
1004
  Screen.Cursors[crMouseGutter] := LoadCursor(hInstance, 'MOUSEGUTTER');
1076
  Screen.Cursors[crMouseGutter] := LoadCursor(hInstance, 'MOUSEGUTTER');
1005
  SynEdit1.Gutter.Cursor := crMouseGutter;
1077
  SynEdit1.Gutter.Cursor := crMouseGutter;
1006
 
1078
 
1007
  exeDir := IncludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0)));
1079
  exeDir := IncludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0)));
1008
  if FileExists(exeDir + 'codeexplorer.bmp') then ImageList1.LoadAndSplitImages(exeDir + 'codeexplorer.bmp');
1080
  if FileExists(exeDir + 'codeexplorer.bmp') then ImageList1.LoadAndSplitImages(exeDir + 'codeexplorer.bmp');
1009
 
1081
 
1010
  FileModLast := FileAge(sScrapFile);
1082
  FileModLast := FileAge(sScrapFile);
1011
  FileModTimer.Enabled := True;
1083
  FileModTimer.Enabled := True;
1012
end;
1084
end;
1013
 
1085
 
1014
procedure TForm1.FormDestroy(Sender: TObject);
1086
procedure TForm1.FormDestroy(Sender: TObject);
1015
begin
1087
begin
1016
  if Assigned(ChmIndex) then
1088
  if Assigned(ChmIndex) then
1017
  begin
1089
  begin
1018
    FreeAndNil(ChmIndex);
1090
    FreeAndNil(ChmIndex);
1019
  end;
1091
  end;
1020
  FreeAndNil(SrcRep);
1092
  FreeAndNil(SrcRep);
1021
 
1093
 
1022
  if hMutex <> 0 then CloseHandle(hMutex); // Note: ReleaseMutex does not work as expected!
1094
  if hMutex <> 0 then CloseHandle(hMutex); // Note: ReleaseMutex does not work as expected!
1023
 
1095
 
1024
  if Assigned(codeExplorer) then
1096
  if Assigned(codeExplorer) then
1025
  begin
1097
  begin
1026
    codeExplorer.Terminate;
1098
    codeExplorer.Terminate;
1027
    codeExplorer.WaitFor;
1099
    codeExplorer.WaitFor;
1028
    FreeAndNil(codeExplorer);
1100
    FreeAndNil(codeExplorer);
1029
  end;
1101
  end;
1030
end;
1102
end;
1031
 
1103
 
1032
var
-
 
1033
  FormShowRanOnce: boolean;
-
 
1034
procedure TForm1.FormShow(Sender: TObject);
1104
procedure TForm1.FormShow(Sender: TObject);
1035
var
1105
var
1036
  ScrapFile: string;
1106
  ScrapFile: string;
1037
  tmpFontSize: integer;
1107
  tmpFontSize: integer;
1038
  opts: TSynEditorOptions;
1108
  opts: TSynEditorOptions;
-
 
1109
resourcestring
-
 
1110
  SFileAlreadyOpen = 'File "%s" is alrady open!';
1039
begin
1111
begin
1040
  if FormShowRanOnce then exit; // If the theme is changed from normal to dark, OnShow will be called another time
1112
  if FormShowRanOnce then exit; // If the theme is changed from normal to dark, OnShow will be called another time
1041
  FormShowRanOnce := true;
1113
  FormShowRanOnce := true;
1042
 
1114
 
1043
  ScrapFile := GetScrapFile;
1115
  ScrapFile := GetScrapFile;
1044
  if ScrapFile = '' then
1116
  if ScrapFile = '' then
1045
  begin
1117
  begin
1046
    Application.Terminate; // Close;
1118
    Application.Terminate; // Close;
1047
    exit;
1119
    exit;
1048
  end;
1120
  end;
1049
 
1121
 
1050
  opts := SynEdit1.Options;
1122
  opts := SynEdit1.Options;
1051
  if TFastPHPConfig.SpecialChars then
1123
  if TFastPHPConfig.SpecialChars then
1052
  begin
1124
  begin
1053
    BtnSpecialChars.Picture.Assign(BtnSpecialCharsOn.Picture);
1125
    BtnSpecialChars.Picture.Assign(BtnSpecialCharsOn.Picture);
1054
    Include(opts, eoShowSpecialChars);
1126
    Include(opts, eoShowSpecialChars);
1055
  end
1127
  end
1056
  else
1128
  else
1057
  begin
1129
  begin
1058
    BtnSpecialChars.Picture.Assign(BtnSpecialCharsOff.Picture);
1130
    BtnSpecialChars.Picture.Assign(BtnSpecialCharsOff.Picture);
1059
    Exclude(opts, eoShowSpecialChars);
1131
    Exclude(opts, eoShowSpecialChars);
1060
  end;
1132
  end;
1061
  SynEdit1.Options := opts;
1133
  SynEdit1.Options := opts;
1062
 
1134
 
1063
  if FileExists(ScrapFile) then
1135
  if FileExists(ScrapFile) then
1064
  begin
1136
  begin
1065
    if hMutex = 0 then
1137
    if hMutex = 0 then
1066
    begin
1138
    begin
1067
      hMutex := CreateMutex(nil, True, PChar('FastPHP'+md5(UpperCase(ScrapFile))));
1139
      hMutex := CreateMutex(nil, True, PChar('FastPHP'+md5(UpperCase(ScrapFile))));
1068
      if GetLastError = ERROR_ALREADY_EXISTS then
1140
      if GetLastError = ERROR_ALREADY_EXISTS then
1069
      begin
1141
      begin
1070
        // TODO: It would be great if the window of that FastPHP instance would switched to foreground
1142
        // TODO: It would be great if the window of that FastPHP instance would switched to foreground
1071
        ShowMessageFmt('File "%s" is alrady open!', [ScrapFile]);
1143
        ShowMessageFmt(SFileAlreadyOpen, [ScrapFile]);
1072
        Close;
1144
        Close;
1073
      end;
1145
      end;
1074
 
1146
 
1075
      SynEdit1.Lines.LoadFromFile(ScrapFile);
1147
      SynEdit1.Lines.LoadFromFile(ScrapFile);
1076
    end;
1148
    end;
1077
  end
1149
  end
1078
  else
1150
  else
1079
    SynEdit1.Lines.Clear;
1151
    SynEdit1.Lines.Clear;
1080
 
1152
 
1081
  PageControl1.ActivePage := PlaintextTabSheet;
1153
  PageControl1.ActivePage := PlaintextTabSheet;
1082
 
1154
 
1083
  PageControl2.ActivePage := CodeTabsheet;
1155
  PageControl2.ActivePage := CodeTabsheet;
1084
  HelpTabsheet.TabVisible := false;
1156
  HelpTabsheet.TabVisible := false;
1085
 
1157
 
1086
  tmpFontSize := TFastPHPConfig.FontSize;
1158
  tmpFontSize := TFastPHPConfig.FontSize;
1087
  if tmpFontSize <> -1 then SynEdit1.Font.Size := tmpFontSize;
1159
  if tmpFontSize <> -1 then SynEdit1.Font.Size := tmpFontSize;
1088
  SynEdit1.SetFocus;
1160
  SynEdit1.SetFocus;
1089
 
1161
 
1090
  DoubleBuffered := true;
1162
  DoubleBuffered := true;
1091
  StartCodeExplorer;
1163
  StartCodeExplorer;
1092
 
1164
 
1093
  DragAcceptFiles(Handle, True);
1165
  DragAcceptFiles(Handle, True);
1094
 
1166
 
1095
  StartupTimer.Enabled := true;
1167
  StartupTimer.Enabled := true;
1096
end;
1168
end;
1097
 
1169
 
1098
procedure TForm1.Save1Click(Sender: TObject);
-
 
1099
begin
-
 
1100
  Button7.Click;
-
 
1101
end;
-
 
1102
 
-
 
1103
procedure TForm1.Saveas1Click(Sender: TObject);
-
 
1104
var
-
 
1105
  hMutexNew: THandle;
-
 
1106
begin
-
 
1107
  if SaveDialog1.Execute then
-
 
1108
  begin
-
 
1109
    {$REGION 'Switch mutex'}
-
 
1110
    hMutexNew := CreateMutex(nil, True, PChar('FastPHP'+md5(UpperCase(SaveDialog1.FileName))));
-
 
1111
    if GetLastError = ERROR_ALREADY_EXISTS then
-
 
1112
    begin
-
 
1113
      ShowMessageFmt('Cannot save because file "%s", because it is alrady open in another FastPHP window!', [SaveDialog1.FileName]);
-
 
1114
      Close;
-
 
1115
    end;
-
 
1116
 
-
 
1117
    if hMutex <> 0 then CloseHandle(hMutex); // Note: ReleaseMutex does not work as expected!
-
 
1118
    hMutex := hMutexNew;
-
 
1119
    {$ENDREGION}
-
 
1120
 
-
 
1121
    FSaveAsFilename := SaveDialog1.FileName;
-
 
1122
    Caption := Copy(Caption, 1, Pos(' - ', Caption)-1) + ' - ' + FSaveAsFilename;
-
 
1123
    Application.Title := Format('%s - FastPHP', [ExtractFileName(FSaveAsFilename)]);
-
 
1124
    Button7.Click;
-
 
1125
  end;
-
 
1126
end;
-
 
1127
 
-
 
1128
procedure TForm1.SaveToFile(filename: string);
1170
procedure TForm1.SaveToFile(filename: string);
1129
var
1171
var
1130
  ss: TStringStream;
1172
  ss: TStringStream;
1131
  ms: TMemoryStream;
1173
  ms: TMemoryStream;
1132
  fs: TFileStream;
1174
  fs: TFileStream;
1133
  eolStyle: string;
1175
  eolStyle: string;
1134
  str: string;
1176
  str: string;
1135
begin
1177
begin
1136
  FileModTimer.Enabled := false;
1178
  FileModTimer.Enabled := false;
1137
 
1179
 
1138
  ms := TMemoryStream.Create;
1180
  ms := TMemoryStream.Create;
1139
  ss := TStringStream.Create('');
1181
  ss := TStringStream.Create('');
1140
  fs := TFileStream.Create(filename, fmCreate);
1182
  fs := TFileStream.Create(filename, fmCreate);
1141
  try
1183
  try
1142
    // Save everything in a memory stream and then to a string
1184
    // Save everything in a memory stream and then to a string
1143
    // in comparison to "str := SynEdit1.Lines.Text;",
1185
    // in comparison to "str := SynEdit1.Lines.Text;",
1144
    // This approach should preserve LF / CRLF line endings
1186
    // This approach should preserve LF / CRLF line endings
1145
    SynEdit1.Lines.SaveToStream(ms);
1187
    SynEdit1.Lines.SaveToStream(ms);
1146
    ms.Position := 0;
1188
    ms.Position := 0;
1147
    ss.CopyFrom(ms, ms.Size);
1189
    ss.CopyFrom(ms, ms.Size);
1148
    ss.Position := 0;
1190
    ss.Position := 0;
1149
    str := ss.ReadString(ss.Size);
1191
    str := ss.ReadString(ss.Size);
1150
    ss.Size := 0; // clear string-stream, because we need it later again
1192
    ss.Size := 0; // clear string-stream, because we need it later again
1151
 
1193
 
1152
    // Detect current line-endings
1194
    // Detect current line-endings
1153
    if Copy(str, 1, 2) = '#!' then
1195
    if Copy(str, 1, 2) = '#!' then
1154
    begin
1196
    begin
1155
      // Shebang. Use ONLY Linux LF
1197
      // Shebang. Use ONLY Linux LF
1156
      str := StringReplace(str, #13#10, #10, [rfReplaceAll]);
1198
      str := StringReplace(str, #13#10, #10, [rfReplaceAll]);
1157
      eolStyle := #10 // Linux LF
1199
      eolStyle := #10 // Linux LF
1158
    end
1200
    end
1159
    else
1201
    else
1160
    begin
1202
    begin
1161
      if Pos(#13#10, str) > 0 then
1203
      if Pos(#13#10, str) > 0 then
1162
        eolStyle := #13#10 // Windows CRLF
1204
        eolStyle := #13#10 // Windows CRLF
1163
      else if Pos(#10, str) > 0 then
1205
      else if Pos(#10, str) > 0 then
1164
        eolStyle := #10 // Linux LF
1206
        eolStyle := #10 // Linux LF
1165
      else
1207
      else
1166
      begin
1208
      begin
1167
        if DefaultTextLineBreakStyle = tlbsLF then
1209
        if DefaultTextLineBreakStyle = tlbsLF then
1168
          eolStyle := #10 // Linux LF
1210
          eolStyle := #10 // Linux LF
1169
        else if DefaultTextLineBreakStyle = tlbsCRLF then
1211
        else if DefaultTextLineBreakStyle = tlbsCRLF then
1170
          eolStyle := #13#10 // Windows CRLF
1212
          eolStyle := #13#10 // Windows CRLF
1171
        //else if DefaultTextLineBreakStyle = tlbsCR then
1213
        //else if DefaultTextLineBreakStyle = tlbsCR then
1172
        //  eolStyle := #13 // Old Mac CR
1214
        //  eolStyle := #13 // Old Mac CR
1173
        else
1215
        else
1174
          eolStyle := #13#10; // (Should not happen)
1216
          eolStyle := #13#10; // (Should not happen)
1175
      end;
1217
      end;
1176
    end;
1218
    end;
1177
 
1219
 
1178
    // Unitfy line-endings
1220
    // Unitfy line-endings
1179
    str := StringReplace(str, #13#10, eolStyle, [rfReplaceAll]);
1221
    str := StringReplace(str, #13#10, eolStyle, [rfReplaceAll]);
1180
    str := StringReplace(str, #10, eolStyle, [rfReplaceAll]);
1222
    str := StringReplace(str, #10, eolStyle, [rfReplaceAll]);
1181
    str := StringReplace(str, #13, '', [rfReplaceAll]);
1223
    str := StringReplace(str, #13, '', [rfReplaceAll]);
1182
 
1224
 
1183
    // Replace all trailing linebreaks by a single line break
1225
    // Replace all trailing linebreaks by a single line break
1184
    // Note: Removing all line breaks is not good, since Linux's "nano" will
1226
    // Note: Removing all line breaks is not good, since Linux's "nano" will
1185
    //       re-add a linebreak at the end of the file
1227
    //       re-add a linebreak at the end of the file
1186
    str := TrimRight(str) + eolStyle;
1228
    str := TrimRight(str) + eolStyle;
1187
 
1229
 
1188
    // Old versions of Delphi/SynEdit write an UTF-8 BOM, which makes problems
1230
    // Old versions of Delphi/SynEdit write an UTF-8 BOM, which makes problems
1189
    // e.g. with AJAX handlers (because AJAX reponses must not have a BOM).
1231
    // e.g. with AJAX handlers (because AJAX reponses must not have a BOM).
1190
    // So we try to avoid that.
1232
    // So we try to avoid that.
1191
    // Note that the output is still UTF-8 encoded if the input file was UTF-8 encoded
1233
    // Note that the output is still UTF-8 encoded if the input file was UTF-8 encoded
1192
    if Copy(str,1,3) = #$EF#$BB#$BF then Delete(str, 1, 3);
1234
    if Copy(str,1,3) = #$EF#$BB#$BF then Delete(str, 1, 3);
1193
 
1235
 
1194
    // Now save to the file
1236
    // Now save to the file
1195
    ss.WriteString(str);
1237
    ss.WriteString(str);
1196
    ss.Position := 0;
1238
    ss.Position := 0;
1197
    fs.CopyFrom(ss, ss.Size-ss.Position);
1239
    fs.CopyFrom(ss, ss.Size-ss.Position);
1198
  finally
1240
  finally
1199
    FreeAndNil(ms);
1241
    FreeAndNil(ms);
1200
    FreeAndNil(ss);
1242
    FreeAndNil(ss);
1201
    FreeAndNil(fs);
1243
    FreeAndNil(fs);
1202
  end;
1244
  end;
1203
 
1245
 
1204
  FileModLast := FileAge(GetScrapFile);
1246
  FileModLast := FileAge(GetScrapFile);
1205
  FileModTimer.Enabled := True;
1247
  FileModTimer.Enabled := True;
1206
end;
1248
end;
1207
 
1249
 
1208
procedure TForm1.StartCodeExplorer;
1250
procedure TForm1.StartCodeExplorer;
1209
begin
1251
begin
1210
  codeExplorer := TRunCodeExplorer.Create(true);
1252
  codeExplorer := TRunCodeExplorer.Create(true);
1211
  codeExplorer.InputRequestCallback := InputRequestCallback;
1253
  codeExplorer.InputRequestCallback := InputRequestCallback;
1212
  codeExplorer.OutputNotifyCallback := OutputNotifyCallback;
1254
  codeExplorer.OutputNotifyCallback := OutputNotifyCallback;
1213
  codeExplorer.PhpExe := GetPHPExe;
1255
  codeExplorer.PhpExe := GetPHPExe;
1214
  codeExplorer.PhpFile := IncludeTrailingPathDelimiter(ExtractFileDir(Application.ExeName)) + 'codeexplorer.php'; // GetScrapFile;
1256
  codeExplorer.PhpFile := IncludeTrailingPathDelimiter(ExtractFileDir(Application.ExeName)) + 'codeexplorer.php'; // GetScrapFile;
1215
  codeExplorer.WorkDir := ExtractFileDir(Application.ExeName);
1257
  codeExplorer.WorkDir := ExtractFileDir(Application.ExeName);
1216
  codeExplorer.Resume;
1258
  codeExplorer.Resume;
1217
end;
1259
end;
1218
 
1260
 
1219
procedure TForm1.StartUpTimerTimer(Sender: TObject);
1261
procedure TForm1.StartUpTimerTimer(Sender: TObject);
1220
begin
1262
begin
1221
  StartupTimer.Enabled := false;
1263
  StartupTimer.Enabled := false;
1222
 
1264
 
1223
  // We need this timer because we cannot change the Theme during OnShow,
1265
  // We need this timer because we cannot change the Theme during OnShow,
1224
  // because the Delphi VCL Theme is buggy!
1266
  // because the Delphi VCL Theme is buggy!
1225
 
1267
 
1226
  if TFastPHPConfig.DarkTheme then
1268
  if TFastPHPConfig.DarkTheme then
1227
  begin
1269
  begin
1228
    BtnLight.Picture.Assign(BtnLightOff.Picture);
1270
    BtnLight.Picture.Assign(BtnLightOff.Picture);
1229
    Theme_Dark;
1271
    Theme_Dark;
1230
  end
1272
  end
1231
  else
1273
  else
1232
  begin
1274
  begin
1233
    BtnLight.Picture.Assign(BtnLightOn.Picture);
1275
    BtnLight.Picture.Assign(BtnLightOn.Picture);
1234
    Theme_Light;
1276
    Theme_Light;
1235
  end;
1277
  end;
1236
end;
1278
end;
1237
 
1279
 
1238
function TForm1.GetScrapFile: string;
1280
function TForm1.GetScrapFile: string;
1239
var
1281
var
1240
  tmpPath: string;
1282
  tmpPath: string;
-
 
1283
resourcestring
-
 
1284
  SFileDoesNotExistsCreate = 'File %s does not exist. Create it?';
-
 
1285
  SPathDoesNotExistTryAgain = 'Path does not exist! Please try again.';
1241
begin
1286
begin
1242
  if FSaveAsFilename <> '' then
1287
  if FSaveAsFilename <> '' then
1243
  begin
1288
  begin
1244
    result := FSaveAsFilename;
1289
    result := FSaveAsFilename;
1245
    exit;
1290
    exit;
1246
  end;
1291
  end;
1247
 
1292
 
1248
  if FScrapFile <> '' then
1293
  if FScrapFile <> '' then
1249
  begin
1294
  begin
1250
    result := FScrapFile;
1295
    result := FScrapFile;
1251
    exit;
1296
    exit;
1252
  end;
1297
  end;
1253
 
1298
 
1254
  if ParamStr(1) <> '' then
1299
  if ParamStr(1) <> '' then
1255
  begin
1300
  begin
1256
    // Program was started with a filename
1301
    // Program was started with a filename
1257
 
1302
 
1258
    result := ParamStr(1);
1303
    result := ParamStr(1);
1259
 
1304
 
1260
    if not FileExists(result) then
1305
    if not FileExists(result) then
1261
    begin
1306
    begin
1262
      case MessageDlg(Format('File %s does not exist. Create it?', [result]), mtConfirmation, mbYesNoCancel, 0) of
1307
      case MessageDlg(Format(SFileDoesNotExistsCreate, [result]), mtConfirmation, mbYesNoCancel, 0) of
1263
        mrYes:
1308
        mrYes:
1264
          try
1309
          try
1265
            SaveToFile(result);
1310
            SaveToFile(result);
1266
          except
1311
          except
1267
            on E: Exception do
1312
            on E: Exception do
1268
            begin
1313
            begin
1269
              MessageDlg(E.Message, mtError, [mbOk], 0);
1314
              MessageDlg(E.Message, mtError, [mbOk], 0);
1270
              Application.Terminate;
1315
              Application.Terminate;
1271
              result := '';
1316
              result := '';
1272
              exit;
1317
              exit;
1273
            end;
1318
            end;
1274
          end;
1319
          end;
1275
        mrNo:
1320
        mrNo:
1276
          begin
1321
          begin
1277
            Application.Terminate;
1322
            Application.Terminate;
1278
            result := '';
1323
            result := '';
1279
            exit;
1324
            exit;
1280
          end;
1325
          end;
1281
        mrCancel:
1326
        mrCancel:
1282
          begin
1327
          begin
1283
            Application.Terminate;
1328
            Application.Terminate;
1284
            result := '';
1329
            result := '';
1285
            exit;
1330
            exit;
1286
          end;
1331
          end;
1287
      end;
1332
      end;
1288
    end;
1333
    end;
1289
  end
1334
  end
1290
  else
1335
  else
1291
  begin
1336
  begin
1292
    // Program is started without filename -> use scrap file
1337
    // Program is started without filename -> use scrap file
1293
 
1338
 
1294
    result := TFastPHPConfig.ScrapFile;
1339
    result := TFastPHPConfig.ScrapFile;
1295
 
1340
 
1296
    if not FileExists(result) then
1341
    if not FileExists(result) then
1297
    begin
1342
    begin
1298
      repeat
1343
      repeat
1299
        {$REGION 'Determinate opendialog initial directory'}
1344
        {$REGION 'Determinate opendialog initial directory'}
1300
        if result <> '' then
1345
        if result <> '' then
1301
        begin
1346
        begin
1302
          tmpPath := ExtractFilePath(result);
1347
          tmpPath := ExtractFilePath(result);
1303
          if DirectoryExists(tmpPath) then
1348
          if DirectoryExists(tmpPath) then
1304
          begin
1349
          begin
1305
            OpenDialog3.InitialDir := tmpPath;
1350
            OpenDialog3.InitialDir := tmpPath;
1306
            OpenDialog3.FileName := Result;
1351
            OpenDialog3.FileName := Result;
1307
          end
1352
          end
1308
          else
1353
          else
1309
          begin
1354
          begin
1310
            OpenDialog3.InitialDir := GetMyDocumentsFolder;
1355
            OpenDialog3.InitialDir := GetMyDocumentsFolder;
1311
          end;
1356
          end;
1312
        end
1357
        end
1313
        else
1358
        else
1314
        begin
1359
        begin
1315
          OpenDialog3.InitialDir := GetMyDocumentsFolder;
1360
          OpenDialog3.InitialDir := GetMyDocumentsFolder;
1316
        end;
1361
        end;
1317
        {$ENDREGION}
1362
        {$ENDREGION}
1318
 
1363
 
1319
        if not OpenDialog3.Execute then
1364
        if not OpenDialog3.Execute then
1320
        begin
1365
        begin
1321
          Application.Terminate;
1366
          Application.Terminate;
1322
          result := '';
1367
          result := '';
1323
          exit;
1368
          exit;
1324
        end;
1369
        end;
1325
 
1370
 
1326
        if not DirectoryExists(ExtractFilePath(OpenDialog3.FileName)) then
1371
        if not DirectoryExists(ExtractFilePath(OpenDialog3.FileName)) then
1327
        begin
1372
        begin
1328
          MessageDlg('Path does not exist! Please try again.', mtWarning, [mbOk], 0);
1373
          MessageDlg(SPathDoesNotExistTryAgain, mtWarning, [mbOk], 0);
1329
        end
1374
        end
1330
        else
1375
        else
1331
        begin
1376
        begin
1332
          result := OpenDialog3.FileName;
1377
          result := OpenDialog3.FileName;
1333
        end;
1378
        end;
1334
      until result <> '';
1379
      until result <> '';
1335
 
1380
 
1336
      if not FileExists(result) then
1381
      if not FileExists(result) then
1337
      begin
1382
      begin
1338
        try
1383
        try
1339
          // Try saving the file; check if we have permissions
1384
          // Try saving the file; check if we have permissions
1340
          //SynEdit1.Lines.Clear;
1385
          //SynEdit1.Lines.Clear;
1341
          SaveToFile(result);
1386
          SaveToFile(result);
1342
        except
1387
        except
1343
          on E: Exception do
1388
          on E: Exception do
1344
          begin
1389
          begin
1345
            MessageDlg(E.Message, mtError, [mbOk], 0);
1390
            MessageDlg(E.Message, mtError, [mbOk], 0);
1346
            Application.Terminate;
1391
            Application.Terminate;
1347
            result := '';
1392
            result := '';
1348
            exit;
1393
            exit;
1349
          end;
1394
          end;
1350
        end;
1395
        end;
1351
      end;
1396
      end;
1352
 
1397
 
1353
      TFastPHPConfig.ScrapFile := result;
1398
      TFastPHPConfig.ScrapFile := result;
1354
      FScrapFile := result;
1399
      FScrapFile := result;
1355
    end;
1400
    end;
1356
  end;
1401
  end;
1357
end;
1402
end;
1358
 
1403
 
1359
procedure TForm1.Help;
1404
procedure TForm1.Help;
1360
var
1405
var
1361
  IndexFile, chmFile, w, OriginalWord, url: string;
1406
  IndexFile, chmFile, w, OriginalWord, url: string;
1362
  internalHtmlFile: string;
1407
  internalHtmlFile: string;
-
 
1408
resourcestring
-
 
1409
  SChmFileNotAValidPHPDocumentation = 'The CHM file is not a valid PHP documentation. Cannot use help.';
-
 
1410
  SUnknownErrorCannotUseHelp = 'Unknown error. Cannot use help.';
-
 
1411
  SNoHelpAvailable = 'No help for "%s" available';
1363
begin
1412
begin
1364
  if not Assigned(ChmIndex) then
1413
  if not Assigned(ChmIndex) then
1365
  begin
1414
  begin
1366
    IndexFile := TFastPHPConfig.HelpIndex;
1415
    IndexFile := TFastPHPConfig.HelpIndex;
1367
    IndexFile := ChangeFileExt(IndexFile, '.ini'); // Just to be sure. Maybe someone wrote manually the ".chm" file in there
1416
    IndexFile := ChangeFileExt(IndexFile, '.ini'); // Just to be sure. Maybe someone wrote manually the ".chm" file in there
1368
    if FileExists(IndexFile) then
1417
    if FileExists(IndexFile) then
1369
    begin
1418
    begin
1370
      ChmIndex := TMemIniFile.Create(IndexFile);
1419
      ChmIndex := TMemIniFile.Create(IndexFile);
1371
    end;
1420
    end;
1372
  end;
1421
  end;
1373
 
1422
 
1374
  if Assigned(ChmIndex) then
1423
  if Assigned(ChmIndex) then
1375
  begin
1424
  begin
1376
    IndexFile := TFastPHPConfig.HelpIndex;
1425
    IndexFile := TFastPHPConfig.HelpIndex;
1377
    // We don't check if IndexFile still exists. It is not important since we have ChmIndex pre-loaded in memory
1426
    // We don't check if IndexFile still exists. It is not important since we have ChmIndex pre-loaded in memory
1378
 
1427
 
1379
    chmFile := ChangeFileExt(IndexFile, '.chm');
1428
    chmFile := ChangeFileExt(IndexFile, '.chm');
1380
    if not FileExists(chmFile) then
1429
    if not FileExists(chmFile) then
1381
    begin
1430
    begin
1382
      FreeAndNil(ChmIndex);
1431
      FreeAndNil(ChmIndex);
1383
    end;
1432
    end;
1384
  end;
1433
  end;
1385
 
1434
 
1386
  if not Assigned(ChmIndex) then
1435
  if not Assigned(ChmIndex) then
1387
  begin
1436
  begin
1388
    if not OpenDialog1.Execute then exit;
1437
    if not OpenDialog1.Execute then exit;
1389
 
1438
 
1390
    chmFile := OpenDialog1.FileName;
1439
    chmFile := OpenDialog1.FileName;
1391
    if not FileExists(chmFile) then exit;
1440
    if not FileExists(chmFile) then exit;
1392
 
1441
 
1393
    IndexFile := ChangeFileExt(chmFile, '.ini');
1442
    IndexFile := ChangeFileExt(chmFile, '.ini');
1394
 
1443
 
1395
    if not FileExists(IndexFile) then
1444
    if not FileExists(IndexFile) then
1396
    begin
1445
    begin
1397
      Panel1.Align := alClient;
1446
      Panel1.Align := alClient;
1398
      Panel1.Visible := true;
1447
      Panel1.Visible := true;
1399
      Panel1.BringToFront;
1448
      Panel1.BringToFront;
1400
      Screen.Cursor := crHourGlass;
1449
      Screen.Cursor := crHourGlass;
1401
      Application.ProcessMessages;
1450
      Application.ProcessMessages;
1402
      try
1451
      try
1403
        if not ParseCHM(chmFile) then
1452
        if not ParseCHM(chmFile) then
1404
        begin
1453
        begin
1405
          MessageDlg('The CHM file is not a valid PHP documentation. Cannot use help.', mtError, [mbOk], 0);
1454
          MessageDlg(SChmFileNotAValidPHPDocumentation, mtError, [mbOk], 0);
1406
          exit;
1455
          exit;
1407
        end;
1456
        end;
1408
      finally
1457
      finally
1409
        Screen.Cursor := crDefault;
1458
        Screen.Cursor := crDefault;
1410
        Panel1.Visible := false;
1459
        Panel1.Visible := false;
1411
      end;
1460
      end;
1412
 
1461
 
1413
      if not FileExists(IndexFile) then
1462
      if not FileExists(IndexFile) then
1414
      begin
1463
      begin
1415
        MessageDlg('Unknown error. Cannot use help.', mtError, [mbOk], 0);
1464
        MessageDlg(SUnknownErrorCannotUseHelp, mtError, [mbOk], 0);
1416
        exit;
1465
        exit;
1417
      end;
1466
      end;
1418
    end;
1467
    end;
1419
 
1468
 
1420
    TFastPHPConfig.HelpIndex := IndexFile;
1469
    TFastPHPConfig.HelpIndex := IndexFile;
1421
 
1470
 
1422
    ChmIndex := TMemIniFile.Create(IndexFile);
1471
    ChmIndex := TMemIniFile.Create(IndexFile);
1423
  end;
1472
  end;
1424
 
1473
 
1425
  w := GetWordUnderCaret(SynEdit1);
1474
  w := GetWordUnderCaret(SynEdit1);
1426
  if w = '' then exit;
1475
  if w = '' then exit;
1427
  {$IFDEF UNICODE}
1476
  {$IFDEF UNICODE}
1428
  if CharInSet(w[1], ['0'..'9']) then exit;
1477
  if CharInSet(w[1], ['0'..'9']) then exit;
1429
  {$ELSE}
1478
  {$ELSE}
1430
  if w[1] in ['0'..'9'] then exit;
1479
  if w[1] in ['0'..'9'] then exit;
1431
  {$ENDIF}
1480
  {$ENDIF}
1432
 
1481
 
1433
  Originalword := w;
1482
  Originalword := w;
1434
//  w := StringReplace(w, '_', '-', [rfReplaceAll]);
1483
//  w := StringReplace(w, '_', '-', [rfReplaceAll]);
1435
  w := LowerCase(w);
1484
  w := LowerCase(w);
1436
  CurSearchTerm := w;
1485
  CurSearchTerm := w;
1437
 
1486
 
1438
  internalHtmlFile := ChmIndex.ReadString('function', CurSearchTerm, '');
1487
  internalHtmlFile := ChmIndex.ReadString('function', CurSearchTerm, ''); // do not translate
1439
  if internalHtmlFile = '' then
1488
  if internalHtmlFile = '' then
1440
    internalHtmlFile := ChmIndex.ReadString('_HelpWords_', CurSearchTerm, '');
1489
    internalHtmlFile := ChmIndex.ReadString('_HelpWords_', CurSearchTerm, ''); // do not translate
1441
  if internalHtmlFile = '' then
1490
  if internalHtmlFile = '' then
1442
  begin
1491
  begin
1443
    HelpTabsheet.TabVisible := false;
1492
    HelpTabsheet.TabVisible := false;
1444
    HlpPrevPageIndex := -1;
1493
    HlpPrevPageIndex := -1;
1445
    ShowMessageFmt('No help for "%s" available', [Originalword]);
1494
    ShowMessageFmt(SNoHelpAvailable, [Originalword]);
1446
    Exit;
1495
    Exit;
1447
  end;
1496
  end;
1448
 
1497
 
1449
  url := 'mk:@MSITStore:'+ChmFile+'::'+internalHtmlFile;
1498
  url := 'mk:@MSITStore:'+ChmFile+'::'+internalHtmlFile;
1450
 
1499
 
1451
  HlpPrevPageIndex := PageControl2.ActivePageIndex; // Return by pressing ESC
1500
  HlpPrevPageIndex := PageControl2.ActivePageIndex; // Return by pressing ESC
1452
  HelpTabsheet.TabVisible := true;
1501
  HelpTabsheet.TabVisible := true;
1453
  PageControl2.ActivePage := HelpTabsheet;
1502
  PageControl2.ActivePage := HelpTabsheet;
1454
  WebBrowser2.Navigate(url);
1503
  WebBrowser2.Navigate(url);
1455
  WebBrowser2.Wait;
1504
  WebBrowser2.Wait;
1456
end;
1505
end;
1457
 
1506
 
1458
procedure TForm1.GotoLineNo(LineNo:integer);
1507
procedure TForm1.GotoLineNo(LineNo:integer);
1459
var
1508
var
1460
  line: string;
1509
  line: string;
1461
  i: integer;
1510
  i: integer;
1462
begin
1511
begin
1463
  SynEdit1.GotoLineAndCenter(LineNo);
1512
  SynEdit1.GotoLineAndCenter(LineNo);
1464
 
1513
 
1465
  // Skip indent
1514
  // Skip indent
1466
  line := SynEdit1.Lines[SynEdit1.CaretY];
1515
  line := SynEdit1.Lines[SynEdit1.CaretY];
1467
  for i := 1 to Length(line) do
1516
  for i := 1 to Length(line) do
1468
  begin
1517
  begin
1469
    {$IFDEF UNICODE}
1518
    {$IFDEF UNICODE}
1470
    if not CharInSet(line[i], [' ', #9]) then
1519
    if not CharInSet(line[i], [' ', #9]) then
1471
    {$ELSE}
1520
    {$ELSE}
1472
    if not (line[i] in [' ', #9]) then
1521
    if not (line[i] in [' ', #9]) then
1473
    {$ENDIF}
1522
    {$ENDIF}
1474
    begin
1523
    begin
1475
      SynEdit1.CaretX := i-1;
1524
      SynEdit1.CaretX := i-1;
1476
      break;
1525
      break;
1477
    end;
1526
    end;
1478
  end;
1527
  end;
1479
 
1528
 
1480
  PageControl2.ActivePage := CodeTabsheet;
1529
  PageControl2.ActivePage := CodeTabsheet;
1481
  if SynEdit1.CanFocus then SynEdit1.SetFocus;
1530
  if SynEdit1.CanFocus then SynEdit1.SetFocus;
1482
end;
1531
end;
1483
 
1532
 
1484
procedure TForm1.GotoPHPdir1Click(Sender: TObject);
-
 
1485
var
-
 
1486
  phpExe: string;
-
 
1487
begin
-
 
1488
  phpExe := GetPHPExe;
-
 
1489
  if phpExe <> '' then
-
 
1490
    ShellExecute(Handle, 'open', 'explorer.exe', PChar(ExtractFilePath(phpExe)), '', SW_NORMAL);
-
 
1491
end;
-
 
1492
 
-
 
1493
procedure TForm1.PageControl2Changing(Sender: TObject;
1533
procedure TForm1.PageControl2Changing(Sender: TObject;
1494
  var AllowChange: Boolean);
1534
  var AllowChange: Boolean);
1495
begin
1535
begin
1496
  if PageControl2.ActivePage = HelpTabsheet then
1536
  if PageControl2.ActivePage = HelpTabsheet then
1497
    HlpPrevPageIndex := -1
1537
    HlpPrevPageIndex := -1
1498
  else
1538
  else
1499
    HlpPrevPageIndex := PageControl2.ActivePageIndex;
1539
    HlpPrevPageIndex := PageControl2.ActivePageIndex;
1500
 
1540
 
1501
  AllowChange := true;
1541
  AllowChange := true;
1502
end;
1542
end;
1503
 
1543
 
1504
procedure TForm1.PHPShell1Click(Sender: TObject);
-
 
1505
var
-
 
1506
  phpExe: string;
-
 
1507
begin
-
 
1508
  phpExe := GetPHPExe;
-
 
1509
  if phpExe <> '' then
-
 
1510
    ShellExecute(Handle, 'open', PChar(phpExe), '-a', PChar(ExtractFilePath(phpExe)), SW_NORMAL);
-
 
1511
end;
-
 
1512
 
-
 
1513
procedure TForm1.Memo2DblClick(Sender: TObject);
1544
procedure TForm1.Memo2DblClick(Sender: TObject);
1514
var
1545
var
1515
  line: string;
1546
  line: string;
1516
 
1547
 
1517
  procedure _process(toFind: string);
1548
  procedure _process(toFind: string);
1518
  var
1549
  var
1519
    p, lineno: integer;
1550
    p, lineno: integer;
1520
  begin
1551
  begin
1521
    if FileSystemCaseSensitive then
1552
    if FileSystemCaseSensitive then
1522
      p := Pos(toFind, line)
1553
      p := Pos(toFind, line)
1523
    else
1554
    else
1524
      p := Pos(LowerCase(toFind), LowerCase(line));
1555
      p := Pos(LowerCase(toFind), LowerCase(line));
1525
    if p <> 0 then
1556
    if p <> 0 then
1526
    begin
1557
    begin
1527
      line := copy(line, p+length(toFind), 99);
1558
      line := copy(line, p+length(toFind), 99);
1528
      if not TryStrToInt(line, lineno) then exit;
1559
      if not TryStrToInt(line, lineno) then exit;
1529
      GotoLineNo(lineno);
1560
      GotoLineNo(lineno);
1530
    end;
1561
    end;
1531
  end;
1562
  end;
1532
 
1563
 
1533
begin
1564
begin
1534
  line := memo2.Lines.Strings[Memo2.CaretPos.Y];
1565
  line := memo2.Lines.Strings[Memo2.CaretPos.Y];
1535
 
1566
 
1536
  {$REGION 'Possibility 1: filename.php:lineno'}
1567
  {$REGION 'Possibility 1: filename.php:lineno'}
1537
  _process(ExtractFileName(GetScrapFile) + ':');
1568
  _process(ExtractFileName(GetScrapFile) + ':');
1538
  {$ENDREGION}
1569
  {$ENDREGION}
1539
 
1570
 
1540
  {$REGION 'Possibility 2: on line xx'}
1571
  {$REGION 'Possibility 2: on line xx'}
1541
  _process(ExtractFileName(GetScrapFile) + ' on line ');
1572
  _process(ExtractFileName(GetScrapFile) + ' on line '); // do not translate!
1542
  {$ENDREGION}
1573
  {$ENDREGION}
1543
end;
1574
end;
1544
 
1575
 
1545
procedure TForm1.Memo2KeyDown(Sender: TObject; var Key: Word;
1576
procedure TForm1.Memo2KeyDown(Sender: TObject; var Key: Word;
1546
  Shift: TShiftState);
1577
  Shift: TShiftState);
1547
begin
1578
begin
1548
  if ((ssCtrl in Shift) and (Key = 65)) then TMemo(Sender).SelectAll;
1579
  if ((ssCtrl in Shift) and (Key = 65)) then TMemo(Sender).SelectAll;
1549
end;
1580
end;
1550
 
1581
 
1551
function TForm1.MarkUpLineReference(cont: string): string;
1582
function TForm1.MarkUpLineReference(cont: string): string;
1552
 
1583
 
1553
  procedure _process(toFind: string);
1584
  procedure _process(toFind: string);
1554
  var
1585
  var
1555
    p, a, b: integer;
1586
    p, a, b: integer;
1556
    num: integer;
1587
    num: integer;
1557
    insert_a, insert_b: string;
1588
    insert_a, insert_b: string;
1558
  begin
1589
  begin
1559
    if FileSystemCaseSensitive then
1590
    if FileSystemCaseSensitive then
1560
      p := Pos(toFind, cont)
1591
      p := Pos(toFind, cont)
1561
    else
1592
    else
1562
      p := Pos(LowerCase(toFind), LowerCase(cont));
1593
      p := Pos(LowerCase(toFind), LowerCase(cont));
1563
    while p >= 1 do
1594
    while p >= 1 do
1564
    begin
1595
    begin
1565
      a := p;
1596
      a := p;
1566
      b := p + length(toFind);
1597
      b := p + length(toFind);
1567
      num := 0;
1598
      num := 0;
1568
      {$IFDEF UNICODE}
1599
      {$IFDEF UNICODE}
1569
      while CharInSet(cont[b], ['0'..'9']) do
1600
      while CharInSet(cont[b], ['0'..'9']) do
1570
      {$ELSE}
1601
      {$ELSE}
1571
      while cont[b] in ['0'..'9'] do
1602
      while cont[b] in ['0'..'9'] do
1572
      {$ENDIF}
1603
      {$ENDIF}
1573
      begin
1604
      begin
1574
        num := num*10 + StrToInt(cont[b]);
1605
        num := num*10 + StrToInt(cont[b]);
1575
        inc(b);
1606
        inc(b);
1576
      end;
1607
      end;
1577
 
1608
 
1578
      insert_b := '</a>';
1609
      insert_b := '</a>';
1579
      insert_a := '<a href="' + FASTPHP_GOTO_URI_PREFIX + IntToStr(num) + '">';
1610
      insert_a := '<a href="' + FASTPHP_GOTO_URI_PREFIX + IntToStr(num) + '">';
1580
 
1611
 
1581
      insert(insert_b, cont, b);
1612
      insert(insert_b, cont, b);
1582
      insert(insert_a, cont, a);
1613
      insert(insert_a, cont, a);
1583
 
1614
 
1584
      p := b + Length(insert_a) + Length(insert_b);
1615
      p := b + Length(insert_a) + Length(insert_b);
1585
 
1616
 
1586
      p := PosEx(toFind, cont, p+1);
1617
      p := PosEx(toFind, cont, p+1);
1587
    end;
1618
    end;
1588
  end;
1619
  end;
1589
 
1620
 
1590
begin
1621
begin
1591
  {$REGION 'Possibility 1: filename.php:lineno'}
1622
  {$REGION 'Possibility 1: filename.php:lineno'}
1592
  _process(ExtractFileName(GetScrapFile) + ':');
1623
  _process(ExtractFileName(GetScrapFile) + ':');
1593
  {$ENDREGION}
1624
  {$ENDREGION}
1594
 
1625
 
1595
  {$REGION 'Possibility 2: on line xx'}
1626
  {$REGION 'Possibility 2: on line xx'}
1596
  _process(ExtractFileName(GetScrapFile) + ' on line ');
1627
  _process(ExtractFileName(GetScrapFile) + ' on line '); // do not translate!
1597
  {$ENDREGION}
1628
  {$ENDREGION}
1598
 
1629
 
1599
  result := cont;
1630
  result := cont;
1600
end;
1631
end;
1601
 
1632
 
1602
function TForm1.InputRequestCallback(var data: AnsiString): boolean;
1633
function TForm1.InputRequestCallback(var data: AnsiString): boolean;
1603
begin
1634
begin
1604
  data := UTF8Encode(SynEdit1.Text);
1635
  data := UTF8Encode(SynEdit1.Text);
1605
  result := true;
1636
  result := true;
1606
end;
1637
end;
1607
 
1638
 
1608
function TForm1.IsThemeDark: boolean;
1639
function TForm1.IsThemeDark: boolean;
1609
begin
1640
begin
1610
  result := Assigned(TStyleManager.ActiveStyle) and (TStyleManager.ActiveStyle.Name<>'Windows');
1641
  result := Assigned(TStyleManager.ActiveStyle) and (TStyleManager.ActiveStyle.Name<>'Windows');
1611
end;
1642
end;
1612
 
1643
 
1613
function TForm1.OutputNotifyCallback(const data: AnsiString): boolean;
1644
function TForm1.OutputNotifyCallback(const data: AnsiString): boolean;
1614
begin
1645
begin
1615
  result := TreeView1.FillWithFastPHPData(data);
1646
  result := TreeView1.FillWithFastPHPData(string(data));
1616
end;
1647
end;
1617
 
1648
 
1618
end.
1649
end.
1619
 
1650