Subversion Repositories fastphp

Rev

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

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