blob: 830ce4f112338dad6b51b4485cb368156331d892 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.lib.terminalemulator;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import org.netbeans.lib.terminalemulator.AbstractInterp.Actor;
/**
* Stuff common to InterpDtTerm and InterpXTerm but not InterpANSI.
* @author ivan
*/
class InterpProtoANSIX extends InterpProtoANSI {
protected static class InterpTypeProtoANSIX extends InterpTypeProtoANSI {
protected final State st_wait = new State("wait"); // NOI18N
protected final State st_esc_rb = new State("esc_rb"); // NOI18N
protected final State st_esc_rb_N = new State("esc_rb_N");// NOI18N
protected final State st_esc_lb_q = new State("esc_lb_q");// NOI18N
protected final State st_esc_lb_b = new State("esc_lb_b");// NOI18N
protected final Actor act_ind = new ACT_IND();
protected final Actor act_start_collect = new ACT_START_COLLECT();
protected final Actor act_collect = new ACT_COLLECT();
protected final Actor act_done_collect_bel = new ACT_DONE_COLLECT_BEL();
protected final Actor act_DEC_private = new ACT_DEC_PRIVATE();
protected InterpTypeProtoANSIX() {
st_esc.setAction('7', st_base, new ACT_SC());
st_esc.setAction('8', st_base, new ACT_RC());
st_esc.setAction('>', st_base, new ACT_PNM());
st_esc.setAction('=', st_base, new ACT_PAM());
st_esc.setAction('D', st_base, act_ind);
// \ESC]%d;%s\BEL
st_esc.setAction(']', st_esc_rb, act_start_collect);
for (char c = '0'; c <= '9'; c++)
st_esc_rb.setAction(c, st_esc_rb_N, act_collect);
for (char c = 0; c < 128; c++)
st_esc_rb_N.setAction(c, st_esc_rb_N, act_collect);
st_esc_rb_N.setRegular(st_esc_rb_N, act_collect);
st_esc_rb_N.setAction((char) 7, st_base, act_done_collect_bel);// BEL
// \ESC[?%dh
// \ESC[?%dl
// \ESC[?%dr
// \ESC[?%ds
st_esc_lb.setAction('?', st_esc_lb_q, act_reset_number);
for (char c = '0'; c <= '9'; c++)
st_esc_lb_q.setAction(c, st_esc_lb_q, act_remember_digit);
st_esc_lb_q.setAction(';', st_esc_lb_q, act_push_number);
st_esc_lb_q.setAction('h', st_base, act_DEC_private);
st_esc_lb_q.setAction('l', st_base, act_DEC_private);
st_esc_lb_q.setAction('r', st_base, act_DEC_private);
st_esc_lb_q.setAction('s', st_base, act_DEC_private);
// \ESC[!p
st_esc_lb.setAction('!', st_esc_lb_b, act_reset_number);
st_esc_lb_b.setAction('p', st_base, new ACT_DEC_STR());
}
private static final class ACT_SC implements Actor {
@Override
public String action(AbstractInterp ai, char c) {
ai.ops.op_sc();
return null;
}
}
private static final class ACT_PAM implements Actor {
@Override
public String action(AbstractInterp ai, char c) {
((InterpProtoANSIX)ai).DECPAM = true;
return null;
}
}
private static final class ACT_PNM implements Actor {
@Override
public String action(AbstractInterp ai, char c) {
((InterpProtoANSIX)ai).DECPAM = false;
return null;
}
}
private static final class ACT_RC implements Actor {
@Override
public String action(AbstractInterp ai, char c) {
ai.ops.op_rc();
return null;
}
}
private static final class ACT_IND implements Actor {
@Override
public String action(AbstractInterp ai, char c) {
// scroll
ai.ops.op_ind(1);
return null;
}
};
private static final class ACT_START_COLLECT implements Actor {
@Override
public String action(AbstractInterp ai, char c) {
InterpProtoANSIX i = (InterpProtoANSIX) ai;
i.text = ""; // NOI18N
return null;
}
}
private static final class ACT_COLLECT implements Actor {
@Override
public String action(AbstractInterp ai, char c) {
// java bug 4318526 text += c;
InterpProtoANSIX i = (InterpProtoANSIX) ai;
i.text = i.text + c;
return null;
}
}
private static final class ACT_DONE_COLLECT_BEL implements Actor {
@Override
public String action(AbstractInterp ai, char c) {
InterpProtoANSIX i = (InterpProtoANSIX) ai;
int semix = i.text.indexOf(';');
if (semix == -1)
return null;
String p1 = i.text.substring(0, semix);
String p2 = i.text.substring(semix+1);
int code = Integer.parseInt(p1);
switch (code) {
case 0:
ai.ops.op_icon_name(p2);
ai.ops.op_win_title(p2);
break;
case 1:
ai.ops.op_icon_name(p2);
break;
case 2:
ai.ops.op_win_title(p2);
break;
case 3:
// cwd is a dttermism.
// This will be inherited by InterpXTerm but it's really
// not supported by xterm.
ai.ops.op_cwd(p2);
break;
case 10: {
// This is specific to nbterm!
int semix2 = p2.indexOf(';');
if (semix2 == -1)
return null;
String p3 = p2.substring(semix2+1);
p2 = p2.substring(0, semix2);
if (p3.isEmpty() && p2.startsWith(Term.ExternalCommandsConstants.COMMAND_PREFIX)) { //NOI18N
ai.ops.op_ext(p2);
} else {
ai.ops.op_hyperlink(p2, p3);
}
}
}
return null;
}
}
private static final class ACT_DEC_PRIVATE implements Actor {
// xterm Sequences to turn mouse reporting on and off are to be
// implemeted here.
// See http://www.xfree86.org/current/ctlseqs.html#Mouse%20Tracking
private static String decPrivateSet(AbstractInterp ai, char c, int n) {
switch (n) {
case 1:
((InterpProtoANSIX)ai).DECCKM = true;
break;
case 5:
ai.ops.op_reverse(true);
break;
case 12:
// blinking cursor
break;
case 25:
ai.ops.op_cursor_visible(true);
break;
default:
return "act_DEC_private: unrecognized code " + n; // NOI18N
}
return null;
}
private static String decPrivateReset(AbstractInterp ai, char c, int n) {
switch (n) {
case 1:
((InterpProtoANSIX)ai).DECCKM = false;
break;
case 5:
ai.ops.op_reverse(false);
break;
case 12:
// blinking cursor
break;
case 25:
ai.ops.op_cursor_visible(false);
break;
default:
return "act_DEC_private: unrecognized code " + n; // NOI18N
}
return null;
}
private static String decPrivateSave(AbstractInterp ai, char c, int n) {
return "act_DEC_private: unrecognized code " + n; // NOI18N
}
private static String decPrivateRestore(AbstractInterp ai, char c, int n) {
return "act_DEC_private: unrecognized code " + n; // NOI18N
}
@Override
public String action(AbstractInterp ai, char c) {
if (ai.noNumber())
return "act_DEC_private: no number"; // NOI18N
for (int nx = 0; nx <= ai.nNumbers(); nx++) {
int n = ai.numberAt(nx);
switch(c) {
case 'h': return decPrivateSet(ai, c, n);
case 'l': return decPrivateReset(ai, c, n);
case 'r': return decPrivateRestore(ai, c, n);
case 's': return decPrivateSave(ai, c, n);
default: return "act_DEC_private: unrecognized cmd " + c; // NOI18N
}
}
return null;
}
}
protected static final class ACT_DEC_STR implements Actor {
@Override
public String action(AbstractInterp ai, char c) {
ai.ops.op_soft_reset();
return null;
}
}
}
protected String text = null;
private final InterpTypeProtoANSIX type;
private static final InterpTypeProtoANSIX type_singleton = new InterpTypeProtoANSIX();
private boolean DECCKM; // CursorKeyboardMode
private boolean DECPAM; // PadApplicationMode
// opposite of DECPNM (PadNormalMode)
public InterpProtoANSIX(Ops ops) {
super(ops, type_singleton);
this.type = type_singleton;
setup();
}
protected InterpProtoANSIX(Ops ops, InterpTypeProtoANSIX type) {
super(ops, type);
this.type = type;
setup();
}
@Override
public String name() {
return "proto-ansi-x"; // NOI18N
}
@Override
public void reset() {
super.reset();
text = null;
}
private void setup() {
}
private static boolean numLock() {
// getLockingKeyState() seems somewhat unreliable.
// Doesn't work:
// Linux w/ Java 6
// Works:
// Linux w/ Java 7
// All other platforms unknown.
//
// We return false in cases where it doesn't work because NumLock is
// off by default.
final Toolkit toolkit = Toolkit.getDefaultToolkit();
try {
return toolkit.getLockingKeyState(KeyEvent.VK_NUM_LOCK);
} catch (UnsupportedOperationException x) {
return false;
}
}
/**
* {@inheritDoc}
*/
@Override
public void keyPressed(KeyEvent e) {
final boolean pam = DECPAM && ! numLock();
switch (e.getKeyCode()) {
//
// 6 key editing group
//
case KeyEvent.VK_INSERT:
sendChars(e, "\033[2~"); // NOI18N
break;
case KeyEvent.VK_DELETE:
sendChars(e, "\033[3~"); // NOI18N
break;
case KeyEvent.VK_PAGE_UP:
sendChars(e, "\033[5~"); // NOI18N
break;
case KeyEvent.VK_PAGE_DOWN:
sendChars(e, "\033[6~"); // NOI18N
break;
case KeyEvent.VK_HOME:
sendChars(e, DECCKM? "\033OH": "\033[H"); // NOI18N
break;
case KeyEvent.VK_END:
sendChars(e, DECCKM? "\033OF": "\033[F"); // NOI18N
break;
//
// Arrow keys
//
case KeyEvent.VK_UP:
sendChars(e, DECCKM? "\033OA": "\033[A"); // NOI18N
break;
case KeyEvent.VK_DOWN:
sendChars(e, DECCKM? "\033OB": "\033[B"); // NOI18N
break;
case KeyEvent.VK_RIGHT:
sendChars(e, DECCKM? "\033OC": "\033[C"); // NOI18N
break;
case KeyEvent.VK_LEFT:
sendChars(e, DECCKM? "\033OD": "\033[D"); // NOI18N
break;
//
// Function keys
//
case KeyEvent.VK_F1:
sendChars(e, "\033OP"); // NOI18N
break;
case KeyEvent.VK_F2:
sendChars(e, "\033OQ"); // NOI18N
break;
case KeyEvent.VK_F3:
sendChars(e, "\033OR"); // NOI18N
break;
case KeyEvent.VK_F4:
sendChars(e, "\033OS"); // NOI18N
break;
case KeyEvent.VK_F5:
sendChars(e, "\033[15~"); // NOI18N
break;
case KeyEvent.VK_F6:
sendChars(e, "\033[17~"); // NOI18N
break;
case KeyEvent.VK_F7:
sendChars(e, "\033[18~"); // NOI18N
break;
case KeyEvent.VK_F8:
sendChars(e, "\033[19~"); // NOI18N
break;
case KeyEvent.VK_F9:
sendChars(e, "\033[20~"); // NOI18N
break;
case KeyEvent.VK_F10:
sendChars(e, "\033[21~"); // NOI18N
break;
case KeyEvent.VK_F11:
sendChars(e, "\033[23~"); // NOI18N
break;
case KeyEvent.VK_F12:
sendChars(e, "\033[24~"); // NOI18N
break;
//
// Keypad
//
case KeyEvent.VK_DIVIDE:
sendChars(e, pam? "\033Oo": "/"); // NOI18N
break;
case KeyEvent.VK_MULTIPLY:
sendChars(e, pam? "\033Oj": "*"); // NOI18N
break;
case KeyEvent.VK_SUBTRACT:
sendChars(e, pam? "\033Om": "-"); // NOI18N
break;
case KeyEvent.VK_ADD:
sendChars(e, pam? "\033Ok": "+"); // NOI18N
break;
/* Java doesn't provide a way to distinguish between the regular
* Enter/Return key and the keypad Enter key.
case KeyEvent.VK_ENTER:
if (pam)
sendChars(e, "\033OM");
break;
*/
case KeyEvent.VK_NUMPAD0:
sendChars(e, "0"); // NOI18N
break;
case KeyEvent.VK_NUMPAD1:
sendChars(e, "1"); // NOI18N
break;
case KeyEvent.VK_NUMPAD2:
sendChars(e, "2"); // NOI18N
break;
case KeyEvent.VK_NUMPAD3:
sendChars(e, "3"); // NOI18N
break;
case KeyEvent.VK_NUMPAD4:
sendChars(e, "4"); // NOI18N
break;
case KeyEvent.VK_NUMPAD5:
sendChars(e, "5"); // NOI18N
break;
case KeyEvent.VK_NUMPAD6:
sendChars(e, "6"); // NOI18N
break;
case KeyEvent.VK_NUMPAD7:
sendChars(e, "7"); // NOI18N
break;
case KeyEvent.VK_NUMPAD8:
sendChars(e, "8"); // NOI18N
break;
case KeyEvent.VK_NUMPAD9:
sendChars(e, "9"); // NOI18N
break;
case KeyEvent.VK_DECIMAL:
sendChars(e, "."); // NOI18N
break;
case KeyEvent.VK_BEGIN:
sendChars(e, "\033[E"); // NOI18N
break;
case KeyEvent.VK_KP_UP:
sendChars(e, "\033[A"); // NOI18N
break;
case KeyEvent.VK_KP_DOWN:
sendChars(e, "\033[B"); // NOI18N
break;
case KeyEvent.VK_KP_LEFT:
sendChars(e, "\033[D"); // NOI18N
break;
case KeyEvent.VK_KP_RIGHT:
sendChars(e, "\033[C"); // NOI18N
break;
}
}
/**
* {@inheritDoc}
*/
@Override
public char mapACS(final char inChar) {
switch (inChar) {
default: return '\0';
case '+': return inChar; // arrow pointing right ACS_RARROW
case ',': return inChar; // arrow pointing left ACS_LARROW
case '-': return inChar; // arrow pointing up ACS_UARROW
case '.': return inChar; // (^Y) arrow pointing down ACS_DARROW
case '0': return inChar; // solid square block ACS_BLOCK
case '`': return inChar; // diamond ACS_DIAMOND
case 'a': return inChar; // checker board (stipple) ACS_CKBOARD
// no-char return 'b'; // HT
// no-char return 'c'; // FF
// no-char return 'd'; // CR
// no-char return 'e'; // LF
case 'f': return inChar; // degree symbol ACS_DEGREE
case 'g': return inChar; // plus/minus ACS_PLMINUS
case 'h': return inChar; // board of squares ACS_BOARD or NL
// no-char return 'i'; // lantern symbol ACS_LANTERN or VT
case 'j': return inChar; // lower right corner ACS_LRCORNER
case 'k': return inChar; // upper right corner ACS_URCORNER
case 'l': return inChar; // upper left corner ACS_ULCORNER
case 'm': return inChar; // lower left corner ACS_LLCORNER
case 'n': return inChar; // large plus or crossover ACS_PLUS
case 'o': return inChar; // (~) scan line 1 ACS_S1
// case 0304: return 'p'; // scan line 3 ACS_S3
case 'q': return inChar; // horizontal line ACS_HLINE
// case 0304: return 'r'; // scan line 7 ACS_S7
case 's': return inChar; // (_) scan line 9 ACS_S9
case 't': return inChar; // tee pointing right ACS_LTEE
case 'u': return inChar; // tee pointing left ACS_RTEE
case 'v': return inChar; // tee pointing up ACS_BTEE
case 'w': return inChar; // tee pointing down ACS_TTEE
case 'x': return inChar; // vertical line ACS_VLINE
case 'y': return inChar; // less-than-or-equal-to ACS_LEQUAL
case 'z': return inChar; // greater-than-or-equal-to ACS_GEQUAL
case '{': return inChar; // greek pi ACS_PI
case '|': return inChar; // not-equal ACS_NEQUAL
case '}': return inChar; // UK pound sign ACS_STERLING
case '~': return inChar; // bullet ACS_BULLET
}
}
@Override
public void softReset() {
DECCKM = false;
DECPAM = false;
}
}