2 * Copyright 1999 - Joseph Pranevich
4 * This "driver" is designed to go on top of an existing driver
5 * to provide support for features only present if using an
6 * xterm or compatible program for your console output.
7 * Currently, it supports resizing and separating debug messages from
9 * It does not currently support changing the title bar.
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
16 * This library 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 GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include "wine/port.h"
32 #include <sys/ioctl.h>
45 #include "wine/debug.h"
47 WINE_DEFAULT_DEBUG_CHANNEL(console);
49 char console_xterm_prog[80];
51 static BOOL wine_create_console(FILE **master, FILE **slave, pid_t *pid);
53 /* The console -- I chose to keep the master and slave
54 * (UNIX) file descriptors around in case they are needed for
55 * ioctls later. The pid is needed to destroy the xterm on close
57 typedef struct _XTERM_CONSOLE {
58 FILE *master; /* xterm side of pty */
59 FILE *slave; /* wine side of pty */
60 pid_t pid; /* xterm's pid, -1 if no xterm */
63 static XTERM_CONSOLE xterm_console;
66 FILE *old_in, *old_out;
68 void XTERM_Start(void)
70 /* Here, this is a supplementary driver so we should remember to call
72 chain.init = driver.init;
73 driver.init = XTERM_Init;
75 chain.close = driver.close;
76 driver.close = XTERM_Close;
78 chain.resizeScreen = driver.resizeScreen;
79 driver.resizeScreen = XTERM_ResizeScreen;
81 /* Read in driver configuration */
82 PROFILE_GetWineIniString("console", "XtermProg",
83 "xterm", console_xterm_prog, 79);
89 wine_create_console(&xterm_console.master, &xterm_console.slave,
92 old_in = driver.console_in;
93 driver.console_in = xterm_console.slave;
95 old_out = driver.console_out;
96 driver.console_out = xterm_console.slave;
98 /* Then call the chain... */
105 /* Call the chain first... */
109 driver.console_in = old_in;
110 driver.console_out = old_out;
112 /* make sure a xterm exists to kill */
113 if (xterm_console.pid != -1) {
114 kill(xterm_console.pid, SIGTERM);
118 void XTERM_ResizeScreen(int x, int y)
122 /* Call the chain first, there shoudln't be any... */
123 if (chain.resizeScreen)
124 chain.resizeScreen(x, y);
126 sprintf(temp, "\x1b[8;%d;%dt", y, x);
127 CONSOLE_WriteRawString(temp);
129 CONSOLE_NotifyResizeScreen(x, y);
133 static BOOL wine_create_console(FILE **master, FILE **slave, pid_t *pid)
135 /* There is definately a bug in this routine that causes a lot
136 of garbage to be written to the screen, but I can't find it...
144 char xterm_resolution[10];
146 sprintf(xterm_resolution, "%dx%d", driver.x_res,
149 if (tcgetattr(0, &term) < 0) return FALSE;
150 term.c_lflag |= ICANON;
151 term.c_lflag &= ~ECHO;
152 if (openpty(&tmaster, &tslave, NULL, &term, NULL) < 0)
154 *master = fdopen(tmaster, "r+");
155 *slave = fdopen(tslave, "r+");
157 if ((*pid=fork()) == 0) {
158 tcsetattr(fileno(*slave), TCSADRAIN, &term);
159 sprintf(buf, "-Sxx%d", fileno(*master));
160 execlp(console_xterm_prog, console_xterm_prog, buf, "-fg",
161 "white", "-bg", "black", "-g",
162 xterm_resolution, NULL);
163 ERR("error creating xterm (file not found?)\n");
167 /* most xterms like to print their window ID when used with -S;
168 * read it and continue before the user has a chance...
169 * NOTE: this is the reason we started xterm with ECHO off,
170 * we'll turn it back on below
173 for (i=0; c!='\n'; (status=fread(&c, 1, 1, *slave)), i++) {
174 if (status == -1 && c == '\0') {
175 /* wait for xterm to be created */
179 WARN("can't read xterm WID\n");
184 term.c_lflag |= ECHO;
185 tcsetattr(fileno(*master), TCSADRAIN, &term);