Example #1
0
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;
}
Example #2
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;
}