3 /* This "driver" is designed to go on top of an existing driver
4 to provide support for features only present if using an
5 xterm or compatible program for your console output.
6 Currently, it supports resizing and separating debug messages from
8 It does not currently support changing the title bar.
14 #include <sys/ioctl.h>
24 char console_xterm_prog
[80];
26 static BOOL
wine_create_console(FILE **master
, FILE **slave
, int *pid
);
27 FILE *wine_openpty(int *master
, int *slave
, char *name
,
28 struct termios
*term
, struct winsize
*winsize
);
30 /* The console -- I chose to keep the master and slave
31 * (UNIX) file descriptors around in case they are needed for
32 * ioctls later. The pid is needed to destroy the xterm on close
34 typedef struct _XTERM_CONSOLE
{
35 FILE *master
; /* xterm side of pty */
36 FILE *slave
; /* wine side of pty */
37 int pid
; /* xterm's pid, -1 if no xterm */
40 static XTERM_CONSOLE xterm_console
;
43 FILE *old_in
, *old_out
;
47 /* Here, this is a supplementary driver so we should remember to call
49 chain
.init
= driver
.init
;
50 driver
.init
= XTERM_Init
;
52 chain
.close
= driver
.close
;
53 driver
.close
= XTERM_Close
;
55 chain
.resizeScreen
= driver
.resizeScreen
;
56 driver
.resizeScreen
= XTERM_ResizeScreen
;
58 /* Read in driver configuration */
59 PROFILE_GetWineIniString("console", "XtermProg",
60 "xterm", console_xterm_prog
, 79);
66 wine_create_console(&xterm_console
.master
, &xterm_console
.slave
,
69 old_in
= driver
.console_in
;
70 driver
.console_in
= xterm_console
.slave
;
72 old_out
= driver
.console_out
;
73 driver
.console_out
= xterm_console
.slave
;
75 /* Then call the chain... */
82 /* Call the chain first... */
86 driver
.console_in
= old_in
;
87 driver
.console_out
= old_out
;
89 /* make sure a xterm exists to kill */
90 if (xterm_console
.pid
!= -1) {
91 kill(xterm_console
.pid
, SIGTERM
);
95 void XTERM_ResizeScreen(int x
, int y
)
99 /* Call the chain first, there shoudln't be any... */
100 if (chain
.resizeScreen
)
101 chain
.resizeScreen(x
, y
);
103 sprintf(temp
, "\x1b[8;%d;%dt", y
, x
);
104 CONSOLE_WriteRawString(temp
);
106 CONSOLE_NotifyResizeScreen(x
, y
);
110 static BOOL
wine_create_console(FILE **master
, FILE **slave
, int *pid
)
112 /* There is definately a bug in this routine that causes a lot
113 of garbage to be written to the screen, but I can't find it...
121 char xterm_resolution
[10];
123 sprintf(xterm_resolution
, "%dx%d", driver
.x_res
,
126 if (tcgetattr(0, &term
) < 0) return FALSE
;
127 term
.c_lflag
|= ICANON
;
128 term
.c_lflag
&= ~ECHO
;
129 if (wine_openpty(&tmaster
, &tslave
, NULL
, &term
, NULL
) < 0)
131 *master
= fdopen(tmaster
, "r+");
132 *slave
= fdopen(tslave
, "r+");
134 if ((*pid
=fork()) == 0) {
135 tcsetattr(fileno(*slave
), TCSADRAIN
, &term
);
136 sprintf(buf
, "-Sxx%d", fileno(*master
));
137 execlp(console_xterm_prog
, console_xterm_prog
, buf
, "-fg",
138 "white", "-bg", "black", "-g",
139 xterm_resolution
, NULL
);
140 ERR(console
, "error creating xterm (file not found?)\n");
144 /* most xterms like to print their window ID when used with -S;
145 * read it and continue before the user has a chance...
146 * NOTE: this is the reason we started xterm with ECHO off,
147 * we'll turn it back on below
150 for (i
=0; c
!='\n'; (status
=fread(&c
, 1, 1, *slave
)), i
++) {
151 if (status
== -1 && c
== '\0') {
152 /* wait for xterm to be created */
156 WARN(console
, "can't read xterm WID\n");
161 term
.c_lflag
|= ECHO
;
162 tcsetattr(fileno(*master
), TCSADRAIN
, &term
);