lineset.c - gramscii - A simple editor for ASCII box-and-arrow charts | |
Log | |
Files | |
Refs | |
Tags | |
README | |
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 m… | |
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 - … | |
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, id… | |
191 for(i=0; i<undo[idx].num; i++){ | |
192 fprintf(stderr, "UU: %d| %s\n", undo[idx].l[i].n, undo[i… | |
193 } | |
194 #endif | |
195 } | |
196 | |
197 void invalidate_undo(){ | |
198 if (undo_lst > undo_cur) | |
199 undo_lst = undo_cur; | |
200 } |