diff --git a/res/icons/os_mac.png b/res/icons/os_mac.png new file mode 100644 index 00000000..03c5076d Binary files /dev/null and b/res/icons/os_mac.png differ diff --git a/res/icons/os_unix.png b/res/icons/os_unix.png new file mode 100644 index 00000000..06d97b35 Binary files /dev/null and b/res/icons/os_unix.png differ diff --git a/res/icons/os_windows.png b/res/icons/os_windows.png new file mode 100644 index 00000000..26b6ba8a Binary files /dev/null and b/res/icons/os_windows.png differ diff --git a/source/main.dfm b/source/main.dfm index f762e01d..5f2c0811 100644 --- a/source/main.dfm +++ b/source/main.dfm @@ -5914,6 +5914,99 @@ object MainForm: TMainForm 71A703AAA444BA1B0000092995BA9A525B530000000049454E44AE426082} Name = 'PngImage120' Background = clWindow + end + item + PngImage.Data = { + 89504E470D0A1A0A0000000D49484452000000100000001008060000001FF3FF + 61000000017352474200AECE1CE90000001874455874536F6674776172650050 + 61696E742E4E45542076332E3336A9E7E225000002FD4944415478DAA5D34B68 + 13511406E07F3A339934AD695293D6E2A4C6A65A1F25ADF8228228B516C40754 + 487CE1AAD04D17922222080A565CB8880B0545178A82A201110575A56E4CC4D6 + 56EBFB55D3E6D6E6D53A69A6E96426337188A8050541CFEEC2E5BBE71EFE43E1 + 3F8B9A79C85EE80848A5A25F4B46207F14216B55A4ACB93560EF3874F2AF40E6 + EE450FD57B26646830213F26427A3705811490363870DF5BD55D57DF1C6C5FB1 + 9FFCB8DF37728B2FE428C74F40E869F773E66480AEA6A17C9AC4D40709C22830 + D5EAC395B210E8D925E0E755876D261B496547F97129EFA9175A82BF3A08EC08 + B115310FC5A890DF4E221351F055EF20BEAF13D7866FC0E234C0626351CEB0C8 + AA1A26E20C7CAE23DF0139FA8ECF5DEE8A1A9C796882849C0EA4A30508B94AF4 + 776E402F79086B1D0B4B390B23C3409055948E2F42DBC20E5F11889F3BE895A5 + D1EBD9DA65982854A14C8C83ED7D0049B192DB2B73FC7821814A278B591C039A + A291D2812553EDD8B5A5932A025DD7DEF86B4D2581D2B2720C900C22D1712C32 + E6C9DE554AF8EA93A35E6E2E0D6B8D0EE8EDCB1A90F8AA62B3F54078DDDA9635 + 4560E785C1C262BB192C43E3E9481AB1CF71E4869338B53B19367229C74B8DE3 + 27310C83FE3AABDA30879D8F9AAA95BE26776390BAFA74CC73FED197D0B6C61A + C4D2129E4505084371D4621A0796DF042BF6C3E556405B9A88022BCFC9F73014 + 5B4F9805877D0BEA5D616AEDE93EBFD3541A585D5789576319BC199E80A803DB + 9702EBD51ED86C229C0B9360CA1BF4D44C43CD0E62207389AC6AD9E3280669D3 + D98190DB6EF6D8CD1CFAA3698C4452C87E4EE0D8D6142A22E750EB123077BE04 + 181783D2DE2331A62266BF136C6A5EE62B025D674385E5761A160E2421286192 + 56BC7DCF9238B6E1014122C4D735C461A936037A22A13CC650BC0DE29C1E5FB3 + FEFF22F07CF025AF0F83CCCC77E8F1732FF7E178C028BF2802C60A270A3487BC + D887D7E20924D44647DBC656F2DB32CDACD7AF5EF0D9E8BD6EB369C24F976850 + 3433A62917A12B9604DD6E77F71FB7F15FEA1BE8C34624405029730000000049 + 454E44AE426082} + Name = 'PngImage125' + Background = clWindow + end + item + PngImage.Data = { + 89504E470D0A1A0A0000000D49484452000000100000001008060000001FF3FF + 61000000017352474200AECE1CE90000001874455874536F6674776172650050 + 61696E742E4E45542076332E3336A9E7E225000002BD4944415478DA95936B48 + 145114C7CFCCECECB8BB5AEDB6D9CEAEEFCC4AC957F8D81451CBECA115141414 + 1AA150501FFA14284464611969914181848295655F943E94F4A0882529C20F51 + 511B413E5673B56D57D7D999B933DDBB9B0B9B91347007EEE3FF3BFF73EEB914 + 2CF215145598139357B50A0199EFEFEDA8F8739FFA97383BAF9C894F4A712060 + F3630CBA96BB9DAD27FF0B505E75684F5252E2FD282D3DEE9972E5DEEEBAEE5A + 149091919E28CBB2CE6C8E75AE5E5F5CC2B1A8DE33E56E1E74BCA4341A56A8AE + AEFCD4D6D6A62E0058F8D4CCACDC9C9B0909091B589685E1E16F134EE7D7FE95 + 169BD966B356D20CADF77A7D303C32FE5AA134BB871C7D636100CFA7C6E76F2C + 1E2A2BB59B689A028454408A028AA20276038220C2EC5C0002A2041E9F34E31A + 1B3DFCE441676F1890B6AEB0EB60CDFE1ABD8E0349944142080B1148582C6291 + 28C9C17544B140536AD38DCBA74F45A49057B47D7AC7B6CD4612958824390440 + 6410181E7EEC40A5A3DCBC49B3F6D285335311801C7B955A565A080A0A0190AC + 0445F362F9F73C202A9FFB7BDAD316DC42A67DD75C6ED69A2892BBAAAA11D5A5 + 288AFC703D14F8F173564DB646A7B75FB9F83102905DBCD761E5CDF6E5C6A5A0 + 65499E345E5580B0889EA699E0D119FF1CF8FDDE014EF155F5F4744B61C0A69D + 758D1CC79D8DB3C6825EAF0786A6415195A01BE28061180CA1419210787D3E78 + F7C1F96CF071777918507FAC819FF4085FE26C169DC9B80CB45A164878850020 + E48080487D028200AFDEBC7FFEB4EF5A694423D51E6D3C67883136D86C168831 + 187054D20FD885A2864EA91488B20413DFDD303A32B2F54E47F3A30840DD9113 + 5A915AF2223925A5C0C69BF0062EDAB417371482684334301A1626DDD3E09E74 + DDBBDAD2B0EFAF6FA1B6EEB85990E85BB12B4C5BB41A784BA968C02F04242180 + 4A684653841FD5433DC71C6839DFE49DD7FC023B9B41206F39112F0000000049 + 454E44AE426082} + Name = 'PngImage123' + Background = clWindow + end + item + PngImage.Data = { + 89504E470D0A1A0A0000000D49484452000000100000001008060000001FF3FF + 61000000017352474200AECE1CE90000001874455874536F6674776172650050 + 61696E742E4E45542076332E3336A9E7E225000002964944415478DA6364C002 + 3838B8947EFDFAB50AC854151212DCF5E1C387B43F7F7EBFC7A696119B201B1B + FBDC3F7FFE2681D8E2E2620C1F3E7C9CFBFDFBD714A20DD0D2D2DE2D2C2CECC2 + C1C10E348C8D61FBF69DD7FFFDFBA345B4017E7EFE5BB4241E7B73F070323CFD + A8C23077FED2E74003A4883620DC8E7FF9846A860816415E86B56B3F33144EFA + F3FBF7EF9FC27FFEFCF94C94019E1EAEFB7283051D3998181858951219A2E2D2 + 195EBD7A55F6F3E78F6E8206303333C7AD58B17CA1AD8D3503370F0F03373737 + 43707028C3C68D5B3E7073731A7FFEFCE91E4E033839B9A4D958D96E5FBE7291 + 5354548481959595E1FDFB0F406FAC63282C2C660046E585A2A222A3CECE8EFF + 580DE0E1E1CDCACACA9CDADEDECAF0FFFF7F0646468834304D30B8BB7B329C3E + 7D86818989C9F6EBD72F47300C30323266BE77EFDEC523470E6A6B6A6A823581 + A210065252D21956AE5C0514FF590F74491386011CEC1C1622423CC76FDCBE07 + F40A27C3CF9F3F19D8D9D9E106E4E4E4312C5EBC94E1C78FEF3D40034A510CB8 + B221D884F1FBED442ED607599BEEA53364163433FCFBF70F1C0620F0E3C56E86 + C2FC0486859B3E324CA9535A9C5A733D0EC58047EB952E09F2BED2650246DBA6 + 630C0C1BAFF8322C5DBA086EFBED6353193E5CA86278FB8981C1DA9CFFF537C1 + 086329E3FEC770031EAE963E2622F4D112C4FB0724B6DC0C63084B9B01D67CF7 + EE5D86791D610C5511F7189898811A806ABEFF913C2FE276DB086EC0A5058ACF + 85B85E4970F33232805CBDE5000BC3F2CBF640FFFE60387CE82883BFE92F86E9 + 556C0CBF7F33327CF92DB6F1CB6FE922DDF043F7E0067C79759C79F3EC72D3DF + 1F1FB8FDFFF321F8EC8DBF9766EDFBDB088C892FECEC1C2C61962CE1AE86FFF3 + D97825A78735DC6A478E7A004A4F0720512A80D90000000049454E44AE426082} + Name = 'PngImage124' + Background = clWindow end> PngOptions = [pngBlendOnDisabled, pngGrayscaleOnDisabled] Left = 104 diff --git a/source/texteditor.dfm b/source/texteditor.dfm index 52761268..2d95a071 100644 --- a/source/texteditor.dfm +++ b/source/texteditor.dfm @@ -4,7 +4,7 @@ object frmTextEditor: TfrmTextEditor BorderStyle = bsSizeToolWin Caption = 'Text editor' ClientHeight = 95 - ClientWidth = 215 + ClientWidth = 253 Color = clBtnFace Constraints.MinHeight = 100 Constraints.MinWidth = 130 @@ -20,12 +20,12 @@ object frmTextEditor: TfrmTextEditor OnDestroy = FormDestroy OnShow = FormShow DesignSize = ( - 215 + 253 95) PixelsPerInch = 96 TextHeight = 13 object lblTextLength: TLabel - Left = 103 + Left = 137 Top = 77 Width = 65 Height = 13 @@ -37,7 +37,7 @@ object frmTextEditor: TfrmTextEditor object memoText: TTntMemo Left = 0 Top = 0 - Width = 215 + Width = 253 Height = 72 Align = alTop Anchors = [akLeft, akTop, akRight, akBottom] @@ -52,7 +52,7 @@ object frmTextEditor: TfrmTextEditor object tlbStandard: TToolBar Left = 0 Top = 73 - Width = 97 + Width = 131 Height = 22 Align = alNone Anchors = [akLeft, akBottom] @@ -69,16 +69,24 @@ object frmTextEditor: TfrmTextEditor ImageIndex = 62 OnClick = btnWrapClick end - object btnLoadText: TToolButton + object btnLinefeedStyle: TToolButton Left = 23 Top = 0 + Caption = 'Linefeed Style' + DropdownMenu = popupLinefeedStyle + ImageIndex = 123 + Style = tbsDropDown + end + object btnLoadText: TToolButton + Left = 61 + Top = 0 Hint = 'Load textfile' Caption = 'Load textfile' ImageIndex = 52 OnClick = btnLoadTextClick end object btnCancel: TToolButton - Left = 46 + Left = 84 Top = 0 Hint = 'Cancel' Caption = 'Cancel' @@ -86,7 +94,7 @@ object frmTextEditor: TfrmTextEditor OnClick = btnCancelClick end object btnApply: TToolButton - Left = 69 + Left = 107 Top = 0 Hint = 'Apply changes' Caption = 'Apply changes' @@ -94,4 +102,24 @@ object frmTextEditor: TfrmTextEditor OnClick = btnApplyClick end end + object popupLinefeedStyle: TPopupMenu + Images = MainForm.PngImageListMain + Left = 8 + Top = 16 + object menuWindowsLF: TMenuItem + Caption = 'Windows linefeeds' + ImageIndex = 123 + OnClick = SelectLinefeedStyle + end + object menuUnixLF: TMenuItem + Caption = 'UNIX linefeeds' + ImageIndex = 125 + OnClick = SelectLinefeedStyle + end + object menuMacLF: TMenuItem + Caption = 'Mac OS linefeeds' + ImageIndex = 124 + OnClick = SelectLinefeedStyle + end + end end diff --git a/source/texteditor.pas b/source/texteditor.pas index 6dc6d76b..6b88bafc 100644 --- a/source/texteditor.pas +++ b/source/texteditor.pas @@ -4,7 +4,7 @@ interface uses Windows, Classes, Graphics, Forms, Controls, helpers, StdCtrls, TntStdCtrls, VirtualTrees, - ComCtrls, ToolWin, Dialogs, SysUtils; + ComCtrls, ToolWin, Dialogs, SysUtils, Menus, WideStrUtils; {$I const.inc} @@ -17,6 +17,11 @@ type btnApply: TToolButton; btnCancel: TToolButton; lblTextLength: TLabel; + btnLinefeedStyle: TToolButton; + popupLinefeedStyle: TPopupMenu; + menuWindowsLF: TMenuItem; + menuUnixLF: TMenuItem; + menuMacLF: TMenuItem; procedure btnApplyClick(Sender: TObject); procedure btnCancelClick(Sender: TObject); procedure btnLoadTextClick(Sender: TObject); @@ -27,10 +32,13 @@ type procedure memoTextKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); procedure FormCreate(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); + procedure SelectLinefeedStyle(Sender: TObject); private { Private declarations } FModified: Boolean; FStopping: Boolean; + DetectedLineFeedStyle: Integer; + SelectedLineFeedStyle: Integer; procedure SetModified(NewVal: Boolean); property Modified: Boolean read FModified write SetModified; public @@ -47,19 +55,60 @@ uses main; {$R *.dfm} +const + NL_WIN = 0; + NL_UNX = 1; + NL_MAC = 2; + function TfrmTextEditor.GetText: WideString; begin Result := memoText.Text; + // Convert linefeed style back to selected + if SelectedLineFeedStyle = NL_UNX then + Result := WideStringReplace(Result, CRLF, #10, [rfReplaceAll]) + else if SelectedLineFeedStyle = NL_MAC then + Result := WideStringReplace(Result, CRLF, #10#13, [rfReplaceAll]) end; + procedure TfrmTextEditor.SetText(text: WideString); begin + // Automatic detection of linefeed style + if Pos(CRLF, text) > 0 then DetectedLineFeedStyle := NL_WIN + else if Pos(#10#13, text) > 0 then DetectedLineFeedStyle := NL_MAC + else if Pos(#10, text) > 0 then DetectedLineFeedStyle := NL_UNX + else DetectedLineFeedStyle := NL_WIN; + SelectLinefeedStyle(popupLineFeedStyle.Items[DetectedLineFeedStyle]); + // Unify linefeeds so they're displayed properly + text := WideStringReplace(text, #13, '', [rfReplaceAll]); + text := WideStringReplace(text, #10, CRLF, [rfReplaceAll]); // TODO: Find out why the Delphi IDE insists hinting that this // property is ANSI when it is in fact a WideString. memoText.Text := text; end; + +procedure TfrmTextEditor.SelectLinefeedStyle(Sender: TObject); +var + Selected, Detected: TMenuItem; + Menu: TMenu; +begin + Selected := Sender as TMenuItem; + Menu := Selected.GetParentMenu; + Detected := Menu.Items[DetectedLineFeedStyle]; + Menu.Items[NL_WIN].Caption := 'Windows® linefeeds'; + Menu.Items[NL_UNX].Caption := 'UNIX linefeeds'; + Menu.Items[NL_MAC].Caption := 'Mac OS linefeeds'; + Detected.Caption := Detected.Caption + ' (detected)'; + Selected.Default := True; + btnLineFeedStyle.Hint := Selected.Caption; + btnLineFeedStyle.ImageIndex := Selected.ImageIndex; + SelectedLineFeedStyle := Selected.MenuIndex; + Modified := True; +end; + + procedure TfrmTextEditor.SetMaxLength(len: integer); begin // Input: Length in number of bytes.