Subversion Repositories fastphp

Compare Revisions

Regard whitespace Rev 91 → Rev 90

/trunk/EditorMain.pas
11,7 → 11,8
You can obtain SynEdit via Embarcadero GetIt
*)
 
// TODO: "crHourGlass" does not work if F9 is pressed!
// TODO: "DragAcceptFiles" does not work with Delphi Dark Design Template !!!
 
// TODO: if a scrapfile is already open, create a new scrap file (scrap2.php)
// TODO: localize
// TODO: wieso geht copy paste im twebbrowser nicht???
21,19 → 22,6
// TODO: "jump to next/prev todo" buttons/shortcuts
// TODO: "increase/decrease indent" buttons/shortcuts
 
// In regards Unicode:
// - Solve compiler warnings
// - If you place Unicode symbols in a ANSI file, they will be replaced during saving
// by "?" without asking the user if the code should be converted to Unicode!
// - FastPHP can only read a UTF-8 file correctly if it has a BOM
// However, the PSR-1 standard requires that files have UTF-8 without BOM!
// So we need auto-detect (since many people are working with ANSI!)
// - When a file is correctly loaded with UTF-8/BOM,
// the run output (Plaintext and HTML) will show UTF-8 instead of Unicode
// (that COULD be intended since the Windows CMD is not Unicode ready?)
// But HTML is also shown as UTF-8 even though I have added <meta charset="UTF-8"> ?!
// - Is it possible that UTF8 BOM automatically gets removed by FastPHP, generating pure ANSI?
 
// Small things:
// - The scroll bars of SynEdit are not affected by the dark theme
 
42,12 → 30,12
// - verschiedene php versionen?
// - webbrowser1 nur laden, wenn man den tab anwählt?
// - doppelklick auf tab soll diesen schließen
// - Onlinehelp (www) aufrufen oder CHM datei
// - Onlinehelp (www) aufrufen
// - Let all colors be adjustable
// - code in bildschirmmitte (horizontal)?
// - search in files of a directory
// - Files in multiple tabs?
// - Configurable tabulator display-width
// - multi tab?
// - DDE (drag n drop)
 
interface
 
127,9 → 115,6
FileModTimer: TTimer;
GotoPHPdir1: TMenuItem;
PHPShell1: TMenuItem;
ActionSaveAs: TAction;
ActionGoToPHPDir: TAction;
ActionPHPInteractiveShell: TAction;
procedure Run(Sender: TObject);
procedure RunConsole(Sender: TObject);
procedure FormShow(Sender: TObject);
181,6 → 166,8
procedure ActionLintExecute(Sender: TObject);
procedure ActionRunConsoleExecute(Sender: TObject);
procedure SynEdit1Change(Sender: TObject);
procedure Saveas1Click(Sender: TObject);
procedure Save1Click(Sender: TObject);
procedure BtnSpecialCharsClick(Sender: TObject);
procedure WebBrowser1WindowClosing(ASender: TObject;
IsChildWindow: WordBool; var Cancel: WordBool);
187,11 → 174,10
procedure BtnLightClick(Sender: TObject);
procedure StartUpTimerTimer(Sender: TObject);
procedure FileModTimerTimer(Sender: TObject);
procedure GotoPHPdir1Click(Sender: TObject);
procedure PHPShell1Click(Sender: TObject);
procedure SynEdit1DropFiles(Sender: TObject; X, Y: Integer;
AFiles: TStrings);
procedure ActionSaveAsExecute(Sender: TObject);
procedure ActionGoToPHPDirExecute(Sender: TObject);
procedure ActionPHPInteractiveShellExecute(Sender: TObject);
private
hMutex: THandle;
CurSearchTerm: string;
201,8 → 187,6
gOnlineHelpWord: string;
{$ENDIF}
FileModLast: TDateTime;
FormShowRanOnce: boolean;
BrowserLoadedOnce: boolean;
procedure Help;
function InputRequestCallback(var data: AnsiString): boolean;
function OutputNotifyCallback(const data: AnsiString): boolean;
265,15 → 249,12
var
val: string;
lineno: integer;
resourcestring
SGoTo = 'Go to';
SLineNumber = 'Line number:';
begin
// TODO: VK_LMENU does not work! only works with AltGr but not Alt
// http://stackoverflow.com/questions/16828250/delphi-xe2-how-to-prevent-the-alt-key-stealing-focus ?
 
