1 /* rendering strings */
8 /* specify the screen position of the characters in s */
9 int *ren_position(char *s
)
12 char **chrs
= uc_chop(s
, &n
);
15 pos
= malloc((n
+ 1) * sizeof(pos
[0]));
16 for (i
= 0; i
< n
; i
++)
20 off
= malloc(n
* sizeof(off
[0]));
21 for (i
= 0; i
< n
; i
++)
23 for (i
= 0; i
< n
; i
++) {
25 cpos
+= ren_cwid(chrs
[off
[i
]], cpos
);
35 int *pos
= ren_position(s
);
42 /* find the next character after visual position p; if cur, start from p itself */
43 static int pos_next(int *pos
, int n
, int p
, int cur
)
46 for (i
= 0; i
< n
; i
++)
47 if (pos
[i
] - !cur
>= p
&& (ret
< 0 || pos
[i
] < pos
[ret
]))
49 return ret
>= 0 ? pos
[ret
] : -1;
52 /* find the previous character after visual position p; if cur, start from p itself */
53 static int pos_prev(int *pos
, int n
, int p
, int cur
)
56 for (i
= 0; i
< n
; i
++)
57 if (pos
[i
] + !cur
<= p
&& (ret
< 0 || pos
[i
] > pos
[ret
]))
59 return ret
>= 0 ? pos
[ret
] : -1;
62 /* convert visual position to character offset */
63 int ren_pos(char *s
, int off
)
66 int *pos
= ren_position(s
);
67 int ret
= off
< n
? pos
[off
] : 0;
72 /* convert visual position to character offset */
73 int ren_off(char *s
, int p
)
77 int *pos
= ren_position(s
);
79 p
= pos_prev(pos
, n
, p
, 1);
80 for (i
= 0; i
< n
; i
++)
84 return off
>= 0 ? off
: 0;
87 /* adjust cursor position */
88 int ren_cursor(char *s
, int p
)
95 pos
= ren_position(s
);
96 p
= pos_prev(pos
, n
, p
, 1);
97 if (uc_code(uc_chr(s
, ren_off(s
, p
))) == '\n')
98 p
= pos_prev(pos
, n
, p
, 0);
99 next
= pos_next(pos
, n
, p
, 0);
100 p
= (next
>= 0 ? next
: pos
[n
]) - 1;
102 return p
>= 0 ? p
: 0;
105 /* real cursor position; never past EOL */
106 int ren_noeol(char *s
, int p
)
113 pos
= ren_position(s
);
114 p
= pos_prev(pos
, n
, p
, 1);
115 if (uc_code(uc_chr(s
, ren_off(s
, p
))) == '\n')
116 p
= pos_prev(pos
, n
, p
, 0);
118 return p
>= 0 ? p
: 0;
121 /* the position of the next character */
122 int ren_next(char *s
, int p
, int dir
)
125 int *pos
= ren_position(s
);
126 p
= pos_prev(pos
, n
, p
, 1);
128 p
= pos_next(pos
, n
, p
, 0);
130 p
= pos_prev(pos
, n
, p
, 0);
135 static void swap(int *i1
, int *i2
)
142 /* the region specified by two visual positions */
143 int ren_region(char *s
, int c1
, int c2
, int *l1
, int *l2
, int closed
)
145 int *ord
; /* ord[i]: the order of the i-th char on the screen */
150 if (c1
== c2
&& !closed
) {
151 *l1
= ren_off(s
, c1
);
152 *l2
= ren_off(s
, c2
);
155 ord
= malloc(n
* sizeof(ord
[0]));
156 for (i
= 0; i
< n
; i
++)
164 c2
= ren_next(s
, c2
, -1);
165 beg
= ren_off(s
, c1
);
166 end
= ren_off(s
, c2
);
173 for (i
= beg
; i
<= end
; i
++)
174 if (ord
[i
] < o1
|| ord
[i
] > o2
)
182 static char *ren_placeholder(char *s
)
187 for (i
= 0; !conf_placeholder(i
, &src
, &dst
, &wid
); i
++)
188 if (uc_code(src
) == c
)
193 int ren_cwid(char *s
, int pos
)
198 return 8 - (pos
& 7);
199 for (i
= 0; !conf_placeholder(i
, &src
, &dst
, &wid
); i
++)
200 if (uc_code(src
) == uc_code(s
))
205 char *ren_translate(char *s
, char *ln
)
207 char *p
= ren_placeholder(s
);
208 return p
|| !xshape
? p
: uc_shape(ln
, s
);