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>
33 # include <sys/ioctl.h>
42 static int CountChars
__P((int));
43 static int DoAddChar
__P((int));
44 static int BlankResize
__P((int, int));
45 static int CallRewrite
__P((int, int, int, int));
46 static void disp_readev_fn
__P((struct event
*, char *));
47 static void disp_writeev_fn
__P((struct event
*, char *));
49 static void disp_writeev_eagain
__P((struct event
*, char *));
51 static void disp_status_fn
__P((struct event
*, char *));
52 static void disp_hstatus_fn
__P((struct event
*, char *));
53 static void disp_blocked_fn
__P((struct event
*, char *));
54 static void cv_winid_fn
__P((struct event
*, char *));
56 static void disp_map_fn
__P((struct event
*, char *));
58 static void disp_idle_fn
__P((struct event
*, char *));
60 static void disp_blanker_fn
__P((struct event
*, char *));
62 static void WriteLP
__P((int, int));
63 static void INSERTCHAR
__P((int));
64 static void RAW_PUTCHAR
__P((int));
66 static void SetBackColor
__P((int));
68 static void RemoveStatusMinWait
__P((void));
71 extern struct layer
*flayer
;
72 extern struct win
*windows
, *fore
;
73 extern struct LayFuncs WinLf
;
75 extern int use_hardstatus
;
76 extern int MsgWait
, MsgMinWait
;
77 extern int Z0width
, Z1width
;
78 extern unsigned char *blank
, *null
;
79 extern struct mline mline_blank
, mline_null
, mline_old
;
80 extern struct mchar mchar_null
, mchar_blank
, mchar_so
;
81 extern struct NewWindow nwin_default
;
82 extern struct action idleaction
;
84 /* XXX shouldn't be here */
85 extern char *hstatusstring
;
86 extern char *captionstring
;
92 extern int pty_preopen
;
93 #if defined(TIOCSWINSZ) || defined(TIOCGWINSZ)
94 extern struct winsize glwz
;
97 extern int real_uid
, real_gid
;
101 * tputs needs this to calculate the padding
105 #endif /* NEED_OSPEED */
109 struct display
*display
, *displays
;
111 int attr2color
[8][4];
116 struct display TheDisplay
;
122 int defobuflimit
= OBUF_MAX
;
123 int defnonblock
= -1;
124 int defmousetrack
= 0;
129 int hardstatusemu
= HSTATUS_IGNORE
;
131 int focusminwidth
, focusminheight
;
134 * Default layer management
138 DefProcess(bufp
, lenp
)
147 DefRedisplayLine(y
, xs
, xe
, isblank
)
148 int y
, xs
, xe
, isblank
;
150 if (isblank
== 0 && y
>= 0)
151 DefClearLine(y
, xs
, xe
, 0);
155 DefClearLine(y
, xs
, xe
, bce
)
158 LClearLine(flayer
, y
, xs
, xe
, bce
, (struct mline
*)0);
163 DefRewrite(y
, xs
, xe
, rend
, doit
)
181 LAY_DISPLAYS(flayer
, InsertMode(0));
182 /* ChangeScrollRegion(0, D_height - 1); */
183 LKeypadMode(flayer
, 0);
184 LCursorkeysMode(flayer
, 0);
185 LCursorVisibility(flayer
, 0);
186 LMouseMode(flayer
, 0);
187 LSetRendition(flayer
, &mchar_null
);
188 LSetFlow(flayer
, nwin_default
.flowflag
& FLOW_NOW
);
192 * Blank layer management
195 struct LayFuncs BlankLf
=
212 flayer
->l_width
= wi
;
213 flayer
->l_height
= he
;
219 * Generate new display, start with a blank layer.
220 * The termcap arrays are not initialised here.
221 * The new display is placed in the displays list.
225 MakeDisplay(uname
, utty
, term
, fd
, pid
, Mode
)
226 char *uname
, *utty
, *term
;
231 struct baud_values
*b
;
233 if (!*(u
= FindUserPtr(uname
)) && UserAdd(uname
, (char *)0, u
))
234 return 0; /* could not find or add user */
237 if ((display
= (struct display
*)calloc(1, sizeof(*display
))) == 0)
242 bzero((char *)&TheDisplay
, sizeof(TheDisplay
));
243 display
= &TheDisplay
;
245 display
->d_next
= displays
;
248 D_nonblock
= defnonblock
;
250 D_readev
.fd
= D_writeev
.fd
= fd
;
251 D_readev
.type
= EV_READ
;
252 D_writeev
.type
= EV_WRITE
;
253 D_readev
.data
= D_writeev
.data
= (char *)display
;
254 D_readev
.handler
= disp_readev_fn
;
255 D_writeev
.handler
= disp_writeev_fn
;
257 D_writeev
.condpos
= &D_obuflen
;
258 D_writeev
.condneg
= &D_obuffree
;
260 D_statusev
.type
= EV_TIMEOUT
;
261 D_statusev
.data
= (char *)display
;
262 D_statusev
.handler
= disp_status_fn
;
263 D_hstatusev
.type
= EV_TIMEOUT
;
264 D_hstatusev
.data
= (char *)display
;
265 D_hstatusev
.handler
= disp_hstatus_fn
;
266 D_blockedev
.type
= EV_TIMEOUT
;
267 D_blockedev
.data
= (char *)display
;
268 D_blockedev
.handler
= disp_blocked_fn
;
269 D_blockedev
.condpos
= &D_obuffree
;
270 D_blockedev
.condneg
= &D_obuflenmax
;
271 D_hstatusev
.handler
= disp_hstatus_fn
;
273 D_mapev
.type
= EV_TIMEOUT
;
274 D_mapev
.data
= (char *)display
;
275 D_mapev
.handler
= disp_map_fn
;
277 D_idleev
.type
= EV_TIMEOUT
;
278 D_idleev
.data
= (char *)display
;
279 D_idleev
.handler
= disp_idle_fn
;
281 D_blankerev
.type
= EV_READ
;
282 D_blankerev
.data
= (char *)display
;
283 D_blankerev
.handler
= disp_blanker_fn
;
287 D_status_obuffree
= -1;
288 Resize_obuf(); /* Allocate memory for buffer */
289 D_obufmax
= defobuflimit
;
290 D_obuflenmax
= D_obuflen
- D_obufmax
;
292 D_auto_nuke
= defautonuke
;
299 if ((b
= lookup_baud((int)cfgetospeed(&D_OldMode
.tio
))))
303 if ((b
= lookup_baud(D_OldMode
.tio
.c_cflag
& CBAUD
)))
306 D_dospeed
= (short)D_OldMode
.m_ttyb
.sg_ospeed
;
309 debug1("New displays ospeed = %d\n", D_dospeed
);
311 strncpy(D_usertty
, utty
, sizeof(D_usertty
) - 1);
312 D_usertty
[sizeof(D_usertty
) - 1] = 0;
313 strncpy(D_termname
, term
, sizeof(D_termname
) - 1);
314 D_termname
[sizeof(D_termname
) - 1] = 0;
316 D_processinput
= ProcessInput
;
317 D_mousetrack
= defmousetrack
;
327 struct display
*d
, **dp
;
341 SetTTY(D_userfd
, &D_OldMode
);
342 fcntl(D_userfd
, F_SETFL
, 0);
348 if (D_processinputdata
)
349 free(D_processinputdata
);
350 D_processinputdata
= 0;
375 if (bd
.bd_dpy
== display
)
377 bd
.bd_start_braille
= 0;
383 for (dp
= &displays
; (d
= *dp
) ; dp
= &d
->d_next
)
387 if (D_status_lastmsg
)
388 free(D_status_lastmsg
);
391 *dp
= display
->d_next
;
393 ASSERT(display
== displays
);
394 ASSERT(display
== &TheDisplay
);
398 while (D_canvas
.c_slperp
)
399 FreeCanvas(D_canvas
.c_slperp
);
402 for (p
= windows
; p
; p
= p
->w_next
)
404 if (p
->w_pdisplay
== display
)
406 if (p
->w_lastdisp
== display
)
408 if (p
->w_readev
.condneg
== &D_status
|| p
->w_readev
.condneg
== &D_obuflenmax
)
409 p
->w_readev
.condpos
= p
->w_readev
.condneg
= 0;
412 for (p
= windows
; p
; p
= p
->w_next
)
413 if (p
->w_zdisplay
== display
)
422 free((char *)display
);
428 * if the adaptflag is on, we keep the size of this display, else
429 * we may try to restore our old window sizes.
440 /* Check for toggle */
441 if (D_IM
&& strcmp(D_IM
, D_EI
))
448 /* Check for toggle */
449 if (D_KS
&& strcmp(D_KS
, D_KE
))
451 if (D_CCS
&& strcmp(D_CCS
, D_CCE
))
462 ResizeDisplay(D_defwidth
, D_defheight
);
463 ChangeScrollRegion(0, D_height
- 1);
467 debug1("we %swant to adapt all our windows to the display\n",
468 (adapt
) ? "" : "don't ");
469 /* In case the size was changed by a init sequence */
470 CheckScreenSize((adapt
) ? 2 : 0);
482 ResizeDisplay(D_defwidth
, D_defheight
);
484 ChangeScrollRegion(0, D_height
- 1);
491 SetRendition(&mchar_null
);
498 ShowHStatus((char *)0);
503 GotoPos(0, D_height
- 1);
517 if (!D_insert
&& D_x
< D_width
- 1)
531 RefreshLine(D_y
, D_x
, D_width
-1, 0);
543 if (D_insert
&& D_x
< D_width
- 1)
552 if (D_x
< D_width
- 1)
559 if (D_CLP
|| D_y
!= D_bot
)
564 GotoPos(D_width
- 1, y
);
567 debug("PUTCHARLP: lp_missing!\n");
572 /* XXX -> PutChar ? */
576 D_lpchar
.image
= D_mbcs
;
584 * RAW_PUTCHAR() is for all text that will be displayed.
585 * NOTE: charset Nr. 0 has a conversion table, but c1, c2, ... don't.
596 if (D_encoding
== UTF8
)
598 c
= (c
& 255) | (unsigned char)D_rend
.font
<< 8;
604 D_x
+= D_AM
? 1 : -1;
607 else if (utf8_isdouble(c
))
616 AddCStr2(D_CS0
, '0');
623 if (D_xtable
&& D_xtable
[(int)(unsigned char)D_rend
.font
] && D_xtable
[(int)(unsigned char)D_rend
.font
][(int)(unsigned char)c
])
624 AddStr(D_xtable
[(int)(unsigned char)D_rend
.font
][(int)(unsigned char)c
]);
634 if (is_dw_font(D_rend
.font
))
644 if (D_x
== D_width
- 1)
645 D_x
+= D_AM
? 1 : -1;
650 # if defined(ENCODINGS) && defined(DW_CHARS)
652 c
= PrepareEncodedChar(c
);
657 if (D_xtable
&& D_xtable
[(int)(unsigned char)D_rend
.font
] && D_xtable
[(int)(unsigned char)D_rend
.font
][(int)(unsigned char)c
])
658 AddStr(D_xtable
[(int)(unsigned char)D_rend
.font
][(int)(unsigned char)c
]);
660 AddChar(D_rend
.font
!= '0' ? c
: D_c0_tab
[(int)(unsigned char)c
]);
668 if (++D_x
>= D_width
)
672 else if (!D_CLP
|| D_x
> D_width
)
675 if (D_y
< D_height
-1 && D_y
!= D_bot
)
693 /* this is for ESC-sequences only (AddChar is a macro) */
702 if (display
&& s
&& *s
)
705 tputs(s
, 1, DoAddChar
);
714 if (display
&& s
&& *s
)
717 tputs(tgoto(s
, 0, c
), 1, DoAddChar
);
722 /* Insert mode is a toggle on some terminals, so we need this hack:
728 if (display
&& on
!= D_insert
&& D_IM
)
738 /* ...and maybe keypad application mode is a toggle, too:
748 if (display
&& D_keypad
!= on
&& D_KS
)
767 if (display
&& D_cursorkeys
!= on
&& D_CCS
)
782 if (display
&& D_revvid
!= on
&& D_CVR
)
796 if (display
&& D_curvis
!= v
)
799 AddCStr(D_VE
); /* do this always, just to be safe */
803 else if (v
== 1 && D_VS
)
818 if (mode
< D_mousetrack
)
828 sprintf(mousebuf
, "\033[?%dl", D_mouse
);
833 sprintf(mousebuf
, "\033[?%dh", mode
);
860 tputs(s
, 1, CountChars
);
868 CallRewrite(y
, xs
, xe
, doit
)
871 struct canvas
*cv
, *cvlist
, *cvlnext
;
873 struct layer
*oldflayer
;
876 debug3("CallRewrite %d %d %d\n", y
, xs
, xe
);
881 for (cv
= D_cvlist
; cv
; cv
= cv
->c_next
)
883 if (y
< cv
->c_ys
|| y
> cv
->c_ye
|| xe
< cv
->c_xs
|| xs
> cv
->c_xe
)
885 for (vp
= cv
->c_vplist
; vp
; vp
= vp
->v_next
)
886 if (y
>= vp
->v_ys
&& y
<= vp
->v_ye
&& xe
>= vp
->v_xs
&& xs
<= vp
->v_xe
)
894 flayer
= cv
->c_layer
;
895 cvlist
= flayer
->l_cvlist
;
896 cvlnext
= cv
->c_lnext
;
897 flayer
->l_cvlist
= cv
;
899 LayRewrite(y
- vp
->v_yoff
, xs
- vp
->v_xoff
, xe
- vp
->v_xoff
, &D_rend
, 1);
900 flayer
->l_cvlist
= cvlist
;
901 cv
->c_lnext
= cvlnext
;
905 if (cv
== 0 || cv
->c_layer
== 0)
906 return EXPENSIVE
; /* not found or nothing on it */
907 if (xs
< vp
->v_xs
|| xe
> vp
->v_xe
)
908 return EXPENSIVE
; /* crosses viewport boundaries */
909 if (y
- vp
->v_yoff
< 0 || y
- vp
->v_yoff
>= cv
->c_layer
->l_height
)
910 return EXPENSIVE
; /* line not on layer */
911 if (xs
- vp
->v_xoff
< 0 || xe
- vp
->v_xoff
>= cv
->c_layer
->l_width
)
912 return EXPENSIVE
; /* line not on layer */
914 if (D_encoding
== UTF8
)
918 flayer
= cv
->c_layer
;
919 debug3("Calling Rewrite %d %d %d\n", y
- vp
->v_yoff
, xs
- vp
->v_xoff
, xe
- vp
->v_xoff
);
920 cost
= LayRewrite(y
- vp
->v_yoff
, xs
- vp
->v_xoff
, xe
- vp
->v_xoff
, &D_rend
, 0);
923 cost
+= D_EIcost
+ D_IMcost
;
932 register int dy
, dx
, x1
, y1
;
933 register int costx
, costy
;
937 enum move_t xm
= M_NONE
, ym
= M_NONE
;
948 x1
= -1; /* don't know how the terminal treats this */
956 if (dy
== 0 && dx
== 0)
958 debug2("GotoPos (%d,%d)", x1
, y1
);
959 debug2(" -> (%d,%d)\n", x2
, y2
);
960 if (!D_MS
) /* Safe to move ? */
961 SetRendition(&mchar_null
);
962 if (y1
< 0 /* don't know the y position */
963 || (y2
> D_bot
&& y1
<= D_bot
) /* have to cross border */
964 || (y2
< D_top
&& y1
>= D_top
)) /* of scrollregion ? */
967 if (D_HO
&& !x2
&& !y2
)
970 AddCStr(tgoto(D_CM
, x2
, y2
));
976 /* some scrollregion implementations don't allow movements
977 * away from the region. sigh.
979 if ((y1
> D_bot
&& y2
> y1
) || (y1
< D_top
&& y2
< y1
))
982 /* Calculate CMcost */
983 if (D_HO
&& !x2
&& !y2
)
986 s
= tgoto(D_CM
, x2
, y2
);
987 CMcost
= CalcCost(s
);
989 /* Calculate the cost to move the cursor to the right x position */
991 if (x1
>= 0) /* relativ x positioning only if we know where we are */
995 if (D_CRI
&& (dx
> 1 || !D_ND
))
997 costx
= CalcCost(tgoto(D_CRI
, 0, dx
));
1000 if ((m
= D_NDcost
* dx
) < costx
)
1005 /* Speedup: dx <= LayRewrite() */
1006 if (dx
< costx
&& (m
= CallRewrite(y1
, x1
, x2
- 1, 0)) < costx
)
1014 if (D_CLE
&& (dx
< -1 || !D_BC
))
1016 costx
= CalcCost(tgoto(D_CLE
, 0, -dx
));
1019 if ((m
= -dx
* D_LEcost
) < costx
)
1028 /* Speedup: LayRewrite() >= x2 */
1029 if (x2
+ D_CRcost
< costx
&& (m
= (x2
? CallRewrite(y1
, 0, x2
- 1, 0) : 0) + D_CRcost
) < costx
)
1035 /* Check if it is already cheaper to do CM */
1036 if (costx
>= CMcost
)
1039 /* Calculate the cost to move the cursor to the right y position */
1043 if (D_CDO
&& dy
> 1) /* DO & NL are always != 0 */
1045 costy
= CalcCost(tgoto(D_CDO
, 0, dy
));
1048 if ((m
= dy
* ((x2
== 0) ? D_NLcost
: D_DOcost
)) < costy
)
1056 if (D_CUP
&& (dy
< -1 || !D_UP
))
1058 costy
= CalcCost(tgoto(D_CUP
, 0, -dy
));
1061 if ((m
= -dy
* D_UPcost
) < costy
)
1070 /* Finally check if it is cheaper to do CM */
1071 if (costx
+ costy
>= CMcost
)
1081 AddCStr2(D_CLE
, -dx
);
1088 AddCStr2(D_CRI
, dx
);
1097 (void) CallRewrite(y1
, x1
, x2
- 1, 1);
1110 AddCStr2(D_CUP
, -dy
);
1113 s
= (x2
== 0) ? D_NL
: D_DO
;
1118 AddCStr2(D_CDO
, dy
);
1131 ClearArea(0, 0, 0, D_width
- 1, D_width
- 1, D_height
- 1, 0, 0);
1135 ClearArea(x1
, y1
, xs
, xe
, x2
, y2
, bce
, uselayfn
)
1136 int x1
, y1
, xs
, xe
, x2
, y2
, bce
, uselayfn
;
1140 struct viewport
*vp
;
1142 debug2("Clear %d,%d", x1
, y1
);
1143 debug2(" %d-%d", xs
, xe
);
1144 debug2(" %d,%d", x2
, y2
);
1145 debug2(" uselayfn=%d bce=%d\n", uselayfn
, bce
);
1155 if (D_UT
) /* Safe to erase ? */
1156 SetRendition(&mchar_null
);
1161 if (D_lp_missing
&& y1
<= D_bot
&& xe
>= D_width
- 1)
1163 if (y2
> D_bot
|| (y2
== D_bot
&& x2
>= D_width
- 1))
1166 if (x2
== D_width
- 1 && (xs
== 0 || y1
== y2
) && xe
== D_width
- 1 && y2
== D_height
- 1 && (!bce
|| D_BE
))
1169 if (x1
== 0 && y1
== 0 && D_auto_nuke
)
1172 if (x1
== 0 && y1
== 0 && D_CL
)
1179 * Workaround a hp700/22 terminal bug. Do not use CD where CE
1180 * is also appropriate.
1182 if (D_CD
&& (y1
< y2
|| !D_CE
))
1189 if (x1
== 0 && xs
== 0 && (xe
== D_width
- 1 || y1
== y2
) && y1
== 0 && D_CCD
&& (!bce
|| D_BE
))
1196 for (y
= y1
; y
<= y2
; y
++, x1
= xs
)
1200 if (x1
== 0 && D_CB
&& (xxe
!= D_width
- 1 || (D_x
== xxe
&& D_y
== y
)) && (!bce
|| D_BE
))
1206 if (xxe
== D_width
- 1 && D_CE
&& (!bce
|| D_BE
))
1215 for (cv
= D_cvlist
; cv
; cv
= cv
->c_next
)
1217 if (y
< cv
->c_ys
|| y
> cv
->c_ye
|| xxe
< cv
->c_xs
|| x1
> cv
->c_xe
)
1219 for (vp
= cv
->c_vplist
; vp
; vp
= vp
->v_next
)
1220 if (y
>= vp
->v_ys
&& y
<= vp
->v_ye
&& xxe
>= vp
->v_xs
&& x1
<= vp
->v_xe
)
1225 if (cv
&& cv
->c_layer
&& x1
>= vp
->v_xs
&& xxe
<= vp
->v_xe
&&
1226 y
- vp
->v_yoff
>= 0 && y
- vp
->v_yoff
< cv
->c_layer
->l_height
&&
1227 xxe
- vp
->v_xoff
>= 0 && x1
- vp
->v_xoff
< cv
->c_layer
->l_width
)
1229 struct layer
*oldflayer
= flayer
;
1230 struct canvas
*cvlist
, *cvlnext
;
1231 flayer
= cv
->c_layer
;
1232 cvlist
= flayer
->l_cvlist
;
1233 cvlnext
= cv
->c_lnext
;
1234 flayer
->l_cvlist
= cv
;
1236 LayClearLine(y
- vp
->v_yoff
, x1
- vp
->v_xoff
, xxe
- vp
->v_xoff
, bce
);
1237 flayer
->l_cvlist
= cvlist
;
1238 cv
->c_lnext
= cvlnext
;
1243 ClearLine((struct mline
*)0, y
, x1
, xxe
, bce
);
1249 * if cur_only > 0, we only redisplay current line, as a full refresh is
1250 * too expensive over a low baud line.
1258 /* XXX do em all? */
1260 ChangeScrollRegion(0, D_height
- 1);
1263 CursorVisibility(0);
1265 SetRendition(&mchar_null
);
1272 if (cur_only
> 0 && D_fore
)
1273 RefreshArea(0, D_fore
->w_y
, D_width
- 1, D_fore
->w_y
, 1);
1277 CV_CALL(D_forecv
, LayRestore();LaySetCursor());
1281 RedisplayDisplays(cur_only
)
1284 struct display
*olddisplay
= display
;
1285 for (display
= displays
; display
; display
= display
->d_next
)
1286 Redisplay(cur_only
);
1287 display
= olddisplay
;
1293 ScrollH(y
, xs
, xe
, n
, bce
, oml
)
1294 int y
, xs
, xe
, n
, bce
;
1301 if (xe
!= D_width
- 1)
1303 RefreshLine(y
, xs
, xe
, 0);
1304 /* UpdateLine(oml, y, xs, xe); */
1309 SetRendition(&mchar_null
);
1316 if (n
>= xe
- xs
+ 1)
1318 if (D_CDC
&& !(n
== 1 && D_DC
))
1327 RefreshLine(y
, xs
, xe
, 0);
1328 /* UpdateLine(oml, y, xs, xe); */
1334 if (-n
>= xe
- xs
+ 1)
1338 if (D_CIC
&& !(n
== -1 && D_IC
))
1339 AddCStr2(D_CIC
, -n
);
1348 SetRendition(&mchar_null
);
1354 bce
= 0; /* all done */
1358 /* UpdateLine(oml, y, xs, xe); */
1359 RefreshLine(y
, xs
, xe
, 0);
1365 SetRendition(&mchar_null
);
1371 bce
= 0; /* all done */
1377 ClearLine((struct mline
*)0, y
, xe
- n
+ 1, xe
, bce
);
1379 ClearLine((struct mline
*)0, y
, xs
, xs
- n
- 1, bce
);
1381 if (D_lp_missing
&& y
== D_bot
)
1384 WriteLP(D_width
- 1 - n
, y
);
1390 ScrollV(xs
, ys
, xe
, ye
, n
, bce
)
1391 int xs
, ys
, xe
, ye
, n
, bce
;
1396 int alok
, dlok
, aldlfaster
;
1402 if (n
>= ye
- ys
+ 1 || -n
>= ye
- ys
+ 1)
1404 ClearArea(xs
, ys
, xs
, xe
, xe
, ye
, bce
, 0);
1407 if (xs
> D_vpxmin
|| xe
< D_vpxmax
)
1409 RefreshArea(xs
, ys
, xe
, ye
, 0);
1415 if (D_bot
> ye
|| D_bot
< ys
)
1420 if (missy
> ye
|| missy
< ys
)
1431 if (n
>= ye
- ys
+ 1)
1436 if (ys
< D_top
|| D_bot
!= ye
)
1437 ChangeScrollRegion(ys
, ye
);
1438 alok
= (D_AL
|| D_CAL
|| (ys
>= D_top
&& ye
== D_bot
&& up
));
1439 dlok
= (D_DL
|| D_CDL
|| (ys
>= D_top
&& ye
== D_bot
&& !up
));
1440 if (D_top
!= ys
&& !(alok
&& dlok
))
1441 ChangeScrollRegion(ys
, ye
);
1445 (oldbot
== D_bot
&& up
&& D_top
== ys
&& D_bot
== ye
)))
1447 WriteLP(D_width
- 1, oldbot
);
1448 if (oldbot
== D_bot
) /* have scrolled */
1453 ChangeScrollRegion(oldtop, oldbot);
1456 ClearLine((struct mline
*)0, ye
, xs
, xe
, bce
);
1463 SetRendition(&mchar_null
);
1469 aldlfaster
= (n
> 1 && ys
>= D_top
&& ye
== D_bot
&& ((up
&& D_CDL
) || (!up
&& D_CAL
)));
1471 if ((up
|| D_SR
) && D_top
== ys
&& D_bot
== ye
&& !aldlfaster
)
1476 for(i
= n
; i
-- > 0; )
1477 AddCStr(D_NL
); /* was SF, I think NL is faster */
1482 for(i
= n
; i
-- > 0; )
1486 else if (alok
&& dlok
)
1488 if (up
|| ye
!= D_bot
)
1490 GotoPos(0, up
? ys
: ye
+1-n
);
1491 if (D_CDL
&& !(n
== 1 && D_DL
))
1497 if (!up
|| ye
!= D_bot
)
1499 GotoPos(0, up
? ye
+1-n
: ys
);
1500 if (D_CAL
&& !(n
== 1 && D_AL
))
1509 RefreshArea(xs
, ys
, xe
, ye
, 0);
1515 ClearArea(xs
, ye
- n
+ 1, xs
, xe
, xe
, ye
, bce
, 0);
1517 ClearArea(xs
, ys
, xs
, xe
, xe
, ys
+ n
- 1, bce
, 0);
1519 if (D_lp_missing
&& missy
!= D_bot
)
1520 WriteLP(D_width
- 1, missy
);
1522 ChangeScrollRegion(oldtop, oldbot);
1523 if (D_lp_missing && missy != D_bot)
1524 WriteLP(D_width - 1, missy);
1532 register int i
, j
, old
, typ
;
1534 if (!display
|| (old
= D_rend
.attr
) == new)
1537 D_col16change
= (old
^ new) & (A_BFG
| A_BBG
);
1538 new ^= D_col16change
;
1542 #if defined(TERMINFO) && defined(USE_SGR)
1548 tputs(tparm(D_SA
, new & A_SO
, new & A_US
, new & A_RV
, new & A_BL
,
1549 new & A_DI
, new & A_BD
, 0 , 0 ,
1555 rend_setdefault(&D_rend
);
1562 if ((new & old
) != old
)
1572 /* ansi attrib handling: \E[m resets color, too */
1574 rend_setdefault(&D_rend
);
1579 /* D_ME may also reset the alternate charset */
1591 for (i
= 0, j
= 1; old
&& i
< NATTR
; i
++, j
<<= 1)
1598 AddCStr(D_attrtab
[i
]);
1599 typ
|= D_attrtyp
[i
];
1610 int old
= D_rend
.font
;
1611 if (!display
|| old
== new)
1615 if (D_encoding
&& CanEncodeFont(D_encoding
, new))
1617 if (new == D_realfont
)
1621 if (D_xtable
&& D_xtable
[(int)(unsigned char)new] &&
1622 D_xtable
[(int)(unsigned char)new][256])
1624 AddCStr(D_xtable
[(int)(unsigned char)new][256]);
1628 if (!D_CG0
&& new != '0')
1647 AddCStr2(D_CS0
, new);
1662 jj
= (jj
- 232) / 6;
1663 jj
= (jj
& 1) << 3 | (jj
& 2 ? 7 : 0);
1671 min
= r
< g
? (r
< b
? r
: b
) : (g
< b
? g
: b
);
1672 max
= r
> g
? (r
> b
? r
: b
) : (g
> b
? g
: b
);
1674 jj
= ((max
+ 1) & 2) << 2 | ((max
+ 1) & 4 ? 7 : 0);
1676 jj
= (b
- min
) / (max
- min
) << 2 | (g
- min
) / (max
- min
) << 1 | (r
-
1677 min
) / (max
- min
) | (max
> 3 ? 8 : 0);
1690 return (jj
- 232) / 3 + 80;
1697 return ((r
+ 1) / 2) * 16 + ((g
+ 1) / 2) * 4 + ((b
+ 1) / 2) + 16;
1708 static unsigned char sftrans
[8] = {0,4,2,6,1,5,3,7};
1713 of
= rend_getfg(&D_rend
);
1714 ob
= rend_getbg(&D_rend
);
1717 /* intense default not invented yet */
1723 debug2("SetColor %d %d", coli2e(of
), coli2e(ob
));
1724 debug2(" -> %d %d\n", coli2e(f
), coli2e(b
));
1725 debug2("(%d %d", of
, ob
);
1726 debug2(" -> %d %d)\n", f
, b
);
1728 if (!D_CAX
&& D_hascolor
&& ((f
== 0 && f
!= of
) || (b
== 0 && b
!= ob
)))
1735 oattr
= D_rend
.attr
;
1736 AddCStr(D_ME
? D_ME
: "\033[m");
1740 /* D_ME may also reset the alternate charset */
1753 rend_setfg(&D_rend
, f
);
1754 rend_setbg(&D_rend
, b
);
1760 f
= f
? coli2e(f
) : -1;
1761 b
= b
? coli2e(b
) : -1;
1762 of
= of
? coli2e(of
) : -1;
1763 ob
= ob
? coli2e(ob
) : -1;
1765 if (f
!= of
&& f
> 15 && D_CCO
!= 256)
1766 f
= D_CCO
== 88 && D_CAF
? color256to88(f
) : color256to16(f
);
1767 if (f
!= of
&& f
> 15 && D_CAF
)
1772 if (b
!= ob
&& b
> 15 && D_CCO
!= 256)
1773 b
= D_CCO
== 88 && D_CAB
? color256to88(b
) : color256to16(b
);
1774 if (b
!= ob
&& b
> 15 && D_CAB
)
1780 if (f
!= of
&& f
!= (of
| 8))
1783 AddCStr("\033[39m"); /* works because AX is set */
1785 AddCStr2(D_CAF
, f
& 7);
1787 AddCStr2(D_CSF
, sftrans
[f
& 7]);
1789 if (b
!= ob
&& b
!= (ob
| 8))
1792 AddCStr("\033[49m"); /* works because AX is set */
1794 AddCStr2(D_CAB
, b
& 7);
1796 AddCStr2(D_CSB
, sftrans
[b
& 7]);
1799 if (f
!= of
&& D_CXT
&& (f
& 8) != 0 && f
!= -1)
1802 AddCStr2("\033[9%p1%dm", f
& 7);
1804 AddCStr2("\033[9%dm", f
& 7);
1807 if (b
!= ob
&& D_CXT
&& (b
& 8) != 0 && b
!= -1)
1810 AddCStr2("\033[10%p1%dm", b
& 7);
1812 AddCStr2("\033[10%dm", b
& 7);
1824 SetColor(rend_getfg(&D_rend
), new);
1835 if (nattr2color
&& D_hascolor
&& (mc
->attr
& nattr2color
) != 0)
1837 static struct mchar mmc
;
1840 for (i
= 0; i
< 8; i
++)
1841 if (attr2color
[i
] && (mc
->attr
& (1 << i
)) != 0)
1843 if (mc
->color
== 0 && attr2color
[i
][3])
1844 ApplyAttrColor(attr2color
[i
][3], &mmc
);
1845 else if ((mc
->color
& 0x0f) == 0 && attr2color
[i
][2])
1846 ApplyAttrColor(attr2color
[i
][2], &mmc
);
1847 else if ((mc
->color
& 0xf0) == 0 && attr2color
[i
][1])
1848 ApplyAttrColor(attr2color
[i
][1], &mmc
);
1850 ApplyAttrColor(attr2color
[i
][0], &mmc
);
1853 debug2("SetRendition: mapped to %02x %02x\n", (unsigned char)mc
->attr
, 0x99 - (unsigned char)mc
->color
);
1856 if (D_hascolor
&& D_CC8
&& (mc
->attr
& (A_BFG
|A_BBG
)))
1859 if ((mc
->attr
& A_BFG
) && D_MD
)
1861 if ((mc
->attr
& A_BBG
) && D_MB
)
1863 if (D_rend
.attr
!= a
)
1867 # endif /* COLORS16 */
1869 if (D_rend
.attr
!= mc
->attr
)
1873 if (D_rend
.color
!= mc
->color
1875 || D_rend
.colorx
!= mc
->colorx
1881 SetColor(rend_getfg(mc
), rend_getbg(mc
));
1884 if (D_rend
.font
!= mc
->font
)
1890 SetRenditionMline(ml
, x
)
1897 if (nattr2color
&& D_hascolor
&& (ml
->attr
[x
] & nattr2color
) != 0)
1900 copy_mline2mchar(&mc
, ml
, x
);
1905 if (D_hascolor
&& D_CC8
&& (ml
->attr
[x
] & (A_BFG
|A_BBG
)))
1907 int a
= ml
->attr
[x
];
1908 if ((ml
->attr
[x
] & A_BFG
) && D_MD
)
1910 if ((ml
->attr
[x
] & A_BBG
) && D_MB
)
1912 if (D_rend
.attr
!= a
)
1916 # endif /* COLORS16 */
1918 if (D_rend
.attr
!= ml
->attr
[x
])
1919 SetAttr(ml
->attr
[x
]);
1921 if (D_rend
.color
!= ml
->color
[x
]
1923 || D_rend
.colorx
!= ml
->colorx
[x
]
1931 copy_mline2mchar(&mc
, ml
, x
);
1932 SetColor(rend_getfg(&mc
), rend_getbg(&mc
));
1936 if (D_rend
.font
!= ml
->font
[x
])
1937 SetFont(ml
->font
[x
]);
1945 register char *s
, *t
;
1955 debug("tc not inited, just writing msg\n");
1956 if (D_processinputdata
)
1957 return; /* XXX: better */
1963 if (!use_hardstatus
|| !D_HS
)
1970 max
= D_WS
> 0 ? D_WS
: (D_width
- !D_CLP
);
1974 if (strcmp(msg
, D_status_lastmsg
) == 0)
1976 debug("same message - increase timeout");
1977 if (!D_status_obufpos
)
1978 SetTimeout(&D_statusev
, MsgWait
);
1981 RemoveStatusMinWait();
1983 for (s
= t
= msg
; *s
&& t
- msg
< max
; ++s
)
1986 else if ((unsigned char)*s
>= ' ' && *s
!= 0177)
1991 if (t
- msg
>= D_status_buflen
)
1994 if (D_status_lastmsg
)
1995 buf
= realloc(D_status_lastmsg
, t
- msg
+ 1);
1997 buf
= malloc(t
- msg
+ 1);
2000 D_status_lastmsg
= buf
;
2001 D_status_buflen
= t
- msg
+ 1;
2004 if (t
- msg
< D_status_buflen
)
2005 strcpy(D_status_lastmsg
, msg
);
2006 D_status_len
= t
- msg
;
2007 D_status_lastx
= D_x
;
2008 D_status_lasty
= D_y
;
2009 if (!use_hardstatus
|| D_has_hstatus
== HSTATUS_IGNORE
|| D_has_hstatus
== HSTATUS_MESSAGE
)
2011 D_status
= STATUS_ON_WIN
;
2012 debug1("using STATLINE %d\n", STATLINE
);
2013 GotoPos(0, STATLINE
);
2014 SetRendition(&mchar_so
);
2017 if (D_status_len
< max
)
2019 /* Wayne Davison: add extra space for readability */
2021 SetRendition(&mchar_null
);
2023 if (D_status_len
< max
)
2035 D_status
= STATUS_ON_HS
;
2039 D_status_obufpos
= D_obufp
- D_obuf
;
2040 ASSERT(D_status_obufpos
> 0);
2042 if (D_status
== STATUS_ON_WIN
)
2044 struct display
*olddisplay
= display
;
2045 struct layer
*oldflayer
= flayer
;
2047 /* this is copied over from RemoveStatus() */
2049 GotoPos(0, STATLINE
);
2050 RefreshLine(STATLINE
, 0, D_status_len
- 1, 0);
2051 GotoPos(D_status_lastx
, D_status_lasty
);
2052 flayer
= D_forecv
? D_forecv
->c_layer
: 0;
2055 display
= olddisplay
;
2057 D_status
= STATUS_ON_WIN
;
2064 struct display
*olddisplay
;
2065 struct layer
*oldflayer
;
2070 if (!(where
= D_status
))
2073 debug("RemoveStatus\n");
2074 if (D_status_obuffree
>= 0)
2076 D_obuflen
= D_status_obuflen
;
2077 D_obuffree
= D_status_obuffree
;
2078 D_status_obuffree
= -1;
2081 D_status_obufpos
= 0;
2084 olddisplay
= display
;
2086 if (where
== STATUS_ON_WIN
)
2088 if (captionalways
|| (D_canvas
.c_slperp
&& D_canvas
.c_slperp
->c_slnext
))
2090 GotoPos(0, STATLINE
);
2091 RefreshLine(STATLINE
, 0, D_status_len
- 1, 0);
2092 GotoPos(D_status_lastx
, D_status_lasty
);
2097 flayer
= D_forecv
? D_forecv
->c_layer
: 0;
2100 display
= olddisplay
;
2104 /* Remove the status but make sure that it is seen for MsgMinWait ms */
2106 RemoveStatusMinWait()
2108 /* XXX: should flush output first if D_status_obufpos is set */
2109 if (!D_status_bell
&& !D_status_obufpos
)
2113 gettimeofday(&now
, NULL
);
2114 ti
= (now
.tv_sec
- D_status_time
.tv_sec
) * 1000 + (now
.tv_usec
- D_status_time
.tv_usec
) / 1000;
2115 if (ti
< MsgMinWait
)
2116 DisplaySleep1000(MsgMinWait
- ti
, 0);
2123 strlen_onscreen(unsigned char *c
, unsigned char *end
)
2127 while (*c
&& (!end
|| c
< end
))
2132 v
= FromUtf8(*c
++, &dec
);
2136 while (v
< 0 && (!end
|| c
< end
));
2137 if (!utf8_iscomb(v
))
2139 if (utf8_isdouble(v
))
2149 PrePutWinMsg(s
, start
, max
)
2153 /* Avoid double-encoding problem for a UTF-8 message on a UTF-8 locale.
2154 Ideally, this would not be necessary. But fixing it the Right Way will
2155 probably take way more time. So this will have to do for now. */
2156 if (D_encoding
== UTF8
)
2158 int chars
= strlen_onscreen(s
+ start
, s
+ max
);
2160 PutWinMsg(s
, start
, max
);
2162 D_x
-= (max
- chars
); /* Yak! But this is necessary to count for
2163 the fact that not every byte represents a
2165 return start
+ chars
;
2169 PutWinMsg(s
, start
, max
);
2175 PrePutWinMsg(s
, start
, max
)
2179 PutWinMsg(s
, start
, max
);
2184 /* refresh the display's hstatus line */
2191 if (D_status
== STATUS_ON_WIN
&& D_has_hstatus
== HSTATUS_LASTLINE
&& STATLINE
== D_height
-1)
2192 return; /* sorry, in use */
2196 if (D_HS
&& D_has_hstatus
== HSTATUS_HS
)
2198 if (!D_hstatus
&& (str
== 0 || *str
== 0))
2200 debug("ShowHStatus: using HS\n");
2201 SetRendition(&mchar_null
);
2206 if (str
== 0 || *str
== 0)
2209 max
= D_WS
> 0 ? D_WS
: (D_width
- !D_CLP
);
2210 if ((int)strlen(str
) > max
)
2217 else if (D_has_hstatus
== HSTATUS_LASTLINE
)
2219 debug("ShowHStatus: using last line\n");
2222 str
= str
? str
: "";
2226 GotoPos(0, D_height
- 1);
2227 SetRendition(captionalways
|| D_cvlist
== 0 || D_cvlist
->c_next
? &mchar_null
: &mchar_so
);
2228 l
= PrePutWinMsg(str
, 0, l
);
2229 if (!captionalways
&& D_cvlist
&& !D_cvlist
->c_next
)
2230 while (l
++ < D_width
)
2233 ClearArea(l
, D_height
- 1, l
, D_width
- 1, D_width
- 1, D_height
- 1, 0, 0);
2234 if (ox
!= -1 && oy
!= -1)
2236 D_hstatus
= *str
? 1 : 0;
2237 SetRendition(&mchar_null
);
2239 else if (str
&& *str
&& D_has_hstatus
== HSTATUS_MESSAGE
)
2241 debug("ShowHStatus: using message\n");
2248 * Refreshes the harstatus of the fore window. Shouldn't be here...
2255 evdeq(&D_hstatusev
);
2256 if (D_status
== STATUS_ON_HS
)
2258 buf
= MakeWinMsgEv(hstatusstring
, D_fore
, '%', (D_HS
&& D_has_hstatus
== HSTATUS_HS
&& D_WS
> 0) ? D_WS
: D_width
- !D_CLP
, &D_hstatusev
, 0);
2262 if (D_has_hstatus
!= HSTATUS_IGNORE
&& D_hstatusev
.timeout
.tv_sec
)
2263 evenq(&D_hstatusev
);
2266 ShowHStatus((char *)0);
2269 /*********************************************************************/
2271 * Here come the routines that refresh an arbitrary part of the screen.
2281 debug("Signalling full refresh!\n");
2282 for (cv
= D_cvlist
; cv
; cv
= cv
->c_next
)
2284 CV_CALL(cv
, LayRedisplayLine(-1, -1, -1, isblank
));
2285 display
= cv
->c_display
; /* just in case! */
2287 RefreshArea(0, 0, D_width
- 1, D_height
- 1, isblank
);
2291 RefreshArea(xs
, ys
, xe
, ye
, isblank
)
2292 int xs
, ys
, xe
, ye
, isblank
;
2296 debug2("Refresh Area: %d,%d", xs
, ys
);
2297 debug3(" - %d,%d (isblank=%d)\n", xe
, ye
, isblank
);
2298 if (!isblank
&& xs
== 0 && xe
== D_width
- 1 && ye
== D_height
- 1 && (ys
== 0 || D_CD
))
2300 ClearArea(xs
, ys
, xs
, xe
, xe
, ye
, 0, 0);
2303 for (y
= ys
; y
<= ye
; y
++)
2304 RefreshLine(y
, xs
, xe
, isblank
);
2308 RefreshLine(y
, from
, to
, isblank
)
2309 int y
, from
, to
, isblank
;
2311 struct viewport
*vp
, *lvp
;
2312 struct canvas
*cv
, *lcv
, *cvlist
, *cvlnext
;
2313 struct layer
*oldflayer
;
2320 debug2("RefreshLine %d %d", y
, from
);
2321 debug2(" %d %d\n", to
, isblank
);
2323 if (D_status
== STATUS_ON_WIN
&& y
== STATLINE
)
2325 if (to
>= D_status_len
)
2326 D_status_len
= to
+ 1;
2327 return; /* can't refresh status */
2330 if (isblank
== 0 && D_CE
&& to
== D_width
- 1 && from
< to
&& D_status
!= STATUS_ON_HS
)
2334 SetRendition(&mchar_null
);
2339 if (y
== D_height
- 1 && D_has_hstatus
== HSTATUS_LASTLINE
)
2349 for (cv
= display
->d_cvlist
; cv
; cv
= cv
->c_next
)
2351 if (y
== cv
->c_ye
+ 1 && from
>= cv
->c_xs
&& from
<= cv
->c_xe
)
2353 p
= Layer2Window(cv
->c_layer
);
2354 buf
= MakeWinMsgEv(captionstring
, p
, '%', cv
->c_xe
- cv
->c_xs
+ (cv
->c_xe
+ 1 < D_width
|| D_CLP
), &cv
->c_captev
, 0);
2355 if (cv
->c_captev
.timeout
.tv_sec
)
2356 evenq(&cv
->c_captev
);
2357 xx
= to
> cv
->c_xe
? cv
->c_xe
: to
;
2360 SetRendition(&mchar_so
);
2361 if (l
> xx
- cv
->c_xs
+ 1)
2362 l
= xx
- cv
->c_xs
+ 1;
2363 l
= PrePutWinMsg(buf
, from
- cv
->c_xs
, l
);
2364 from
= cv
->c_xs
+ l
;
2365 for (; from
<= xx
; from
++)
2369 if (from
== cv
->c_xe
+ 1 && y
>= cv
->c_ys
&& y
<= cv
->c_ye
+ 1)
2372 SetRendition(&mchar_so
);
2377 if (y
< cv
->c_ys
|| y
> cv
->c_ye
|| to
< cv
->c_xs
|| from
> cv
->c_xe
)
2379 debug2("- canvas hit: %d %d", cv
->c_xs
, cv
->c_ys
);
2380 debug2(" %d %d\n", cv
->c_xe
, cv
->c_ye
);
2381 for (vp
= cv
->c_vplist
; vp
; vp
= vp
->v_next
)
2383 debug2(" - vp: %d %d", vp
->v_xs
, vp
->v_ys
);
2384 debug2(" %d %d\n", vp
->v_xe
, vp
->v_ye
);
2385 /* find leftmost overlapping vp */
2386 if (y
>= vp
->v_ys
&& y
<= vp
->v_ye
&& from
<= vp
->v_xe
&& to
>= vp
->v_xs
&& (lvp
== 0 || lvp
->v_xs
> vp
->v_xs
))
2394 continue; /* we advanced from */
2397 if (from
< lvp
->v_xs
)
2400 DisplayLine(&mline_null
, &mline_blank
, y
, from
, lvp
->v_xs
- 1);
2404 /* call LayRedisplayLine on canvas lcv viewport lvp */
2405 yy
= y
- lvp
->v_yoff
;
2406 xx
= to
< lvp
->v_xe
? to
: lvp
->v_xe
;
2408 if (lcv
->c_layer
&& lcv
->c_xoff
+ lcv
->c_layer
->l_width
== from
)
2411 SetRendition(&mchar_blank
);
2415 if (lcv
->c_layer
&& yy
== lcv
->c_layer
->l_height
)
2418 SetRendition(&mchar_blank
);
2419 while (from
<= lvp
->v_xe
&& from
- lvp
->v_xoff
< lcv
->c_layer
->l_width
)
2424 if (from
>= lvp
->v_xe
+ 1)
2427 if (lcv
->c_layer
== 0 || yy
>= lcv
->c_layer
->l_height
|| from
- lvp
->v_xoff
>= lcv
->c_layer
->l_width
)
2430 DisplayLine(&mline_null
, &mline_blank
, y
, from
, lvp
->v_xe
);
2431 from
= lvp
->v_xe
+ 1;
2435 if (xx
- lvp
->v_xoff
>= lcv
->c_layer
->l_width
)
2436 xx
= lcv
->c_layer
->l_width
+ lvp
->v_xoff
- 1;
2438 flayer
= lcv
->c_layer
;
2439 cvlist
= flayer
->l_cvlist
;
2440 cvlnext
= lcv
->c_lnext
;
2441 flayer
->l_cvlist
= lcv
;
2443 LayRedisplayLine(yy
, from
- lvp
->v_xoff
, xx
- lvp
->v_xoff
, isblank
);
2444 flayer
->l_cvlist
= cvlist
;
2445 lcv
->c_lnext
= cvlnext
;
2450 if (!isblank
&& from
<= to
)
2451 DisplayLine(&mline_null
, &mline_blank
, y
, from
, to
);
2454 /*********************************************************************/
2456 /* clear lp_missing by writing the char on the screen. The
2457 * position must be safe.
2463 struct mchar oldrend
;
2466 ASSERT(D_lp_missing
);
2468 debug2("WriteLP(%d,%d)\n", x2
, y2
);
2475 D_lpchar
= mchar_blank
;
2478 /* Can't use PutChar */
2480 SetRendition(&D_lpchar
);
2481 PUTCHAR(D_lpchar
.image
);
2484 PUTCHAR(D_lpchar
.mbcs
);
2487 SetRendition(&oldrend
);
2491 ClearLine(oml
, y
, from
, to
, bce
)
2493 int from
, to
, y
, bce
;
2497 struct mchar bcechar
;
2500 debug3("ClearLine %d,%d-%d\n", y
, from
, to
);
2501 if (D_UT
) /* Safe to erase ? */
2502 SetRendition(&mchar_null
);
2507 if (from
== 0 && D_CB
&& (to
!= D_width
- 1 || (D_x
== to
&& D_y
== y
)) && (!bce
|| D_BE
))
2513 if (to
== D_width
- 1 && D_CE
&& (!bce
|| D_BE
))
2524 DisplayLine(oml
, &mline_blank
, y
, from
, to
);
2527 bcechar
= mchar_null
;
2528 rend_setbg(&bcechar
, bce
);
2529 for (x
= from
; x
<= to
; x
++)
2530 copy_mchar2mline(&bcechar
, &mline_old
, x
);
2531 DisplayLine(oml
, &mline_old
, y
, from
, to
);
2533 DisplayLine(oml
, &mline_blank
, y
, from
, to
);
2538 DisplayLine(oml
, ml
, y
, from
, to
)
2539 struct mline
*oml
, *ml
;
2543 int last2flag
= 0, delete_lp
= 0;
2546 ASSERT(y
>= 0 && y
< D_height
);
2547 ASSERT(from
>= 0 && from
< D_width
);
2548 ASSERT(to
>= 0 && to
< D_width
);
2549 if (!D_CLP
&& y
== D_bot
&& to
== D_width
- 1)
2551 if (D_lp_missing
|| !cmp_mline(oml
, ml
, to
))
2554 if ((D_IC
|| D_IM
) && from
< to
&& !dw_left(ml
, to
, D_encoding
))
2556 if ((D_IC
|| D_IM
) && from
< to
)
2565 delete_lp
= !cmp_mchar_mline(&mchar_blank
, oml
, to
) && (D_CE
|| D_DC
|| D_CDC
);
2566 D_lp_missing
= !cmp_mchar_mline(&mchar_blank
, ml
, to
);
2567 copy_mline2mchar(&D_lpchar
, ml
, to
);
2575 /* finish dw-char (can happen after a wrap) */
2576 debug("DisplayLine finishing kanji\n");
2577 SetRenditionMline(ml
, from
);
2578 PUTCHAR(ml
->image
[from
]);
2582 for (x
= from
; x
<= to
; x
++)
2584 #if 0 /* no longer needed */
2585 if (x
|| D_x
!= D_width
|| D_y
!= y
- 1)
2588 if (x
< to
|| x
!= D_width
- 1 || ml
->image
[x
+ 1])
2589 if (cmp_mline(oml
, ml
, x
))
2594 if (dw_right(ml
, x
, D_encoding
))
2597 debug1("DisplayLine on right side of dw char- x now %d\n", x
);
2600 if (x
== to
&& dw_left(ml
, x
, D_encoding
))
2601 break; /* don't start new kanji */
2603 SetRenditionMline(ml
, x
);
2604 PUTCHAR(ml
->image
[x
]);
2606 if (dw_left(ml
, x
, D_encoding
))
2607 PUTCHAR(ml
->image
[++x
]);
2610 #if 0 /* not needed any longer */
2611 /* compare != 0 because ' ' can happen when clipping occures */
2612 if (to
== D_width
- 1 && y
< D_height
- 1 && D_x
== D_width
&& ml
->image
[to
+ 1])
2618 SetRenditionMline(ml
, x
+ 1);
2619 PUTCHAR(ml
->image
[x
+ 1]);
2621 SetRenditionMline(ml
, x
);
2622 INSERTCHAR(ml
->image
[x
]);
2627 SetRendition(&mchar_null
);
2644 PUTCHARLP(c
->image
);
2649 if (D_encoding
== UTF8
)
2658 InsChar(c
, x
, xe
, y
, oml
)
2664 if (y
== D_bot
&& !D_CLP
)
2666 if (x
== D_width
- 1)
2672 if (xe
== D_width
- 1)
2678 PUTCHARLP(c
->image
);
2681 if (!(D_IC
|| D_CIC
|| D_IM
) || xe
!= D_width
- 1)
2683 RefreshLine(y
, x
, xe
, 0);
2685 /* UpdateLine(oml, y, x, xe); */
2692 if (c
->mbcs
&& D_IC
)
2697 AddCStr2(D_CIC
, c
->mbcs
? 2 : 1);
2706 RAW_PUTCHAR(c
->image
);
2711 if (D_encoding
== UTF8
)
2714 if (D_x
== D_width
- 1)
2717 RAW_PUTCHAR(c
->mbcs
);
2723 WrapChar(c
, x
, y
, xs
, ys
, xe
, ye
, ins
)
2732 bce
= rend_getbg(c
);
2737 debug2(" x %d y %d", x
, y
);
2738 debug2(" Dx %d Dy %d", D_x
, D_y
);
2739 debug2(" xs %d ys %d", xs
, ys
);
2740 debug3(" xe %d ye %d ins %d\n", xe
, ye
, ins
);
2741 if (xs
!= 0 || x
!= D_width
|| !D_AM
)
2744 ScrollV(xs
, ys
, xe
, ye
, 1, bce
);
2745 else if (y
< D_height
- 1)
2748 InsChar(c
, xs
, xe
, y
, 0);
2753 if (y
== ye
) /* we have to scroll */
2755 debug("- scrolling\n");
2756 ChangeScrollRegion(ys
, ye
);
2757 if (D_bot
!= y
|| D_x
!= D_width
|| (!bce
&& !D_BE
))
2759 debug("- have to call ScrollV\n");
2760 ScrollV(xs
, ys
, xe
, ye
, 1, bce
);
2764 else if (y
== D_bot
) /* remove unusable region? */
2765 ChangeScrollRegion(0, D_height
- 1);
2766 if (D_x
!= D_width
|| D_y
!= y
)
2768 if (D_CLP
&& y
>= 0) /* don't even try if !LP */
2769 RefreshLine(y
, D_width
- 1, D_width
- 1, 0);
2770 debug2("- refresh last char -> x,y now %d,%d\n", D_x
, D_y
);
2771 if (D_x
!= D_width
|| D_y
!= y
) /* sorry, no bonus */
2774 ScrollV(xs
, ys
, xe
, ye
, 1, bce
);
2775 GotoPos(xs
, y
== ye
|| y
== D_height
- 1 ? y
: y
+ 1);
2778 debug("- writeing new char");
2779 if (y
!= ye
&& y
< D_height
- 1)
2781 if (ins
!= D_insert
)
2783 if (ins
&& !D_insert
)
2785 InsChar(c
, 0, xe
, y
, 0);
2786 debug2(" -> done with insert (%d,%d)\n", D_x
, D_y
);
2792 RAW_PUTCHAR(c
->image
);
2797 if (D_encoding
== UTF8
)
2800 RAW_PUTCHAR(c
->mbcs
);
2803 debug2(" -> done (%d,%d)\n", D_x
, D_y
);
2807 ResizeDisplay(wi
, he
)
2811 debug2("ResizeDisplay: to (%d,%d).\n", wi
, he
);
2812 if (D_width
== wi
&& D_height
== he
)
2814 debug("ResizeDisplay: No change\n");
2817 if (D_width
!= wi
&& (D_height
== he
|| !D_CWS
) && D_CZ0
&& (wi
== Z0width
|| wi
== Z1width
))
2819 debug("ResizeDisplay: using Z0/Z1\n");
2820 AddCStr(wi
== Z0width
? D_CZ0
: D_CZ1
);
2821 ChangeScreenSize(wi
, D_height
, 0);
2822 return (he
== D_height
) ? 0 : -1;
2826 debug("ResizeDisplay: using WS\n");
2827 AddCStr(tgoto(D_CWS
, wi
, he
));
2828 ChangeScreenSize(wi
, he
, 0);
2835 ChangeScrollRegion(newtop
, newbot
)
2840 if (newtop
== newbot
)
2841 return; /* xterm etc can't do it */
2845 newbot
= D_height
- 1;
2849 D_bot
= D_height
- 1;
2852 if (D_top
== newtop
&& D_bot
== newbot
)
2854 debug2("ChangeScrollRegion: (%d - %d)\n", newtop
, newbot
);
2855 AddCStr(tgoto(D_CS
, newbot
, newtop
));
2858 D_y
= D_x
= -1; /* Just in case... */
2862 #define WT_FLAG "2" /* change to "0" to set both title and icon */
2869 static char *oscs
[][2] = {
2870 { WT_FLAG
";", "screen" }, /* set window title */
2871 { "20;", "" }, /* background */
2872 { "39;", "black" }, /* default foreground (black?) */
2873 { "49;", "white" } /* default background (white?) */
2881 if (!D_xtermosc
[i
] && !*s
)
2883 if (i
== 0 && !D_xtermosc
[0])
2884 AddStr("\033[22;" WT_FLAG
"t"); /* stack titles (xterm patch #251) */
2898 for (i
= 3; i
>= 0; i
--)
2901 AddStr("\033[23;" WT_FLAG
"t"); /* unstack titles (xterm patch #251) */
2907 * Output buffering routines
2919 if (D_encoding
== UTF8
)
2921 while ((c
= *str
++))
2922 AddUtf8((unsigned char)c
);
2926 while ((c
= *str
++))
2939 if (D_encoding
== UTF8
)
2941 while ((c
= *str
++) && n
-- > 0)
2942 AddUtf8((unsigned char)c
);
2946 while ((c
= *str
++) && n
-- > 0)
2961 l
= D_obufp
- D_obuf
;
2962 debug1("Flush(): %d\n", l
);
2965 ASSERT(l
+ D_obuffree
== D_obuflen
);
2975 if (fcntl(D_userfd
, F_SETFL
, 0))
2976 debug1("Warning: BLOCK fcntl failed: %d\n", errno
);
2984 FD_SET(D_userfd
, &w
);
2986 t
.tv_sec
= progress
;
2988 wr
= select(FD_SETSIZE
, (fd_set
*)0, &w
, (fd_set
*)0, &t
);
2993 debug1("Warning: select failed: %d\n", errno
);
2998 /* no progress after 3 seconds. sorry. */
2999 debug1("Warning: no progress after %d seconds\n", progress
);
3003 wr
= write(D_userfd
, p
, l
);
3008 debug1("Writing to display: %d\n", errno
);
3016 debug1("Warning: Flush could not write %d bytes\n", l
);
3021 if (fcntl(D_userfd
, F_SETFL
, FNBLOCK
))
3022 debug1("Warning: NBLOCK fcntl failed: %d\n", errno
);
3034 debug1("did freetty %d\n", D_userfd
);
3042 D_obuflenmax
= -D_obufmax
;
3048 * Asynchronous output routines by
3049 * Tim MacKenzie (tym@dibbler.cs.monash.edu.au)
3058 if (D_status_obuffree
>= 0)
3060 ASSERT(D_obuffree
== -1);
3061 RemoveStatusMinWait();
3062 if (--D_obuffree
> 0) /* redo AddChar decrement */
3065 if (D_obuflen
&& D_obuf
)
3067 ind
= D_obufp
- D_obuf
;
3069 D_obuffree
+= GRAIN
;
3070 D_obuf
= realloc(D_obuf
, D_obuflen
);
3077 D_obuf
= malloc(D_obuflen
);
3080 Panic(0, "Out of memory");
3081 D_obufp
= D_obuf
+ ind
;
3082 D_obuflenmax
= D_obuflen
- D_obufmax
;
3083 debug1("ResizeObuf: resized to %d\n", D_obuflen
);
3087 DisplaySleep1000(n
, eat
)
3099 debug("DisplaySleep has no display sigh\n");
3103 t
.tv_usec
= (n
% 1000) * 1000;
3104 t
.tv_sec
= n
/ 1000;
3106 FD_SET(D_userfd
, &r
);
3107 if (select(FD_SETSIZE
, &r
, (fd_set
*)0, (fd_set
*)0, &t
) > 0)
3109 debug("display activity stopped sleep\n");
3111 read(D_userfd
, &buf
, 1);
3113 debug2("DisplaySleep(%d) ending, eat was %d\n", n
, eat
);
3119 {/* Nuke pending output in current display, clear screen */
3121 int oldtop
= D_top
, oldbot
= D_bot
;
3122 struct mchar oldrend
;
3123 int oldkeypad
= D_keypad
, oldcursorkeys
= D_cursorkeys
;
3124 int oldcurvis
= D_curvis
;
3125 int oldmouse
= D_mouse
;
3128 len
= D_obufp
- D_obuf
;
3129 debug1("NukePending: nuking %d chars\n", len
);
3131 /* Throw away any output that we can... */
3133 tcflush(D_userfd
, TCOFLUSH
);
3136 (void) ioctl(D_userfd
, TCFLSH
, (char *) 1);
3145 /* Turn off all attributes. (Tim MacKenzie) */
3152 AddStr("\033[m"); /* why is D_ME not set? */
3157 /* Check for toggle */
3158 if (D_IM
&& strcmp(D_IM
, D_EI
))
3161 /* Check for toggle */
3163 if (D_KS
&& strcmp(D_KS
, D_KE
))
3165 if (D_CCS
&& strcmp(D_CCS
, D_CCE
))
3168 if (D_KS
&& strcmp(D_KS
, D_KE
))
3171 if (D_CCS
&& strcmp(D_CCS
, D_CCE
))
3176 D_rend
= mchar_null
;
3182 ChangeScrollRegion(oldtop
, oldbot
);
3183 SetRendition(&oldrend
);
3184 KeypadMode(oldkeypad
);
3185 CursorkeysMode(oldcursorkeys
);
3186 CursorVisibility(oldcurvis
);
3187 MouseMode(oldmouse
);
3190 debug("ResizeDisplay: using WS\n");
3191 AddCStr(tgoto(D_CWS
, D_width
, D_height
));
3193 else if (D_CZ0
&& (D_width
== Z0width
|| D_width
== Z1width
))
3195 debug("ResizeDisplay: using Z0/Z1\n");
3196 AddCStr(D_width
== Z0width
? D_CZ0
: D_CZ1
);
3199 #endif /* AUTO_NUKE */
3202 /* linux' select can't handle flow control, so wait 100ms if
3206 disp_writeev_eagain(ev
, data
)
3210 display
= (struct display
*)data
;
3212 D_writeev
.type
= EV_WRITE
;
3213 D_writeev
.handler
= disp_writeev_fn
;
3219 disp_writeev_fn(ev
, data
)
3223 int len
, size
= OUTPUT_BLOCK_SIZE
;
3225 display
= (struct display
*)data
;
3226 len
= D_obufp
- D_obuf
;
3229 if (D_status_obufpos
&& size
> D_status_obufpos
)
3230 size
= D_status_obufpos
;
3232 size
= write(D_userfd
, D_obuf
, size
);
3238 bcopy(D_obuf
+ size
, D_obuf
, len
);
3239 debug2("ASYNC: wrote %d - remaining %d\n", size
, len
);
3243 if (D_status_obufpos
)
3245 D_status_obufpos
-= size
;
3246 if (!D_status_obufpos
)
3248 debug("finished writing the status message\n");
3249 /* we're finished displaying the message! */
3250 if (D_status
== STATUS_ON_WIN
)
3252 /* setup continue trigger */
3253 D_status_obuflen
= D_obuflen
;
3254 D_status_obuffree
= D_obuffree
;
3255 /* setting obbuffree to 0 will make AddChar call
3257 D_obuffree
= D_obuflen
= 0;
3259 gettimeofday(&D_status_time
, NULL
);
3260 SetTimeout(&D_statusev
, MsgWait
);
3263 RefreshBraille(); /* let user see multiple Msg()s */
3269 D_blocked_fuzz
-= size
;
3270 if (D_blocked_fuzz
< 0)
3273 if (D_blockedev
.queued
)
3275 if (D_obufp
- D_obuf
> D_obufmax
/ 2)
3277 debug2("%s: resetting timeout to %g secs\n", D_usertty
, D_nonblock
/1000.);
3278 SetTimeout(&D_blockedev
, D_nonblock
);
3282 debug1("%s: deleting blocked timeout\n", D_usertty
);
3283 evdeq(&D_blockedev
);
3286 if (D_blocked
== 1 && D_obuf
== D_obufp
)
3288 /* empty again, restart output */
3289 debug1("%s: buffer empty, unblocking\n", D_usertty
);
3291 Activate(D_fore
? D_fore
->w_norefresh
: 0);
3292 D_blocked_fuzz
= D_obufp
- D_obuf
;
3298 /* linux flow control is badly broken */
3299 if (errno
== EAGAIN
)
3302 D_writeev
.type
= EV_TIMEOUT
;
3303 D_writeev
.handler
= disp_writeev_eagain
;
3304 SetTimeout(&D_writeev
, 100);
3308 if (errno
!= EINTR
&& errno
!= EAGAIN
)
3309 #if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
3310 if (errno
!= EWOULDBLOCK
)
3312 Msg(errno
, "Error writing output to display");
3317 disp_readev_fn(ev
, data
)
3325 display
= (struct display
*)data
;
3327 /* Hmmmm... a bit ugly... */
3329 for (cv
= D_forecv
->c_layer
->l_cvlist
; cv
; cv
= cv
->c_lnext
)
3331 display
= cv
->c_display
;
3332 if (D_status
== STATUS_ON_WIN
)
3336 display
= (struct display
*)data
;
3343 size
= sizeof(D_fore
->w_pwin
->p_inbuf
) - D_fore
->w_pwin
->p_inlen
;
3346 size
= sizeof(D_fore
->w_inbuf
) - D_fore
->w_inlen
;
3352 size
= 1; /* Always allow one char for command keys */
3354 size
= read(D_userfd
, buf
, size
);
3357 if (errno
== EINTR
|| errno
== EAGAIN
)
3359 #if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
3360 if (errno
== EWOULDBLOCK
)
3363 debug1("Read error: %d - hangup!\n", errno
);
3370 debug("Found EOF - hangup!\n");
3381 Activate(D_fore
? D_fore
->w_norefresh
: 0);
3386 if (D_blocked
> 1) /* 2, 3 */
3392 for (p
= windows
; p
; p
= p
->w_next
)
3393 if (p
->w_zdisplay
== display
)
3395 flayer
= &p
->w_layer
;
3398 LayProcess(&bufp
, &size
);
3401 debug("zmodem window gone, deblocking display");
3402 zmodem_abort(0, display
);
3408 D_fore
->w_lastdisp
= display
;
3409 if (D_mouse
&& D_forecv
)
3411 unsigned char *bp
= (unsigned char *)buf
;
3414 /* XXX this assumes that the string is read in as a whole... */
3415 for (i
= size
; i
> 0; i
--, bp
++)
3417 if (i
> 5 && bp
[0] == 033 && bp
[1] == '[' && bp
[2] == 'M')
3422 else if (i
< 5 || bp
[0] != 0233 || bp
[1] != 'M')
3426 if (x
>= D_forecv
->c_xs
&& x
<= D_forecv
->c_xe
&& y
>= D_forecv
->c_ys
&& y
<= D_forecv
->c_ye
)
3428 if ((D_fore
&& D_fore
->w_mouse
) || (D_mousetrack
&& D_forecv
->c_layer
->l_mode
== 1))
3430 /* Send clicks only if the window is expecting clicks */
3431 x
-= D_forecv
->c_xoff
;
3432 y
-= D_forecv
->c_yoff
;
3433 if (x
>= 0 && x
< D_forecv
->c_layer
->l_width
&& y
>= 0 && y
< D_forecv
->c_layer
->l_height
)
3443 else if (D_mousetrack
&& bp
[2] == '#')
3445 /* 'focus' to the clicked region, only on mouse up */
3446 struct canvas
*cv
= FindCanvas(x
, y
);
3449 SetForeCanvas(display
, cv
);
3450 /* XXX: Do we want to reset the input buffer? */
3455 bcopy((char *)bp
+ 1, (char *)bp
, i
);
3460 bcopy((char *)bp
+ 5, (char *)bp
, i
- 5);
3467 if (D_encoding
!= (D_forecv
? D_forecv
->c_layer
->l_encoding
: 0))
3470 char buf2
[IOSIZE
* 2 + 10];
3471 enc
= D_forecv
? D_forecv
->c_layer
->l_encoding
: 0;
3472 for (i
= j
= 0; i
< size
; i
++)
3474 c
= ((unsigned char *)buf
)[i
];
3475 c
= DecodeChar(c
, D_encoding
, &D_decodestate
);
3477 i
--; /* try char again */
3483 j
+= EncodeChar(buf2
+ j
, c
, enc
, &font
);
3484 j
+= EncodeChar(buf2
+ j
, -1, enc
, &font
);
3487 j
+= EncodeChar(buf2
+ j
, c
, enc
, 0);
3488 if (j
> (int)sizeof(buf2
) - 10) /* just in case... */
3491 (*D_processinput
)(buf2
, j
);
3495 (*D_processinput
)(buf
, size
);
3499 disp_status_fn(ev
, data
)
3503 display
= (struct display
*)data
;
3504 debug1("disp_status_fn for display %x\n", (int)display
);
3510 disp_hstatus_fn(ev
, data
)
3514 display
= (struct display
*)data
;
3515 if (D_status
== STATUS_ON_HS
)
3525 disp_blocked_fn(ev
, data
)
3531 display
= (struct display
*)data
;
3532 debug1("blocked timeout %s\n", D_usertty
);
3533 if (D_obufp
- D_obuf
> D_obufmax
+ D_blocked_fuzz
)
3535 debug("stopping output to display\n");
3537 /* re-enable all windows */
3538 for (p
= windows
; p
; p
= p
->w_next
)
3539 if (p
->w_readev
.condneg
== &D_obuflenmax
)
3541 debug1("freeing window #%d\n", p
->w_number
);
3542 p
->w_readev
.condpos
= p
->w_readev
.condneg
= 0;
3549 disp_map_fn(ev
, data
)
3556 display
= (struct display
*)data
;
3557 debug("Flushing map sequence\n");
3560 p
= (char *)D_seqp
- l
;
3561 D_seqp
= D_kmaps
+ 3;
3563 if ((q
= D_seqh
) != 0)
3566 i
= q
[0] << 8 | q
[1];
3567 i
&= ~KMAP_NOTIMEOUT
;
3568 debug1("Mapping former hit #%d - ", i
);
3569 debug2("%d(%s) - ", q
[2], q
+ 3);
3571 ProcessInput2((char *)q
+ 3, q
[2]);
3584 disp_idle_fn(ev
, data
)
3588 struct display
*olddisplay
;
3589 display
= (struct display
*)data
;
3590 debug("idle timeout\n");
3591 if (idletimo
<= 0 || idleaction
.nr
== RC_ILLEGAL
)
3593 olddisplay
= display
;
3594 flayer
= D_forecv
->c_layer
;
3596 DoAction(&idleaction
, -1);
3597 if (idleaction
.nr
== RC_BLANKER
)
3599 for (display
= displays
; display
; display
= display
->d_next
)
3600 if (olddisplay
== display
)
3611 SetTimeout(&D_idleev
, idletimo
);
3612 if (!D_idleev
.queued
)
3623 disp_blanker_fn(ev
, data
)
3627 char buf
[IOSIZE
], *b
;
3630 display
= (struct display
*)data
;
3631 size
= read(D_blankerev
.fd
, buf
, IOSIZE
);
3634 evdeq(&D_blankerev
);
3635 close(D_blankerev
.fd
);
3636 D_blankerev
.fd
= -1;
3639 for (b
= buf
; size
; size
--)
3646 int oldtop
= D_top
, oldbot
= D_bot
;
3647 struct mchar oldrend
;
3649 if (D_blankerev
.fd
== -1)
3653 evdeq(&D_blankerev
);
3654 close(D_blankerev
.fd
);
3655 D_blankerev
.fd
= -1;
3656 Kill(D_blankerpid
, SIGHUP
);
3668 AddStr("\033[m\033[m"); /* why is D_ME not set? */
3675 D_rend
= mchar_null
;
3679 ChangeScrollRegion(oldtop
, oldbot
);
3680 SetRendition(&oldrend
);
3693 char libuf
[20], cobuf
[20];
3697 strcpy(termname
, "TERM=");
3698 strncpy(termname
+ 5, D_termname
, sizeof(termname
) - 6);
3699 termname
[sizeof(termname
) - 1] = 0;
3702 if ((D_blankerev
.fd
= OpenPTY(&m
)) == -1)
3704 Msg(0, "OpenPty failed");
3710 if ((slave
= open(m
, O_RDWR
|O_NOCTTY
)) == -1)
3712 Msg(errno
, "%s", m
);
3713 close(D_blankerev
.fd
);
3714 D_blankerev
.fd
= -1;
3719 switch (pid
= (int)fork())
3723 close(D_blankerev
.fd
);
3724 D_blankerev
.fd
= -1;
3729 if (dfp
&& dfp
!= stderr
)
3735 if (setgid(real_gid
) || setuid(real_uid
))
3736 Panic(errno
, "setuid/setgid");
3742 closeallfiles(slave
);
3743 if (open(m
, O_RDWR
))
3744 Panic(errno
, "Cannot open %s", m
);
3751 SetTTY(0, &D_OldMode
);
3756 glwz
.ws_col
= D_width
;
3757 glwz
.ws_row
= D_height
;
3758 (void)ioctl(0, TIOCSWINSZ
, (char *)&glwz
);
3760 sprintf(libuf
, "LINES=%d", D_height
);
3761 sprintf(cobuf
, "COLUMNS=%d", D_width
);
3766 signal(SIGPIPE
, SIG_DFL
);
3769 execvpe(*cmdv
, cmdv
, NewEnv
+ 3);
3770 Panic(errno
, "%s", *cmdv
);
3775 evenq(&D_blankerev
);
3780 #endif /* BLANKER_PRG */