if not InputQuery(SGoTo, SLineNumber, val) or
not TryStrToInt(val, lineno) then
InputQuery('Go to', 'Line number:', val);
if not TryStrToInt(val, lineno) then
begin
if SynEdit1.CanFocus then SynEdit1.SetFocus;
exit;
281,15 → 262,6
GotoLineNo(lineno);
end;
 
procedure TForm1.ActionGoToPHPDirExecute(Sender: TObject);
var
phpExe: string;
begin
phpExe := GetPHPExe;
if phpExe <> '' then
ShellExecute(Handle, 'open', 'explorer.exe', PChar(ExtractFilePath(phpExe)), '', SW_NORMAL);
end;
 
procedure TForm1.ActionHelpExecute(Sender: TObject);
begin
Help;
313,15 → 285,6
end;
end;
 
procedure TForm1.ActionPHPInteractiveShellExecute(Sender: TObject);
var
phpExe: string;
begin
phpExe := GetPHPExe;
if phpExe <> '' then
ShellExecute(Handle, 'open', PChar(phpExe), '-a', PChar(ExtractFilePath(phpExe)), SW_NORMAL);
end;
 
procedure TForm1.ActionReplaceExecute(Sender: TObject);
begin
SrcRep.ReplaceExecute;
362,33 → 325,6
*)
end;
 
procedure TForm1.ActionSaveAsExecute(Sender: TObject);
var
hMutexNew: THandle;
resourcestring
SCannotSaveBecauseMutex = 'Cannot save because file "%s", because it is alrady open in another FastPHP window!';
begin
if SaveDialog1.Execute then
begin
{$REGION 'Switch mutex'}
hMutexNew := CreateMutex(nil, True, PChar('FastPHP'+md5(UpperCase(SaveDialog1.FileName))));
if GetLastError = ERROR_ALREADY_EXISTS then
begin
ShowMessageFmt(SCannotSaveBecauseMutex, [SaveDialog1.FileName]);
Close;
end;
 
if hMutex <> 0 then CloseHandle(hMutex); // Note: ReleaseMutex does not work as expected!
hMutex := hMutexNew;
{$ENDREGION}
 
FSaveAsFilename := SaveDialog1.FileName;
Caption := Copy(Caption, 1, Pos(' - ', Caption)-1) + ' - ' + FSaveAsFilename;
Application.Title := Format('%s - FastPHP', [ExtractFileName(FSaveAsFilename)]); // do not translate!
Button7.Click;
end;
end;
 
procedure TForm1.ActionSaveExecute(Sender: TObject);
begin
RightTrimAll;
471,8 → 407,6
ind: integer;
resourcestring
SNoLinesAvailable = 'No lines with spaces at the beginning available';
SSpacesToLabs = 'Spaces to tabs';
SIndent = 'Indent:';
begin
// TODO: if something is selected, only process the selected part
 
485,17 → 419,16
ind := GuessIndent(SynEdit1.Lines);
if ind <> -1 then val := IntToStr(ind);
 
if not InputQuery(SSpacesToLabs, SIndent, val) or
not TryStrToInt(Trim(val), ind) then
InputQuery('Spaces to tabs', 'Indent:', val); // TODO: handle CANCEL correctly...
if TryStrToInt(Trim(val), ind) then
begin
if SynEdit1.CanFocus then SynEdit1.SetFocus;
exit;
end;
 
if ind = 0 then exit;
SpaceToTab(SynEdit1.Lines, ind);
end;
 
if SynEdit1.CanFocus then SynEdit1.SetFocus;
end;
 
procedure TForm1.ActionESCExecute(Sender: TObject);
begin
if (HlpPrevPageIndex <> -1) and (PageControl2.ActivePage = HelpTabSheet) and
514,6 → 447,8
SrcRep.FindExecute;
end;
 
