Subversion Repositories fastphp

Rev

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

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