]> git.proxmox.com Git - mirror_xterm.js.git/commitdiff
Implement CSI Ps SP q Set cursor style
authorDaniel Imms <daimms@microsoft.com>
Mon, 16 Jan 2017 22:53:35 +0000 (14:53 -0800)
committerDaniel Imms <daimms@microsoft.com>
Wed, 18 Jan 2017 18:06:57 +0000 (10:06 -0800)
Fixes #480

demo/style.css
src/InputHandler.ts
src/Interfaces.ts
src/Parser.ts
src/xterm.css
src/xterm.js

index 2f05e309a0268d22001390da5d9d0af74b8dc8bc..7138962123c84ba2270f92dfba34d88990286457 100644 (file)
@@ -20,7 +20,3 @@ h1 {
     color: #fafafa;
     padding: 2px;
 }
-
-#terminal-container .terminal:focus .terminal-cursor {
-    background-color: #fafafa;
-}
index 00626cebf0b5065800481c1d195106c6a622c7cf..975d7c113d674c9b0053f6337775d9f1bd6c9108 100644 (file)
@@ -1392,6 +1392,36 @@ export class InputHandler implements IInputHandler {
     this._terminal.charsets = [null]; // ??
   }
 
+  /**
+   * CSI Ps SP q  Set cursor style (DECSCUSR, VT520).
+   *   Ps = 0  -> blinking block.
+   *   Ps = 1  -> blinking block (default).
+   *   Ps = 2  -> steady block.
+   *   Ps = 3  -> blinking underline.
+   *   Ps = 4  -> steady underline.
+   *   Ps = 5  -> blinking bar (xterm).
+   *   Ps = 6  -> steady bar (xterm).
+   */
+  public setCursorStyle(params?: number[]): void {
+    const param = params[0] < 1 ? 1 : params[0];
+    switch (param) {
+      case 1:
+      case 2:
+        this._terminal.setOption('cursorStyle', 'block');
+        break;
+      case 3:
+      case 4:
+        this._terminal.setOption('cursorStyle', 'underline');
+        break;
+      case 5:
+      case 6:
+        this._terminal.setOption('cursorStyle', 'bar');
+        break;
+    }
+    const isBlinking = param % 2 === 1;
+    this._terminal.setOption('cursorBlink', isBlinking);
+  }
+
   /**
    * CSI Ps ; Ps r
    *   Set Scrolling Region [top;bottom] (default = full size of win-
index 878092866261945a05fec50a5e28b479a91c6084..049a599ca7da94fcb8c8bc0e749aa8cbed342ae6 100644 (file)
@@ -79,6 +79,7 @@ export interface IInputHandler {
   /** CSI m */ charAttributes(params?: number[]): void;
   /** CSI n */ deviceStatus(params?: number[]): void;
   /** CSI p */ softReset(params?: number[]): void;
+  /** CSI q */ setCursorStyle(params?: number[]): void;
   /** CSI r */ setScrollRegion(params?: number[]): void;
   /** CSI s */ saveCursor(params?: number[]): void;
   /** CSI u */ restoreCursor(params?: number[]): void;
index 860baaa6a64ae99012ae0e48bf56ad30681cd50b..02028005e6e70544157f537bcd6d41722992fb71 100644 (file)
@@ -95,7 +95,7 @@ csiParamStateHandler[' '] = (parser) => parser.setPostfix(' ');
 csiParamStateHandler['\''] = (parser) => parser.setPostfix('\'');
 csiParamStateHandler[';'] = (parser) => parser.finalizeParam();
 
-const csiStateHandler: {[key: string]: (handler: IInputHandler, params: number[], prefix: string) => void} = {};
+const csiStateHandler: {[key: string]: (handler: IInputHandler, params: number[], prefix: string, postfix: string) => void} = {};
 csiStateHandler['@'] = (handler, params, prefix) => handler.insertChars(params);
 csiStateHandler['A'] = (handler, params, prefix) => handler.cursorUp(params);
 csiStateHandler['B'] = (handler, params, prefix) => handler.cursorDown(params);
