wmii

git clone git://oldgit.suckless.org/wmii/
Log | Files | Refs | README | LICENSE

caret.c (2820B)


      1 #include "dat.h"
      2 #include <ctype.h>
      3 #include <string.h>
      4 #include "fns.h"
      5 
      6 static int
      7 iswordrune(Rune r) {
      8 	if(isalpharune(r))
      9 		return 1;
     10 	return r < 0x80 && (r == '_' || isdigit(r));
     11 }
     12 
     13 static char*
     14 prev_rune(char *start, char *p, Rune *r) {
     15 
     16 	*r = 0;
     17 	if(p == start)
     18 		return p;
     19 	while(p > start && (*(--p)&0xC0) == 0x80)
     20 		;
     21 	chartorune(r, p);
     22 	return p;
     23 }
     24 
     25 static char*
     26 next_rune(char *p, Rune *r) {
     27 	int i;
     28 
     29 	*r = 0;
     30 	if(!*p)
     31 		return p;
     32 	i = chartorune(r, p);
     33 	return p + i;
     34 }
     35 
     36 void
     37 caret_set(int start, int end) {
     38 	int len;
     39 
     40 	len = input.end - input.string;
     41 	start = max(0, min(len, start));
     42 
     43 	input.pos = input.string + start;
     44 	if(end < 0)
     45 		input.pos_end = nil;
     46 	else
     47 		input.pos_end = input.string + max(start, end);
     48 }
     49 
     50 char*
     51 caret_find(int dir, int type) {
     52 	char *end;
     53 	char *next, *p;
     54 	Rune r;
     55 	int res;
     56 
     57 	p = input.pos;
     58 	if(dir == FORWARD) {
     59 		end = input.end;
     60 		switch(type) {
     61 		case LINE:
     62 			return end;
     63 		case WORD:
     64 			chartorune(&r, p);
     65 			res = iswordrune(r);
     66 			while(next=next_rune(p, &r), r && iswordrune(r) == res && !isspacerune(r))
     67 				p = next;
     68 			while(next=next_rune(p, &r), r && isspacerune(r))
     69 				p = next;
     70 			return p;
     71 		case CHAR:
     72 			return next_rune(p, &r);
     73 		}
     74 	}
     75 	else if(dir == BACKWARD) {
     76 		end = input.string;
     77 		switch(type) {
     78 		case LINE:
     79 			return end;
     80 		case WORD:
     81 			while(next=prev_rune(end, p, &r), r && isspacerune(r))
     82 				p = next;
     83 			prev_rune(end, p, &r);
     84 			res = iswordrune(r);
     85 			while(next=prev_rune(end, p, &r), r && iswordrune(r) == res && !isspacerune(r))
     86 				p = next;
     87 			return p;
     88 		case CHAR:
     89 			return prev_rune(end, p, &r);
     90 		}
     91 	}
     92 	input.pos_end = nil;
     93 	return input.pos;
     94 }
     95 
     96 void
     97 caret_move(int dir, int type) {
     98 	input.pos = caret_find(dir, type);
     99 	input.pos_end = nil;
    100 }
    101 
    102 void
    103 caret_delete(int dir, int type) {
    104 	char *pos, *p;
    105 	int n;
    106 
    107 	if(input.pos_end)
    108 		p = input.pos_end;
    109 	else
    110 		p = caret_find(dir, type);
    111 	pos = input.pos;
    112 	if(p == input.end)
    113 		input.end = pos;
    114 	else {
    115 		if(p < pos) {
    116 			pos = p;
    117 			p = input.pos;
    118 		}
    119 		n = input.end - p;
    120 		memmove(pos, p, n);
    121 		input.pos = pos;
    122 		input.end = pos + n;
    123 	}
    124 	*input.end = '\0';
    125 	input.pos_end = nil;
    126 }
    127 
    128 void
    129 caret_insert(char *s, bool clear) {
    130 	int pos, end, len, size;
    131 
    132 	if(s == nil)
    133 		return;
    134 	if(clear) {
    135 		input.pos = input.string;
    136 		input.end = input.string;
    137 	}else if(input.pos_end)
    138 		caret_delete(0, 0);
    139 
    140 	len = strlen(s);
    141 	pos = input.pos - input.string;
    142 	end = input.end - input.string;
    143 
    144 	size = input.size;
    145 	if(input.size == 0)
    146 		input.size = 1;
    147 	while(input.size < end + len + 1)
    148 		input.size <<= 2;
    149 	if(input.size != size)
    150 		input.string = erealloc(input.string, input.size);
    151 
    152 	input.pos = input.string + pos;
    153 	input.end = input.string + end + len;
    154 	*input.end = '\0';
    155 	memmove(input.pos + len, input.pos, end - pos);
    156 	memmove(input.pos, s, len);
    157 	input.pos += len;
    158 	input.pos_end = nil;
    159 }
    160