lineset.c - gramscii - A simple editor for ASCII box-and-arrow charts DIR Log DIR Files DIR Refs DIR Tags DIR README DIR LICENSE --- lineset.c (4125B) --- 1 #define _POSIX_C_SOURCE 200112L 2 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <string.h> 6 #include "gramscii.h" 7 8 /** extern declarations **/ 9 10 extern lineset_t screen; /* what is visualised */ 11 extern lineset_t cutbuf; /* cut/paste buffer */ 12 extern lineset_t *undo; /* undo list */ 13 14 extern int undo_sz;/* allocated size of undo list*/ 15 extern int undo_cur;/* undo position */ 16 extern int undo_lst;/* last valid undo position */ 17 18 extern int WIDTH, HEIGHT; 19 20 extern char modified; /* set to 1 if screen modified since last save */ 21 22 /****/ 23 24 static int LONG_STEP; 25 26 /* line_t and lineset_t management */ 27 28 void ensure_line_length(line_t *l, int len){ 29 char *tmp; 30 31 if (l->sz < len + 1){ 32 tmp = realloc(l->s, (len+1) * 2 * sizeof(char)); 33 if (tmp == NULL){ 34 fprintf(stderr, "Unable to allocate string\n"); 35 cleanup(1); 36 } 37 l->s = tmp; 38 l->sz = (len + 1) * 2; 39 } 40 } 41 42 43 void alloc_line(line_t *l){ 44 char *tmp; 45 46 l->sz = WIDTH+1; 47 tmp = malloc((l->sz) * sizeof(char)); 48 if (tmp == NULL){ 49 fprintf(stderr, "unable to allocate line\n"); 50 cleanup(1); 51 } 52 l->s = tmp; 53 memset(l->s, BG, l->sz); 54 l->lst = -1; 55 l->s[0]='\0'; 56 } 57 58 void ensure_num_lines(lineset_t *ls, int n){ 59 line_t *tmp; 60 61 if (n > ls->sz){ 62 if (ls->sz == 0) 63 ls->l=NULL; 64 tmp = realloc(ls->l, (n + LONG_STEP) * sizeof(line_t)); 65 if (tmp == NULL){ 66 fprintf(stderr, "Unable to allocate memory for more lines"); 67 cleanup(1); 68 } 69 else { 70 ls->l = tmp; 71 while ( ls->sz < n + LONG_STEP){ 72 alloc_line(&(ls->l[ls->sz])); 73 ls->sz ++; 74 } 75 } 76 } 77 } 78 79 80 void dump_lines(lineset_t ls, FILE *f){ 81 int i; 82 for (i=0; i<ls.num ;i++){ 83 fprintf(f, "%s\n", ls.l[i].s); 84 } 85 fflush(f); 86 } 87 88 void pad_line_to_length(char *s, int W){ 89 90 int i; 91 92 for (i=strlen(s); i<W; i++){ 93 s[i] = BG; 94 } 95 } 96 97 /* cut/yank/paste/undo management */ 98 99 void yank_region(int x1, int y1, int x2, int y2){ 100 101 int N, W, i; 102 103 N = y2 - y1 + 1; 104 W = x2 - x1 + 1; 105 ensure_num_lines(&cutbuf, N); 106 107 for (i=y1; i<=y2; i++){ 108 ensure_line_length(&(cutbuf.l[i-y1]), W); 109 memcpy(cutbuf.l[i-y1].s, screen.l[i].s + x1, x2-x1+1); 110 if (strlen(cutbuf.l[i-y1].s) < W) 111 pad_line_to_length(cutbuf.l[i-y1].s, W); 112 cutbuf.l[i-y1].s[W] = '\0'; 113 cutbuf.l[i-y1].n = i; 114 } 115 cutbuf.num = N; 116 #ifdef DEBUG 117 dump_lines(cutbuf, stderr); 118 #endif 119 120 } 121 122 123 void paste_region(int x1, int y1){ 124 int i, curlen, pastelen; 125 126 i = y1; 127 while( i < HEIGHT && i < y1 + cutbuf.num){ 128 pastelen = strlen(cutbuf.l[i-y1].s); 129 curlen = strlen(screen.l[i].s); 130 memcpy(screen.l[i].s + x1, cutbuf.l[i-y1].s, pastelen); 131 if (curlen <= x1) 132 /* double-check this line below */ 133 pad_line_to_length(screen.l[i].s + curlen, x1 - curlen); 134 if (curlen <= x1 + pastelen) 135 screen.l[i].s[x1 + pastelen] = '\0'; 136 137 screen.l[i].lst = strlen(screen.l[i].s) - 1; 138 #ifdef DEBUG 139 fprintf(stderr, "%d.lst: %d\n", i, screen.l[i].lst); 140 #endif 141 i += 1; 142 modified = 1; 143 } 144 redraw(); 145 } 146 147 void copy_lines_to_ring(int y1, int y2, int which){ 148 int i, len, idx; 149 lineset_t *tmp; 150 151 if (y1 > y2){ 152 y1 ^= y2; 153 y2 ^= y1; 154 y1 ^= y2; 155 } 156 if (undo_cur > undo_lst) 157 undo_cur = undo_lst; 158 if (which == PRV_STATE){ /* adding a new previous state */ 159 undo_cur += 2; 160 idx = undo_cur; 161 } 162 else 163 idx = undo_cur + 1; 164 if (idx >= undo_sz - 1){ 165 tmp = realloc(undo, (undo_sz + 10) * sizeof(lineset_t)); 166 if (tmp == NULL){ 167 fprintf(stderr, "Error allocating undo buffer"); 168 cleanup(1); 169 } 170 undo = tmp; 171 for (i=0; i<10; i++){ 172 undo[undo_sz + i].sz = 0; 173 undo[undo_sz + i].l = NULL; 174 undo[undo_sz + i].num = 0; 175 } 176 undo_sz += 10; 177 } 178 ensure_num_lines(&(undo[idx]), y2 - y1 + 1); 179 for(i=y1; i<=y2; i++){ 180 len = strlen(screen.l[i].s); 181 ensure_line_length(&(undo[idx].l[i-y1]), len); 182 strcpy(undo[idx].l[i-y1].s, screen.l[i].s); 183 undo[idx].l[i-y1].n = i; 184 undo[idx].l[i-y1].lst = screen.l[i].lst; 185 } 186 undo[idx].num = y2 - y1 + 1; 187 if (which == PRV_STATE) 188 undo_lst = undo_cur; 189 #ifdef DEBUG 190 fprintf(stderr, "undo_ring: y1: %d y2: %d idx: %d\n", y1, y2, idx); 191 for(i=0; i<undo[idx].num; i++){ 192 fprintf(stderr, "UU: %d| %s\n", undo[idx].l[i].n, undo[idx].l[i].s); 193 } 194 #endif 195 } 196 197 void invalidate_undo(){ 198 if (undo_lst > undo_cur) 199 undo_lst = undo_cur; 200 }