11,8 → 11,7 |
You can obtain SynEdit via Embarcadero GetIt |
*) |
|
// TODO: "DragAcceptFiles" does not work with Delphi Dark Design Template !!! |
|
// TODO: "crHourGlass" does not work if F9 is pressed! |
// TODO: if a scrapfile is already open, create a new scrap file (scrap2.php) |
// TODO: localize |
// TODO: wieso geht copy paste im twebbrowser nicht??? |
22,6 → 21,19 |
// 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 |
|
30,12 → 42,12 |
// - verschiedene php versionen? |
// - webbrowser1 nur laden, wenn man den tab anwählt? |
// - doppelklick auf tab soll diesen schließen |
// - Onlinehelp (www) aufrufen |
// - Onlinehelp (www) aufrufen oder CHM datei |
// - Let all colors be adjustable |
// - code in bildschirmmitte (horizontal)? |
// - search in files of a directory |
// - multi tab? |
// - DDE (drag n drop) |
// - Files in multiple tabs? |
// - Configurable tabulator display-width |
|
interface |
|
115,6 → 127,9 |
FileModTimer: TTimer; |
GotoPHPdir1: TMenuItem; |
PHPShell1: TMenuItem; |
ActionSaveAs: TAction; |
ActionGoToPHPDir: TAction; |
ActionPHPInteractiveShell: TAction; |
procedure Run(Sender: TObject); |
procedure RunConsole(Sender: TObject); |
procedure FormShow(Sender: TObject); |
166,8 → 181,6 |
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); |
174,10 → 187,11 |
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; |
187,6 → 201,8 |
gOnlineHelpWord: string; |
{$ENDIF} |
FileModLast: TDateTime; |
FormShowRanOnce: boolean; |
BrowserLoadedOnce: boolean; |
procedure Help; |
function InputRequestCallback(var data: AnsiString): boolean; |
function OutputNotifyCallback(const data: AnsiString): boolean; |
249,12 → 265,15 |
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 ? |
|
InputQuery('Go to', 'Line number:', val); |
if not TryStrToInt(val, lineno) then |
if not InputQuery(SGoTo, SLineNumber, val) or |
not TryStrToInt(val, lineno) then |
begin |
if SynEdit1.CanFocus then SynEdit1.SetFocus; |
exit; |
262,6 → 281,15 |
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; |
285,6 → 313,15 |
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; |
325,6 → 362,33 |
*) |
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; |
407,6 → 471,8 |
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 |
|
419,16 → 485,17 |
ind := GuessIndent(SynEdit1.Lines); |
if ind <> -1 then val := IntToStr(ind); |
|
InputQuery('Spaces to tabs', 'Indent:', val); // TODO: handle CANCEL correctly... |
if TryStrToInt(Trim(val), ind) then |
if not InputQuery(SSpacesToLabs, SIndent, val) or |
not 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 |
447,8 → 514,6 |
SrcRep.FindExecute; |
end; |
|
var |
firstTimeBrowserLoad: boolean = true; |
procedure TForm1.Run(Sender: TObject); |
var |
bakTS: TTabSheet; |
457,7 → 522,7 |
begin |
memo2.Lines.Text := ''; |
|
if firstTimeBrowserLoad then |
if not BrowserLoadedOnce then |
begin |
bakTS := PageControl1.ActivePage; |
try |
466,12 → 531,12 |
finally |
PageControl1.ActivePage := bakTS; |
end; |
firstTimeBrowserLoad := false; |
BrowserLoadedOnce := true; |
end |
else |
Webbrowser1.Clear; |
|
Screen.Cursor := crHourGlass; |
Screen.Cursor := crHourGlass; // TODO: Doesn't work with F9 |
Application.ProcessMessages; |
|
try |
521,10 → 586,12 |
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('Are you sure you want to open %d files?', [WARN_FILE_COUNT]), mtConfirmation, mbYesNoCancel, 0) <> mrYes then |
if not MessageDlg(Format(SAreYouSure, [WARN_FILE_COUNT]), mtConfirmation, mbYesNoCancel, 0) <> mrYes then |
exit; |
end; |
|
751,7 → 818,7 |
procedure TForm1.Theme_Dark; |
begin |
if IsThemeDark then exit; |
TStyleManager.TrySetStyle('Windows10 SlateGray'); |
TStyleManager.TrySetStyle('Windows10 SlateGray'); // do not translate |
Color := 1316887; |
Font.Color := clCream; |
//Memo2.Font.Color := clCream; |
775,12 → 842,12 |
procedure TForm1.Theme_Light; |
begin |
if not IsThemeDark then exit; |
TStyleManager.TrySetStyle('Windows'); |
TStyleManager.TrySetStyle('Windows'); // do not translate |
Color := clBtnFace; |
Font.Color := clWindowText; |
//Memo2.Font.Color := clWindowText; |
SynEdit1.ActiveLineColor := 14680010; |
SynEdit1.Color := clWindow; |
SynEdit1.Color := clCream; |
SynEdit1.Font.Color := clWindowText; |
SynEdit1.Gutter.Color := clBtnFace; |
SynEdit1.Gutter.Font.Color := clWindowText; |
839,9 → 906,9 |
procedure TForm1.WebBrowser1WindowClosing(ASender: TObject; |
IsChildWindow: WordBool; var Cancel: WordBool); |
resourcestring |
LNG_CLOSE_REQUEST = 'A script has requested the window to be closed. The window of a standalone script would now close.'; |
SCloseRequest = 'A script has requested the window to be closed. The window of a standalone script would now close.'; |
begin |
ShowMessage(LNG_CLOSE_REQUEST); |
ShowMessage(SCloseRequest); |
TWebBrowser(ASender).Clear; |
Cancel := true; |
end; |
930,6 → 997,9 |
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 |
937,7 → 1007,7 |
FileModLast := FileAge(GetScrapFile); |
if SynEdit1.Modified then |
begin |
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 |
if MessageDlg(SChangeConflict, mtWarning, mbYesNoCancel, 0) = mrYes then |
begin |
SynEdit1.Lines.LoadFromFile(GetScrapFile); |
end; |
944,7 → 1014,7 |
end |
else |
begin |
if MessageDlg('The file was changed in a different application! Reload file?', mtConfirmation, mbYesNoCancel, 0) = mrYes then |
if MessageDlg(SChangeNotify, mtConfirmation, mbYesNoCancel, 0) = mrYes then |
begin |
SynEdit1.Lines.LoadFromFile(GetScrapFile); |
end; |
962,12 → 1032,14 |
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('Do you want to save?', mtConfirmation, mbYesNoCancel, 0); |
r := MessageDlg(SWantToSave, mtConfirmation, mbYesNoCancel, 0); |
if r = mrCancel then |
begin |
CanClose := false; |
996,7 → 1068,7 |
CurSearchTerm := ''; |
sScrapFile := GetScrapFile; |
Caption := Caption + ' - ' + sScrapFile; |
Application.Title := Format('%s - FastPHP', [ExtractFileName(sScrapFile)]); |
Application.Title := Format('%s - FastPHP', [ExtractFileName(sScrapFile)]); // do not translate! |
SrcRep := TSynEditFindReplace.Create(self); |
SrcRep.Editor := SynEdit1; |
SynEdit1.Gutter.Gradient := HighColorWindows; |
1029,13 → 1101,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; |
1068,7 → 1140,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('File "%s" is alrady open!', [ScrapFile]); |
ShowMessageFmt(SFileAlreadyOpen, [ScrapFile]); |
Close; |
end; |
|
1095,36 → 1167,6 |
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; |
1238,6 → 1280,9 |
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 |
1259,7 → 1304,7 |
|
if not FileExists(result) then |
begin |
case MessageDlg(Format('File %s does not exist. Create it?', [result]), mtConfirmation, mbYesNoCancel, 0) of |
case MessageDlg(Format(SFileDoesNotExistsCreate, [result]), mtConfirmation, mbYesNoCancel, 0) of |
mrYes: |
try |
SaveToFile(result); |
1325,7 → 1370,7 |
|
if not DirectoryExists(ExtractFilePath(OpenDialog3.FileName)) then |
begin |
MessageDlg('Path does not exist! Please try again.', mtWarning, [mbOk], 0); |
MessageDlg(SPathDoesNotExistTryAgain, mtWarning, [mbOk], 0); |
end |
else |
begin |
1360,6 → 1405,10 |
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 |
1402,7 → 1451,7 |
try |
if not ParseCHM(chmFile) then |
begin |
MessageDlg('The CHM file is not a valid PHP documentation. Cannot use help.', mtError, [mbOk], 0); |
MessageDlg(SChmFileNotAValidPHPDocumentation, mtError, [mbOk], 0); |
exit; |
end; |
finally |
1412,7 → 1461,7 |
|
if not FileExists(IndexFile) then |
begin |
MessageDlg('Unknown error. Cannot use help.', mtError, [mbOk], 0); |
MessageDlg(SUnknownErrorCannotUseHelp, mtError, [mbOk], 0); |
exit; |
end; |
end; |
1435,14 → 1484,14 |
w := LowerCase(w); |
CurSearchTerm := w; |
|
internalHtmlFile := ChmIndex.ReadString('function', CurSearchTerm, ''); |
internalHtmlFile := ChmIndex.ReadString('function', CurSearchTerm, ''); // do not translate |
if internalHtmlFile = '' then |
internalHtmlFile := ChmIndex.ReadString('_HelpWords_', CurSearchTerm, ''); |
internalHtmlFile := ChmIndex.ReadString('_HelpWords_', CurSearchTerm, ''); // do not translate |
if internalHtmlFile = '' then |
begin |
HelpTabsheet.TabVisible := false; |
HlpPrevPageIndex := -1; |
ShowMessageFmt('No help for "%s" available', [Originalword]); |
ShowMessageFmt(SNoHelpAvailable, [Originalword]); |
Exit; |
end; |
|
1481,15 → 1530,6 |
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 |
1501,15 → 1541,6 |
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; |
1538,7 → 1569,7 |
{$ENDREGION} |
|
{$REGION 'Possibility 2: on line xx'} |
_process(ExtractFileName(GetScrapFile) + ' on line '); |
_process(ExtractFileName(GetScrapFile) + ' on line '); // do not translate! |
{$ENDREGION} |
end; |
|
1593,7 → 1624,7 |
{$ENDREGION} |
|
{$REGION 'Possibility 2: on line xx'} |
_process(ExtractFileName(GetScrapFile) + ' on line '); |
_process(ExtractFileName(GetScrapFile) + ' on line '); // do not translate! |
{$ENDREGION} |
|
result := cont; |
1612,7 → 1643,7 |
|
function TForm1.OutputNotifyCallback(const data: AnsiString): boolean; |
begin |
result := TreeView1.FillWithFastPHPData(data); |
result := TreeView1.FillWithFastPHPData(string(data)); |
end; |
|
end. |