we’ll need to distinguish these for sarge/etch as well
[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.9 2017/12/02 02:07:29 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(BW *bw, int flg)
38 {
39         W *w = bw->parent;
40         PW *pw = (PW *) bw->object;
41
42         if (!flg) {
43                 return;
44         }
45
46         /* Scroll buffer and position prompt */
47         if (pw->promptlen > w->w / 2 + w->w / 4) {
48                 pw->promptofst = pw->promptlen - w->w / 2;
49                 if (piscol(bw->cursor) < w->w - (pw->promptlen - pw->promptofst)) {
50                         bw->offset = 0;
51                 } else {
52                         bw->offset = piscol(bw->cursor) - (w->w - (pw->promptlen - pw->promptofst) - 1);
53                 }
54         } else {
55                 if (piscol(bw->cursor) < w->w - pw->promptlen) {
56                         pw->promptofst = 0;
57                         bw->offset = 0;
58                 } else if (piscol(bw->cursor) >= w->w) {
59                         pw->promptofst = pw->promptlen;
60                         bw->offset = piscol(bw->cursor) - (w->w - 1);
61                 } else {
62                         pw->promptofst = pw->promptlen - (w->w - piscol(bw->cursor) - 1);
63                         bw->offset = piscol(bw->cursor) - (w->w - (pw->promptlen - pw->promptofst) - 1);
64                 }
65         }
66
67         /* Set cursor position */
68         w->curx = piscol(bw->cursor) - bw->offset + pw->promptlen - pw->promptofst;
69         w->cury = 0;
70
71         /* Generate prompt */
72         w->t->t->updtab[w->y] = 1;
73         genfmt(w->t->t, w->x, w->y, pw->promptofst, pw->prompt, 0);
74
75         /* Position and size buffer */
76         bwmove(bw, w->x + pw->promptlen - pw->promptofst, w->y);
77         bwresz(bw, w->w - (pw->promptlen - pw->promptofst), 1);
78
79         /* Generate buffer */
80         bwgen(bw, 0);
81 }
82
83 /* When user hits return in a prompt window */
84
85 extern volatile int dostaupd;
86
87 static int rtnpw(BW *bw)
88 {
89         W *w = bw->parent;
90         PW *pw = (PW *) bw->object;
91         unsigned char *s;
92         W *win;
93         int *notify;
94         int (*pfunc) ();
95         void *object;
96         long byte;
97
98         p_goto_eol(bw->cursor);
99         byte = bw->cursor->byte;
100         p_goto_bol(bw->cursor);
101         s = brvs(bw->cursor, (int) (byte - bw->cursor->byte));
102         if (pw->hist) {
103                 if (bw->b->changed) {
104                         P *q = pdup(pw->hist->eof);
105
106                         binsm(q, s, (int) (byte - bw->cursor->byte));
107                         p_goto_eof(q);
108                         binsc(q, '\n');
109                         prm(q);
110                 } else {
111                         P *q = pdup(pw->hist->bof);
112                         P *r;
113                         P *t;
114
115                         pline(q, bw->cursor->line);
116                         r = pdup(q);
117                         pnextl(r);
118                         t = pdup(pw->hist->eof);
119                         binsb(t, bcpy(q, r));
120                         bdel(q, r);
121                         prm(q);
122                         prm(r);
123                         prm(t);
124                 }
125         }
126         win = w->win;
127         pfunc = pw->pfunc;
128         object = pw->object;
129         bwrm(bw);
130         joe_free(pw->prompt);
131         joe_free(pw);
132         w->object = NULL;
133         notify = w->notify;
134         w->notify = 0;
135         wabort(w);
136         dostaupd = 1;
137         if (pfunc) {
138                 return pfunc(win->object, s, object, notify);
139         } else {
140                 return -1;
141         }
142 }
143
144 int ucmplt(BW *bw, int k)
145 {
146         PW *pw = (PW *) bw->object;
147
148         if (pw->tab) {
149                 return pw->tab(bw, k);
150         } else {
151                 return -1;
152         }
153 }
154
155 static void inspw(BW *bw, B *b, long l, long n, int flg)
156 {
157         if (b == bw->b) {
158                 bwins(bw, l, n, flg);
159         }
160 }
161
162 static void delpw(BW *bw, B *b, long l, long n, int flg)
163 {
164         if (b == bw->b) {
165                 bwdel(bw, l, n, flg);
166         }
167 }
168
169 static int abortpw(BW *b)
170 {
171         PW *pw = b->object;
172         void *object = pw->object;
173         int (*abrt) () = pw->abrt;
174
175         W *win = b->parent->win;
176
177         bwrm(b);
178         joe_free(pw->prompt);
179         joe_free(pw);
180         if (abrt) {
181                 return abrt(win->object, object);
182         } else {
183                 return -1;
184         }
185 }
186
187 WATOM watompw = {
188         US "prompt",
189         disppw,
190         bwfllw,
191         abortpw,
192         rtnpw,
193         utypebw,
194         NULL,
195         NULL,
196         inspw,
197         delpw,
198         TYPEPW
199 };
200
201 /* Create a prompt window */
202
203 BW *wmkpw(W *w, unsigned char *prompt, B **history, int (*func) (), const unsigned char *huh, int (*abrt) (), int (*tab) (), void *object, int *notify, struct charmap *map)
204 {
205         W *new;
206         PW *pw;
207         BW *bw;
208
209         new = wcreate(w->t, &watompw, w, w, w->main, 1, huh, notify);
210         if (!new) {
211                 if (notify) {
212                         *notify = 1;
213                 }
214                 return NULL;
215         }
216         wfit(new->t);
217         new->object = (void *) (bw = bwmk(new, bmk(NULL), 1));
218         bw->b->o.charmap = map;
219         bw->object = (void *) (pw = (PW *) joe_malloc(sizeof(PW)));
220         pw->abrt = abrt;
221         pw->tab = tab;
222         pw->object = object;
223         pw->prompt = (unsigned char *)strdup((char *)prompt);
224         pw->promptlen = fmtlen(prompt);
225         pw->promptofst = 0;
226         pw->pfunc = func;
227         if (history) {
228                 if (!*history) {
229                         *history = bmk(NULL);
230                 }
231                 pw->hist = *history;
232                 binsb(bw->cursor, bcpy(pw->hist->bof, pw->hist->eof));
233                 bw->b->changed = 0;
234                 p_goto_eof(bw->cursor);
235                 p_goto_eof(bw->top);
236                 p_goto_bol(bw->top);
237         } else {
238                 pw->hist = NULL;
239         }
240         w->t->curwin = new;
241         return bw;
242 }
243
244 /* Tab completion functions */
245
246 unsigned char **regsub(unsigned char **z, int len, unsigned char *s)
247 {
248         unsigned char **lst = NULL;
249         int x = -1;
250
251         while (++x < len)
252                 if (rmatch(s, z[x]))
253                         lst = vaadd(lst, vsncpy(NULL, 0, sz(z[x])));
254         return lst;
255 }
256
257 void cmplt_ins(BW *bw, unsigned char *line)
258 {
259         P *p = pdup(bw->cursor);
260
261         p_goto_bol(p);
262         p_goto_eol(bw->cursor);
263         bdel(p, bw->cursor);
264         binsm(bw->cursor, sv(line));
265         p_goto_eol(bw->cursor);
266         prm(p);
267         bw->cursor->xcol = piscol(bw->cursor);
268 }
269
270 int cmplt_abrt(BW *bw, int x, unsigned char *line)
271 {
272         if (line) {
273                 cmplt_ins(bw, line);
274                 vsrm(line);
275         }
276         return -1;
277 }
278
279 int cmplt_rtn(MENU *m, int x, unsigned char *line)
280 {
281         cmplt_ins(m->parent->win->object, m->list[x]);
282         vsrm(line);
283         m->object = NULL;
284         wabort(m->parent);
285         return 0;
286 }
287
288 int simple_cmplt(BW *bw,unsigned char **list)
289 {
290         MENU *m;
291         P *p, *q;
292         unsigned char *line;
293         unsigned char *line1;
294         unsigned char **lst;
295
296         p = pdup(bw->cursor);
297         p_goto_bol(p);
298         q = pdup(bw->cursor);
299         p_goto_eol(q);
300         line = brvs(p, (int) (q->byte - p->byte));      /* Assumes short lines :-) */
301         prm(p);
302         prm(q);
303
304         line1 = vsncpy(NULL, 0, sv(line));
305         line1 = vsadd(line1, '*');
306         lst = regsub(list, aLEN(list), line1);
307         vsrm(line1);
308
309         if (!lst) {
310                 ttputc(7);
311                 vsrm(line);
312                 return -1;
313         }
314
315         m = mkmenu(bw->parent, lst, cmplt_rtn, cmplt_abrt, NULL, 0, line, NULL);
316         if (!m) {
317                 varm(lst);
318                 vsrm(line);
319                 return -1;
320         }
321         if (aLEN(lst) == 1)
322                 return cmplt_rtn(m, 0, line);
323         else if (smode || isreg(line))
324                 return 0;
325         else {
326                 unsigned char *com = mcomplete(m);
327
328                 vsrm(m->object);
329                 m->object = com;
330                 wabort(m->parent);
331                 smode = 2;
332                 ttputc(7);
333                 return 0;
334         }
335 }