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 }