vi_mode.c (3733B)
1 static unsigned int using_vi_mode = 0; 2 3 void 4 vi_keypress(KeySym ksym, const XKeyEvent *ev) 5 { 6 static const size_t quit_len = LENGTH(quit_keys); 7 if (ev->state & ControlMask) { 8 switch(ksym) { 9 /* movement */ 10 case XK_d: /* fallthrough */ 11 if (next) { 12 sel = curr = next; 13 calcoffsets(); 14 goto draw; 15 } else 16 ksym = XK_G; 17 break; 18 case XK_u: 19 if (prev) { 20 sel = curr = prev; 21 calcoffsets(); 22 goto draw; 23 } else 24 ksym = XK_g; 25 break; 26 case XK_p: /* fallthrough */ 27 case XK_P: break; 28 case XK_c: 29 cleanup(); 30 exit(1); 31 case XK_Return: /* fallthrough */ 32 case XK_KP_Enter: break; 33 default: return; 34 } 35 } 36 37 switch(ksym) { 38 /* movement */ 39 case XK_0: 40 cursor = 0; 41 break; 42 case XK_dollar: 43 if (text[cursor + 1] != '\0') { 44 cursor = strlen(text) - 1; 45 break; 46 } 47 break; 48 case XK_b: 49 movewordedge(-1); 50 break; 51 case XK_e: 52 cursor = nextrune(+1); 53 movewordedge(+1); 54 if (text[cursor] == '\0') 55 --cursor; 56 else 57 cursor = nextrune(-1); 58 break; 59 case XK_g: 60 if (sel == matches) { 61 break; 62 } 63 sel = curr = matches; 64 calcoffsets(); 65 break; 66 case XK_G: 67 if (next) { 68 /* jump to end of list and position items in reverse */ 69 curr = matchend; 70 calcoffsets(); 71 curr = prev; 72 calcoffsets(); 73 while (next && (curr = curr->right)) 74 calcoffsets(); 75 } 76 sel = matchend; 77 break; 78 case XK_h: 79 if (cursor) 80 cursor = nextrune(-1); 81 break; 82 case XK_j: 83 if (sel && sel->right && (sel = sel->right) == next) { 84 curr = next; 85 calcoffsets(); 86 } 87 break; 88 case XK_k: 89 if (sel && sel->left && (sel = sel->left)->right == curr) { 90 curr = prev; 91 calcoffsets(); 92 } 93 break; 94 case XK_l: 95 if (text[cursor] != '\0' && text[cursor + 1] != '\0') 96 cursor = nextrune(+1); 97 else if (text[cursor] == '\0' && cursor) 98 --cursor; 99 break; 100 case XK_w: 101 movewordedge(+1); 102 if (text[cursor] != '\0' && text[cursor + 1] != '\0') 103 cursor = nextrune(+1); 104 else if (cursor) 105 --cursor; 106 break; 107 /* insertion */ 108 case XK_a: 109 cursor = nextrune(+1); 110 /* fallthrough */ 111 case XK_i: 112 using_vi_mode = 0; 113 break; 114 case XK_A: 115 if (text[cursor] != '\0') 116 cursor = strlen(text); 117 using_vi_mode = 0; 118 break; 119 case XK_I: 120 cursor = using_vi_mode = 0; 121 break; 122 case XK_p: 123 if (text[cursor] != '\0') 124 cursor = nextrune(+1); 125 XConvertSelection(dpy, (ev->state & ControlMask) ? clip : XA_PRIMARY, 126 utf8, utf8, win, CurrentTime); 127 return; 128 case XK_P: 129 XConvertSelection(dpy, (ev->state & ControlMask) ? clip : XA_PRIMARY, 130 utf8, utf8, win, CurrentTime); 131 return; 132 /* deletion */ 133 case XK_D: 134 text[cursor] = '\0'; 135 if (cursor) 136 cursor = nextrune(-1); 137 match(); 138 break; 139 case XK_x: 140 cursor = nextrune(+1); 141 insert(NULL, nextrune(-1) - cursor); 142 if (text[cursor] == '\0' && text[0] != '\0') 143 --cursor; 144 match(); 145 break; 146 /* misc. */ 147 case XK_Return: 148 case XK_KP_Enter: 149 #if RESTRICT_RETURN_PATCH 150 if (restrict_return && (!sel || ev->state & (ShiftMask | ControlMask))) 151 break; 152 #endif // RESTRICT_RETURN_PATCH 153 #if !MULTI_SELECTION_PATCH 154 printcurrent(ev->state); 155 #endif // MULTI_SELECTION_PATCH 156 if (!(ev->state & ControlMask)) { 157 #if MULTI_SELECTION_PATCH 158 printselected(ev->state); 159 #endif // MULTI_SELECTION_PATCH 160 cleanup(); 161 exit(0); 162 } 163 #if !MULTI_SELECTION_PATCH 164 if (sel) 165 sel->out = 1; 166 #endif // MULTI_SELECTION_PATCH 167 break; 168 break; 169 case XK_Tab: 170 if (!sel) 171 return; 172 strncpy(text, sel->text, sizeof text - 1); 173 text[sizeof text - 1] = '\0'; 174 cursor = strlen(text) - 1; 175 match(); 176 break; 177 default: 178 for (size_t i = 0; i < quit_len; ++i) 179 if (quit_keys[i].ksym == ksym && 180 (quit_keys[i].state & ev->state) == quit_keys[i].state) { 181 cleanup(); 182 exit(1); 183 } 184 } 185 186 draw: 187 drawmenu(); 188 }