/* xterm.c */

/* This "driver" is designed to go on top of an existing driver
   to provide support for features only present if using an
   xterm or compatible program for your console output. 
   Currently, it supports resizing and separating debug messages from
   program output.
   It does not currently support changing the title bar.
*/

#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>

#include "console.h"
#include "options.h"
#include "debugtools.h"

DEFAULT_DEBUG_CHANNEL(console);

char console_xterm_prog[80];

static BOOL wine_create_console(FILE **master, FILE **slave, pid_t *pid);
int wine_openpty(int *master, int *slave, char *name,
		 struct termios *term, struct winsize *winsize);

/* The console -- I chose to keep the master and slave
 * (UNIX) file descriptors around in case they are needed for
 * ioctls later.  The pid is needed to destroy the xterm on close
 */
typedef struct _XTERM_CONSOLE {
        FILE    *master;                 /* xterm side of pty */
        FILE    *slave;                  /* wine side of pty */
        pid_t    pid;                    /* xterm's pid, -1 if no xterm */
} XTERM_CONSOLE;

static XTERM_CONSOLE xterm_console;

CONSOLE_device chain;
FILE *old_in, *old_out;

void XTERM_Start(void)
{
   /* Here, this is a supplementary driver so we should remember to call
      the chain. */
   chain.init = driver.init;
   driver.init = XTERM_Init;

   chain.close = driver.close;
   driver.close = XTERM_Close;

   chain.resizeScreen = driver.resizeScreen;
   driver.resizeScreen = XTERM_ResizeScreen;

   /* Read in driver configuration */
   PROFILE_GetWineIniString("console", "XtermProg",
      "xterm", console_xterm_prog, 79); 

}

void XTERM_Init()
{
   wine_create_console(&xterm_console.master, &xterm_console.slave,
      &xterm_console.pid);

   old_in = driver.console_in;
   driver.console_in = xterm_console.slave;

   old_out = driver.console_out;
   driver.console_out = xterm_console.slave;

   /* Then call the chain... */
   if (chain.init)
      chain.init();
}

void XTERM_Close()
{
   /* Call the chain first... */
   if (chain.close)
      chain.close();

   driver.console_in = old_in;
   driver.console_out = old_out;

   /* make sure a xterm exists to kill */
   if (xterm_console.pid != -1) {
      kill(xterm_console.pid, SIGTERM);
   }
}

void XTERM_ResizeScreen(int x, int y)
{
   char temp[100];

   /* Call the chain first, there shoudln't be any... */
   if (chain.resizeScreen)
      chain.resizeScreen(x, y);

   sprintf(temp, "\x1b[8;%d;%dt", y, x);
   CONSOLE_WriteRawString(temp);

   CONSOLE_NotifyResizeScreen(x, y);
}


static BOOL wine_create_console(FILE **master, FILE **slave, pid_t *pid)
{
        /* There is definately a bug in this routine that causes a lot
           of garbage to be written to the screen, but I can't find it...
        */
        struct termios term;
        char buf[1024];
        char c = '\0';
        int status = 0;
        int i;
        int tmaster, tslave;
        char xterm_resolution[10];

        sprintf(xterm_resolution, "%dx%d", driver.x_res,
           driver.y_res);

        if (tcgetattr(0, &term) < 0) return FALSE;
        term.c_lflag |= ICANON;
        term.c_lflag &= ~ECHO;
        if (wine_openpty(&tmaster, &tslave, NULL, &term, NULL) < 0)
           return FALSE;
        *master = fdopen(tmaster, "r+");
        *slave = fdopen(tslave, "r+");

        if ((*pid=fork()) == 0) {
                tcsetattr(fileno(*slave), TCSADRAIN, &term);
                sprintf(buf, "-Sxx%d", fileno(*master));
                execlp(console_xterm_prog, console_xterm_prog, buf, "-fg",
                   "white", "-bg", "black", "-g",
                   xterm_resolution, NULL);
                ERR("error creating xterm (file not found?)\n");
                exit(1);
        }

        /* most xterms like to print their window ID when used with -S;
         * read it and continue before the user has a chance...
         * NOTE: this is the reason we started xterm with ECHO off,
         * we'll turn it back on below
         */

        for (i=0; c!='\n'; (status=fread(&c, 1, 1, *slave)), i++) {
                if (status == -1 && c == '\0') {
                                /* wait for xterm to be created */
                        usleep(100);
                }
                if (i > 10000) {
                        WARN("can't read xterm WID\n");
                        kill(*pid, SIGKILL);
                        return FALSE;
                }
        }
        term.c_lflag |= ECHO;
        tcsetattr(fileno(*master), TCSADRAIN, &term);

        return TRUE;
}
