Group commit for recovery after disk crash.
[wine/multimedia.git] / console / xterm.c
blobb3c2afd3c173d41e89446ca86cad6db7c1083211
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 <signal.h>
12 #include <sys/ioctl.h>
13 #include <fcntl.h>
14 #include <unistd.h>
15 #include <termios.h>
16 #include <errno.h>
18 #include "windows.h"
19 #include "console.h"
20 #include "debug.h"
22 #define ESC '\x1b'
24 static BOOL32 wine_create_console(FILE **master, FILE **slave, int *pid);
25 static FILE *wine_openpty(FILE **master, FILE **slave, char *name,
26 struct termios *term, struct winsize *winsize);
28 /* The console -- I chose to keep the master and slave
29 * (UNIX) file descriptors around in case they are needed for
30 * ioctls later. The pid is needed to destroy the xterm on close
32 typedef struct _XTERM_CONSOLE {
33 FILE *master; /* xterm side of pty */
34 FILE *slave; /* wine side of pty */
35 int pid; /* xterm's pid, -1 if no xterm */
36 } XTERM_CONSOLE;
38 static XTERM_CONSOLE xterm_console;
40 CONSOLE_device chain;
41 FILE *old_in, *old_out;
43 void XTERM_Start()
45 /* Here, this is a supplementary driver so we should remember to call
46 the chain. */
47 chain.init = driver.init;
48 driver.init = XTERM_Init;
50 chain.close = driver.close;
51 driver.close = XTERM_Close;
53 chain.resizeScreen = driver.resizeScreen;
54 driver.resizeScreen = XTERM_ResizeScreen;
57 void XTERM_Init()
59 wine_create_console(&xterm_console.master, &xterm_console.slave,
60 &xterm_console.pid);
62 old_in = driver.console_in;
63 driver.console_in = xterm_console.slave;
65 old_out = driver.console_out;
66 driver.console_out = xterm_console.slave;
68 /* Then call the chain... */
69 if (chain.init)
70 chain.init();
73 void XTERM_Close()
75 /* Call the chain first... */
76 if (chain.close)
77 chain.close();
79 driver.console_in = old_in;
80 driver.console_out = old_out;
82 /* make sure a xterm exists to kill */
83 if (xterm_console.pid != -1) {
84 kill(xterm_console.pid, SIGTERM);
88 void XTERM_ResizeScreen(int x, int y)
90 char temp[100];
92 /* Call the chain first, there shoudln't be any... */
93 if (chain.resizeScreen)
94 chain.resizeScreen(x, y);
96 sprintf(temp, "\x1b[8;%d;%dt", y, x);
97 CONSOLE_WriteRawString(temp);
99 CONSOLE_NotifyResizeScreen(x, y);
103 static BOOL32 wine_create_console(FILE **master, FILE **slave, int *pid)
105 /* There is definately a bug in this routine that causes a lot
106 of garbage to be written to the screen, but I can't find it...
108 struct termios term;
109 char buf[1024];
110 char c = '\0';
111 int status = 0;
112 int i;
113 int tmaster, tslave;
115 if (tcgetattr(0, &term) < 0) return FALSE;
116 term.c_lflag |= ICANON;
117 term.c_lflag &= ~ECHO;
118 if (wine_openpty(&tmaster, &tslave, NULL, &term, NULL) < 0)
119 return FALSE;
120 *master = fdopen(tmaster, "r+");
121 *slave = fdopen(tslave, "r+");
123 if ((*pid=fork()) == 0) {
124 tcsetattr(fileno(*slave), TCSADRAIN, &term);
125 sprintf(buf, "-Sxx%d", fileno(*master));
126 execlp(CONSOLE_XTERM_PROG, CONSOLE_XTERM_PROG, buf, "-fg",
127 "white", "-bg", "black", NULL);
128 ERR(console, "error creating xterm\n");
129 exit(1);
132 /* most xterms like to print their window ID when used with -S;
133 * read it and continue before the user has a chance...
134 * NOTE: this is the reason we started xterm with ECHO off,
135 * we'll turn it back on below
138 for (i=0; c!='\n'; (status=fread(&c, 1, 1, *slave)), i++) {
139 if (status == -1 && c == '\0') {
140 /* wait for xterm to be created */
141 usleep(100);
143 if (i > 10000) {
144 WARN(console, "can't read xterm WID\n");
145 kill(*pid, SIGKILL);
146 return FALSE;
149 term.c_lflag |= ECHO;
150 tcsetattr(fileno(*master), TCSADRAIN, &term);
152 return TRUE;