]> git.proxmox.com Git - mirror_xterm.js.git/blob - src/handlers/Clipboard.ts
Merge remote-tracking branch 'ups/master' into 207_selection_manager
[mirror_xterm.js.git] / src / handlers / Clipboard.ts
1 /**
2 * Clipboard handler module: exports methods for handling all clipboard-related events in the
3 * terminal.
4 * @module xterm/handlers/Clipboard
5 * @license MIT
6 */
7
8 import { ITerminal, ISelectionManager } from '../Interfaces';
9
10 interface IWindow extends Window {
11 clipboardData?: {
12 getData(format: string): string;
13 setData(format: string, data: string);
14 };
15 }
16
17 declare var window: IWindow;
18
19 const SPACE_CHAR = String.fromCharCode(32);
20 const NON_BREAKING_SPACE_CHAR = String.fromCharCode(160);
21 const ALL_NON_BREAKING_SPACE_REGEX = new RegExp(NON_BREAKING_SPACE_CHAR, 'g');
22
23 /**
24 * Prepares text copied from terminal selection, to be saved in the clipboard by:
25 * 1. stripping all trailing white spaces
26 * 2. converting all non-breaking spaces to regular spaces
27 * @param {string} text The copied text that needs processing for storing in clipboard
28 * @returns {string}
29 */
30 export function prepareTextForClipboard(text: string): string {
31 // TODO: Pass an unjoined string array into this function so not splitting is needed
32 return text.split('\n').map(line => {
33 return line.replace(ALL_NON_BREAKING_SPACE_REGEX, SPACE_CHAR);
34 }).join('\n');
35 }
36
37 /**
38 * Prepares text to be pasted into the terminal by normalizing the line endings
39 * @param text The pasted text that needs processing before inserting into the terminal
40 */
41 export function prepareTextForTerminal(text: string, isMSWindows: boolean): string {
42 if (isMSWindows) {
43 return text.replace(/\r?\n/g, '\n');
44 }
45 return text;
46 }
47
48 /**
49 * Binds copy functionality to the given terminal.
50 * @param {ClipboardEvent} ev The original copy event to be handled
51 */
52 export function copyHandler(ev: ClipboardEvent, term: ITerminal, selectionManager: ISelectionManager) {
53 // We cast `window` to `any` type, because TypeScript has not declared the `clipboardData`
54 // property that we use below for Internet Explorer.
55 let text = prepareTextForClipboard(selectionManager.selectionText);
56
57 if (term.browser.isMSIE) {
58 window.clipboardData.setData('Text', text);
59 } else {
60 ev.clipboardData.setData('text/plain', text);
61 }
62
63 ev.preventDefault(); // Prevent or the original text will be copied.
64 }
65
66 /**
67 * Redirect the clipboard's data to the terminal's input handler.
68 * @param {ClipboardEvent} ev The original paste event to be handled
69 * @param {Terminal} term The terminal on which to apply the handled paste event
70 */
71 export function pasteHandler(ev: ClipboardEvent, term: ITerminal) {
72 ev.stopPropagation();
73
74 let text: string;
75
76 let dispatchPaste = function(text) {
77 text = prepareTextForTerminal(text, term.browser.isMSWindows);
78 term.handler(text);
79 term.textarea.value = '';
80 term.emit('paste', text);
81
82 return term.cancel(ev);
83 };
84
85 if (term.browser.isMSIE) {
86 if (window.clipboardData) {
87 text = window.clipboardData.getData('Text');
88 dispatchPaste(text);
89 }
90 } else {
91 if (ev.clipboardData) {
92 text = ev.clipboardData.getData('text/plain');
93 dispatchPaste(text);
94 }
95 }
96 }
97
98 /**
99 * Bind to right-click event and allow right-click copy and paste.
100 * @param ev The original right click event to be handled
101 * @param term The terminal on which to apply the handled paste event
102 * @param selectionManager The terminal's selection manager.
103 */
104 export function rightClickHandler(ev: MouseEvent, textarea: HTMLTextAreaElement, selectionManager: ISelectionManager) {
105 // Bring textarea at the cursor position
106 textarea.style.position = 'fixed';
107 textarea.style.width = '20px';
108 textarea.style.height = '20px';
109 textarea.style.left = (ev.clientX - 10) + 'px';
110 textarea.style.top = (ev.clientY - 10) + 'px';
111 textarea.style.zIndex = '1000';
112
113 // Get textarea ready to copy from the context menu
114 textarea.value = prepareTextForClipboard(selectionManager.selectionText);
115 textarea.focus();
116 textarea.select();
117
118 // Reset the terminal textarea's styling
119 setTimeout(function () {
120 textarea.style.position = null;
121 textarea.style.width = null;
122 textarea.style.height = null;
123 textarea.style.left = null;
124 textarea.style.top = null;
125 textarea.style.zIndex = null;
126 }, 4);
127 }