*** empty log message ***
authorroot <root>
Sun, 16 Jan 2005 15:59:45 +0000 (15:59 +0000)
committerroot <root>
Sun, 16 Jan 2005 15:59:45 +0000 (15:59 +0000)
12 files changed:
README.FAQ
README.configure
doc/rxvt.1.html
doc/rxvt.1.man.in
doc/rxvt.1.txt
doc/rxvt.7.html
doc/rxvt.7.man.in
doc/rxvt.7.txt
src/feature.h
src/keyboard.C [new file with mode: 0644]
src/keyboard.h [new file with mode: 0644]
src/rxvtutil.h

index 41fb729..0e457a0 100644 (file)
@@ -503,49 +503,31 @@ FREQUENTLY ASKED QUESTIONS
         There are some compile-time selections available via configure.
         Unless you have run "configure" with the "--disable-resources"
         option you can use the `keysym' resource to alter the keystrings
-        associated with keysym 0xFF00 - 0xFFFF (function, cursor keys, etc).
-
-        Here's an example for a tn3270 session started using `rxvt -name
-        tn3270'
-
-           !#  ----- special uses ------:
-           ! tn3270 login, remap function and arrow keys.
-           tn3270*font:      *clean-bold-*-*--15-*
-
-           ! keysym - used by rxvt only
-           ! Delete - ^D
-           tn3270*keysym.0xFFFF:      \004
-
-           ! Home - ^A
-           tn3270*keysym.0xFF50:      \001
-           ! Left - ^B
-           tn3270*keysym.0xFF51:      \002
-           ! Up - ^P
-           tn3270*keysym.0xFF52:      \020
-           ! Right - ^F
-           tn3270*keysym.0xFF53:      \006
-           ! Down - ^N
-           tn3270*keysym.0xFF54:      \016
-           ! End - ^E
-           tn3270*keysym.0xFF57:      \005
-
-           ! F1 - F12
-           tn3270*keysym.0xFFBE:      \e1
-           tn3270*keysym.0xFFBF:      \e2
-           tn3270*keysym.0xFFC0:      \e3
-           tn3270*keysym.0xFFC1:      \e4
-           tn3270*keysym.0xFFC2:      \e5
-           tn3270*keysym.0xFFC3:      \e6
-           tn3270*keysym.0xFFC4:      \e7
-           tn3270*keysym.0xFFC5:      \e8
-           tn3270*keysym.0xFFC6:      \e9
-           tn3270*keysym.0xFFC7:      \e0
-           tn3270*keysym.0xFFC8:      \e-
-           tn3270*keysym.0xFFC9:      \e=
-
-           ! map Prior/Next to F7/F8
-           tn3270*keysym.0xFF55:      \e7
-           tn3270*keysym.0xFF56:      \e8
+        associated with keysyms.
+
+        Here's an example for a URxvt session started using `rxvt -name
+        URxvt'
+
+                URxvt*keysym.Home:          \e[1~
+                URxvt*keysym.End:           \e[4~
+                URxvt*keysym.C-apostrophe:  \e<C-'>
+                URxvt*keysym.C-slash:       \e<C-/>
+                URxvt*keysym.C-semicolon:   \e<C-;>
+                URxvt*keysym.C-grave:       \e<C-`>
+                URxvt*keysym.C-comma:       \e<C-,>
+                URxvt*keysym.C-period:      \e<C-.>
+                URxvt*keysym.C-0x60:        \e<C-`>
+                URxvt*keysym.C-Tab:         \e<C-Tab>
+                URxvt*keysym.C-Return:      \e<C-Return>
+                URxvt*keysym.S-Return:      \e<S-Return>
+                URxvt*keysym.S-space:       \e<S-Space>
+                URxvt*keysym.M-Up:          \e<M-Up>
+                URxvt*keysym.M-Down:        \e<M-Down>
+                URxvt*keysym.M-Left:        \e<M-Left>
+                URxvt*keysym.M-Right:       \e<M-Right>
+                URxvt*keysym.M-C-0:         list.0123456789.\e<M-C-.>
+                URxvt*keysym.M-C-a:         list.abcdefghijklmnopqrstuvwxyz.\033<M-C-.>
+                URxvt*keysym.F12:           proto:\033]701;zh_CN.GBK\007
 
     I'm using keyboard model XXX that has extra Prior/Next/Insert keys. How
     do I make use of them? For example, the Sun Keyboard type 4 has the
index ba48d36..39c1b63 100644 (file)
@@ -169,6 +169,20 @@ CONFIGURE OPTIONS
         to have. Normally you want this, but for very small binaries you may
         want to disable this.
 
+        A non-exhaustive list of features enabled by "--enable-frills"
+        (possibly in combination with other switches) is:
+
+          MWM-hints
+          seperate underline colour
+          settable border widths and borderless switch
+          settable extra linespacing
+          extra window properties (e.g. UTF-8 window names and PID)
+          iso-14755-2 and -3, and visual feedback
+          backindex and forwardindex escape sequence
+          window op and locale change escape sequences
+          tripleclickwords
+          settable insecure mode
+
     --enable-iso14755
         Enable extended ISO 14755 support (see rxvt(1), or doc/rxvt.1.txt).
         Basic support (section 5.1) is enabled by "--enable-frills", while
index 97df44a..2d9b0b8 100644 (file)
@@ -1103,14 +1103,52 @@ instead scroll the screen up.
 <dt><strong><a name="item_keysym_2esym_3a_string"><strong>keysym.</strong><em>sym</em>: <em>string</em></a></strong><br />
 </dt>
 <dd>
-Associate <em>string</em> with keysym <em>sym</em> (<strong>0xFF00 - 0xFFFF</strong>). It may
+Associate <em>string</em> with keysym <em>sym</em>.  The intervening resource
+name <strong>keysym.</strong> cannot be omitted. This resource is only available
+when compiled with KEYSYM_RESOURCE.
+</dd>
+<dd>
+<p>The format of <em>sym</em> is ``<em>(mask-)key</em>'',
+where <em>mask</em> can be any combination of <strong>Control</strong>, <strong>NumLock</strong>,
+<strong>Shift</strong>, <strong>Meta</strong>, <strong>Lock</strong>, <strong>Mod1</strong>, <strong>Mod2</strong>, <strong>Mod3</strong>, <strong>Mod4</strong>,
+<strong>Mod5</strong>, and the abbreviated
+<strong>C</strong>, <strong>N</strong>, <strong>S</strong>, <strong>M</strong>, <strong>A</strong>, <strong>L</strong>, <strong>1</strong>, <strong>2</strong>, <strong>3</strong>, <strong>4</strong>, <strong>5</strong>.
+The spellings of <em>key</em> can be obtained by using <strong>xev</strong>(1)
+command or searching keysym macros from
+<strong>/usr/X11R6/include/X11/keysymdef.h</strong> and omit the prefix <strong>XK_</strong>.
+Alternatively you can specify <em>key</em> by its hex keysym value 
+(<strong>0x0000 - 0xFFFF</strong>).
+Note that the lookup of <em>sym</em>s is not performed in an exact manner;
+however, the closest match is assured.</p>
+</dd>
+<dd>
+<p><em>string</em> may
 contain escape values (\a: bell, \b: backspace, \e, \E: escape, \n:
 newline, \r: return, \t:
 tab, \000: octal number) or control characters (^?: delete, ^@: null,
 ^A ...) and may enclosed with double quotes so that it can start or end
-with whitespace. The intervening resource name <strong>keysym.</strong> cannot be
-omitted. This resource is only available when compiled with
-KEYSYM_RESOURCE.
+with whitespace.</p>
+</dd>
+<dd>
+<p>You can define a range of keysyms in one shot by providing a <em>string</em>
+with pattern <strong>list/STRING1/STRING2/STRING3</strong>, where the delimeter `/'
+should be a character not used by the <strong>STRING</strong>s.</p>
+</dd>
+<dd>
+<p>Its usage can be demonstrated by an example:
+        URxvt.keysym.M-C-0x61:    list.abc.\e&lt;M-C-.&gt;</p>
+</dd>
+<dd>
+<p>The above line is equivalent to the following three lines:
+        URxvt.keysym.Meta-Control-0x61:    \e&lt;M-C-a&gt;
+        URxvt.keysym.Meta-Control-0x62:    \e&lt;M-C-b&gt;
+        URxvt.keysym.Meta-Control-0x63:    \e&lt;M-C-c&gt;</p>
+</dd>
+<dd>
+<p>If <em>string</em> takes the form of <strong>proto:STRING</strong>,
+the specified <strong>STRING</strong> is interpreted and executed as <strong>rxvt</strong>'s
+control sequence. For example, <strong>``proto:\033]701;zh_CN.GBK\007''</strong>
+means changing the current locale to zh_CN.GBK.</p>
 </dd>
 <p></p></dl>
 <p>
index 45afbf6..b58a7e5 100644 (file)
 .\" ========================================================================
 .\"
 .IX Title "rxvt 1"
-.TH rxvt 1 "2005-01-11" "4.8" "RXVT-UNICODE"
+.TH rxvt 1 "2005-01-16" "4.8" "RXVT-UNICODE"
 .SH "NAME"
 rxvt\-unicode (ouR XVT, unicode) \- (a VT102 emulator for the X window system)
 .SH "SYNOPSIS"
@@ -830,14 +830,46 @@ scrollback buffer and switching to/from the secondary screen will
 instead scroll the screen up.
 .IP "\fBkeysym.\fR\fIsym\fR: \fIstring\fR" 4
 .IX Item "keysym.sym: string"
-Associate \fIstring\fR with keysym \fIsym\fR (\fB0xFF00 \- 0xFFFF\fR). It may
+Associate \fIstring\fR with keysym \fIsym\fR.  The intervening resource
+name \fBkeysym.\fR cannot be omitted. This resource is only available
+when compiled with \s-1KEYSYM_RESOURCE\s0.
+.Sp
+The format of \fIsym\fR is "\fI(mask\-)key\fR",
+where \fImask\fR can be any combination of \fBControl\fR, \fBNumLock\fR,
+\&\fBShift\fR, \fBMeta\fR, \fBLock\fR, \fBMod1\fR, \fBMod2\fR, \fBMod3\fR, \fBMod4\fR,
+\&\fBMod5\fR, and the abbreviated
+\&\fBC\fR, \fBN\fR, \fBS\fR, \fBM\fR, \fBA\fR, \fBL\fR, \fB1\fR, \fB2\fR, \fB3\fR, \fB4\fR, \fB5\fR.
+The spellings of \fIkey\fR can be obtained by using \fBxev\fR(1)
+command or searching keysym macros from
+\&\fB/usr/X11R6/include/X11/keysymdef.h\fR and omit the prefix \fB\s-1XK_\s0\fR.
+Alternatively you can specify \fIkey\fR by its hex keysym value 
+(\fB0x0000 \- 0xFFFF\fR).
+Note that the lookup of \fIsym\fRs is not performed in an exact manner;
+however, the closest match is assured.
+.Sp
+\&\fIstring\fR may
 contain escape values (\ea: bell, \eb: backspace, \ee, \eE: escape, \en:
 newline, \er: return, \et:
 tab, \e000: octal number) or control characters (^?: delete, ^@: null,
 ^A ...) and may enclosed with double quotes so that it can start or end
-with whitespace. The intervening resource name \fBkeysym.\fR cannot be
-omitted. This resource is only available when compiled with
-\&\s-1KEYSYM_RESOURCE\s0.
+with whitespace.
+.Sp
+You can define a range of keysyms in one shot by providing a \fIstring\fR
+with pattern \fBlist/STRING1/STRING2/STRING3\fR, where the delimeter `/'
+should be a character not used by the \fB\s-1STRING\s0\fRs.
+.Sp
+Its usage can be demonstrated by an example:
+        URxvt.keysym.M\-C\-0x61:    list.abc.\ee<M\-C\-.>
+.Sp
+The above line is equivalent to the following three lines:
+        URxvt.keysym.Meta\-Control\-0x61:    \ee<M\-C\-a>
+        URxvt.keysym.Meta\-Control\-0x62:    \ee<M\-C\-b>
+        URxvt.keysym.Meta\-Control\-0x63:    \ee<M\-C\-c>
+.Sp
+If \fIstring\fR takes the form of \fBproto:STRING\fR,
+the specified \fB\s-1STRING\s0\fR is interpreted and executed as \fB@@RXVT_NAME@@\fR's
+control sequence. For example, \fB\*(L"proto:\e033]701;zh_CN.GBK\e007\*(R"\fR
+means changing the current locale to zh_CN.GBK.
 .SH "THE SCROLLBAR"
 .IX Header "THE SCROLLBAR"
 Lines of text that scroll off the top of the \fB@@RXVT_NAME@@\fR window
index ec855c0..bf2e70c 100644 (file)
@@ -692,13 +692,41 @@ RESOURCES (available also as long-options)
         instead scroll the screen up.
 
     keysym.*sym*: *string*
-        Associate *string* with keysym *sym* (0xFF00 - 0xFFFF). It may
-        contain escape values (\a: bell, \b: backspace, \e, \E: escape, \n:
-        newline, \r: return, \t: tab, \000: octal number) or control
-        characters (^?: delete, ^@: null, ^A ...) and may enclosed with
-        double quotes so that it can start or end with whitespace. The
-        intervening resource name keysym. cannot be omitted. This resource
-        is only available when compiled with KEYSYM_RESOURCE.
+        Associate *string* with keysym *sym*. The intervening resource name
+        keysym. cannot be omitted. This resource is only available when
+        compiled with KEYSYM_RESOURCE.
+
+        The format of *sym* is "*(mask-)key*", where *mask* can be any
+        combination of Control, NumLock, Shift, Meta, Lock, Mod1, Mod2,
+        Mod3, Mod4, Mod5, and the abbreviated C, N, S, M, A, L, 1, 2, 3, 4,
+        5. The spellings of *key* can be obtained by using xev(1) command or
+        searching keysym macros from /usr/X11R6/include/X11/keysymdef.h and
+        omit the prefix XK_. Alternatively you can specify *key* by its hex
+        keysym value (0x0000 - 0xFFFF). Note that the lookup of *sym*s is
+        not performed in an exact manner; however, the closest match is
+        assured.
+
+        *string* may contain escape values (\a: bell, \b: backspace, \e, \E:
+        escape, \n: newline, \r: return, \t: tab, \000: octal number) or
+        control characters (^?: delete, ^@: null, ^A ...) and may enclosed
+        with double quotes so that it can start or end with whitespace.
+
+        You can define a range of keysyms in one shot by providing a
+        *string* with pattern list/STRING1/STRING2/STRING3, where the
+        delimeter `/' should be a character not used by the STRINGs.
+
+        Its usage can be demonstrated by an example: URxvt.keysym.M-C-0x61:
+        list.abc.\e<M-C-.>
+
+        The above line is equivalent to the following three lines:
+        URxvt.keysym.Meta-Control-0x61: \e<M-C-a>
+        URxvt.keysym.Meta-Control-0x62: \e<M-C-b>
+        URxvt.keysym.Meta-Control-0x63: \e<M-C-c>
+
+        If *string* takes the form of proto:STRING, the specified STRING is
+        interpreted and executed as rxvt's control sequence. For example,
+        "proto:\033]701;zh_CN.GBK\007" means changing the current locale to
+        zh_CN.GBK.
 
 THE SCROLLBAR
     Lines of text that scroll off the top of the rxvt window (resource:
index acab850..47b57aa 100644 (file)
@@ -724,60 +724,33 @@ GNU Emacs (and Emacs-like editors) use ^H for help.</p>
 <dd>
 There are some compile-time selections available via configure. Unless
 you have run ``configure'' with the <a href="#item__2d_2ddisable_2dresources"><code>--disable-resources</code></a> option you can
-use the `keysym' resource to alter the keystrings associated with keysym
-0xFF00 - 0xFFFF (function, cursor keys, etc).
+use the `keysym' resource to alter the keystrings associated with keysyms.
 </dd>
 <dd>
-<p>Here's an example for a tn3270 session started using `rxvt -name tn3270'</p>
+<p>Here's an example for a URxvt session started using `rxvt -name URxvt'</p>
 </dd>
 <dd>
 <pre>
-   !#  ----- special uses ------:
-   ! tn3270 login, remap function and arrow keys.
-   tn3270*font:      *clean-bold-*-*--15-*</pre>
-</dd>
-<dd>
-<pre>
-   ! keysym - used by rxvt only
-   ! Delete - ^D
-   tn3270*keysym.0xFFFF:      \004</pre>
-</dd>
-<dd>
-<pre>
-   ! Home - ^A
-   tn3270*keysym.0xFF50:      \001
-   ! Left - ^B
-   tn3270*keysym.0xFF51:      \002
-   ! Up - ^P
-   tn3270*keysym.0xFF52:      \020
-   ! Right - ^F
-   tn3270*keysym.0xFF53:      \006
-   ! Down - ^N
-   tn3270*keysym.0xFF54:      \016
-   ! End - ^E
-   tn3270*keysym.0xFF57:      \005</pre>
-</dd>
-<dd>
-<pre>
-   ! F1 - F12
-   tn3270*keysym.0xFFBE:      \e1
-   tn3270*keysym.0xFFBF:      \e2
-   tn3270*keysym.0xFFC0:      \e3
-   tn3270*keysym.0xFFC1:      \e4
-   tn3270*keysym.0xFFC2:      \e5
-   tn3270*keysym.0xFFC3:      \e6
-   tn3270*keysym.0xFFC4:      \e7
-   tn3270*keysym.0xFFC5:      \e8
-   tn3270*keysym.0xFFC6:      \e9
-   tn3270*keysym.0xFFC7:      \e0
-   tn3270*keysym.0xFFC8:      \e-
-   tn3270*keysym.0xFFC9:      \e=</pre>
-</dd>
-<dd>
-<pre>
-   ! map Prior/Next to F7/F8
-   tn3270*keysym.0xFF55:      \e7
-   tn3270*keysym.0xFF56:      \e8</pre>
+        URxvt*keysym.Home:          \e[1~
+        URxvt*keysym.End:           \e[4~
+        URxvt*keysym.C-apostrophe:  \e&lt;C-'&gt;
+        URxvt*keysym.C-slash:       \e&lt;C-/&gt;
+        URxvt*keysym.C-semicolon:   \e&lt;C-;&gt;
+        URxvt*keysym.C-grave:       \e&lt;C-`&gt;
+        URxvt*keysym.C-comma:       \e&lt;C-,&gt;
+        URxvt*keysym.C-period:      \e&lt;C-.&gt;
+        URxvt*keysym.C-0x60:        \e&lt;C-`&gt;
+        URxvt*keysym.C-Tab:         \e&lt;C-Tab&gt;
+        URxvt*keysym.C-Return:      \e&lt;C-Return&gt;
+        URxvt*keysym.S-Return:      \e&lt;S-Return&gt;
+        URxvt*keysym.S-space:       \e&lt;S-Space&gt;
+        URxvt*keysym.M-Up:          \e&lt;M-Up&gt;
+        URxvt*keysym.M-Down:        \e&lt;M-Down&gt;
+        URxvt*keysym.M-Left:        \e&lt;M-Left&gt;
+        URxvt*keysym.M-Right:       \e&lt;M-Right&gt;
+        URxvt*keysym.M-C-0:         list.0123456789.\e&lt;M-C-.&gt;
+        URxvt*keysym.M-C-a:         list.abcdefghijklmnopqrstuvwxyz.\033&lt;M-C-.&gt;
+        URxvt*keysym.F12:           proto:\033]701;zh_CN.GBK\007</pre>
 </dd>
 <p></p>
 <dt><strong><a name="item_i_27m_using_keyboard_model_xxx_that_has_extra_prio">I'm using keyboard model XXX that has extra Prior/Next/Insert keys.
@@ -2663,6 +2636,23 @@ Add support for many small features that are not essential but nice to
 have. Normally you want this, but for very small binaries you may want to
 disable this.
 </dd>
+<dd>
+<p>A non-exhaustive list of features enabled by <a href="#item__2d_2denable_2dfrills"><code>--enable-frills</code></a> (possibly
+in combination with other switches) is:</p>
+</dd>
+<dd>
+<pre>
+  MWM-hints
+  seperate underline colour
+  settable border widths and borderless switch
+  settable extra linespacing
+  extra window properties (e.g. UTF-8 window names and PID)
+  iso-14755-2 and -3, and visual feedback
+  backindex and forwardindex escape sequence
+  window op and locale change escape sequences
+  tripleclickwords
+  settable insecure mode</pre>
+</dd>
 <p></p>
 <dt><strong><a name="item__2d_2denable_2diso14755">--enable-iso14755</a></strong><br />
 </dt>
index e7063fb..fbbb252 100644 (file)
 .\" ========================================================================
 .\"
 .IX Title "rxvt 7"
-.TH rxvt 7 "2005-01-11" "4.8" "RXVT-UNICODE"
+.TH rxvt 7 "2005-01-16" "4.8" "RXVT-UNICODE"
 .SH "NAME"
 RXVT REFERENCE \- FAQ, command sequences and other background information
 .SH "FREQUENTLY ASKED QUESTIONS"
@@ -680,58 +680,31 @@ Perhaps someday this will all be resolved in a consistent manner.
 .IX Item "I don't like the key-bindings.  How do I change them?"
 There are some compile-time selections available via configure. Unless
 you have run \*(L"configure\*(R" with the \f(CW\*(C`\-\-disable\-resources\*(C'\fR option you can
-use the `keysym' resource to alter the keystrings associated with keysym
-0xFF00 \- 0xFFFF (function, cursor keys, etc).
-.Sp
-Here's an example for a tn3270 session started using `@@RXVT_NAME@@ \-name tn3270'
-.Sp
-.Vb 3
-\&   !#  ----- special uses ------:
-\&   ! tn3270 login, remap function and arrow keys.
-\&   tn3270*font:      *clean-bold-*-*--15-*
-.Ve
-.Sp
-.Vb 3
-\&   ! keysym - used by rxvt only
-\&   ! Delete - ^D
-\&   tn3270*keysym.0xFFFF:      \e004
-.Ve
-.Sp
-.Vb 12
-\&   ! Home - ^A
-\&   tn3270*keysym.0xFF50:      \e001
-\&   ! Left - ^B
-\&   tn3270*keysym.0xFF51:      \e002
-\&   ! Up - ^P
-\&   tn3270*keysym.0xFF52:      \e020
-\&   ! Right - ^F
-\&   tn3270*keysym.0xFF53:      \e006
-\&   ! Down - ^N
-\&   tn3270*keysym.0xFF54:      \e016
-\&   ! End - ^E
-\&   tn3270*keysym.0xFF57:      \e005
-.Ve
-.Sp
-.Vb 13
-\&   ! F1 - F12
-\&   tn3270*keysym.0xFFBE:      \ee1
-\&   tn3270*keysym.0xFFBF:      \ee2
-\&   tn3270*keysym.0xFFC0:      \ee3
-\&   tn3270*keysym.0xFFC1:      \ee4
-\&   tn3270*keysym.0xFFC2:      \ee5
-\&   tn3270*keysym.0xFFC3:      \ee6
-\&   tn3270*keysym.0xFFC4:      \ee7
-\&   tn3270*keysym.0xFFC5:      \ee8
-\&   tn3270*keysym.0xFFC6:      \ee9
-\&   tn3270*keysym.0xFFC7:      \ee0
-\&   tn3270*keysym.0xFFC8:      \ee-
-\&   tn3270*keysym.0xFFC9:      \ee=
-.Ve
-.Sp
-.Vb 3
-\&   ! map Prior/Next to F7/F8
-\&   tn3270*keysym.0xFF55:      \ee7
-\&   tn3270*keysym.0xFF56:      \ee8
+use the `keysym' resource to alter the keystrings associated with keysyms.
+.Sp
+Here's an example for a URxvt session started using `@@RXVT_NAME@@ \-name URxvt'
+.Sp
+.Vb 20
+\&        URxvt*keysym.Home:          \ee[1~
+\&        URxvt*keysym.End:           \ee[4~
+\&        URxvt*keysym.C-apostrophe:  \ee<C-'>
+\&        URxvt*keysym.C-slash:       \ee<C-/>
+\&        URxvt*keysym.C-semicolon:   \ee<C-;>
+\&        URxvt*keysym.C-grave:       \ee<C-`>
+\&        URxvt*keysym.C-comma:       \ee<C-,>
+\&        URxvt*keysym.C-period:      \ee<C-.>
+\&        URxvt*keysym.C-0x60:        \ee<C-`>
+\&        URxvt*keysym.C-Tab:         \ee<C-Tab>
+\&        URxvt*keysym.C-Return:      \ee<C-Return>
+\&        URxvt*keysym.S-Return:      \ee<S-Return>
+\&        URxvt*keysym.S-space:       \ee<S-Space>
+\&        URxvt*keysym.M-Up:          \ee<M-Up>
+\&        URxvt*keysym.M-Down:        \ee<M-Down>
+\&        URxvt*keysym.M-Left:        \ee<M-Left>
+\&        URxvt*keysym.M-Right:       \ee<M-Right>
+\&        URxvt*keysym.M-C-0:         list.0123456789.\ee<M-C-.>
+\&        URxvt*keysym.M-C-a:         list.abcdefghijklmnopqrstuvwxyz.\e033<M-C-.>
+\&        URxvt*keysym.F12:           proto:\e033]701;zh_CN.GBK\e007
 .Ve
 .IP "I'm using keyboard model \s-1XXX\s0 that has extra Prior/Next/Insert keys. How do I make use of them?  For example, the Sun Keyboard type 4 has the following mappings that rxvt-unicode doesn't recognize." 4
 .IX Item "I'm using keyboard model XXX that has extra Prior/Next/Insert keys. How do I make use of them?  For example, the Sun Keyboard type 4 has the following mappings that rxvt-unicode doesn't recognize."
@@ -2256,6 +2229,22 @@ Remove support for swap screen.
 Add support for many small features that are not essential but nice to
 have. Normally you want this, but for very small binaries you may want to
 disable this.
+.Sp
+A non-exhaustive list of features enabled by \f(CW\*(C`\-\-enable\-frills\*(C'\fR (possibly
+in combination with other switches) is:
+.Sp
+.Vb 10
+\&  MWM-hints
+\&  seperate underline colour
+\&  settable border widths and borderless switch
+\&  settable extra linespacing
+\&  extra window properties (e.g. UTF-8 window names and PID)
+\&  iso-14755-2 and -3, and visual feedback
+\&  backindex and forwardindex escape sequence
+\&  window op and locale change escape sequences
+\&  tripleclickwords
+\&  settable insecure mode
+.Ve
 .IP "\-\-enable\-iso14755" 4
 .IX Item "--enable-iso14755"
 Enable extended \s-1ISO\s0 14755 support (see @@RXVT_NAME@@(1), or
index a567048..7eff48c 100644 (file)
@@ -506,49 +506,31 @@ FREQUENTLY ASKED QUESTIONS
         There are some compile-time selections available via configure.
         Unless you have run "configure" with the "--disable-resources"
         option you can use the `keysym' resource to alter the keystrings
-        associated with keysym 0xFF00 - 0xFFFF (function, cursor keys, etc).
-
-        Here's an example for a tn3270 session started using `rxvt -name
-        tn3270'
-
-           !#  ----- special uses ------:
-           ! tn3270 login, remap function and arrow keys.
-           tn3270*font:      *clean-bold-*-*--15-*
-
-           ! keysym - used by rxvt only
-           ! Delete - ^D
-           tn3270*keysym.0xFFFF:      \004
-
-           ! Home - ^A
-           tn3270*keysym.0xFF50:      \001
-           ! Left - ^B
-           tn3270*keysym.0xFF51:      \002
-           ! Up - ^P
-           tn3270*keysym.0xFF52:      \020
-           ! Right - ^F
-           tn3270*keysym.0xFF53:      \006
-           ! Down - ^N
-           tn3270*keysym.0xFF54:      \016
-           ! End - ^E
-           tn3270*keysym.0xFF57:      \005
-
-           ! F1 - F12
-           tn3270*keysym.0xFFBE:      \e1
-           tn3270*keysym.0xFFBF:      \e2
-           tn3270*keysym.0xFFC0:      \e3
-           tn3270*keysym.0xFFC1:      \e4
-           tn3270*keysym.0xFFC2:      \e5
-           tn3270*keysym.0xFFC3:      \e6
-           tn3270*keysym.0xFFC4:      \e7
-           tn3270*keysym.0xFFC5:      \e8
-           tn3270*keysym.0xFFC6:      \e9
-           tn3270*keysym.0xFFC7:      \e0
-           tn3270*keysym.0xFFC8:      \e-
-           tn3270*keysym.0xFFC9:      \e=
-
-           ! map Prior/Next to F7/F8
-           tn3270*keysym.0xFF55:      \e7
-           tn3270*keysym.0xFF56:      \e8
+        associated with keysyms.
+
+        Here's an example for a URxvt session started using `rxvt -name
+        URxvt'
+
+                URxvt*keysym.Home:          \e[1~
+                URxvt*keysym.End:           \e[4~
+                URxvt*keysym.C-apostrophe:  \e<C-'>
+                URxvt*keysym.C-slash:       \e<C-/>
+                URxvt*keysym.C-semicolon:   \e<C-;>
+                URxvt*keysym.C-grave:       \e<C-`>
+                URxvt*keysym.C-comma:       \e<C-,>
+                URxvt*keysym.C-period:      \e<C-.>
+                URxvt*keysym.C-0x60:        \e<C-`>
+                URxvt*keysym.C-Tab:         \e<C-Tab>
+                URxvt*keysym.C-Return:      \e<C-Return>
+                URxvt*keysym.S-Return:      \e<S-Return>
+                URxvt*keysym.S-space:       \e<S-Space>
+                URxvt*keysym.M-Up:          \e<M-Up>
+                URxvt*keysym.M-Down:        \e<M-Down>
+                URxvt*keysym.M-Left:        \e<M-Left>
+                URxvt*keysym.M-Right:       \e<M-Right>
+                URxvt*keysym.M-C-0:         list.0123456789.\e<M-C-.>
+                URxvt*keysym.M-C-a:         list.abcdefghijklmnopqrstuvwxyz.\033<M-C-.>
+                URxvt*keysym.F12:           proto:\033]701;zh_CN.GBK\007
 
     I'm using keyboard model XXX that has extra Prior/Next/Insert keys. How
     do I make use of them? For example, the Sun Keyboard type 4 has the
@@ -1729,6 +1711,20 @@ CONFIGURE OPTIONS
         to have. Normally you want this, but for very small binaries you may
         want to disable this.
 
+        A non-exhaustive list of features enabled by "--enable-frills"
+        (possibly in combination with other switches) is:
+
+          MWM-hints
+          seperate underline colour
+          settable border widths and borderless switch
+          settable extra linespacing
+          extra window properties (e.g. UTF-8 window names and PID)
+          iso-14755-2 and -3, and visual feedback
+          backindex and forwardindex escape sequence
+          window op and locale change escape sequences
+          tripleclickwords
+          settable insecure mode
+
     --enable-iso14755
         Enable extended ISO 14755 support (see rxvt(1), or doc/rxvt.1.txt).
         Basic support (section 5.1) is enabled by "--enable-frills", while
index 0aeee49..a3f38f4 100644 (file)
  * with various KeySyms (0xFF00 - 0xFFFF).
  * Only works with the default hand-rolled resources.
  */
-#ifndef NO_RESOURCES
+#if !NO_RESOURCES && ENABLE_FRILLS
 # define KEYSYM_RESOURCE
 #endif
 
diff --git a/src/keyboard.C b/src/keyboard.C
new file mode 100644 (file)
index 0000000..5491125
--- /dev/null
@@ -0,0 +1,501 @@
+#include "../config.h"
+#include "rxvt.h"
+#include "keyboard.h"
+#include "command.h"
+#include <string.h>
+#include <X11/X.h>
+
+#ifdef KEYSYM_RESOURCE
+
+////////////////////////////////////////////////////////////////////////////////
+// default keycode translation map and keyevent handlers
+keyevent_handler keysym_translator;
+keyevent_handler keyrange_translator;
+keyevent_handler keyrange_translator_meta8;
+keyevent_handler keylist_translator;
+
+keysym_t keyboard_manager::stock_keymap_[] =
+{
+  /* examples */
+  /*        keysym,                state, range,                   handler,             str*/
+//{XK_ISO_Left_Tab,                    0,     1,         keysym_translator,           "\033[Z"},
+//{            'a',                    0,    26, keyrange_translator_meta8,           "a" "%c"},
+//{            'a',          ControlMask,    26, keyrange_translator_meta8,          "\ 1" "%c"},
+//{        XK_Left,                    0,     4,        keylist_translator,   "DACBZ" "\033[Z"},
+//{        XK_Left,            ShiftMask,     4,        keylist_translator,   "dacbZ" "\033[Z"},
+//{        XK_Left,          ControlMask,     4,        keylist_translator,   "dacbZ" "\033OZ"},
+//{         XK_Tab,          ControlMask,     1,         keysym_translator,      "\033<C-Tab>"},
+//{  XK_apostrophe,          ControlMask,     1,         keysym_translator,        "\033<C-'>"},
+//{       XK_slash,          ControlMask,     1,         keysym_translator,        "\033<C-/>"},
+//{   XK_semicolon,          ControlMask,     1,         keysym_translator,        "\033<C-;>"},
+//{       XK_grave,          ControlMask,     1,         keysym_translator,        "\033<C-`>"},
+//{       XK_comma,          ControlMask,     1,         keysym_translator,     "\033<C-\054>"},
+//{      XK_Return,          ControlMask,     1,         keysym_translator,    "\033<C-Return>"},
+//{      XK_Return,            ShiftMask,     1,         keysym_translator,    "\033<S-Return>"},
+//{            ' ',            ShiftMask,     1,         keysym_translator,    "\033<S-Space>"},
+//{            '.',          ControlMask,     1,         keysym_translator,        "\033<C-.>"},
+//{            '0',          ControlMask,    10,       keyrange_translator,   "0" "\033<C-%c>"},
+//{            '0', MetaMask|ControlMask,    10,       keyrange_translator, "0" "\033<M-C-%c>"},
+//{            'a', MetaMask|ControlMask,    26,       keyrange_translator, "a" "\033<M-C-%c>"},
+};
+
+void output_string (rxvt_term *rt,
+                    const char *str)
+{
+  assert (rt && str);
+  if (strncmp (str, "proto:", 6) == 0)
+    rt->cmd_write ((unsigned char*)str + 6, strlen (str) - 6);
+  else
+    rt->tt_write ((unsigned char*)str, strlen (str));
+}
+
+void output_string_meta8 (rxvt_term *rt,
+                          unsigned int state,
+                          char buf[],
+                          int buflen)
+{
+  if (state & rt->ModMetaMask)
+    {
+#ifdef META8_OPTION
+      if(rt->meta_char == 0x80) /* set 8-bit on */
+        {
+          for (char *ch = buf; ch < buf + buflen; ch++)
+            *ch |= 0x80;
+        }
+      else if(rt->meta_char == C0_ESC) /* escape prefix */
+#endif
+        {
+          const unsigned char ch = C0_ESC;
+          rt->tt_write (&ch, 1);
+        }
+    }
+
+  rt->tt_write ((unsigned char*)buf, buflen);
+}
+
+int format_keyrange_string (keysym_t *key,
+                            KeySym keysym,
+                            char buf[],
+                            int bufsize)
+{
+  int len;
+
+  assert (key->str);
+  len = snprintf (buf, bufsize, key->str + 1,
+                  keysym - key->keysym + (int)(key->str[0]));
+  if (len >= bufsize)
+    {
+      fprintf (stderr, "buffer overflowed!\n");
+      buf[bufsize-1] = '\0';
+    }
+  else if (len < 0)
+    {
+      perror("keyrange_translator()");
+    }
+
+  return len;
+}
+
+bool format_keylist_string (keysym_t *key,
+                            KeySym keysym,
+                            char buf[],
+                            int bufsize)
+{
+  char *p;
+
+  assert (key->str);
+  strncpy (buf, key->str + key->range + 1, bufsize);
+  buf[bufsize-1] = '\0';
+
+  p = strchr (buf, key->str[key->range]);
+  if (p)
+    {
+      *p = key->str[keysym - key->keysym];
+      return true;
+    }
+  else
+    {
+      fprintf (stderr, "invalid str for keylist_translator()!\n");
+      return false;
+    }
+}
+
+/////////////////////////////////////////////////////////////////
+void keysym_translator (rxvt_term *rt,
+                        keysym_t *key,
+                        KeySym keysym,
+                        unsigned int state)
+{
+  output_string (rt, key->str);
+}
+
+void keyrange_translator (rxvt_term *rt,
+                          keysym_t *key,
+                          KeySym keysym,
+                          unsigned int state)
+{
+  char buf[STRING_MAX];
+
+  if (format_keyrange_string (key, keysym, buf, sizeof(buf)) > 0)
+    output_string (rt, buf);
+}
+
+void keyrange_translator_meta8 (rxvt_term *rt,
+                                keysym_t *key,
+                                KeySym keysym,
+                                unsigned int state)
+{
+  int len;
+  char buf[STRING_MAX];
+
+  len = format_keyrange_string (key, keysym, buf, sizeof(buf));
+  if (len > 0)
+    output_string_meta8 (rt, state, buf, len);
+}
+
+void keylist_translator (rxvt_term *rt,
+                         keysym_t *key,
+                         KeySym keysym,
+                         unsigned int state)
+{
+  char buf[STRING_MAX];
+
+  format_keylist_string (key, keysym, buf, sizeof(buf));
+  output_string (rt, buf);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// return: #bits of '1'
+int
+bitcount (unsigned int n)
+{
+  int i;
+  for (i = 0; n; ++i, n &= (n - 1));
+  return i;
+}
+
+// return: priority_of_a - priority_of_b
+int
+compare_priority (keysym_t *a, keysym_t *b)
+{
+  assert (a && b);
+
+  // (the more '1's in state; the less range): the greater priority
+  int ca = bitcount (a->state/* & AllModMask*/);
+  int cb = bitcount (b->state/* & AllModMask*/);
+  if (ca != cb)
+    return ca - cb;
+//else if (a->state != b->state) // this behavior is to be disscussed
+//  return b->state - a->state;
+  else
+    return b->range - a->range;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+keyboard_manager::keyboard_manager (rxvt_term *rt)
+  :term_(rt)
+{
+  keymap_.reserve (256);
+  hash_[0] = 1; // hash_[0] != 0 indicates uninitialized data
+}
+
+keyboard_manager::~keyboard_manager ()
+{
+  clear ();
+}
+
+void
+keyboard_manager::clear ()
+{
+  keymap_.clear ();
+  hash_[0] = 2;
+
+  for(unsigned int i = 0;i < user_translations_.size();++i)
+    {
+      delete[] user_translations_[i];
+      user_translations_[i] = 0;
+    }
+
+  for(unsigned int i = 0;i < user_keymap_.size();++i)
+    {
+      delete user_keymap_[i];
+      user_keymap_[i] = 0;
+    }
+
+  user_keymap_.clear();
+  user_translations_.clear();
+}
+
+// a wrapper for register_keymap,
+// so that outside codes don't have to know so much details.
+//
+// the string 'trans' is copied to an internal managed buffer,
+// so the caller can free memory of 'trans' at any time.
+void
+keyboard_manager::register_user_translation (KeySym keysym,
+                                             unsigned int state,
+                                             const char *trans)
+{
+  assert(trans);
+
+  keysym_t *key = new keysym_t;
+  const char *translation = new char[1+strlen(trans)];
+
+  if(key && translation)
+    {
+      key->keysym = keysym;
+      key->state = state;
+      key->range = 1;
+      key->str = translation;
+
+      if (strncmp (trans, "list", 4) == 0)
+        {
+          const char *p = &trans[4];
+          if (*p && (p = strchr (p+1, *p)))
+            if ((p - trans - 5 > 1) && strchr (p+1, *p))
+              {
+                strcpy (translation, trans+5);
+                key->range = p - trans - 5;
+                key->handler = keylist_translator;
+              }
+        }
+      if (key->range == 1)
+        {
+          strcpy (translation, trans);
+          key->handler = keysym_translator;
+        }
+
+      user_keymap_.push_back (key);
+      user_translations_.push_back (translation);
+      register_keymap (key);
+    }
+  else
+    {
+      delete key;
+      delete[] translation;
+      rxvt_fatal ("out of memory, aborting.\n");
+    }
+}
+
+void
+keyboard_manager::register_keymap (keysym_t *key)
+{
+  assert (key);
+  assert (key->handler);
+  assert (key->range >= 1);
+
+  if (keymap_.size () == keymap_.capacity ())
+    keymap_.reserve (keymap_.size () * 2);
+
+  keymap_.push_back (key);
+  hash_[0] = 3;
+}
+
+void
+keyboard_manager::register_done ()
+{
+  unsigned int i, n = sizeof(stock_keymap_)/sizeof(keysym_t);
+
+  if(keymap_.back() != &stock_keymap_[n-1])
+    for(i = 0;i < n;++i)
+      register_keymap(&stock_keymap_[i]);
+
+  purge_duplicate_keymap ();
+
+  for (i = 0; i < keymap_.size(); ++i)
+    {
+      keysym_t *key = keymap_[i];
+
+      assert (bitcount (term_->ModMetaMask) == 1
+              && "call me after ModMetaMask was set!");
+      if (key->state & MetaMask)
+        {
+          //key->state &= ~MetaMask;
+          key->state |= term_->ModMetaMask;
+        }
+
+      assert (bitcount (term_->ModNumLockMask) == 1
+              && "call me after ModNumLockMask was set!");
+      if (key->state & NumLockMask)
+        {
+          //key->state &= ~NumLockMask;
+          key->state |= term_->ModNumLockMask;
+        }
+    }
+
+  setup_hash ();
+}
+
+bool keyboard_manager::dispatch (KeySym keysym, unsigned int state)
+{
+  assert(hash_[0] == 0 && "register_done() need to be called");
+
+  int index = find_keysym (keysym, state);
+
+  if (index >= 0)
+    {
+      assert (term_ && keymap_[index] && keymap_[index]->handler);
+      keymap_[index]->handler (term_, keymap_[index], keysym, state);
+      return true;
+    }
+  else
+  {
+    // fprintf(stderr,"[%x:%x]",state,keysym);
+    return false;
+  }
+}
+
+// purge duplicate keymap_ entries
+void
+keyboard_manager::purge_duplicate_keymap ()
+{
+  for (unsigned int i = 0; i < keymap_.size (); ++i)
+    {
+      for (unsigned int j = 0; j < i; ++j)
+        {
+          if (keymap_[i] == keymap_[j])
+            {
+              while (keymap_[i] == keymap_.back ())
+                keymap_.pop_back ();
+              if (i < keymap_.size ())
+                {
+                  keymap_[i] = keymap_.back ();
+                  keymap_.pop_back ();
+                }
+              break;
+            }
+        }
+    }
+}
+
+void
+keyboard_manager::setup_hash ()
+{
+  unsigned int i, index, hashkey;
+  vector<keysym_t *> sorted_keymap;
+  u16 hash_budget_size[KEYSYM_HASH_BUDGETS];     // size of each budget
+  u16 hash_budget_counter[KEYSYM_HASH_BUDGETS];  // #elements in each budget
+
+  memset (hash_budget_size, 0, sizeof (hash_budget_size));
+  memset (hash_budget_counter, 0, sizeof (hash_budget_counter));
+
+  // count keysyms for corresponding hash budgets
+  for (i = 0; i < keymap_.size (); ++i)
+    {
+      assert (keymap_[i]);
+      hashkey = (keymap_[i]->keysym & KEYSYM_HASH_MASK);
+      ++hash_budget_size[hashkey];
+    }
+
+  // keysym A with range>1 is counted one more time for
+  // every keysym B lies in its range
+  for (i = 0; i < keymap_.size (); ++i)
+    {
+      if (keymap_[i]->range > 1)
+        {
+          for (int j = min (keymap_[i]->range, KEYSYM_HASH_BUDGETS) - 1;j > 0; --j)
+            {
+              hashkey = ((keymap_[i]->keysym + j) & KEYSYM_HASH_MASK);
+              if (hash_budget_size[hashkey])
+                ++hash_budget_size[hashkey];
+            }
+        }
+    }
+
+  // now we know the size of each budget
+  // compute the index of each budget
+  hash_[0] = 0;
+  for (index = 0,i = 1; i < KEYSYM_HASH_BUDGETS; ++i)
+    {
+      index += hash_budget_size[i-1];
+      hash_[i] = (hash_budget_size[i] ? index : hash_[i-1]);
+    }
+  // and allocate just enough space
+  //sorted_keymap.reserve (hash_[i - 1] + hash_budget_size[i - 1]);
+  sorted_keymap.insert (sorted_keymap.begin(), index + hash_budget_size[i - 1], 0);
+
+  // fill in sorted_keymap
+  // it is sorted in each budget
+  for (i = 0; i < keymap_.size (); ++i)
+    {
+      for (int j = min (keymap_[i]->range, KEYSYM_HASH_BUDGETS) - 1;j >= 0; --j)
+        {
+          hashkey = ((keymap_[i]->keysym + j) & KEYSYM_HASH_MASK);
+          if (hash_budget_size[hashkey])
+            {
+              index = hash_[hashkey] + hash_budget_counter[hashkey];
+              while (index > hash_[hashkey] &&
+                     compare_priority (keymap_[i],
+                                       sorted_keymap[index - 1]) > 0)
+                {
+                  sorted_keymap[index] = sorted_keymap[index - 1];
+                  --index;
+                }
+              sorted_keymap[index] = keymap_[i];
+              ++hash_budget_counter[hashkey];
+            }
+        }
+    }
+
+  keymap_.swap (sorted_keymap);
+
+#if defined (DEBUG_STRICT) || defined (DEBUG_KEYBOARD)
+  // check for invariants
+  for (i = 0; i < KEYSYM_HASH_BUDGETS; ++i)
+    {
+      index = hash_[i];
+      for (int j = 0; j < hash_budget_size[i]; ++j)
+        {
+          if (keymap_[index + j]->range == 1)
+            assert (i == (keymap_[index + j]->keysym & KEYSYM_HASH_MASK));
+          if (j)
+            assert (compare_priority (keymap_[index + j - 1],
+                                      keymap_[index + j]) >= 0);
+        }
+    }
+
+  // this should be able to detect most possible bugs
+  for (i = 0; i < sorted_keymap.size (); ++i)
+    {
+      keysym_t *a = sorted_keymap[i];
+      for (int j = 0; j < a->range; ++j)
+        {
+          int index = find_keysym (a->keysym + j, a->state & AllModMask);
+          assert (index >= 0);
+          keysym_t *b = keymap_[index];
+          assert (i == (signed)index || // the normally expected result
+              (a->keysym + j) >= b->keysym &&
+              (a->keysym + j) <= (b->keysym + b->range) &&
+              compare_priority (a, b) <= 0); // is effectively the same
+        }
+    }
+#endif
+}
+
+int
+keyboard_manager::find_keysym (KeySym keysym, unsigned int state)
+{
+  int hashkey = (keysym & KEYSYM_HASH_MASK);
+  unsigned int index = hash_[hashkey];
+
+  for (;index < keymap_.size(); ++index)
+    {
+      keysym_t *key = keymap_[index];
+      assert (key);
+      if (key->keysym <= keysym &&
+          key->keysym + key->range > keysym &&
+          // match only the specified bits in state and ignore others
+          (key->state & (unsigned int)AllModMask) == (key->state & state))
+        {
+          return index;
+        }
+      else if (key->keysym > keysym &&
+               key->range == 1)
+        return -1;
+    }
+
+  return -1;
+}
+
+#endif /* KEYSYM_RESOURCE */
+// vim:et:ts=2:sw=2
diff --git a/src/keyboard.h b/src/keyboard.h
new file mode 100644 (file)
index 0000000..75b837a
--- /dev/null
@@ -0,0 +1,75 @@
+#ifndef KEYBOARD_H_
+#define KEYBOARD_H_
+
+#include "feature.h"
+#include "rxvtutil.h"
+
+#ifdef KEYSYM_RESOURCE
+
+#define KEYSYM_HASH_BITS        9       /* lowest #bits of keysym is used as hash key */
+#define KEYSYM_HASH_BUDGETS     (1<<KEYSYM_HASH_BITS)
+#define KEYSYM_HASH_MASK        (KEYSYM_HASH_BUDGETS-1)
+
+#define MetaMask                0x0100
+#define NumLockMask             0x0200
+#define AllModMask              (ShiftMask | LockMask | ControlMask \
+                                | Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask)
+
+#if (AllModMask & (MetaMask | NumLockMask)) != 0
+#error redefine MetaMask or NumLockMask!
+#endif
+
+struct rxvt_term;
+struct keysym_t;
+typedef void (keyevent_handler) (rxvt_term *rt,
+                                 keysym_t *key,
+                                 KeySym keysym,
+                                 unsigned int state);
+typedef unsigned short u16;
+
+struct keysym_t
+{
+  KeySym            keysym;
+  /* only the lower 8 bits of state are used for matching according to X.h */
+  /* the higher bits are preserved for Meta/NumLock keys */
+  /* which are mapped to corresponding lower bits at register time */
+  u16               state;    /* indicates each modifiers' DOWN/UP status         */
+  u16               range;    /* =1: single keysym; >1: a of range keysyms        */
+  keyevent_handler *handler;  /* event handler                                    */
+  const char       *str;      /* would normally be a keycode translation          */
+};
+
+
+class keyboard_manager
+{
+public:
+  keyboard_manager (rxvt_term *rt);
+  ~keyboard_manager ();
+
+  void clear ();
+  void register_user_translation (KeySym keysym, unsigned int state, const char *trans);
+  void register_done ();        // call this to make newly registered keymaps take effect
+  bool dispatch (KeySym keysym, unsigned int state);
+
+private:
+  void register_keymap (keysym_t *key);
+  void purge_duplicate_keymap ();
+  void setup_hash ();
+  int find_keysym (KeySym keysym, unsigned int state);
+
+private:
+  rxvt_term * const term_;
+
+  u16 hash_[KEYSYM_HASH_BUDGETS];               //
+  vector<keysym_t *> keymap_;
+
+  // stock keymaps are all static data
+  static keysym_t stock_keymap_[];
+  // user keymaps and their .string are dynamicly allocated and freed
+  vector<keysym_t *> user_keymap_;
+  vector<const char *> user_translations_;
+};
+
+#endif /* KEYSYM_RESOURCE */
+#endif /* KEYBOARD_H_ */
+// vim:et:ts=2:sw=2
index fd063dd..9e3bdf5 100644 (file)
@@ -18,6 +18,9 @@ template<typename T, typename U>
 static inline T min (T a, U b) { return a < b ? a : (T)b; }
 template<typename T, typename U>
 static inline T max (T a, U b) { return a > b ? a : (T)b; }
+template<typename T>
+static inline void swap (T& a, T& b) { T t=a; a=b; b=t; }
+
 
 struct zero_initialized {
   void *operator new (size_t s);
@@ -42,72 +45,72 @@ private:
 public:
     const_iterator begin () const
     {
-       return &_buf[0];
+        return &_buf[0];
     }
     iterator begin ()
     {
-       return &_buf[0];
+        return &_buf[0];
     }
     const_iterator end () const
     {
-       return &_buf[_last];
+        return &_buf[_last];
     }
     iterator end ()
     {
-       return &_buf[_last];
+        return &_buf[_last];
     }
     size_type capacity () const
     {
-       return _size;
+        return _size;
     }
     size_type size () const
     {
-       return _last;
+        return _last;
     }
 
 private:
     static T *alloc (size_type n)
     {
-       return (T *)::operator new ((size_t) (n * sizeof (T)));
+        return (T *)::operator new ((size_t) (n * sizeof (T)));
     }
     static void dealloc (T *buf)
     {
-       if (buf)
-           ::operator delete (buf);
+        if (buf)
+            ::operator delete (buf);
     }
 
     void reserve (iterator where, size_type n)
     {
-       if (_last + n <= _size) {
-           memmove (where+n, where, (end ()-where)*sizeof (T));
-       } else {
-           size_type sz = _last+n;
-           sz = (_size == 0) ? max (sz, 5) : max (sz, 2*_size);
-           T *nbuf = alloc (sz);
-           if (_buf) {
-               memcpy (nbuf, begin (), (where-begin ())*sizeof (T));
-               memcpy (nbuf + (where-begin ()) + n, where,
-                       (end ()-where)*sizeof (T));
-               dealloc (_buf);
-           }
-           _buf = nbuf;
-           _size = sz;
-       }
+        if (_last + n <= _size) {
+            memmove (where+n, where, (end ()-where)*sizeof (T));
+        } else {
+            size_type sz = _last+n;
+            sz = (_size == 0) ? max (sz, 5) : max (sz, 2*_size);
+            T *nbuf = alloc (sz);
+            if (_buf) {
+                memcpy (nbuf, begin (), (where-begin ())*sizeof (T));
+                memcpy (nbuf + (where-begin ()) + n, where,
+                        (end ()-where)*sizeof (T));
+                dealloc (_buf);
+            }
+            _buf = nbuf;
+            _size = sz;
+        }
     }
 
 public:
     void reserve (size_type sz)
     {
-       if (_size < sz) {
-           sz = (_size == 0) ? max (sz, 5) : max (sz, 2*_size);
-           T *nbuf = alloc (sz);
-           if (_buf) {
-               memcpy (nbuf, begin (), size ()*sizeof (T));
-               dealloc (_buf);
-           }
-           _buf = nbuf;
-           _size = sz;
-       }
+        if (_size < sz) {
+            sz = (_size == 0) ? max (sz, 5) : max (sz, 2*_size);
+            T *nbuf = alloc (sz);
+            if (_buf) {
+                memcpy (nbuf, begin (), size ()*sizeof (T));
+                dealloc (_buf);
+            }
+            _buf = nbuf;
+            _size = sz;
+        }
     }
     simplevec ()
     : _last(0), _size(0), _buf(0)
@@ -116,146 +119,152 @@ public:
     simplevec (size_type n, const T& t = T ())
     : _last(0), _size(0), _buf(0)
     {
-       insert (begin (), n, t);
+        insert (begin (), n, t);
     }
     simplevec (const_iterator first, const_iterator last)
     : _last(0), _size(0), _buf(0)
     {
-       insert (begin (), first, last);
+        insert (begin (), first, last);
     }
     simplevec (const simplevec<T> &v)
     : _last(0), _size(0), _buf(0)
     {
-       reserve (v._last);
-       memcpy (_buf, v.begin (), v.size ()*sizeof (T));
-       _last = v._last;
+        reserve (v._last);
+        memcpy (_buf, v.begin (), v.size ()*sizeof (T));
+        _last = v._last;
     }
     simplevec<T> &operator= (const simplevec<T> &v)
     {
-       if (this != &v) {
-           _last = 0;
-           reserve (v._last);
-           memcpy (_buf, v.begin (), v.size ()*sizeof (T));
-           _last = v._last;
-       }
+        if (this != &v) {
+            _last = 0;
+            reserve (v._last);
+            memcpy (_buf, v.begin (), v.size ()*sizeof (T));
+            _last = v._last;
+        }
         return *this;
     }
     ~simplevec ()
     {
-       dealloc (_buf);
+        dealloc (_buf);
     }
     const T &front () const
     {
-       //ministl_assert (size () > 0);
-       return _buf[0];
+        //ministl_assert (size () > 0);
+        return _buf[0];
     }
     T &front ()
     {
-       //ministl_assert (size () > 0);
-       return _buf[0];
+        //ministl_assert (size () > 0);
+        return _buf[0];
     }
     const T &back () const
     {
-       //ministl_assert (size () > 0);
-       return _buf[_last-1];
+        //ministl_assert (size () > 0);
+        return _buf[_last-1];
     }
     T &back ()
     {
-       //ministl_assert (size () > 0);
-       return _buf[_last-1];
+        //ministl_assert (size () > 0);
+        return _buf[_last-1];
     }
     bool empty () const
     {
-       return _last == 0;
+        return _last == 0;
     }
     void clear ()
     {
-       _last = 0;
+        _last = 0;
     }
     void push_back (const T &t)
     {
-       reserve (_last+1);
-       *end () = t;
-       ++_last;
+        reserve (_last+1);
+        *end () = t;
+        ++_last;
     }
     void push_back (T &t)
     {
-       reserve (_last+1);
-       *end () = t;
-       ++_last;
+        reserve (_last+1);
+        *end () = t;
+        ++_last;
     }
     void pop_back ()
     {
-       //ministl_assert (size () > 0);
-       --_last;
+        //ministl_assert (size () > 0);
+        --_last;
     }
     const T &operator[] (size_type idx) const
     {
-       //ministl_assert (idx < size ());
-       return _buf[idx];
+        //ministl_assert (idx < size ());
+        return _buf[idx];
     }
     T &operator[] (size_type idx)
     {
-       //ministl_assert (idx < size ());
-       return _buf[idx];
+        //ministl_assert (idx < size ());
+        return _buf[idx];
     }
     iterator insert (iterator pos, const T &t)
     {
-       //ministl_assert (pos <= end ());
-       long at = pos - begin ();
-       reserve (pos, 1);
-       pos = begin ()+at;
-       *pos = t;
-       ++_last;
-       return pos;
+        //ministl_assert (pos <= end ());
+        long at = pos - begin ();
+        reserve (pos, 1);
+        pos = begin ()+at;
+        *pos = t;
+        ++_last;
+        return pos;
     }
     iterator insert (iterator pos, const_iterator first, const_iterator last)
     {
         //ministl_assert (pos <= end ());
-       long n = last - first;
-       long at = pos - begin ();
-       if (n > 0) {
-           reserve (pos, n);
-           pos = begin ()+at;
-           memcpy (pos, first, (last-first)*sizeof (T));
-           _last += n;
-       }
-       return pos;
+        long n = last - first;
+        long at = pos - begin ();
+        if (n > 0) {
+            reserve (pos, n);
+            pos = begin ()+at;
+            memcpy (pos, first, (last-first)*sizeof (T));
+            _last += n;
+        }
+        return pos;
     }
     iterator insert (iterator pos, size_type n, const T &t)
     {
         //ministl_assert (pos <= end ());
-       long at = pos - begin ();
-       if (n > 0) {
-           reserve (pos, n);
-           pos = begin ()+at;
-           for (int i = 0; i < n; ++i)
-               pos[i] = t;
-           _last += n;
-       }
-       return pos;
+        long at = pos - begin ();
+        if (n > 0) {
+            reserve (pos, n);
+            pos = begin ()+at;
+            for (int i = 0; i < n; ++i)
+                pos[i] = t;
+            _last += n;
+        }
+        return pos;
     }
     void erase (iterator first, iterator last)
     {
-       if (last != first) {
-           memmove (first, last, (end ()-last)*sizeof (T));
-           _last -= last - first;
-       }
+        if (last != first) {
+            memmove (first, last, (end ()-last)*sizeof (T));
+            _last -= last - first;
+        }
     }
     void erase (iterator pos)
     {
         if (pos != end ()) {
-           memmove (pos, pos+1, (end ()- (pos+1))*sizeof (T));
+            memmove (pos, pos+1, (end ()- (pos+1))*sizeof (T));
             --_last;
         }
     }
+    void swap (simplevec<T> &t)
+    {
+        ::swap(_last, t._last);
+        ::swap(_size, t._size);
+        ::swap(_buf, t._buf);
+    }
 };
 
 template<class T>
 bool operator== (const simplevec<T> &v1, const simplevec<T> &v2)
 {
     if (v1.size () != v2.size ())
-       return false;
+        return false;
     return !v1.size () || !memcmp (&v1[0], &v2[0], v1.size ()*sizeof (T));
 }
 
@@ -265,9 +274,9 @@ bool operator< (const simplevec<T> &v1, const simplevec<T> &v2)
     unsigned long minlast = min (v1.size (), v2.size ());
     for (unsigned long i = 0; i < minlast; ++i) {
         if (v1[i] < v2[i])
-           return true;
-       if (v2[i] < v1[i])
-           return false;
+            return true;
+        if (v2[i] < v1[i])
+            return false;
     }
     return v1.size () < v2.size ();
 }