var
firstTimeBrowserLoad: boolean = true;
procedure TForm1.Run(Sender: TObject);
var
bakTS: TTabSheet;
522,7 → 457,7
begin
memo2.Lines.Text := '';
 
if not BrowserLoadedOnce then
if firstTimeBrowserLoad then
begin
bakTS := PageControl1.ActivePage;
try
531,12 → 466,12
finally
PageControl1.ActivePage := bakTS;
end;
BrowserLoadedOnce := true;
firstTimeBrowserLoad := false;
end
else
Webbrowser1.Clear;
 
Screen.Cursor := crHourGlass; // TODO: Doesn't work with F9
Screen.Cursor := crHourGlass;
Application.ProcessMessages;
 
try
586,12 → 521,10
FileName: string;
const
WARN_FILE_COUNT = 10;
resourcestring
SAreYouSure = 'Are you sure you want to open %d files?';
begin
if AFiles.Count > WARN_FILE_COUNT then
begin
if not MessageDlg(Format(SAreYouSure, [WARN_FILE_COUNT]), mtConfirmation, mbYesNoCancel, 0) <> mrYes then
if not MessageDlg(Format('Are you sure you want to open %d files?', [WARN_FILE_COUNT]), mtConfirmation, mbYesNoCancel, 0) <> mrYes then
exit;
end;
 
818,7 → 751,7
procedure TForm1.Theme_Dark;
begin
if IsThemeDark then exit;
TStyleManager.TrySetStyle('Windows10 SlateGray'); // do not translate
TStyleManager.TrySetStyle('Windows10 SlateGray');
Color := 1316887;
Font.Color := clCream;
//Memo2.Font.Color := clCream;
842,12 → 775,12
procedure TForm1.Theme_Light;
begin
if not IsThemeDark then exit;
TStyleManager.TrySetStyle('Windows'); // do not translate
TStyleManager.TrySetStyle('Windows');
Color := clBtnFace;
Font.Color := clWindowText;
//Memo2.Font.Color := clWindowText;
SynEdit1.ActiveLineColor := 14680010;
SynEdit1.Color := clCream;
SynEdit1.Color := clWindow;
SynEdit1.Font.Color := clWindowText;
SynEdit1.Gutter.Color := clBtnFace;
SynEdit1.Gutter.Font.Color := clWindowText;
906,9 → 839,9
procedure TForm1.WebBrowser1WindowClosing(ASender: TObject;
IsChildWindow: WordBool; var Cancel: WordBool);
resourcestring
SCloseRequest = 'A script has requested the window to be closed. The window of a standalone script would now close.';
LNG_CLOSE_REQUEST = 'A script has requested the window to be closed. The window of a standalone script would now close.';
begin
ShowMessage(SCloseRequest);
ShowMessage(LNG_CLOSE_REQUEST);
TWebBrowser(ASender).Clear;
Cancel := true;
end;
997,9 → 930,6
end;
 
procedure TForm1.FileModTimerTimer(Sender: TObject);
resourcestring
SChangeConflict = 'The file was changed in a different application BUT IT WAS ALSO MODIFIED HERE! Reload file AND LOSE CHANGES HERE?';
SChangeNotify = 'The file was changed in a different application! Reload file?';
begin
FileModTimer.Enabled := false;
if FileModLast <> FileAge(GetScrapFile) then
1007,7 → 937,7
FileModLast := FileAge(GetScrapFile);
if SynEdit1.Modified then
begin
if MessageDlg(SChangeConflict, mtWarning, mbYesNoCancel, 0) = mrYes then
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
begin
SynEdit1.Lines.LoadFromFile(GetScrapFile);
end;
1014,7 → 944,7
end
else
begin
if MessageDlg(SChangeNotify, mtConfirmation, mbYesNoCancel, 0) = mrYes then
if MessageDlg('The file was changed in a different application! Reload file?', mtConfirmation, mbYesNoCancel, 0) = mrYes then
begin
SynEdit1.Lines.LoadFromFile(GetScrapFile);
end;
1032,14 → 962,12
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
var
r: integer;
resourcestring
SWantToSave = 'Do you want to save?';
begin
if SynEdit1.Modified then
begin
if (ParamStr(1) <> '') or (FSaveAsFilename <> '') then
begin
r := MessageDlg(SWantToSave, mtConfirmation, mbYesNoCancel, 0);
r := MessageDlg('Do you want to save?', mtConfirmation, mbYesNoCancel, 0);
if r = mrCancel then
begin
CanClose := false;
1068,7 → 996,7
CurSearchTerm := '';
sScrapFile := GetScrapFile;
Caption := Caption + ' - ' + sScrapFile;
Application.Title := Format('%s - FastPHP', [ExtractFileName(sScrapFile)]); // do not translate!
Application.Title := Format('%s - FastPHP', [ExtractFileName(sScrapFile)]);
SrcRep := TSynEditFindReplace.Create(self);
SrcRep.Editor := SynEdit1;
SynEdit1.Gutter.Gradient := HighColorWindows;
1101,13 → 1029,13
end;
end;
 
var
FormShowRanOnce: boolean;
procedure TForm1.FormShow(Sender: TObject);
var
ScrapFile: string;
tmpFontSize: integer;
opts: TSynEditorOptions;
resourcestring
SFileAlreadyOpen = 'File "%s" is alrady open!';
begin
if FormShowRanOnce then exit; // If the theme is changed from normal to dark, OnShow will be called another time
FormShowRanOnce := true;
1140,7 → 1068,7
if GetLastError = ERROR_ALREADY_EXISTS then
begin
// TODO: It would be great if the window of that FastPHP instance would switched to foreground
ShowMessageFmt(SFileAlreadyOpen, [ScrapFile]);
ShowMessageFmt('File "%s" is alrady open!', [ScrapFile]);
Close;
end;
 
1167,6 → 1095,36
StartupTimer.Enabled := true;
end;
 
procedure TForm1.Save1Click(Sender: TObject);
begin
Button7.Click;
end;
 
procedure TForm1.Saveas1Click(Sender: TObject);
var
hMutexNew: THandle;
begin
if SaveDialog1.Execute then
begin
{$REGION 'Switch mutex'}
hMutexNew := CreateMutex(nil, True, PChar('FastPHP'+md5(UpperCase(SaveDialog1.FileName))));
if GetLastError = ERROR_ALREADY_EXISTS then
begin
ShowMessageFmt('Cannot save because file "%s", because it is alrady open in another FastPHP window!', [SaveDialog1.FileName]);
Close;
end;
 
if hMutex <> 0 then CloseHandle(hMutex); // Note: ReleaseMutex does not work as expected!
hMutex := hMutexNew;
{$ENDREGION}
 
FSaveAsFilename := SaveDialog1.FileName;
Caption := Copy(Caption, 1, Pos(' - ', Caption)-1) + ' - ' + FSaveAsFilename;
Application.Title := Format('%s - FastPHP', [ExtractFileName(FSaveAsFilename)]);
Button7.Click;
end;
end;
 
procedure TForm1.SaveToFile(filename: string);
var
ss: TStringStream;
1280,9 → 1238,6
function TForm1.GetScrapFile: string;
var
tmpPath: string;
resourcestring
SFileDoesNotExistsCreate = 'File %s does not exist. Create it?';
SPathDoesNotExistTryAgain = 'Path does not exist! Please try again.';
begin
if FSaveAsFilename <> '' then
begin
1304,7 → 1259,7
 
if not FileExists(result) then
begin
case MessageDlg(Format(SFileDoesNotExistsCreate, [result]), mtConfirmation, mbYesNoCancel, 0) of
case MessageDlg(Format('File %s does not exist. Create it?', [result]), mtConfirmation, mbYesNoCancel, 0) of
mrYes:
try
SaveToFile(result);
1370,7 → 1325,7
 
