tmot.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
       ---
       tmot.c (5227B)
       ---
            1 #include <stdio.h>
            2 #include <string.h>
            3 #include "vi.h"
            4 
            5 int lbuf_indents(struct lbuf *lb, int r)
            6 {
            7         char *ln = lbuf_get(lb, r);
            8         int o;
            9         if (!ln)
           10                 return 0;
           11         for (o = 0; uc_isspace(ln); o++)
           12                 ln = uc_next(ln);
           13         return o;
           14 }
           15 
           16 static int uc_nextdir(char **s, char *beg, int dir)
           17 {
           18         if (dir < 0) {
           19                 if (*s == beg)
           20                         return 1;
           21                 *s = uc_prev(beg, *s);
           22         } else {
           23                 *s = uc_next(*s);
           24                 if (!(*s)[0])
           25                         return 1;
           26         }
           27         return 0;
           28 }
           29 
           30 int lbuf_findchar(struct lbuf *lb, char *cs, int cmd, int n, int *row, int *off)
           31 {
           32         char *ln = lbuf_get(lb, *row);
           33         char *s;
           34         int dir = (cmd == 'f' || cmd == 't') ? +1 : -1;
           35         if (!ln)
           36                 return 1;
           37         if (n < 0)
           38                 dir = -dir;
           39         if (n < 0)
           40                 n = -n;
           41         s = uc_chr(ln, *off);
           42         while (n > 0 && !uc_nextdir(&s, ln, dir))
           43                 if (uc_code(s) == uc_code(cs))
           44                         n--;
           45         if (!n && (cmd == 't' || cmd == 'T'))
           46                 uc_nextdir(&s, ln, -dir);
           47         if (!n)
           48                 *off = uc_off(ln, s - ln);
           49         return n != 0;
           50 }
           51 
           52 int lbuf_search(struct lbuf *lb, char *kw, int dir, int *r, int *o, int *len)
           53 {
           54         int offs[2];
           55         int found = 0;
           56         int r0 = *r, o0 = *o;
           57         int i;
           58         struct rstr *re = rstr_make(kw, xic ? RE_ICASE : 0);
           59         if (!re)
           60                 return 1;
           61         for (i = r0; !found && i >= 0 && i < lbuf_len(lb); i += dir) {
           62                 char *s = lbuf_get(lb, i);
           63                 int off = dir > 0 && r0 == i ? uc_chr(s, o0 + 1) - s : 0;
           64                 while (rstr_find(re, s + off, 1, offs,
           65                                 off ? RE_NOTBOL : 0) >= 0) {
           66                         if (dir < 0 && r0 == i &&
           67                                         uc_off(s, off + offs[0]) >= o0)
           68                                 break;
           69                         found = 1;
           70                         *o = uc_off(s, off + offs[0]);
           71                         *r = i;
           72                         *len = uc_off(s + off + offs[0], offs[1] - offs[0]);
           73                         off += offs[1] > offs[0] ? offs[1] : offs[1] + 1;
           74                         if (dir > 0 || !s[off] || s[off] == '\n')
           75                                 break;
           76                 }
           77         }
           78         rstr_free(re);
           79         return !found;
           80 }
           81 
           82 int lbuf_paragraphbeg(struct lbuf *lb, int dir, int *row, int *off)
           83 {
           84         while (*row >= 0 && *row < lbuf_len(lb) && !strcmp("\n", lbuf_get(lb, *row)))
           85                 *row += dir;
           86         while (*row >= 0 && *row < lbuf_len(lb) && strcmp("\n", lbuf_get(lb, *row)))
           87                 *row += dir;
           88         *row = MAX(0, MIN(*row, lbuf_len(lb) - 1));
           89         *off = 0;
           90         return 0;
           91 }
           92 
           93 int lbuf_sectionbeg(struct lbuf *lb, int dir, int *row, int *off)
           94 {
           95         *row += dir;
           96         while (*row >= 0 && *row < lbuf_len(lb) && lbuf_get(lb, *row)[0] != '{')
           97                 *row += dir;
           98         *row = MAX(0, MIN(*row, lbuf_len(lb) - 1));
           99         *off = 0;
          100         return 0;
          101 }
          102 
          103 static int lbuf_lnnext(struct lbuf *lb, int dir, int *r, int *o)
          104 {
          105         int off = *o + dir;
          106         if (off < 0 || !lbuf_get(lb, *r) || off >= uc_slen(lbuf_get(lb, *r)))
          107                 return 1;
          108         *o = off;
          109         return 0;
          110 }
          111 
          112 int lbuf_eol(struct lbuf *lb, int row)
          113 {
          114         int len = lbuf_get(lb, row) ? uc_slen(lbuf_get(lb, row)) : 0;
          115         return len ? len - 1 : 0;
          116 }
          117 
          118 static int lbuf_next(struct lbuf *lb, int dir, int *r, int *o)
          119 {
          120         if (dir < 0 && *r >= lbuf_len(lb))
          121                 *r = MAX(0, lbuf_len(lb) - 1);
          122         if (lbuf_lnnext(lb, dir, r, o)) {
          123                 if (!lbuf_get(lb, *r + dir))
          124                         return -1;
          125                 *r += dir;
          126                 *o = dir > 0 ? 0 : lbuf_eol(lb, *r);
          127                 return 0;
          128         }
          129         return 0;
          130 }
          131 
          132 /* return a pointer to the character at visual position c of line r */
          133 static char *lbuf_chr(struct lbuf *lb, int r, int c)
          134 {
          135         char *ln = lbuf_get(lb, r);
          136         return ln ? uc_chr(ln, c) : "";
          137 }
          138 
          139 /* move to the last character of the word */
          140 static int lbuf_wordlast(struct lbuf *lb, int kind, int dir, int *row, int *off)
          141 {
          142         if (!kind || !(uc_kind(lbuf_chr(lb, *row, *off)) & kind))
          143                 return 0;
          144         while (uc_kind(lbuf_chr(lb, *row, *off)) & kind)
          145                 if (lbuf_next(lb, dir, row, off))
          146                         return 1;
          147         if (!(uc_kind(lbuf_chr(lb, *row, *off)) & kind))
          148                 lbuf_next(lb, -dir, row, off);
          149         return 0;
          150 }
          151 
          152 int lbuf_wordbeg(struct lbuf *lb, int big, int dir, int *row, int *off)
          153 {
          154         int nl;
          155         lbuf_wordlast(lb, big ? 3 : uc_kind(lbuf_chr(lb, *row, *off)), dir, row, off);
          156         nl = uc_code(lbuf_chr(lb, *row, *off)) == '\n';
          157         if (lbuf_next(lb, dir, row, off))
          158                 return 1;
          159         while (uc_isspace(lbuf_chr(lb, *row, *off))) {
          160                 nl += uc_code(lbuf_chr(lb, *row, *off)) == '\n';
          161                 if (nl == 2)
          162                         return 0;
          163                 if (lbuf_next(lb, dir, row, off))
          164                         return 1;
          165         }
          166         return 0;
          167 }
          168 
          169 int lbuf_wordend(struct lbuf *lb, int big, int dir, int *row, int *off)
          170 {
          171         int nl = 0;
          172         if (!uc_isspace(lbuf_chr(lb, *row, *off))) {
          173                 if (lbuf_next(lb, dir, row, off))
          174                         return 1;
          175                 nl = dir < 0 && uc_code(lbuf_chr(lb, *row, *off)) == '\n';
          176         }
          177         nl += dir > 0 && uc_code(lbuf_chr(lb, *row, *off)) == '\n';
          178         while (uc_isspace(lbuf_chr(lb, *row, *off))) {
          179                 if (lbuf_next(lb, dir, row, off))
          180                         return 1;
          181                 nl += uc_code(lbuf_chr(lb, *row, *off)) == '\n';
          182                 if (nl == 2) {
          183                         if (dir < 0)
          184                                 lbuf_next(lb, -dir, row, off);
          185                         return 0;
          186                 }
          187         }
          188         if (lbuf_wordlast(lb, big ? 3 : uc_kind(lbuf_chr(lb, *row, *off)), dir, row, off))
          189                 return 1;
          190         return 0;
          191 }
          192 
          193 /* move to the matching character */
          194 int lbuf_pair(struct lbuf *lb, int *row, int *off)
          195 {
          196         int r = *row, o = *off;
          197         char *pairs = "()[]{}";
          198         int pchr;                /* parenthesis character */
          199         int pidx;                /* index into pairs[] */
          200         int dep = 1;                /* parenthesis depth */
          201         while ((pchr = (unsigned char) lbuf_chr(lb, r, o)[0]) && !strchr(pairs, pchr))
          202                 o++;
          203         if (!pchr)
          204                 return 1;
          205         pidx = strchr(pairs, pchr) - pairs;
          206         while (!lbuf_next(lb, (pidx & 1) ? -1 : +1, &r, &o)) {
          207                 int c = (unsigned char) lbuf_chr(lb, r, o)[0];
          208                 if (c == pairs[pidx ^ 1])
          209                         dep--;
          210                 if (c == pairs[pidx])
          211                         dep++;
          212                 if (!dep) {
          213                         *row = r;
          214                         *off = o;
          215                         return 0;
          216                 }
          217         }
          218         return 1;
          219 }