diff options
Diffstat (limited to 'resize.c')
-rw-r--r-- | resize.c | 368 |
1 files changed, 303 insertions, 65 deletions
@@ -44,16 +44,16 @@ static void CheckMaxSize __P((int)); static void FreeMline __P((struct mline *)); static int AllocMline __P((struct mline *ml, int)); static void MakeBlankLine __P((char *, int)); +static void kaablamm __P((void)); +static int BcopyMline __P((struct mline *, int, struct mline *, int, int, int)); +extern struct layer *flayer; extern struct display *display, *displays; extern char *blank, *null; extern struct mline mline_blank, mline_null, mline_old; extern struct win *windows; extern int Z0width, Z1width; - -#ifdef NETHACK -extern int nethackflag; -#endif +extern int captionalways; #if defined(TIOCGWINSZ) || defined(TIOCSWINSZ) struct winsize glwz; @@ -61,8 +61,10 @@ extern int nethackflag; static struct mline mline_zero = { (char *)0, - (char *)0, (char *)0 +#ifdef FONT + ,(char *)0 +#endif #ifdef COLOR ,(char *)0 #endif @@ -82,15 +84,12 @@ CheckScreenSize(change_flag) int change_flag; { int wi, he; - struct win *p; - struct layer *oldlay; if (display == 0) { debug("CheckScreenSize: No display -> no check.\n"); return; } - oldlay = D_lay; #ifdef TIOCGWINSZ if (ioctl(D_userfd, TIOCGWINSZ, (char *)&glwz) != 0) { @@ -114,6 +113,7 @@ int change_flag; debug2("CheckScreenSize: screen is (%d,%d)\n", wi, he); +#if 0 /* XXX: Fixme */ if (change_flag == 2) { debug("Trying to adapt all windows (-A)\n"); @@ -121,6 +121,7 @@ int change_flag; if (p->w_display == 0 || p->w_display == display) ChangeWindowSize(p, wi, he, p->w_histheight); } +#endif if (D_width == wi && D_height == he) { debug("CheckScreenSize: No change -> return.\n"); @@ -128,16 +129,7 @@ int change_flag; } ChangeScreenSize(wi, he, change_flag); if (change_flag == 1) - Activate(D_fore ? D_fore->w_norefresh : 0); - if (D_lay != oldlay) - { -#ifdef NETHACK - if (nethackflag) - Msg(0, "KAABLAMM!!! You triggered a land mine!"); - else -#endif - Msg(0, "Aborted because of window size change."); - } + Redisplay(D_fore ? D_fore->w_norefresh : 0); } void @@ -146,15 +138,60 @@ int wi, he; int change_fore; { struct win *p; + struct canvas *cv, **cvpp; int wwi; + int y, h, hn; - if (D_width == wi && D_height == he) - { - debug("ChangeScreenSize: no change\n"); - return; - } debug2("ChangeScreenSize from (%d,%d) ", D_width, D_height); debug3("to (%d,%d) (change_fore: %d)\n",wi, he, change_fore); + + /* + * STRATEGY: keep the ratios. + * if canvas doesn't fit anymore, throw it off. + * (ATTENTION: cvlist must be sorted!) + */ + y = 0; + h = he; + if (D_has_hstatus == HSTATUS_LASTLINE) + h--; + for (cvpp = &D_cvlist; (cv = *cvpp); ) + { + if (h < 2) + { + /* kill canvas */ + SetCanvasWindow(cv, 0); + *cvpp = cv->c_next; + free(cv); + if (D_forecv == cv) + D_forecv = 0; + continue; + } + hn = (cv->c_ye - cv->c_ys + 1) * he / D_height; + if (hn == 0) + hn = 1; + if (hn + 2 >= h || cv->c_next == 0) + hn = h - 1; + if (!captionalways && cv == D_cvlist && h - hn < 2) + hn = h; + ASSERT(hn > 0); + cv->c_xs = 0; + cv->c_xe = wi - 1; + cv->c_ys = y; + cv->c_ye = y + hn - 1; + + cv->c_xoff = cv->c_xs; + cv->c_yoff = cv->c_ys; + + y += hn + 1; + h -= hn + 1; + cvpp = &cv->c_next; + } + RethinkDisplayViewports(); + if (D_forecv == 0) + D_forecv = D_cvlist; + if (D_forecv) + D_fore = Layer2Window(D_forecv->c_layer); + D_width = wi; D_height = he; @@ -175,7 +212,7 @@ int change_fore; } debug2("Default size: (%d,%d)\n", D_defwidth, D_defheight); if (change_fore) - DoResize(wi, he); + ResizeLayersToCanvases(); if (D_CWS == NULL && displays->d_next == 0) { /* adapt all windows - to be removed ? */ @@ -183,40 +220,179 @@ int change_fore; { debug1("Trying to change window %d.\n", p->w_number); wwi = wi; - if (D_CZ0 && (wi == Z0width || wi == Z1width)) +#if 0 + if (D_CZ0 && p->w_width != wi && (wi == Z0width || wi == Z1width)) { if (p->w_width > (Z0width + Z1width) / 2) wwi = Z0width; else wwi = Z1width; } +#endif + if (p->w_savelayer && p->w_savelayer->l_cvlist == 0) + ResizeLayer(p->w_savelayer, wwi, he, 0); +#if 0 ChangeWindowSize(p, wwi, he, p->w_histheight); +#endif } } } void -DoResize(wi, he) -int wi, he; +ResizeLayersToCanvases() { - struct layer *oldlay; - int q = 0; + struct canvas *cv; + struct layer *l; + int lx, ly; - for(;;) + debug("ResizeLayersToCanvases\n"); + for (cv = D_cvlist; cv; cv = cv->c_next) { - oldlay = D_lay; - for (; D_lay; D_lay = D_lay->l_next) + l = cv->c_layer; + if (l == 0) + continue; + debug("Doing canvas: "); + if (l->l_width == cv->c_xe - cv->c_xs + 1 && + l->l_height == cv->c_ye - cv->c_ys + 1) + { + debug("already fitting.\n"); + continue; + } + if (!MayResizeLayer(l)) + { + debug("may not resize.\n"); + } + else { - D_layfn = D_lay->l_layfn; - if ((q = Resize(wi, he))) - break; + debug("doing resize.\n"); + ResizeLayer(l, cv->c_xe - cv->c_xs + 1, cv->c_ye - cv->c_ys + 1, display); + } + + /* normalize window, see screen.c */ + lx = cv->c_layer->l_x; + ly = cv->c_layer->l_y; + if (ly + cv->c_yoff < cv->c_ys) + { + cv->c_yoff = cv->c_ys - ly; + RethinkViewportOffsets(cv); + } + else if (ly + cv->c_yoff > cv->c_ye) + { + cv->c_yoff = cv->c_ye - ly; + RethinkViewportOffsets(cv); + } + if (lx + cv->c_xoff < cv->c_xs) + { + int n = cv->c_xs - (lx + cv->c_xoff); + if (n < (cv->c_xe - cv->c_xs + 1) / 2) + n = (cv->c_xe - cv->c_xs + 1) / 2; + if (cv->c_xoff + n > cv->c_xs) + n = cv->c_xs - cv->c_xoff; + cv->c_xoff += n; + RethinkViewportOffsets(cv); + } + else if (lx + cv->c_xoff > cv->c_xe) + { + int n = lx + cv->c_xoff - cv->c_xe; + if (n < (cv->c_xe - cv->c_xs + 1) / 2) + n = (cv->c_xe - cv->c_xs + 1) / 2; + if (cv->c_xoff - n + cv->c_layer->l_width - 1 < cv->c_xe) + n = cv->c_xoff + cv->c_layer->l_width - 1 - cv->c_xe; + cv->c_xoff -= n; + RethinkViewportOffsets(cv); } - D_lay = oldlay; - D_layfn = D_lay->l_layfn; - if (q == 0) - break; - ExitOverlayPage(); } + Redisplay(0); +} + +int +MayResizeLayer(l) +struct layer *l; +{ + int cvs = 0; + debug("MayResizeLayer:\n"); + for (; l; l = l->l_next) + { + if (l->l_cvlist) + if (++cvs > 1 || l->l_cvlist->c_lnext) + { + debug1("may not - cvs %d\n", cvs); + return 0; + } + } + debug("may resize\n"); + return 1; +} + +/* + * Easy implementation: rely on the fact that the only layers + * supporting resize are Win and Blank. So just kill all overlays. + * + * This is a lot harder if done the right way... + */ + +static void +kaablamm() +{ + /* this only works because of the status_delayed hack... */ + Msg(0, "Aborted because of window size change."); +} + +void +ResizeLayer(l, wi, he, norefdisp) +struct layer *l; +int wi, he; +struct display *norefdisp; +{ + struct win *p; + struct canvas *cv; + struct layer *oldflayer = flayer; + struct display *d, *olddisplay = display; + + if (l->l_width == wi && l->l_height == he) + return; + p = Layer2Window(l); + + if (oldflayer && (l == oldflayer || Layer2Window(oldflayer) == p)) + while(oldflayer->l_next) + oldflayer = oldflayer->l_next; + + if (p) + { + for (d = displays; d; d = d->d_next) + for (cv = d->d_cvlist; cv; cv = cv->c_next) + { + if (p == Layer2Window(cv->c_layer)) + { + flayer = cv->c_layer; + if (flayer->l_next) + kaablamm(); + while(flayer->l_next) + ExitOverlayPage(); + } + } + l = p->w_savelayer; + } + flayer = l; + if (flayer->l_next) + kaablamm(); + while(flayer->l_next) + ExitOverlayPage(); + if (p) + flayer = &p->w_layer; + Resize(wi, he); + /* now everybody is on flayer, redisplay */ + l = flayer; + for (display = displays; display; display = display->d_next) + { + if (display == norefdisp) + continue; + for (cv = D_cvlist; cv; cv = cv->c_next) + if (cv->c_layer == l) + RefreshArea(cv->c_xs, cv->c_ys, cv->c_xe, cv->c_ye, 0); + } + flayer = oldflayer; + display = olddisplay; } @@ -228,8 +404,10 @@ struct mline *ml; free(ml->image); if (ml->attr && ml->attr != null) free(ml->attr); +#ifdef FONT if (ml->font && ml->font != null) free(ml->font); +#endif #ifdef COLOR if (ml->color && ml->color != null) free(ml->color); @@ -244,7 +422,9 @@ int w; { ml->image = malloc(w); ml->attr = null; +#ifdef FONT ml->font = null; +#endif #ifdef COLOR ml->color = null; #endif @@ -270,6 +450,7 @@ int xf, xt, l, w; } if (mlt->attr != null) bcopy(mlf->attr + xf, mlt->attr + xt, l); +#ifdef FONT if (mlf->font != null && mlt->font == null) { if ((mlt->font = malloc(w)) == 0) @@ -278,6 +459,7 @@ int xf, xt, l, w; } if (mlt->font != null) bcopy(mlf->font + xf, mlt->font + xt, l); +#endif #ifdef COLOR if (mlf->color != null && mlt->color == null) { @@ -324,38 +506,32 @@ int wi; mline_old.attr = malloc((unsigned) maxwidth); else mline_old.attr = xrealloc(mline_old.attr, maxwidth); +#ifdef FONT if (mline_old.font == 0) mline_old.font = malloc((unsigned) maxwidth); else mline_old.font = xrealloc(mline_old.font, maxwidth); +#endif #ifdef COLOR if (mline_old.color == 0) mline_old.color = malloc((unsigned) maxwidth); else mline_old.color = xrealloc(mline_old.color, maxwidth); - if (!(blank && null && mline_old.image && mline_old.attr - && mline_old.font && mline_old.color)) - { - Panic(0, "Out of memory -> Game over!!"); - /*NOTREACHED*/ - } -#else - if (!(blank && null && mline_old.image && mline_old.attr - && mline_old.font)) - { - Panic(0, "Out of memory -> Game over!!"); - /*NOTREACHED*/ - } #endif + if (!(blank && null && mline_old.image && mline_old.attr IFFONT(&& mline_old.font) IFCOLOR(&& mline_old.color))) + Panic(0, strnomem); + MakeBlankLine(blank, maxwidth); bzero(null, maxwidth); mline_blank.image = blank; mline_blank.attr = null; - mline_blank.font = null; mline_null.image = null; mline_null.attr = null; +#ifdef FONT + mline_blank.font = null; mline_null.font = null; +#endif #ifdef COLOR mline_blank.color = null; mline_null.color = null; @@ -371,8 +547,10 @@ int wi; { if (ml->attr == oldnull) ml->attr = null; +#ifdef FONT if (ml->font == oldnull) ml->font = null; +#endif #ifdef COLOR if (ml->color== oldnull) ml->color= null; @@ -384,8 +562,10 @@ int wi; { if (ml->attr == oldnull) ml->attr = null; +# ifdef FONT if (ml->font == oldnull) ml->font = null; +# endif # ifdef COLOR if (ml->color== oldnull) ml->color= null; @@ -445,6 +625,7 @@ int wi, he, hi; struct mline *mlf = 0, *mlt = 0, *ml, *nmlines, *nhlines; int fy, ty, l, lx, lf, lt, yy, oty, addone; int ncx, ncy, naka, t; + int y, shift; if (wi == 0) he = hi = 0; @@ -457,12 +638,15 @@ int wi, he, hi; CheckMaxSize(wi); + /* XXX */ +#if 0 /* just in case ... */ if (wi && (p->w_width != wi || p->w_height != he) && p->w_lay != &p->w_winlay) { debug("ChangeWindowSize: No resize because of overlay?\n"); return -1; } +#endif debug("ChangeWindowSize"); debug3(" from (%d,%d)+%d", p->w_width, p->w_height, p->w_histheight); @@ -519,6 +703,38 @@ int wi, he, hi; p->w_x--; } + /* handle the cursor and autoaka lines now if the widths are equal */ + if (p->w_width == wi) + { + ncx = p->w_x + addone; + ncy = p->w_y + he - p->w_height; + /* never lose sight of the line with the cursor on it */ + shift = -ncy; + for (yy = p->w_y + p->w_histheight - 1; yy >= 0 && ncy + shift < he; yy--) + { + ml = OLDWIN(yy); + if (ml->image[p->w_width] == ' ') + break; + shift++; + } + if (shift < 0) + shift = 0; + else + debug1("resize: cursor out of bounds, shifting %d\n", shift); + ncy += shift; + if (p->w_autoaka > 0) + { + naka = p->w_autoaka + he - p->w_height + shift; + if (naka < 1 || naka > he) + naka = 0; + } + while (shift-- > 0) + { + ml = OLDWIN(fy); + FreeMline(ml); + fy--; + } + } debug2("fy %d ty %d\n", fy, ty); if (fy >= 0) mlf = OLDWIN(fy); @@ -532,13 +748,6 @@ int wi, he, hi; /* here is a simple shortcut: just copy over */ *mlt = *mlf; *mlf = mline_zero; - if (fy == p->w_y + p->w_histheight) - { - ncx = p->w_x + addone; - ncy = ty - hi >= 0 ? ty - hi : 0; - } - if (p->w_autoaka > 0 && fy == p->w_autoaka - 1 + p->w_histheight) - naka = ty - hi >= 0 ? 1 + ty - hi : 0; if (--fy >= 0) mlf = OLDWIN(fy); if (--ty >= 0) @@ -584,7 +793,30 @@ int wi, he, hi; if (fy == p->w_y + p->w_histheight && lf - lx <= p->w_x && lf > p->w_x) { ncx = p->w_x + lt - lf + addone; - ncy = ty - hi >= 0 ? ty - hi : 0; + ncy = ty - hi; + shift = wi ? -ncy + (l - lx) / wi : 0; + if (ty + shift > hi + he - 1) + shift = hi + he - 1 - ty; + if (shift > 0) + { + debug3("resize: cursor out of bounds, shifting %d [%d/%d]\n", shift, lt - lx, wi); + for (y = hi + he - 1; y >= ty; y--) + { + mlt = NEWWIN(y); + FreeMline(mlt); + if (y - shift < ty) + continue; + ml = NEWWIN(y - shift); + *mlt = *ml; + *ml = mline_zero; + } + ncy += shift; + ty += shift; + mlt = NEWWIN(ty); + if (naka > 0) + naka = naka + shift > he ? 0 : naka + shift; + } + ASSERT(ncy >= 0); } /* did we copy autoaka line ? */ if (p->w_autoaka > 0 && fy == p->w_autoaka - 1 + p->w_histheight && lf - lx <= 0) @@ -652,7 +884,7 @@ int wi, he, hi; { /* tabs get wi+1 because 0 <= x <= wi */ p->w_tabs = malloc((unsigned) wi + 1); - t = 8; + t = 0; } else { @@ -680,8 +912,9 @@ int wi, he, hi; Msg(0, strnomem); return -1; } - for (t = (t + 7) & 8; t < wi; t += 8) - p->w_tabs[t] = 1; + for (; t < wi; t++) + p->w_tabs[t] = t && !(t & 7) ? 1 : 0; + p->w_tabs[wi] = 0; } else { @@ -735,6 +968,11 @@ int wi, he, hi; p->w_histheight = hi; #endif +#ifdef BUILTIN_TELNET + if (p->w_type == W_TYPE_TELNET) + TelWindowSize(p); +#endif + #ifdef DEBUG /* Test if everything was ok */ for (fy = 0; fy < p->w_height + p->w_histheight; fy++) |