another update from CVS HEAD, for QA
[alioth/jupp.git] / tw.c
1 /*
2  *      Text editing 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/tw.c,v 1.20 2017/12/08 03:24:15 tg Exp $");
12
13 #include <stdlib.h>
14 #include <string.h>
15 #ifdef HAVE_TIME_H
16 #include <time.h>
17 #endif
18
19 #ifdef HAVE_BSD_STRING_H
20 #include <bsd/string.h>
21 #endif
22
23 #include "b.h"
24 #include "bw.h"
25 #include "macro.h"
26 #include "main.h"
27 #include "qw.h"
28 #include "scrn.h"
29 #include "uedit.h"
30 #include "ufile.h"
31 #include "ushell.h"
32 #include "utils.h"
33 #include "vs.h"
34 #include "syntax.h"
35 #include "charmap.h"
36 #include "tw.h"
37 #include "w.h"
38
39 #if !HAVE_DECL_CTIME
40 char *ctime(const time_t *);
41 #endif
42
43 extern int square;
44 int staen = 0;
45 int staupd = 0;
46 int keepup = 0;
47
48 /* Move text window */
49
50 static void movetw(jobject jO, int x, int y)
51 {
52         BW *bw = jO.bw;
53         TW *tw = (TW *) bw->object;
54
55         if (y || !staen) {
56                 if (!tw->staon) {       /* Scroll down and shrink */
57                         nscrldn(bw->parent->t->t, y, bw->parent->nh + y, 1);
58                 }
59                 bwmove(bw, x + (bw->o.linums ? LINCOLS : 0), y + 1);
60                 tw->staon = 1;
61         } else {
62                 if (tw->staon) {        /* Scroll up and grow */
63                         nscrlup(bw->parent->t->t, y, bw->parent->nh + y, 1);
64                 }
65                 bwmove(bw, x + (bw->o.linums ? LINCOLS : 0), y);
66                 tw->staon = 0;
67         }
68 }
69
70 /* Resize text window */
71
72 static void resizetw(jobject jO, int wi, int he)
73 {
74         BW *bw = jO.bw;
75
76         if (bw->parent->ny || !staen)
77                 bwresz(bw, wi - (bw->o.linums ? LINCOLS : 0), he - 1);
78         else
79                 bwresz(bw, wi - (bw->o.linums ? LINCOLS : 0), he);
80 }
81
82 /* Get current context */
83
84 /* Find first line (going backwards) which has 0 indentation level
85  * and is not a comment, blank, or block structuring line.  This is
86  * likely to be the line with the function name.
87  *
88  * There are actually two possibilities:
89  *
90  * We want the first line-
91  *
92  * int
93  * foo(int x,int y) {
94  *
95  *   }
96  *
97  * We want the last line-
98  *
99  * program foo(input,output);
100  * var a, b, c : real;
101  * begin
102  *
103  */
104
105 static unsigned char *
106 get_context(BW *bw)
107 {
108         P *p = pdup(bw->cursor);
109         static unsigned char buf1[stdsiz];
110
111
112         buf1[0] = 0;
113         /* Find first line with 0 indentation which is not a comment line */
114         do {
115                 p_goto_bol(p);
116                 if (!pisindent(p) && !pisblank(p)) {
117                         /* Uncomment to get the last line instead of the first line (see above)
118  next:
119                         */
120                         brzs(p,stdbuf,stdsiz-1);
121                         /* Ignore comment and block structuring lines */
122                         if (!(stdbuf[0]=='{' ||
123                             (stdbuf[0]=='/' && stdbuf[1]=='*') ||
124                             (stdbuf[0]=='\f') ||
125                             (stdbuf[0]=='/' && stdbuf[1]=='/') ||
126                             (stdbuf[0]=='#') ||
127                             ((stdbuf[0] | 0x20) == 'b' && (stdbuf[1] | 0x20) == 'e' && (stdbuf[2] | 0x20) == 'g' && (stdbuf[3] | 0x20) == 'i' && (stdbuf[4] | 0x20) == 'n') ||
128                             (stdbuf[0]=='-' && stdbuf[1]=='-') ||
129                             stdbuf[0]==';')) {
130                                 strlcpy(buf1,stdbuf,stdsiz);
131                                 /* Uncomment to get the last line instead of the first line (see above)
132                                 if (pprevl(p)) {
133                                         p_goto_bol(p);
134                                         if (!pisindent(p) && !pisblank(p))
135                                                 goto next;
136                                 }
137                                 */
138                                 break;
139                         }
140
141                 }
142         } while (!buf1[0] && pprevl(p));
143
144         prm(p);
145
146         return buf1;
147 }
148
149 static unsigned char *stagen(unsigned char *stalin, BW *bw, unsigned char *s, int fill)
150 {
151         unsigned char *cp, *cp2, uc;
152         unsigned char buf[80];
153         int x;
154         W *w = bw->parent;
155         time_t tt;
156         int special_aA = 0;
157
158         cp = s;
159         while ((cp2 = strstr(cp, "%a")) != NULL) {
160                 cp2 += /* %a */ 2;
161                 if (cp2[1] == '%')
162                         ++cp2;
163                 if (cp2[0] == '%' && cp2[1] == 'A') {
164                         special_aA = 1;
165                         break;
166                 }
167         }
168         if (!special_aA) while ((cp2 = strstr(cp, "%A")) != NULL) {
169                 cp2 += /* %A */ 2;
170                 if (cp2[1] == '%')
171                         ++cp2;
172                 if (cp2[0] == '%' && cp2[1] == 'a') {
173                         special_aA = 1;
174                         break;
175                 }
176         }
177
178         stalin = vstrunc(stalin, 0);
179         while (*s) {
180                 if (*s == '%' && s[1]) {
181                         switch (*++s) {
182                         case 'x':
183                                 /* Context (but only if autoindent is enabled) */
184                                 if (bw->o.autoindent) {
185                                         cp = get_context(bw);
186                                         stalin = vsncpy(sv(stalin), sz(cp));
187                                 }
188                                 break;
189
190                         case 'y':
191                                 if (bw->o.syntax) {
192                                         joe_snprintf_1((char *)buf, sizeof(buf), "(%s)", bw->o.syntax->name);
193                                         stalin = vsncpy(sv(stalin), sz(buf));
194                                 }
195                                 break;
196                         case 't':
197                                 tt = time(NULL);
198                                 cp = (unsigned char *)ctime(&tt);
199
200                                 x = (cp[11] - '0') * 10 + cp[12] - '0';
201                                 if (x > 12)
202                                         x -= 12;
203                                 joe_snprintf_1((char *)buf, sizeof(buf), "%2.2d", x);
204                                 if (buf[0] == '0')
205                                         buf[0] = fill;
206                                 stalin = vsncpy(sv(stalin), buf, 2);
207                                 stalin = vsncpy(sv(stalin), cp + 13, 3);
208                                 break;
209                         case 'u':
210                                 tt = time(NULL);
211                                 cp = (unsigned char *)ctime(&tt);
212                                 stalin = vsncpy(sv(stalin), cp + 11, 5);
213                                 break;
214                         case 'T':
215                                 if (bw->o.overtype)
216                                         stalin = vsadd(stalin, 'O');
217                                 else
218                                         stalin = vsadd(stalin, 'I');
219                                 break;
220                         case 'W':
221                                 if (bw->o.wordwrap)
222                                         stalin = vsadd(stalin, 'W');
223                                 else
224                                         stalin = vsadd(stalin, fill);
225                                 break;
226                         case 'I':
227                                 if (bw->o.autoindent)
228                                         stalin = vsadd(stalin, 'A');
229                                 else
230                                         stalin = vsadd(stalin, fill);
231                                 break;
232                         case 'X':
233                                 if (square)
234                                         stalin = vsadd(stalin, 'X');
235                                 else
236                                         stalin = vsadd(stalin, fill);
237                                 break;
238                         case 'n':
239                                 if (!bw->b->name) {
240                                         stalin = vsncpy(sv(stalin), sc("Unnamed"));
241                                         break;
242                                 }
243                                 cp = bw->b->name;
244  escape_loop:
245                                 switch ((uc = *cp++)) {
246                                 case '\\':
247                                         stalin = vsadd(stalin, uc);
248                                         /* FALLTHROUGH */
249                                 default:
250                                         stalin = vsadd(stalin, uc);
251                                         goto escape_loop;
252                                 case '\0':
253                                         break;
254                                 }
255                                 break;
256                         case 'm':
257                                 if (bw->b->changed)
258                                         stalin = vsncpy(sv(stalin), sc("(Modified)"));
259                                 break;
260                         case 'R':
261                                 if (bw->b->rdonly)
262                                         stalin = vsncpy(sv(stalin), sc("(Read only)"));
263                                 break;
264                         case '*':
265                                 if (bw->b->changed)
266                                         stalin = vsadd(stalin, '*');
267                                 else
268                                         stalin = vsadd(stalin, fill);
269                                 break;
270                         case 'r':
271                                 joe_snprintf_1((char *)buf, sizeof(buf), "%-4ld", bw->cursor->line + 1);
272                                 for (x = 0; buf[x]; ++x)
273                                         if (buf[x] == ' ')
274                                                 buf[x] = fill;
275                                 stalin = vsncpy(sv(stalin), sz(buf));
276                                 break;
277                         case 'o':
278                                 joe_snprintf_1((char *)buf, sizeof(buf), "%-4ld", bw->cursor->byte);
279                                 for (x = 0; buf[x]; ++x)
280                                         if (buf[x] == ' ')
281                                                 buf[x] = fill;
282                                 stalin = vsncpy(sv(stalin), sz(buf));
283                                 break;
284                         case 'O':
285                                 joe_snprintf_1((char *)buf, sizeof(buf), "%-4lX", bw->cursor->byte);
286                                 for (x = 0; buf[x]; ++x)
287                                         if (buf[x] == ' ')
288                                                 buf[x] = fill;
289                                 stalin = vsncpy(sv(stalin), sz(buf));
290                                 break;
291                         case 'a':
292                                 if (bw->b->o.charmap->type && !(special_aA && brch(bw->cursor) == 0x1000FFFE)) {
293                                         /* UTF-8: don't display decimal value */
294                                         buf[0] = 'u';
295                                         buf[1] = 0;
296                                 } else {
297                                         if (!piseof(bw->cursor))
298                                                 joe_snprintf_1((char *)buf, sizeof(buf), "%3d", 255 & brc(bw->cursor));
299                                         else
300                                                 joe_snprintf_0((char *)buf, sizeof(buf), "   ");
301                                         for (x = 0; buf[x]; ++x)
302                                                 if (buf[x] == ' ')
303                                                         buf[x] = fill;
304                                 }
305                                 stalin = vsncpy(sv(stalin), sz(buf));
306                                 break;
307                         case 'A':
308                                 if (bw->b->o.charmap->type) {
309                                         /* UTF-8, display UCS-2 value */
310                                         if (!piseof(bw->cursor)) {
311                                                 int uch = brch(bw->cursor);
312                                                 if (uch == 0x1000FFFE)
313                                                         joe_snprintf_1((char *)buf, sizeof(buf), special_aA ? "%02X" : "  %02X", 255 & brc(bw->cursor));
314                                                 else if (uch == 0x1000FFFF)
315                                                         joe_snprintf_0((char *)buf, sizeof(buf), "<-2>");
316                                                 else
317                                                         joe_snprintf_1((char *)buf, sizeof(buf), "%04X", uch);
318                                         } else
319                                                 joe_snprintf_0((char *)buf, sizeof(buf), "    ");
320                                 } else {
321                                         if (!piseof(bw->cursor))
322                                                 joe_snprintf_1((char *)buf, sizeof(buf), "%2.2X", 255 & brc(bw->cursor));
323                                         else
324                                                 joe_snprintf_0((char *)buf, sizeof(buf), "  ");
325                                 }
326                                 for (x = 0; buf[x]; ++x)
327                                         if (buf[x] == ' ')
328                                                 buf[x] = fill;
329                                 stalin = vsncpy(sv(stalin), sz(buf));
330                                 break;
331                         case 'c':
332                                 joe_snprintf_1((char *)buf, sizeof(buf), "%-3ld", piscol(bw->cursor) + 1);
333                                 for (x = 0; buf[x]; ++x)
334                                         if (buf[x] == ' ')
335                                                 buf[x] = fill;
336                                 stalin = vsncpy(sv(stalin), sz(buf));
337                                 break;
338                         case 'p':
339                                 if (bw->b->eof->byte)
340                                         joe_snprintf_1((char *)buf, sizeof(buf), "%3ld", bw->cursor->byte * 100 / bw->b->eof->byte);
341                                 else
342                                         joe_snprintf_0((char *)buf, sizeof(buf), "100");
343                                 for (x = 0; buf[x]; ++x)
344                                         if (buf[x] == ' ')
345                                                 buf[x] = fill;
346                                 stalin = vsncpy(sv(stalin), sz(buf));
347                                 break;
348                         case 'l':
349                                 joe_snprintf_1((char *)buf, sizeof(buf), "%-4ld", bw->b->eof->line + 1);
350                                 for (x = 0; buf[x]; ++x)
351                                         if (buf[x] == ' ')
352                                                 buf[x] = fill;
353                                 stalin = vsncpy(sv(stalin), sz(buf));
354                                 break;
355                         case 'k':
356                                 cp = buf;
357                                 buf[0] = 0;
358                                 if (w->kbd->x && w->kbd->seq[0])
359                                         for (x = 0; x != w->kbd->x; ++x) {
360                                                 uc = w->kbd->seq[x] & 127;
361
362                                                 if (uc < 32) {
363                                                         cp[0] = '^';
364                                                         cp[1] = uc + '@';
365                                                         cp += 2;
366                                                 } else if (uc == 127) {
367                                                         cp[0] = '^';
368                                                         cp[1] = '?';
369                                                         cp += 2;
370                                                 } else {
371                                                         cp[0] = uc;
372                                                         cp += 1;
373                                                 }
374                                         }
375                                 *cp++ = fill;
376                                 while (cp - buf < 4)
377                                         *cp++ = fill;
378                                 stalin = vsncpy(sv(stalin), buf, cp - buf);
379                                 break;
380                         case 'S':
381                                 if (bw->b->pid)
382                                         stalin = vsncpy(sv(stalin), sc("*SHELL*"));
383                                 break;
384                         case 'M':
385                                 if (recmac) {
386                                         joe_snprintf_1((char *)buf, sizeof(buf), "(Macro %d recording...)", recmac->n);
387                                         stalin = vsncpy(sv(stalin), sz(buf));
388                                 }
389                                 break;
390                         default:
391                                 stalin = vsadd(stalin, *s);
392                         }
393                 } else
394                         stalin = vsadd(stalin, *s);
395                 ++s;
396         }
397         return stalin;
398 }
399
400 static void disptw(jobject jO, int flg)
401 {
402         BW *bw = jO.bw;
403         W *w = bw->parent;
404         TW *tw = (TW *) bw->object;
405
406         if (bw->o.linums != bw->linums) {
407                 bw->linums = bw->o.linums;
408                 resizetw(jO, w->w, w->h);
409                 movetw(jO, w->x, w->y);
410                 bwfllw(jO);
411         }
412
413         if (bw->o.hex) {
414                 w->cury = (bw->cursor->byte-bw->top->byte)/16 + bw->y - w->y;
415                 w->curx = (bw->cursor->byte-bw->top->byte)%16 + 60 - bw->offset;
416         } else {
417                 w->cury = bw->cursor->line - bw->top->line + bw->y - w->y;
418                 w->curx = bw->cursor->xcol - bw->offset + (bw->o.linums ? LINCOLS : 0);
419         }
420
421         if ((staupd || keepup || bw->cursor->line != tw->prevline || bw->b->changed != tw->changed || bw->b != tw->prev_b) && (w->y || !staen)) {
422                 int fill;
423
424                 tw->prevline = bw->cursor->line;
425                 tw->changed = bw->b->changed;
426                 tw->prev_b = bw->b;
427                 if (bw->o.rmsg[0])
428                         fill = bw->o.rmsg[0];
429                 else
430                         fill = ' ';
431                 tw->stalin = stagen(tw->stalin, bw, bw->o.lmsg, fill);
432                 tw->staright = stagen(tw->staright, bw, bw->o.rmsg, fill);
433                 if (fmtlen(tw->staright) < w->w) {
434                         int x = fmtpos(tw->stalin, w->w - fmtlen(tw->staright));
435
436                         if (x > sLEN(tw->stalin))
437                                 tw->stalin = vsfill(sv(tw->stalin), fill, x - sLEN(tw->stalin));
438                         tw->stalin = vsncpy(tw->stalin, fmtpos(tw->stalin, w->w - fmtlen(tw->staright)), sv(tw->staright));
439                 }
440                 tw->stalin = vstrunc(tw->stalin, fmtpos(tw->stalin, w->w));
441                 genfmt(w->t->t, w->x, w->y, 0, tw->stalin, 0);
442                 w->t->t->updtab[w->y] = 0;
443         }
444
445         if (flg) {
446                 if (bw->o.hex)
447                         bwgenh(bw);
448                 else
449                         bwgen(bw, bw->o.linums);
450         }
451 }
452
453 /* Split current window */
454
455 static void iztw(TW *tw, int y)
456 {
457         tw->stalin = NULL;
458         tw->staright = NULL;
459         tw->changed = -1;
460         tw->prevline = -1;
461         tw->staon = (!staen || y);
462         tw->prev_b = 0;
463 }
464
465 extern int dostaupd;
466
467 int usplitw(BW *bw)
468 {
469         W *w = bw->parent;
470         int newh = getgrouph(w);
471         W *new;
472         TW *newtw;
473         BW *newbw;
474
475         dostaupd = 1;
476         if (newh / 2 < FITHEIGHT)
477                 return -1;
478         new = wcreate(w->t, w->watom, findbotw(w), NULL, w, newh / 2 + (newh & 1), NULL, NULL);
479         if (!new)
480                 return -1;
481         wfit(new->t);
482         new->object.bw = newbw = bwmk(new, bw->b, 0);
483         ++bw->b->count;
484         newbw->offset = bw->offset;
485         newbw->object = newtw = malloc(sizeof(TW));
486         iztw(newtw, new->y);
487         pset(newbw->top, bw->top);
488         pset(newbw->cursor, bw->cursor);
489         newbw->cursor->xcol = bw->cursor->xcol;
490         new->t->curwin = new;
491         return 0;
492 }
493
494 int uduptw(BW *bw)
495 {
496         W *w = bw->parent;
497         int newh = getgrouph(w);
498         W *new;
499         TW *newtw;
500         BW *newbw;
501
502         dostaupd = 1;
503         new = wcreate(w->t, w->watom, findbotw(w), NULL, NULL, newh, NULL, NULL);
504         if (!new)
505                 return -1;
506         if (demotegroup(w))
507                 new->t->topwin = new;
508         new->object.bw = newbw = bwmk(new, bw->b, 0);
509         ++bw->b->count;
510         newbw->offset = bw->offset;
511         newbw->object = newtw = malloc(sizeof(TW));
512         iztw(newtw, new->y);
513         pset(newbw->top, bw->top);
514         pset(newbw->cursor, bw->cursor);
515         newbw->cursor->xcol = bw->cursor->xcol;
516         new->t->curwin = new;
517         wfit(w->t);
518         return 0;
519 }
520
521 static void instw(BW *bw, B *b, long int l, long int n, int flg)
522 {
523         if (b == bw->b)
524                 bwins(bw, l, n, flg);
525 }
526
527 static void deltw(BW *bw, B *b, long int l, long int n, int flg)
528 {
529         if (b == bw->b)
530                 bwdel(bw, l, n, flg);
531 }
532
533 WATOM watomtw = {
534         US "main",
535         disptw,
536         bwfllw,
537         NULL,
538         rtntw,
539         utypebw,
540         resizetw,
541         movetw,
542         instw,
543         deltw,
544         TYPETW
545 };
546
547 int abortit(BW *bw)
548 {
549         W *w;
550         TW *tw;
551         B *b;
552         if (bw->parent->watom != &watomtw)
553                 return wabort(bw->parent);
554         if (bw->b->pid && bw->b->count==1)
555                 return ukillpid(bw);
556         w = bw->parent;
557         tw = (TW *) bw->object;
558         /* If only one main window on the screen... */
559         if (countmain(w->t) == 1)
560                 /* Replace it with an orphaned buffer if there are any */
561                 if ((b = borphan()) != NULL) {
562                         void *object = bw->object;
563                         /* FIXME: Shouldn't we wabort() and wcreate here to kill
564                            any prompt windows? */
565
566                         bwrm(bw);
567                         w->object.bw = bw = bwmk(w, b, 0);
568                         wredraw(bw->parent);
569                         bw->object = object;
570                         return 0;
571                 }
572         bwrm(bw);
573         vsrm(tw->stalin);
574         free(tw);
575         w->object.base = NULL;
576         wabort(w);      /* Eliminate this window and it's children */
577         return 0;
578 }
579
580 /* User routine for aborting a text window */
581
582 static int naborttw(BW *bw, int k, void *object, int *notify)
583 {
584         if (notify)
585                 *notify = 1;
586         if ((k | 0x20) != 'y')
587                 return -1;
588
589         genexmsg(bw, 0, NULL);
590         return abortit(bw);
591 }
592
593 static int naborttw1(BW *bw, int k, void *object, int *notify)
594 {
595         if (notify)
596                 *notify = 1;
597         if ((k | 0x20) != 'y')
598                 return -1;
599
600         if (!exmsg) genexmsg(bw, 0, NULL);
601         return abortit(bw);
602 }
603
604 /* k is last character types which lead to uabort.  If k is -1, it means uabort
605    was called internally, and not by the user: which means uabort will not send
606    Ctrl-C to process */
607 int uabort(BW *bw, int k)
608 {
609         if (bw->parent->watom != &watomtw)
610                 return wabort(bw->parent);
611         if (bw->b->pid && bw->b->count==1)
612                 return ukillpid(bw);
613         if (bw->b->changed && bw->b->count == 1 && !bw->b->scratch)
614                 if (mkqw(bw->parent, sc("Lose changes to this file (y,n,^C)? "), naborttw, NULL, NULL, NULL))
615                         return 0;
616                 else
617                         return -1;
618         else
619                 return naborttw(bw, 'y', NULL, NULL);
620 }
621
622 int ucancel(BW *bw, int k)
623 {
624         if (bw->parent->watom != &watomtw) {
625                 wabort(bw->parent);
626                 return 0;
627         } else
628                 return uabort(bw,k);
629 }
630
631 /* Same as above, but only calls genexmsg if nobody else has */
632
633 int uabort1(BW *bw, int k)
634 {
635         if (bw->parent->watom != &watomtw)
636                 return wabort(bw->parent);
637         if (bw->b->pid && bw->b->count==1)
638                 return ukillpid(bw);
639         if (bw->b->changed && bw->b->count == 1 && !bw->b->scratch)
640                 if (mkqw(bw->parent, sc("Lose changes to this file (y,n,^C)? "), naborttw1, NULL, NULL, NULL))
641                         return 0;
642                 else
643                         return -1;
644         else
645                 return naborttw1(bw, 'y', NULL, NULL);
646 }
647
648 /* Abort buffer without prompting: just fail if this is last window on buffer */
649
650 int uabortbuf(BW *bw)
651 {
652         W *w = bw->parent;
653         B *b;
654
655         if (bw->b->pid && bw->b->count==1)
656                 return ukillpid(bw);
657
658         if (okrepl(bw))
659                 return -1;
660
661         if ((b = borphan()) != NULL) {
662                 void *object = bw->object;
663
664                 bwrm(bw);
665                 w->object.bw = bw = bwmk(w, b, 0);
666                 wredraw(bw->parent);
667                 bw->object = object;
668                 return 0;
669         }
670
671         return naborttw(bw, 'y', NULL, NULL);
672 }
673
674 /* Kill current window (orphans buffer) */
675
676 int utw0(BASE *b)
677 {
678         BW *bw = b->parent->main->object.bw;
679
680         if (countmain(b->parent->t) == 1)
681                 return -1;
682         if (bw->b->count == 1)
683                 orphit(bw);
684         return uabort(bw, -1);
685 }
686
687 /* Kill all other windows (orphans buffers) */
688
689 int utw1(BASE *b)
690 {
691         W *starting = b->parent;
692         W *mainw = starting->main;
693         SCREEN *t = mainw->t;
694         int yn;
695
696         do {
697                 yn = 0;
698  loop:
699                 do {
700                         wnext(t);
701                 } while (t->curwin->main == mainw && t->curwin != starting);
702                 if (t->curwin->main != mainw) {
703                         BW *bw = t->curwin->main->object.bw;
704                         utw0((BASE *)bw);
705                         yn = 1;
706                         goto loop;
707                 }
708         } while (yn);
709         return 0;
710 }
711
712 void setline(B *b, long int line)
713 {
714         W *w = maint->curwin;
715
716         do {
717                 if (w->watom->what == TYPETW) {
718                         BW *bw = w->object.bw;
719
720                         if (bw->b == b) {
721                                 long oline = bw->top->line;
722
723                                 pline(bw->top, line);
724                                 pline(bw->cursor, line);
725                                 if (w->y >= 0 && bw->top->line > oline && bw->top->line - oline < bw->h)
726                                         nscrlup(w->t->t, bw->y, bw->y + bw->h, (int) (bw->top->line - oline));
727                                 else if (w->y >= 0 && bw->top->line < oline && oline - bw->top->line < bw->h)
728                                         nscrldn(w->t->t, bw->y, bw->y + bw->h, (int) (oline - bw->top->line));
729                         }
730                 }
731         } while ((w = w->link.next) != maint->curwin);
732 }
733
734 /* Create a text window.  It becomes the last window on the screen */
735
736 BW *wmktw(SCREEN *t, B *b)
737 {
738         W *w;
739         BW *bw;
740         TW *tw;
741
742         w = wcreate(t, &watomtw, NULL, NULL, NULL, t->h, NULL, NULL);
743         wfit(w->t);
744         w->object.bw = bw = bwmk(w, b, 0);
745         bw->object = tw = malloc(sizeof(TW));
746         iztw(tw, w->y);
747         return bw;
748 }