1 /* Copyright (c) 2008, 2009
2 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
3 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
4 * Micah Cowan (micah@cowan.name)
5 * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
6 * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007
7 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
8 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
9 * Copyright (c) 1987 Oliver Laumann
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3, or (at your option)
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program (see the file COPYING); if not, see
23 * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
26 ****************************************************************
29 #include <sys/types.h>
32 #include <sys/ioctl.h>
37 # include <sys/sioctl.h>
45 static void CheckMaxSize
__P((int));
46 static void FreeMline
__P((struct mline
*));
47 static int AllocMline
__P((struct mline
*ml
, int));
48 static void MakeBlankLine
__P((unsigned char *, int));
49 static void kaablamm
__P((void));
50 static int BcopyMline
__P((struct mline
*, int, struct mline
*, int, int, int));
51 static void SwapAltScreen
__P((struct win
*));
53 extern struct layer
*flayer
;
54 extern struct display
*display
, *displays
;
55 extern unsigned char *blank
, *null
;
56 extern struct mline mline_blank
, mline_null
, mline_old
;
57 extern struct win
*windows
;
58 extern int Z0width
, Z1width
;
59 extern int captionalways
;
61 #if defined(TIOCGWINSZ) || defined(TIOCSWINSZ)
65 static struct mline mline_zero
= {
80 * ChangeFlag: 0: try to modify no window
81 * 1: modify fore (and try to modify no other) + redisplay
82 * 2: modify all windows
84 * Note: Activate() is only called if change_flag == 1
85 * i.e. on a WINCH event
89 CheckScreenSize(change_flag
)
96 debug("CheckScreenSize: No display -> no check.\n");
100 if (ioctl(D_userfd
, TIOCGWINSZ
, (char *)&glwz
) != 0)
102 debug2("CheckScreenSize: ioctl(%d, TIOCGWINSZ) errno %d\n", D_userfd
, errno
);
120 debug2("CheckScreenSize: screen is (%d,%d)\n", wi
, he
);
122 #if 0 /* XXX: Fixme */
123 if (change_flag
== 2)
125 debug("Trying to adapt all windows (-A)\n");
126 for (p
= windows
; p
; p
= p
->w_next
)
127 if (p
->w_display
== 0 || p
->w_display
== display
)
128 ChangeWindowSize(p
, wi
, he
, p
->w_histheight
);
131 if (D_width
== wi
&& D_height
== he
)
133 debug("CheckScreenSize: No change -> return.\n");
140 ChangeScreenSize(wi
, he
, change_flag
);
141 /* XXX Redisplay logic */
143 if (change_flag
== 1)
144 Redisplay(D_fore
? D_fore
->w_norefresh
: 0);
149 ChangeScreenSize(wi
, he
, change_fore
)
157 debug2("ChangeScreenSize from (%d,%d) ", D_width
, D_height
);
158 debug3("to (%d,%d) (change_fore: %d)\n",wi
, he
, change_fore
);
162 cv
->c_ye
= he
- 1 - ((cv
->c_slperp
&& cv
->c_slperp
->c_slnext
) || captionalways
) - (D_has_hstatus
== HSTATUS_LASTLINE
);
163 cv
->c_blank
.l_height
= cv
->c_ye
- cv
->c_ys
+ 1;
167 RecreateCanvasChain();
168 RethinkDisplayViewports();
173 D_fore
= Layer2Window(D_forecv
->c_layer
);
186 if (D_CZ0
&& (wi
== Z0width
|| wi
== Z1width
) &&
187 (D_CO
== Z0width
|| D_CO
== Z1width
))
193 debug2("Default size: (%d,%d)\n", D_defwidth
, D_defheight
);
195 ResizeLayersToCanvases();
196 if (change_fore
== 2 && D_CWS
== NULL
&& displays
->d_next
== 0)
198 /* adapt all windows - to be removed ? */
199 for (p
= windows
; p
; p
= p
->w_next
)
201 debug1("Trying to change window %d.\n", p
->w_number
);
204 if (D_CZ0
&& p
->w_width
!= wi
&& (wi
== Z0width
|| wi
== Z1width
))
206 if (p
->w_width
> (Z0width
+ Z1width
) / 2)
212 if (p
->w_savelayer
&& p
->w_savelayer
->l_cvlist
== 0)
213 ResizeLayer(p
->w_savelayer
, wwi
, he
, 0);
215 ChangeWindowSize(p
, wwi
, he
, p
->w_histheight
);
222 ResizeLayersToCanvases()
228 debug("ResizeLayersToCanvases\n");
230 for (cv
= D_cvlist
; cv
; cv
= cv
->c_next
)
235 debug("Doing canvas: ");
236 if (l
->l_width
== cv
->c_xe
- cv
->c_xs
+ 1 &&
237 l
->l_height
== cv
->c_ye
- cv
->c_ys
+ 1)
239 debug("already fitting.\n");
242 if (!MayResizeLayer(l
))
244 debug("may not resize.\n");
248 debug("doing resize.\n");
249 ResizeLayer(l
, cv
->c_xe
- cv
->c_xs
+ 1, cv
->c_ye
- cv
->c_ys
+ 1, display
);
252 /* normalize window, see screen.c */
253 lx
= cv
->c_layer
->l_x
;
254 ly
= cv
->c_layer
->l_y
;
255 if (ly
+ cv
->c_yoff
< cv
->c_ys
)
257 cv
->c_yoff
= cv
->c_ys
- ly
;
258 RethinkViewportOffsets(cv
);
260 else if (ly
+ cv
->c_yoff
> cv
->c_ye
)
262 cv
->c_yoff
= cv
->c_ye
- ly
;
263 RethinkViewportOffsets(cv
);
265 if (lx
+ cv
->c_xoff
< cv
->c_xs
)
267 int n
= cv
->c_xs
- (lx
+ cv
->c_xoff
);
268 if (n
< (cv
->c_xe
- cv
->c_xs
+ 1) / 2)
269 n
= (cv
->c_xe
- cv
->c_xs
+ 1) / 2;
270 if (cv
->c_xoff
+ n
> cv
->c_xs
)
271 n
= cv
->c_xs
- cv
->c_xoff
;
273 RethinkViewportOffsets(cv
);
275 else if (lx
+ cv
->c_xoff
> cv
->c_xe
)
277 int n
= lx
+ cv
->c_xoff
- cv
->c_xe
;
278 if (n
< (cv
->c_xe
- cv
->c_xs
+ 1) / 2)
279 n
= (cv
->c_xe
- cv
->c_xs
+ 1) / 2;
280 if (cv
->c_xoff
- n
+ cv
->c_layer
->l_width
- 1 < cv
->c_xe
)
281 n
= cv
->c_xoff
+ cv
->c_layer
->l_width
- 1 - cv
->c_xe
;
283 RethinkViewportOffsets(cv
);
299 debug("MayResizeLayer:\n");
300 for (; l
; l
= l
->l_next
)
303 if (++cvs
> 1 || l
->l_cvlist
->c_lnext
)
305 debug1("may not - cvs %d\n", cvs
);
309 debug("may resize\n");
314 * Easy implementation: rely on the fact that the only layers
315 * supporting resize are Win and Blank. So just kill all overlays.
317 * This is a lot harder if done the right way...
323 Msg(0, "Aborted because of window size change.");
327 ResizeLayer(l
, wi
, he
, norefdisp
)
330 struct display
*norefdisp
;
334 struct layer
*oldflayer
= flayer
;
335 struct display
*d
, *olddisplay
= display
;
337 if (l
->l_width
== wi
&& l
->l_height
== he
)
341 if (oldflayer
&& (l
== oldflayer
|| Layer2Window(oldflayer
) == p
))
342 while (oldflayer
->l_next
)
343 oldflayer
= oldflayer
->l_next
;
347 for (d
= displays
; d
; d
= d
->d_next
)
348 for (cv
= d
->d_cvlist
; cv
; cv
= cv
->c_next
)
350 if (p
== Layer2Window(cv
->c_layer
))
352 flayer
= cv
->c_layer
;
355 while (flayer
->l_next
)
362 if (p
== 0 && flayer
->l_next
&& flayer
->l_next
->l_next
== 0 && LayResize(wi
, he
) == 0)
364 flayer
= flayer
->l_next
;
371 for (cv
= flayer
->l_cvlist
; cv
; cv
= cv
->c_lnext
)
372 cv
->c_display
->d_kaablamm
= 1;
373 while (flayer
->l_next
)
377 flayer
= &p
->w_layer
;
379 /* now everybody is on flayer, redisplay */
381 for (display
= displays
; display
; display
= display
->d_next
)
383 if (display
== norefdisp
)
385 for (cv
= D_cvlist
; cv
; cv
= cv
->c_next
)
386 if (cv
->c_layer
== l
)
388 CV_CALL(cv
, LayRedisplayLine(-1, -1, -1, 0));
389 RefreshArea(cv
->c_xs
, cv
->c_ys
, cv
->c_xe
, cv
->c_ye
, 0);
398 display
= olddisplay
;
408 if (ml
->attr
&& ml
->attr
!= null
)
411 if (ml
->font
&& ml
->font
!= null
)
415 if (ml
->color
&& ml
->color
!= null
)
418 if (ml
->colorx
&& ml
->colorx
!= null
)
430 ml
->image
= malloc(w
);
448 BcopyMline(mlf
, xf
, mlt
, xt
, l
, w
)
449 struct mline
*mlf
, *mlt
;
454 bcopy((char *)mlf
->image
+ xf
, (char *)mlt
->image
+ xt
, l
);
455 if (mlf
->attr
!= null
&& mlt
->attr
== null
)
457 if ((mlt
->attr
= (unsigned char *)calloc(w
, 1)) == 0)
458 mlt
->attr
= null
, r
= -1;
460 if (mlt
->attr
!= null
)
461 bcopy((char *)mlf
->attr
+ xf
, (char *)mlt
->attr
+ xt
, l
);
463 if (mlf
->font
!= null
&& mlt
->font
== null
)
465 if ((mlt
->font
= (unsigned char *)calloc(w
, 1)) == 0)
466 mlt
->font
= null
, r
= -1;
468 if (mlt
->font
!= null
)
469 bcopy((char *)mlf
->font
+ xf
, (char *)mlt
->font
+ xt
, l
);
472 if (mlf
->color
!= null
&& mlt
->color
== null
)
474 if ((mlt
->color
= (unsigned char *)calloc(w
, 1)) == 0)
475 mlt
->color
= null
, r
= -1;
477 if (mlt
->color
!= null
)
478 bcopy((char *)mlf
->color
+ xf
, (char *)mlt
->color
+ xt
, l
);
480 if (mlf
->colorx
!= null
&& mlt
->colorx
== null
)
482 if ((mlt
->colorx
= (unsigned char *)calloc(w
, 1)) == 0)
483 mlt
->colorx
= null
, r
= -1;
485 if (mlt
->colorx
!= null
)
486 bcopy((char *)mlf
->colorx
+ xf
, (char *)mlt
->colorx
+ xt
, l
);
499 unsigned char *oldnull
= null
;
500 unsigned char *oldblank
= blank
;
505 wi
= ((wi
+ 1) + 255) & ~255;
509 debug1("New maxwidth: %d\n", maxwidth
);
510 blank
= (unsigned char *)xrealloc((char *)blank
, maxwidth
);
511 null
= (unsigned char *)xrealloc((char *)null
, maxwidth
);
512 mline_old
.image
= (unsigned char *)xrealloc((char *)mline_old
.image
, maxwidth
);
513 mline_old
.attr
= (unsigned char *)xrealloc((char *)mline_old
.attr
, maxwidth
);
515 mline_old
.font
= (unsigned char *)xrealloc((char *)mline_old
.font
, maxwidth
);
518 mline_old
.color
= (unsigned char *)xrealloc((char *)mline_old
.color
, maxwidth
);
520 mline_old
.colorx
= (unsigned char *)xrealloc((char *)mline_old
.colorx
, maxwidth
);
523 if (!(blank
&& null
&& mline_old
.image
&& mline_old
.attr
IFFONT(&& mline_old
.font
) IFCOLOR(&& mline_old
.color
) IFCOLORX(&& mline_old
.colorx
)))
526 MakeBlankLine(blank
, maxwidth
);
527 bzero((char *)null
, maxwidth
);
529 mline_blank
.image
= blank
;
530 mline_blank
.attr
= null
;
531 mline_null
.image
= null
;
532 mline_null
.attr
= null
;
534 mline_blank
.font
= null
;
535 mline_null
.font
= null
;
538 mline_blank
.color
= null
;
539 mline_null
.color
= null
;
541 mline_blank
.colorx
= null
;
542 mline_null
.colorx
= null
;
546 #define RESET_AFC(x, bl) do { if (x == old##bl) x = bl; } while (0)
548 #define RESET_LINES(lines, count) \
551 for (i = 0; i < count; i++, ml++) \
553 RESET_AFC(ml->image, blank); \
554 RESET_AFC(ml->attr, null); \
555 IFFONT(RESET_AFC(ml->font, null)); \
556 IFCOLOR(RESET_AFC(ml->color, null)); \
557 IFCOLORX(RESET_AFC(ml->colorx, null)); \
561 /* We have to run through all windows to substitute
562 * the null and blank references.
564 for (p
= windows
; p
; p
= p
->w_next
)
566 RESET_LINES(p
->w_mlines
, p
->w_height
);
569 RESET_LINES(p
->w_hlines
, p
->w_histheight
);
570 RESET_LINES(p
->w_alt_hlines
, p
->w_alt_histheight
);
573 RESET_LINES(p
->w_alt_mlines
, p
->w_alt_height
);
587 if ((nmem
= realloc(mem
, len
)))
595 register unsigned char *p
;
607 #define OLDWIN(y) ((y < p->w_histheight) \
608 ? &p->w_hlines[(p->w_histidx + y) % p->w_histheight] \
609 : &p->w_mlines[y - p->w_histheight])
611 #define NEWWIN(y) ((y < hi) ? &nhlines[y] : &nmlines[y - hi])
615 #define OLDWIN(y) (&p->w_mlines[y])
616 #define NEWWIN(y) (&nmlines[y])
622 ChangeWindowSize(p
, wi
, he
, hi
)
626 struct mline
*mlf
= 0, *mlt
= 0, *ml
, *nmlines
, *nhlines
;
627 int fy
, ty
, l
, lx
, lf
, lt
, yy
, oty
, addone
;
628 int ncx
, ncy
, naka
, t
;
634 if (p
->w_type
== W_TYPE_GROUP
)
636 if (p
->w_width
== wi
&& p
->w_height
== he
&& p
->w_histheight
== hi
)
638 debug("ChangeWindowSize: No change.\n");
646 /* just in case ... */
647 if (wi
&& (p
->w_width
!= wi
|| p
->w_height
!= he
) && p
->w_lay
!= &p
->w_winlay
)
649 debug("ChangeWindowSize: No resize because of overlay?\n");
654 debug("ChangeWindowSize");
655 debug3(" from (%d,%d)+%d", p
->w_width
, p
->w_height
, p
->w_histheight
);
656 debug3(" to(%d,%d)+%d\n", wi
, he
, hi
);
658 fy
= p
->w_histheight
+ p
->w_height
- 1;
661 nmlines
= nhlines
= 0;
668 if (wi
!= p
->w_width
|| he
!= p
->w_height
)
670 if ((nmlines
= (struct mline
*)calloc(he
, sizeof(struct mline
))) == 0)
679 debug1("image stays the same: %d lines\n", he
);
680 nmlines
= p
->w_mlines
;
691 if ((nhlines
= (struct mline
*)calloc(hi
, sizeof(struct mline
))) == 0)
693 Msg(0, "No memory for history buffer - turned off");
700 /* special case: cursor is at magic margin position */
702 if (p
->w_width
&& p
->w_x
== p
->w_width
)
704 debug2("Special addone case: %d %d\n", p
->w_x
, p
->w_y
);
709 /* handle the cursor and autoaka lines now if the widths are equal */
710 if (p
->w_width
== wi
)
712 ncx
= p
->w_x
+ addone
;
713 ncy
= p
->w_y
+ he
- p
->w_height
;
714 /* never lose sight of the line with the cursor on it */
716 for (yy
= p
->w_y
+ p
->w_histheight
- 1; yy
>= 0 && ncy
+ shift
< he
; yy
--)
719 if (ml
->image
[p
->w_width
] == ' ')
726 debug1("resize: cursor out of bounds, shifting %d\n", shift
);
728 if (p
->w_autoaka
> 0)
730 naka
= p
->w_autoaka
+ he
- p
->w_height
+ shift
;
731 if (naka
< 1 || naka
> he
)
741 debug2("fy %d ty %d\n", fy
, ty
);
747 while (fy
>= 0 && ty
>= 0)
749 if (p
->w_width
== wi
)
751 /* here is a simple shortcut: just copy over */
761 /* calculate lenght */
762 for (l
= p
->w_width
- 1; l
> 0; l
--)
763 if (mlf
->image
[l
] != ' ' || mlf
->attr
[l
])
765 if (fy
== p
->w_y
+ p
->w_histheight
&& l
< p
->w_x
)
766 l
= p
->w_x
; /* cursor is non blank */
770 /* add wrapped lines to length */
771 for (yy
= fy
- 1; yy
>= 0; yy
--)
774 if (ml
->image
[p
->w_width
] == ' ')
780 lt
= (l
- 1) % wi
+ 1; /* lf is set above */
782 while (l
> 0 && fy
>= 0 && ty
>= 0)
784 lx
= lt
> lf
? lf
: lt
;
787 if (AllocMline(mlt
, wi
+ 1))
789 MakeBlankLine(mlt
->image
+ lt
, wi
- lt
);
790 mlt
->image
[wi
] = ((oty
== ty
) ? ' ' : 0);
792 if (BcopyMline(mlf
, lf
- lx
, mlt
, lt
- lx
, lx
, wi
+ 1))
795 /* did we copy the cursor ? */
796 if (fy
== p
->w_y
+ p
->w_histheight
&& lf
- lx
<= p
->w_x
&& lf
> p
->w_x
)
798 ncx
= p
->w_x
+ lt
- lf
+ addone
;
800 shift
= wi
? -ncy
+ (l
- lx
) / wi
: 0;
801 if (ty
+ shift
> hi
+ he
- 1)
802 shift
= hi
+ he
- 1 - ty
;
805 debug3("resize: cursor out of bounds, shifting %d [%d/%d]\n", shift
, lt
- lx
, wi
);
806 for (y
= hi
+ he
- 1; y
>= ty
; y
--)
812 ml
= NEWWIN(y
- shift
);
820 naka
= naka
+ shift
> he
? 0 : naka
+ shift
;
824 /* did we copy autoaka line ? */
825 if (p
->w_autoaka
> 0 && fy
== p
->w_autoaka
- 1 + p
->w_histheight
&& lf
- lx
<= 0)
826 naka
= ty
- hi
>= 0 ? 1 + ty
- hi
: 0;
845 ASSERT(l
!= 0 || fy
== yy
);
855 if (AllocMline(mlt
, wi
+ 1))
857 MakeBlankLine(mlt
->image
, wi
+ 1);
863 if (nmlines
!= p
->w_mlines
)
864 for (fy
= 0; fy
< p
->w_height
+ p
->w_histheight
; fy
++)
867 ASSERT(ml
->image
== 0);
871 if (p
->w_mlines
&& p
->w_mlines
!= nmlines
)
872 free((char *)p
->w_mlines
);
873 p
->w_mlines
= nmlines
;
875 if (p
->w_hlines
&& p
->w_hlines
!= nhlines
)
876 free((char *)p
->w_hlines
);
877 p
->w_hlines
= nhlines
;
879 nmlines
= nhlines
= 0;
882 if (p
->w_width
!= wi
)
886 t
= p
->w_tabs
? p
->w_width
: 0;
887 p
->w_tabs
= xrealloc(p
->w_tabs
, wi
+ 1);
893 for (ty
= he
+ hi
- 1; ty
>= 0; ty
--)
898 if (nmlines
&& p
->w_mlines
!= nmlines
)
899 free((char *)nmlines
);
901 if (nhlines
&& p
->w_hlines
!= nhlines
)
902 free((char *)nhlines
);
910 p
->w_tabs
[t
] = t
&& !(t
& 7) ? 1 : 0;
921 /* Change w_Saved_y - this is only an estimate... */
922 p
->w_Saved_y
+= ncy
- p
->w_y
;
926 if (p
->w_autoaka
> 0)
929 /* do sanity checks */
934 if (p
->w_Saved_x
> wi
)
936 if (p
->w_Saved_y
< 0)
938 if (p
->w_Saved_y
>= he
)
939 p
->w_Saved_y
= he
- 1;
941 /* reset scrolling region */
945 /* signal new size to window */
947 if (wi
&& (p
->w_width
!= wi
|| p
->w_height
!= he
)
948 && p
->w_width
!= 0 && p
->w_height
!= 0 && p
->w_ptyfd
>= 0 && p
->w_pid
)
952 debug("Setting pty winsize.\n");
953 if (ioctl(p
->w_ptyfd
, TIOCSWINSZ
, (char *)&glwz
))
954 debug2("SetPtySize: errno %d (fd:%d)\n", errno
, p
->w_ptyfd
);
956 #endif /* TIOCSWINSZ */
963 p
->w_histheight
= hi
;
966 #ifdef BUILTIN_TELNET
967 if (p
->w_type
== W_TYPE_TELNET
)
972 /* Test if everything was ok */
973 for (fy
= 0; fy
< p
->w_height
+ p
->w_histheight
; fy
++)
978 if (p
->w_encoding
== UTF8
)
980 for (l
= 0; l
< p
->w_width
; l
++)
981 ASSERT(ml
->image
[l
] >= ' ' || ml
->font
[l
]);
985 for (l
= 0; l
< p
->w_width
; l
++)
986 ASSERT(ml
->image
[l
] >= ' ');
1000 for (i
= 0; i
< p
->w_alt_height
; i
++)
1001 FreeMline(p
->w_alt_mlines
+ i
);
1002 free(p
->w_alt_mlines
);
1004 p
->w_alt_mlines
= 0;
1006 p
->w_alt_height
= 0;
1010 if (p
->w_alt_hlines
)
1012 for (i
= 0; i
< p
->w_alt_histheight
; i
++)
1013 FreeMline(p
->w_alt_hlines
+ i
);
1014 free(p
->w_alt_hlines
);
1016 p
->w_alt_hlines
= 0;
1017 p
->w_alt_histidx
= 0;
1019 p
->w_alt_histheight
= 0;
1029 ml
= p
->w_alt_mlines
; p
->w_alt_mlines
= p
->w_mlines
; p
->w_mlines
= ml
;
1030 t
= p
->w_alt_width
; p
->w_alt_width
= p
->w_width
; p
->w_width
= t
;
1031 t
= p
->w_alt_height
; p
->w_alt_height
= p
->w_height
; p
->w_height
= t
;
1032 t
= p
->w_alt_histheight
; p
->w_alt_histheight
= p
->w_histheight
; p
->w_histheight
= t
;
1033 t
= p
->w_alt_x
; p
->w_alt_x
= p
->w_x
; p
->w_x
= t
;
1034 t
= p
->w_alt_y
; p
->w_alt_y
= p
->w_y
; p
->w_y
= t
;
1036 ml
= p
->w_alt_hlines
; p
->w_alt_hlines
= p
->w_hlines
; p
->w_hlines
= ml
;
1037 t
= p
->w_alt_histidx
; p
->w_alt_histidx
= p
->w_histidx
; p
->w_histidx
= t
;
1045 int ox
= p
->w_x
, oy
= p
->w_y
;
1048 ChangeWindowSize(p
, p
->w_alt_width
, p
->w_alt_height
, p
->w_alt_histheight
);
1057 if (!p
->w_alt_mlines
)
1060 ChangeWindowSize(p
, p
->w_alt_width
, p
->w_alt_height
, p
->w_alt_histheight
);