Rev 4 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4 | Rev 5 | ||
---|---|---|---|
1 | unit Unit1; |
1 | unit Unit1; |
2 | 2 | ||
3 | (* |
3 | (* |
4 | This program requires |
4 | This program requires |
5 | - Microsoft Internet Controls (TWebBrowser) |
5 | - Microsoft Internet Controls (TWebBrowser) |
6 | If you are using Delphi 10.1 Starter Edition, please import the ActiveX TLB |
6 | If you are using Delphi 10.1 Starter Edition, please import the ActiveX TLB |
7 | "Microsoft Internet Controls" |
7 | "Microsoft Internet Controls" |
8 | - SynEdit |
8 | - SynEdit |
9 | You can obtain SynEdit via Embarcadero GetIt |
9 | You can obtain SynEdit via Embarcadero GetIt |
10 | *) |
10 | *) |
11 | 11 | ||
12 | // TODO: localize |
12 | // TODO: localize |
13 | 13 | ||
14 | // TODO: wieso geht copy paste im twebbrowser nicht??? |
14 | // TODO: wieso geht copy paste im twebbrowser nicht??? |
15 | // Wieso dauert webbrowser1 erste kompilierung so lange??? |
15 | // Wieso dauert webbrowser1 erste kompilierung so lange??? |
- | 16 | // TODO: wieso kommt syntax fehler zweimal? einmal stderr einmal stdout? |
|
- | 17 | // TODO: Browser titlebar (link preview) |
|
- | 18 | ||
- | 19 | // TODO: strg+f / h |
|
- | 20 | // TODO: font bigger |
|
- | 21 | // TODO: code in bildschirmmitte? |
|
- | 22 | // TODO: regelmäßig scrap zwischenspeichern, oder bei strg+s |
|
16 | 23 | ||
17 | // Future ideas |
24 | // Future ideas |
18 | // - ToDo list |
25 | // - ToDo list |
19 | // - Open/Save real files |
26 | // - Open/Save real files |
20 | // - multiple scraps? |
27 | // - multiple scraps? |
21 | // - verschiedene php versionen? |
28 | // - verschiedene php versionen? |
22 | // - webbrowser1 nur laden, wenn man den tab anwählt? |
29 | // - webbrowser1 nur laden, wenn man den tab anwählt? |
23 | // - doppelklick auf tab soll diesen schließen |
30 | // - doppelklick auf tab soll diesen schließen |
24 | // - Strg+S |
31 | // - Strg+S |
25 | // - tastenkombo für "springe zu zeile" |
- | |
26 | // - Onlinehelp aufrufen |
32 | // - Onlinehelp (www) aufrufen |
27 | 33 | ||
28 | interface |
34 | interface |
29 | 35 | ||
30 | uses |
36 | uses |
31 | Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, |
37 | Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, |
32 | Dialogs, StdCtrls, OleCtrls, ComCtrls, ExtCtrls, ToolWin, IniFiles, |
38 | Dialogs, StdCtrls, OleCtrls, ComCtrls, ExtCtrls, ToolWin, IniFiles, |
33 | SynEditHighlighter, SynHighlighterPHP, SynEdit, SHDocVw_TLB; |
39 | SynEditHighlighter, SynHighlighterPHP, SynEdit, SHDocVw_TLB; |
34 | 40 | ||
35 | type |
41 | type |
36 | TForm1 = class(TForm) |
42 | TForm1 = class(TForm) |
37 | PageControl1: TPageControl; |
43 | PageControl1: TPageControl; |
38 | PlaintextTabSheet: TTabSheet; |
44 | PlaintextTabSheet: TTabSheet; |
39 | HtmlTabSheet: TTabSheet; |
45 | HtmlTabSheet: TTabSheet; |
40 | Memo2: TMemo; |
46 | Memo2: TMemo; |
41 | WebBrowser1: TWebBrowser; |
47 | WebBrowser1: TWebBrowser; |
42 | Splitter1: TSplitter; |
48 | Splitter1: TSplitter; |
43 | PageControl2: TPageControl; |
49 | PageControl2: TPageControl; |
44 | TabSheet3: TTabSheet; |
50 | TabSheet3: TTabSheet; |
45 | HelpTabsheet: TTabSheet; |
51 | HelpTabsheet: TTabSheet; |
46 | WebBrowser2: TWebBrowser; |
52 | WebBrowser2: TWebBrowser; |
47 | OpenDialog1: TOpenDialog; |
53 | OpenDialog1: TOpenDialog; |
48 | Panel1: TPanel; |
54 | Panel1: TPanel; |
49 | OpenDialog2: TOpenDialog; |
55 | OpenDialog2: TOpenDialog; |
50 | OpenDialog3: TOpenDialog; |
56 | OpenDialog3: TOpenDialog; |
51 | SynEdit1: TSynEdit; |
57 | SynEdit1: TSynEdit; |
52 | SynPHPSyn1: TSynPHPSyn; |
58 | SynPHPSyn1: TSynPHPSyn; |
- | 59 | Panel2: TPanel; |
|
- | 60 | SynEditFocusTimer: TTimer; |
|
- | 61 | Button1: TButton; |
|
- | 62 | Button2: TButton; |
|
- | 63 | Button3: TButton; |
|
53 | procedure Run(Sender: TObject); |
64 | procedure Run(Sender: TObject); |
54 | procedure FormShow(Sender: TObject); |
65 | procedure FormShow(Sender: TObject); |
55 | procedure Memo1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); |
- | |
56 | procedure FormCreate(Sender: TObject); |
66 | procedure FormCreate(Sender: TObject); |
57 | procedure FormDestroy(Sender: TObject); |
67 | procedure FormDestroy(Sender: TObject); |
58 | procedure FormClose(Sender: TObject; var Action: TCloseAction); |
68 | procedure FormClose(Sender: TObject; var Action: TCloseAction); |
59 | procedure PageControl2Changing(Sender: TObject; var AllowChange: Boolean); |
69 | procedure PageControl2Changing(Sender: TObject; var AllowChange: Boolean); |
- | 70 | procedure Memo2DblClick(Sender: TObject); |
|
- | 71 | procedure WebBrowser1BeforeNavigate2(ASender: TObject; |
|
- | 72 | const pDisp: IDispatch; const URL, Flags, TargetFrameName, PostData, |
|
- | 73 | Headers: OleVariant; var Cancel: WordBool); |
|
- | 74 | procedure SynEditFocusTimerTimer(Sender: TObject); |
|
- | 75 | procedure Button1Click(Sender: TObject); |
|
- | 76 | procedure Button2Click(Sender: TObject); |
|
- | 77 | procedure Button3Click(Sender: TObject); |
|
60 | private |
78 | private |
61 | CurSearchTerm: string; |
79 | CurSearchTerm: string; |
62 | HlpPrevPageIndex: integer; |
80 | HlpPrevPageIndex: integer; |
63 | procedure Help; |
81 | procedure Help; |
64 | procedure ApplicationOnMessage(var Msg: tagMSG; var Handled: Boolean); |
82 | procedure ApplicationOnMessage(var Msg: tagMSG; var Handled: Boolean); |
- | 83 | function MarkUpLineReference(cont: string): string; |
|
65 | protected |
84 | protected |
66 | FastPHPConfig: TMemIniFile; |
85 | FastPHPConfig: TMemIniFile; |
67 | ChmIndex: TMemIniFile; |
86 | ChmIndex: TMemIniFile; |
- | 87 | procedure GotoLineNo(LineNo:integer); |
|
68 | function GetScrapFile: string; |
88 | function GetScrapFile: string; |
69 | end; |
89 | end; |
70 | 90 | ||
71 | var |
91 | var |
72 | Form1: TForm1; |
92 | Form1: TForm1; |
73 | 93 | ||
74 | implementation |
94 | implementation |
75 | 95 | ||
76 | {$R *.dfm} |
96 | {$R *.dfm} |
77 | 97 | ||
78 | uses |
98 | uses |
79 | Functions; |
99 | Functions, StrUtils; |
80 | 100 | ||
81 | procedure TForm1.ApplicationOnMessage(var Msg: tagMSG; var Handled: Boolean); |
101 | procedure TForm1.ApplicationOnMessage(var Msg: tagMSG; var Handled: Boolean); |
- | 102 | var |
|
- | 103 | val: string; |
|
- | 104 | lineno: integer; |
|
82 | begin |
105 | begin |
83 | case Msg.message of |
106 | case Msg.message of |
84 | WM_KEYUP: |
107 | WM_KEYUP: |
85 | begin |
108 | begin |
86 | case Msg.wParam of |
109 | case Msg.wParam of |
- | 110 | {$REGION 'Esc'} |
|
87 | VK_ESCAPE: |
111 | VK_ESCAPE: |
88 | begin |
112 | begin |
- | 113 | Handled := true; |
|
89 | // It is necessary to use Application.OnMessage, because Form1.KeyPreview does not work when TWebBrowser has the focus |
114 | // It is necessary to use Application.OnMessage, because Form1.KeyPreview does not work when TWebBrowser has the focus |
90 | if (HlpPrevPageIndex <> -1) and (PageControl2.ActivePage = HelpTabSheet) and |
115 | if (HlpPrevPageIndex <> -1) and (PageControl2.ActivePage = HelpTabSheet) and |
91 | (HelpTabsheet.TabVisible) then |
116 | (HelpTabsheet.TabVisible) then |
92 | begin |
117 | begin |
93 | PageControl2.ActivePageIndex := HlpPrevPageIndex; |
118 | PageControl2.ActivePageIndex := HlpPrevPageIndex; |
94 | HelpTabsheet.TabVisible := false; |
119 | HelpTabsheet.TabVisible := false; |
95 | end; |
120 | end; |
- | 121 | end; |
|
- | 122 | {$ENDREGION} |
|
- | 123 | ||
- | 124 | {$REGION 'Ctrl+G : Go to line'} |
|
- | 125 | ord('G'): |
|
- | 126 | begin |
|
- | 127 | // TODO: VK_LMENU does not work! only works with AltGr but not Alt |
|
- | 128 | // http://stackoverflow.com/questions/16828250/delphi-xe2-how-to-prevent-the-alt-key-stealing-focus ? |
|
- | 129 | if (GetKeyState(VK_CONTROL) < 0) then |
|
- | 130 | begin |
|
- | 131 | Handled := true; |
|
- | 132 | InputQuery('Go to', 'Line number:', val); |
|
- | 133 | if not TryStrToInt(val, lineno) then exit; |
|
- | 134 | GotoLineNo(lineno); |
|
- | 135 | end; |
|
- | 136 | end; |
|
- | 137 | {$ENDREGION} |
|
- | 138 | ||
- | 139 | VK_F1: |
|
- | 140 | begin |
|
- | 141 | if SynEdit1.Focused then |
|
- | 142 | begin |
|
96 | Handled := true; |
143 | Handled := true; |
- | 144 | Help; |
|
- | 145 | end; |
|
- | 146 | end; |
|
- | 147 | ||
- | 148 | VK_F5: |
|
- | 149 | begin |
|
- | 150 | Run(Self); |
|
- | 151 | end; |
|
- | 152 | ||
- | 153 | VK_F9: |
|
- | 154 | begin |
|
- | 155 | Run(Self); |
|
97 | end; |
156 | end; |
98 | end; |
157 | end; |
99 | end; |
158 | end; |
100 | end; |
159 | end; |
101 | end; |
160 | end; |
102 | 161 | ||
103 | procedure TForm1.Run(Sender: TObject); |
162 | procedure TForm1.Run(Sender: TObject); |
104 | var |
163 | var |
105 | phpExe: string; |
164 | phpExe: string; |
106 | begin |
165 | begin |
- | 166 | memo2.Lines.Text := ''; |
|
- | 167 | BrowseContent(Webbrowser1, memo2.Lines.Text); |
|
- | 168 | Screen.Cursor := crHourGlass; |
|
- | 169 | Application.ProcessMessages; |
|
- | 170 | ||
- | 171 | try |
|
107 | if not FileExists(phpExe) then |
172 | if not FileExists(phpExe) then |
108 | begin |
173 | begin |
109 | phpExe := FastPHPConfig.ReadString('Paths', 'PHPInterpreter', ''); |
174 | phpExe := FastPHPConfig.ReadString('Paths', 'PHPInterpreter', ''); |
110 | if not FileExists(phpExe) then |
175 | if not FileExists(phpExe) then |
111 | begin |
176 | begin |
112 | if not OpenDialog2.Execute then exit; |
177 | if not OpenDialog2.Execute then exit; |
113 | if not FileExists(OpenDialog2.FileName) then exit; |
178 | if not FileExists(OpenDialog2.FileName) then exit; |
114 | phpExe := OpenDialog2.FileName; |
179 | phpExe := OpenDialog2.FileName; |
115 | 180 | ||
116 | if not IsValidPHPExe(phpExe) then |
181 | if not IsValidPHPExe(phpExe) then |
117 | begin |
182 | begin |
118 | ShowMessage('This is not a valid PHP executable.'); |
183 | ShowMessage('This is not a valid PHP executable.'); |
119 | exit; |
184 | exit; |
120 | end; |
185 | end; |
121 | 186 | ||
122 | FastPHPConfig.WriteString('Paths', 'PHPInterpreter', phpExe); |
187 | FastPHPConfig.WriteString('Paths', 'PHPInterpreter', phpExe); |
123 | FastPHPConfig.UpdateFile; |
188 | FastPHPConfig.UpdateFile; |
124 | end; |
189 | end; |
125 | end; |
190 | end; |
126 | 191 | ||
127 | SynEdit1.Lines.SaveToFile(GetScrapFile); |
192 | SynEdit1.Lines.SaveToFile(GetScrapFile); |
128 | 193 | ||
129 | memo2.Lines.Text := GetDosOutput('"'+phpExe+'" "'+GetScrapFile+'"', ExtractFileDir(Application.ExeName)); |
194 | memo2.Lines.Text := GetDosOutput('"'+phpExe+'" "'+GetScrapFile+'"', ExtractFileDir(Application.ExeName)); |
130 | 195 | ||
131 | BrowseContent(Webbrowser1, memo2.Lines.Text); |
196 | BrowseContent(Webbrowser1, MarkUpLineReference(memo2.Lines.Text)); |
132 | 197 | ||
133 | if IsTextHTML(memo2.lines.text) then |
198 | if IsTextHTML(memo2.lines.text) then |
134 | PageControl1.ActivePage := HtmlTabSheet |
199 | PageControl1.ActivePage := HtmlTabSheet |
135 | else |
200 | else |
136 | PageControl1.ActivePage := PlaintextTabSheet; |
201 | PageControl1.ActivePage := PlaintextTabSheet; |
- | 202 | finally |
|
- | 203 | Screen.Cursor := crDefault; |
|
- | 204 | end; |
|
- | 205 | end; |
|
- | 206 | ||
- | 207 | procedure TForm1.SynEditFocusTimerTimer(Sender: TObject); |
|
- | 208 | begin |
|
- | 209 | SynEditFocusTimer.Enabled := false; |
|
- | 210 | Button1.SetFocus; // Workaround for weird bug... This (and the timer) is necessary to get the focus to SynEdit1 |
|
- | 211 | SynEdit1.SetFocus; |
|
- | 212 | end; |
|
- | 213 | ||
- | 214 | procedure TForm1.WebBrowser1BeforeNavigate2(ASender: TObject; |
|
- | 215 | const pDisp: IDispatch; const URL, Flags, TargetFrameName, PostData, |
|
- | 216 | Headers: OleVariant; var Cancel: WordBool); |
|
- | 217 | const |
|
- | 218 | MAG_BEGIN = 'fastphp://gotoline/'; |
|
- | 219 | var |
|
- | 220 | s: string; |
|
- | 221 | lineno: integer; |
|
- | 222 | begin |
|
- | 223 | if Copy(URL, 1, length(MAG_BEGIN)) = MAG_BEGIN then |
|
- | 224 | begin |
|
- | 225 | try |
|
- | 226 | s := copy(URL, length(MAG_BEGIN)+1, 99); |
|
- | 227 | if not TryStrToInt(s, lineno) then exit; |
|
- | 228 | GotoLineNo(lineno); |
|
- | 229 | SynEditFocusTimer.Enabled := true; |
|
- | 230 | finally |
|
- | 231 | Cancel := true; |
|
- | 232 | end; |
|
- | 233 | end; |
|
- | 234 | end; |
|
- | 235 | ||
- | 236 | procedure TForm1.Button1Click(Sender: TObject); |
|
- | 237 | begin |
|
- | 238 | Run(Sender); |
|
- | 239 | SynEdit1.SetFocus; |
|
- | 240 | end; |
|
- | 241 | ||
- | 242 | procedure TForm1.Button2Click(Sender: TObject); |
|
- | 243 | begin |
|
- | 244 | Help; |
|
- | 245 | if PageControl2.ActivePage = HelpTabsheet then |
|
- | 246 | WebBrowser2.SetFocus |
|
- | 247 | else if PageControl2.ActivePage = TabSheet3{Scrap} then |
|
- | 248 | SynEdit1.SetFocus; |
|
- | 249 | end; |
|
- | 250 | ||
- | 251 | procedure TForm1.Button3Click(Sender: TObject); |
|
- | 252 | var |
|
- | 253 | val: string; |
|
- | 254 | lineno: integer; |
|
- | 255 | begin |
|
- | 256 | InputQuery('Go to', 'Line number:', val); |
|
- | 257 | if not TryStrToInt(val, lineno) then exit; |
|
- | 258 | GotoLineNo(lineno); |
|
137 | end; |
259 | end; |
138 | 260 | ||
139 | procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); |
261 | procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); |
140 | begin |
262 | begin |
141 | SynEdit1.Lines.SaveToFile(GetScrapFile); |
263 | SynEdit1.Lines.SaveToFile(GetScrapFile); |
142 | end; |
264 | end; |
143 | 265 | ||
144 | procedure TForm1.FormCreate(Sender: TObject); |
266 | procedure TForm1.FormCreate(Sender: TObject); |
145 | begin |
267 | begin |
146 | HlpPrevPageIndex := -1; |
268 | HlpPrevPageIndex := -1; |
147 | CurSearchTerm := ''; |
269 | CurSearchTerm := ''; |
148 | Application.OnMessage := ApplicationOnMessage; |
270 | Application.OnMessage := ApplicationOnMessage; |
149 | 271 | ||
150 | FastPHPConfig := TMemIniFile.Create(ChangeFileExt(Application.ExeName, '.ini')); |
272 | FastPHPConfig := TMemIniFile.Create(ChangeFileExt(Application.ExeName, '.ini')); |
151 | end; |
273 | end; |
152 | 274 | ||
153 | procedure TForm1.FormDestroy(Sender: TObject); |
275 | procedure TForm1.FormDestroy(Sender: TObject); |
154 | begin |
276 | begin |
155 | if Assigned(ChmIndex) then |
277 | if Assigned(ChmIndex) then |
156 | begin |
278 | begin |
157 | FreeAndNil(ChmIndex); |
279 | FreeAndNil(ChmIndex); |
158 | end; |
280 | end; |
159 | 281 | ||
160 | FastPHPConfig.UpdateFile; |
282 | FastPHPConfig.UpdateFile; |
161 | FreeAndNil(FastPHPConfig); |
283 | FreeAndNil(FastPHPConfig); |
162 | end; |
284 | end; |
163 | 285 | ||
164 | procedure TForm1.FormShow(Sender: TObject); |
286 | procedure TForm1.FormShow(Sender: TObject); |
165 | var |
287 | var |
166 | ScrapFile: string; |
288 | ScrapFile: string; |
167 | begin |
289 | begin |
168 | ScrapFile := GetScrapFile; |
290 | ScrapFile := GetScrapFile; |
169 | if ScrapFile = '' then |
291 | if ScrapFile = '' then |
170 | begin |
292 | begin |
171 | Close; |
293 | Close; |
172 | exit; |
294 | exit; |
173 | end; |
295 | end; |
174 | SynEdit1.Lines.LoadFromFile(ScrapFile); |
296 | SynEdit1.Lines.LoadFromFile(ScrapFile); |
175 | 297 | ||
176 | PageControl1.ActivePage := PlaintextTabSheet; |
298 | PageControl1.ActivePage := PlaintextTabSheet; |
177 | 299 | ||
178 | PageControl2.ActivePageIndex := 0; // Scraps |
300 | PageControl2.ActivePageIndex := 0; // Scraps |
179 | HelpTabsheet.TabVisible := false; |
301 | HelpTabsheet.TabVisible := false; |
- | 302 | ||
- | 303 | SynEdit1.SetFocus; |
|
180 | end; |
304 | end; |
181 | 305 | ||
182 | function TForm1.GetScrapFile: string; |
306 | function TForm1.GetScrapFile: string; |
183 | begin |
307 | begin |
184 | result := FastPHPConfig.ReadString('Paths', 'ScrapFile', ''); |
308 | result := FastPHPConfig.ReadString('Paths', 'ScrapFile', ''); |
185 | if not FileExists(result) then |
309 | if not FileExists(result) then |
186 | begin |
310 | begin |
187 | if not OpenDialog3.Execute then |
311 | if not OpenDialog3.Execute then |
188 | begin |
312 | begin |
189 | result := ''; |
313 | result := ''; |
190 | exit; |
314 | exit; |
191 | end; |
315 | end; |
192 | 316 | ||
193 | result := OpenDialog3.FileName; |
317 | result := OpenDialog3.FileName; |
194 | 318 | ||
195 | if not DirectoryExists(ExtractFilePath(result)) then |
319 | if not DirectoryExists(ExtractFilePath(result)) then |
196 | begin |
320 | begin |
197 | ShowMessage('Path does not exist!'); |
321 | ShowMessage('Path does not exist!'); |
198 | result := ''; |
322 | result := ''; |
199 | exit; |
323 | exit; |
200 | end; |
324 | end; |
201 | 325 | ||
202 | SynEdit1.Lines.Clear; |
326 | SynEdit1.Lines.Clear; |
203 | SynEdit1.Lines.SaveToFile(result); |
327 | SynEdit1.Lines.SaveToFile(result); |
204 | 328 | ||
205 | FastPHPConfig.WriteString('Paths', 'ScrapFile', result); |
329 | FastPHPConfig.WriteString('Paths', 'ScrapFile', result); |
206 | end; |
330 | end; |
207 | end; |
331 | end; |
208 | 332 | ||
209 | procedure TForm1.Help; |
333 | procedure TForm1.Help; |
210 | var |
334 | var |
211 | IndexFile, chmFile, w, url: string; |
335 | IndexFile, chmFile, w, url: string; |
212 | internalHtmlFile: string; |
336 | internalHtmlFile: string; |
213 | begin |
337 | begin |
214 | if not Assigned(ChmIndex) then |
338 | if not Assigned(ChmIndex) then |
215 | begin |
339 | begin |
216 | IndexFile := FastPHPConfig.ReadString('Paths', 'HelpIndex', ''); |
340 | IndexFile := FastPHPConfig.ReadString('Paths', 'HelpIndex', ''); |
217 | IndexFile := ChangeFileExt(IndexFile, '.ini'); // Just to be sure. Maybe someone wrote manually the ".chm" file in there |
341 | IndexFile := ChangeFileExt(IndexFile, '.ini'); // Just to be sure. Maybe someone wrote manually the ".chm" file in there |
218 | if FileExists(IndexFile) then |
342 | if FileExists(IndexFile) then |
219 | begin |
343 | begin |
220 | ChmIndex := TMemIniFile.Create(IndexFile); |
344 | ChmIndex := TMemIniFile.Create(IndexFile); |
221 | end; |
345 | end; |
222 | end; |
346 | end; |
223 | 347 | ||
224 | if Assigned(ChmIndex) then |
348 | if Assigned(ChmIndex) then |
225 | begin |
349 | begin |
226 | IndexFile := FastPHPConfig.ReadString('Paths', 'HelpIndex', ''); |
350 | IndexFile := FastPHPConfig.ReadString('Paths', 'HelpIndex', ''); |
227 | // We don't check if IndexFile still exists. It is not important since we have ChmIndex pre-loaded in memory |
351 | // We don't check if IndexFile still exists. It is not important since we have ChmIndex pre-loaded in memory |
228 | 352 | ||
229 | chmFile := ChangeFileExt(IndexFile, '.chm'); |
353 | chmFile := ChangeFileExt(IndexFile, '.chm'); |
230 | if not FileExists(chmFile) then |
354 | if not FileExists(chmFile) then |
231 | begin |
355 | begin |
232 | FreeAndNil(ChmIndex); |
356 | FreeAndNil(ChmIndex); |
233 | end; |
357 | end; |
234 | end; |
358 | end; |
235 | 359 | ||
236 | if not Assigned(ChmIndex) then |
360 | if not Assigned(ChmIndex) then |
237 | begin |
361 | begin |
238 | if not OpenDialog1.Execute then exit; |
362 | if not OpenDialog1.Execute then exit; |
239 | 363 | ||
240 | chmFile := OpenDialog1.FileName; |
364 | chmFile := OpenDialog1.FileName; |
241 | if not FileExists(chmFile) then exit; |
365 | if not FileExists(chmFile) then exit; |
242 | 366 | ||
243 | IndexFile := ChangeFileExt(chmFile, '.ini'); |
367 | IndexFile := ChangeFileExt(chmFile, '.ini'); |
244 | 368 | ||
245 | if not FileExists(IndexFile) then |
369 | if not FileExists(IndexFile) then |
246 | begin |
370 | begin |
247 | Panel1.Align := alClient; |
371 | Panel1.Align := alClient; |
248 | Panel1.Visible := true; |
372 | Panel1.Visible := true; |
249 | Panel1.BringToFront; |
373 | Panel1.BringToFront; |
250 | Screen.Cursor := crHourGlass; |
374 | Screen.Cursor := crHourGlass; |
251 | Application.ProcessMessages; |
375 | Application.ProcessMessages; |
252 | try |
376 | try |
253 | if not ParseCHM(chmFile) then |
377 | if not ParseCHM(chmFile) then |
254 | begin |
378 | begin |
255 | ShowMessage('The CHM file is not a valid PHP documentation. Cannot use help.'); |
379 | ShowMessage('The CHM file is not a valid PHP documentation. Cannot use help.'); |
256 | exit; |
380 | exit; |
257 | end; |
381 | end; |
258 | finally |
382 | finally |
259 | Screen.Cursor := crDefault; |
383 | Screen.Cursor := crDefault; |
260 | Panel1.Visible := false; |
384 | Panel1.Visible := false; |
261 | end; |
385 | end; |
262 | 386 | ||
263 | if not FileExists(IndexFile) then |
387 | if not FileExists(IndexFile) then |
264 | begin |
388 | begin |
265 | ShowMessage('Unknown error. Cannot use help.'); |
389 | ShowMessage('Unknown error. Cannot use help.'); |
266 | exit; |
390 | exit; |
267 | end; |
391 | end; |
268 | end; |
392 | end; |
269 | 393 | ||
270 | FastPHPConfig.WriteString('Paths', 'HelpIndex', IndexFile); |
394 | FastPHPConfig.WriteString('Paths', 'HelpIndex', IndexFile); |
271 | FastPHPConfig.UpdateFile; |
395 | FastPHPConfig.UpdateFile; |
272 | 396 | ||
273 | ChmIndex := TMemIniFile.Create(IndexFile); |
397 | ChmIndex := TMemIniFile.Create(IndexFile); |
274 | end; |
398 | end; |
275 | 399 | ||
276 | w := GetWordUnderCaret(SynEdit1); |
400 | w := GetWordUnderCaret(SynEdit1); |
277 | if w = '' then exit; |
401 | if w = '' then exit; |
278 | if w[1] in ['0'..'9'] then exit; |
402 | if w[1] in ['0'..'9'] then exit; |
279 | w := StringReplace(w, '_', '-', [rfReplaceAll]); |
403 | w := StringReplace(w, '_', '-', [rfReplaceAll]); |
280 | w := LowerCase(w); |
404 | w := LowerCase(w); |
281 | CurSearchTerm := w; |
405 | CurSearchTerm := w; |
282 | 406 | ||
283 | internalHtmlFile := ChmIndex.ReadString('_HelpWords_', CurSearchTerm, ''); |
407 | internalHtmlFile := ChmIndex.ReadString('_HelpWords_', CurSearchTerm, ''); |
284 | if internalHtmlFile = '' then |
408 | if internalHtmlFile = '' then |
285 | begin |
409 | begin |
286 | HelpTabsheet.TabVisible := false; |
410 | HelpTabsheet.TabVisible := false; |
287 | HlpPrevPageIndex := -1; |
411 | HlpPrevPageIndex := -1; |
288 | ShowMessage('No help for "'+CurSearchTerm+'" available'); |
412 | ShowMessage('No help for "'+CurSearchTerm+'" available'); |
289 | Exit; |
413 | Exit; |
290 | end; |
414 | end; |
291 | 415 | ||
292 | url := 'mk:@MSITStore:'+ChmFile+'::'+internalHtmlFile; |
416 | url := 'mk:@MSITStore:'+ChmFile+'::'+internalHtmlFile; |
293 | 417 | ||
294 | HlpPrevPageIndex := PageControl2.ActivePageIndex; // Return by pressing ESC |
418 | HlpPrevPageIndex := PageControl2.ActivePageIndex; // Return by pressing ESC |
295 | HelpTabsheet.TabVisible := true; |
419 | HelpTabsheet.TabVisible := true; |
296 | PageControl2.ActivePage := HelpTabsheet; |
420 | PageControl2.ActivePage := HelpTabsheet; |
297 | BrowseURL(WebBrowser2, url); |
421 | BrowseURL(WebBrowser2, url); |
298 | end; |
422 | end; |
299 | 423 | ||
300 | procedure TForm1.Memo1KeyDown(Sender: TObject; var Key: Word; |
424 | procedure TForm1.GotoLineNo(LineNo:integer); |
- | 425 | var |
|
- | 426 | line: string; |
|
301 | Shift: TShiftState); |
427 | i: integer; |
302 | begin |
428 | begin |
303 | if (Key = VK_F9) or (Key = VK_F5) then |
429 | SynEdit1.GotoLineAndCenter(LineNo); |
- | 430 | ||
304 | Run(Sender) |
431 | // Skip indent |
- | 432 | line := SynEdit1.Lines[SynEdit1.CaretY]; |
|
- | 433 | for i := 1 to Length(line) do |
|
- | 434 | begin |
|
305 | else if Key = VK_F1 then |
435 | if not (line[i] in [' ', #9]) then |
- | 436 | begin |
|
- | 437 | SynEdit1.CaretX := i-1; |
|
- | 438 | break; |
|
306 | Help; |
439 | end; |
- | 440 | end; |
|
- | 441 | ||
- | 442 | PageControl2.ActivePage := TabSheet3{Scrap}; |
|
- | 443 | if SynEdit1.CanFocus then SynEdit1.SetFocus; |
|
- | 444 | end; |
|
- | 445 | ||
- | 446 | procedure TForm1.Memo2DblClick(Sender: TObject); |
|
- | 447 | var |
|
- | 448 | line: string; |
|
- | 449 | p, lineno: integer; |
|
- | 450 | begin |
|
- | 451 | line := memo2.Lines.Strings[Memo2.CaretPos.Y]; |
|
- | 452 | p := Pos(' on line ', line); |
|
- | 453 | if p = 0 then exit; |
|
- | 454 | line := copy(line, p+length(' on line '), 99); |
|
- | 455 | if not TryStrToInt(line, lineno) then exit; |
|
- | 456 | GotoLineNo(lineno); |
|
307 | end; |
457 | end; |
308 | 458 | ||
309 | procedure TForm1.PageControl2Changing(Sender: TObject; |
459 | procedure TForm1.PageControl2Changing(Sender: TObject; |
310 | var AllowChange: Boolean); |
460 | var AllowChange: Boolean); |
311 | begin |
461 | begin |
312 | if PageControl2.ActivePage = HelpTabsheet then |
462 | if PageControl2.ActivePage = HelpTabsheet then |
313 | HlpPrevPageIndex := -1 |
463 | HlpPrevPageIndex := -1 |
314 | else |
464 | else |
315 | HlpPrevPageIndex := PageControl2.ActivePageIndex; |
465 | HlpPrevPageIndex := PageControl2.ActivePageIndex; |
316 | 466 | ||
317 | AllowChange := true; |
467 | AllowChange := true; |
318 | end; |
468 | end; |
- | 469 | ||
- | 470 | function TForm1.MarkUpLineReference(cont: string): string; |
|
- | 471 | var |
|
- | 472 | p, a, b: integer; |
|
- | 473 | num: integer; |
|
- | 474 | insert_a, insert_b: string; |
|
- | 475 | begin |
|
- | 476 | // TODO: make it more specific to PHP error messages. "on line" is too broad. |
|
- | 477 | p := Pos(' on line ', cont); |
|
- | 478 | while p >= 1 do |
|
- | 479 | begin |
|
- | 480 | a := p+1; |
|
- | 481 | b := p+length(' on line '); |
|
- | 482 | num := 0; |
|
- | 483 | while cont[b] in ['0'..'9'] do |
|
- | 484 | begin |
|
- | 485 | num := num*10 + StrToInt(cont[b]); |
|
- | 486 | inc(b); |
|
- | 487 | end; |
|
- | 488 | ||
- | 489 | insert_b := '</a>'; |
|
- | 490 | insert_a := '<a href="fastphp://gotoline/'+IntToStr(num)+'">'; |
|
- | 491 | ||
- | 492 | insert(insert_b, cont, b); |
|
- | 493 | insert(insert_a, cont, a); |
|
- | 494 | ||
- | 495 | p := b + Length(insert_a) + Length(insert_b); |
|
- | 496 | ||
- | 497 | p := PosEx(' on line ', cont, p+1); |
|
- | 498 | end; |
|
- | 499 | ||
- | 500 | result := cont; |
|
- | 501 | end; |
|
319 | 502 | ||
320 | end. |
503 | end. |
321 | 504 |