st-keyboard_select-20190207-3be4cf1.diff - sites - public wiki contents of suckless.org
 (HTM) git clone git://git.suckless.org/sites
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
       st-keyboard_select-20190207-3be4cf1.diff (9523B)
       ---
            1 diff --git a/config.def.h b/config.def.h
            2 index 0e01717..021bcdd 100644
            3 --- a/config.def.h
            4 +++ b/config.def.h
            5 @@ -178,6 +178,7 @@ static Shortcut shortcuts[] = {
            6          { TERMMOD,              XK_Y,           selpaste,       {.i =  0} },
            7          { ShiftMask,            XK_Insert,      selpaste,       {.i =  0} },
            8          { TERMMOD,              XK_Num_Lock,    numlock,        {.i =  0} },
            9 +        { TERMMOD,              XK_Escape,      keyboard_select,{ 0 } },
           10  };
           11  
           12  /*
           13 diff --git a/st.c b/st.c
           14 index b8e6077..1ad0f22 100644
           15 --- a/st.c
           16 +++ b/st.c
           17 @@ -16,6 +16,8 @@
           18  #include <termios.h>
           19  #include <unistd.h>
           20  #include <wchar.h>
           21 +#include <X11/keysym.h>
           22 +#include <X11/X.h>
           23  
           24  #include "st.h"
           25  #include "win.h"
           26 @@ -2481,6 +2483,9 @@ tresize(int col, int row)
           27          int *bp;
           28          TCursor c;
           29  
           30 +        if ( row < term.row  || col < term.col )
           31 +        toggle_winmode(trt_kbdselect(XK_Escape, NULL, 0));
           32 +
           33          if (col < 1 || row < 1) {
           34                  fprintf(stderr,
           35                          "tresize: error resizing to %dx%d\n", col, row);
           36 @@ -2602,3 +2607,220 @@ redraw(void)
           37          tfulldirt();
           38          draw();
           39  }
           40 +
           41 +void set_notifmode(int type, KeySym ksym) {
           42 +    static char *lib[] = { " MOVE ", " SEL  "};
           43 +    static Glyph *g, *deb, *fin;
           44 +    static int col, bot;
           45 +
           46 +    if ( ksym == -1 ) {
           47 +        free(g);
           48 +        col = term.col, bot = term.bot;
           49 +        g = xmalloc(col * sizeof(Glyph));
           50 +        memcpy(g, term.line[bot], col * sizeof(Glyph));
           51 +    
           52 +    }
           53 +    else if ( ksym == -2 )
           54 +        memcpy(term.line[bot], g, col * sizeof(Glyph));
           55 +
           56 +    if ( type < 2 ) {
           57 +        char *z = lib[type];
           58 +        for (deb = &term.line[bot][col - 6], fin = &term.line[bot][col]; deb < fin; z++, deb++)
           59 +            deb->mode = ATTR_REVERSE,
           60 +            deb->u = *z,
           61 +            deb->fg = defaultfg, deb->bg = defaultbg;
           62 +    }
           63 +    else if ( type < 5 )
           64 +        memcpy(term.line[bot], g, col * sizeof(Glyph));
           65 +    else {
           66 +        for (deb = &term.line[bot][0], fin = &term.line[bot][col]; deb < fin; deb++)
           67 +            deb->mode = ATTR_REVERSE,
           68 +            deb->u = ' ',
           69 +            deb->fg = defaultfg, deb->bg = defaultbg;
           70 +        term.line[bot][0].u = ksym;
           71 +    }
           72 +
           73 +    term.dirty[bot] = 1;
           74 +    drawregion(0, bot, col, bot + 1);
           75 +}
           76 +
           77 +void select_or_drawcursor(int selectsearch_mode, int type) {
           78 +    int done = 0;
           79 +
           80 +    if ( selectsearch_mode & 1 ) {
           81 +        selextend(term.c.x, term.c.y, type, done);
           82 +        xsetsel(getsel());
           83 +    }
           84 +    else
           85 +        xdrawcursor(term.c.x, term.c.y, term.line[term.c.y][term.c.x],
           86 +                    term.ocx, term.ocy, term.line[term.ocy][term.ocx]);
           87 +}
           88 +
           89 +void search(int selectsearch_mode, Rune *target, int ptarget, int incr, int type, TCursor *cu) {
           90 +    Rune *r;
           91 +    int i, bound = (term.col * cu->y + cu->x) * (incr > 0) + incr;
           92 +
           93 +    for (i = term.col * term.c.y + term.c.x + incr; i != bound; i += incr) {
           94 +        for (r = target; r - target < ptarget; r++) {
           95 +            if ( *r == term.line[(i + r - target) / term.col][(i + r - target) % term.col].u ) {
           96 +                if ( r - target == ptarget - 1 )     break;
           97 +            } else {
           98 +                r = NULL;
           99 +                break;
          100 +            }
          101 +        }
          102 +        if ( r != NULL )    break;
          103 +    }
          104 +        
          105 +    if ( i != bound ) {
          106 +        term.c.y = i / term.col, term.c.x = i % term.col;
          107 +        select_or_drawcursor(selectsearch_mode, type);
          108 +    }
          109 +}
          110 +
          111 +int trt_kbdselect(KeySym ksym, char *buf, int len) {
          112 +    static TCursor cu;
          113 +    static Rune target[64];
          114 +    static int type = 1, ptarget, in_use;
          115 +    static int sens, quant;
          116 +    static char selectsearch_mode;
          117 +    int i, bound, *xy;
          118 +    
          119 +    
          120 +    if ( selectsearch_mode & 2 ) {
          121 +                if ( ksym == XK_Return ) {
          122 +                        selectsearch_mode ^= 2;
          123 +                        set_notifmode(selectsearch_mode, -2);
          124 +            if ( ksym == XK_Escape )    ptarget = 0;
          125 +                        return 0;
          126 +                }
          127 +        else if ( ksym == XK_BackSpace ) {
          128 +            if ( !ptarget )     return 0;
          129 +            term.line[term.bot][ptarget--].u = ' ';
          130 +                }
          131 +        else if ( len < 1 ) {
          132 +                        return 0;
          133 +                }
          134 +        else if ( ptarget == term.col  || ksym == XK_Escape ) {
          135 +            return 0;
          136 +        }
          137 +                else {
          138 +            utf8decode(buf, &target[ptarget++], len);
          139 +            term.line[term.bot][ptarget].u = target[ptarget - 1];
          140 +                }
          141 +
          142 +        if ( ksym != XK_BackSpace )
          143 +            search(selectsearch_mode, &target[0], ptarget, sens, type, &cu);
          144 +
          145 +        term.dirty[term.bot] = 1; 
          146 +        drawregion(0, term.bot, term.col, term.bot + 1);
          147 +        return 0;
          148 +    }
          149 +
          150 +    switch ( ksym ) {
          151 +    case -1 :
          152 +        in_use = 1;
          153 +        cu.x = term.c.x, cu.y = term.c.y;
          154 +        set_notifmode(0, ksym);
          155 +        return MODE_KBDSELECT;
          156 +    case XK_s :
          157 +        if ( selectsearch_mode & 1 )
          158 +            selclear();
          159 +        else
          160 +            selstart(term.c.x, term.c.y, 0);
          161 +        set_notifmode(selectsearch_mode ^= 1, ksym);
          162 +        break;
          163 +    case XK_t :
          164 +        selextend(term.c.x, term.c.y, type ^= 3, i = 0);  /* 2 fois */
          165 +        selextend(term.c.x, term.c.y, type, i = 0);
          166 +        break;
          167 +    case XK_slash :
          168 +    case XK_KP_Divide :
          169 +    case XK_question :
          170 +        ksym &= XK_question;                /* Divide to slash */
          171 +        sens = (ksym == XK_slash) ? -1 : 1;
          172 +        ptarget = 0;
          173 +        set_notifmode(15, ksym);
          174 +        selectsearch_mode ^= 2;
          175 +        break;
          176 +    case XK_Escape :
          177 +        if ( !in_use )  break;
          178 +        selclear();
          179 +    case XK_Return :
          180 +        set_notifmode(4, ksym);
          181 +        term.c.x = cu.x, term.c.y = cu.y;
          182 +        select_or_drawcursor(selectsearch_mode = 0, type);
          183 +        in_use = quant = 0;
          184 +        return MODE_KBDSELECT;
          185 +    case XK_n :
          186 +    case XK_N :
          187 +        if ( ptarget )
          188 +            search(selectsearch_mode, &target[0], ptarget, (ksym == XK_n) ? -1 : 1, type, &cu);
          189 +        break;
          190 +    case XK_BackSpace :
          191 +        term.c.x = 0;
          192 +        select_or_drawcursor(selectsearch_mode, type);
          193 +        break;
          194 +    case XK_dollar :
          195 +        term.c.x = term.col - 1;
          196 +        select_or_drawcursor(selectsearch_mode, type);
          197 +        break;
          198 +    case XK_Home :
          199 +        term.c.x = 0, term.c.y = 0;
          200 +        select_or_drawcursor(selectsearch_mode, type);
          201 +        break;
          202 +    case XK_End :
          203 +        term.c.x = cu.x, term.c.y = cu.y;
          204 +        select_or_drawcursor(selectsearch_mode, type);
          205 +        break;
          206 +    case XK_Page_Up :
          207 +    case XK_Page_Down :
          208 +        term.c.y = (ksym == XK_Prior ) ? 0 : cu.y;
          209 +        select_or_drawcursor(selectsearch_mode, type);
          210 +        break;
          211 +    case XK_exclam :
          212 +        term.c.x = term.col >> 1;
          213 +        select_or_drawcursor(selectsearch_mode, type);
          214 +        break;
          215 +    case XK_asterisk :
          216 +    case XK_KP_Multiply :
          217 +        term.c.x = term.col >> 1;
          218 +    case XK_underscore :
          219 +        term.c.y = cu.y >> 1;
          220 +        select_or_drawcursor(selectsearch_mode, type);
          221 +        break;
          222 +    default :
          223 +        if ( ksym >= XK_0 && ksym <= XK_9 ) {               /* 0-9 keyboard */
          224 +            quant = (quant * 10) + (ksym ^ XK_0);
          225 +            return 0;
          226 +        }
          227 +        else if ( ksym >= XK_KP_0 && ksym <= XK_KP_9 ) {    /* 0-9 numpad */
          228 +            quant = (quant * 10) + (ksym ^ XK_KP_0);
          229 +            return 0;
          230 +        }
          231 +        else if ( ksym == XK_k || ksym == XK_h )
          232 +            i = ksym & 1;
          233 +        else if ( ksym == XK_l || ksym == XK_j )
          234 +            i = ((ksym & 6) | 4) >> 1;
          235 +        else if ( (XK_Home & ksym) != XK_Home || (i = (ksym ^ XK_Home) - 1) > 3 )
          236 +            break;
          237 +
          238 +        xy = (i & 1) ? &term.c.y : &term.c.x;
          239 +        sens = (i & 2) ? 1 : -1;
          240 +        bound = (i >> 1 ^ 1) ? 0 : (i ^ 3) ? term.col - 1 : term.bot;
          241 +
          242 +        if ( quant == 0 )
          243 +            quant++;
          244 +
          245 +        if ( *xy == bound && ((sens < 0 && bound == 0) || (sens > 0 && bound > 0)) )
          246 +            break;
          247 +
          248 +        *xy += quant * sens;
          249 +        if ( *xy < 0 || ( bound > 0 && *xy > bound) )
          250 +            *xy = bound;
          251 +
          252 +        select_or_drawcursor(selectsearch_mode, type);
          253 +    }
          254 +    quant = 0;
          255 +    return 0;
          256 +}
          257 diff --git a/st.h b/st.h
          258 index 38c61c4..a76419e 100644
          259 --- a/st.h
          260 +++ b/st.h
          261 @@ -109,6 +109,7 @@ size_t utf8encode(Rune, char *);
          262  void *xmalloc(size_t);
          263  void *xrealloc(void *, size_t);
          264  char *xstrdup(char *);
          265 +int trt_kbdselect(KeySym, char *, int);
          266  
          267  /* config.h globals */
          268  extern char *utmp;
          269 diff --git a/win.h b/win.h
          270 index 31f327d..75a2756 100644
          271 --- a/win.h
          272 +++ b/win.h
          273 @@ -21,6 +21,7 @@ enum win_mode {
          274          MODE_NUMLOCK     = 1 << 17,
          275          MODE_MOUSE       = MODE_MOUSEBTN|MODE_MOUSEMOTION|MODE_MOUSEX10\
          276                            |MODE_MOUSEMANY,
          277 +        MODE_KBDSELECT   = 1 << 18,
          278  };
          279  
          280  void xbell(void);
          281 @@ -36,3 +37,5 @@ void xsetmode(int, unsigned int);
          282  void xsetpointermotion(int);
          283  void xsetsel(char *);
          284  int xstartdraw(void);
          285 +void toggle_winmode(int);
          286 +void keyboard_select(const Arg *);
          287 diff --git a/x.c b/x.c
          288 index 0422421..f5fa3e2 100644
          289 --- a/x.c
          290 +++ b/x.c
          291 @@ -1699,6 +1699,13 @@ kpress(XEvent *ev)
          292                  return;
          293  
          294          len = XmbLookupString(xw.xic, e, buf, sizeof buf, &ksym, &status);
          295 +    if ( IS_SET(MODE_KBDSELECT) ) {
          296 +                if ( match(XK_NO_MOD, e->state) ||
          297 +            (XK_Shift_L | XK_Shift_R) & e->state )
          298 +            win.mode ^= trt_kbdselect(ksym, buf, len);
          299 +                return;
          300 +    }
          301 +
          302          /* 1. shortcuts */
          303          for (bp = shortcuts; bp < shortcuts + LEN(shortcuts); bp++) {
          304                  if (ksym == bp->keysym && match(bp->mod, e->state)) {
          305 @@ -1883,6 +1890,14 @@ usage(void)
          306              " [stty_args ...]\n", argv0, argv0);
          307  }
          308  
          309 +void toggle_winmode(int flag) {
          310 +        win.mode ^= flag;
          311 +}
          312 +
          313 +void keyboard_select(const Arg *dummy) {
          314 +    win.mode ^= trt_kbdselect(-1, NULL, 0);
          315 +}
          316 +
          317  int
          318  main(int argc, char *argv[])
          319  {