@@ -136,6 +136,11 @@ csiStateHandler['p'] = (handler, params, prefix) => {
     case '!': handler.softReset(params); break;
   }
 };
+csiStateHandler['q'] = (handler, params, prefix, postfix) => {
+  if (postfix === ' ') {
+    handler.setCursorStyle(params);
+  }
+};
 csiStateHandler['r'] = (handler, params) => handler.setScrollRegion(params);
 csiStateHandler['s'] = (handler, params) => handler.saveCursor(params);
 csiStateHandler['u'] = (handler, params) => handler.restoreCursor(params);
@@ -472,7 +477,7 @@ export class Parser {
 
         case ParserState.CSI:
           if (ch in csiStateHandler) {
-            csiStateHandler[ch](this._inputHandler, this._terminal.params, this._terminal.prefix);
+            csiStateHandler[ch](this._inputHandler, this._terminal.params, this._terminal.prefix, this._terminal.postfix);
           } else {
             this._terminal.error('Unknown CSI code: %s.', ch);
           }
index 623164a250fb916b1f3dd3842edcde5049ece4d9..27638e14756ef607c7aec3bc181f40c723d4b1ff 100644 (file)
@@ -71,7 +71,7 @@
     resize: none;
 }
 
-.terminal .terminal-cursor {
+.terminal:not(.xterm-cursor-style-underline):not(.xterm-cursor-style-bar) .terminal-cursor {
     background-color: #fff;
     color: #000;
 }
@@ -82,7 +82,7 @@
     background-color: transparent;
 }
 
-.terminal.focus.xterm-cursor-blink .terminal-cursor {
+.terminal:not(.xterm-cursor-style-underline):not(.xterm-cursor-style-bar).focus.xterm-cursor-blink .terminal-cursor {
     animation: xterm-cursor-blink 1.2s infinite step-end;
 }
 
     }
 }
 
+.terminal.xterm-cursor-style-bar .terminal-cursor,
+.terminal.xterm-cursor-style-underline .terminal-cursor {
+    position: relative;
+}
+.terminal.xterm-cursor-style-bar .terminal-cursor::before,
+.terminal.xterm-cursor-style-underline .terminal-cursor::before {
+    content: "";
+    display: block;
+    position: absolute;
+    background-color: #fff;
+}
+.terminal.xterm-cursor-style-bar .terminal-cursor::before {
+    top: 0;
+    bottom: 0;
+    left: 0;
+    width: 1px;
+}
+.terminal.xterm-cursor-style-underline .terminal-cursor::before {
+    bottom: 0;
+    left: 0;
+    right: 0;
+    height: 1px;
+}
+.terminal.xterm-cursor-style-bar.focus.xterm-cursor-blink .terminal-cursor::before,
+.terminal.xterm-cursor-style-underline.focus.xterm-cursor-blink .terminal-cursor::before {
+    animation: xterm-cursor-non-bar-blink 1.2s infinite step-end;
+}
+@keyframes xterm-cursor-non-bar-blink {
+    0% { background-color: #fff; }
+    50% { background-color: transparent; }
+}
+
 .terminal .composition-view {
     background: #000;
     color: #FFF;
index 24a840c09250d4ff8d45c5c5f6f3a0bee5827304..7f50295fc5eb0c21f2c8249ffcb25179dbffc0ea 100644 (file)
@@ -353,6 +353,7 @@ Terminal.defaults = {
   termName: 'xterm',
   geometry: [80, 24],
   cursorBlink: false,
+  cursorStyle: 'block',
   visualBell: false,
   popOnBell: false,
   scrollback: 1000,
@@ -427,6 +428,11 @@ Terminal.prototype.setOption = function(key, value) {
   this.options[key] = value;
   switch (key) {
     case 'cursorBlink': this.element.classList.toggle('xterm-cursor-blink', value); break;
+    case 'cursorStyle':
+      // Style 'block' applies with no class
+      this.element.classList.toggle(`xterm-cursor-style-underline`, value === 'underline');
+      this.element.classList.toggle(`xterm-cursor-style-bar`, value === 'bar');
+      break;
   }
 };