if not DirectoryExists(ExtractFilePath(OpenDialog3.FileName)) then
begin
MessageDlg(SPathDoesNotExistTryAgain, mtWarning, [mbOk], 0);
MessageDlg('Path does not exist! Please try again.', mtWarning, [mbOk], 0);
end
else
begin
1405,10 → 1360,6
var
IndexFile, chmFile, w, OriginalWord, url: string;
internalHtmlFile: string;
resourcestring
SChmFileNotAValidPHPDocumentation = 'The CHM file is not a valid PHP documentation. Cannot use help.';
SUnknownErrorCannotUseHelp = 'Unknown error. Cannot use help.';
SNoHelpAvailable = 'No help for "%s" available';
begin
if not Assigned(ChmIndex) then
begin
1451,7 → 1402,7
try
if not ParseCHM(chmFile) then
begin
MessageDlg(SChmFileNotAValidPHPDocumentation, mtError, [mbOk], 0);
MessageDlg('The CHM file is not a valid PHP documentation. Cannot use help.', mtError, [mbOk], 0);
exit;
end;
finally
1461,7 → 1412,7
 
if not FileExists(IndexFile) then
begin
MessageDlg(SUnknownErrorCannotUseHelp, mtError, [mbOk], 0);
MessageDlg('Unknown error. Cannot use help.', mtError, [mbOk], 0);
exit;
end;
end;
1484,14 → 1435,14
w := LowerCase(w);
CurSearchTerm := w;
 
internalHtmlFile := ChmIndex.ReadString('function', CurSearchTerm, ''); // do not translate
internalHtmlFile := ChmIndex.ReadString('function', CurSearchTerm, '');
if internalHtmlFile = '' then
internalHtmlFile := ChmIndex.ReadString('_HelpWords_', CurSearchTerm, ''); // do not translate
internalHtmlFile := ChmIndex.ReadString('_HelpWords_', CurSearchTerm, '');
if internalHtmlFile = '' then
begin
HelpTabsheet.TabVisible := false;
HlpPrevPageIndex := -1;
ShowMessageFmt(SNoHelpAvailable, [Originalword]);
ShowMessageFmt('No help for "%s" available', [Originalword]);
Exit;
end;
 
1530,6 → 1481,15
if SynEdit1.CanFocus then SynEdit1.SetFocus;
end;
 
procedure TForm1.GotoPHPdir1Click(Sender: TObject);
var
phpExe: string;
begin
phpExe := GetPHPExe;
if phpExe <> '' then
ShellExecute(Handle, 'open', 'explorer.exe', PChar(ExtractFilePath(phpExe)), '', SW_NORMAL);
end;
 
procedure TForm1.PageControl2Changing(Sender: TObject;
var AllowChange: Boolean);
begin
1541,6 → 1501,15
AllowChange := true;
end;
 
procedure TForm1.PHPShell1Click(Sender: TObject);
var
phpExe: string;
begin
phpExe := GetPHPExe;
if phpExe <> '' then
ShellExecute(Handle, 'open', PChar(phpExe), '-a', PChar(ExtractFilePath(phpExe)), SW_NORMAL);
end;
 
procedure TForm1.Memo2DblClick(Sender: TObject);
var
line: string;
1569,7 → 1538,7
{$ENDREGION}
 
{$REGION 'Possibility 2: on line xx'}
_process(ExtractFileName(GetScrapFile) + ' on line '); // do not translate!
_process(ExtractFileName(GetScrapFile) + ' on line ');
{$ENDREGION}
end;
 
1624,7 → 1593,7
{$ENDREGION}
 
{$REGION 'Possibility 2: on line xx'}
_process(ExtractFileName(GetScrapFile) + ' on line '); // do not translate!
_process(ExtractFileName(GetScrapFile) + ' on line ');
{$ENDREGION}
 
result := cont;
1643,7 → 1612,7
 
function TForm1.OutputNotifyCallback(const data: AnsiString): boolean;
begin
result := TreeView1.FillWithFastPHPData(string(data));
result := TreeView1.FillWithFastPHPData(data);
end;
 
end.