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