7 #define MARK(c) ((c) >= 'a' && (c) <= 'z' ? (c) - 'a' : 30)
11 char *buf
; /* text inserted or deleted */
12 int ins
; /* insertion operation if non-zero */
14 int seq
; /* operation number */
19 int mark
[32]; /* buffer marks */
20 struct lopt hist
[128]; /* buffer history */
21 int undo
; /* current index into hist[] */
22 int useq
; /* current operation sequence */
23 char **ln
; /* lines */
24 int ln_n
; /* number of lbuf in l[] */
25 int ln_sz
; /* size of l[] */
28 struct lbuf
*lbuf_make(void)
30 struct lbuf
*lb
= malloc(sizeof(*lb
));
32 memset(lb
, 0, sizeof(*lb
));
33 for (i
= 0; i
< LEN(lb
->mark
); i
++)
38 void lbuf_free(struct lbuf
*lb
)
41 for (i
= 0; i
< lb
->ln_n
; i
++)
43 for (i
= 0; i
< LEN(lb
->hist
); i
++)
44 free(lb
->hist
[i
].buf
);
49 /* insert a line at pos */
50 static void lbuf_insertline(struct lbuf
*lb
, int pos
, char *s
)
52 if (lb
->ln_n
== lb
->ln_sz
) {
53 int nsz
= lb
->ln_sz
+ 512;
54 char **nln
= malloc(nsz
* sizeof(nln
[0]));
55 memcpy(nln
, lb
->ln
, lb
->ln_n
* sizeof(lb
->ln
[0]));
60 memmove(lb
->ln
+ pos
+ 1, lb
->ln
+ pos
,
61 (lb
->ln_n
- pos
) * sizeof(lb
->ln
[0]));
66 /* low-level insertion */
67 static void lbuf_insert(struct lbuf
*lb
, int pos
, char *s
)
71 int lb_len
= lbuf_len(lb
);
74 for (i
= 0; i
< len
; i
++) {
75 sbuf_chr(sb
, (unsigned char) s
[i
]);
77 lbuf_insertline(lb
, pos
++, sbuf_done(sb
));
82 for (i
= 0; i
< LEN(lb
->mark
); i
++) /* updating marks */
83 if (lb
->mark
[i
] >= pos
)
84 lb
->mark
[i
] += lbuf_len(lb
) - lb_len
;
87 /* low-level deletion */
88 static void lbuf_delete(struct lbuf
*lb
, int beg
, int end
)
91 for (i
= beg
; i
< end
; i
++)
93 memmove(lb
->ln
+ beg
, lb
->ln
+ end
, (lb
->ln_n
- end
) * sizeof(lb
->ln
[0]));
94 lb
->ln_n
-= end
- beg
;
95 for (i
= 0; i
< LEN(lb
->mark
); i
++) /* updating marks */
96 if (lb
->mark
[i
] > beg
)
97 lb
->mark
[i
] = MAX(beg
, lb
->mark
[i
] + beg
- end
);
100 /* append undo/redo history */
101 static void lbuf_opt(struct lbuf
*lb
, int ins
, int beg
, int end
)
103 struct lopt
*lo
= &lb
->hist
[0];
104 int n
= LEN(lb
->hist
);
107 for (i
= 0; i
< lb
->undo
; i
++)
108 free(lb
->hist
[i
].buf
);
109 memmove(lb
->hist
+ 1, lb
->hist
+ lb
->undo
,
110 (n
- lb
->undo
) * sizeof(lb
->hist
[0]));
111 for (i
= n
- lb
->undo
+ 1; i
< n
; i
++)
112 lb
->hist
[i
].buf
= NULL
;
114 free(lb
->hist
[n
- 1].buf
);
115 memmove(lb
->hist
+ 1, lb
->hist
, (n
- 1) * sizeof(lb
->hist
[0]));
120 lo
->buf
= lbuf_cp(lb
, beg
, end
);
125 void lbuf_rd(struct lbuf
*lbuf
, int fd
, int pos
)
131 while ((nr
= read(fd
, buf
, sizeof(buf
))) > 0)
132 sbuf_mem(sb
, buf
, nr
);
133 lbuf_put(lbuf
, pos
, sbuf_buf(sb
));
137 void lbuf_wr(struct lbuf
*lbuf
, int fd
, int beg
, int end
)
140 for (i
= beg
; i
< end
; i
++)
141 write(fd
, lbuf
->ln
[i
], strlen(lbuf
->ln
[i
]));
144 void lbuf_rm(struct lbuf
*lb
, int beg
, int end
)
148 lbuf_opt(lb
, 0, beg
, end
);
149 lbuf_delete(lb
, beg
, end
);
152 void lbuf_put(struct lbuf
*lb
, int pos
, char *s
)
154 int lb_len
= lbuf_len(lb
);
155 lbuf_insert(lb
, pos
, s
);
156 lbuf_opt(lb
, 1, pos
, pos
+ lbuf_len(lb
) - lb_len
);
159 char *lbuf_cp(struct lbuf
*lb
, int beg
, int end
)
164 for (i
= beg
; i
< end
; i
++)
166 sbuf_str(sb
, lb
->ln
[i
]);
167 return sbuf_done(sb
);
170 char *lbuf_get(struct lbuf
*lb
, int pos
)
172 return pos
>= 0 && pos
< lb
->ln_n
? lb
->ln
[pos
] : NULL
;
175 int lbuf_len(struct lbuf
*lb
)
180 void lbuf_mark(struct lbuf
*lbuf
, int mark
, int pos
)
182 lbuf
->mark
[MARK(mark
)] = pos
;
185 int lbuf_markpos(struct lbuf
*lbuf
, int mark
)
187 return lbuf
->mark
[MARK(mark
)];
190 static struct lopt
*lbuf_lopt(struct lbuf
*lb
, int i
)
192 struct lopt
*lo
= &lb
->hist
[i
];
193 return i
>= 0 && i
< LEN(lb
->hist
) && lo
->buf
? lo
: NULL
;
196 void lbuf_undo(struct lbuf
*lb
)
198 struct lopt
*lo
= lbuf_lopt(lb
, lb
->undo
);
199 int useq
= lo
? lo
->seq
: 0;
200 while (lo
&& lo
->seq
== useq
) {
203 lbuf_delete(lb
, lo
->beg
, lo
->end
);
205 lbuf_insert(lb
, lo
->beg
, lo
->buf
);
206 lo
= lbuf_lopt(lb
, lb
->undo
);
210 void lbuf_redo(struct lbuf
*lb
)
212 struct lopt
*lo
= lbuf_lopt(lb
, lb
->undo
- 1);
213 int useq
= lo
? lo
->seq
: 0;
214 while (lo
&& lo
->seq
== useq
) {
217 lbuf_insert(lb
, lo
->beg
, lo
->buf
);
219 lbuf_delete(lb
, lo
->beg
, lo
->end
);
220 lo
= lbuf_lopt(lb
, lb
->undo
- 1);
224 void lbuf_undofree(struct lbuf
*lb
)
227 for (i
= 0; i
< LEN(lb
->hist
); i
++)
228 free(lb
->hist
[i
].buf
);
229 memset(lb
->hist
, 0, sizeof(lb
->hist
));
233 void lbuf_undomark(struct lbuf
*lbuf
)