tren.c - neatvi - [fork] simple vi-type editor with UTF-8 support
 (HTM) git clone git://src.adamsgaard.dk/neatvi
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
       ---
       tren.c (3770B)
       ---
            1 /* rendering strings */
            2 #include <ctype.h>
            3 #include <stdio.h>
            4 #include <stdlib.h>
            5 #include <string.h>
            6 #include "vi.h"
            7 
            8 /* specify the screen position of the characters in s; reordering version */
            9 int *ren_position_reorder(char *s)
           10 {
           11         int i, n;
           12         char **chrs = uc_chop(s, &n);
           13         int *off, *pos;
           14         int cpos = 0;
           15         pos = malloc((n + 1) * sizeof(pos[0]));
           16         for (i = 0; i < n; i++)
           17                 pos[i] = i;
           18         if (xorder)
           19                 dir_reorder(s, pos);
           20         off = malloc(n * sizeof(off[0]));
           21         for (i = 0; i < n; i++)
           22                 off[pos[i]] = i;
           23         for (i = 0; i < n; i++) {
           24                 pos[off[i]] = cpos;
           25                 cpos += ren_cwid(chrs[off[i]], cpos);
           26         }
           27         pos[n] = cpos;
           28         free(chrs);
           29         free(off);
           30         return pos;
           31 }
           32 
           33 /* specify the screen position of the characters in s; fast version */
           34 int *ren_position(char *s)
           35 {
           36         int cpos = 0;
           37         int *pos;
           38         int i;
           39         int n = uc_slen(s);
           40         if (n <= xlim && xorder)
           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)) {
           44                 pos[i] = cpos;
           45                 cpos += ren_cwid(s, cpos);
           46         }
           47         pos[i] = cpos;
           48         return pos;
           49 }
           50 
           51 int ren_wid(char *s)
           52 {
           53         int *pos = ren_position(s);
           54         int n = uc_slen(s);
           55         int ret = pos[n];
           56         free(pos);
           57         return ret;
           58 }
           59 
           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)
           62 {
           63         int i, ret = -1;
           64         for (i = 0; i < n; i++)
           65                 if (pos[i] - !cur >= p && (ret < 0 || pos[i] < pos[ret]))
           66                         ret = i;
           67         return ret >= 0 ? pos[ret] : -1;
           68 }
           69 
           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)
           72 {
           73         int i, ret = -1;
           74         for (i = 0; i < n; i++)
           75                 if (pos[i] + !cur <= p && (ret < 0 || pos[i] > pos[ret]))
           76                         ret = i;
           77         return ret >= 0 ? pos[ret] : -1;
           78 }
           79 
           80 /* convert character offset to visual position */
           81 int ren_pos(char *s, int off)
           82 {
           83         int n = uc_slen(s);
           84         int *pos = ren_position(s);
           85         int ret = off < n ? pos[off] : 0;
           86         free(pos);
           87         return ret;
           88 }
           89 
           90 /* convert visual position to character offset */
           91 int ren_off(char *s, int p)
           92 {
           93         int off = -1;
           94         int n = uc_slen(s);
           95         int *pos = ren_position(s);
           96         int i;
           97         p = pos_prev(pos, n, p, 1);
           98         for (i = 0; i < n; i++)
           99                 if (pos[i] == p)
          100                         off = i;
          101         free(pos);
          102         return off >= 0 ? off : 0;
          103 }
          104 
          105 /* adjust cursor position */
          106 int ren_cursor(char *s, int p)
          107 {
          108         int n, next;
          109         int *pos;
          110         if (!s)
          111                 return 0;
          112         n = uc_slen(s);
          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;
          119         free(pos);
          120         return p >= 0 ? p : 0;
          121 }
          122 
          123 /* return an offset before EOL */
          124 int ren_noeol(char *s, int o)
          125 {
          126         int n = s ? uc_slen(s) : 0;
          127         if (o >= n)
          128                 o = MAX(0, n - 1);
          129         return o > 0 && uc_chr(s, o)[0] == '\n' ? o - 1 : o;
          130 }
          131 
          132 /* the position of the next character */
          133 int ren_next(char *s, int p, int dir)
          134 {
          135         int n = uc_slen(s);
          136         int *pos = ren_position(s);
          137         p = pos_prev(pos, n, p, 1);
          138         if (dir >= 0)
          139                 p = pos_next(pos, n, p, 0);
          140         else
          141                 p = pos_prev(pos, n, p, 0);
          142         free(pos);
          143         return s && uc_chr(s, ren_off(s, p))[0] != '\n' ? p : -1;
          144 }
          145 
          146 static char *ren_placeholder(char *s, int *wid)
          147 {
          148         char *src, *dst;
          149         int i;
          150         for (i = 0; !conf_placeholder(i, &src, &dst, wid); i++)
          151                 if (src[0] == s[0] && uc_code(src) == uc_code(s))
          152                         return dst;
          153         if (wid)
          154                 *wid = 1;
          155         if (uc_iscomb(s)) {
          156                 static char buf[16];
          157                 char cbuf[8] = "";
          158                 memcpy(cbuf, s, uc_len(s));
          159                 sprintf(buf, "ـ%s", cbuf);
          160                 return buf;
          161         }
          162         if (uc_isbell(s))
          163                 return "�";
          164         return NULL;
          165 }
          166 
          167 int ren_cwid(char *s, int pos)
          168 {
          169         int wid;
          170         if (s[0] == '\t')
          171                 return 8 - (pos & 7);
          172         if (ren_placeholder(s, &wid))
          173                 return wid;
          174         return uc_wid(s);
          175 }
          176 
          177 char *ren_translate(char *s, char *ln)
          178 {
          179         char *p = ren_placeholder(s, NULL);
          180         return p || !xshape ? p : uc_shape(ln, s);
          181 }