diff --git a/joe/kbd.c b/joe/kbd.c index d11bd9a0..cadf3527 100644 --- a/joe/kbd.c +++ b/joe/kbd.c @@ -85,6 +85,10 @@ static int keyval(char *s) default: return s[1] & 0x1F; } + else if (s[0] == '^' && s[1] == '^' && s[2] >= '@' && s[2] <= 127 && !s[3]) + return KEY_CTRLCAPLOWER | (s[2] & 0x1F); + else if (s[0] == '^' && s[1] == '@' && (s[2] & 0xDF) >= 'A' && (s[2] & 0xDF) <= 'Z' && !s[3]) + return KEY_CAPLOWER | (s[2] & 0x1F); else if ((s[0] == 'S' || s[0] == 's') && (s[1] == 'P' || s[1] == 'p') && !s[2]) return ' '; @@ -163,6 +167,8 @@ static char *range(char *seq, int *vv, int *ww) return NULL; seq[x] = c; /* Restore the space or 0 */ for (seq += x; *seq == ' '; ++seq) ; /* Skip over spaces */ + if (v >= KEY_CTRLCAPLOWER && v <= KEY_CAPLOWER_LAST) + goto done; /* Check for 'TO ' */ if ((seq[0] == 'T' || seq[0] == 't') && (seq[1] == 'O' || seq[1] == 'o') && seq[2] == ' ') { @@ -180,6 +186,7 @@ static char *range(char *seq, int *vv, int *ww) if (v > w) return NULL; + done: *vv = v; *ww = w; return seq; @@ -296,9 +303,29 @@ static KMAP *kbuild(CAP *cap, KMAP *kmap, char *seq, MACRO *bind, int *err, cons if (!kmap) kmap = mkkmap(); /* Create new keymap if 'kmap' was NULL */ - /* Make bindings between v and w */ - if (v <= w) { + if (v >= KEY_CTRLCAPLOWER && v <= KEY_CAPLOWER_LAST) { + /* Make two or three bindings, e.g. Ctrl-A (if three), 'A' and 'a' */ + int k = v >= KEY_CAPLOWER ? 64 : 0; + v &= 31; + for (; k <= 96; k += 32) { + if (*seq) { + KMAP *old; + if (k == 32) + continue; + old = (KMAP *)interval_lookup(kmap->src, NULL, k|v); + if (!old || !old->what) { + kmap->src = interval_add(kmap->src, k|v, k|v, kbuild(cap, NULL, seq, bind, err, NULL, 0)); + ++kmap->src_version; + } else + kbuild(cap, old, seq, bind, err, NULL, 0); + } else { + kmap->src = interval_add(kmap->src, k|v, k|v, bind); + ++kmap->src_version; + } + } + } else if (v <= w) { if (*seq || seql) { + /* Make bindings from a looked-up sequence */ KMAP *old = (KMAP *)interval_lookup(kmap->src, NULL, v); if (!old || !old->what) { kmap->src = interval_add(kmap->src, v, w, kbuild(cap, NULL, seq, bind, err, capseq, seql)); @@ -306,6 +333,7 @@ static KMAP *kbuild(CAP *cap, KMAP *kmap, char *seq, MACRO *bind, int *err, cons } else kbuild(cap, old, seq, bind, err, capseq, seql); } else { + /* Make bindings between v and w */ kmap->src = interval_add(kmap->src, v, w, bind); ++kmap->src_version; } @@ -348,8 +376,18 @@ int kdel(KMAP *kmap, char *seq) if (!seq) return -1; - /* Clear bindings between v and w */ - if (v <= w) { + if (v >= KEY_CTRLCAPLOWER && v <= KEY_CTRLCAPLOWER_LAST) { + /* Clear three codes, e.g Ctrl-A, 'A' and 'a' */ + char s[2] = {}; + char c = (char)v & 31; + s[0] = c; + kdel(kmap, s); + s[0] = c | 64; + kdel(kmap, s); + s[0] = c | 96; + kdel(kmap, s); + } else if (v <= w) { + /* Clear bindings between v and w */ if (*seq) { KMAP *old = (KMAP *)interval_lookup(kmap->src, NULL, v); if (old->what == 1) { diff --git a/joe/types.h b/joe/types.h index f4820881..db25b021 100644 --- a/joe/types.h +++ b/joe/types.h @@ -256,6 +256,13 @@ typedef int pid_t; #define KEY_MIDDLEUP 0x10000B #define KEY_MIDDLEDOWN 0x10000C +/* This one's for letters which may be modified with Ctrl or Shift: three-in-one */ +#define KEY_CTRLCAPLOWER 0x110000 +#define KEY_CTRLCAPLOWER_LAST (KEY_CTRLCAPLOWER + 31) +/* And just for upper and lower case: two-in-one */ +#define KEY_CAPLOWER (KEY_CTRLCAPLOWER + 32) +#define KEY_CAPLOWER_LAST (KEY_CAPLOWER + 31) + #define stdsiz 8192 #define FITHEIGHT 4 /* Minimum height needed for new text windows */ #define FITMIN 2 /* Minimum main window height */ diff --git a/rc/joerc.in b/rc/joerc.in index f08ea56e..3a9bc36f 100644 --- a/rc/joerc.in +++ b/rc/joerc.in @@ -738,6 +738,9 @@ mode,"syntax_debug",rtn,"3",rtn,retype % % Syntax debug: full (3) Use U+12345 for specific unicode character Use ^@ through ^_ and ^? for Ctrl chars + Use ^^A to ^^Z to represent a choice between the upper-case letter, the + lower-case letter and the corresponding Ctrl char + Use ^@A to ^@Z to do similarly without the Ctrl char Use SP for space Use a TO b to generate a range of characters Use MDOWN, MDRAG, MUP, M2DOWN, M2DRAG, M2UP, M3DOWN, M3DRAG, M3UP for mouse @@ -786,32 +789,21 @@ mode,"syntax_debug",rtn,"3",rtn,retype % % Syntax debug: full (3) :windows Bindings common to all windows type U+0 TO U+10FFFF abort ^C Abort window -abort ^K Q -abort ^K ^Q -abort ^K q +abort ^K ^^Q querysave,query,killjoe ^K Q Query to save files, then exit querysave,query,killjoe ^K ^Q querysave,query,killjoe ^K q arg ^K \ Repeat next command -explode ^K I Show all windows or show only one window -explode ^K ^I +explode ^K ^^I Show all windows or show only one window explode ^K ^[ [ 1 0 5 ; 5 u -explode ^K i -help ^K H Help menu -help ^K ^H -help ^K h +help ^K ^^H Help menu hnext ^[ . Next help window hprev ^[ , Previous help window -math ^[ m Calculator -math ^[ M Calculator +math ^[ ^@m Calculator math ^[ ^M Calculator math ^[ ^[ [ 1 0 9 ; 5 u -msg ^[ h Display a message -msg ^[ H Display a message -msg ^[ ^H Display a message -nextw ^K N Goto next window -nextw ^K ^N -nextw ^K n +msg ^[ ^^H Display a message +nextw ^K ^^N Goto next window pgdn .kN Screen down pgdn ^V pgdn ^[ [ 6 ~ @@ -821,18 +813,14 @@ pgup ^U pgup ^[ [ 5 ~ pgup ^# T play ^K 0 TO 9 Execute macro -prevw ^K P Goto previous window -prevw ^K ^P -prevw ^K p +prevw ^K ^^P Goto previous window query ^K ? Macro query insert record ^K [ Record a macro retype ^R Refresh screen recenter ^R Recenter and refresh screen rtn ^M Return rtn ^[ [ 1 0 9 ; 5 u -shell ^K Z Shell escape -shell ^K ^Z -shell ^K z +shell ^K ^^Z Shell escape stop ^K ] Stop recording Mouse handling defmdown MDOWN Move the cursor to the mouse location @@ -1028,66 +1016,39 @@ ltarw,rtarw,begin_marking,prevword,toggle_marking ^[ [ 1 ; 6 D Shift-Ctrl-Lef Extra functions not really part of JOE user interface: -delbol ^[ o Delete to beginning of line -delbol ^[ ^O Delete to beginning of line -dnslide ^[ z Scroll down one line -dnslide ^[ Z Scroll down one line -dnslide ^[ ^Z Scroll down one line +delbol ^[ ^^O Delete to beginning of line +dnslide ^[ ^^Z Scroll down one line dnslide,dnslide,dnslide,dnslide MWDOWN -compile ^[ c Compile -compile ^[ C -compile ^[ ^C Compile -grep_find ^[ g Grep -grep_find ^[ G Grep -grep_find ^[ ^G Grep -execmd ^[ x Prompt for command to execute -execmd ^[ X Prompt for command to execute -execmd ^[ ^X Prompt for command to execute +compile ^[ ^^C Compile +grep_find ^[ ^^G Grep +execmd ^[ ^^X Prompt for command to execute finish ^[ ^I Complete word in document finish ^[ ^[ [ 1 0 5 ; 5 u finish ^[ ^M Complete word: used to be math finish ^[ ^[ [ 1 0 9 ; 5 u mwind!,mfit,jump,bol ^[ SP -isrch ^[ s Forward incremental search -isrch ^[ S Forward incremental search -isrch ^[ ^S Forward incremental search +isrch ^[ ^^S Forward incremental search isrch ^S notmod ^[ ~ Not modified mwind,mfit,prevw,nxterr ^[ = To next error -parserr ^[ e Parse errors in current buffer -parserr ^[ E Parse errors in current buffer -parserr ^[ ^E Parse errors in current buffer +parserr ^[ ^^E Parse errors in current buffer mwind,mfit,prevw,prverr ^[ - To previous error -rsrch ^[ r Backward incremental search -rsrch ^[ R Backward incremental search -rsrch ^[ ^R Backward incremental search +rsrch ^[ ^^R Backward incremental search retype,rsrch ^R run ^[ ! Run a program in a window -tomarkb ^[ b Go to beginning of marked block -tomarkb ^[ ^B Go to beginning of marked block -tomarkk ^[ k Go to end of marked block -tomarkk ^[ ^K Go to end of marked block -tomarkk ^[ K Go to end of marked block -txt ^[ i Prompt for text and insert it -txt ^[ I Prompt for text and insert it -upslide ^[ w Scroll up one line -upslide ^[ ^W Scroll up one line -upslide ^[ W Scroll up one line +tomarkb ^[ ^^B Go to beginning of marked block +tomarkk ^[ ^^K Go to end of marked block +txt ^[ ^@i Prompt for text and insert it +upslide ^[ ^^W Scroll up one line upslide,upslide,upslide,upslide MWUP -yank ^[ y Undelete text -yankpop ^[ ^Y Undelete text -yank ^[ Y Undelete text +yankpop ^[ ^^Y Undelete text toggle_marking ^@ Ctrl-space block selection method insc ^@ Ctrl-space used to insert a space bufed ^[ d Menu of buffers -nbuf ^[ v Next buffer -nbuf ^[ V Next buffer -nbuf ^[ ^V Next buffer -pbuf ^[ u Prev buffer -pbuf ^[ U Prev buffer -pbuf ^[ ^U Prev buffer +nbuf ^[ ^^V Next buffer +pbuf ^[ ^^U Prev buffer query ^[ q Quoted insert byte ^[ n Goto byte col ^[ c Goto column @@ -1123,30 +1084,18 @@ backs ^? Backspace backs ^H backw ^O Backspace word bknd ^K ' Shell window -blkcpy ^K C Copy marked block -blkcpy ^K ^C -blkcpy ^K c -blkdel ^K Y Delete marked block -blkdel ^K ^Y -blkdel ^K y -blkmove ^K M Move marked block -blkmove ^K ^M +blkcpy ^K ^^C Copy marked block +blkdel ^K ^^Y Delete marked block +blkmove ^K ^^M Move marked block blkmove ^K ^[ [ 1 0 9 ; 5 u -blkmove ^K m -blksave ^K W Save marked block -blksave ^K ^W -blksave ^K w -bof ^K U Goto beginning of file -bof ^K ^U -bof ^K u +blksave ^K ^^W Save marked block +bof ^K ^^U Goto beginning of file bol .kh Goto beginning of line bol ^A bol ^# SP A home .kh home ^A -center ^K A Center line -center ^K ^A -center ^K a +center ^K ^^A Center line crawll ^K < Pan left crawll ^[ < Pan left crawlr ^K > Pan right @@ -1162,56 +1111,35 @@ dnarw ^N dnarw ^[ O B dnarw ^[ [ B dnarw ^# B -edit ^K E Edit a file -edit ^K ^E -edit ^K e -eof ^K V Go to end of file -eof ^K ^V -eof ^K v +edit ^K ^^E Edit a file +eof ^K ^^V Go to end of file eol .kH Go to end of line eol .@7 eol ^E -exsave ^K X Save and exit (prepend with ask,query, if you want it to ask before saving) -exsave ^K ^X -exsave ^K x -ffirst ^K F Find first -ffirst ^K ^F -ffirst ^K f +exsave ^K ^^X Save and exit (prepend with ask,query, if you want it to ask before saving) +ffirst ^K ^^F Find first filt ^K / Filter block finish ^K ^M Complete text under cursor finish ^K ^[ [ 1 0 9 ; 5 u fnext ^L Find next -fmtblk ^K J Format paragraphs in block -fmtblk ^K ^J -fmtblk ^K j +fmtblk ^K ^^J Format paragraphs in block gomark ^[ 0 TO 9 Goto bookmark -groww ^K G Grow window -groww ^K ^G -groww ^K g +groww ^K ^^G Grow window yank .kI Insert previously deleted insc .kI Insert a space mode,"overwrite",rtn .kI Toggle insert/overtype insc ^@ -insf ^K R Insert a file -insf ^K ^R -insf ^K r +insf ^K ^^R Insert a file lindent ^K , Indent to left -line ^K L Goto line no. -line ^K ^L -line ^K l +line ^K ^^L Goto line no. ltarw .kl Go left ltarw ^B ltarw ^[ O D ltarw ^[ [ D ltarw ^# D -macros ^[ d Dump keyboard macros -macros ^[ ^D -markb ^K B Set beginning of marked block -markb ^K ^B -markb ^K b -markk ^K K Set end of marked block -markk ^K ^K -markk ^K k +macros ^[ ^^D Dump keyboard macros +markb ^K ^^B Set beginning of marked block +markk ^K ^^K Set end of marked block mode ^T Options menu menu,"root",rtn ^T nextpos ^K = Goto next position in position history @@ -1228,19 +1156,11 @@ rtarw ^[ O C rtarw ^[ [ C rtarw ^# C run ^K ! Run a shell command -save ^K D Save file -save ^K S -save ^K ^D -save ^K ^S -save ^K d -save ^K s +save ^K ^^D Save file +save ^K ^^S setmark ^[ ^[ Set bookmark -shrinkw ^K T Shrink window -shrinkw ^K ^T -shrinkw ^K t -splitw ^K O Split window -splitw ^K ^O -splitw ^K o +shrinkw ^K ^^T Shrink window +splitw ^K ^^O Split window stat ^K SP Show status stat ^K ^@ Show status tag ^K ; Tags file search @@ -1306,9 +1226,7 @@ eolmenu ^[ [ 8 ~ RxVT abort ^[ ^[ Why? backsmenu ^? backsmenu ^H -bofmenu ^K U -bofmenu ^K ^U -bofmenu ^K u +bofmenu ^K ^^U bolmenu .kh bolmenu ^A dnarwmenu .kd @@ -1317,9 +1235,7 @@ dnarwmenu ^[ [ B dnarwmenu ^[ O B dnarwmenu ^# B dnarwmenu MWDOWN -eofmenu ^K V -eofmenu ^K ^V -eofmenu ^K v +eofmenu ^K ^^V eolmenu .kH eolmenu ^E ltarwmenu .kl @@ -1343,9 +1259,7 @@ rtarwmenu ^[ O C rtn SP rtn ^I rtn ^[ [ 1 0 5 ; 5 u -rtn ^K H -rtn ^K h -rtn ^K ^H +rtn ^K ^^H tabmenu ^I tabmenu ^[ [ 1 0 5 ; 5 u uparwmenu .ku diff --git a/tests/joefx/keys.py b/tests/joefx/keys.py index a5427885..ee42900b 100644 --- a/tests/joefx/keys.py +++ b/tests/joefx/keys.py @@ -122,7 +122,12 @@ def fromRcFile(keys): result = b'' for k in keys: if k[0] == '^': - result += toctl(k) + if k[1] == '@': # upper or lower + result += toctl(k[2]) + elif k[1] == '^': # upper, lower or ctrl + result += toctl('^'+k[2]) + else: # ctrl + result += toctl(k) elif k.startswith("U+"): result += chr(int(k[2:], 16)).encode('utf-8') elif len(k) > 1: diff --git a/tests/joefx/rcfile.py b/tests/joefx/rcfile.py index dae18105..8a5665b5 100644 --- a/tests/joefx/rcfile.py +++ b/tests/joefx/rcfile.py @@ -453,6 +453,8 @@ def iskey(self, k): if len(k) == 1: return True if k.startswith('U+'): return True if k.startswith('^') and len(k) == 2: return True + if k.startswith('^^') and len(k) == 3: return True + if k.startswith('^@') and len(k) == 3: return True if k.startswith('.k') and len(k) == 3: return True if k in ('MDOWN', 'MDRAG', 'MUP', 'M2DOWN', 'M2DRAG', 'M2UP', 'M3DOWN', 'M3DRAG', 'M3UP', 'MWDOWN', 'MWUP', 'SP', 'TO'):