|
|
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 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 } |
|