1 /* rendering strings */
8 /* specify the screen position of the characters in s; reordering version */
9 static int *ren_position_reorder(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
);
33 /* specify the screen position of the characters in s; fast version */
34 int *ren_position(char *s
)
40 if (n
<= xlim
&& (xorder
== 2 || (xorder
== 1 && n
< strlen(s
))))
41 return ren_position_reorder(s
);
42 pos
= malloc((n
+ 1) * sizeof(pos
[0]));
43 for (i
= 0; i
< n
; i
++, s
+= uc_len(s
)) {
45 cpos
+= ren_cwid(s
, cpos
);
53 int *pos
= ren_position(s
);
60 /* find the next character after visual position p; if cur, start from p itself */
61 static int pos_next(int *pos
, int n
, int p
, int cur
)
64 for (i
= 0; i
< n
; i
++)
65 if (pos
[i
] - !cur
>= p
&& (ret
< 0 || pos
[i
] < pos
[ret
]))
67 return ret
>= 0 ? pos
[ret
] : -1;
70 /* find the previous character after visual position p; if cur, start from p itself */
71 static int pos_prev(int *pos
, int n
, int p
, int cur
)
74 for (i
= 0; i
< n
; i
++)
75 if (pos
[i
] + !cur
<= p
&& (ret
< 0 || pos
[i
] > pos
[ret
]))
77 return ret
>= 0 ? pos
[ret
] : -1;
80 /* convert character offset to visual position */
81 int ren_pos(char *s
, int off
)
84 int *pos
= ren_position(s
);
85 int ret
= off
< n
? pos
[off
] : 0;
90 /* convert visual position to character offset */
91 int ren_off(char *s
, int p
)
95 int *pos
= ren_position(s
);
97 p
= pos_prev(pos
, n
, p
, 1);
98 for (i
= 0; i
< n
; i
++)
102 return off
>= 0 ? off
: 0;
105 /* adjust cursor position */
106 int ren_cursor(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);
117 next
= pos_next(pos
, n
, p
, 0);
118 p
= (next
>= 0 ? next
: pos
[n
]) - 1;
120 return p
>= 0 ? p
: 0;
123 /* return an offset before EOL */
124 int ren_noeol(char *s
, int o
)
126 int n
= s
? uc_slen(s
) : 0;
129 return o
> 0 && uc_chr(s
, o
)[0] == '\n' ? o
- 1 : o
;
132 /* the position of the next character */
133 int ren_next(char *s
, int p
, int dir
)
136 int *pos
= ren_position(s
);
137 p
= pos_prev(pos
, n
, p
, 1);
139 p
= pos_next(pos
, n
, p
, 0);
141 p
= pos_prev(pos
, n
, p
, 0);
143 return s
&& uc_chr(s
, ren_off(s
, p
))[0] != '\n' ? p
: -1;
146 static char *ren_placeholder(char *s
, int *wid
)
148 static int bits
= 0xffff; /* common bits in placeholders */
151 if (bits
== 0xffff) {
152 for (i
= 0; !conf_placeholder(i
, &src
, &dst
, wid
); i
++)
153 bits
&= (unsigned char) *src
;
155 if ((((unsigned char) *s
) & bits
) == bits
) {
156 for (i
= 0; !conf_placeholder(i
, &src
, &dst
, wid
); i
++)
157 if (src
[0] == s
[0] && uc_code(src
) == uc_code(s
))
167 int ren_cwid(char *s
, int pos
)
171 return 8 - (pos
& 7);
172 if (ren_placeholder(s
, &wid
))
177 char *ren_translate(char *s
, char *ln
)
179 char *p
= ren_placeholder(s
, NULL
);
180 return p
|| !xshape
? p
: uc_shape(ln
, s
);