another update from CVS HEAD, for QA
[alioth/jupp.git] / pw.c
1 /*
2  *      Prompt windows
3  *      Copyright
4  *              (C) 1992 Joseph H. Allen
5  *
6  *      This file is part of JOE (Joe's Own Editor)
7  */
8 #include "config.h"
9 #include "types.h"
10
11 __RCSID("$MirOS: contrib/code/jupp/pw.c,v 1.14 2017/12/08 02:00:39 tg Exp $");
12
13 #include <stdlib.h>
14 #include <string.h>
15
16 #include "b.h"
17 #include "bw.h"
18 #include "help.h"
19 #include "kbd.h"
20 #include "path.h"
21 #include "pw.h"
22 #include "scrn.h"
23 #include "tab.h"
24 #include "termcap.h"
25 #include "tw.h"
26 #include "uedit.h"
27 #include "undo.h"
28 #include "utils.h"
29 #include "vfile.h"
30 #include "menu.h"
31 #include "va.h"
32 #include "w.h"
33
34 extern int smode;
35 extern int dobeep;
36
37 static void disppw(jobject jO, int flg)
38 {
39         BW *bw = jO.bw;
40         W *w = bw->parent;
41         PW *pw = (PW *) bw->object;
42
43         if (!flg) {
44                 return;
45         }
46
47         /* Scroll buffer and position prompt */
48         if (pw->promptlen > w->w / 2 + w->w / 4) {
49                 pw->promptofst = pw->promptlen - w->w / 2;
50                 if (piscol(bw->cursor) < w->w - (pw->promptlen - pw->promptofst)) {
51                         bw->offset = 0;
52                 } else {
53                         bw->offset = piscol(bw->cursor) - (w->w - (pw->promptlen - pw->promptofst) - 1);
54                 }
55         } else {
56                 if (piscol(bw->cursor) < w->w - pw->promptlen) {
57                         pw->promptofst = 0;
58                         bw->offset = 0;
59                 } else if (piscol(bw->cursor) >= w->w) {
60                         pw->promptofst = pw->promptlen;
61                         bw->offset = piscol(bw->cursor) - (w->w - 1);
62                 } else {
63                         pw->promptofst = pw->promptlen - (w->w - piscol(bw->cursor) - 1);
64                         bw->offset = piscol(bw->cursor) - (w->w - (pw->promptlen - pw->promptofst) - 1);
65                 }
66         }
67
68         /* Set cursor position */
69         w->curx = piscol(bw->cursor) - bw->offset + pw->promptlen - pw->promptofst;
70         w->cury = 0;
71
72         /* Generate prompt */
73         w->t->t->updtab[w->y] = 1;
74         genfmt(w->t->t, w->x, w->y, pw->promptofst, pw->prompt, 0);
75
76         /* Position and size buffer */
77         bwmove(bw, w->x + pw->promptlen - pw->promptofst, w->y);
78         bwresz(bw, w->w - (pw->promptlen - pw->promptofst), 1);
79
80         /* Generate buffer */
81         bwgen(bw, 0);
82 }
83
84 /* When user hits return in a prompt window */
85
86 extern volatile int dostaupd;
87
88 static int rtnpw(jobject jO)
89 {
90         BW *bw = jO.bw;
91         W *w = bw->parent;
92         PW *pw = (PW *) bw->object;
93         unsigned char *s;
94         W *win;
95         int *notify;
96         jpoly_int *pfunc;
97         void *object;
98         long byte;
99
100         p_goto_eol(bw->cursor);
101         byte = bw->cursor->byte;
102         p_goto_bol(bw->cursor);
103         s = brvs(bw->cursor, (int)(byte - bw->cursor->byte));
104         if (pw->hist) {
105                 if (bw->b->changed) {
106                         P *q = pdup(pw->hist->eof);
107                         P *r = pdup(q);
108                         unsigned char *s2;
109                         long byte2;
110
111                         pprevl(r);
112                         byte2 = r->byte;
113                         p_goto_bol(r);
114                         s2 = brs(r, (int)(byte2 - r->byte));
115                         prm(r);
116                         byte2 = strcmp(s, s2);
117                         free(s2);
118                         if (byte2) {
119                                 binsm(q, s, (int)(byte - bw->cursor->byte));
120                                 p_goto_eof(q);
121                                 binsc(q, '\n');
122                         }
123                         prm(q);
124                 } else {
125                         P *q = pdup(pw->hist->bof);
126                         P *r;
127                         P *t;
128
129                         pline(q, bw->cursor->line);
130                         r = pdup(q);
131                         pnextl(r);
132                         t = pdup(pw->hist->eof);
133                         binsb(t, bcpy(q, r));
134                         bdel(q, r);
135                         prm(q);
136                         prm(r);
137                         prm(t);
138                 }
139         }
140         win = w->win;
141         pfunc = pw->pfunc;
142         object = pw->object;
143         bwrm(bw);
144         free(pw->prompt);
145         free(pw);
146         w->object.base = NULL;
147         notify = w->notify;
148         w->notify = 0;
149         wabort(w);
150         dostaupd = 1;
151         if (pfunc) {
152                 return pfunc(win->object, s, object, notify);
153         } else {
154                 return -1;
155         }
156 }
157
158 int ucmplt(BW *bw, int k)
159 {
160         PW *pw = (PW *) bw->object;
161
162         if (pw->tab) {
163                 return pw->tab(bw, k);
164         } else {
165                 return -1;
166         }
167 }
168
169 static void inspw(BW *bw, B *b, long l, long n, int flg)
170 {
171         if (b == bw->b) {
172                 bwins(bw, l, n, flg);
173         }
174 }
175
176 static void delpw(BW *bw, B *b, long l, long n, int flg)
177 {
178         if (b == bw->b) {
179                 bwdel(bw, l, n, flg);
180         }
181 }
182
183 static int abortpw(jobject jO)
184 {
185         BW *b = jO.bw;
186         PW *pw = b->object;
187         void *object = pw->object;
188         jpoly_int *abrt = pw->abrt;
189
190         W *win = b->parent->win;
191
192         bwrm(b);
193         free(pw->prompt);
194         free(pw);
195         if (abrt) {
196                 return abrt(win->object, object);
197         } else {
198                 return -1;
199         }
200 }
201
202 WATOM watompw = {
203         US "prompt",
204         disppw,
205         bwfllw,
206         abortpw,
207         rtnpw,
208         utypebw,
209         NULL,
210         NULL,
211         inspw,
212         delpw,
213         TYPEPW
214 };
215
216 /* Create a prompt window */
217
218 BW *wmkpw(W *w, const unsigned char *prompt, B **history, jpoly_int *func, const unsigned char *huh, jpoly_int *abrt, jpoly_int *tab, void *object, int *notify, struct charmap *map)
219 {
220         W *new;
221         PW *pw;
222         BW *bw;
223
224         new = wcreate(w->t, &watompw, w, w, w->main, 1, huh, notify);
225         if (!new) {
226                 if (notify) {
227                         *notify = 1;
228                 }
229                 return NULL;
230         }
231         wfit(new->t);
232         new->object.bw = bw = bwmk(new, bmk(NULL), 1);
233         bw->b->o.charmap = map;
234         bw->object = pw = malloc(sizeof(PW));
235         pw->abrt = abrt;
236         pw->tab = tab;
237         pw->object = object;
238         pw->prompt = (unsigned char *)strdup((const char *)prompt);
239         pw->promptlen = fmtlen(prompt);
240         pw->promptofst = 0;
241         pw->pfunc = func;
242         if (history) {
243                 if (!*history) {
244                         *history = bmk(NULL);
245                 }
246                 pw->hist = *history;
247                 binsb(bw->cursor, bcpy(pw->hist->bof, pw->hist->eof));
248                 bw->b->changed = 0;
249                 p_goto_eof(bw->cursor);
250                 p_goto_eof(bw->top);
251                 p_goto_bol(bw->top);
252         } else {
253                 pw->hist = NULL;
254         }
255         w->t->curwin = new;
256         return bw;
257 }
258
259 /* Tab completion functions */
260
261 unsigned char **regsub(unsigned char **z, int len, unsigned char *s)
262 {
263         unsigned char **lst = NULL;
264         int x = -1;
265
266         while (++x < len)
267                 if (rmatch(s, z[x]))
268                         lst = vaadd(lst, vsncpy(NULL, 0, sz(z[x])));
269         return lst;
270 }
271
272 void cmplt_ins(BW *bw, unsigned char *line)
273 {
274         P *p = pdup(bw->cursor);
275
276         p_goto_bol(p);
277         p_goto_eol(bw->cursor);
278         bdel(p, bw->cursor);
279         binsm(bw->cursor, sv(line));
280         p_goto_eol(bw->cursor);
281         prm(p);
282         bw->cursor->xcol = piscol(bw->cursor);
283 }
284
285 int cmplt_abrt(BW *bw, int x, unsigned char *line)
286 {
287         if (line) {
288                 cmplt_ins(bw, line);
289                 vsrm(line);
290         }
291         return -1;
292 }
293
294 int cmplt_rtn(MENU *m, int x, unsigned char *line)
295 {
296         cmplt_ins(m->parent->win->object.bw, m->list[x]);
297         vsrm(line);
298         m->object = NULL;
299         wabort(m->parent);
300         return 0;
301 }
302
303 int simple_cmplt(BW *bw,unsigned char **list)
304 {
305         MENU *m;
306         P *p, *q;
307         unsigned char *line;
308         unsigned char *line1;
309         unsigned char **lst;
310
311         p = pdup(bw->cursor);
312         p_goto_bol(p);
313         q = pdup(bw->cursor);
314         p_goto_eol(q);
315         line = brvs(p, (int) (q->byte - p->byte));      /* Assumes short lines :-) */
316         prm(p);
317         prm(q);
318
319         line1 = vsncpy(NULL, 0, sv(line));
320         line1 = vsadd(line1, '*');
321         lst = regsub(list, aLEN(list), line1);
322         vsrm(line1);
323
324         if (!lst) {
325                 ttputc(7);
326                 vsrm(line);
327                 return -1;
328         }
329
330         m = mkmenu(bw->parent, lst, cmplt_rtn, cmplt_abrt, NULL, 0, line, NULL);
331         if (!m) {
332                 varm(lst);
333                 vsrm(line);
334                 return -1;
335         }
336         if (aLEN(lst) == 1)
337                 return cmplt_rtn(m, 0, line);
338         else if (smode || isreg(line))
339                 return 0;
340         else {
341                 unsigned char *com = mcomplete(m);
342
343                 vsrm(m->object);
344                 m->object = com;
345                 wabort(m->parent);
346                 smode = 2;
347                 ttputc(7);
348                 return 0;
349         }
350 }