Added an optional on-screen keyboard. Must be activated by the user by selecting the option in the context-menu.
git-svn-id: https://shellinabox.googlecode.com/svn/trunk@221 0da03de8-d603-11dd-86c2-0f8696b7b6f9
This commit is contained in:
parent
13d0448fc6
commit
2c262e1077
16 changed files with 2026 additions and 481 deletions
|
@ -1,3 +1,8 @@
|
|||
2010-09-04 Markus Gutschke <markus@shellinabox.com>
|
||||
|
||||
* Added an optional on-screen keyboard. Must be activated by the
|
||||
user by selecting the option in the context-menu.
|
||||
|
||||
2010-09-03 Markus Gutschke <markus@shellinabox.com>
|
||||
|
||||
* Fix some scaling related issues. This fix is thanks to some
|
||||
|
|
31
Makefile.am
31
Makefile.am
|
@ -32,6 +32,7 @@ EXTRA_DIST = INSTALL.Debian \
|
|||
demo/demo.jspp \
|
||||
demo/demo.xml \
|
||||
demo/enabled.gif \
|
||||
demo/keyboard.png \
|
||||
demo/styles.css \
|
||||
demo/print-styles.css \
|
||||
demo/vt100.js \
|
||||
|
@ -106,6 +107,8 @@ shellinaboxd_SOURCES = shellinabox/shellinaboxd.c \
|
|||
shellinabox/print-styles.css \
|
||||
shellinabox/enabled.gif \
|
||||
shellinabox/favicon.ico \
|
||||
shellinabox/keyboard.png \
|
||||
shellinabox/keyboard-layout.html \
|
||||
shellinabox/beep.wav \
|
||||
config.h
|
||||
shellinaboxd_LDADD = liblogging.la \
|
||||
|
@ -148,7 +151,9 @@ libtool: $(LIBTOOL_DEPS)
|
|||
|
||||
${top_srcdir}/demo/demo.js: ${top_srcdir}/demo/beep.wav \
|
||||
${top_srcdir}/demo/demo.jspp \
|
||||
${top_srcdir}/demo/enabled.gif \
|
||||
${top_srcdir}/demo/favicon.ico \
|
||||
${top_srcdir}/demo/keyboard.png \
|
||||
${top_srcdir}/demo/styles.css \
|
||||
${top_srcdir}/demo/print-styles.css \
|
||||
${top_srcdir}/demo/vt100.js \
|
||||
|
@ -169,6 +174,10 @@ ${top_srcdir}/demo/favicon.ico: ${top_srcdir}/shellinabox/favicon.ico
|
|||
@rm -f "$@"
|
||||
ln "$?" "$@"
|
||||
|
||||
${top_srcdir}/demo/keyboard.png: ${top_srcdir}/shellinabox/keyboard.png
|
||||
@rm -f "$@"
|
||||
ln "$?" "$@"
|
||||
|
||||
${top_srcdir}/demo/styles.css: ${top_srcdir}/shellinabox/styles.css
|
||||
@rm -f "$@"
|
||||
sed -e '/\[if DEFINES_COLORS\]/,/\[endif DEFINES_COLORS\]/d' "$?" >"$@"
|
||||
|
@ -197,7 +206,8 @@ ${top_srcdir}/demo/vt100.js: ${top_srcdir}/shellinabox/vt100.js
|
|||
@rm -f "$@"
|
||||
ln "$?" "$@"
|
||||
|
||||
shellinaboxd.1: shellinabox/shellinaboxd.man.in config.h
|
||||
shellinaboxd.1: ${top_srcdir}/shellinabox/shellinaboxd.man.in \
|
||||
${top_srcdir}/config.h
|
||||
@src="${top_srcdir}/shellinabox/shellinaboxd.man.in"; \
|
||||
echo preprocess "$$src" '>'"$@"; \
|
||||
if sed -e 's/^#define \([^ ]*\).*/\1/' -e t -e d config.h | \
|
||||
|
@ -253,6 +263,13 @@ clean-local:
|
|||
$(OBJCOPY) --add-section .note.GNU-stack=GNU-stack "$@"; \
|
||||
rm -f GNU-stack
|
||||
|
||||
.png.o:
|
||||
@echo $(OBJCOPY) "$<" "$@"
|
||||
@$(OBJCOPY) -I binary `$(objcopyflags)` `echo "$<" | $(renamesymbols)`\
|
||||
"$<" "$@"
|
||||
@-printf '\000' >GNU-stack && \
|
||||
$(OBJCOPY) --add-section .note.GNU-stack=GNU-stack "$@"; \
|
||||
rm -f GNU-stack
|
||||
|
||||
.html.o:
|
||||
@echo $(OBJCOPY) "$<" "$@"
|
||||
|
@ -272,15 +289,23 @@ clean-local:
|
|||
rm -f GNU-stack
|
||||
|
||||
|
||||
shellinabox/shell_in_a_box.o: shellinabox/shell_in_a_box.js config.h
|
||||
shellinabox/shell_in_a_box.o: ${top_srcdir}/shellinabox/shell_in_a_box.js \
|
||||
${top_srcdir}/config.h
|
||||
|
||||
${top_srcdir}/shellinabox/vt100.js: ${top_srcdir}/shellinabox/vt100.jspp \
|
||||
${top_srcdir}/shellinabox/keyboard-layout.html
|
||||
|
||||
.jspp.js:
|
||||
@echo preprocess "$<" "$@"
|
||||
@sed -e "`sed -e 's/^#define *\([^ ]*\) *\(.*\)/\/^[^#]\/s\/\1\/\2 \\\\\/* \1 *\\\\\/\/g/' \
|
||||
@kbd=`while read i; do \
|
||||
printf '%s' "\`echo "$$i" | sed 's/&/\\\\\\&/g'\`"; \
|
||||
done <${top_srcdir}/shellinabox/keyboard-layout.html`; \
|
||||
sed -e "`sed -e 's/^#define *\([^ ]*\) *\(.*\)/\/^[^#]\/s\/\1\/\2 \\\\\/* \1 *\\\\\/\/g/' \
|
||||
-e t \
|
||||
-e d "$<"`" \
|
||||
-e "s/^#/\/\/ #/" \
|
||||
-e "s/VERSION/\"@VERSION@ (revision @VCS_REVISION@)\"/g" \
|
||||
-e "s%KEYBOARD%'$${kbd}'%" \
|
||||
"$<" >"$@"
|
||||
|
||||
.js.o:
|
||||
|
|
42
Makefile.in
42
Makefile.in
|
@ -82,6 +82,8 @@ am_shellinaboxd_OBJECTS = shellinaboxd.$(OBJEXT) \
|
|||
shellinabox/styles.$(OBJEXT) \
|
||||
shellinabox/print-styles.$(OBJEXT) \
|
||||
shellinabox/enabled.$(OBJEXT) shellinabox/favicon.$(OBJEXT) \
|
||||
shellinabox/keyboard.$(OBJEXT) \
|
||||
shellinabox/keyboard-layout.$(OBJEXT) \
|
||||
shellinabox/beep.$(OBJEXT)
|
||||
shellinaboxd_OBJECTS = $(am_shellinaboxd_OBJECTS)
|
||||
shellinaboxd_DEPENDENCIES = liblogging.la libhttp.la
|
||||
|
@ -288,6 +290,7 @@ EXTRA_DIST = INSTALL.Debian \
|
|||
demo/demo.jspp \
|
||||
demo/demo.xml \
|
||||
demo/enabled.gif \
|
||||
demo/keyboard.png \
|
||||
demo/styles.css \
|
||||
demo/print-styles.css \
|
||||
demo/vt100.js \
|
||||
|
@ -366,6 +369,8 @@ shellinaboxd_SOURCES = shellinabox/shellinaboxd.c \
|
|||
shellinabox/print-styles.css \
|
||||
shellinabox/enabled.gif \
|
||||
shellinabox/favicon.ico \
|
||||
shellinabox/keyboard.png \
|
||||
shellinabox/keyboard-layout.html \
|
||||
shellinabox/beep.wav \
|
||||
config.h
|
||||
|
||||
|
@ -407,7 +412,7 @@ all: config.h
|
|||
$(MAKE) $(AM_MAKEFLAGS) all-am
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .css .gif .html .ico .js .jspp .lo .o .obj .wav
|
||||
.SUFFIXES: .c .css .gif .html .ico .js .jspp .lo .o .obj .png .wav
|
||||
am--refresh:
|
||||
@:
|
||||
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
|
@ -537,6 +542,10 @@ shellinabox/enabled.$(OBJEXT): shellinabox/$(am__dirstamp) \
|
|||
shellinabox/$(DEPDIR)/$(am__dirstamp)
|
||||
shellinabox/favicon.$(OBJEXT): shellinabox/$(am__dirstamp) \
|
||||
shellinabox/$(DEPDIR)/$(am__dirstamp)
|
||||
shellinabox/keyboard.$(OBJEXT): shellinabox/$(am__dirstamp) \
|
||||
shellinabox/$(DEPDIR)/$(am__dirstamp)
|
||||
shellinabox/keyboard-layout.$(OBJEXT): shellinabox/$(am__dirstamp) \
|
||||
shellinabox/$(DEPDIR)/$(am__dirstamp)
|
||||
shellinabox/beep.$(OBJEXT): shellinabox/$(am__dirstamp) \
|
||||
shellinabox/$(DEPDIR)/$(am__dirstamp)
|
||||
shellinaboxd$(EXEEXT): $(shellinaboxd_OBJECTS) $(shellinaboxd_DEPENDENCIES)
|
||||
|
@ -549,6 +558,8 @@ mostlyclean-compile:
|
|||
-rm -f shellinabox/cgi_root.$(OBJEXT)
|
||||
-rm -f shellinabox/enabled.$(OBJEXT)
|
||||
-rm -f shellinabox/favicon.$(OBJEXT)
|
||||
-rm -f shellinabox/keyboard-layout.$(OBJEXT)
|
||||
-rm -f shellinabox/keyboard.$(OBJEXT)
|
||||
-rm -f shellinabox/print-styles.$(OBJEXT)
|
||||
-rm -f shellinabox/root_page.$(OBJEXT)
|
||||
-rm -f shellinabox/shell_in_a_box.$(OBJEXT)
|
||||
|
@ -1162,7 +1173,9 @@ libtool: $(LIBTOOL_DEPS)
|
|||
|
||||
${top_srcdir}/demo/demo.js: ${top_srcdir}/demo/beep.wav \
|
||||
${top_srcdir}/demo/demo.jspp \
|
||||
${top_srcdir}/demo/enabled.gif \
|
||||
${top_srcdir}/demo/favicon.ico \
|
||||
${top_srcdir}/demo/keyboard.png \
|
||||
${top_srcdir}/demo/styles.css \
|
||||
${top_srcdir}/demo/print-styles.css \
|
||||
${top_srcdir}/demo/vt100.js \
|
||||
|
@ -1183,6 +1196,10 @@ ${top_srcdir}/demo/favicon.ico: ${top_srcdir}/shellinabox/favicon.ico
|
|||
@rm -f "$@"
|
||||
ln "$?" "$@"
|
||||
|
||||
${top_srcdir}/demo/keyboard.png: ${top_srcdir}/shellinabox/keyboard.png
|
||||
@rm -f "$@"
|
||||
ln "$?" "$@"
|
||||
|
||||
${top_srcdir}/demo/styles.css: ${top_srcdir}/shellinabox/styles.css
|
||||
@rm -f "$@"
|
||||
sed -e '/\[if DEFINES_COLORS\]/,/\[endif DEFINES_COLORS\]/d' "$?" >"$@"
|
||||
|
@ -1211,7 +1228,8 @@ ${top_srcdir}/demo/vt100.js: ${top_srcdir}/shellinabox/vt100.js
|
|||
@rm -f "$@"
|
||||
ln "$?" "$@"
|
||||
|
||||
shellinaboxd.1: shellinabox/shellinaboxd.man.in config.h
|
||||
shellinaboxd.1: ${top_srcdir}/shellinabox/shellinaboxd.man.in \
|
||||
${top_srcdir}/config.h
|
||||
@src="${top_srcdir}/shellinabox/shellinaboxd.man.in"; \
|
||||
echo preprocess "$$src" '>'"$@"; \
|
||||
if sed -e 's/^#define \([^ ]*\).*/\1/' -e t -e d config.h | \
|
||||
|
@ -1267,6 +1285,14 @@ clean-local:
|
|||
$(OBJCOPY) --add-section .note.GNU-stack=GNU-stack "$@"; \
|
||||
rm -f GNU-stack
|
||||
|
||||
.png.o:
|
||||
@echo $(OBJCOPY) "$<" "$@"
|
||||
@$(OBJCOPY) -I binary `$(objcopyflags)` `echo "$<" | $(renamesymbols)`\
|
||||
"$<" "$@"
|
||||
@-printf '\000' >GNU-stack && \
|
||||
$(OBJCOPY) --add-section .note.GNU-stack=GNU-stack "$@"; \
|
||||
rm -f GNU-stack
|
||||
|
||||
.html.o:
|
||||
@echo $(OBJCOPY) "$<" "$@"
|
||||
@$(OBJCOPY) -I binary `$(objcopyflags)` `echo "$<" | $(renamesymbols)`\
|
||||
|
@ -1283,15 +1309,23 @@ clean-local:
|
|||
$(OBJCOPY) --add-section .note.GNU-stack=GNU-stack "$@"; \
|
||||
rm -f GNU-stack
|
||||
|
||||
shellinabox/shell_in_a_box.o: shellinabox/shell_in_a_box.js config.h
|
||||
shellinabox/shell_in_a_box.o: ${top_srcdir}/shellinabox/shell_in_a_box.js \
|
||||
${top_srcdir}/config.h
|
||||
|
||||
${top_srcdir}/shellinabox/vt100.js: ${top_srcdir}/shellinabox/vt100.jspp \
|
||||
${top_srcdir}/shellinabox/keyboard-layout.html
|
||||
|
||||
.jspp.js:
|
||||
@echo preprocess "$<" "$@"
|
||||
@sed -e "`sed -e 's/^#define *\([^ ]*\) *\(.*\)/\/^[^#]\/s\/\1\/\2 \\\\\/* \1 *\\\\\/\/g/' \
|
||||
@kbd=`while read i; do \
|
||||
printf '%s' "\`echo "$$i" | sed 's/&/\\\\\\&/g'\`"; \
|
||||
done <${top_srcdir}/shellinabox/keyboard-layout.html`; \
|
||||
sed -e "`sed -e 's/^#define *\([^ ]*\) *\(.*\)/\/^[^#]\/s\/\1\/\2 \\\\\/* \1 *\\\\\/\/g/' \
|
||||
-e t \
|
||||
-e d "$<"`" \
|
||||
-e "s/^#/\/\/ #/" \
|
||||
-e "s/VERSION/\"@VERSION@ (revision @VCS_REVISION@)\"/g" \
|
||||
-e "s%KEYBOARD%'$${kbd}'%" \
|
||||
"$<" >"$@"
|
||||
|
||||
.js.o:
|
||||
|
|
2
config.h
2
config.h
|
@ -153,7 +153,7 @@
|
|||
#define STDC_HEADERS 1
|
||||
|
||||
/* Most recent revision number in the version control system */
|
||||
#define VCS_REVISION "220"
|
||||
#define VCS_REVISION "221"
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "2.10"
|
||||
|
|
2
configure
vendored
2
configure
vendored
|
@ -2328,7 +2328,7 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
|
|||
ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
|
||||
|
||||
VCS_REVISION=220
|
||||
VCS_REVISION=221
|
||||
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
|
|
|
@ -2,7 +2,7 @@ AC_PREREQ(2.57)
|
|||
|
||||
dnl This is the one location where the authoritative version number is stored
|
||||
AC_INIT(shellinabox, 2.10, markus@shellinabox.com)
|
||||
VCS_REVISION=220
|
||||
VCS_REVISION=221
|
||||
AC_SUBST(VCS_REVISION)
|
||||
AC_DEFINE_UNQUOTED(VCS_REVISION, "${VCS_REVISION}",
|
||||
[Most recent revision number in the version control system])
|
||||
|
|
BIN
demo/keyboard.png
Normal file
BIN
demo/keyboard.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 808 B |
215
demo/styles.css
215
demo/styles.css
|
@ -1,156 +1,233 @@
|
|||
#vt100 a {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
#vt100 a:hover {
|
||||
text-decoration: underline;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#vt100 #reconnect {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
#vt100 #reconnect input {
|
||||
padding: 1ex;
|
||||
font-weight: bold;
|
||||
font-size: x-large;
|
||||
padding: 1ex;
|
||||
font-weight: bold;
|
||||
font-size: x-large;
|
||||
}
|
||||
|
||||
#vt100 #cursize {
|
||||
background: #EEEEEE;
|
||||
border: 1px solid black;
|
||||
font-family: sans-serif;
|
||||
font-size: large;
|
||||
font-weight: bold;
|
||||
padding: 1ex;
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
background: #EEEEEE;
|
||||
border: 1px solid black;
|
||||
font-family: sans-serif;
|
||||
font-size: large;
|
||||
font-weight: bold;
|
||||
padding: 1ex;
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
#vt100 pre {
|
||||
margin: 0px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
#vt100 pre pre {
|
||||
overflow: hidden;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#vt100 #scrollable {
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
position: relative;
|
||||
padding: 1px;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
position: relative;
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
#vt100 #console, #vt100 #alt_console, #vt100 #cursor, #vt100 #lineheight, #vt100 .hidden pre {
|
||||
font-family: "DejaVu Sans Mono", "Everson Mono", FreeMono, "Andale Mono", "Lucida Console", monospace;
|
||||
font-family: "DejaVu Sans Mono", "Everson Mono", FreeMono, "Andale Mono", "Lucida Console", monospace;
|
||||
}
|
||||
|
||||
#vt100 #lineheight {
|
||||
position: absolute;
|
||||
visibility: hidden;
|
||||
position: absolute;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#vt100 #cursor {
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
overflow: hidden;
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
overflow: hidden;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
#vt100 #cursor.bright {
|
||||
background-color: #e60000;
|
||||
color: white;
|
||||
background-color: #e60000;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#vt100 #cursor.dim {
|
||||
visibility: hidden;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#vt100 #cursor.inactive {
|
||||
border: 1px solid #e60000;
|
||||
margin: -1px;
|
||||
border: 1px solid #e60000;
|
||||
margin: -1px;
|
||||
}
|
||||
|
||||
#vt100 #padding {
|
||||
visibility: hidden;
|
||||
width: 1px;
|
||||
height: 0px;
|
||||
overflow: hidden;
|
||||
visibility: hidden;
|
||||
width: 1px;
|
||||
height: 0px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#vt100 .hidden {
|
||||
position: absolute;
|
||||
top: -10000px;
|
||||
left: -10000px;
|
||||
width: 0px;
|
||||
height: 0px;
|
||||
position: absolute;
|
||||
top: -10000px;
|
||||
left: -10000px;
|
||||
width: 0px;
|
||||
height: 0px;
|
||||
}
|
||||
|
||||
#vt100 #menu {
|
||||
overflow: visible;
|
||||
position: absolute;
|
||||
z-index: 3;
|
||||
overflow: visible;
|
||||
position: absolute;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
#vt100 #menu .popup {
|
||||
background-color: #EEEEEE;
|
||||
border: 1px solid black;
|
||||
font-family: sans-serif;
|
||||
position: absolute;
|
||||
background-color: #EEEEEE;
|
||||
border: 1px solid black;
|
||||
font-family: sans-serif;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
#vt100 #menu .popup ul {
|
||||
list-style-type: none;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
min-width: 10em;
|
||||
list-style-type: none;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
min-width: 10em;
|
||||
}
|
||||
|
||||
#vt100 #menu .popup li {
|
||||
padding: 3px 0.5ex 3px 0.5ex;
|
||||
padding: 3px 0.5ex 3px 0.5ex;
|
||||
}
|
||||
|
||||
#vt100 #menu .popup li.hover {
|
||||
background-color: #444444;
|
||||
color: white;
|
||||
background-color: #444444;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#vt100 #menu .popup li.disabled {
|
||||
color: #AAAAAA;
|
||||
color: #AAAAAA;
|
||||
}
|
||||
|
||||
#vt100 #menu .popup hr {
|
||||
margin: 0.5ex 0px 0.5ex 0px;
|
||||
margin: 0.5ex 0px 0.5ex 0px;
|
||||
}
|
||||
|
||||
#vt100 #menu img {
|
||||
margin-right: 0.5ex;
|
||||
width: 1ex;
|
||||
height: 1ex;
|
||||
margin-right: 0.5ex;
|
||||
width: 1ex;
|
||||
height: 1ex;
|
||||
}
|
||||
|
||||
#vt100 #scrollable.inverted { color: #ffffff;
|
||||
background-color: #000000; }
|
||||
|
||||
#vt100 #kbd_button {
|
||||
float: left;
|
||||
position: fixed;
|
||||
z-index: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#vt100 #keyboard {
|
||||
z-index: 3;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
#vt100 #keyboard .box {
|
||||
font-family: sans-serif;
|
||||
background-color: #cccccc;
|
||||
padding: .8em;
|
||||
float: left;
|
||||
position: absolute;
|
||||
border-radius: 10px;
|
||||
-moz-border-radius: 10px;
|
||||
box-shadow: 4px 4px 6px #222222;
|
||||
-webkit-box-shadow: 4px 4px 6px #222222;
|
||||
/* Don't set the -moz-box-shadow. It doesn't properly scale when CSS
|
||||
* transforms are in effect. Once Firefox supports box-shadow, it should
|
||||
* automatically do the right thing. Until then, leave shadows disabled
|
||||
* for Firefox.
|
||||
*/
|
||||
opacity: 0.85;
|
||||
-moz-opacity: 0.85;
|
||||
filter: alpha(opacity=85);
|
||||
}
|
||||
|
||||
#vt100 #keyboard .box * {
|
||||
vertical-align: top;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#vt100 #keyboard b, #vt100 #keyboard i, #vt100 #keyboard s, #vt100 #keyboard u {
|
||||
font-style: normal;
|
||||
font-weight: bold;
|
||||
border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
background-color: #555555;
|
||||
color: #eeeeee;
|
||||
box-shadow: 2px 2px 3px #222222;
|
||||
-webkit-box-shadow: 2px 2px 3px #222222;
|
||||
padding: 4px;
|
||||
margin: 2px;
|
||||
height: 2ex;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#vt100 #keyboard b, #vt100 #keyboard s {
|
||||
width: 2ex;
|
||||
}
|
||||
|
||||
#vt100 #keyboard u, #vt100 #keyboard s {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#vt100 #keyboard .shifted {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#vt100 #keyboard .selected {
|
||||
color: #888888;
|
||||
background-color: #eeeeee;
|
||||
box-shadow: 0px 0px 3px #222222;
|
||||
-webkit-box-shadow: 0px 0px 3px #222222;
|
||||
position: relative;
|
||||
top: 1px;
|
||||
left: 1px;
|
||||
}
|
||||
|
||||
|
||||
@media print {
|
||||
#vt100 .scrollback {
|
||||
display: none;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#vt100 #reconnect, #vt100 #cursor, #vt100 #menu {
|
||||
visibility: hidden;
|
||||
#vt100 #reconnect, #vt100 #cursor, #vt100 #menu, #vt100 #kbd_button, #vt100 #keyboard {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#vt100 #scrollable {
|
||||
overflow: hidden;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#vt100 #console, #vt100 #alt_console {
|
||||
overflow: hidden;
|
||||
width: 1000000ex;
|
||||
overflow: hidden;
|
||||
width: 1000000ex;
|
||||
}
|
||||
}
|
||||
|
|
643
demo/vt100.js
643
demo/vt100.js
|
@ -238,22 +238,16 @@ VT100.prototype.reset = function(clearHistory) {
|
|||
this.enableAlternateScreen(false);
|
||||
|
||||
var wasCompressed = false;
|
||||
var styles = [ 'transform',
|
||||
'WebkitTransform',
|
||||
'MozTransform',
|
||||
'filter' ];
|
||||
for (var i = 0; i < styles.length; ++i) {
|
||||
if (typeof this.console[0].style[styles[i]] != 'undefined') {
|
||||
for (var j = 0; j < 1; ++j) {
|
||||
wasCompressed |= this.console[j].style[styles[i]] != '';
|
||||
this.console[j].style[styles[i]] = '';
|
||||
}
|
||||
this.cursor.style[styles[i]] = '';
|
||||
this.space.style[styles[i]] = '';
|
||||
if (styles[i] == 'filter') {
|
||||
this.console[this.currentScreen].style.width = '';
|
||||
}
|
||||
break;
|
||||
var transform = this.getTransformName();
|
||||
if (transform) {
|
||||
for (var i = 0; i < 2; ++i) {
|
||||
wasCompressed |= this.console[i].style[transform] != '';
|
||||
this.console[i].style[transform] = '';
|
||||
}
|
||||
this.cursor.style[transform] = '';
|
||||
this.space.style[transform] = '';
|
||||
if (transform == 'filter') {
|
||||
this.console[this.currentScreen].style.width = '';
|
||||
}
|
||||
}
|
||||
this.scale = 1.0;
|
||||
|
@ -270,10 +264,13 @@ VT100.prototype.reset = function(clearHistory) {
|
|||
};
|
||||
|
||||
VT100.prototype.addListener = function(elem, event, listener) {
|
||||
if (elem.addEventListener) {
|
||||
elem.addEventListener(event, listener, false);
|
||||
} else {
|
||||
elem.attachEvent('on' + event, listener);
|
||||
try {
|
||||
if (elem.addEventListener) {
|
||||
elem.addEventListener(event, listener, false);
|
||||
} else {
|
||||
elem.attachEvent('on' + event, listener);
|
||||
}
|
||||
} catch (e) {
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -281,11 +278,12 @@ VT100.prototype.getUserSettings = function() {
|
|||
// Compute hash signature to identify the entries in the userCSS menu.
|
||||
// If the menu is unchanged from last time, default values can be
|
||||
// looked up in a cookie associated with this page.
|
||||
this.signature = 2;
|
||||
this.signature = 3;
|
||||
this.utfPreferred = true;
|
||||
this.visualBell = typeof suppressAllAudio != 'undefined' &&
|
||||
suppressAllAudio;
|
||||
this.autoprint = true;
|
||||
this.softKeyboard = false;
|
||||
this.blinkingCursor = true;
|
||||
if (this.visualBell) {
|
||||
this.signature = Math.floor(16807*this.signature + 1) %
|
||||
|
@ -311,15 +309,16 @@ VT100.prototype.getUserSettings = function() {
|
|||
if (settings >= 0) {
|
||||
settings = document.cookie.substr(settings + key.length).
|
||||
replace(/([0-1]*).*/, "$1");
|
||||
if (settings.length == 3 + (typeof userCSSList == 'undefined' ?
|
||||
if (settings.length == 5 + (typeof userCSSList == 'undefined' ?
|
||||
0 : userCSSList.length)) {
|
||||
this.utfPreferred = settings.charAt(0) != '0';
|
||||
this.visualBell = settings.charAt(1) != '0';
|
||||
this.autoprint = settings.charAt(2) != '0';
|
||||
this.blinkingCursor = settings.charAt(3) != '0';
|
||||
this.softKeyboard = settings.charAt(3) != '0';
|
||||
this.blinkingCursor = settings.charAt(4) != '0';
|
||||
if (typeof userCSSList != 'undefined') {
|
||||
for (var i = 0; i < userCSSList.length; ++i) {
|
||||
userCSSList[i][2] = settings.charAt(i + 3) != '0';
|
||||
userCSSList[i][2] = settings.charAt(i + 5) != '0';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -332,6 +331,7 @@ VT100.prototype.storeUserSettings = function() {
|
|||
(this.utfEnabled ? '1' : '0') +
|
||||
(this.visualBell ? '1' : '0') +
|
||||
(this.autoprint ? '1' : '0') +
|
||||
(this.softKeyboard ? '1' : '0') +
|
||||
(this.blinkingCursor ? '1' : '0');
|
||||
if (typeof userCSSList != 'undefined') {
|
||||
for (var i = 0; i < userCSSList.length; ++i) {
|
||||
|
@ -413,7 +413,7 @@ VT100.prototype.initializeUserCSSStyles = function() {
|
|||
label.textContent= label.textContent;
|
||||
}
|
||||
|
||||
// User style sheets are number sequentially
|
||||
// User style sheets are numbered sequentially
|
||||
var sheet = document.getElementById(
|
||||
'usercss-' + i);
|
||||
if (i == current) {
|
||||
|
@ -470,6 +470,328 @@ VT100.prototype.initializeUserCSSStyles = function() {
|
|||
}
|
||||
};
|
||||
|
||||
VT100.prototype.resetLastSelectedKey = function(e) {
|
||||
var key = this.lastSelectedKey;
|
||||
if (!key) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var position = this.mousePosition(e);
|
||||
|
||||
// We don't get all the necessary events to reliably reselect a key
|
||||
// if we moved away from it and then back onto it. We approximate the
|
||||
// behavior by remembering the key until either we release the mouse
|
||||
// button (we might never get this event if the mouse has since left
|
||||
// the window), or until we move away too far.
|
||||
var box = this.keyboard.firstChild;
|
||||
if (position[0] < box.offsetLeft + key.offsetWidth ||
|
||||
position[1] < box.offsetTop + key.offsetHeight ||
|
||||
position[0] >= box.offsetLeft + box.offsetWidth - key.offsetWidth ||
|
||||
position[1] >= box.offsetTop + box.offsetHeight - key.offsetHeight ||
|
||||
position[0] < box.offsetLeft + key.offsetLeft - key.offsetWidth ||
|
||||
position[1] < box.offsetTop + key.offsetTop - key.offsetHeight ||
|
||||
position[0] >= box.offsetLeft + key.offsetLeft + 2*key.offsetWidth ||
|
||||
position[1] >= box.offsetTop + key.offsetTop + 2*key.offsetHeight) {
|
||||
if (this.lastSelectedKey.className) log.console('reset: deselecting');
|
||||
this.lastSelectedKey.className = '';
|
||||
this.lastSelectedKey = undefined;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
VT100.prototype.showShiftState = function(state) {
|
||||
var style = document.getElementById('shift_state');
|
||||
if (state) {
|
||||
this.setTextContentRaw(style,
|
||||
'#vt100 #keyboard .shifted {' +
|
||||
'display: inline }' +
|
||||
'#vt100 #keyboard .unshifted {' +
|
||||
'display: none }');
|
||||
} else {
|
||||
this.setTextContentRaw(style, '');
|
||||
}
|
||||
var elems = this.keyboard.getElementsByTagName('I');
|
||||
for (var i = 0; i < elems.length; ++i) {
|
||||
if (elems[i].id == '16') {
|
||||
elems[i].className = state ? 'selected' : '';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
VT100.prototype.showCtrlState = function(state) {
|
||||
var ctrl = this.getChildById(this.keyboard, '17' /* Ctrl */);
|
||||
if (ctrl) {
|
||||
ctrl.className = state ? 'selected' : '';
|
||||
}
|
||||
};
|
||||
|
||||
VT100.prototype.showAltState = function(state) {
|
||||
var alt = this.getChildById(this.keyboard, '18' /* Alt */);
|
||||
if (alt) {
|
||||
alt.className = state ? 'selected' : '';
|
||||
}
|
||||
};
|
||||
|
||||
VT100.prototype.clickedKeyboard = function(e, elem, ch, key, shift, ctrl, alt){
|
||||
var fake = [ ];
|
||||
fake.charCode = ch;
|
||||
fake.keyCode = key;
|
||||
fake.ctrlKey = ctrl;
|
||||
fake.shiftKey = shift;
|
||||
fake.altKey = alt;
|
||||
fake.metaKey = alt;
|
||||
return this.handleKey(fake);
|
||||
};
|
||||
|
||||
VT100.prototype.addKeyBinding = function(elem, ch, key, CH, KEY) {
|
||||
if (elem == undefined) {
|
||||
return;
|
||||
}
|
||||
if (ch == '\u00A0') {
|
||||
// should be treated as a regular space character.
|
||||
ch = ' ';
|
||||
}
|
||||
if (ch != undefined && CH == undefined) {
|
||||
// For letter keys, we automatically compute the uppercase character code
|
||||
// from the lowercase one.
|
||||
CH = ch.toUpperCase();
|
||||
}
|
||||
if (KEY == undefined && key != undefined) {
|
||||
// Most keys have identically key codes for both lowercase and uppercase
|
||||
// keypresses. Normally, only function keys would have distinct key codes,
|
||||
// whereas regular keys have character codes.
|
||||
KEY = key;
|
||||
} else if (KEY == undefined && CH != undefined) {
|
||||
// For regular keys, copy the character code to the key code.
|
||||
KEY = CH.charCodeAt(0);
|
||||
}
|
||||
if (key == undefined && ch != undefined) {
|
||||
// For regular keys, copy the character code to the key code.
|
||||
key = ch.charCodeAt(0);
|
||||
}
|
||||
// Convert characters to numeric character codes. If the character code
|
||||
// is undefined (i.e. this is a function key), set it to zero.
|
||||
ch = ch ? ch.charCodeAt(0) : 0;
|
||||
CH = CH ? CH.charCodeAt(0) : 0;
|
||||
|
||||
// Mouse down events high light the key. We also set lastSelectedKey. This
|
||||
// is needed to that mouseout/mouseover can keep track of the key that
|
||||
// is currently being clicked.
|
||||
this.addListener(elem, 'mousedown',
|
||||
function(vt100, elem, key) { return function(e) {
|
||||
if ((e.which || e.button) == 1) {
|
||||
if (vt100.lastSelectedKey) {
|
||||
vt100.lastSelectedKey.className= '';
|
||||
}
|
||||
// Highlight the key while the mouse button is held down.
|
||||
if (key == 16 /* Shift */) {
|
||||
if (!elem.className != vt100.isShift) {
|
||||
vt100.showShiftState(!vt100.isShift);
|
||||
}
|
||||
} else if (key == 17 /* Ctrl */) {
|
||||
if (!elem.className != vt100.isCtrl) {
|
||||
vt100.showCtrlState(!vt100.isCtrl);
|
||||
}
|
||||
} else if (key == 18 /* Alt */) {
|
||||
if (!elem.className != vt100.isAlt) {
|
||||
vt100.showAltState(!vt100.isAlt);
|
||||
}
|
||||
} else {
|
||||
elem.className = 'selected';
|
||||
}
|
||||
vt100.lastSelectedKey = elem;
|
||||
}
|
||||
return false; }; }(this, elem, key));
|
||||
var clicked =
|
||||
// Modifier keys update the state of the keyboard, but do not generate
|
||||
// any key clicks that get forwarded to the application.
|
||||
key >= 16 /* Shift */ && key <= 18 /* Alt */ ?
|
||||
function(vt100, elem) { return function(e) {
|
||||
if (elem == vt100.lastSelectedKey) {
|
||||
if (key == 16 /* Shift */) {
|
||||
// The user clicked the Shift key
|
||||
vt100.isShift = !vt100.isShift;
|
||||
vt100.showShiftState(vt100.isShift);
|
||||
} else if (key == 17 /* Ctrl */) {
|
||||
vt100.isCtrl = !vt100.isCtrl;
|
||||
vt100.showCtrlState(vt100.isCtrl);
|
||||
} else if (key == 18 /* Alt */) {
|
||||
vt100.isAlt = !vt100.isAlt;
|
||||
vt100.showAltState(vt100.isAlt);
|
||||
}
|
||||
vt100.lastSelectedKey = undefined;
|
||||
}
|
||||
if (vt100.lastSelectedKey) {
|
||||
vt100.lastSelectedKey.className = '';
|
||||
vt100.lastSelectedKey = undefined;
|
||||
}
|
||||
return false; }; }(this, elem) :
|
||||
// Regular keys generate key clicks, when the mouse button is released or
|
||||
// when a mouse click event is received.
|
||||
function(vt100, elem, ch, key, CH, KEY) { return function(e) {
|
||||
if (vt100.lastSelectedKey) {
|
||||
if (elem == vt100.lastSelectedKey) {
|
||||
// The user clicked a key.
|
||||
if (vt100.isShift) {
|
||||
vt100.clickedKeyboard(e, elem, CH, KEY,
|
||||
true, vt100.isCtrl, vt100.isAlt);
|
||||
} else {
|
||||
vt100.clickedKeyboard(e, elem, ch, key,
|
||||
false, vt100.isCtrl, vt100.isAlt);
|
||||
}
|
||||
vt100.isShift = false;
|
||||
vt100.showShiftState(false);
|
||||
vt100.isCtrl = false;
|
||||
vt100.showCtrlState(false);
|
||||
vt100.isAlt = false;
|
||||
vt100.showAltState(false);
|
||||
}
|
||||
vt100.lastSelectedKey.className = '';
|
||||
vt100.lastSelectedKey = undefined;
|
||||
}
|
||||
elem.className = '';
|
||||
return false; }; }(this, elem, ch, key, CH, KEY);
|
||||
this.addListener(elem, 'mouseup', clicked);
|
||||
this.addListener(elem, 'click', clicked);
|
||||
|
||||
// When moving the mouse away from a key, check if any keys need to be
|
||||
// deselected.
|
||||
this.addListener(elem, 'mouseout',
|
||||
function(vt100, elem, key) { return function(e) {
|
||||
if (key == 16 /* Shift */) {
|
||||
if (!elem.className == vt100.isShift) {
|
||||
vt100.showShiftState(vt100.isShift);
|
||||
}
|
||||
} else if (key == 17 /* Ctrl */) {
|
||||
if (!elem.className == vt100.isCtrl) {
|
||||
vt100.showCtrlState(vt100.isCtrl);
|
||||
}
|
||||
} else if (key == 18 /* Alt */) {
|
||||
if (!elem.className == vt100.isAlt) {
|
||||
vt100.showAltState(vt100.isAlt);
|
||||
}
|
||||
} else if (elem.className) {
|
||||
elem.className = '';
|
||||
vt100.lastSelectedKey = elem;
|
||||
} else if (vt100.lastSelectedKey) {
|
||||
vt100.resetLastSelectedKey(e);
|
||||
}
|
||||
return false; }; }(this, elem, key));
|
||||
|
||||
// When moving the mouse over a key, select it if the user is still holding
|
||||
// the mouse button down (i.e. elem == lastSelectedKey)
|
||||
this.addListener(elem, 'mouseover',
|
||||
function(vt100, elem, key) { return function(e) {
|
||||
if (elem == vt100.lastSelectedKey) {
|
||||
if (key == 16 /* Shift */) {
|
||||
if (!elem.className != vt100.isShift) {
|
||||
vt100.showShiftState(!vt100.isShift);
|
||||
}
|
||||
} else if (key == 17 /* Ctrl */) {
|
||||
if (!elem.className != vt100.isCtrl) {
|
||||
vt100.showCtrlState(!vt100.isCtrl);
|
||||
}
|
||||
} else if (key == 18 /* Alt */) {
|
||||
if (!elem.className != vt100.isAlt) {
|
||||
vt100.showAltState(!vt100.isAlt);
|
||||
}
|
||||
} else if (!elem.className) {
|
||||
elem.className = 'selected';
|
||||
}
|
||||
} else {
|
||||
vt100.resetLastSelectedKey(e);
|
||||
}
|
||||
return false; }; }(this, elem, key));
|
||||
};
|
||||
|
||||
VT100.prototype.initializeKeyBindings = function(elem) {
|
||||
if (elem) {
|
||||
if (elem.nodeName == "I" || elem.nodeName == "B") {
|
||||
if (elem.id) {
|
||||
// Function keys. The Javascript keycode is part of the "id"
|
||||
var i = parseInt(elem.id);
|
||||
if (i) {
|
||||
// If the id does not parse as a number, it is not a keycode.
|
||||
this.addKeyBinding(elem, undefined, i);
|
||||
}
|
||||
} else {
|
||||
var child = elem.firstChild;
|
||||
if (child.nodeName == "#text") {
|
||||
// If the key only has a text node as a child, then it is a letter.
|
||||
// Automatically compute the lower and upper case version of the key.
|
||||
this.addKeyBinding(elem, this.getTextContent(child).toLowerCase());
|
||||
} else {
|
||||
// If the key has two children, they are the lower and upper case
|
||||
// character code, respectively.
|
||||
this.addKeyBinding(elem, this.getTextContent(child), undefined,
|
||||
this.getTextContent(child.nextSibling));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Recursively parse all other child nodes.
|
||||
for (elem = elem.firstChild; elem; elem = elem.nextSibling) {
|
||||
this.initializeKeyBindings(elem);
|
||||
}
|
||||
};
|
||||
|
||||
VT100.prototype.initializeKeyboard = function() {
|
||||
// Configure mouse event handlers for button that displays/hides keyboard
|
||||
var box = this.keyboard.firstChild;
|
||||
this.hideSoftKeyboard();
|
||||
this.addListener(this.keyboardImage, 'click',
|
||||
function(vt100) { return function(e) {
|
||||
if (vt100.keyboard.style.display != '') {
|
||||
if (vt100.reconnectBtn.style.visibility != '') {
|
||||
vt100.showSoftKeyboard();
|
||||
}
|
||||
} else {
|
||||
vt100.hideSoftKeyboard();
|
||||
vt100.input.focus();
|
||||
}
|
||||
return false; }; }(this));
|
||||
|
||||
// Enable button that displays keyboard
|
||||
if (this.softKeyboard) {
|
||||
this.keyboardImage.style.visibility = 'visible';
|
||||
}
|
||||
|
||||
// Configure mouse event handlers for on-screen keyboard
|
||||
this.addListener(this.keyboard, 'click',
|
||||
function(vt100) { return function(e) {
|
||||
vt100.hideSoftKeyboard();
|
||||
vt100.input.focus();
|
||||
return false; }; }(this));
|
||||
this.addListener(this.keyboard, 'selectstart', this.cancelEvent);
|
||||
this.addListener(box, 'click', this.cancelEvent);
|
||||
this.addListener(box, 'mouseup',
|
||||
function(vt100) { return function(e) {
|
||||
if (vt100.lastSelectedKey) {
|
||||
vt100.lastSelectedKey.className = '';
|
||||
vt100.lastSelectedKey = undefined;
|
||||
}
|
||||
return false; }; }(this));
|
||||
this.addListener(box, 'mouseout',
|
||||
function(vt100) { return function(e) {
|
||||
return vt100.resetLastSelectedKey(e); }; }(this));
|
||||
this.addListener(box, 'mouseover',
|
||||
function(vt100) { return function(e) {
|
||||
return vt100.resetLastSelectedKey(e); }; }(this));
|
||||
|
||||
// Configure SHIFT key behavior
|
||||
var style = document.createElement('style');
|
||||
var id = document.createAttribute('id');
|
||||
id.nodeValue = 'shift_state';
|
||||
style.setAttributeNode(id);
|
||||
var type = document.createAttribute('type');
|
||||
type.nodeValue = 'text/css';
|
||||
style.setAttributeNode(type);
|
||||
document.getElementsByTagName('head')[0].appendChild(style);
|
||||
|
||||
// Set up key bindings
|
||||
this.initializeKeyBindings(box);
|
||||
};
|
||||
|
||||
VT100.prototype.initializeElements = function(container) {
|
||||
// If the necessary objects have not already been defined in the HTML
|
||||
// page, create them now.
|
||||
|
@ -483,6 +805,9 @@ VT100.prototype.initializeElements = function(container) {
|
|||
|
||||
if (!this.getChildById(this.container, 'reconnect') ||
|
||||
!this.getChildById(this.container, 'menu') ||
|
||||
!this.getChildById(this.container, 'keyboard') ||
|
||||
!this.getChildById(this.container, 'kbd_button') ||
|
||||
!this.getChildById(this.container, 'kbd_img') ||
|
||||
!this.getChildById(this.container, 'scrollable') ||
|
||||
!this.getChildById(this.container, 'console') ||
|
||||
!this.getChildById(this.container, 'alt_console') ||
|
||||
|
@ -525,7 +850,15 @@ VT100.prototype.initializeElements = function(container) {
|
|||
'<div id="cursize" style="visibility: hidden">' +
|
||||
'</div>' +
|
||||
'<div id="menu"></div>' +
|
||||
'<div id="keyboard" unselectable="on">' +
|
||||
'<pre class="box"><div><i id="27">Esc</i><i id="112">F1</i><i id="113">F2</i><i id="114">F3</i><i id="115">F4</i><i id="116">F5</i><i id="117">F6</i><i id="118">F7</i><i id="119">F8</i><i id="120">F9</i><i id="121">F10</i><i id="122">F11</i><i id="123">F12</i><br /><b><span class="unshifted">`</span><span class="shifted">~</span></b><b><span class="unshifted">1</span><span class="shifted">!</span></b><b><span class="unshifted">2</span><span class="shifted">@</span></b><b><span class="unshifted">3</span><span class="shifted">#</span></b><b><span class="unshifted">4</span><span class="shifted">$</span></b><b><span class="unshifted">5</span><span class="shifted">%</span></b><b><span class="unshifted">6</span><span class="shifted">^</span></b><b><span class="unshifted">7</span><span class="shifted">&</span></b><b><span class="unshifted">8</span><span class="shifted">*</span></b><b><span class="unshifted">9</span><span class="shifted">(</span></b><b><span class="unshifted">0</span><span class="shifted">)</span></b><b><span class="unshifted">-</span><span class="shifted">_</span></b><b><span class="unshifted">=</span><span class="shifted">+</span></b><i id="8"> ← </i><br /><i id="9">Tab</i><b>Q</b><b>W</b><b>E</b><b>R</b><b>T</b><b>Y</b><b>U</b><b>I</b><b>O</b><b>P</b><b><span class="unshifted">[</span><span class="shifted">{</span></b><b><span class="unshifted">]</span><span class="shifted">}</span></b><b><span class="unshifted">\</span><span class="shifted">|</span></b><br /><u>Tab </u><b>A</b><b>S</b><b>D</b><b>F</b><b>G</b><b>H</b><b>J</b><b>K</b><b>L</b><b><span class="unshifted">;</span><span class="shifted">:</span></b><b><span class="unshifted">'</span><span class="shifted">"</span></b><i id="13">Enter</i><br /><u> </u><i id="16">Shift</i><b>Z</b><b>X</b><b>C</b><b>V</b><b>B</b><b>N</b><b>M</b><b><span class="unshifted">,</span><span class="shifted"><</span></b><b><span class="unshifted">.</span><span class="shifted">></span></b><b><span class="unshifted">/</span><span class="shifted">?</span></b><i id="16">Shift</i><br /><u>XXX</u><i id="17">Ctrl</i><i id="18">Alt</i><i style="width: 25ex"> </i></div> <div><i id="45">Ins</i><i id="46">Del</i><i id="36">Home</i><i id="35">End</i><br /><u> </u><br /><u> </u><br /><u>Ins</u><s> </s><b id="38">↑</b><s> </s><u> </u><b id="33">⇑</b><br /><u>Ins</u><b id="37">←</b><b id="40">↓</b><b id="39">→</b><u> </u><b id="34">⇓</b></div></pre>' +
|
||||
'</div>' +
|
||||
'<div id="scrollable">' +
|
||||
'<table id="kbd_button">' +
|
||||
'<tr><td width="100%"> </td>' +
|
||||
'<td><img id="kbd_img" src="keyboard.png" /></td>' +
|
||||
'<td> </td></tr>' +
|
||||
'</table>' +
|
||||
'<pre id="lineheight"> </pre>' +
|
||||
'<pre id="console">' +
|
||||
'<pre></pre>' +
|
||||
|
@ -566,6 +899,8 @@ VT100.prototype.initializeElements = function(container) {
|
|||
this.reconnectBtn = this.getChildById(this.container,'reconnect');
|
||||
this.curSizeBox = this.getChildById(this.container, 'cursize');
|
||||
this.menu = this.getChildById(this.container, 'menu');
|
||||
this.keyboard = this.getChildById(this.container, 'keyboard');
|
||||
this.keyboardImage = this.getChildById(this.container, 'kbd_img');
|
||||
this.scrollable = this.getChildById(this.container,
|
||||
'scrollable');
|
||||
this.lineheight = this.getChildById(this.container,
|
||||
|
@ -646,6 +981,9 @@ VT100.prototype.initializeElements = function(container) {
|
|||
// Hide context menu
|
||||
this.hideContextMenu();
|
||||
|
||||
// Set up onscreen soft keyboard
|
||||
this.initializeKeyboard();
|
||||
|
||||
// Add listener to reconnect button
|
||||
this.addListener(this.reconnectBtn.firstChild, 'click',
|
||||
function(vt100) {
|
||||
|
@ -733,6 +1071,7 @@ VT100.prototype.reconnect = function() {
|
|||
|
||||
VT100.prototype.showReconnect = function(state) {
|
||||
if (state) {
|
||||
this.hideSoftKeyboard();
|
||||
this.reconnectBtn.style.visibility = '';
|
||||
} else {
|
||||
this.reconnectBtn.style.visibility = 'hidden';
|
||||
|
@ -766,6 +1105,9 @@ VT100.prototype.resized = function(w, h) {
|
|||
};
|
||||
|
||||
VT100.prototype.resizer = function() {
|
||||
// Hide onscreen soft keyboard
|
||||
this.hideSoftKeyboard();
|
||||
|
||||
// The cursor can get corrupted if the print-preview is displayed in Firefox.
|
||||
// Recreating it, will repair it.
|
||||
var newCursor = document.createElement('pre');
|
||||
|
@ -945,6 +1287,17 @@ VT100.prototype.cancelEvent = function(event) {
|
|||
return false;
|
||||
};
|
||||
|
||||
VT100.prototype.mousePosition = function(event) {
|
||||
var offsetX = this.container.offsetLeft;
|
||||
var offsetY = this.container.offsetTop;
|
||||
for (var e = this.container; e = e.offsetParent; ) {
|
||||
offsetX += e.offsetLeft;
|
||||
offsetY += e.offsetTop;
|
||||
}
|
||||
return [ event.clientX - offsetX,
|
||||
event.clientY - offsetY ];
|
||||
};
|
||||
|
||||
VT100.prototype.mouseEvent = function(event, type) {
|
||||
// If any text is currently selected, do not move the focus as that would
|
||||
// invalidate the selection.
|
||||
|
@ -954,15 +1307,10 @@ VT100.prototype.mouseEvent = function(event, type) {
|
|||
}
|
||||
|
||||
// Compute mouse position in characters.
|
||||
var offsetX = this.container.offsetLeft;
|
||||
var offsetY = this.container.offsetTop;
|
||||
for (var e = this.container; e = e.offsetParent; ) {
|
||||
offsetX += e.offsetLeft;
|
||||
offsetY += e.offsetTop;
|
||||
}
|
||||
var x = (event.clientX - offsetX) / this.cursorWidth;
|
||||
var y = ((event.clientY - offsetY) + this.scrollable.offsetTop) /
|
||||
this.cursorHeight - this.numScrollbackLines;
|
||||
var position = this.mousePosition(event);
|
||||
var x = Math.floor(position[0] / this.cursorWidth);
|
||||
var y = Math.floor((position[1] + this.scrollable.scrollTop) /
|
||||
this.cursorHeight) - this.numScrollbackLines;
|
||||
var inside = true;
|
||||
if (x >= this.terminalWidth) {
|
||||
x = this.terminalWidth - 1;
|
||||
|
@ -1022,7 +1370,7 @@ VT100.prototype.mouseEvent = function(event, type) {
|
|||
// Bring up context menu.
|
||||
if (button == 2 && !event.shiftKey) {
|
||||
if (type == 0 /* MOUSE_DOWN */) {
|
||||
this.showContextMenu(event.clientX - offsetX, event.clientY - offsetY);
|
||||
this.showContextMenu(position[0], position[1]);
|
||||
}
|
||||
return this.cancelEvent(event);
|
||||
}
|
||||
|
@ -1058,6 +1406,29 @@ VT100.prototype.getTextContent = function(elem) {
|
|||
(typeof elem.textContent == 'undefined' ? elem.innerText : '');
|
||||
};
|
||||
|
||||
VT100.prototype.setTextContentRaw = function(elem, s) {
|
||||
// Updating the content of an element is an expensive operation. It actually
|
||||
// pays off to first check whether the element is still unchanged.
|
||||
if (typeof elem.textContent == 'undefined') {
|
||||
if (elem.innerText != s) {
|
||||
try {
|
||||
elem.innerText = s;
|
||||
} catch (e) {
|
||||
// Very old versions of IE do not allow setting innerText. Instead,
|
||||
// remove all children, by setting innerHTML and then set the text
|
||||
// using DOM methods.
|
||||
elem.innerHTML = '';
|
||||
elem.appendChild(document.createTextNode(
|
||||
this.replaceChar(s, ' ', '\u00A0')));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (elem.textContent != s) {
|
||||
elem.textContent = s;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
VT100.prototype.setTextContent = function(elem, s) {
|
||||
// Check if we find any URLs in the text. If so, automatically convert them
|
||||
// to links.
|
||||
|
@ -1103,26 +1474,7 @@ VT100.prototype.setTextContent = function(elem, s) {
|
|||
return;
|
||||
}
|
||||
|
||||
// Updating the content of an element is an expensive operation. It actually
|
||||
// pays off to first check whether the element is still unchanged.
|
||||
if (typeof elem.textContent == 'undefined') {
|
||||
if (elem.innerText != s) {
|
||||
try {
|
||||
elem.innerText = s;
|
||||
} catch (e) {
|
||||
// Very old versions of IE do not allow setting innerText. Instead,
|
||||
// remove all children, by setting innerHTML and then set the text
|
||||
// using DOM methods.
|
||||
elem.innerHTML = '';
|
||||
elem.appendChild(document.createTextNode(
|
||||
this.replaceChar(s, ' ', '\u00A0')));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (elem.textContent != s) {
|
||||
elem.textContent = s;
|
||||
}
|
||||
}
|
||||
this.setTextContentRaw(elem, s);
|
||||
};
|
||||
|
||||
VT100.prototype.insertBlankLine = function(y, color, style) {
|
||||
|
@ -1578,27 +1930,21 @@ VT100.prototype.enableAlternateScreen = function(state) {
|
|||
this.console[this.currentScreen].style.display = '';
|
||||
|
||||
// Select appropriate character pitch.
|
||||
var styles = [ 'transform',
|
||||
'WebkitTransform',
|
||||
'MozTransform',
|
||||
'filter' ];
|
||||
for (var i = 0; i < styles.length; ++i) {
|
||||
if (typeof this.console[0].style[styles[i]] != 'undefined') {
|
||||
if (state) {
|
||||
// Upon enabling the alternate screen, we switch to 80 column mode. But
|
||||
// upon returning to the regular screen, we restore the mode that was
|
||||
// in effect previously.
|
||||
this.console[1].style[styles[i]] = '';
|
||||
}
|
||||
var style =
|
||||
this.console[this.currentScreen].style[styles[i]];
|
||||
this.cursor.style[styles[i]] = style;
|
||||
this.space.style[styles[i]] = style;
|
||||
this.scale = style == '' ? 1.0:1.65;
|
||||
if (styles[i] == 'filter') {
|
||||
this.console[this.currentScreen].style.width = style == '' ? '165%':'';
|
||||
}
|
||||
break;
|
||||
var transform = this.getTransformName();
|
||||
if (transform) {
|
||||
if (state) {
|
||||
// Upon enabling the alternate screen, we switch to 80 column mode. But
|
||||
// upon returning to the regular screen, we restore the mode that was
|
||||
// in effect previously.
|
||||
this.console[1].style[transform] = '';
|
||||
}
|
||||
var style =
|
||||
this.console[this.currentScreen].style[transform];
|
||||
this.cursor.style[transform] = style;
|
||||
this.space.style[transform] = style;
|
||||
this.scale = style == '' ? 1.0:1.65;
|
||||
if (transform == 'filter') {
|
||||
this.console[this.currentScreen].style.width = style == '' ? '165%':'';
|
||||
}
|
||||
}
|
||||
this.resizer();
|
||||
|
@ -1969,12 +2315,76 @@ VT100.prototype.toggleBell = function() {
|
|||
this.visualBell = !this.visualBell;
|
||||
};
|
||||
|
||||
VT100.prototype.toggleSoftKeyboard = function() {
|
||||
this.softKeyboard = !this.softKeyboard;
|
||||
this.keyboardImage.style.visibility = this.softKeyboard ? 'visible' : '';
|
||||
};
|
||||
|
||||
VT100.prototype.deselectKeys = function(elem) {
|
||||
if (elem && elem.className == 'selected') {
|
||||
elem.className = '';
|
||||
}
|
||||
for (elem = elem.firstChild; elem; elem = elem.nextSibling) {
|
||||
this.deselectKeys(elem);
|
||||
}
|
||||
};
|
||||
|
||||
VT100.prototype.showSoftKeyboard = function() {
|
||||
// Make sure no key is currently selected
|
||||
this.lastSelectedKey = undefined;
|
||||
this.deselectKeys(this.keyboard);
|
||||
this.isShift = false;
|
||||
this.showShiftState(false);
|
||||
this.isCtrl = false;
|
||||
this.showCtrlState(false);
|
||||
this.isAlt = false;
|
||||
this.showAltState(false);
|
||||
|
||||
this.keyboard.style.left = '0px';
|
||||
this.keyboard.style.top = '0px';
|
||||
this.keyboard.style.width = this.container.offsetWidth + 'px';
|
||||
this.keyboard.style.height = this.container.offsetHeight + 'px';
|
||||
this.keyboard.style.visibility = 'hidden';
|
||||
this.keyboard.style.display = '';
|
||||
|
||||
var kbd = this.keyboard.firstChild;
|
||||
var scale = 1.0;
|
||||
var transform = this.getTransformName();
|
||||
if (transform) {
|
||||
kbd.style[transform] = '';
|
||||
if (kbd.offsetWidth > 0.9 * this.container.offsetWidth) {
|
||||
scale = (kbd.offsetWidth/
|
||||
this.container.offsetWidth)/0.9;
|
||||
}
|
||||
if (kbd.offsetHeight > 0.9 * this.container.offsetHeight) {
|
||||
scale = Math.max((kbd.offsetHeight/
|
||||
this.container.offsetHeight)/0.9);
|
||||
}
|
||||
var style = this.getTransformStyle(transform,
|
||||
scale > 1.0 ? scale : undefined);
|
||||
kbd.style[transform] = style;
|
||||
}
|
||||
if (transform == 'filter') {
|
||||
scale = 1.0;
|
||||
}
|
||||
kbd.style.left = ((this.container.offsetWidth -
|
||||
kbd.offsetWidth/scale)/2) + 'px';
|
||||
kbd.style.top = ((this.container.offsetHeight -
|
||||
kbd.offsetHeight/scale)/2) + 'px';
|
||||
|
||||
this.keyboard.style.visibility = 'visible';
|
||||
};
|
||||
|
||||
VT100.prototype.hideSoftKeyboard = function() {
|
||||
this.keyboard.style.display = 'none';
|
||||
};
|
||||
|
||||
VT100.prototype.toggleCursorBlinking = function() {
|
||||
this.blinkingCursor = !this.blinkingCursor;
|
||||
};
|
||||
|
||||
VT100.prototype.about = function() {
|
||||
alert("VT100 Terminal Emulator " + "2.10 (revision 220)" +
|
||||
alert("VT100 Terminal Emulator " + "2.10 (revision 221)" +
|
||||
"\nCopyright 2008-2010 by Markus Gutschke\n" +
|
||||
"For more information check http://shellinabox.com");
|
||||
};
|
||||
|
@ -2007,6 +2417,9 @@ VT100.prototype.showContextMenu = function(x, y) {
|
|||
'<li>' +
|
||||
(this.visualBell ? '<img src="enabled.gif" />' : '') +
|
||||
'Visual Bell</li>'+
|
||||
'<li>' +
|
||||
(this.softKeyboard ? '<img src="enabled.gif" />' : '') +
|
||||
'Onscreen Keyboard</li>' +
|
||||
'<li id="endconfig">' +
|
||||
(this.blinkingCursor ? '<img src="enabled.gif" />' : '') +
|
||||
'Blinking Cursor</li>'+
|
||||
|
@ -2038,6 +2451,7 @@ VT100.prototype.showContextMenu = function(x, y) {
|
|||
// Actions for default items
|
||||
var actions = [ this.copyLast, p, this.reset,
|
||||
this.toggleUTF, this.toggleBell,
|
||||
this.toggleSoftKeyboard,
|
||||
this.toggleCursorBlinking ];
|
||||
|
||||
// Actions for user CSS styles (if any)
|
||||
|
@ -2093,26 +2507,30 @@ VT100.prototype.showContextMenu = function(x, y) {
|
|||
}
|
||||
|
||||
// Position menu next to the mouse pointer
|
||||
if (x + popup.clientWidth > this.container.offsetWidth) {
|
||||
x = this.container.offsetWidth - popup.clientWidth;
|
||||
this.menu.style.left = '0px';
|
||||
this.menu.style.top = '0px';
|
||||
this.menu.style.width = this.container.offsetWidth + 'px';
|
||||
this.menu.style.height = this.container.offsetHeight + 'px';
|
||||
popup.style.left = '0px';
|
||||
popup.style.top = '0px';
|
||||
|
||||
var margin = 2;
|
||||
if (x + popup.clientWidth >= this.container.offsetWidth - margin) {
|
||||
x = this.container.offsetWidth-popup.clientWidth - margin - 1;
|
||||
}
|
||||
if (x < 0) {
|
||||
x = 0;
|
||||
if (x < margin) {
|
||||
x = margin;
|
||||
}
|
||||
if (y + popup.clientHeight > this.container.offsetHeight) {
|
||||
y = this.container.offsetHeight-popup.clientHeight;
|
||||
if (y + popup.clientHeight >= this.container.offsetHeight - margin) {
|
||||
y = this.container.offsetHeight-popup.clientHeight - margin - 1;
|
||||
}
|
||||
if (y < 0) {
|
||||
y = 0;
|
||||
if (y < margin) {
|
||||
y = margin;
|
||||
}
|
||||
popup.style.left = x + 'px';
|
||||
popup.style.top = y + 'px';
|
||||
|
||||
// Block all other interactions with the terminal emulator
|
||||
this.menu.style.left = '0px';
|
||||
this.menu.style.top = '0px';
|
||||
this.menu.style.width = this.container.offsetWidth + 'px';
|
||||
this.menu.style.height = this.container.offsetHeight + 'px';
|
||||
this.addListener(this.menu, 'click', function(vt100) {
|
||||
return function() {
|
||||
vt100.hideContextMenu();
|
||||
|
@ -2895,39 +3313,42 @@ VT100.prototype.restoreCursor = function() {
|
|||
this.savedY[this.currentScreen]);
|
||||
};
|
||||
|
||||
VT100.prototype.set80_132Mode = function(state) {
|
||||
var transform = undefined;
|
||||
var styles = [ 'transform',
|
||||
'WebkitTransform',
|
||||
'MozTransform',
|
||||
'filter'
|
||||
];
|
||||
VT100.prototype.getTransformName = function() {
|
||||
var styles = [ 'transform', 'WebkitTransform', 'MozTransform', 'filter' ];
|
||||
for (var i = 0; i < styles.length; ++i) {
|
||||
if (typeof this.console[0].style[styles[i]] != 'undefined') {
|
||||
transform = styles[i];
|
||||
break;
|
||||
return styles[i];
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
VT100.prototype.getTransformStyle = function(transform, scale) {
|
||||
return scale && scale != 1.0
|
||||
? transform == 'filter'
|
||||
? 'progid:DXImageTransform.Microsoft.Matrix(' +
|
||||
'M11=' + (1.0/scale) + ',M12=0,M21=0,M22=1,' +
|
||||
"sizingMethod='auto expand')"
|
||||
: 'translateX(-50%) ' +
|
||||
'scaleX(' + (1.0/scale) + ') ' +
|
||||
'translateX(50%)'
|
||||
: '';
|
||||
};
|
||||
|
||||
VT100.prototype.set80_132Mode = function(state) {
|
||||
var transform = this.getTransformName();
|
||||
if (transform) {
|
||||
if ((this.console[this.currentScreen].style[transform] != '') == state) {
|
||||
return;
|
||||
}
|
||||
var style =
|
||||
state ? transform == 'filter'
|
||||
? 'progid:DXImageTransform.Microsoft.Matrix(' +
|
||||
'M11=0.606060606060606060606,M12=0,M21=0,M22=1,' +
|
||||
"sizingMethod='auto expand')"
|
||||
: 'translateX(-50%) ' +
|
||||
'scaleX(0.606060606060606060606) ' +
|
||||
'translateX(50%)'
|
||||
: '';
|
||||
var style = state ?
|
||||
this.getTransformStyle(transform, 1.65):'';
|
||||
this.console[this.currentScreen].style[transform] = style;
|
||||
this.cursor.style[transform] = style;
|
||||
this.space.style[transform] = style;
|
||||
this.scale = state ? 1.65 : 1.0;
|
||||
this.cursor.style[transform] = style;
|
||||
this.space.style[transform] = style;
|
||||
this.scale = state ? 1.65 : 1.0;
|
||||
if (transform == 'filter') {
|
||||
this.console[this.currentScreen].style.width = state ? '165%' : '';
|
||||
this.console[this.currentScreen].style.width = state ? '165%' : '';
|
||||
}
|
||||
this.resizer();
|
||||
}
|
||||
|
|
59
shellinabox/keyboard-layout.html
Normal file
59
shellinabox/keyboard-layout.html
Normal file
|
@ -0,0 +1,59 @@
|
|||
<pre class="box">
|
||||
<div>
|
||||
<i id="27">Esc</i><i id="112">F1</i><i id="113">F2</i><i id="114">F3</i>
|
||||
<i id="115">F4</i><i id="116">F5</i><i id="117">F6</i><i id="118">F7</i>
|
||||
<i id="119">F8</i><i id="120">F9</i><i id="121">F10</i><i id="122">F11</i>
|
||||
<i id="123">F12</i><br />
|
||||
<b><span class="unshifted">`</span><span class="shifted">~</span></b>
|
||||
<b><span class="unshifted">1</span><span class="shifted">!</span></b>
|
||||
<b><span class="unshifted">2</span><span class="shifted">@</span></b>
|
||||
<b><span class="unshifted">3</span><span class="shifted">#</span></b>
|
||||
<b><span class="unshifted">4</span><span class="shifted">$</span></b>
|
||||
<b><span class="unshifted">5</span><span class="shifted">%</span></b>
|
||||
<b><span class="unshifted">6</span><span class="shifted">^</span></b>
|
||||
<b><span class="unshifted">7</span><span class="shifted">&</span></b>
|
||||
<b><span class="unshifted">8</span><span class="shifted">*</span></b>
|
||||
<b><span class="unshifted">9</span><span class="shifted">(</span></b>
|
||||
<b><span class="unshifted">0</span><span class="shifted">)</span></b>
|
||||
<b><span class="unshifted">-</span><span class="shifted">_</span></b>
|
||||
<b><span class="unshifted">=</span><span class="shifted">+</span></b>
|
||||
<i id="8"> ← </i>
|
||||
<br />
|
||||
<i id="9">Tab</i>
|
||||
<b>Q</b><b>W</b><b>E</b><b>R</b><b>T</b><b>Y</b><b>U</b><b>I</b><b>O</b>
|
||||
<b>P</b>
|
||||
<b><span class="unshifted">[</span><span class="shifted">{</span></b>
|
||||
<b><span class="unshifted">]</span><span class="shifted">}</span></b>
|
||||
<b><span class="unshifted">\</span><span class="shifted">|</span></b>
|
||||
<br />
|
||||
<u>Tab </u>
|
||||
<b>A</b><b>S</b><b>D</b><b>F</b><b>G</b><b>H</b><b>J</b><b>K</b><b>L</b>
|
||||
<b><span class="unshifted">;</span><span class="shifted">:</span></b>
|
||||
<b><span class="unshifted">'</span><span class="shifted">"</span></b>
|
||||
<i id="13">Enter</i>
|
||||
<br />
|
||||
<u> </u>
|
||||
<i id="16">Shift</i>
|
||||
<b>Z</b><b>X</b><b>C</b><b>V</b><b>B</b><b>N</b><b>M</b>
|
||||
<b><span class="unshifted">,</span><span class="shifted"><</span></b>
|
||||
<b><span class="unshifted">.</span><span class="shifted">></span></b>
|
||||
<b><span class="unshifted">/</span><span class="shifted">?</span></b>
|
||||
<i id="16">Shift</i>
|
||||
<br />
|
||||
<u>XXX</u>
|
||||
<i id="17">Ctrl</i>
|
||||
<i id="18">Alt</i>
|
||||
<i style="width: 25ex"> </i>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<i id="45">Ins</i><i id="46">Del</i><i id="36">Home</i><i id="35">End</i>
|
||||
<br />
|
||||
<u> </u><br />
|
||||
<u> </u><br />
|
||||
<u>Ins</u><s> </s><b id="38">↑</b><s> </s><u> </u>
|
||||
<b id="33">⇑</b><br />
|
||||
<u>Ins</u><b id="37">←</b><b id="40">↓</b>
|
||||
<b id="39">→</b><u> </u><b id="34">⇓</b>
|
||||
</div>
|
||||
</pre>
|
BIN
shellinabox/keyboard.png
Normal file
BIN
shellinabox/keyboard.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 808 B |
|
@ -358,7 +358,7 @@ ShellInABox.prototype.extendContextMenu = function(entries, actions) {
|
|||
};
|
||||
|
||||
ShellInABox.prototype.about = function() {
|
||||
alert("Shell In A Box version " + "2.10 (revision 220)" +
|
||||
alert("Shell In A Box version " + "2.10 (revision 221)" +
|
||||
"\nCopyright 2008-2010 by Markus Gutschke\n" +
|
||||
"For more information check http://shellinabox.com" +
|
||||
(typeof serverSupportsSSL != 'undefined' && serverSupportsSSL ?
|
||||
|
|
|
@ -641,6 +641,11 @@ static int shellInABoxHttpHandler(HttpConnection *http, void *arg,
|
|||
extern char faviconStart[];
|
||||
extern char faviconEnd[];
|
||||
serveStaticFile(http, "image/x-icon", faviconStart, faviconEnd);
|
||||
} else if (pathInfoLength == 12 && !memcmp(pathInfo, "keyboard.png", 11)) {
|
||||
// Serve the keyboard icon
|
||||
extern char keyboardStart[];
|
||||
extern char keyboardEnd[];
|
||||
serveStaticFile(http, "image/png", keyboardStart, keyboardEnd);
|
||||
} else if (pathInfoLength == 14 && !memcmp(pathInfo, "ShellInABox.js", 14)) {
|
||||
// Serve both vt100.js and shell_in_a_box.js in the same transaction.
|
||||
// Also, indicate to the client whether the server is SSL enabled.
|
||||
|
|
|
@ -1,140 +1,217 @@
|
|||
#vt100 a {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
#vt100 a:hover {
|
||||
text-decoration: underline;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#vt100 #reconnect {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
#vt100 #reconnect input {
|
||||
padding: 1ex;
|
||||
font-weight: bold;
|
||||
font-size: x-large;
|
||||
padding: 1ex;
|
||||
font-weight: bold;
|
||||
font-size: x-large;
|
||||
}
|
||||
|
||||
#vt100 #cursize {
|
||||
background: #EEEEEE;
|
||||
border: 1px solid black;
|
||||
font-family: sans-serif;
|
||||
font-size: large;
|
||||
font-weight: bold;
|
||||
padding: 1ex;
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
background: #EEEEEE;
|
||||
border: 1px solid black;
|
||||
font-family: sans-serif;
|
||||
font-size: large;
|
||||
font-weight: bold;
|
||||
padding: 1ex;
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
#vt100 pre {
|
||||
margin: 0px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
#vt100 pre pre {
|
||||
overflow: hidden;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#vt100 #scrollable {
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
position: relative;
|
||||
padding: 1px;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
position: relative;
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
#vt100 #console, #vt100 #alt_console, #vt100 #cursor, #vt100 #lineheight, #vt100 .hidden pre {
|
||||
font-family: "DejaVu Sans Mono", "Everson Mono", FreeMono, "Andale Mono", "Lucida Console", monospace;
|
||||
font-family: "DejaVu Sans Mono", "Everson Mono", FreeMono, "Andale Mono", "Lucida Console", monospace;
|
||||
}
|
||||
|
||||
#vt100 #lineheight {
|
||||
position: absolute;
|
||||
visibility: hidden;
|
||||
position: absolute;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#vt100 #cursor {
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
overflow: hidden;
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
overflow: hidden;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
#vt100 #cursor.bright {
|
||||
background-color: #e60000;
|
||||
color: white;
|
||||
background-color: #e60000;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#vt100 #cursor.dim {
|
||||
visibility: hidden;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#vt100 #cursor.inactive {
|
||||
border: 1px solid #e60000;
|
||||
margin: -1px;
|
||||
border: 1px solid #e60000;
|
||||
margin: -1px;
|
||||
}
|
||||
|
||||
#vt100 #padding {
|
||||
visibility: hidden;
|
||||
width: 1px;
|
||||
height: 0px;
|
||||
overflow: hidden;
|
||||
visibility: hidden;
|
||||
width: 1px;
|
||||
height: 0px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#vt100 .hidden {
|
||||
position: absolute;
|
||||
top: -10000px;
|
||||
left: -10000px;
|
||||
width: 0px;
|
||||
height: 0px;
|
||||
position: absolute;
|
||||
top: -10000px;
|
||||
left: -10000px;
|
||||
width: 0px;
|
||||
height: 0px;
|
||||
}
|
||||
|
||||
#vt100 #menu {
|
||||
overflow: visible;
|
||||
position: absolute;
|
||||
z-index: 3;
|
||||
overflow: visible;
|
||||
position: absolute;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
#vt100 #menu .popup {
|
||||
background-color: #EEEEEE;
|
||||
border: 1px solid black;
|
||||
font-family: sans-serif;
|
||||
position: absolute;
|
||||
background-color: #EEEEEE;
|
||||
border: 1px solid black;
|
||||
font-family: sans-serif;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
#vt100 #menu .popup ul {
|
||||
list-style-type: none;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
min-width: 10em;
|
||||
list-style-type: none;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
min-width: 10em;
|
||||
}
|
||||
|
||||
#vt100 #menu .popup li {
|
||||
padding: 3px 0.5ex 3px 0.5ex;
|
||||
padding: 3px 0.5ex 3px 0.5ex;
|
||||
}
|
||||
|
||||
#vt100 #menu .popup li.hover {
|
||||
background-color: #444444;
|
||||
color: white;
|
||||
background-color: #444444;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#vt100 #menu .popup li.disabled {
|
||||
color: #AAAAAA;
|
||||
color: #AAAAAA;
|
||||
}
|
||||
|
||||
#vt100 #menu .popup hr {
|
||||
margin: 0.5ex 0px 0.5ex 0px;
|
||||
margin: 0.5ex 0px 0.5ex 0px;
|
||||
}
|
||||
|
||||
#vt100 #menu img {
|
||||
margin-right: 0.5ex;
|
||||
width: 1ex;
|
||||
height: 1ex;
|
||||
margin-right: 0.5ex;
|
||||
width: 1ex;
|
||||
height: 1ex;
|
||||
}
|
||||
|
||||
#vt100 #scrollable.inverted { color: #ffffff;
|
||||
background-color: #000000; }
|
||||
|
||||
#vt100 #kbd_button {
|
||||
float: left;
|
||||
position: fixed;
|
||||
z-index: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#vt100 #keyboard {
|
||||
z-index: 3;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
#vt100 #keyboard .box {
|
||||
font-family: sans-serif;
|
||||
background-color: #cccccc;
|
||||
padding: .8em;
|
||||
float: left;
|
||||
position: absolute;
|
||||
border-radius: 10px;
|
||||
-moz-border-radius: 10px;
|
||||
box-shadow: 4px 4px 6px #222222;
|
||||
-webkit-box-shadow: 4px 4px 6px #222222;
|
||||
/* Don't set the -moz-box-shadow. It doesn't properly scale when CSS
|
||||
* transforms are in effect. Once Firefox supports box-shadow, it should
|
||||
* automatically do the right thing. Until then, leave shadows disabled
|
||||
* for Firefox.
|
||||
*/
|
||||
opacity: 0.85;
|
||||
-moz-opacity: 0.85;
|
||||
filter: alpha(opacity=85);
|
||||
}
|
||||
|
||||
#vt100 #keyboard .box * {
|
||||
vertical-align: top;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#vt100 #keyboard b, #vt100 #keyboard i, #vt100 #keyboard s, #vt100 #keyboard u {
|
||||
font-style: normal;
|
||||
font-weight: bold;
|
||||
border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
background-color: #555555;
|
||||
color: #eeeeee;
|
||||
box-shadow: 2px 2px 3px #222222;
|
||||
-webkit-box-shadow: 2px 2px 3px #222222;
|
||||
padding: 4px;
|
||||
margin: 2px;
|
||||
height: 2ex;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#vt100 #keyboard b, #vt100 #keyboard s {
|
||||
width: 2ex;
|
||||
}
|
||||
|
||||
#vt100 #keyboard u, #vt100 #keyboard s {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#vt100 #keyboard .shifted {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#vt100 #keyboard .selected {
|
||||
color: #888888;
|
||||
background-color: #eeeeee;
|
||||
box-shadow: 0px 0px 3px #222222;
|
||||
-webkit-box-shadow: 0px 0px 3px #222222;
|
||||
position: relative;
|
||||
top: 1px;
|
||||
left: 1px;
|
||||
}
|
||||
|
||||
[if DEFINES_COLORS]
|
||||
/* IE cannot properly handle "inherit" properties. So, the monochrome.css/
|
||||
* color.css style sheets cannot work, if we define colors in styles.css.
|
||||
|
@ -177,19 +254,19 @@
|
|||
|
||||
@media print {
|
||||
#vt100 .scrollback {
|
||||
display: none;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#vt100 #reconnect, #vt100 #cursor, #vt100 #menu {
|
||||
visibility: hidden;
|
||||
#vt100 #reconnect, #vt100 #cursor, #vt100 #menu, #vt100 #kbd_button, #vt100 #keyboard {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#vt100 #scrollable {
|
||||
overflow: hidden;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#vt100 #console, #vt100 #alt_console {
|
||||
overflow: hidden;
|
||||
width: 1000000ex;
|
||||
overflow: hidden;
|
||||
width: 1000000ex;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -238,22 +238,16 @@ VT100.prototype.reset = function(clearHistory) {
|
|||
this.enableAlternateScreen(false);
|
||||
|
||||
var wasCompressed = false;
|
||||
var styles = [ 'transform',
|
||||
'WebkitTransform',
|
||||
'MozTransform',
|
||||
'filter' ];
|
||||
for (var i = 0; i < styles.length; ++i) {
|
||||
if (typeof this.console[0].style[styles[i]] != 'undefined') {
|
||||
for (var j = 0; j < 1; ++j) {
|
||||
wasCompressed |= this.console[j].style[styles[i]] != '';
|
||||
this.console[j].style[styles[i]] = '';
|
||||
}
|
||||
this.cursor.style[styles[i]] = '';
|
||||
this.space.style[styles[i]] = '';
|
||||
if (styles[i] == 'filter') {
|
||||
this.console[this.currentScreen].style.width = '';
|
||||
}
|
||||
break;
|
||||
var transform = this.getTransformName();
|
||||
if (transform) {
|
||||
for (var i = 0; i < 2; ++i) {
|
||||
wasCompressed |= this.console[i].style[transform] != '';
|
||||
this.console[i].style[transform] = '';
|
||||
}
|
||||
this.cursor.style[transform] = '';
|
||||
this.space.style[transform] = '';
|
||||
if (transform == 'filter') {
|
||||
this.console[this.currentScreen].style.width = '';
|
||||
}
|
||||
}
|
||||
this.scale = 1.0;
|
||||
|
@ -270,10 +264,13 @@ VT100.prototype.reset = function(clearHistory) {
|
|||
};
|
||||
|
||||
VT100.prototype.addListener = function(elem, event, listener) {
|
||||
if (elem.addEventListener) {
|
||||
elem.addEventListener(event, listener, false);
|
||||
} else {
|
||||
elem.attachEvent('on' + event, listener);
|
||||
try {
|
||||
if (elem.addEventListener) {
|
||||
elem.addEventListener(event, listener, false);
|
||||
} else {
|
||||
elem.attachEvent('on' + event, listener);
|
||||
}
|
||||
} catch (e) {
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -281,11 +278,12 @@ VT100.prototype.getUserSettings = function() {
|
|||
// Compute hash signature to identify the entries in the userCSS menu.
|
||||
// If the menu is unchanged from last time, default values can be
|
||||
// looked up in a cookie associated with this page.
|
||||
this.signature = 2;
|
||||
this.signature = 3;
|
||||
this.utfPreferred = true;
|
||||
this.visualBell = typeof suppressAllAudio != 'undefined' &&
|
||||
suppressAllAudio;
|
||||
this.autoprint = true;
|
||||
this.softKeyboard = false;
|
||||
this.blinkingCursor = true;
|
||||
if (this.visualBell) {
|
||||
this.signature = Math.floor(16807*this.signature + 1) %
|
||||
|
@ -311,15 +309,16 @@ VT100.prototype.getUserSettings = function() {
|
|||
if (settings >= 0) {
|
||||
settings = document.cookie.substr(settings + key.length).
|
||||
replace(/([0-1]*).*/, "$1");
|
||||
if (settings.length == 3 + (typeof userCSSList == 'undefined' ?
|
||||
if (settings.length == 5 + (typeof userCSSList == 'undefined' ?
|
||||
0 : userCSSList.length)) {
|
||||
this.utfPreferred = settings.charAt(0) != '0';
|
||||
this.visualBell = settings.charAt(1) != '0';
|
||||
this.autoprint = settings.charAt(2) != '0';
|
||||
this.blinkingCursor = settings.charAt(3) != '0';
|
||||
this.softKeyboard = settings.charAt(3) != '0';
|
||||
this.blinkingCursor = settings.charAt(4) != '0';
|
||||
if (typeof userCSSList != 'undefined') {
|
||||
for (var i = 0; i < userCSSList.length; ++i) {
|
||||
userCSSList[i][2] = settings.charAt(i + 3) != '0';
|
||||
userCSSList[i][2] = settings.charAt(i + 5) != '0';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -332,6 +331,7 @@ VT100.prototype.storeUserSettings = function() {
|
|||
(this.utfEnabled ? '1' : '0') +
|
||||
(this.visualBell ? '1' : '0') +
|
||||
(this.autoprint ? '1' : '0') +
|
||||
(this.softKeyboard ? '1' : '0') +
|
||||
(this.blinkingCursor ? '1' : '0');
|
||||
if (typeof userCSSList != 'undefined') {
|
||||
for (var i = 0; i < userCSSList.length; ++i) {
|
||||
|
@ -413,7 +413,7 @@ VT100.prototype.initializeUserCSSStyles = function() {
|
|||
label.textContent= label.textContent;
|
||||
}
|
||||
|
||||
// User style sheets are number sequentially
|
||||
// User style sheets are numbered sequentially
|
||||
var sheet = document.getElementById(
|
||||
'usercss-' + i);
|
||||
if (i == current) {
|
||||
|
@ -470,6 +470,328 @@ VT100.prototype.initializeUserCSSStyles = function() {
|
|||
}
|
||||
};
|
||||
|
||||
VT100.prototype.resetLastSelectedKey = function(e) {
|
||||
var key = this.lastSelectedKey;
|
||||
if (!key) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var position = this.mousePosition(e);
|
||||
|
||||
// We don't get all the necessary events to reliably reselect a key
|
||||
// if we moved away from it and then back onto it. We approximate the
|
||||
// behavior by remembering the key until either we release the mouse
|
||||
// button (we might never get this event if the mouse has since left
|
||||
// the window), or until we move away too far.
|
||||
var box = this.keyboard.firstChild;
|
||||
if (position[0] < box.offsetLeft + key.offsetWidth ||
|
||||
position[1] < box.offsetTop + key.offsetHeight ||
|
||||
position[0] >= box.offsetLeft + box.offsetWidth - key.offsetWidth ||
|
||||
position[1] >= box.offsetTop + box.offsetHeight - key.offsetHeight ||
|
||||
position[0] < box.offsetLeft + key.offsetLeft - key.offsetWidth ||
|
||||
position[1] < box.offsetTop + key.offsetTop - key.offsetHeight ||
|
||||
position[0] >= box.offsetLeft + key.offsetLeft + 2*key.offsetWidth ||
|
||||
position[1] >= box.offsetTop + key.offsetTop + 2*key.offsetHeight) {
|
||||
if (this.lastSelectedKey.className) log.console('reset: deselecting');
|
||||
this.lastSelectedKey.className = '';
|
||||
this.lastSelectedKey = undefined;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
VT100.prototype.showShiftState = function(state) {
|
||||
var style = document.getElementById('shift_state');
|
||||
if (state) {
|
||||
this.setTextContentRaw(style,
|
||||
'#vt100 #keyboard .shifted {' +
|
||||
'display: inline }' +
|
||||
'#vt100 #keyboard .unshifted {' +
|
||||
'display: none }');
|
||||
} else {
|
||||
this.setTextContentRaw(style, '');
|
||||
}
|
||||
var elems = this.keyboard.getElementsByTagName('I');
|
||||
for (var i = 0; i < elems.length; ++i) {
|
||||
if (elems[i].id == '16') {
|
||||
elems[i].className = state ? 'selected' : '';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
VT100.prototype.showCtrlState = function(state) {
|
||||
var ctrl = this.getChildById(this.keyboard, '17' /* Ctrl */);
|
||||
if (ctrl) {
|
||||
ctrl.className = state ? 'selected' : '';
|
||||
}
|
||||
};
|
||||
|
||||
VT100.prototype.showAltState = function(state) {
|
||||
var alt = this.getChildById(this.keyboard, '18' /* Alt */);
|
||||
if (alt) {
|
||||
alt.className = state ? 'selected' : '';
|
||||
}
|
||||
};
|
||||
|
||||
VT100.prototype.clickedKeyboard = function(e, elem, ch, key, shift, ctrl, alt){
|
||||
var fake = [ ];
|
||||
fake.charCode = ch;
|
||||
fake.keyCode = key;
|
||||
fake.ctrlKey = ctrl;
|
||||
fake.shiftKey = shift;
|
||||
fake.altKey = alt;
|
||||
fake.metaKey = alt;
|
||||
return this.handleKey(fake);
|
||||
};
|
||||
|
||||
VT100.prototype.addKeyBinding = function(elem, ch, key, CH, KEY) {
|
||||
if (elem == undefined) {
|
||||
return;
|
||||
}
|
||||
if (ch == '\u00A0') {
|
||||
// should be treated as a regular space character.
|
||||
ch = ' ';
|
||||
}
|
||||
if (ch != undefined && CH == undefined) {
|
||||
// For letter keys, we automatically compute the uppercase character code
|
||||
// from the lowercase one.
|
||||
CH = ch.toUpperCase();
|
||||
}
|
||||
if (KEY == undefined && key != undefined) {
|
||||
// Most keys have identically key codes for both lowercase and uppercase
|
||||
// keypresses. Normally, only function keys would have distinct key codes,
|
||||
// whereas regular keys have character codes.
|
||||
KEY = key;
|
||||
} else if (KEY == undefined && CH != undefined) {
|
||||
// For regular keys, copy the character code to the key code.
|
||||
KEY = CH.charCodeAt(0);
|
||||
}
|
||||
if (key == undefined && ch != undefined) {
|
||||
// For regular keys, copy the character code to the key code.
|
||||
key = ch.charCodeAt(0);
|
||||
}
|
||||
// Convert characters to numeric character codes. If the character code
|
||||
// is undefined (i.e. this is a function key), set it to zero.
|
||||
ch = ch ? ch.charCodeAt(0) : 0;
|
||||
CH = CH ? CH.charCodeAt(0) : 0;
|
||||
|
||||
// Mouse down events high light the key. We also set lastSelectedKey. This
|
||||
// is needed to that mouseout/mouseover can keep track of the key that
|
||||
// is currently being clicked.
|
||||
this.addListener(elem, 'mousedown',
|
||||
function(vt100, elem, key) { return function(e) {
|
||||
if ((e.which || e.button) == 1) {
|
||||
if (vt100.lastSelectedKey) {
|
||||
vt100.lastSelectedKey.className= '';
|
||||
}
|
||||
// Highlight the key while the mouse button is held down.
|
||||
if (key == 16 /* Shift */) {
|
||||
if (!elem.className != vt100.isShift) {
|
||||
vt100.showShiftState(!vt100.isShift);
|
||||
}
|
||||
} else if (key == 17 /* Ctrl */) {
|
||||
if (!elem.className != vt100.isCtrl) {
|
||||
vt100.showCtrlState(!vt100.isCtrl);
|
||||
}
|
||||
} else if (key == 18 /* Alt */) {
|
||||
if (!elem.className != vt100.isAlt) {
|
||||
vt100.showAltState(!vt100.isAlt);
|
||||
}
|
||||
} else {
|
||||
elem.className = 'selected';
|
||||
}
|
||||
vt100.lastSelectedKey = elem;
|
||||
}
|
||||
return false; }; }(this, elem, key));
|
||||
var clicked =
|
||||
// Modifier keys update the state of the keyboard, but do not generate
|
||||
// any key clicks that get forwarded to the application.
|
||||
key >= 16 /* Shift */ && key <= 18 /* Alt */ ?
|
||||
function(vt100, elem) { return function(e) {
|
||||
if (elem == vt100.lastSelectedKey) {
|
||||
if (key == 16 /* Shift */) {
|
||||
// The user clicked the Shift key
|
||||
vt100.isShift = !vt100.isShift;
|
||||
vt100.showShiftState(vt100.isShift);
|
||||
} else if (key == 17 /* Ctrl */) {
|
||||
vt100.isCtrl = !vt100.isCtrl;
|
||||
vt100.showCtrlState(vt100.isCtrl);
|
||||
} else if (key == 18 /* Alt */) {
|
||||
vt100.isAlt = !vt100.isAlt;
|
||||
vt100.showAltState(vt100.isAlt);
|
||||
}
|
||||
vt100.lastSelectedKey = undefined;
|
||||
}
|
||||
if (vt100.lastSelectedKey) {
|
||||
vt100.lastSelectedKey.className = '';
|
||||
vt100.lastSelectedKey = undefined;
|
||||
}
|
||||
return false; }; }(this, elem) :
|
||||
// Regular keys generate key clicks, when the mouse button is released or
|
||||
// when a mouse click event is received.
|
||||
function(vt100, elem, ch, key, CH, KEY) { return function(e) {
|
||||
if (vt100.lastSelectedKey) {
|
||||
if (elem == vt100.lastSelectedKey) {
|
||||
// The user clicked a key.
|
||||
if (vt100.isShift) {
|
||||
vt100.clickedKeyboard(e, elem, CH, KEY,
|
||||
true, vt100.isCtrl, vt100.isAlt);
|
||||
} else {
|
||||
vt100.clickedKeyboard(e, elem, ch, key,
|
||||
false, vt100.isCtrl, vt100.isAlt);
|
||||
}
|
||||
vt100.isShift = false;
|
||||
vt100.showShiftState(false);
|
||||
vt100.isCtrl = false;
|
||||
vt100.showCtrlState(false);
|
||||
vt100.isAlt = false;
|
||||
vt100.showAltState(false);
|
||||
}
|
||||
vt100.lastSelectedKey.className = '';
|
||||
vt100.lastSelectedKey = undefined;
|
||||
}
|
||||
elem.className = '';
|
||||
return false; }; }(this, elem, ch, key, CH, KEY);
|
||||
this.addListener(elem, 'mouseup', clicked);
|
||||
this.addListener(elem, 'click', clicked);
|
||||
|
||||
// When moving the mouse away from a key, check if any keys need to be
|
||||
// deselected.
|
||||
this.addListener(elem, 'mouseout',
|
||||
function(vt100, elem, key) { return function(e) {
|
||||
if (key == 16 /* Shift */) {
|
||||
if (!elem.className == vt100.isShift) {
|
||||
vt100.showShiftState(vt100.isShift);
|
||||
}
|
||||
} else if (key == 17 /* Ctrl */) {
|
||||
if (!elem.className == vt100.isCtrl) {
|
||||
vt100.showCtrlState(vt100.isCtrl);
|
||||
}
|
||||
} else if (key == 18 /* Alt */) {
|
||||
if (!elem.className == vt100.isAlt) {
|
||||
vt100.showAltState(vt100.isAlt);
|
||||
}
|
||||
} else if (elem.className) {
|
||||
elem.className = '';
|
||||
vt100.lastSelectedKey = elem;
|
||||
} else if (vt100.lastSelectedKey) {
|
||||
vt100.resetLastSelectedKey(e);
|
||||
}
|
||||
return false; }; }(this, elem, key));
|
||||
|
||||
// When moving the mouse over a key, select it if the user is still holding
|
||||
// the mouse button down (i.e. elem == lastSelectedKey)
|
||||
this.addListener(elem, 'mouseover',
|
||||
function(vt100, elem, key) { return function(e) {
|
||||
if (elem == vt100.lastSelectedKey) {
|
||||
if (key == 16 /* Shift */) {
|
||||
if (!elem.className != vt100.isShift) {
|
||||
vt100.showShiftState(!vt100.isShift);
|
||||
}
|
||||
} else if (key == 17 /* Ctrl */) {
|
||||
if (!elem.className != vt100.isCtrl) {
|
||||
vt100.showCtrlState(!vt100.isCtrl);
|
||||
}
|
||||
} else if (key == 18 /* Alt */) {
|
||||
if (!elem.className != vt100.isAlt) {
|
||||
vt100.showAltState(!vt100.isAlt);
|
||||
}
|
||||
} else if (!elem.className) {
|
||||
elem.className = 'selected';
|
||||
}
|
||||
} else {
|
||||
vt100.resetLastSelectedKey(e);
|
||||
}
|
||||
return false; }; }(this, elem, key));
|
||||
};
|
||||
|
||||
VT100.prototype.initializeKeyBindings = function(elem) {
|
||||
if (elem) {
|
||||
if (elem.nodeName == "I" || elem.nodeName == "B") {
|
||||
if (elem.id) {
|
||||
// Function keys. The Javascript keycode is part of the "id"
|
||||
var i = parseInt(elem.id);
|
||||
if (i) {
|
||||
// If the id does not parse as a number, it is not a keycode.
|
||||
this.addKeyBinding(elem, undefined, i);
|
||||
}
|
||||
} else {
|
||||
var child = elem.firstChild;
|
||||
if (child.nodeName == "#text") {
|
||||
// If the key only has a text node as a child, then it is a letter.
|
||||
// Automatically compute the lower and upper case version of the key.
|
||||
this.addKeyBinding(elem, this.getTextContent(child).toLowerCase());
|
||||
} else {
|
||||
// If the key has two children, they are the lower and upper case
|
||||
// character code, respectively.
|
||||
this.addKeyBinding(elem, this.getTextContent(child), undefined,
|
||||
this.getTextContent(child.nextSibling));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Recursively parse all other child nodes.
|
||||
for (elem = elem.firstChild; elem; elem = elem.nextSibling) {
|
||||
this.initializeKeyBindings(elem);
|
||||
}
|
||||
};
|
||||
|
||||
VT100.prototype.initializeKeyboard = function() {
|
||||
// Configure mouse event handlers for button that displays/hides keyboard
|
||||
var box = this.keyboard.firstChild;
|
||||
this.hideSoftKeyboard();
|
||||
this.addListener(this.keyboardImage, 'click',
|
||||
function(vt100) { return function(e) {
|
||||
if (vt100.keyboard.style.display != '') {
|
||||
if (vt100.reconnectBtn.style.visibility != '') {
|
||||
vt100.showSoftKeyboard();
|
||||
}
|
||||
} else {
|
||||
vt100.hideSoftKeyboard();
|
||||
vt100.input.focus();
|
||||
}
|
||||
return false; }; }(this));
|
||||
|
||||
// Enable button that displays keyboard
|
||||
if (this.softKeyboard) {
|
||||
this.keyboardImage.style.visibility = 'visible';
|
||||
}
|
||||
|
||||
// Configure mouse event handlers for on-screen keyboard
|
||||
this.addListener(this.keyboard, 'click',
|
||||
function(vt100) { return function(e) {
|
||||
vt100.hideSoftKeyboard();
|
||||
vt100.input.focus();
|
||||
return false; }; }(this));
|
||||
this.addListener(this.keyboard, 'selectstart', this.cancelEvent);
|
||||
this.addListener(box, 'click', this.cancelEvent);
|
||||
this.addListener(box, 'mouseup',
|
||||
function(vt100) { return function(e) {
|
||||
if (vt100.lastSelectedKey) {
|
||||
vt100.lastSelectedKey.className = '';
|
||||
vt100.lastSelectedKey = undefined;
|
||||
}
|
||||
return false; }; }(this));
|
||||
this.addListener(box, 'mouseout',
|
||||
function(vt100) { return function(e) {
|
||||
return vt100.resetLastSelectedKey(e); }; }(this));
|
||||
this.addListener(box, 'mouseover',
|
||||
function(vt100) { return function(e) {
|
||||
return vt100.resetLastSelectedKey(e); }; }(this));
|
||||
|
||||
// Configure SHIFT key behavior
|
||||
var style = document.createElement('style');
|
||||
var id = document.createAttribute('id');
|
||||
id.nodeValue = 'shift_state';
|
||||
style.setAttributeNode(id);
|
||||
var type = document.createAttribute('type');
|
||||
type.nodeValue = 'text/css';
|
||||
style.setAttributeNode(type);
|
||||
document.getElementsByTagName('head')[0].appendChild(style);
|
||||
|
||||
// Set up key bindings
|
||||
this.initializeKeyBindings(box);
|
||||
};
|
||||
|
||||
VT100.prototype.initializeElements = function(container) {
|
||||
// If the necessary objects have not already been defined in the HTML
|
||||
// page, create them now.
|
||||
|
@ -483,6 +805,9 @@ VT100.prototype.initializeElements = function(container) {
|
|||
|
||||
if (!this.getChildById(this.container, 'reconnect') ||
|
||||
!this.getChildById(this.container, 'menu') ||
|
||||
!this.getChildById(this.container, 'keyboard') ||
|
||||
!this.getChildById(this.container, 'kbd_button') ||
|
||||
!this.getChildById(this.container, 'kbd_img') ||
|
||||
!this.getChildById(this.container, 'scrollable') ||
|
||||
!this.getChildById(this.container, 'console') ||
|
||||
!this.getChildById(this.container, 'alt_console') ||
|
||||
|
@ -525,7 +850,15 @@ VT100.prototype.initializeElements = function(container) {
|
|||
'<div id="cursize" style="visibility: hidden">' +
|
||||
'</div>' +
|
||||
'<div id="menu"></div>' +
|
||||
'<div id="keyboard" unselectable="on">' +
|
||||
'<pre class="box"><div><i id="27">Esc</i><i id="112">F1</i><i id="113">F2</i><i id="114">F3</i><i id="115">F4</i><i id="116">F5</i><i id="117">F6</i><i id="118">F7</i><i id="119">F8</i><i id="120">F9</i><i id="121">F10</i><i id="122">F11</i><i id="123">F12</i><br /><b><span class="unshifted">`</span><span class="shifted">~</span></b><b><span class="unshifted">1</span><span class="shifted">!</span></b><b><span class="unshifted">2</span><span class="shifted">@</span></b><b><span class="unshifted">3</span><span class="shifted">#</span></b><b><span class="unshifted">4</span><span class="shifted">$</span></b><b><span class="unshifted">5</span><span class="shifted">%</span></b><b><span class="unshifted">6</span><span class="shifted">^</span></b><b><span class="unshifted">7</span><span class="shifted">&</span></b><b><span class="unshifted">8</span><span class="shifted">*</span></b><b><span class="unshifted">9</span><span class="shifted">(</span></b><b><span class="unshifted">0</span><span class="shifted">)</span></b><b><span class="unshifted">-</span><span class="shifted">_</span></b><b><span class="unshifted">=</span><span class="shifted">+</span></b><i id="8"> ← </i><br /><i id="9">Tab</i><b>Q</b><b>W</b><b>E</b><b>R</b><b>T</b><b>Y</b><b>U</b><b>I</b><b>O</b><b>P</b><b><span class="unshifted">[</span><span class="shifted">{</span></b><b><span class="unshifted">]</span><span class="shifted">}</span></b><b><span class="unshifted">\</span><span class="shifted">|</span></b><br /><u>Tab </u><b>A</b><b>S</b><b>D</b><b>F</b><b>G</b><b>H</b><b>J</b><b>K</b><b>L</b><b><span class="unshifted">;</span><span class="shifted">:</span></b><b><span class="unshifted">'</span><span class="shifted">"</span></b><i id="13">Enter</i><br /><u> </u><i id="16">Shift</i><b>Z</b><b>X</b><b>C</b><b>V</b><b>B</b><b>N</b><b>M</b><b><span class="unshifted">,</span><span class="shifted"><</span></b><b><span class="unshifted">.</span><span class="shifted">></span></b><b><span class="unshifted">/</span><span class="shifted">?</span></b><i id="16">Shift</i><br /><u>XXX</u><i id="17">Ctrl</i><i id="18">Alt</i><i style="width: 25ex"> </i></div> <div><i id="45">Ins</i><i id="46">Del</i><i id="36">Home</i><i id="35">End</i><br /><u> </u><br /><u> </u><br /><u>Ins</u><s> </s><b id="38">↑</b><s> </s><u> </u><b id="33">⇑</b><br /><u>Ins</u><b id="37">←</b><b id="40">↓</b><b id="39">→</b><u> </u><b id="34">⇓</b></div></pre>' +
|
||||
'</div>' +
|
||||
'<div id="scrollable">' +
|
||||
'<table id="kbd_button">' +
|
||||
'<tr><td width="100%"> </td>' +
|
||||
'<td><img id="kbd_img" src="keyboard.png" /></td>' +
|
||||
'<td> </td></tr>' +
|
||||
'</table>' +
|
||||
'<pre id="lineheight"> </pre>' +
|
||||
'<pre id="console">' +
|
||||
'<pre></pre>' +
|
||||
|
@ -566,6 +899,8 @@ VT100.prototype.initializeElements = function(container) {
|
|||
this.reconnectBtn = this.getChildById(this.container,'reconnect');
|
||||
this.curSizeBox = this.getChildById(this.container, 'cursize');
|
||||
this.menu = this.getChildById(this.container, 'menu');
|
||||
this.keyboard = this.getChildById(this.container, 'keyboard');
|
||||
this.keyboardImage = this.getChildById(this.container, 'kbd_img');
|
||||
this.scrollable = this.getChildById(this.container,
|
||||
'scrollable');
|
||||
this.lineheight = this.getChildById(this.container,
|
||||
|
@ -646,6 +981,9 @@ VT100.prototype.initializeElements = function(container) {
|
|||
// Hide context menu
|
||||
this.hideContextMenu();
|
||||
|
||||
// Set up onscreen soft keyboard
|
||||
this.initializeKeyboard();
|
||||
|
||||
// Add listener to reconnect button
|
||||
this.addListener(this.reconnectBtn.firstChild, 'click',
|
||||
function(vt100) {
|
||||
|
@ -733,6 +1071,7 @@ VT100.prototype.reconnect = function() {
|
|||
|
||||
VT100.prototype.showReconnect = function(state) {
|
||||
if (state) {
|
||||
this.hideSoftKeyboard();
|
||||
this.reconnectBtn.style.visibility = '';
|
||||
} else {
|
||||
this.reconnectBtn.style.visibility = 'hidden';
|
||||
|
@ -766,6 +1105,9 @@ VT100.prototype.resized = function(w, h) {
|
|||
};
|
||||
|
||||
VT100.prototype.resizer = function() {
|
||||
// Hide onscreen soft keyboard
|
||||
this.hideSoftKeyboard();
|
||||
|
||||
// The cursor can get corrupted if the print-preview is displayed in Firefox.
|
||||
// Recreating it, will repair it.
|
||||
var newCursor = document.createElement('pre');
|
||||
|
@ -945,6 +1287,17 @@ VT100.prototype.cancelEvent = function(event) {
|
|||
return false;
|
||||
};
|
||||
|
||||
VT100.prototype.mousePosition = function(event) {
|
||||
var offsetX = this.container.offsetLeft;
|
||||
var offsetY = this.container.offsetTop;
|
||||
for (var e = this.container; e = e.offsetParent; ) {
|
||||
offsetX += e.offsetLeft;
|
||||
offsetY += e.offsetTop;
|
||||
}
|
||||
return [ event.clientX - offsetX,
|
||||
event.clientY - offsetY ];
|
||||
};
|
||||
|
||||
VT100.prototype.mouseEvent = function(event, type) {
|
||||
// If any text is currently selected, do not move the focus as that would
|
||||
// invalidate the selection.
|
||||
|
@ -954,15 +1307,10 @@ VT100.prototype.mouseEvent = function(event, type) {
|
|||
}
|
||||
|
||||
// Compute mouse position in characters.
|
||||
var offsetX = this.container.offsetLeft;
|
||||
var offsetY = this.container.offsetTop;
|
||||
for (var e = this.container; e = e.offsetParent; ) {
|
||||
offsetX += e.offsetLeft;
|
||||
offsetY += e.offsetTop;
|
||||
}
|
||||
var x = (event.clientX - offsetX) / this.cursorWidth;
|
||||
var y = ((event.clientY - offsetY) + this.scrollable.offsetTop) /
|
||||
this.cursorHeight - this.numScrollbackLines;
|
||||
var position = this.mousePosition(event);
|
||||
var x = Math.floor(position[0] / this.cursorWidth);
|
||||
var y = Math.floor((position[1] + this.scrollable.scrollTop) /
|
||||
this.cursorHeight) - this.numScrollbackLines;
|
||||
var inside = true;
|
||||
if (x >= this.terminalWidth) {
|
||||
x = this.terminalWidth - 1;
|
||||
|
@ -1022,7 +1370,7 @@ VT100.prototype.mouseEvent = function(event, type) {
|
|||
// Bring up context menu.
|
||||
if (button == 2 && !event.shiftKey) {
|
||||
if (type == 0 /* MOUSE_DOWN */) {
|
||||
this.showContextMenu(event.clientX - offsetX, event.clientY - offsetY);
|
||||
this.showContextMenu(position[0], position[1]);
|
||||
}
|
||||
return this.cancelEvent(event);
|
||||
}
|
||||
|
@ -1058,6 +1406,29 @@ VT100.prototype.getTextContent = function(elem) {
|
|||
(typeof elem.textContent == 'undefined' ? elem.innerText : '');
|
||||
};
|
||||
|
||||
VT100.prototype.setTextContentRaw = function(elem, s) {
|
||||
// Updating the content of an element is an expensive operation. It actually
|
||||
// pays off to first check whether the element is still unchanged.
|
||||
if (typeof elem.textContent == 'undefined') {
|
||||
if (elem.innerText != s) {
|
||||
try {
|
||||
elem.innerText = s;
|
||||
} catch (e) {
|
||||
// Very old versions of IE do not allow setting innerText. Instead,
|
||||
// remove all children, by setting innerHTML and then set the text
|
||||
// using DOM methods.
|
||||
elem.innerHTML = '';
|
||||
elem.appendChild(document.createTextNode(
|
||||
this.replaceChar(s, ' ', '\u00A0')));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (elem.textContent != s) {
|
||||
elem.textContent = s;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
VT100.prototype.setTextContent = function(elem, s) {
|
||||
// Check if we find any URLs in the text. If so, automatically convert them
|
||||
// to links.
|
||||
|
@ -1103,26 +1474,7 @@ VT100.prototype.setTextContent = function(elem, s) {
|
|||
return;
|
||||
}
|
||||
|
||||
// Updating the content of an element is an expensive operation. It actually
|
||||
// pays off to first check whether the element is still unchanged.
|
||||
if (typeof elem.textContent == 'undefined') {
|
||||
if (elem.innerText != s) {
|
||||
try {
|
||||
elem.innerText = s;
|
||||
} catch (e) {
|
||||
// Very old versions of IE do not allow setting innerText. Instead,
|
||||
// remove all children, by setting innerHTML and then set the text
|
||||
// using DOM methods.
|
||||
elem.innerHTML = '';
|
||||
elem.appendChild(document.createTextNode(
|
||||
this.replaceChar(s, ' ', '\u00A0')));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (elem.textContent != s) {
|
||||
elem.textContent = s;
|
||||
}
|
||||
}
|
||||
this.setTextContentRaw(elem, s);
|
||||
};
|
||||
|
||||
VT100.prototype.insertBlankLine = function(y, color, style) {
|
||||
|
@ -1578,27 +1930,21 @@ VT100.prototype.enableAlternateScreen = function(state) {
|
|||
this.console[this.currentScreen].style.display = '';
|
||||
|
||||
// Select appropriate character pitch.
|
||||
var styles = [ 'transform',
|
||||
'WebkitTransform',
|
||||
'MozTransform',
|
||||
'filter' ];
|
||||
for (var i = 0; i < styles.length; ++i) {
|
||||
if (typeof this.console[0].style[styles[i]] != 'undefined') {
|
||||
if (state) {
|
||||
// Upon enabling the alternate screen, we switch to 80 column mode. But
|
||||
// upon returning to the regular screen, we restore the mode that was
|
||||
// in effect previously.
|
||||
this.console[1].style[styles[i]] = '';
|
||||
}
|
||||
var style =
|
||||
this.console[this.currentScreen].style[styles[i]];
|
||||
this.cursor.style[styles[i]] = style;
|
||||
this.space.style[styles[i]] = style;
|
||||
this.scale = style == '' ? 1.0:1.65;
|
||||
if (styles[i] == 'filter') {
|
||||
this.console[this.currentScreen].style.width = style == '' ? '165%':'';
|
||||
}
|
||||
break;
|
||||
var transform = this.getTransformName();
|
||||
if (transform) {
|
||||
if (state) {
|
||||
// Upon enabling the alternate screen, we switch to 80 column mode. But
|
||||
// upon returning to the regular screen, we restore the mode that was
|
||||
// in effect previously.
|
||||
this.console[1].style[transform] = '';
|
||||
}
|
||||
var style =
|
||||
this.console[this.currentScreen].style[transform];
|
||||
this.cursor.style[transform] = style;
|
||||
this.space.style[transform] = style;
|
||||
this.scale = style == '' ? 1.0:1.65;
|
||||
if (transform == 'filter') {
|
||||
this.console[this.currentScreen].style.width = style == '' ? '165%':'';
|
||||
}
|
||||
}
|
||||
this.resizer();
|
||||
|
@ -1969,12 +2315,76 @@ VT100.prototype.toggleBell = function() {
|
|||
this.visualBell = !this.visualBell;
|
||||
};
|
||||
|
||||
VT100.prototype.toggleSoftKeyboard = function() {
|
||||
this.softKeyboard = !this.softKeyboard;
|
||||
this.keyboardImage.style.visibility = this.softKeyboard ? 'visible' : '';
|
||||
};
|
||||
|
||||
VT100.prototype.deselectKeys = function(elem) {
|
||||
if (elem && elem.className == 'selected') {
|
||||
elem.className = '';
|
||||
}
|
||||
for (elem = elem.firstChild; elem; elem = elem.nextSibling) {
|
||||
this.deselectKeys(elem);
|
||||
}
|
||||
};
|
||||
|
||||
VT100.prototype.showSoftKeyboard = function() {
|
||||
// Make sure no key is currently selected
|
||||
this.lastSelectedKey = undefined;
|
||||
this.deselectKeys(this.keyboard);
|
||||
this.isShift = false;
|
||||
this.showShiftState(false);
|
||||
this.isCtrl = false;
|
||||
this.showCtrlState(false);
|
||||
this.isAlt = false;
|
||||
this.showAltState(false);
|
||||
|
||||
this.keyboard.style.left = '0px';
|
||||
this.keyboard.style.top = '0px';
|
||||
this.keyboard.style.width = this.container.offsetWidth + 'px';
|
||||
this.keyboard.style.height = this.container.offsetHeight + 'px';
|
||||
this.keyboard.style.visibility = 'hidden';
|
||||
this.keyboard.style.display = '';
|
||||
|
||||
var kbd = this.keyboard.firstChild;
|
||||
var scale = 1.0;
|
||||
var transform = this.getTransformName();
|
||||
if (transform) {
|
||||
kbd.style[transform] = '';
|
||||
if (kbd.offsetWidth > 0.9 * this.container.offsetWidth) {
|
||||
scale = (kbd.offsetWidth/
|
||||
this.container.offsetWidth)/0.9;
|
||||
}
|
||||
if (kbd.offsetHeight > 0.9 * this.container.offsetHeight) {
|
||||
scale = Math.max((kbd.offsetHeight/
|
||||
this.container.offsetHeight)/0.9);
|
||||
}
|
||||
var style = this.getTransformStyle(transform,
|
||||
scale > 1.0 ? scale : undefined);
|
||||
kbd.style[transform] = style;
|
||||
}
|
||||
if (transform == 'filter') {
|
||||
scale = 1.0;
|
||||
}
|
||||
kbd.style.left = ((this.container.offsetWidth -
|
||||
kbd.offsetWidth/scale)/2) + 'px';
|
||||
kbd.style.top = ((this.container.offsetHeight -
|
||||
kbd.offsetHeight/scale)/2) + 'px';
|
||||
|
||||
this.keyboard.style.visibility = 'visible';
|
||||
};
|
||||
|
||||
VT100.prototype.hideSoftKeyboard = function() {
|
||||
this.keyboard.style.display = 'none';
|
||||
};
|
||||
|
||||
VT100.prototype.toggleCursorBlinking = function() {
|
||||
this.blinkingCursor = !this.blinkingCursor;
|
||||
};
|
||||
|
||||
VT100.prototype.about = function() {
|
||||
alert("VT100 Terminal Emulator " + "2.10 (revision 220)" +
|
||||
alert("VT100 Terminal Emulator " + "2.10 (revision 221)" +
|
||||
"\nCopyright 2008-2010 by Markus Gutschke\n" +
|
||||
"For more information check http://shellinabox.com");
|
||||
};
|
||||
|
@ -2007,6 +2417,9 @@ VT100.prototype.showContextMenu = function(x, y) {
|
|||
'<li>' +
|
||||
(this.visualBell ? '<img src="enabled.gif" />' : '') +
|
||||
'Visual Bell</li>'+
|
||||
'<li>' +
|
||||
(this.softKeyboard ? '<img src="enabled.gif" />' : '') +
|
||||
'Onscreen Keyboard</li>' +
|
||||
'<li id="endconfig">' +
|
||||
(this.blinkingCursor ? '<img src="enabled.gif" />' : '') +
|
||||
'Blinking Cursor</li>'+
|
||||
|
@ -2038,6 +2451,7 @@ VT100.prototype.showContextMenu = function(x, y) {
|
|||
// Actions for default items
|
||||
var actions = [ this.copyLast, p, this.reset,
|
||||
this.toggleUTF, this.toggleBell,
|
||||
this.toggleSoftKeyboard,
|
||||
this.toggleCursorBlinking ];
|
||||
|
||||
// Actions for user CSS styles (if any)
|
||||
|
@ -2093,26 +2507,30 @@ VT100.prototype.showContextMenu = function(x, y) {
|
|||
}
|
||||
|
||||
// Position menu next to the mouse pointer
|
||||
if (x + popup.clientWidth > this.container.offsetWidth) {
|
||||
x = this.container.offsetWidth - popup.clientWidth;
|
||||
this.menu.style.left = '0px';
|
||||
this.menu.style.top = '0px';
|
||||
this.menu.style.width = this.container.offsetWidth + 'px';
|
||||
this.menu.style.height = this.container.offsetHeight + 'px';
|
||||
popup.style.left = '0px';
|
||||
popup.style.top = '0px';
|
||||
|
||||
var margin = 2;
|
||||
if (x + popup.clientWidth >= this.container.offsetWidth - margin) {
|
||||
x = this.container.offsetWidth-popup.clientWidth - margin - 1;
|
||||
}
|
||||
if (x < 0) {
|
||||
x = 0;
|
||||
if (x < margin) {
|
||||
x = margin;
|
||||
}
|
||||
if (y + popup.clientHeight > this.container.offsetHeight) {
|
||||
y = this.container.offsetHeight-popup.clientHeight;
|
||||
if (y + popup.clientHeight >= this.container.offsetHeight - margin) {
|
||||
y = this.container.offsetHeight-popup.clientHeight - margin - 1;
|
||||
}
|
||||
if (y < 0) {
|
||||
y = 0;
|
||||
if (y < margin) {
|
||||
y = margin;
|
||||
}
|
||||
popup.style.left = x + 'px';
|
||||
popup.style.top = y + 'px';
|
||||
|
||||
// Block all other interactions with the terminal emulator
|
||||
this.menu.style.left = '0px';
|
||||
this.menu.style.top = '0px';
|
||||
this.menu.style.width = this.container.offsetWidth + 'px';
|
||||
this.menu.style.height = this.container.offsetHeight + 'px';
|
||||
this.addListener(this.menu, 'click', function(vt100) {
|
||||
return function() {
|
||||
vt100.hideContextMenu();
|
||||
|
@ -2895,39 +3313,42 @@ VT100.prototype.restoreCursor = function() {
|
|||
this.savedY[this.currentScreen]);
|
||||
};
|
||||
|
||||
VT100.prototype.set80_132Mode = function(state) {
|
||||
var transform = undefined;
|
||||
var styles = [ 'transform',
|
||||
'WebkitTransform',
|
||||
'MozTransform',
|
||||
'filter'
|
||||
];
|
||||
VT100.prototype.getTransformName = function() {
|
||||
var styles = [ 'transform', 'WebkitTransform', 'MozTransform', 'filter' ];
|
||||
for (var i = 0; i < styles.length; ++i) {
|
||||
if (typeof this.console[0].style[styles[i]] != 'undefined') {
|
||||
transform = styles[i];
|
||||
break;
|
||||
return styles[i];
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
VT100.prototype.getTransformStyle = function(transform, scale) {
|
||||
return scale && scale != 1.0
|
||||
? transform == 'filter'
|
||||
? 'progid:DXImageTransform.Microsoft.Matrix(' +
|
||||
'M11=' + (1.0/scale) + ',M12=0,M21=0,M22=1,' +
|
||||
"sizingMethod='auto expand')"
|
||||
: 'translateX(-50%) ' +
|
||||
'scaleX(' + (1.0/scale) + ') ' +
|
||||
'translateX(50%)'
|
||||
: '';
|
||||
};
|
||||
|
||||
VT100.prototype.set80_132Mode = function(state) {
|
||||
var transform = this.getTransformName();
|
||||
if (transform) {
|
||||
if ((this.console[this.currentScreen].style[transform] != '') == state) {
|
||||
return;
|
||||
}
|
||||
var style =
|
||||
state ? transform == 'filter'
|
||||
? 'progid:DXImageTransform.Microsoft.Matrix(' +
|
||||
'M11=0.606060606060606060606,M12=0,M21=0,M22=1,' +
|
||||
"sizingMethod='auto expand')"
|
||||
: 'translateX(-50%) ' +
|
||||
'scaleX(0.606060606060606060606) ' +
|
||||
'translateX(50%)'
|
||||
: '';
|
||||
var style = state ?
|
||||
this.getTransformStyle(transform, 1.65):'';
|
||||
this.console[this.currentScreen].style[transform] = style;
|
||||
this.cursor.style[transform] = style;
|
||||
this.space.style[transform] = style;
|
||||
this.scale = state ? 1.65 : 1.0;
|
||||
this.cursor.style[transform] = style;
|
||||
this.space.style[transform] = style;
|
||||
this.scale = state ? 1.65 : 1.0;
|
||||
if (transform == 'filter') {
|
||||
this.console[this.currentScreen].style.width = state ? '165%' : '';
|
||||
this.console[this.currentScreen].style.width = state ? '165%' : '';
|
||||
}
|
||||
this.resizer();
|
||||
}
|
||||
|
|
|
@ -238,22 +238,16 @@ VT100.prototype.reset = function(clearHistory) {
|
|||
this.enableAlternateScreen(false);
|
||||
|
||||
var wasCompressed = false;
|
||||
var styles = [ 'transform',
|
||||
'WebkitTransform',
|
||||
'MozTransform',
|
||||
'filter' ];
|
||||
for (var i = 0; i < styles.length; ++i) {
|
||||
if (typeof this.console[0].style[styles[i]] != 'undefined') {
|
||||
for (var j = 0; j < 1; ++j) {
|
||||
wasCompressed |= this.console[j].style[styles[i]] != '';
|
||||
this.console[j].style[styles[i]] = '';
|
||||
}
|
||||
this.cursor.style[styles[i]] = '';
|
||||
this.space.style[styles[i]] = '';
|
||||
if (styles[i] == 'filter') {
|
||||
this.console[this.currentScreen].style.width = '';
|
||||
}
|
||||
break;
|
||||
var transform = this.getTransformName();
|
||||
if (transform) {
|
||||
for (var i = 0; i < 2; ++i) {
|
||||
wasCompressed |= this.console[i].style[transform] != '';
|
||||
this.console[i].style[transform] = '';
|
||||
}
|
||||
this.cursor.style[transform] = '';
|
||||
this.space.style[transform] = '';
|
||||
if (transform == 'filter') {
|
||||
this.console[this.currentScreen].style.width = '';
|
||||
}
|
||||
}
|
||||
this.scale = 1.0;
|
||||
|
@ -270,10 +264,13 @@ VT100.prototype.reset = function(clearHistory) {
|
|||
};
|
||||
|
||||
VT100.prototype.addListener = function(elem, event, listener) {
|
||||
if (elem.addEventListener) {
|
||||
elem.addEventListener(event, listener, false);
|
||||
} else {
|
||||
elem.attachEvent('on' + event, listener);
|
||||
try {
|
||||
if (elem.addEventListener) {
|
||||
elem.addEventListener(event, listener, false);
|
||||
} else {
|
||||
elem.attachEvent('on' + event, listener);
|
||||
}
|
||||
} catch (e) {
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -281,11 +278,12 @@ VT100.prototype.getUserSettings = function() {
|
|||
// Compute hash signature to identify the entries in the userCSS menu.
|
||||
// If the menu is unchanged from last time, default values can be
|
||||
// looked up in a cookie associated with this page.
|
||||
this.signature = 2;
|
||||
this.signature = 3;
|
||||
this.utfPreferred = true;
|
||||
this.visualBell = typeof suppressAllAudio != 'undefined' &&
|
||||
suppressAllAudio;
|
||||
this.autoprint = true;
|
||||
this.softKeyboard = false;
|
||||
this.blinkingCursor = true;
|
||||
if (this.visualBell) {
|
||||
this.signature = Math.floor(16807*this.signature + 1) %
|
||||
|
@ -311,15 +309,16 @@ VT100.prototype.getUserSettings = function() {
|
|||
if (settings >= 0) {
|
||||
settings = document.cookie.substr(settings + key.length).
|
||||
replace(/([0-1]*).*/, "$1");
|
||||
if (settings.length == 3 + (typeof userCSSList == 'undefined' ?
|
||||
if (settings.length == 5 + (typeof userCSSList == 'undefined' ?
|
||||
0 : userCSSList.length)) {
|
||||
this.utfPreferred = settings.charAt(0) != '0';
|
||||
this.visualBell = settings.charAt(1) != '0';
|
||||
this.autoprint = settings.charAt(2) != '0';
|
||||
this.blinkingCursor = settings.charAt(3) != '0';
|
||||
this.softKeyboard = settings.charAt(3) != '0';
|
||||
this.blinkingCursor = settings.charAt(4) != '0';
|
||||
if (typeof userCSSList != 'undefined') {
|
||||
for (var i = 0; i < userCSSList.length; ++i) {
|
||||
userCSSList[i][2] = settings.charAt(i + 3) != '0';
|
||||
userCSSList[i][2] = settings.charAt(i + 5) != '0';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -332,6 +331,7 @@ VT100.prototype.storeUserSettings = function() {
|
|||
(this.utfEnabled ? '1' : '0') +
|
||||
(this.visualBell ? '1' : '0') +
|
||||
(this.autoprint ? '1' : '0') +
|
||||
(this.softKeyboard ? '1' : '0') +
|
||||
(this.blinkingCursor ? '1' : '0');
|
||||
if (typeof userCSSList != 'undefined') {
|
||||
for (var i = 0; i < userCSSList.length; ++i) {
|
||||
|
@ -413,7 +413,7 @@ VT100.prototype.initializeUserCSSStyles = function() {
|
|||
label.textContent= label.textContent;
|
||||
}
|
||||
|
||||
// User style sheets are number sequentially
|
||||
// User style sheets are numbered sequentially
|
||||
var sheet = document.getElementById(
|
||||
'usercss-' + i);
|
||||
if (i == current) {
|
||||
|
@ -470,6 +470,328 @@ VT100.prototype.initializeUserCSSStyles = function() {
|
|||
}
|
||||
};
|
||||
|
||||
VT100.prototype.resetLastSelectedKey = function(e) {
|
||||
var key = this.lastSelectedKey;
|
||||
if (!key) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var position = this.mousePosition(e);
|
||||
|
||||
// We don't get all the necessary events to reliably reselect a key
|
||||
// if we moved away from it and then back onto it. We approximate the
|
||||
// behavior by remembering the key until either we release the mouse
|
||||
// button (we might never get this event if the mouse has since left
|
||||
// the window), or until we move away too far.
|
||||
var box = this.keyboard.firstChild;
|
||||
if (position[0] < box.offsetLeft + key.offsetWidth ||
|
||||
position[1] < box.offsetTop + key.offsetHeight ||
|
||||
position[0] >= box.offsetLeft + box.offsetWidth - key.offsetWidth ||
|
||||
position[1] >= box.offsetTop + box.offsetHeight - key.offsetHeight ||
|
||||
position[0] < box.offsetLeft + key.offsetLeft - key.offsetWidth ||
|
||||
position[1] < box.offsetTop + key.offsetTop - key.offsetHeight ||
|
||||
position[0] >= box.offsetLeft + key.offsetLeft + 2*key.offsetWidth ||
|
||||
position[1] >= box.offsetTop + key.offsetTop + 2*key.offsetHeight) {
|
||||
if (this.lastSelectedKey.className) log.console('reset: deselecting');
|
||||
this.lastSelectedKey.className = '';
|
||||
this.lastSelectedKey = undefined;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
VT100.prototype.showShiftState = function(state) {
|
||||
var style = document.getElementById('shift_state');
|
||||
if (state) {
|
||||
this.setTextContentRaw(style,
|
||||
'#vt100 #keyboard .shifted {' +
|
||||
'display: inline }' +
|
||||
'#vt100 #keyboard .unshifted {' +
|
||||
'display: none }');
|
||||
} else {
|
||||
this.setTextContentRaw(style, '');
|
||||
}
|
||||
var elems = this.keyboard.getElementsByTagName('I');
|
||||
for (var i = 0; i < elems.length; ++i) {
|
||||
if (elems[i].id == '16') {
|
||||
elems[i].className = state ? 'selected' : '';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
VT100.prototype.showCtrlState = function(state) {
|
||||
var ctrl = this.getChildById(this.keyboard, '17' /* Ctrl */);
|
||||
if (ctrl) {
|
||||
ctrl.className = state ? 'selected' : '';
|
||||
}
|
||||
};
|
||||
|
||||
VT100.prototype.showAltState = function(state) {
|
||||
var alt = this.getChildById(this.keyboard, '18' /* Alt */);
|
||||
if (alt) {
|
||||
alt.className = state ? 'selected' : '';
|
||||
}
|
||||
};
|
||||
|
||||
VT100.prototype.clickedKeyboard = function(e, elem, ch, key, shift, ctrl, alt){
|
||||
var fake = [ ];
|
||||
fake.charCode = ch;
|
||||
fake.keyCode = key;
|
||||
fake.ctrlKey = ctrl;
|
||||
fake.shiftKey = shift;
|
||||
fake.altKey = alt;
|
||||
fake.metaKey = alt;
|
||||
return this.handleKey(fake);
|
||||
};
|
||||
|
||||
VT100.prototype.addKeyBinding = function(elem, ch, key, CH, KEY) {
|
||||
if (elem == undefined) {
|
||||
return;
|
||||
}
|
||||
if (ch == '\u00A0') {
|
||||
// should be treated as a regular space character.
|
||||
ch = ' ';
|
||||
}
|
||||
if (ch != undefined && CH == undefined) {
|
||||
// For letter keys, we automatically compute the uppercase character code
|
||||
// from the lowercase one.
|
||||
CH = ch.toUpperCase();
|
||||
}
|
||||
if (KEY == undefined && key != undefined) {
|
||||
// Most keys have identically key codes for both lowercase and uppercase
|
||||
// keypresses. Normally, only function keys would have distinct key codes,
|
||||
// whereas regular keys have character codes.
|
||||
KEY = key;
|
||||
} else if (KEY == undefined && CH != undefined) {
|
||||
// For regular keys, copy the character code to the key code.
|
||||
KEY = CH.charCodeAt(0);
|
||||
}
|
||||
if (key == undefined && ch != undefined) {
|
||||
// For regular keys, copy the character code to the key code.
|
||||
key = ch.charCodeAt(0);
|
||||
}
|
||||
// Convert characters to numeric character codes. If the character code
|
||||
// is undefined (i.e. this is a function key), set it to zero.
|
||||
ch = ch ? ch.charCodeAt(0) : 0;
|
||||
CH = CH ? CH.charCodeAt(0) : 0;
|
||||
|
||||
// Mouse down events high light the key. We also set lastSelectedKey. This
|
||||
// is needed to that mouseout/mouseover can keep track of the key that
|
||||
// is currently being clicked.
|
||||
this.addListener(elem, 'mousedown',
|
||||
function(vt100, elem, key) { return function(e) {
|
||||
if ((e.which || e.button) == 1) {
|
||||
if (vt100.lastSelectedKey) {
|
||||
vt100.lastSelectedKey.className= '';
|
||||
}
|
||||
// Highlight the key while the mouse button is held down.
|
||||
if (key == 16 /* Shift */) {
|
||||
if (!elem.className != vt100.isShift) {
|
||||
vt100.showShiftState(!vt100.isShift);
|
||||
}
|
||||
} else if (key == 17 /* Ctrl */) {
|
||||
if (!elem.className != vt100.isCtrl) {
|
||||
vt100.showCtrlState(!vt100.isCtrl);
|
||||
}
|
||||
} else if (key == 18 /* Alt */) {
|
||||
if (!elem.className != vt100.isAlt) {
|
||||
vt100.showAltState(!vt100.isAlt);
|
||||
}
|
||||
} else {
|
||||
elem.className = 'selected';
|
||||
}
|
||||
vt100.lastSelectedKey = elem;
|
||||
}
|
||||
return false; }; }(this, elem, key));
|
||||
var clicked =
|
||||
// Modifier keys update the state of the keyboard, but do not generate
|
||||
// any key clicks that get forwarded to the application.
|
||||
key >= 16 /* Shift */ && key <= 18 /* Alt */ ?
|
||||
function(vt100, elem) { return function(e) {
|
||||
if (elem == vt100.lastSelectedKey) {
|
||||
if (key == 16 /* Shift */) {
|
||||
// The user clicked the Shift key
|
||||
vt100.isShift = !vt100.isShift;
|
||||
vt100.showShiftState(vt100.isShift);
|
||||
} else if (key == 17 /* Ctrl */) {
|
||||
vt100.isCtrl = !vt100.isCtrl;
|
||||
vt100.showCtrlState(vt100.isCtrl);
|
||||
} else if (key == 18 /* Alt */) {
|
||||
vt100.isAlt = !vt100.isAlt;
|
||||
vt100.showAltState(vt100.isAlt);
|
||||
}
|
||||
vt100.lastSelectedKey = undefined;
|
||||
}
|
||||
if (vt100.lastSelectedKey) {
|
||||
vt100.lastSelectedKey.className = '';
|
||||
vt100.lastSelectedKey = undefined;
|
||||
}
|
||||
return false; }; }(this, elem) :
|
||||
// Regular keys generate key clicks, when the mouse button is released or
|
||||
// when a mouse click event is received.
|
||||
function(vt100, elem, ch, key, CH, KEY) { return function(e) {
|
||||
if (vt100.lastSelectedKey) {
|
||||
if (elem == vt100.lastSelectedKey) {
|
||||
// The user clicked a key.
|
||||
if (vt100.isShift) {
|
||||
vt100.clickedKeyboard(e, elem, CH, KEY,
|
||||
true, vt100.isCtrl, vt100.isAlt);
|
||||
} else {
|
||||
vt100.clickedKeyboard(e, elem, ch, key,
|
||||
false, vt100.isCtrl, vt100.isAlt);
|
||||
}
|
||||
vt100.isShift = false;
|
||||
vt100.showShiftState(false);
|
||||
vt100.isCtrl = false;
|
||||
vt100.showCtrlState(false);
|
||||
vt100.isAlt = false;
|
||||
vt100.showAltState(false);
|
||||
}
|
||||
vt100.lastSelectedKey.className = '';
|
||||
vt100.lastSelectedKey = undefined;
|
||||
}
|
||||
elem.className = '';
|
||||
return false; }; }(this, elem, ch, key, CH, KEY);
|
||||
this.addListener(elem, 'mouseup', clicked);
|
||||
this.addListener(elem, 'click', clicked);
|
||||
|
||||
// When moving the mouse away from a key, check if any keys need to be
|
||||
// deselected.
|
||||
this.addListener(elem, 'mouseout',
|
||||
function(vt100, elem, key) { return function(e) {
|
||||
if (key == 16 /* Shift */) {
|
||||
if (!elem.className == vt100.isShift) {
|
||||
vt100.showShiftState(vt100.isShift);
|
||||
}
|
||||
} else if (key == 17 /* Ctrl */) {
|
||||
if (!elem.className == vt100.isCtrl) {
|
||||
vt100.showCtrlState(vt100.isCtrl);
|
||||
}
|
||||
} else if (key == 18 /* Alt */) {
|
||||
if (!elem.className == vt100.isAlt) {
|
||||
vt100.showAltState(vt100.isAlt);
|
||||
}
|
||||
} else if (elem.className) {
|
||||
elem.className = '';
|
||||
vt100.lastSelectedKey = elem;
|
||||
} else if (vt100.lastSelectedKey) {
|
||||
vt100.resetLastSelectedKey(e);
|
||||
}
|
||||
return false; }; }(this, elem, key));
|
||||
|
||||
// When moving the mouse over a key, select it if the user is still holding
|
||||
// the mouse button down (i.e. elem == lastSelectedKey)
|
||||
this.addListener(elem, 'mouseover',
|
||||
function(vt100, elem, key) { return function(e) {
|
||||
if (elem == vt100.lastSelectedKey) {
|
||||
if (key == 16 /* Shift */) {
|
||||
if (!elem.className != vt100.isShift) {
|
||||
vt100.showShiftState(!vt100.isShift);
|
||||
}
|
||||
} else if (key == 17 /* Ctrl */) {
|
||||
if (!elem.className != vt100.isCtrl) {
|
||||
vt100.showCtrlState(!vt100.isCtrl);
|
||||
}
|
||||
} else if (key == 18 /* Alt */) {
|
||||
if (!elem.className != vt100.isAlt) {
|
||||
vt100.showAltState(!vt100.isAlt);
|
||||
}
|
||||
} else if (!elem.className) {
|
||||
elem.className = 'selected';
|
||||
}
|
||||
} else {
|
||||
vt100.resetLastSelectedKey(e);
|
||||
}
|
||||
return false; }; }(this, elem, key));
|
||||
};
|
||||
|
||||
VT100.prototype.initializeKeyBindings = function(elem) {
|
||||
if (elem) {
|
||||
if (elem.nodeName == "I" || elem.nodeName == "B") {
|
||||
if (elem.id) {
|
||||
// Function keys. The Javascript keycode is part of the "id"
|
||||
var i = parseInt(elem.id);
|
||||
if (i) {
|
||||
// If the id does not parse as a number, it is not a keycode.
|
||||
this.addKeyBinding(elem, undefined, i);
|
||||
}
|
||||
} else {
|
||||
var child = elem.firstChild;
|
||||
if (child.nodeName == "#text") {
|
||||
// If the key only has a text node as a child, then it is a letter.
|
||||
// Automatically compute the lower and upper case version of the key.
|
||||
this.addKeyBinding(elem, this.getTextContent(child).toLowerCase());
|
||||
} else {
|
||||
// If the key has two children, they are the lower and upper case
|
||||
// character code, respectively.
|
||||
this.addKeyBinding(elem, this.getTextContent(child), undefined,
|
||||
this.getTextContent(child.nextSibling));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Recursively parse all other child nodes.
|
||||
for (elem = elem.firstChild; elem; elem = elem.nextSibling) {
|
||||
this.initializeKeyBindings(elem);
|
||||
}
|
||||
};
|
||||
|
||||
VT100.prototype.initializeKeyboard = function() {
|
||||
// Configure mouse event handlers for button that displays/hides keyboard
|
||||
var box = this.keyboard.firstChild;
|
||||
this.hideSoftKeyboard();
|
||||
this.addListener(this.keyboardImage, 'click',
|
||||
function(vt100) { return function(e) {
|
||||
if (vt100.keyboard.style.display != '') {
|
||||
if (vt100.reconnectBtn.style.visibility != '') {
|
||||
vt100.showSoftKeyboard();
|
||||
}
|
||||
} else {
|
||||
vt100.hideSoftKeyboard();
|
||||
vt100.input.focus();
|
||||
}
|
||||
return false; }; }(this));
|
||||
|
||||
// Enable button that displays keyboard
|
||||
if (this.softKeyboard) {
|
||||
this.keyboardImage.style.visibility = 'visible';
|
||||
}
|
||||
|
||||
// Configure mouse event handlers for on-screen keyboard
|
||||
this.addListener(this.keyboard, 'click',
|
||||
function(vt100) { return function(e) {
|
||||
vt100.hideSoftKeyboard();
|
||||
vt100.input.focus();
|
||||
return false; }; }(this));
|
||||
this.addListener(this.keyboard, 'selectstart', this.cancelEvent);
|
||||
this.addListener(box, 'click', this.cancelEvent);
|
||||
this.addListener(box, 'mouseup',
|
||||
function(vt100) { return function(e) {
|
||||
if (vt100.lastSelectedKey) {
|
||||
vt100.lastSelectedKey.className = '';
|
||||
vt100.lastSelectedKey = undefined;
|
||||
}
|
||||
return false; }; }(this));
|
||||
this.addListener(box, 'mouseout',
|
||||
function(vt100) { return function(e) {
|
||||
return vt100.resetLastSelectedKey(e); }; }(this));
|
||||
this.addListener(box, 'mouseover',
|
||||
function(vt100) { return function(e) {
|
||||
return vt100.resetLastSelectedKey(e); }; }(this));
|
||||
|
||||
// Configure SHIFT key behavior
|
||||
var style = document.createElement('style');
|
||||
var id = document.createAttribute('id');
|
||||
id.nodeValue = 'shift_state';
|
||||
style.setAttributeNode(id);
|
||||
var type = document.createAttribute('type');
|
||||
type.nodeValue = 'text/css';
|
||||
style.setAttributeNode(type);
|
||||
document.getElementsByTagName('head')[0].appendChild(style);
|
||||
|
||||
// Set up key bindings
|
||||
this.initializeKeyBindings(box);
|
||||
};
|
||||
|
||||
VT100.prototype.initializeElements = function(container) {
|
||||
// If the necessary objects have not already been defined in the HTML
|
||||
// page, create them now.
|
||||
|
@ -483,6 +805,9 @@ VT100.prototype.initializeElements = function(container) {
|
|||
|
||||
if (!this.getChildById(this.container, 'reconnect') ||
|
||||
!this.getChildById(this.container, 'menu') ||
|
||||
!this.getChildById(this.container, 'keyboard') ||
|
||||
!this.getChildById(this.container, 'kbd_button') ||
|
||||
!this.getChildById(this.container, 'kbd_img') ||
|
||||
!this.getChildById(this.container, 'scrollable') ||
|
||||
!this.getChildById(this.container, 'console') ||
|
||||
!this.getChildById(this.container, 'alt_console') ||
|
||||
|
@ -525,7 +850,15 @@ VT100.prototype.initializeElements = function(container) {
|
|||
'<div id="cursize" style="visibility: hidden">' +
|
||||
'</div>' +
|
||||
'<div id="menu"></div>' +
|
||||
'<div id="keyboard" unselectable="on">' +
|
||||
KEYBOARD +
|
||||
'</div>' +
|
||||
'<div id="scrollable">' +
|
||||
'<table id="kbd_button">' +
|
||||
'<tr><td width="100%"> </td>' +
|
||||
'<td><img id="kbd_img" src="keyboard.png" /></td>' +
|
||||
'<td> </td></tr>' +
|
||||
'</table>' +
|
||||
'<pre id="lineheight"> </pre>' +
|
||||
'<pre id="console">' +
|
||||
'<pre></pre>' +
|
||||
|
@ -566,6 +899,8 @@ VT100.prototype.initializeElements = function(container) {
|
|||
this.reconnectBtn = this.getChildById(this.container,'reconnect');
|
||||
this.curSizeBox = this.getChildById(this.container, 'cursize');
|
||||
this.menu = this.getChildById(this.container, 'menu');
|
||||
this.keyboard = this.getChildById(this.container, 'keyboard');
|
||||
this.keyboardImage = this.getChildById(this.container, 'kbd_img');
|
||||
this.scrollable = this.getChildById(this.container,
|
||||
'scrollable');
|
||||
this.lineheight = this.getChildById(this.container,
|
||||
|
@ -646,6 +981,9 @@ VT100.prototype.initializeElements = function(container) {
|
|||
// Hide context menu
|
||||
this.hideContextMenu();
|
||||
|
||||
// Set up onscreen soft keyboard
|
||||
this.initializeKeyboard();
|
||||
|
||||
// Add listener to reconnect button
|
||||
this.addListener(this.reconnectBtn.firstChild, 'click',
|
||||
function(vt100) {
|
||||
|
@ -733,6 +1071,7 @@ VT100.prototype.reconnect = function() {
|
|||
|
||||
VT100.prototype.showReconnect = function(state) {
|
||||
if (state) {
|
||||
this.hideSoftKeyboard();
|
||||
this.reconnectBtn.style.visibility = '';
|
||||
} else {
|
||||
this.reconnectBtn.style.visibility = 'hidden';
|
||||
|
@ -766,6 +1105,9 @@ VT100.prototype.resized = function(w, h) {
|
|||
};
|
||||
|
||||
VT100.prototype.resizer = function() {
|
||||
// Hide onscreen soft keyboard
|
||||
this.hideSoftKeyboard();
|
||||
|
||||
// The cursor can get corrupted if the print-preview is displayed in Firefox.
|
||||
// Recreating it, will repair it.
|
||||
var newCursor = document.createElement('pre');
|
||||
|
@ -945,6 +1287,17 @@ VT100.prototype.cancelEvent = function(event) {
|
|||
return false;
|
||||
};
|
||||
|
||||
VT100.prototype.mousePosition = function(event) {
|
||||
var offsetX = this.container.offsetLeft;
|
||||
var offsetY = this.container.offsetTop;
|
||||
for (var e = this.container; e = e.offsetParent; ) {
|
||||
offsetX += e.offsetLeft;
|
||||
offsetY += e.offsetTop;
|
||||
}
|
||||
return [ event.clientX - offsetX,
|
||||
event.clientY - offsetY ];
|
||||
};
|
||||
|
||||
VT100.prototype.mouseEvent = function(event, type) {
|
||||
// If any text is currently selected, do not move the focus as that would
|
||||
// invalidate the selection.
|
||||
|
@ -954,15 +1307,10 @@ VT100.prototype.mouseEvent = function(event, type) {
|
|||
}
|
||||
|
||||
// Compute mouse position in characters.
|
||||
var offsetX = this.container.offsetLeft;
|
||||
var offsetY = this.container.offsetTop;
|
||||
for (var e = this.container; e = e.offsetParent; ) {
|
||||
offsetX += e.offsetLeft;
|
||||
offsetY += e.offsetTop;
|
||||
}
|
||||
var x = (event.clientX - offsetX) / this.cursorWidth;
|
||||
var y = ((event.clientY - offsetY) + this.scrollable.offsetTop) /
|
||||
this.cursorHeight - this.numScrollbackLines;
|
||||
var position = this.mousePosition(event);
|
||||
var x = Math.floor(position[0] / this.cursorWidth);
|
||||
var y = Math.floor((position[1] + this.scrollable.scrollTop) /
|
||||
this.cursorHeight) - this.numScrollbackLines;
|
||||
var inside = true;
|
||||
if (x >= this.terminalWidth) {
|
||||
x = this.terminalWidth - 1;
|
||||
|
@ -1022,7 +1370,7 @@ VT100.prototype.mouseEvent = function(event, type) {
|
|||
// Bring up context menu.
|
||||
if (button == 2 && !event.shiftKey) {
|
||||
if (type == MOUSE_DOWN) {
|
||||
this.showContextMenu(event.clientX - offsetX, event.clientY - offsetY);
|
||||
this.showContextMenu(position[0], position[1]);
|
||||
}
|
||||
return this.cancelEvent(event);
|
||||
}
|
||||
|
@ -1058,6 +1406,29 @@ VT100.prototype.getTextContent = function(elem) {
|
|||
(typeof elem.textContent == 'undefined' ? elem.innerText : '');
|
||||
};
|
||||
|
||||
VT100.prototype.setTextContentRaw = function(elem, s) {
|
||||
// Updating the content of an element is an expensive operation. It actually
|
||||
// pays off to first check whether the element is still unchanged.
|
||||
if (typeof elem.textContent == 'undefined') {
|
||||
if (elem.innerText != s) {
|
||||
try {
|
||||
elem.innerText = s;
|
||||
} catch (e) {
|
||||
// Very old versions of IE do not allow setting innerText. Instead,
|
||||
// remove all children, by setting innerHTML and then set the text
|
||||
// using DOM methods.
|
||||
elem.innerHTML = '';
|
||||
elem.appendChild(document.createTextNode(
|
||||
this.replaceChar(s, ' ', '\u00A0')));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (elem.textContent != s) {
|
||||
elem.textContent = s;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
VT100.prototype.setTextContent = function(elem, s) {
|
||||
// Check if we find any URLs in the text. If so, automatically convert them
|
||||
// to links.
|
||||
|
@ -1103,26 +1474,7 @@ VT100.prototype.setTextContent = function(elem, s) {
|
|||
return;
|
||||
}
|
||||
|
||||
// Updating the content of an element is an expensive operation. It actually
|
||||
// pays off to first check whether the element is still unchanged.
|
||||
if (typeof elem.textContent == 'undefined') {
|
||||
if (elem.innerText != s) {
|
||||
try {
|
||||
elem.innerText = s;
|
||||
} catch (e) {
|
||||
// Very old versions of IE do not allow setting innerText. Instead,
|
||||
// remove all children, by setting innerHTML and then set the text
|
||||
// using DOM methods.
|
||||
elem.innerHTML = '';
|
||||
elem.appendChild(document.createTextNode(
|
||||
this.replaceChar(s, ' ', '\u00A0')));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (elem.textContent != s) {
|
||||
elem.textContent = s;
|
||||
}
|
||||
}
|
||||
this.setTextContentRaw(elem, s);
|
||||
};
|
||||
|
||||
VT100.prototype.insertBlankLine = function(y, color, style) {
|
||||
|
@ -1578,27 +1930,21 @@ VT100.prototype.enableAlternateScreen = function(state) {
|
|||
this.console[this.currentScreen].style.display = '';
|
||||
|
||||
// Select appropriate character pitch.
|
||||
var styles = [ 'transform',
|
||||
'WebkitTransform',
|
||||
'MozTransform',
|
||||
'filter' ];
|
||||
for (var i = 0; i < styles.length; ++i) {
|
||||
if (typeof this.console[0].style[styles[i]] != 'undefined') {
|
||||
if (state) {
|
||||
// Upon enabling the alternate screen, we switch to 80 column mode. But
|
||||
// upon returning to the regular screen, we restore the mode that was
|
||||
// in effect previously.
|
||||
this.console[1].style[styles[i]] = '';
|
||||
}
|
||||
var style =
|
||||
this.console[this.currentScreen].style[styles[i]];
|
||||
this.cursor.style[styles[i]] = style;
|
||||
this.space.style[styles[i]] = style;
|
||||
this.scale = style == '' ? 1.0:1.65;
|
||||
if (styles[i] == 'filter') {
|
||||
this.console[this.currentScreen].style.width = style == '' ? '165%':'';
|
||||
}
|
||||
break;
|
||||
var transform = this.getTransformName();
|
||||
if (transform) {
|
||||
if (state) {
|
||||
// Upon enabling the alternate screen, we switch to 80 column mode. But
|
||||
// upon returning to the regular screen, we restore the mode that was
|
||||
// in effect previously.
|
||||
this.console[1].style[transform] = '';
|
||||
}
|
||||
var style =
|
||||
this.console[this.currentScreen].style[transform];
|
||||
this.cursor.style[transform] = style;
|
||||
this.space.style[transform] = style;
|
||||
this.scale = style == '' ? 1.0:1.65;
|
||||
if (transform == 'filter') {
|
||||
this.console[this.currentScreen].style.width = style == '' ? '165%':'';
|
||||
}
|
||||
}
|
||||
this.resizer();
|
||||
|
@ -1969,6 +2315,70 @@ VT100.prototype.toggleBell = function() {
|
|||
this.visualBell = !this.visualBell;
|
||||
};
|
||||
|
||||
VT100.prototype.toggleSoftKeyboard = function() {
|
||||
this.softKeyboard = !this.softKeyboard;
|
||||
this.keyboardImage.style.visibility = this.softKeyboard ? 'visible' : '';
|
||||
};
|
||||
|
||||
VT100.prototype.deselectKeys = function(elem) {
|
||||
if (elem && elem.className == 'selected') {
|
||||
elem.className = '';
|
||||
}
|
||||
for (elem = elem.firstChild; elem; elem = elem.nextSibling) {
|
||||
this.deselectKeys(elem);
|
||||
}
|
||||
};
|
||||
|
||||
VT100.prototype.showSoftKeyboard = function() {
|
||||
// Make sure no key is currently selected
|
||||
this.lastSelectedKey = undefined;
|
||||
this.deselectKeys(this.keyboard);
|
||||
this.isShift = false;
|
||||
this.showShiftState(false);
|
||||
this.isCtrl = false;
|
||||
this.showCtrlState(false);
|
||||
this.isAlt = false;
|
||||
this.showAltState(false);
|
||||
|
||||
this.keyboard.style.left = '0px';
|
||||
this.keyboard.style.top = '0px';
|
||||
this.keyboard.style.width = this.container.offsetWidth + 'px';
|
||||
this.keyboard.style.height = this.container.offsetHeight + 'px';
|
||||
this.keyboard.style.visibility = 'hidden';
|
||||
this.keyboard.style.display = '';
|
||||
|
||||
var kbd = this.keyboard.firstChild;
|
||||
var scale = 1.0;
|
||||
var transform = this.getTransformName();
|
||||
if (transform) {
|
||||
kbd.style[transform] = '';
|
||||
if (kbd.offsetWidth > 0.9 * this.container.offsetWidth) {
|
||||
scale = (kbd.offsetWidth/
|
||||
this.container.offsetWidth)/0.9;
|
||||
}
|
||||
if (kbd.offsetHeight > 0.9 * this.container.offsetHeight) {
|
||||
scale = Math.max((kbd.offsetHeight/
|
||||
this.container.offsetHeight)/0.9);
|
||||
}
|
||||
var style = this.getTransformStyle(transform,
|
||||
scale > 1.0 ? scale : undefined);
|
||||
kbd.style[transform] = style;
|
||||
}
|
||||
if (transform == 'filter') {
|
||||
scale = 1.0;
|
||||
}
|
||||
kbd.style.left = ((this.container.offsetWidth -
|
||||
kbd.offsetWidth/scale)/2) + 'px';
|
||||
kbd.style.top = ((this.container.offsetHeight -
|
||||
kbd.offsetHeight/scale)/2) + 'px';
|
||||
|
||||
this.keyboard.style.visibility = 'visible';
|
||||
};
|
||||
|
||||
VT100.prototype.hideSoftKeyboard = function() {
|
||||
this.keyboard.style.display = 'none';
|
||||
};
|
||||
|
||||
VT100.prototype.toggleCursorBlinking = function() {
|
||||
this.blinkingCursor = !this.blinkingCursor;
|
||||
};
|
||||
|
@ -2007,6 +2417,9 @@ VT100.prototype.showContextMenu = function(x, y) {
|
|||
'<li>' +
|
||||
(this.visualBell ? '<img src="enabled.gif" />' : '') +
|
||||
'Visual Bell</li>'+
|
||||
'<li>' +
|
||||
(this.softKeyboard ? '<img src="enabled.gif" />' : '') +
|
||||
'Onscreen Keyboard</li>' +
|
||||
'<li id="endconfig">' +
|
||||
(this.blinkingCursor ? '<img src="enabled.gif" />' : '') +
|
||||
'Blinking Cursor</li>'+
|
||||
|
@ -2038,6 +2451,7 @@ VT100.prototype.showContextMenu = function(x, y) {
|
|||
// Actions for default items
|
||||
var actions = [ this.copyLast, p, this.reset,
|
||||
this.toggleUTF, this.toggleBell,
|
||||
this.toggleSoftKeyboard,
|
||||
this.toggleCursorBlinking ];
|
||||
|
||||
// Actions for user CSS styles (if any)
|
||||
|
@ -2093,26 +2507,30 @@ VT100.prototype.showContextMenu = function(x, y) {
|
|||
}
|
||||
|
||||
// Position menu next to the mouse pointer
|
||||
if (x + popup.clientWidth > this.container.offsetWidth) {
|
||||
x = this.container.offsetWidth - popup.clientWidth;
|
||||
this.menu.style.left = '0px';
|
||||
this.menu.style.top = '0px';
|
||||
this.menu.style.width = this.container.offsetWidth + 'px';
|
||||
this.menu.style.height = this.container.offsetHeight + 'px';
|
||||
popup.style.left = '0px';
|
||||
popup.style.top = '0px';
|
||||
|
||||
var margin = 2;
|
||||
if (x + popup.clientWidth >= this.container.offsetWidth - margin) {
|
||||
x = this.container.offsetWidth-popup.clientWidth - margin - 1;
|
||||
}
|
||||
if (x < 0) {
|
||||
x = 0;
|
||||
if (x < margin) {
|
||||
x = margin;
|
||||
}
|
||||
if (y + popup.clientHeight > this.container.offsetHeight) {
|
||||
y = this.container.offsetHeight-popup.clientHeight;
|
||||
if (y + popup.clientHeight >= this.container.offsetHeight - margin) {
|
||||
y = this.container.offsetHeight-popup.clientHeight - margin - 1;
|
||||
}
|
||||
if (y < 0) {
|
||||
y = 0;
|
||||
if (y < margin) {
|
||||
y = margin;
|
||||
}
|
||||
popup.style.left = x + 'px';
|
||||
popup.style.top = y + 'px';
|
||||
|
||||
// Block all other interactions with the terminal emulator
|
||||
this.menu.style.left = '0px';
|
||||
this.menu.style.top = '0px';
|
||||
this.menu.style.width = this.container.offsetWidth + 'px';
|
||||
this.menu.style.height = this.container.offsetHeight + 'px';
|
||||
this.addListener(this.menu, 'click', function(vt100) {
|
||||
return function() {
|
||||
vt100.hideContextMenu();
|
||||
|
@ -2895,39 +3313,42 @@ VT100.prototype.restoreCursor = function() {
|
|||
this.savedY[this.currentScreen]);
|
||||
};
|
||||
|
||||
VT100.prototype.set80_132Mode = function(state) {
|
||||
var transform = undefined;
|
||||
var styles = [ 'transform',
|
||||
'WebkitTransform',
|
||||
'MozTransform',
|
||||
'filter'
|
||||
];
|
||||
VT100.prototype.getTransformName = function() {
|
||||
var styles = [ 'transform', 'WebkitTransform', 'MozTransform', 'filter' ];
|
||||
for (var i = 0; i < styles.length; ++i) {
|
||||
if (typeof this.console[0].style[styles[i]] != 'undefined') {
|
||||
transform = styles[i];
|
||||
break;
|
||||
return styles[i];
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
VT100.prototype.getTransformStyle = function(transform, scale) {
|
||||
return scale && scale != 1.0
|
||||
? transform == 'filter'
|
||||
? 'progid:DXImageTransform.Microsoft.Matrix(' +
|
||||
'M11=' + (1.0/scale) + ',M12=0,M21=0,M22=1,' +
|
||||
"sizingMethod='auto expand')"
|
||||
: 'translateX(-50%) ' +
|
||||
'scaleX(' + (1.0/scale) + ') ' +
|
||||
'translateX(50%)'
|
||||
: '';
|
||||
};
|
||||
|
||||
VT100.prototype.set80_132Mode = function(state) {
|
||||
var transform = this.getTransformName();
|
||||
if (transform) {
|
||||
if ((this.console[this.currentScreen].style[transform] != '') == state) {
|
||||
return;
|
||||
}
|
||||
var style =
|
||||
state ? transform == 'filter'
|
||||
? 'progid:DXImageTransform.Microsoft.Matrix(' +
|
||||
'M11=0.606060606060606060606,M12=0,M21=0,M22=1,' +
|
||||
"sizingMethod='auto expand')"
|
||||
: 'translateX(-50%) ' +
|
||||
'scaleX(0.606060606060606060606) ' +
|
||||
'translateX(50%)'
|
||||
: '';
|
||||
var style = state ?
|
||||
this.getTransformStyle(transform, 1.65):'';
|
||||
this.console[this.currentScreen].style[transform] = style;
|
||||
this.cursor.style[transform] = style;
|
||||
this.space.style[transform] = style;
|
||||
this.scale = state ? 1.65 : 1.0;
|
||||
this.cursor.style[transform] = style;
|
||||
this.space.style[transform] = style;
|
||||
this.scale = state ? 1.65 : 1.0;
|
||||
if (transform == 'filter') {
|
||||
this.console[this.currentScreen].style.width = state ? '165%' : '';
|
||||
this.console[this.currentScreen].style.width = state ? '165%' : '';
|
||||
}
|
||||
this.resizer();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue