Introduction
Introduction Statistics Contact Development Disclaimer Help
st-preedit-0.9.2.diff - sites - public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log
Files
Refs
---
st-preedit-0.9.2.diff (10180B)
---
1 diff --git a/st.c b/st.c
2 index b9f66e7..ede6d6b 100644
3 --- a/st.c
4 +++ b/st.c
5 @@ -109,6 +109,12 @@ typedef struct {
6 int alt;
7 } Selection;
8
9 +typedef struct {
10 + Glyph *text; /* preedit text */
11 + int len; /* text length */
12 + PLine pline;
13 +} Preedit;
14 +
15 /* Internal representation of the screen */
16 typedef struct {
17 int row; /* nb row */
18 @@ -202,6 +208,7 @@ static int32_t tdefcolor(const int *, int *, int);
19 static void tdeftran(char);
20 static void tstrsequence(uchar);
21
22 +static void pelineupdate(void);
23 static void drawregion(int, int, int, int);
24
25 static void selnormalize(void);
26 @@ -221,6 +228,7 @@ static ssize_t xwrite(int, const char *, size_t);
27 /* Globals */
28 static Term term;
29 static Selection sel;
30 +static Preedit preedit;
31 static CSIEscape csiescseq;
32 static STREscape strescseq;
33 static int iofd = 1;
34 @@ -1179,6 +1187,9 @@ tmoveto(int x, int y)
35 term.c.state &= ~CURSOR_WRAPNEXT;
36 term.c.x = LIMIT(x, 0, term.col-1);
37 term.c.y = LIMIT(y, miny, maxy);
38 +
39 + if (preedit.len > 0)
40 + pelineupdate();
41 }
42
43 void
44 @@ -2627,6 +2638,115 @@ resettitle(void)
45 xsettitle(NULL);
46 }
47
48 +void
49 +pereset(void)
50 +{
51 + preedit.len = 0;
52 + preedit.pline.width = 0;
53 + pelineupdate();
54 +}
55 +
56 +void
57 +peupdate(int caret, int chg_fst, int chg_len,
58 + unsigned short str_len, const ushort *modes, const char…
59 +{
60 + int i;
61 + int defmode;
62 + Glyph *text, *g;
63 + int chg_last, len;
64 +
65 + chg_fst = MIN(chg_fst, preedit.len);
66 + chg_len = MIN(chg_len, preedit.len - chg_fst);
67 + chg_last = chg_fst + chg_len;
68 + len = preedit.len - chg_len + (str ? str_len : 0);
69 +
70 + /* default glyph mode */
71 + defmode = ATTR_NULL;
72 + if (preedit.len > 0)
73 + defmode = (chg_fst < preedit.len) ?
74 + preedit.text[chg_fst].mode :
75 + preedit.text[chg_fst - 1].mode;
76 + defmode &= ~ATTR_WIDE;
77 +
78 + /* create new text and copy old glyphs */
79 + text = xmalloc(len * sizeof(Glyph));
80 + if (preedit.len > 0) {
81 + memcpy(text, preedit.text, chg_fst * sizeof(Glyph));
82 + memcpy(text + chg_fst + (str ? str_len : 0),
83 + preedit.text + chg_last,
84 + (preedit.len - chg_last) * sizeof(Glyph…
85 + free(preedit.text);
86 + }
87 + preedit.text = text;
88 + preedit.len = len;
89 +
90 + /* new glyphs */
91 + if (str) {
92 + for (i = 0; i < str_len; i++) {
93 + g = text + chg_fst + i;
94 + *g = (Glyph){ 0, defmode, defaultfg, defaultbg …
95 + str += utf8decode(str, &g->u, UTF_SIZ);
96 + if (wcwidth(g->u) > 1)
97 + g->mode |= ATTR_WIDE;
98 + }
99 + }
100 +
101 + /* glyph mode */
102 + if (modes) {
103 + for (i = 0; i < str_len; i++) {
104 + g = text + chg_fst + i;
105 + g->mode = modes[i] | (g->mode & ATTR_WIDE);
106 + }
107 + }
108 +
109 + /* visual width and caret position */
110 + preedit.pline.width = 0;
111 + preedit.pline.caret = 0;
112 + for (i = 0; i < len; i++) {
113 + preedit.pline.width += MAX(wcwidth(text[i].u), 1);
114 + if (i + 1 == caret)
115 + preedit.pline.caret = preedit.pline.width;
116 + }
117 +
118 + pelineupdate();
119 +}
120 +
121 +void
122 +pelineupdate()
123 +{
124 + int i, x;
125 +
126 + free(preedit.pline.line);
127 + preedit.pline.line = xmalloc((term.col + 1) * sizeof(Glyph));
128 + for (i = 0; i < term.col + 1; i++)
129 + preedit.pline.line[i] = (Glyph){ ' ', ATTR_WDUMMY };
130 +
131 + x = term.col / 2 - preedit.pline.caret;
132 + x = MIN(x, 0);
133 + x = MAX(x, term.col - preedit.pline.width);
134 + x = MIN(x, term.c.x);
135 + preedit.pline.offset = x;
136 +
137 + for (i = 0; i < preedit.len; i++) {
138 + if (term.col < x)
139 + break;
140 + if (0 <= x)
141 + preedit.pline.line[x] = preedit.text[i];
142 + x += MAX(wcwidth(preedit.text[i].u), 1);
143 + }
144 +
145 + if (preedit.len == 0)
146 + term.dirty[term.c.y] = 1;
147 +
148 + if (preedit.pline.l.u == 0) {
149 + preedit.pline.l = preedit.pline.r = (Glyph){
150 + 0, ATTR_REVERSE, defaultfg, defaultbg
151 + };
152 + utf8decode("<", &preedit.pline.l.u, UTF_SIZ);
153 + utf8decode(">", &preedit.pline.r.u, UTF_SIZ);
154 + }
155 +}
156 +
157 void
158 drawregion(int x1, int y1, int x2, int y2)
159 {
160 @@ -2660,6 +2780,7 @@ draw(void)
161 drawregion(0, 0, term.col, term.row);
162 xdrawcursor(cx, term.c.y, term.line[term.c.y][cx],
163 term.ocx, term.ocy, term.line[term.ocy][term.oc…
164 + xdrawpreedit(&preedit.pline, term.line[term.c.y], term.c.y, ter…
165 term.ocx = cx;
166 term.ocy = term.c.y;
167 xfinishdraw();
168 diff --git a/st.h b/st.h
169 index fd3b0d8..97e1491 100644
170 --- a/st.h
171 +++ b/st.h
172 @@ -69,6 +69,14 @@ typedef struct {
173
174 typedef Glyph *Line;
175
176 +typedef struct {
177 + Line line;
178 + int offset;
179 + int width;
180 + int caret;
181 + Glyph l,r;
182 +} PLine;
183 +
184 typedef union {
185 int i;
186 uint ui;
187 @@ -95,6 +103,8 @@ int ttynew(const char *, char *, const char *, char *…
188 size_t ttyread(void);
189 void ttyresize(int, int);
190 void ttywrite(const char *, size_t, int);
191 +void pereset(void);
192 +void peupdate(int, int, int, unsigned short, const ushort *, const char…
193
194 void resettitle(void);
195
196 diff --git a/win.h b/win.h
197 index 6de960d..fb5a1d5 100644
198 --- a/win.h
199 +++ b/win.h
200 @@ -27,6 +27,7 @@ void xbell(void);
201 void xclipcopy(void);
202 void xdrawcursor(int, int, Glyph, int, int, Glyph);
203 void xdrawline(Line, int, int, int);
204 +void xdrawpreedit(PLine *, Line, int, int);
205 void xfinishdraw(void);
206 void xloadcols(void);
207 int xsetcolorname(int, const char *);
208 diff --git a/x.c b/x.c
209 index bd23686..fd6308e 100644
210 --- a/x.c
211 +++ b/x.c
212 @@ -99,6 +99,7 @@ typedef struct {
213 XIC xic;
214 XPoint spot;
215 XVaNestedList spotlist;
216 + XVaNestedList preeditattrs;
217 } ime;
218 Draw draw;
219 Visual *vis;
220 @@ -150,6 +151,10 @@ static int ximopen(Display *);
221 static void ximinstantiate(Display *, XPointer, XPointer);
222 static void ximdestroy(XIM, XPointer, XPointer);
223 static int xicdestroy(XIC, XPointer, XPointer);
224 +static void xpreeditstart(XIM , XPointer, XPointer);
225 +static void xpreeditdone(XIM, XPointer, XPointer);
226 +static void xpreeditdraw(XIM, XPointer, XIMPreeditDrawCallbackStruct *);
227 +static void xpreeditcaret(XIM, XPointer, XIMPreeditCaretCallbackStruct …
228 static void xinit(int, int);
229 static void cresize(int, int);
230 static void xresize(int, int);
231 @@ -1077,6 +1082,16 @@ ximopen(Display *dpy)
232 {
233 XIMCallback imdestroy = { .client_data = NULL, .callback = ximd…
234 XICCallback icdestroy = { .client_data = NULL, .callback = xicd…
235 + static XIMCallback pestart = { NULL, xpreeditstart };
236 + static XIMCallback pedone = { NULL, xpreeditdone };
237 + static XIMCallback pedraw = { NULL, (XIMProc)xpreeditdraw };
238 + static XIMCallback pecaret = { NULL, (XIMProc)xpreeditcaret };
239 + XIMStyles *styles;
240 + XIMStyle candidates[] = {
241 + XIMPreeditCallbacks | XIMStatusNothing,
242 + XIMPreeditNothing | XIMStatusNothing
243 + };
244 + int i, j;
245
246 xw.ime.xim = XOpenIM(xw.dpy, NULL, NULL, NULL);
247 if (xw.ime.xim == NULL)
248 @@ -1089,12 +1104,38 @@ ximopen(Display *dpy)
249 xw.ime.spotlist = XVaCreateNestedList(0, XNSpotLocation, &xw.im…
250 NULL);
251
252 + if (XGetIMValues(xw.ime.xim, XNQueryInputStyle, &styles, NULL))…
253 + fprintf(stderr, "XGetIMValues:"
254 + "Could not get XNQueryInputStyle.\n");
255 + return 1;
256 + }
257 + for (i = 0; i < LEN(candidates); i++)
258 + for (j = 0; j < styles->count_styles; j++)
259 + if (candidates[i] == styles->supported_styles[j…
260 + goto match;
261 + fprintf(stderr, "XGetIMValues: "
262 + "None of the candidates styles matched.\n");
263 + XFree(styles);
264 + return 1;
265 +match:
266 + XFree(styles);
267 +
268 if (xw.ime.xic == NULL) {
269 xw.ime.xic = XCreateIC(xw.ime.xim, XNInputStyle,
270 - XIMPreeditNothing | XIMStatusNot…
271 + candidates[i],
272 XNClientWindow, xw.win,
273 XNDestroyCallback, &icdestroy,
274 NULL);
275 + if (xw.ime.xic && candidates[i] & XIMPreeditCallbacks) {
276 + xw.ime.preeditattrs = XVaCreateNestedList(0,
277 + XNPreeditStartCallback, &pestar…
278 + XNPreeditDoneCallback, &pedone,
279 + XNPreeditDrawCallback, &pedraw,
280 + XNPreeditCaretCallback, &pecare…
281 + NULL);
282 + XSetICValues(xw.ime.xic, XNPreeditAttributes,
283 + xw.ime.preeditattrs, NULL);
284 + }
285 }
286 if (xw.ime.xic == NULL)
287 fprintf(stderr, "XCreateIC: Could not create input cont…
288 @@ -1123,9 +1164,64 @@ int
289 xicdestroy(XIC xim, XPointer client, XPointer call)
290 {
291 xw.ime.xic = NULL;
292 + XFree(xw.ime.preeditattrs);
293 + xw.ime.preeditattrs = NULL;
294 return 1;
295 }
296
297 +void
298 +xpreeditstart(XIM xim, XPointer client, XPointer call)
299 +{
300 + pereset();
301 +}
302 +
303 +void
304 +xpreeditdone(XIM xim, XPointer client, XPointer call)
305 +{
306 + pereset();
307 +}
308 +
309 +void
310 +xpreeditdraw(XIM xim, XPointer client, XIMPreeditDrawCallbackStruct *ca…
311 +{
312 + const XIMText *text = call->text;
313 + ushort *m, *modes = NULL;
314 + int i;
315 + XIMFeedback fb;
316 +
317 + if (!text) {
318 + peupdate(call->caret, call->chg_first, call->chg_length,
319 + 0, NULL, NULL);
320 + return;
321 + }
322 +
323 + if (text->feedback) {
324 + modes = xmalloc(text->length * sizeof(ushort));
325 + for (i = 0; i < text->length; i++) {
326 + m = modes + i;
327 + fb = text->feedback[i];
328 + *m = ATTR_NULL;
329 + *m |= fb & XIMReverse ? ATTR_REVERSE : ATT…
330 + *m |= fb & XIMUnderline ? ATTR_UNDERLINE : ATT…
331 + *m |= fb & XIMHighlight ? ATTR_BOLD : ATT…
332 + *m |= fb & XIMPrimary ? ATTR_ITALIC : ATT…
333 + *m |= fb & XIMSecondary ? ATTR_FAINT : ATT…
334 + *m |= fb & XIMTertiary ? ATTR_BOLD_FAINT : ATT…
335 + }
336 + }
337 +
338 + peupdate(call->caret, call->chg_first, call->chg_length,
339 + text->length, modes, text->string.multi_byte);
340 +
341 + free(modes);
342 +}
343 +
344 +void
345 +xpreeditcaret(XIM xim, XPointer client, XIMPreeditCaretCallbackStruct *…
346 +{
347 + peupdate(call->position, 0, 0, 0, NULL, NULL);
348 +}
349 +
350 void
351 xinit(int cols, int rows)
352 {
353 @@ -1682,6 +1778,35 @@ xdrawline(Line line, int x1, int y1, int x2)
354 xdrawglyphfontspecs(specs, base, i, ox, y1);
355 }
356
357 +void
358 +xdrawpreedit(PLine *pl, Line base, int y, int col)
359 +{
360 + int head, tail;
361 + int tcur;
362 + const int offc = pl->offset + pl->caret;
363 +
364 + if (pl->width == 0 || !(win.mode & MODE_FOCUSED))
365 + return;
366 +
367 + xdrawline(base, 0, y, col);
368 +
369 + head = MAX(pl->offset, 0);
370 + tail = MIN(pl->offset + pl->width, col);
371 + if (pl->line[head].mode & ATTR_WDUMMY)
372 + head++;
373 + xdrawline(pl->line, head, y, tail);
374 +
375 + tcur = win.cursor;
376 + win.cursor = 6;
377 + xdrawcursor(offc, y, pl->line[offc], head, y, pl->line[head]);
378 + win.cursor = tcur;
379 +
380 + if (pl->offset < 0)
381 + xdrawline(&pl->l, 0, y, 1);
382 + if (col < pl->offset + pl->width)
383 + xdrawline(&pl->r - (col - 1), col - 1, y, col);
384 +}
385 +
386 void
387 xfinishdraw(void)
388 {
You are viewing proxied material from suckless.org. 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.