Added RunInThread callout to winedos.
[wine/multimedia.git] / console / xterm.c
blob4b56418d6118c1e112a3469ddbd9e579ded3d8ac
1 /* xterm.c */
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
7 program output.
8 It does not currently support changing the title bar.
9 */
11 #include "config.h"
13 #include <stdlib.h>
14 #include <stdio.h>
15 #include <signal.h>
16 #include <sys/ioctl.h>
17 #include <fcntl.h>
18 #include <unistd.h>
19 #include <termios.h>
21 #include "console.h"
22 #include "options.h"
23 #include "debugtools.h"
25 DEFAULT_DEBUG_CHANNEL(console);
27 char console_xterm_prog[80];
29 static BOOL wine_create_console(FILE **master, FILE **slave, pid_t *pid);
30 int wine_openpty(int *master, int *slave, char *name,
31 struct termios *term, struct winsize *winsize);
33 /* The console -- I chose to keep the master and slave
34 * (UNIX) file descriptors around in case they are needed for
35 * ioctls later. The pid is needed to destroy the xterm on close
37 typedef struct _XTERM_CONSOLE {
38 FILE *master; /* xterm side of pty */
39 FILE *slave; /* wine side of pty */
40 pid_t pid; /* xterm's pid, -1 if no xterm */
41 } XTERM_CONSOLE;
43 static XTERM_CONSOLE xterm_console;
45 CONSOLE_device chain;
46 FILE *old_in, *old_out;
48 void XTERM_Start(void)
50 /* Here, this is a supplementary driver so we should remember to call
51 the chain. */
52 chain.init = driver.init;
53 driver.init = XTERM_Init;
55 chain.close = driver.close;
56 driver.close = XTERM_Close;
58 chain.resizeScreen = driver.resizeScreen;
59 driver.resizeScreen = XTERM_ResizeScreen;
61 /* Read in driver configuration */
62 PROFILE_GetWineIniString("console", "XtermProg",
63 "xterm", console_xterm_prog, 79);
67 void XTERM_Init()
69 wine_create_console(&xterm_console.master, &xterm_console.slave,
70 &xterm_console.pid);
72 old_in = driver.console_in;
73 driver.console_in = xterm_console.slave;
75 old_out = driver.console_out;
76 driver.console_out = xterm_console.slave;
78 /* Then call the chain... */
79 if (chain.init)
80 chain.init();
83 void XTERM_Close()
85 /* Call the chain first... */
86 if (chain.close)
87 chain.close();
89 driver.console_in = old_in;
90 driver.console_out = old_out;
92 /* make sure a xterm exists to kill */
93 if (xterm_console.pid != -1) {
94 kill(xterm_console.pid, SIGTERM);
98 void XTERM_ResizeScreen(int x, int y)
100 char temp[100];
102 /* Call the chain first, there shoudln't be any... */
103 if (chain.resizeScreen)
104 chain.resizeScreen(x, y);
106 sprintf(temp, "\x1b[8;%d;%dt", y, x);
107 CONSOLE_WriteRawString(temp);
109 CONSOLE_NotifyResizeScreen(x, y);
113 static BOOL wine_create_console(FILE **master, FILE **slave, pid_t *pid)
115 /* There is definately a bug in this routine that causes a lot
116 of garbage to be written to the screen, but I can't find it...
118 struct termios term;
119 char buf[1024];
120 char c = '\0';
121 int status = 0;
122 int i;
123 int tmaster, tslave;
124 char xterm_resolution[10];
126 sprintf(xterm_resolution, "%dx%d", driver.x_res,
127 driver.y_res);
129 if (tcgetattr(0, &term) < 0) return FALSE;
130 term.c_lflag |= ICANON;
131 term.c_lflag &= ~ECHO;
132 if (wine_openpty(&tmaster, &tslave, NULL, &term, NULL) < 0)
133 return FALSE;
134 *master = fdopen(tmaster, "r+");
135 *slave = fdopen(tslave, "r+");
137 if ((*pid=fork()) == 0) {
138 tcsetattr(fileno(*slave), TCSADRAIN, &term);
139 sprintf(buf, "-Sxx%d", fileno(*master));
140 execlp(console_xterm_prog, console_xterm_prog, buf, "-fg",
141 "white", "-bg", "black", "-g",
142 xterm_resolution, NULL);
143 ERR("error creating xterm (file not found?)\n");
144 exit(1);
147 /* most xterms like to print their window ID when used with -S;
148 * read it and continue before the user has a chance...
149 * NOTE: this is the reason we started xterm with ECHO off,
150 * we'll turn it back on below
153 for (i=0; c!='\n'; (status=fread(&c, 1, 1, *slave)), i++) {
154 if (status == -1 && c == '\0') {
155 /* wait for xterm to be created */
156 usleep(100);
158 if (i > 10000) {
159 WARN("can't read xterm WID\n");
160 kill(*pid, SIGKILL);
161 return FALSE;
164 term.c_lflag |= ECHO;
165 tcsetattr(fileno(*master), TCSADRAIN, &term);
167 return TRUE;