int ChangeWindowSize(Window *p, int wi, int he, int 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 <= 0) wi = he = hi = 0; if (p->w_type == W_TYPE_GROUP) return 0; if (wi > MAXWIDTH) { Msg(0, "Window width too large. Truncated to %d.", MAXWIDTH); wi = MAXWIDTH; } if (he > MAXWIDTH) { Msg(0, "Window height too large. Truncated to %d.", MAXWIDTH); he = MAXWIDTH; } if (p->w_width == wi && p->w_height == he && p->w_histheight == hi) { return 0; } CheckMaxSize(wi); fy = p->w_histheight + p->w_height - 1; ty = hi + he - 1; nmlines = nhlines = 0; ncx = 0; ncy = 0; naka = 0; if (wi) { if (wi != p->w_width || he != p->w_height) { if ((nmlines = calloc(he, sizeof(struct mline))) == 0) { KillWindow(p); Msg(0, "%s", strnomem); return -1; } } else { nmlines = p->w_mlines; fy -= he; ty -= he; ncx = p->w_x; ncy = p->w_y; naka = p->w_autoaka; } } if (hi) { if ((nhlines = calloc(hi, sizeof(struct mline))) == 0) { Msg(0, "No memory for history buffer - turned off"); hi = 0; ty = he - 1; } } /* special case: cursor is at magic margin position */ addone = 0; if (p->w_width && p->w_x == p->w_width) { addone = 1; 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) break; if (ml->image[p->w_width] == ' ') break; shift++; } if (shift < 0) shift = 0; 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--; } } if (fy >= 0) mlf = OLDWIN(fy); if (ty >= 0) mlt = NEWWIN(ty); while (fy >= 0 && ty >= 0) { if (p->w_width == wi) { /* here is a simple shortcut: just copy over */ *mlt = *mlf; *mlf = mline_zero; if (--fy >= 0) mlf = OLDWIN(fy); if (--ty >= 0) mlt = NEWWIN(ty); continue; } /* calculate lenght */ for (l = p->w_width - 1; l > 0; l--) if (mlf->image[l] != ' ' || mlf->attr[l]) break; if (fy == p->w_y + p->w_histheight && l < p->w_x) l = p->w_x; /* cursor is non blank */ l++; lf = l; /* add wrapped lines to length */ for (yy = fy - 1; yy >= 0; yy--) { ml = OLDWIN(yy); if (ml->image[p->w_width] == ' ') break; l += p->w_width; } /* rewrap lines */ lt = (l - 1) % wi + 1; /* lf is set above */ oty = ty; while (l > 0 && fy >= 0 && ty >= 0) { lx = lt > lf ? lf : lt; if (mlt->image == 0) { if (AllocMline(mlt, wi + 1)) goto nomem; MakeBlankLine(mlt->image + lt, wi - lt); mlt->image[wi] = ((oty == ty) ? ' ' : 0); } if (BcopyMline(mlf, lf - lx, mlt, lt - lx, lx, wi + 1)) goto nomem; /* did we copy the cursor ? */ 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; shift = wi ? -ncy + (l - lx) / wi : 0; if (ty + shift > hi + he - 1) shift = hi + he - 1 - ty; if (shift > 0) { 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; } } /* did we copy autoaka line ? */ if (p->w_autoaka > 0 && fy == p->w_autoaka - 1 + p->w_histheight && lf - lx <= 0) naka = ty - hi >= 0 ? 1 + ty - hi : 0; lf -= lx; lt -= lx; l -= lx; if (lf == 0) { FreeMline(mlf); lf = p->w_width; if (--fy >= 0) mlf = OLDWIN(fy); } if (lt == 0) { lt = wi; if (--ty >= 0) mlt = NEWWIN(ty); } } } while (fy >= 0) { FreeMline(mlf); if (--fy >= 0) mlf = OLDWIN(fy); } while (ty >= 0) { if (AllocMline(mlt, wi + 1)) goto nomem; MakeBlankLine(mlt->image, wi + 1); if (--ty >= 0) mlt = NEWWIN(ty); } if (p->w_mlines && p->w_mlines != nmlines) free((char *)p->w_mlines); p->w_mlines = nmlines; if (p->w_hlines && p->w_hlines != nhlines) free((char *)p->w_hlines); p->w_hlines = nhlines; /* change tabs */ if (p->w_width != wi) { if (wi) { t = p->w_tabs ? p->w_width : 0; p->w_tabs = xrealloc(p->w_tabs, (wi + 1) * 4); if (p->w_tabs == 0) { nomem: if (nmlines) { for (ty = he + hi - 1; ty >= 0; ty--) { mlt = NEWWIN(ty); FreeMline(mlt); } if (nmlines && p->w_mlines != nmlines) free((char *)nmlines); if (nhlines && p->w_hlines != nhlines) free((char *)nhlines); } KillWindow(p); Msg(0, "%s", strnomem); if (nmlines) free(nmlines); if (nhlines) free(nhlines); return -1; } for (; t < wi; t++) p->w_tabs[t] = t && !(t & 7) ? 1 : 0; p->w_tabs[wi] = 0; } else { if (p->w_tabs) free(p->w_tabs); p->w_tabs = 0; } } /* Change w_saved.y - this is only an estimate... */ p->w_saved.y += ncy - p->w_y; p->w_x = ncx; p->w_y = ncy; if (p->w_autoaka > 0) p->w_autoaka = naka; /* do sanity checks */ if (p->w_x > wi) p->w_x = wi; if (p->w_y >= he) p->w_y = he - 1; if (p->w_saved.x > wi) p->w_saved.x = wi; if (p->w_saved.y >= he) p->w_saved.y = he - 1; if (p->w_saved.y < 0) p->w_saved.y = 0; if (p->w_alt.cursor.x > wi) p->w_alt.cursor.x = wi; if (p->w_alt.cursor.y >= he) p->w_alt.cursor.y = he - 1; if (p->w_alt.cursor.y < 0) p->w_alt.cursor.y = 0; /* reset scrolling region */ p->w_top = 0; p->w_bot = he - 1; /* signal new size to window */ if (wi && (p->w_width != wi || p->w_height != he) && p->w_width != 0 && p->w_height != 0 && p->w_ptyfd >= 0 && p->w_pid) { glwz.ws_col = wi; glwz.ws_row = he; ioctl(p->w_ptyfd, TIOCSWINSZ, (char *)&glwz); } /* store new size */ p->w_width = wi; p->w_height = he; p->w_histidx = 0; p->w_histheight = hi; #ifdef ENABLE_TELNET if (p->w_type == W_TYPE_TELNET) TelWindowSize(p); #endif return 0; }
int ChangeWindowSize(struct win *p, int wi, int he, int 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 <= 0) wi = he = hi = 0; if (p->w_type == W_TYPE_GROUP) return 0; if (wi > 1000) { Msg(0, "Window width too large. Truncated to 1000."); wi = 1000; } if (he > 1000) { Msg(0, "Window height too large. Truncated to 1000."); he = 1000; } if (p->w_width == wi && p->w_height == he && p->w_histheight == hi) { debug("ChangeWindowSize: No change.\n"); return 0; } CheckMaxSize(wi); debug("ChangeWindowSize"); debug3(" from (%d,%d)+%d", p->w_width, p->w_height, p->w_histheight); debug3(" to(%d,%d)+%d\n", wi, he, hi); fy = p->w_histheight + p->w_height - 1; ty = hi + he - 1; nmlines = nhlines = 0; ncx = 0; ncy = 0; naka = 0; if (wi) { if (wi != p->w_width || he != p->w_height) { if ((nmlines = (struct mline *)calloc(he, sizeof(struct mline))) == 0) { KillWindow(p); Msg(0, "%s", strnomem); return -1; } } else { debug1("image stays the same: %d lines\n", he); nmlines = p->w_mlines; fy -= he; ty -= he; ncx = p->w_x; ncy = p->w_y; naka = p->w_autoaka; } } if (hi) { if ((nhlines = (struct mline *)calloc(hi, sizeof(struct mline))) == 0) { Msg(0, "No memory for history buffer - turned off"); hi = 0; ty = he - 1; } } /* special case: cursor is at magic margin position */ addone = 0; if (p->w_width && p->w_x == p->w_width) { debug2("Special addone case: %d %d\n", p->w_x, p->w_y); addone = 1; 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); if (ty >= 0) mlt = NEWWIN(ty); while (fy >= 0 && ty >= 0) { if (p->w_width == wi) { /* here is a simple shortcut: just copy over */ *mlt = *mlf; *mlf = mline_zero; if (--fy >= 0) mlf = OLDWIN(fy); if (--ty >= 0) mlt = NEWWIN(ty); continue; } /* calculate lenght */ for (l = p->w_width - 1; l > 0; l--) if (mlf->image[l] != ' ' || mlf->attr[l]) break; if (fy == p->w_y + p->w_histheight && l < p->w_x) l = p->w_x; /* cursor is non blank */ l++; lf = l; /* add wrapped lines to length */ for (yy = fy - 1; yy >= 0; yy--) { ml = OLDWIN(yy); if (ml->image[p->w_width] == ' ') break; l += p->w_width; } /* rewrap lines */ lt = (l - 1) % wi + 1; /* lf is set above */ oty = ty; while (l > 0 && fy >= 0 && ty >= 0) { lx = lt > lf ? lf : lt; if (mlt->image == 0) { if (AllocMline(mlt, wi + 1)) goto nomem; MakeBlankLine(mlt->image + lt, wi - lt); mlt->image[wi] = ((oty == ty) ? ' ' : 0); } if (BcopyMline(mlf, lf - lx, mlt, lt - lx, lx, wi + 1)) goto nomem; /* did we copy the cursor ? */ 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; 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) naka = ty - hi >= 0 ? 1 + ty - hi : 0; lf -= lx; lt -= lx; l -= lx; if (lf == 0) { FreeMline(mlf); lf = p->w_width; if (--fy >= 0) mlf = OLDWIN(fy); } if (lt == 0) { lt = wi; if (--ty >= 0) mlt = NEWWIN(ty); } } ASSERT(l != 0 || fy == yy); } while (fy >= 0) { FreeMline(mlf); if (--fy >= 0) mlf = OLDWIN(fy); } while (ty >= 0) { if (AllocMline(mlt, wi + 1)) goto nomem; MakeBlankLine(mlt->image, wi + 1); if (--ty >= 0) mlt = NEWWIN(ty); } #ifdef DEBUG if (nmlines != p->w_mlines) for (fy = 0; fy < p->w_height + p->w_histheight; fy++) { ml = OLDWIN(fy); ASSERT(ml->image == 0); } #endif if (p->w_mlines && p->w_mlines != nmlines) free((char *)p->w_mlines); p->w_mlines = nmlines; if (p->w_hlines && p->w_hlines != nhlines) free((char *)p->w_hlines); p->w_hlines = nhlines; nmlines = nhlines = 0; /* change tabs */ if (p->w_width != wi) { if (wi) { t = p->w_tabs ? p->w_width : 0; p->w_tabs = xrealloc(p->w_tabs, wi + 1); if (p->w_tabs == 0) { nomem: if (nmlines) { for (ty = he + hi - 1; ty >= 0; ty--) { mlt = NEWWIN(ty); FreeMline(mlt); } if (nmlines && p->w_mlines != nmlines) free((char *)nmlines); if (nhlines && p->w_hlines != nhlines) free((char *)nhlines); } KillWindow(p); Msg(0, "%s", strnomem); return -1; } for (; t < wi; t++) p->w_tabs[t] = t && !(t & 7) ? 1 : 0; p->w_tabs[wi] = 0; } else { if (p->w_tabs) free(p->w_tabs); p->w_tabs = 0; } } /* Change w_saved.y - this is only an estimate... */ p->w_saved.y += ncy - p->w_y; p->w_x = ncx; p->w_y = ncy; if (p->w_autoaka > 0) p->w_autoaka = naka; /* do sanity checks */ if (p->w_x > wi) p->w_x = wi; if (p->w_y >= he) p->w_y = he - 1; if (p->w_saved.x > wi) p->w_saved.x = wi; if (p->w_saved.y < 0) p->w_saved.y = 0; if (p->w_saved.y >= he) p->w_saved.y = he - 1; if (p->w_alt.cursor.x > wi) p->w_alt.cursor.x = wi; if (p->w_alt.cursor.y >= he) p->w_alt.cursor.y = he - 1; /* reset scrolling region */ p->w_top = 0; p->w_bot = he - 1; /* signal new size to window */ #ifdef TIOCSWINSZ if (wi && (p->w_width != wi || p->w_height != he) && p->w_width != 0 && p->w_height != 0 && p->w_ptyfd >= 0 && p->w_pid) { glwz.ws_col = wi; glwz.ws_row = he; debug("Setting pty winsize.\n"); if (ioctl(p->w_ptyfd, TIOCSWINSZ, (char *)&glwz)) debug2("SetPtySize: errno %d (fd:%d)\n", errno, p->w_ptyfd); } #endif /* TIOCSWINSZ */ /* store new size */ p->w_width = wi; p->w_height = he; p->w_histidx = 0; p->w_histheight = hi; #ifdef DEBUG /* Test if everything was ok */ for (fy = 0; fy < p->w_height + p->w_histheight; fy++) { ml = OLDWIN(fy); ASSERT(ml->image); if (p->w_encoding == UTF8) { for (l = 0; l < p->w_width; l++) ASSERT(ml->image[l] >= ' ' || ml->font[l]); } else for (l = 0; l < p->w_width; l++) ASSERT(ml->image[l] >= ' '); } #endif return 0; }