1 unit frmJCFNotepad;
2 
3 {(*}
4 (*------------------------------------------------------------------------------
5  Delphi Code formatter source code
6 
7 The Original Code is frmJCFNotepad, released May 2003.
8 The Initial Developer of the Original Code is Anthony Steele.
9 Portions created by Anthony Steele are Copyright (C) 1999-2008 Anthony Steele.
10 All Rights Reserved.
11 Contributor(s): Anthony Steele.
12 
13 The contents of this file are subject to the Mozilla Public License Version 1.1
14 (the "License"). you may not use this file except in compliance with the License.
15 You may obtain a copy of the License at http://www.mozilla.org/NPL/
16 
17 Software distributed under the License is distributed on an "AS IS" basis,
18 WITHOUT WARRANTY OF ANY KIND, either express or implied.
19 See the License for the specific language governing rights and limitations
20 under the License.
21 
22 Alternatively, the contents of this file may be used under the terms of
23 the GNU General Public License Version 2 or later (the "GPL")
24 See http://www.gnu.org/licenses/gpl.html
25 ------------------------------------------------------------------------------*)
26 {*)}
27 
28 {$I JcfGlobal.inc}
29 
30 interface
31 
32 uses
33   { delphi }
34   Windows, Messages, SysUtils, Classes, Controls, Forms,
35   Dialogs, StdCtrls, ComCtrls, ExtCtrls, ActnList,
36   Buttons, Menus, ShellAPI,
37   { JEDI }
38   JvMRUManager, JvMemo, JvComponent, JvExStdCtrls, JvFormPlacement, JvComponentBase,
39   { local }
40   JcfRegistrySettings, Converter, ConvertTypes, JcfUnicodeFiles;
41 
42 { have to do file pos display *after* various processing }
43 const
44   WM_SHOWFILEPOS = WM_USER + 42;
45 
46 type
47   TfmJCFNotepad = class(TForm)
48     sb1:          TStatusBar;
49     pnlTop:       TPanel;
50     pcPages:      TPageControl;
51     tsInput:      TTabSheet;
52     tsOutput:     TTabSheet;
53     mInput:       TJvMemo;
54     mOutput:      TJvMemo;
55     mMessages:    TJvMemo;
56     lblMessages:  TLabel;
57     sbLoad:       TSpeedButton;
58     sbSave:       TSpeedButton;
59     sbGo:         TSpeedButton;
60     ActionList1:  TActionList;
61     actOpen:      TAction;
62     actSave:      TAction;
63     actGo:        TAction;
64     OpenDialog1:  TOpenDialog;
65     SaveDialog1:  TSaveDialog;
66     actClear:     TAction;
67     sbClear:      TSpeedButton;
68     MainMenu1:    TMainMenu;
69     mnuFile:      TMenuItem;
70     mnuFileOpen:  TMenuItem;
71     mnuFileSaveOut: TMenuItem;
72     mnuExit:      TMenuItem;
73     mnuSettings:  TMenuItem;
74     actCopy:      TAction;
75     actPaste:     TAction;
76     N1:           TMenuItem;
77     mruFiles:     TJvMRUManager;
78     mnuEdit:      TMenuItem;
79     mnuEditPaste: TMenuItem;
80     mnuEditCopy:  TMenuItem;
81     mnuEditGo:    TMenuItem;
82     mnuEditClear: TMenuItem;
83     mnuEditCut:   TMenuItem;
84     mnuEditCopyOutput: TMenuItem;
85     mnuEditSelectAll: TMenuItem;
86     mnuEditCopyMessages: TMenuItem;
87     mnuFormat:    TMenuItem;
88     mnuFileSaveInAs: TMenuItem;
89     mnuHelp:      TMenuItem;
90     mnuHelpAbout: TMenuItem;
91     mnuShowRegSetting: TMenuItem;
92     mnuFormatSettings: TMenuItem;
93     ActCut:       TAction;
94     Contents1:    TMenuItem;
95     JvFormStorage1: TJvFormStorage;
96     mnuFileSaveIn: TMenuItem;
97     procedure FormResize(Sender: TObject);
98     procedure pcPagesChange(Sender: TObject);
99     procedure actGoExecute(Sender: TObject);
100     procedure mInputKeyUp(Sender: TObject; var Key: word; Shift: TShiftState);
101     procedure FormShow(Sender: TObject);
102     procedure actOpenExecute(Sender: TObject);
103     procedure actClearExecute(Sender: TObject);
104     procedure actSaveExecute(Sender: TObject);
105     procedure mnuExitClick(Sender: TObject);
106     procedure FormCreate(Sender: TObject);
107     procedure FormDestroy(Sender: TObject);
108     procedure actCopyExecute(Sender: TObject);
109     procedure actPasteExecute(Sender: TObject);
110     procedure mruFilesClick(Sender: TObject; const RecentName, Caption: string;
111       UserData: integer);
112     procedure mnuEditCopyOutputClick(Sender: TObject);
113     procedure mnuEditSelectAllClick(Sender: TObject);
114     procedure mnuEditCopyMessagesClick(Sender: TObject);
115     procedure mnuFileSaveInAsClick(Sender: TObject);
116     procedure mnuHelpAboutClick(Sender: TObject);
117     procedure mnuShowRegSettingClick(Sender: TObject);
118     procedure mnuFormatSettingsClick(Sender: TObject);
119     procedure ActCutExecute(Sender: TObject);
120     procedure mInputMouseUp(Sender: TObject; Button: TMouseButton;
121       Shift: TShiftState; X, Y: integer);
122     procedure Contents1Click(Sender: TObject);
123     procedure FormKeyUp(Sender: TObject; var Key: word; Shift: TShiftState);
124     procedure mOutputKeyUp(Sender: TObject; var Key: word; Shift: TShiftState);
125     procedure mInputKeyDown(Sender: TObject; var Key: word; Shift: TShiftState);
126     procedure mInputEnter(Sender: TObject);
127     procedure mOutputEnter(Sender: TObject);
128     procedure mInputClick(Sender: TObject);
129     procedure mOutputClick(Sender: TObject);
130     procedure mInputKeyPress(Sender: TObject; var Key: char);
131     procedure mnuFileSaveInClick(Sender: TObject);
132   private
133     fcConvert: TConverter;
134     fsLastInputFileName: string;
135     feLastInputContentType: TFileContentType;
136 
137     procedure OnConvertStatusMessage(const psUnit, psMessage: string;
138      const peMessageType: TStatusMessageType;
139      const piY, piX: integer);
140 
141     procedure CheckInputState;
142     procedure CheckCutPasteState;
143     procedure DoFileOpen(const psFileName: string);
144     procedure SaveInputToFile(const psFileName: string);
145 
146     procedure CheckSaveEnabled;
147 
148     procedure AddCheckMRU(const psFile: string);
149 
150     procedure ShowFilePos;
151     procedure SendShowFilePos;
152 
153     procedure OnReceiveShowFilePos(var msg: TMessage); message WM_SHOWFILEPOS;
154   public
155   end;
156 
157 var
158   fmJCFNotepad: TfmJCFNotepad;
159 
160 implementation
161 
162 uses
163   { delphi }
164   ClipBrd,
165   { local }
166   JcfStringUtils,
167   JcfHelp, fAbout, fRegistrySettings, fAllSettings, JcfFontSetFunctions;
168 
169 {$ifdef FPC}
170   {$R *.lfm}
171 {$else}
172   {$R *.dfm}
173 {$endif}
174 
175 procedure TfmJCFNotepad.CheckInputState;
176 begin
177   actGo.Enabled := (mInput.Text <> '');
178   actClear.Enabled := (mInput.Text <> '');
179 end;
180 
181 procedure TfmJCFNotepad.CheckSaveEnabled;
182 begin
183   mnuFileSaveIn.Enabled := (fsLastInputFileName <> '');
184 end;
185 
186 procedure TfmJCFNotepad.CheckCutPasteState;
187 var
188   lbHasOutput: boolean;
189 begin
190   actPaste.Enabled := (pcPages.ActivePage = tsInput) and Clipboard.HasFormat(CF_TEXT);
191   actCut.Enabled := (pcPages.ActivePage = tsInput) and (mInput.SelLength > 0);
192 
193   lbHasOutput := (pcPages.ActivePage = tsOutput) and (mOutput.Text <> '');
194   actSave.Enabled := lbHasOutput;
195 
196   if pcPages.ActivePage = tsOutput then
197     actCopy.Enabled := lbHasOutput
198   else
199     actCopy.Enabled := (mInput.Text <> '');
200 
201 end;
202 
203 procedure TfmJCFNotepad.DoFileOpen(const psFileName: string);
204 var
205   lsFileContents: String;
206 begin
207   if psFileName = '' then
208     exit;
209   if not FileExists(psFileName) then
210     exit;
211 
212   GetRegSettings.InputDir := ExtractFilePath(psFileName);
213 
214   ReadTextFile(psFileName, lsFileContents, feLastInputContentType);
215 
216   mInput.Text := lsFileContents;
217   sb1.Panels[1].Text := psFileName;
218   AddCheckMRU(psFileName);
219   fsLastInputFileName := psFileName;
220 
221   CheckInputState;
222   SendShowFilePos;
223   CheckSaveEnabled;
224 end;
225 
226 procedure TfmJCFNotepad.SaveInputToFile(const psFileName: string);
227 begin
228   if psFileName = '' then
229     exit;
230 
231   // default the file type to utf-8 if it's not known
232   if feLastInputContentType = eUnknown then
233   begin
234     feLastInputContentType := eUtf8;
235   end;
236 
237   WriteTextFile(psFileName, mInput.Text, feLastInputContentType);
238 
239 
240   sb1.Panels[1].Text := 'Saved input as ' + psFileName;
241   AddCheckMRU(psFileName);
242 
243   fsLastInputFileName := psFileName;
244   CheckSaveEnabled;
245 end;
246 
247 procedure TfmJCFNotepad.AddCheckMRU(const psFile: string);
248 var
249   liIndex: integer;
250 begin
251   liIndex := mruFiles.Strings.IndexOf(psFile);
252 
253   if (liIndex < 0) then
254   begin
255     mruFiles.Add(psFile, 0);
256     liIndex := mruFiles.Strings.IndexOf(psFile);
257   end;
258 
259   mruFiles.Strings.Move(liIndex, 0);
260 
261   while mruFiles.Strings.Count > mruFiles.Capacity do
262     mruFiles.Strings.Delete(mruFiles.Strings.Count - 1);
263 end;
264 
265 procedure TfmJCFNotepad.FormResize(Sender: TObject);
266 const
267   OUTPUT_PAD = 4;
268 begin
269   mOutput.Left := OUTPUT_PAD;
270   mOutput.Top  := OUTPUT_PAD;
271   mOutput.Width := tsOutput.ClientWidth - (2 * OUTPUT_PAD);
272 
273   // two thirds height
274   mOutput.Height := (tsOutput.Height * 2 div 3) - (2 * OUTPUT_PAD);
275 
276   lblMessages.Left := 4;
277   lblMessages.Top  := mOutput.Top + mOutput.Height + OUTPUT_PAD;
278 
279   mMessages.Top  := lblMessages.Top + lblMessages.Height + OUTPUT_PAD;
280   mMessages.Height := tsOutput.ClientHeight - (lblMessages.Top +
281     lblMessages.Height + (OUTPUT_PAD * 2));
282   mMessages.Left := OUTPUT_PAD;
283   mMessages.Width := tsOutput.ClientWidth - (2 * OUTPUT_PAD);
284 end;
285 
286 procedure TfmJCFNotepad.pcPagesChange(Sender: TObject);
287 begin
288   CheckCutPasteState;
289   SendShowFilePos;
290 end;
291 
292 procedure TfmJCFNotepad.actGoExecute(Sender: TObject);
293 begin
294   actGo.Enabled := False;
295 
296   mMessages.Clear;
297   fcConvert.OnStatusMessage := OnConvertStatusMessage;
298 
299   fcConvert.InputCode := mInput.Lines.Text;
300   fcConvert.Convert;
301   mOutput.Lines.Text := fcConvert.OutputCode;
302   fcConvert.Clear;
303 
304   pcPages.ActivePage := tsOutput;
305   pcPagesChange(nil);
306 
307   CheckInputState;
308 end;
309 
310 procedure TfmJCFNotepad.mInputKeyUp(Sender: TObject; var Key: word; Shift: TShiftState);
311 begin
312   CheckInputState;
313   CheckCutPasteState;
314 end;
315 
316 
317 procedure TfmJCFNotepad.FormShow(Sender: TObject);
318 begin
319   CheckInputState;
320   CheckCutPasteState;
321 end;
322 
323 procedure TfmJCFNotepad.actOpenExecute(Sender: TObject);
324 begin
325   OpenDialog1.InitialDir := GetRegSettings.InputDir;
326   OpenDialog1.Filter := SOURCE_FILE_FILTERS;
327 
328   if OpenDialog1.Execute then
329   begin
330     pcPages.ActivePage := tsInput;
331     DoFileOpen(OpenDialog1.FileName);
332   end;
333 end;
334 
335 procedure TfmJCFNotepad.actClearExecute(Sender: TObject);
336 begin
337   mInput.Text  := '';
338   mOutput.Text := '';
339   mMessages.Text := '';
340   pcPages.ActivePage := tsInput;
341 
342   CheckInputState;
343   CheckCutPasteState;
344 end;
345 
346 procedure TfmJCFNotepad.actSaveExecute(Sender: TObject);
347 begin
348   SaveDialog1.InitialDir := GetRegSettings.OutputDir;
349   SaveDialog1.Title  := 'Save output file';
350   SaveDialog1.Filter := SOURCE_FILE_FILTERS;
351 
352 
353   if SaveDialog1.Execute then
354   begin
355     GetRegSettings.OutputDir := ExtractFilePath(SaveDialog1.FileName);
356     StringToFile(SaveDialog1.FileName, AnsiString(mOutput.Text));
357     sb1.Panels[1].Text := 'Saved output: ' + SaveDialog1.FileName;
358     AddCheckMRU(SaveDialog1.FileName);
359   end;
360 end;
361 
362 procedure TfmJCFNotepad.mnuExitClick(Sender: TObject);
363 begin
364   Close;
365 end;
366 
367 procedure TfmJCFNotepad.FormCreate(Sender: TObject);
368 var
369   lsHelpFile: string;
370 begin
371   SetObjectFontToSystemFont(Self);
372 
373   //lsHelpFile := IncludeTrailingPathDelimiter(ExtractFilePath(Application.ExeName)) + 'CodeFormat.chm';
374   //lsHelpFile := IncludeTrailingPathDelimiter(ExtractFilePath(GetModuleName(GetModuleHandle('JCFIdeD11.bpl')))) + 'CodeFormat.chm';
375   lsHelpFile := GetHelpFilePath;
376 
377   if FileExists(lsHelpFile) then
378     Application.HelpFile := lsHelpFile;
379 
380   fcConvert := TConverter.Create;
381 
382   GetRegSettings.MRUFiles := mruFiles.Strings;
383   GetRegSettings.ReadAll;
384 
385   mruFiles.RemoveInvalid;
386 
387   pcPages.ActivePage := tsInput;
388 
389   feLastInputContentType := eUnknown;
390   fsLastInputFileName := '';
391 
392   CheckSaveEnabled;
393 end;
394 
395 procedure TfmJCFNotepad.FormDestroy(Sender: TObject);
396 begin
397   GetRegSettings.WriteAll;
398   GetRegSettings.MRUFiles := nil;
399 
400   FreeAndNil(fcConvert);
401 end;
402 
403 procedure TfmJCFNotepad.actCopyExecute(Sender: TObject);
404 begin
405   if pcPages.ActivePage = tsOutput then
406     mOutput.CopyToClipboard
407   else
408     mInput.CopyToClipboard;
409 end;
410 
411 procedure TfmJCFNotepad.actPasteExecute(Sender: TObject);
412 begin
413   if (pcPages.ActivePage = tsInput) and Clipboard.HasFormat(CF_TEXT) then
414   begin
415     mInput.PasteFromClipboard;
416     CheckInputState;
417   end;
418 end;
419 
420 procedure TfmJCFNotepad.mruFilesClick(Sender: TObject;
421   const RecentName, Caption: string; UserData: integer);
422 begin
423   DoFileOpen(RecentName);
424 end;
425 
426 procedure TfmJCFNotepad.mnuEditCopyOutputClick(Sender: TObject);
427 begin
428   Clipboard.AsText := mOutput.Text;
429 end;
430 
431 procedure TfmJCFNotepad.ActCutExecute(Sender: TObject);
432 begin
433   if (pcPages.ActivePage = tsInput) then
434   begin
435     mInput.CutToClipboard;
436     CheckInputState;
437   end;
438 end;
439 
440 procedure TfmJCFNotepad.mnuEditSelectAllClick(Sender: TObject);
441 begin
442   if (pcPages.ActivePage = tsInput) then
443   begin
444     mInput.SetFocus;
445     mInput.SelectAll;
446     CheckCutPasteState;
447   end
448   else
449   begin
450     mOutput.SetFocus;
451     mOutput.SelectAll;
452   end;
453 end;
454 
455 procedure TfmJCFNotepad.mnuEditCopyMessagesClick(Sender: TObject);
456 begin
457   Clipboard.AsText := mMessages.Text;
458 end;
459 
460 procedure TfmJCFNotepad.mnuFileSaveInClick(Sender: TObject);
461 begin
462   if fsLastInputFileName <> '' then
463   begin
464     SaveInputToFile(fsLastInputFileName);
465   end;
466 
467 end;
468 
469 
470 procedure TfmJCFNotepad.mnuFileSaveInAsClick(Sender: TObject);
471 begin
472   SaveDialog1.InitialDir := GetRegSettings.OutputDir;
473   SaveDialog1.Title  := 'Save input file';
474   SaveDialog1.Filter := SOURCE_FILE_FILTERS;
475 
476   if SaveDialog1.Execute then
477   begin
478     GetRegSettings.OutputDir := ExtractFilePath(SaveDialog1.FileName);
479 
480     SaveInputToFile(SaveDialog1.FileName);
481   end;
482 end;
483 
484 procedure TfmJCFNotepad.mnuHelpAboutClick(Sender: TObject);
485 var
486   lfAbout: TfrmAboutBox;
487 begin
488   lfAbout := TfrmAboutBox.Create(self);
489   try
490     lfAbout.ShowModal;
491   finally
492     lfAbout.Release;
493   end;
494 end;
495 
496 procedure TfmJCFNotepad.mnuShowRegSettingClick(Sender: TObject);
497 var
498   lfSettings: TfmRegistrySettings;
499 begin
500   lfSettings := TfmRegistrySettings.Create(self);
501   try
502     lfSettings.Execute;
503   finally
504     lfSettings.Release;
505   end;
506 end;
507 
508 procedure TfmJCFNotepad.mnuFormatSettingsClick(Sender: TObject);
509 var
510   lfAllSettings: TFormAllSettings;
511 begin
512   lfAllSettings := TFormAllSettings.Create(self);
513   try
514     lfAllSettings.Execute;
515   finally
516     lfAllSettings.Release;
517   end;
518 end;
519 
520 procedure TfmJCFNotepad.mInputMouseUp(Sender: TObject; Button: TMouseButton;
521   Shift: TShiftState; X, Y: integer);
522 begin
523   CheckCutPasteState;
524 end;
525 
526 procedure TfmJCFNotepad.Contents1Click(Sender: TObject);
527 begin
528   try
529     Application.HelpContext(HELP_MAIN);
530   except
531     ShellExecute(Handle, 'open', PChar(Application.HelpFile), nil, nil, SW_SHOWNORMAL);
532   end;
533 end;
534 
535 procedure TfmJCFNotepad.FormKeyUp(Sender: TObject; var Key: word; Shift: TShiftState);
536 begin
537   if Key = VK_F1 then
538     try
539       Application.HelpContext(HELP_MAIN);
540     except
541       ShellExecute(Handle, 'open', PChar(Application.HelpFile), nil, nil, SW_SHOWNORMAL);
542     end;
543 end;
544 
545 procedure TfmJCFNotepad.ShowFilePos;
546 const
547   POS_NUM_LEN = 4;
548 var
549   liX, liY: integer;
550   lsPos: string;
551   lsX, lsY: string;
552 begin
553   if pcPages.ActivePage = tsInput then
554   begin
555     liX := mInput.CaretPos.X;
556     liY := mInput.CaretPos.Y;
557   end
558   else
559   begin
560     liX := mOutput.CaretPos.X;
561     liY := mOutput.CaretPos.Y;
562   end;
563 
564   { index in delphi is 1-based not 0-based,
565     ie starts at line 1 char 1}
566   Inc(liX);
567   Inc(liY);
568 
569   if liX > 0 then
570     lsX := StrPadLeft(IntToStr(liX), POS_NUM_LEN, ' ')
571   else
572     lsX := '?';
573 
574   if liY > 0 then
575     lsY := StrPadLeft(IntToStr(liY), POS_NUM_LEN, ' ')
576   else
577     lsY := '?';
578 
579   lsPos := lsY + ':' + lsX;
580 
581   sb1.Panels[0].Text := lsPos;
582 end;
583 
584 procedure TfmJCFNotepad.SendShowFilePos;
585 begin
586   { send a note to yourself to redisplay this
587     as soon as the current operation is finished }
588   PostMessage(Handle, WM_SHOWFILEPOS, 0, 0);
589 end;
590 
591 { triggered by SendShowFilePos }
592 procedure TfmJCFNotepad.OnReceiveShowFilePos(var msg: TMessage);
593 begin
594   ShowFilePos;
595 end;
596 
597 procedure TfmJCFNotepad.mOutputKeyUp(Sender: TObject; var Key: word;
598   Shift: TShiftState);
599 begin
600   SendShowFilePos;
601 end;
602 
603 procedure TfmJCFNotepad.mInputKeyDown(Sender: TObject; var Key: word;
604   Shift: TShiftState);
605 begin
606   SendShowFilePos;
607 end;
608 
609 procedure TfmJCFNotepad.mInputEnter(Sender: TObject);
610 begin
611   SendShowFilePos;
612 end;
613 
614 procedure TfmJCFNotepad.mOutputEnter(Sender: TObject);
615 begin
616   SendShowFilePos;
617 end;
618 
619 procedure TfmJCFNotepad.mInputClick(Sender: TObject);
620 begin
621   SendShowFilePos;
622 end;
623 
624 procedure TfmJCFNotepad.mOutputClick(Sender: TObject);
625 begin
626   SendShowFilePos;
627 end;
628 
629 procedure TfmJCFNotepad.mInputKeyPress(Sender: TObject; var Key: char);
630 begin
631   SendShowFilePos;
632 end;
633 
634 procedure TfmJCFNotepad.OnConvertStatusMessage(const psUnit, psMessage: string;
635   const peMessageType: TStatusMessageType;
636   const piY, piX: integer);
637 var
638   lsWholeMessage: string;
639 begin
640   lsWholeMessage := psMessage;
641   if (piY >= 0) and (piX >= 0) then
642     lsWholeMessage := lsWholeMessage + ' at line ' + IntToStr(piY) +
643       ' col ' + IntToStr(piX);
644 
645   mMessages.Lines.Add(lsWholeMessage);
646 
647   { make it visible }
648   if pcPages.ActivePage <> tsOutput then
649     pcPages.ActivePage := tsOutput;
650 end;
651 
652 end.
653