From 426cd0d2c85afd108ef803348d0ecd9e9b8670f1 Mon Sep 17 00:00:00 2001 From: Basile Burg Date: Tue, 22 Jan 2019 10:23:14 +0100 Subject: [PATCH] fix #148 - Use common shortcuts to copy and paste from the terminal --- etc/terminal/gtk2term.pas | 9 +++++ etc/terminal/terminalctrls.pas | 18 ++++++++++ src/u_term.lfm | 1 + src/u_term.pas | 65 +++++++++++++++++++++++++++++++++- 4 files changed, 92 insertions(+), 1 deletion(-) diff --git a/etc/terminal/gtk2term.pas b/etc/terminal/gtk2term.pas index b2f19264..b14af311 100644 --- a/etc/terminal/gtk2term.pas +++ b/etc/terminal/gtk2term.pas @@ -88,6 +88,10 @@ var vte_terminal_feed_child: procedure(terminal: PVteTerminal; data: PChar; length: PtrInt); cdecl; + vte_terminal_copy_clipboard: procedure(terminal: PVteTerminal); cdecl; + + vte_terminal_paste_clipboard: procedure(terminal: PVteTerminal); cdecl; + vte_get_user_shell: function(): PChar; function Gtk2TermLoad: Boolean; @@ -134,9 +138,14 @@ begin 'vte_terminal_feed'); @vte_terminal_feed_child := GetProcAddress(Lib, 'vte_terminal_feed_child'); + @vte_terminal_copy_clipboard := GetProcAddress(Lib, + 'vte_terminal_copy_clipboard'); + @vte_terminal_paste_clipboard := GetProcAddress(Lib, + 'vte_terminal_paste_clipboard'); @vte_get_user_shell := GetProcAddress(Lib, 'vte_get_user_shell'); + // assume all or none Loaded := @vte_terminal_new <> nil; diff --git a/etc/terminal/terminalctrls.pas b/etc/terminal/terminalctrls.pas index 39a43df6..9cecdfda 100644 --- a/etc/terminal/terminalctrls.pas +++ b/etc/terminal/terminalctrls.pas @@ -51,6 +51,8 @@ type procedure Reparent; // Sends a command, as it would be manually typed. Line feed is automatically added. procedure Command(const data: string); + procedure copyToClipboard(); + procedure pasteFromClipboard(); published {$ifdef windows} property terminalProgram: string read fTermProgram write fTermProgram; @@ -301,6 +303,22 @@ begin {$endif} end; +procedure TTerminal.copyToClipboard(); +begin + {$ifdef hasgtk2term} + if assigned(fTerminalHanlde) and assigned(vte_terminal_copy_clipboard) then + vte_terminal_copy_clipboard(fTerminalHanlde); + {$endif} +end; + +procedure TTerminal.pasteFromClipboard(); +begin + {$ifdef hasgtk2term} + if assigned(fTerminalHanlde) and assigned(vte_terminal_paste_clipboard) then + vte_terminal_paste_clipboard(fTerminalHanlde); + {$endif} +end; + function TerminalAvailable: Boolean; begin {$ifdef hasgtk2term} diff --git a/src/u_term.lfm b/src/u_term.lfm index b94d3aaa..7e266485 100644 --- a/src/u_term.lfm +++ b/src/u_term.lfm @@ -5,6 +5,7 @@ inherited TermWidget: TTermWidget Caption = 'Terminal' ClientHeight = 296 ClientWidth = 674 + OnShortCut = FormShortCut inherited Back: TPanel Height = 296 Width = 674 diff --git a/src/u_term.pas b/src/u_term.pas index 0af3a806..d7df24fa 100644 --- a/src/u_term.pas +++ b/src/u_term.pas @@ -5,12 +5,25 @@ unit u_term; interface uses - Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, + Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, LCLType, + ActnList, LMessages, u_widget, TerminalCtrls, u_interfaces, u_writableComponent, u_observer, u_common, u_synmemo; type + TTerminalShortcuts = class(TPersistent) + private + fCopy: TShortCut; + fPaste: TShortCut; + published + property copy: TShortCut read fCopy write fCopy; + property paste: TShortCut read fPaste write fPaste; + public + constructor create; + procedure assign(source: TPersistent); override; + end; + // Terminal options TTerminalOptionsBase = class(TWritableLfmTextComponent) private @@ -22,7 +35,9 @@ type fFollowExplorer: boolean; fScrollbackLines: longword; fFont: TFont; + fShortcuts: TTerminalShortcuts; procedure setFont(value: TFont); + procedure setShortcuts(value: TTerminalShortcuts); public constructor create(AOwner: TComponent); override; destructor destroy; override; @@ -36,6 +51,7 @@ type property followProjects: boolean read fFollowProjects write fFollowProjects; property followExplorer: boolean read fFollowExplorer write fFollowExplorer; property scrollbackLines: longword read fScrollbackLines write fScrollbackLines default 512; + property shortcuts: TTerminalShortcuts read fShortcuts write fShortcuts; end; // Editable and reversible Terminal options @@ -56,6 +72,7 @@ type TTermWidget = class(TDexedWidget, IDocumentObserver, IProjectObserver, IMiniExplorerObserver) procedure ContentPaint(Sender: TObject); + procedure FormShortCut(var Msg: TLMKey; var Handled: Boolean); private fTerm: TTerminal; fOpts: TTerminalOptions; @@ -92,6 +109,25 @@ implementation const optFname = 'terminal.txt'; +constructor TTerminalShortcuts.create; +begin + fCopy := KeyToShortCut(word(char('C')), [ssCtrl]); + fPaste:= KeyToShortCut(word(char('V')), [ssCtrl]); +end; + +procedure TTerminalShortcuts.assign(source: TPersistent); +var + s: TTerminalShortcuts; +begin + if source is TTerminalShortcuts then + begin + s := TTerminalShortcuts(source); + fCopy := s.fCopy; + fPaste:= s.fPaste; + end + else inherited; +end; + constructor TTerminalOptionsBase.create(AOwner: TComponent); begin inherited; @@ -102,11 +138,13 @@ begin fFont.Name:= 'Monospace'; fFont.Size:= 12; fScrollbackLines:=512; + fShortcuts := TTerminalShortcuts.create; end; destructor TTerminalOptionsBase.destroy; begin fFont.Free; + fShortcuts.Free; inherited; end; @@ -115,6 +153,11 @@ begin fFont.Assign(value); end; +procedure TTerminalOptionsBase.setShortcuts(value: TTerminalShortcuts); +begin + fShortcuts.assign(value); +end; + procedure TTerminalOptionsBase.assign(value: TPersistent); var s: TTerminalOptionsBase; @@ -131,6 +174,7 @@ begin fFont.Height:=fFont.Height-1; fFont.Assign(s.font); fFont.EndUpdate; + fShortcuts.assign(s.fShortcuts); fScrollbackLines := s.fScrollbackLines; end else inherited; @@ -204,6 +248,7 @@ var f: string; begin inherited; + toolbarVisible:=false; fTerm := TTerminal.Create(self); fTerm.Align:= alClient; @@ -247,6 +292,24 @@ begin fOpts.applyChanges; end; +procedure TTermWidget.FormShortCut(var Msg: TLMKey; var Handled: Boolean); +var + s: TShortCut; +begin + Handled := false; + s := KeyToShortCut(Msg.CharCode, KeyDataToShiftState(Msg.KeyData)); + if s = fOpts.shortcuts.copy then + begin + fTerm.copyToClipboard(); + handled := true; + end + else if s = fOpts.shortcuts.paste then + begin + fTerm.pasteFromClipboard(); + handled := true; + end; +end; + procedure TTermWidget.mnexDirectoryChanged(const directory: string); begin if fOpts.followExplorer and directory.dirExists and