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