Introduction
Introduction Statistics Contact Development Disclaimer Help
Added runtime rcfile parsing. - sam - An updated version of the sam text editor.
git clone git://vernunftzentrum.de/sam.git
Log
Files
Refs
LICENSE
---
commit 071c95698bc28739fb0289c84ff46a2278d1270c
parent 140ba1042462570fc3c966652ea1d6e79cd3ae93
Author: Rob King <[email protected]>
Date: Fri, 9 Sep 2016 13:07:48 -0500
Added runtime rcfile parsing.
Diffstat:
include/libg.h | 2 ++
libXg/gwin.c | 121 ++++++++++++++++++++++---------
libXg/libgint.h | 4 ++++
libXg/xtbinit.c | 2 ++
samterm/Makefile | 2 +-
samterm/main.c | 12 ++++++++++++
samterm/samrc.c | 255 +++++++++++++++++++++++++++++++
samterm/samterm.h | 3 +++
8 files changed, 365 insertions(+), 36 deletions(-)
---
diff --git a/include/libg.h b/include/libg.h
@@ -230,4 +230,6 @@ extern XftColor bgcolor;
#define BPSHORT(p, v) ((p)[0]=(v), (p)[1]=((v)>>8))
#define BPLONG(p, v) (BPSHORT(p, (v)), BPSHORT(p+2, (v)>>16))
+extern int installbinding(int, KeySym, int, int);
+extern int installchord(int, int, int, int);
#endif
diff --git a/libXg/gwin.c b/libXg/gwin.c
@@ -160,19 +160,6 @@ Mappingaction(Widget w, XEvent *e, String *p, Cardinal *np)
for (c = 0; c < composing; c++) \
(*f)(compose[c], 0, Tcurrent, 0, 0)
-typedef struct Keymapping Keymapping;
-struct Keymapping{
- int mask;
- int sym;
- int kind;
- int result;
-};
-
-Keymapping keymappings[] ={
- #include "../commands.h"
- {0, 0, Kend, 0}
-};
-
typedef struct Unikeysym Unikeysym;
struct Unikeysym{
KeySym keysym;
@@ -195,6 +182,49 @@ keysymtoshort(KeySym k)
return k;
}
+typedef struct Keymapping Keymapping;
+struct Keymapping{
+ Keymapping *next;
+ int m;
+ KeySym s;
+ int k;
+ int c;
+};
+
+static Keymapping *keymappings = NULL;
+
+int
+installbinding(int m, KeySym s, int k, int c)
+{
+ if (m < 0 || s == NoSymbol || k < 0 || c < 0)
+ return -1;
+
+ Keymapping *km = calloc(1, sizeof(Keymapping));
+ if (!km)
+ return -1;
+
+ km->m = m;
+ km->s = s;
+ km->k = k;
+ km->c = c;
+
+ km->next = keymappings;
+ keymappings = km;
+
+ return 0;
+}
+
+void
+freebindings(void)
+{
+ Keymapping *m = keymappings;
+ while (m){
+ Keymapping *n = m->next;
+ free(m);
+ m = n;
+ }
+}
+
static void
Keyaction(Widget w, XEvent *e, String *p, Cardinal *np)
{
@@ -220,12 +250,12 @@ Keyaction(Widget w, XEvent *e, String *p, Cardinal *np)
XtTranslateKeycode(e->xany.display, (KeyCode)e->xkey.keycode, e->xkey.stat…
/* Check to see if it's a specially-handled key first. */
- for (Keymapping *m = keymappings; m && m->kind != Kend; m++){
- if (k == m->sym && m->kind != Kdefault){
- if ((e->xkey.state & m->mask) || m->mask == 0){
+ for (Keymapping *m = keymappings; m; m = m->next){
+ if (k == m->s){
+ if ((e->xkey.state & m->m) || m->m == 0){
f = ((GwinWidget)w)->gwin.gotchar;
if (f)
- (*f)(m->result, m->kind, Tcurrent, 0, 0);
+ (*f)(m->c, m->k, Tcurrent, 0, 0);
return;
}
}
@@ -308,24 +338,45 @@ Keyaction(Widget w, XEvent *e, String *p, Cardinal *np)
typedef struct Chordmapping Chordmapping;
struct Chordmapping{
- int start;
- int end;
- int kind;
- int result;
- int target;
+ Chordmapping *next;
+ int s1;
+ int s2;
+ int c;
+ int t;
};
-#define Bnone 0
-#define B1 1
-#define B2 2
-#define B3 4
-#define B4 8
-#define B5 16
+static Chordmapping *chordmap = NULL;
-Chordmapping chordmappings[] ={
- #include "../chords.h"
- {0, 0, Kend, 0, 0}
-};
+int
+installchord(int s1, int s2, int c, int t)
+{
+ if (s1 < 0 || s2 < 0 || c < 0 || (t != Tmouse && t != Tcurrent))
+ return -1;
+
+ Chordmapping *m = calloc(1, sizeof(Chordmapping));
+ if (!m)
+ return -1;
+
+ m->s1 = s1;
+ m->s2 = s2;
+ m->c = c;
+ m->t = t;
+
+ m->next = chordmap;
+ chordmap = m;
+ return 0;
+}
+
+void
+freechords(void)
+{
+ Chordmapping *m = chordmap;
+ while (m){
+ Chordmapping *n = m->next;
+ free(m);
+ m = n;
+ }
+}
static void
Mouseaction(Widget w, XEvent *e, String *p, Cardinal *np)
@@ -391,11 +442,11 @@ Mouseaction(Widget w, XEvent *e, String *p, Cardinal *np)
if(s & Button5Mask) m.buttons |= 16;
/* Check to see if it's a chord first. */
- for (Chordmapping *cm = chordmappings; cm && cm->kind != Kend; cm++){
- if (ob == cm->start && m.buttons == cm->end){
+ for (Chordmapping *cm = chordmap; cm; cm = cm->next){
+ if (ob == cm->s1 && m.buttons == cm->s2){
Charfunc kf = ((GwinWidget)w)->gwin.gotchar;
if (kf)
- (*kf)(cm->result, cm->kind, cm->target, m.xy.x, m.xy.y);
+ (*kf)(cm->c, Kcommand, cm->t, m.xy.x, m.xy.y);
m.buttons = 0;
}
diff --git a/libXg/libgint.h b/libXg/libgint.h
@@ -29,6 +29,10 @@ typedef char* caddr_t;
#undef Font
#undef Event
+/* binding and chord management */
+void freechords(void);
+void freebindings(void);
+
/* Cursor initialization */
void initcursors(void);
diff --git a/libXg/xtbinit.c b/libXg/xtbinit.c
@@ -209,6 +209,8 @@ xtbinit(Errfunc f, char *class, int *pargc, char **argv, ch…
}
initcursors();
+ atexit(freebindings);
+ atexit(freechords);
font = XftFontOpenName(_dpy, DefaultScreen(_dpy), getenv("FONT") ? getenv(…
screen.id = 0;
diff --git a/samterm/Makefile b/samterm/Makefile
@@ -22,7 +22,7 @@ CFLAGS=$(INCS) $(STANDARDS) $(INCLUDES)
LIBS=../libframe/libframe.a ../libXg/libXg.a
CC?=c99
-OBJ=main.o flayer.o icons.o io.o menu.o mesg.o rasp.o scroll.o unix.o
+OBJ=main.o flayer.o icons.o io.o menu.o mesg.o rasp.o samrc.o scroll.o unix.o
all: samterm
diff --git a/samterm/main.c b/samterm/main.c
@@ -47,6 +47,18 @@ main(int argc, char *argv[])
Rectangle r;
Flayer *nwhich;
int fwdbut;
+ char rcpath[PATH_MAX + 1] = {0};
+ FILE *rc = NULL;
+
+ installdefaultbindings();
+ installdefaultchords();
+
+ snprintf(rcpath, PATH_MAX, "%s/.samrc", getenv("HOME") ? getenv("HOME") : …
+ rc = fopen(rcpath, "r");
+ if (rc){
+ loadrcfile(rc);
+ fclose(rc);
+ }
while ((opt = getopt(argc, argv, "efr:")) != -1){
switch (opt){
diff --git a/samterm/samrc.c b/samterm/samrc.c
@@ -0,0 +1,255 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <X11/Xlib.h>
+#include <X11/keysym.h>
+
+#include <commands.h>
+#include <u.h>
+#include <libg.h>
+
+typedef struct Namemapping Namemapping;
+struct Namemapping{
+ const char *name;
+ int value;
+};
+
+static Namemapping commandmapping[] ={
+ {"escape", Cescape},
+ {"scrolldown", Cscrolldown},
+ {"scrollup", Cscrollup},
+ {"scrolldownline", Cscrolldownline},
+ {"scrollupline", Cscrollupline},
+ {"jump", Cjump},
+ {"charright", Ccharright},
+ {"charleft", Ccharleft},
+ {"linedown", Clinedown},
+ {"lineup", Clineup},
+ {"delword", Cdelword},
+ {"delbol", Cdelbol},
+ {"del", Cdel},
+ {"snarf", Csnarf},
+ {"cut", Ccut},
+ {"paste", Cpaste},
+ {"exchange", Cexchange},
+ {"write", Cwrite},
+ {"eol", Ceol},
+ {"bol", Cbol},
+ {NULL, 0}
+};
+
+static Namemapping targetmapping[] ={
+ {"current", Tcurrent},
+ {"mouse", Tmouse},
+ {NULL, 0}
+};
+
+static Namemapping buttonmapping[] ={
+ {"0", 0},
+ {"n", 0},
+#define B1 1
+ {"1", 1},
+#define B2 2
+ {"2", 2},
+#define B3 4
+ {"3", 4},
+#define B4 8
+ {"4", 8},
+#define B5 16
+ {"5", 16},
+ {NULL, 0}
+};
+
+static Namemapping modmapping[] ={
+ {"n", 0},
+ {"c", ControlMask},
+ {"a", Mod1Mask},
+ {"m", Mod1Mask},
+ {"s", Mod2Mask},
+ {"h", Mod3Mask},
+ {"1", Mod1Mask},
+ {"2", Mod2Mask},
+ {"3", Mod3Mask},
+ {"4", Mod4Mask},
+ {"5", Mod5Mask},
+ {NULL, 0}
+};
+
+static int
+lookupmapping(const char *n, Namemapping *m)
+{
+ for (Namemapping *k = m; k->name != NULL; k++){
+ if (strcasecmp(k->name, n) == 0)
+ return k->value;
+ }
+
+ return -1;
+}
+
+static int
+nametocommand(const char *n)
+{
+ return lookupmapping(n, commandmapping);
+}
+
+static int
+nametotarget(const char *n)
+{
+ return lookupmapping(n, targetmapping);
+}
+
+typedef struct Defaultbinding Defaultbinding;
+struct Defaultbinding{
+ int modifiers;
+ KeySym keysym;
+ int kind;
+ int command;
+};
+
+static Defaultbinding defaultbindings[] ={
+ /* Motion commands. */
+ {ControlMask, XK_e, Kcommand, Clineup},
+ {ControlMask, XK_x, Kcommand, Clinedown},
+ {ControlMask, XK_d, Kcommand, Ccharright},
+ {ControlMask, XK_s, Kcommand, Ccharleft},
+ {ControlMask, XK_u, Kcommand, Cdelbol},
+ {ControlMask, XK_w, Kcommand, Cdelword},
+ {ControlMask, XK_k, Kcommand, Cjump},
+ {ControlMask, XK_BackSpace, Kcommand, Cdelword},
+ {ControlMask, XK_y, Kcommand, Ccut},
+ {ControlMask, XK_c, Kcommand, Csnarf},
+ {ControlMask, XK_v, Kcommand, Cpaste},
+ {ControlMask, XK_q, Kcommand, Cexchange},
+
+ /* Use Control-Tab to insert a literal tab when tab expansion is enabled. …
+ {ControlMask, XK_Tab, Kcomposed, '\t'},
+
+ /* Handle arrow keys, page up/down, and escape. */
+ {0, XK_Up, Kcommand, Cscrollup},
+ {0, XK_Prior, Kcommand, Cscrollup},
+ {0, XK_Left, Kcommand, Cscrollup},
+ {0, XK_Down, Kcommand, Cscrolldown},
+ {0, XK_Next, Kcommand, Cscrolldown},
+ {0, XK_Right, Kcommand, Cscrolldown},
+ {0, XK_Escape, Kcommand, Cescape},
+
+ /* More fundamental stuff: backspace, delete, etc. */
+ {0, XK_BackSpace, Kcommand, Cdel},
+ {0, XK_Delete, Kcommand, Cdel},
+ {0, XK_Return, Kraw, '\n'},
+ {0, XK_KP_Enter, Kraw, '\n'},
+ {0, XK_Linefeed, Kraw, '\r'},
+ {0, XK_Tab, Kraw, '\t'},
+ {0, XK_KP_0, Kraw, '0'},
+ {0, XK_KP_1, Kraw, '1'},
+ {0, XK_KP_2, Kraw, '2'},
+ {0, XK_KP_3, Kraw, '3'},
+ {0, XK_KP_4, Kraw, '4'},
+ {0, XK_KP_5, Kraw, '5'},
+ {0, XK_KP_6, Kraw, '6'},
+ {0, XK_KP_7, Kraw, '7'},
+ {0, XK_KP_8, Kraw, '8'},
+ {0, XK_KP_9, Kraw, '9'},
+ {0, XK_KP_Divide, Kraw, '/'},
+ {0, XK_KP_Multiply, Kraw, '*'},
+ {0, XK_KP_Subtract, Kraw, '-'},
+ {0, XK_KP_Add, Kraw, '+'},
+ {0, XK_KP_Decimal, Kraw, '.'},
+ {0, XK_hyphen, Kraw, '-'},
+ {0, 0, Kend, 0}
+};
+
+void
+installdefaultbindings(void)
+{
+ for (Defaultbinding *b = defaultbindings; b->kind != Kend; b++)
+ installbinding(b->modifiers, b->keysym, b->kind, b->command);
+}
+
+typedef struct Defaultchord Defaultchord;
+struct Defaultchord{
+ int state1;
+ int state2;
+ int command;
+ int target;
+};
+
+static Defaultchord defaultchords[] ={
+ {B1, B1|B2, Ccut, Tcurrent},
+ {B1, B1|B3, Cpaste, Tcurrent},
+ {B1|B2, B1, Cnone, Tcurrent},
+ {B1|B3, B1, Cnone, Tcurrent},
+
+ {B4, 0, Cscrollupline, Tmouse},
+ {B5, 0, Cscrolldownline, Tmouse},
+
+ {0, 0, Kend, 0}
+};
+
+void
+installdefaultchords(void)
+{
+ for (Defaultchord *c = defaultchords; c->state1 != 0; c++)
+ installchord(c->state1, c->state2, c->command, c->target);
+}
+
+static int
+statetomask(const char *n, Namemapping *m)
+{
+ int r = 0;
+ for (int i = 0; n[i] != 0; i++){
+ char s[2] = {n[i], 0};
+ int v = lookupmapping(s, m);
+ if (v < 0)
+ return -1;
+ r |= v;
+ }
+
+ return r;
+}
+
+void
+loadrcfile(FILE *f)
+{
+ char *l = NULL;
+ size_t n = 0;
+ ssize_t r = 0;
+ size_t ln = 0;
+
+ while ((r = getline(&l, &n, f)) >= 0){
+ char s1[6] = {0};
+ char s2[6] = {0};
+ char cname[100] = {0};
+ char tname[100] = {0};
+ char c = 0;
+ unsigned short i = 0;
+ int rc = 0;
+
+ ln++;
+ if (r == 0 || l[0] == '\n' || l[0] == 0)
+ continue;
+
+ if (sscanf(l, " chord %5[Nn12345] %5[Nn12345] %99s %99s", s1, s2, cnam…
+ rc = installchord(statetomask(s1, buttonmapping), statetomask(s2, …
+ else if (sscanf(l, " bind %5[ncamshNCAMSH12345] %99s raw %hx", s1, s2,…
+ rc = installbinding(statetomask(s1, modmapping), XStringToKeysym(s…
+ else if (sscanf(l, " bind %5[ncamshNCAMSH12345] %99s composed %hx", s1…
+ rc = installbinding(statetomask(s1, modmapping), XStringToKeysym(s…
+ else if (sscanf(l, " bind %5[ncamshNCAMSH12345] %99s raw %c", s1, s2, …
+ rc = installbinding(statetomask(s1, modmapping), XStringToKeysym(s…
+ else if (sscanf(l, " bind %5[ncamshNCAMSH12345] %99s composed %c", s1,…
+ rc = installbinding(statetomask(s1, modmapping), XStringToKeysym(s…
+ else if (sscanf(l, " bind %5[ncamshNCAMSH12345] %99s command %99s", s1…
+ rc = installbinding(statetomask(s1, modmapping), XStringToKeysym(s…
+ else if (sscanf(l, " %[#]", &c) == 1)
+ continue;
+ else
+ fprintf(stderr, "invalid rc line %zd\n", ln);
+
+ if (rc != 0)
+ fprintf(stderr, "invalid chord/binding on rc line %zd\n", ln);
+ }
+
+ free(l);
+}
diff --git a/samterm/samterm.h b/samterm/samterm.h
@@ -157,3 +157,6 @@ void outlong(long);
void outvlong(void*);
void outsend(void);
int getlayer(const Flayer *l, const Text *t);
+void loadrcfile(FILE *);
+void installdefaultbindings(void);
+void installdefaultchords(void);
You are viewing proxied material from vernunftzentrum.de. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.