PATCH: xterm support for wineconsole

Marcus Meissner marcus at jet.franken.de
Sun Nov 25 15:14:16 CST 2001


Hi,

This patch adds a XTERM backend to wineconsole.

Some problems:
- In full screen text applications (like IDA), the cursor shows sometimes
  up in the wrong spot.
- Scrolling does not work yet (so winedbg doesn't really work).
- Uses config.h.

Not quite ready for production use, but mostly for Eric and Alexandre to
review :) I am however running IDAW in it already.

Ciao, Marcus

Changelog:
	Added 'xterm' backend to wineconsole.
-------------- next part --------------
Index: Makefile.in
===================================================================
RCS file: /home/wine/wine/programs/wineconsole/Makefile.in,v
retrieving revision 1.2
diff -u -r1.2 Makefile.in
--- Makefile.in	2001/11/24 17:07:13	1.2
+++ Makefile.in	2001/11/25 19:29:04
@@ -8,7 +8,8 @@
 C_SRCS = \
 	dialog.c \
 	user.c \
-        wineconsole.c
+        wineconsole.c \
+	xterm.c
 
 RC_SRCS = \
         wineconsole_res.rc
Index: winecon_private.h
===================================================================
RCS file: /home/wine/wine/programs/wineconsole/winecon_private.h,v
retrieving revision 1.1
diff -u -r1.1 winecon_private.h
--- winecon_private.h	2001/11/23 23:05:03	1.1
+++ winecon_private.h	2001/11/25 19:29:15
@@ -44,6 +44,9 @@
     BOOL		hasSelection;	/* a rectangular mouse selection has taken place */
     COORD		selectPt1;	/* start (and end) point of a mouse selection */
     COORD		selectPt2;
+
+    /* The following fields are used by the xterm backend (should be hidden) */
+    int 		xtermfd,xtermpid;
 };
 
 #  ifdef __GNUC__
@@ -68,8 +71,15 @@
 extern void WINECON_FetchCells(struct inner_data* data, int upd_tp, int upd_bm);
 extern int  WINECON_GrabChanges(struct inner_data* data);
 
+
 extern BOOL WCUSER_GetProperties(struct inner_data*);
 extern BOOL WCUSER_SetFont(struct inner_data* data, const LOGFONT* font, const TEXTMETRIC* tm);
 extern BOOL WCUSER_ValidateFont(const struct inner_data* data, const LOGFONT* lf);
 extern BOOL WCUSER_ValidateFontMetric(const struct inner_data* data, const TEXTMETRIC* tm);
 extern BOOL WCUSER_InitBackend(struct inner_data* data);
+
+extern BOOL WCXTERM_GetProperties(struct inner_data*);
+extern BOOL WCXTERM_SetFont(struct inner_data* data, const LOGFONT* font, const TEXTMETRIC* tm);
+extern BOOL WCXTERM_ValidateFont(const struct inner_data* data, const LOGFONT* lf);
+extern BOOL WCXTERM_ValidateFontMetric(const struct inner_data* data, const TEXTMETRIC* tm);
+extern BOOL WCXTERM_InitBackend(struct inner_data* data);
Index: wineconsole.c
===================================================================
RCS file: /home/wine/wine/programs/wineconsole/wineconsole.c,v
retrieving revision 1.2
diff -u -r1.2 wineconsole.c
--- wineconsole.c	2001/11/25 00:49:36	1.2
+++ wineconsole.c	2001/11/25 19:29:20
@@ -212,8 +212,7 @@
 	else num = 0;
     }
     SERVER_END_VAR_REQ;
-    if (!num) {Trace(0, "hmm renderer signaled but no events available\n"); return 1;}
-    
+
     /* FIXME: should do some event compression here (cursor pos, update) */
     Trace(1, "Change notification:");
     for (i = 0; i < num; i++)
-------------- next part --------------
/*
 * a GUI application for displaying a console
 *	XTERM back end
 * Copyright 2001 Marcus Meissner
 */

#include "config.h"

#ifdef HAVE_OPENPTY /* use this as trigger whether we can use it or not */

#include <assert.h>
#include <fcntl.h>
#include <sys/time.h>
#include <errno.h>
#include <sys/errno.h>
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#ifdef HAVE_PTY_H
# include <pty.h>
#endif

#include "winecon_private.h"

/* Ascii -> VK, generated by calling VkKeyScanA(i) */
static int vkkeyscan_table[256] = {
	0,0,0,0,0,0,0,0,8,9,0,0,0,13,0,0,0,0,0,19,145,556,0,0,0,0,0,27,0,0,0,
	0,32,305,478,307,308,309,311,222,313,304,312,443,188,189,190,191,48,
	49,50,51,52,53,54,55,56,57,442,186,444,187,446,447,306,321,322,323,
	324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,
	341,342,343,344,345,346,219,220,221,310,445,192,65,66,67,68,69,70,71,
	72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,475,476,477,
	448,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,400,0,0,0,0,0,0
};

static int mapvkey_0[256]={
	0,0,0,0,0,0,0,0,14,15,0,0,0,28,0,0,42,29,56,69,58,0,0,0,0,0,0,1,0,0,
	0,0,57,73,81,79,71,75,72,77,80,0,0,0,55,82,83,0,11,2,3,4,5,6,7,8,9,
	10,0,0,0,0,0,0,0,30,48,46,32,18,33,34,35,23,36,37,38,50,49,24,25,16,
	19,31,20,22,47,17,45,21,44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,55,78,0,74,
	0,53,59,60,61,62,63,64,65,66,67,68,87,88,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,69,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,39,13,51,12,52,53,41,0,0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,26,43,27,40,76,96,0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};

static int mapvkey_1[256]={
	0,27,49,50,51,52,53,54,55,56,57,48,189,187,8,9,81,87,69,82,84,89,85,
	73,79,80,219,221,13,17,65,83,68,70,71,72,74,75,76,186,222,192,16,220,
	90,88,67,86,66,78,77,188,190,191,16,106,18,32,20,112,113,114,115,116,
	117,118,119,120,121,144,145,36,38,33,109,37,223,39,107,35,40,34,45,
	46,0,0,0,122,123,0,0,0,0,0,0,0,224,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0
};

int xwrite(int fd,caddr_t buf,size_t size) {
    int curwritten = 0;

    while (curwritten < size) {
	int res = write(fd,buf+curwritten,size-curwritten);
	
	if (res == -1)
	    return -1;
	curwritten += res;
    }
    return curwritten;
}

/******************************************************************
 *		WCXTERM_PosCursor
 *
 * Set a new position for the cursor
 */
static void	WCXTERM_PosCursor(const struct inner_data* data)
{
    char buf[30];

    sprintf(buf,"%c[%d;%dH",27,data->cursor.Y+1,data->cursor.X+1);
    xwrite(data->xtermfd,buf,strlen(buf));
}

/******************************************************************
 *		WCXTERM_FillMemDC
 *
 * Fills the Mem DC with current cells values
 */
static void WCXTERM_FillMemDC(const struct inner_data* data, int upd_tp, int upd_bm)
{
    unsigned		i, j, k;
    CHAR_INFO*		cell;
    WORD		attr;
    CHAR*		line;
    char		outbuf[30];
    const int colormap[8] = { 0,4,2,6, 1,5,3,7, };

    sprintf(outbuf,"%c7",27);xwrite(data->xtermfd,outbuf,2);

    if (!(line = HeapAlloc(GetProcessHeap(), 0, data->sb_width*sizeof(CHAR))))
    {Trace(0, "OOM\n"); return;}

    for (j = upd_tp; j <= upd_bm; j++)
    {
	cell = &data->cells[j * data->sb_width];
	for (i = 0; i < data->win_width; i++)
	{
	    attr = cell[i].Attributes;
	    sprintf(outbuf,"%c[0;%s3%d;4%dm%c[%d;%dH",
		    27,
		    (attr & FOREGROUND_INTENSITY)?"1;":"",
		    colormap[attr&7],
		    colormap[(attr&0x70)>>4],
		    27,
		    j+1,
		    i+1
	    );
	    xwrite(data->xtermfd,outbuf,strlen(outbuf));
	    for (k = i; k < data->win_width && cell[k].Attributes == attr; k++){
		WCHAR c = cell[k].Char.UnicodeChar;
		/* Escape special vt100 escape codes with 8 bit set */
		switch (c) {
		case 132:case 133:case 136:case 141:case 142:case 143:case 144:
		case 150:case 151:case 155:case 156:case 157:case 158:case 159:
			c='?';break;
		default: break;
		}
		line[k - i] = c;
	    }
	    xwrite(data->xtermfd,line,k-i);
	    i = k - 1;
	}
    }
    sprintf(outbuf,"%c8",27);xwrite(data->xtermfd,outbuf,2);
}

/******************************************************************
 *		WCXTERM_NewBitmap
 *
 * Either the font geometry or the sb geometry has changed.
 */
static void WCXTERM_NewBitmap(struct inner_data* data, BOOL fill)
{
    if (!data->sb_width || !data->sb_height)
	return;
    if (fill)
	WCXTERM_FillMemDC(data, 0, data->sb_height - 1);
}

/******************************************************************
 *		WCXTERM_ResizeScreenBuffer
 *
 *
 */
static void WCXTERM_ResizeScreenBuffer(struct inner_data* data)
{
    WCXTERM_NewBitmap(data, FALSE);
}

/******************************************************************
 *		WCXTERM_SetTitle
 *
 * Sets the title to the wine console
 */
static void	WCXTERM_SetTitle(const struct inner_data* data)
{
    WCHAR	buffer[256];

    if (WINECON_GetConsoleTitle(data->hConIn, buffer, sizeof(buffer))) {
	WCHAR	*w;
	char	abuffer[256],*s;

	strcpy( abuffer, "\033]2;" );
	s = abuffer+strlen(abuffer);

	w = buffer;
	while ((*s++ = *w++))
	    /*EMPTY*/;
	s--; /* step back to \0 */
	*s++='\a';
	*s++='\0';
	xwrite(data->xtermfd,abuffer,strlen(abuffer));
    }
}

static void WCXTERM_Refresh(const struct inner_data* data, int tp, int bm)
{
    if (data->win_pos.Y <= bm && data->win_pos.Y + data->win_height >= tp)
    {
	WCXTERM_FillMemDC(data, tp, bm);
    }
}

/******************************************************************
 *		WCXTERM_DeleteBackend
 *
 *
 */
void WCXTERM_DeleteBackend(struct inner_data* data)
{
    fprintf(stderr,"WCXTERM_DeleteBackend\n");
}

/****************************************************************************
 *		WCXTERM_string_to_IR			[internal]
 *
 * Transfers a string read from XTERM to INPUT_RECORDs and adds them to the
 * queue. Does translation of vt100 style function keys and xterm-mouse clicks.
 */
static void
WCXTERM_string_to_IR( struct inner_data *data,unsigned char *buf,int len) {
    int			j,k;
    INPUT_RECORD	ir;
    DWORD		junk;

    for (j=0;j<len;j++) {
    	unsigned char inchar = buf[j];

	memset(&ir,0,sizeof(ir));

	if (inchar!=27) { /* no escape -> 'normal' keyboard event */
	    ir.EventType = 1; /* Key_event */

	    ir.Event.KeyEvent.bKeyDown		= 1;
	    ir.Event.KeyEvent.wRepeatCount	= 0;

	    ir.Event.KeyEvent.dwControlKeyState	= 0;
	    if (inchar & 0x80) {
		ir.Event.KeyEvent.dwControlKeyState|=LEFT_ALT_PRESSED;
		inchar &= ~0x80;
	    }
	    ir.Event.KeyEvent.wVirtualKeyCode = vkkeyscan_table[inchar];
	    if (ir.Event.KeyEvent.wVirtualKeyCode & 0x0100)
		ir.Event.KeyEvent.dwControlKeyState|=SHIFT_PRESSED;
	    if (ir.Event.KeyEvent.wVirtualKeyCode & 0x0200)
		ir.Event.KeyEvent.dwControlKeyState|=LEFT_CTRL_PRESSED;
	    if (ir.Event.KeyEvent.wVirtualKeyCode & 0x0400)
		ir.Event.KeyEvent.dwControlKeyState|=LEFT_ALT_PRESSED;
	    ir.Event.KeyEvent.wVirtualScanCode = mapvkey_0[
	    	ir.Event.KeyEvent.wVirtualKeyCode & 0x00ff
	    ]; /* VirtualKeyCodes to ScanCode */
	    ir.Event.KeyEvent.uChar.AsciiChar = inchar;

	    if ((inchar==127)||(inchar=='\b')) { /* backspace */
	    	ir.Event.KeyEvent.uChar.AsciiChar = '\b'; /* FIXME: hmm */
		ir.Event.KeyEvent.wVirtualScanCode = 0x0e;
		ir.Event.KeyEvent.wVirtualKeyCode = VK_BACK;
	    } else {
		if ((inchar=='\n')||(inchar=='\r')) {
		    ir.Event.KeyEvent.uChar.AsciiChar	= '\r';
		    ir.Event.KeyEvent.wVirtualKeyCode	= VK_RETURN;
		    ir.Event.KeyEvent.wVirtualScanCode	= 0x1c;
		    ir.Event.KeyEvent.dwControlKeyState = 0;
		} else {
		    if (inchar<' ') {
			/* FIXME: find good values for ^X */
			ir.Event.KeyEvent.wVirtualKeyCode = 0xdead;
			ir.Event.KeyEvent.wVirtualScanCode = 0xbeef;
		    } 
		}
	    }

	    assert(WriteConsoleInputA( data->hConIn, &ir, 1, &junk ));
	    ir.Event.KeyEvent.bKeyDown = 0;
	    assert(WriteConsoleInputA( data->hConIn, &ir, 1, &junk ));
	    continue;
	}
	/* inchar is ESC */
	if ((j==len-1) || (buf[j+1]!='[')) {/* add ESCape on its own */
	    ir.EventType = 1; /* Key_event */
	    ir.Event.KeyEvent.bKeyDown		= 1;
	    ir.Event.KeyEvent.wRepeatCount	= 0;

	    ir.Event.KeyEvent.wVirtualKeyCode	= VK_ESCAPE;
	    ir.Event.KeyEvent.wVirtualScanCode	= mapvkey_0[
	    	ir.Event.KeyEvent.wVirtualKeyCode
	    ];
	    ir.Event.KeyEvent.dwControlKeyState = 0;
	    ir.Event.KeyEvent.uChar.AsciiChar	= 27;
	    assert(WriteConsoleInputA( data->hConIn, &ir, 1, &junk ));
	    ir.Event.KeyEvent.bKeyDown = 0;
	    assert(WriteConsoleInputA( data->hConIn, &ir, 1, &junk ));
	    continue;
	}
	for (k=j;k<len;k++) {
	    if (((buf[k]>='A') && (buf[k]<='Z')) ||
		((buf[k]>='a') && (buf[k]<='z')) ||
	    	 (buf[k]=='~')
	    )
	    	break;
	}
	if (k<len) {
	    int	subid,scancode=0;

	    ir.EventType			= 1; /* Key_event */
	    ir.Event.KeyEvent.bKeyDown		= 1;
	    ir.Event.KeyEvent.wRepeatCount	= 0;
	    ir.Event.KeyEvent.dwControlKeyState	= 0;

	    ir.Event.KeyEvent.wVirtualKeyCode	= 0xad; /* FIXME */
	    ir.Event.KeyEvent.wVirtualScanCode	= 0xad; /* FIXME */
	    ir.Event.KeyEvent.uChar.AsciiChar	= 0;

	    switch (buf[k]) {
	    case '~':
		sscanf(&buf[j+2],"%d",&subid);
		switch (subid) {
		case  2:/*INS */scancode = 0xe052;break;
		case  3:/*DEL */scancode = 0xe053;break;
		case  6:/*PGDW*/scancode = 0xe051;break;
		case  5:/*PGUP*/scancode = 0xe049;break;
		case 11:/*F1  */scancode = 0x003b;break;
		case 12:/*F2  */scancode = 0x003c;break;
		case 13:/*F3  */scancode = 0x003d;break;
		case 14:/*F4  */scancode = 0x003e;break;
		case 15:/*F5  */scancode = 0x003f;break;
		case 17:/*F6  */scancode = 0x0040;break;
		case 18:/*F7  */scancode = 0x0041;break;
		case 19:/*F8  */scancode = 0x0042;break;
		case 20:/*F9  */scancode = 0x0043;break;
		case 21:/*F10 */scancode = 0x0044;break;
		case 23:/*F11 */scancode = 0x00d9;break;
		case 24:/*F12 */scancode = 0x00da;break;
		/* FIXME: Shift-Fx */
		default:
			fprintf(stderr,"parse ESC[%d~\n",subid);
			break;
		}
		break;
	    case 'A': /* Cursor Up    */scancode = 0xe048;break;
	    case 'B': /* Cursor Down  */scancode = 0xe050;break;
	    case 'D': /* Cursor Left  */scancode = 0xe04b;break;
	    case 'C': /* Cursor Right */scancode = 0xe04d;break;
	    case 'F': /* End          */scancode = 0xe04f;break;
	    case 'H': /* Home         */scancode = 0xe047;break;
	    case 'M':
	    	/* Mouse Button Press  (ESCM<button+'!'><x+'!'><y+'!'>) or
		 *              Release (ESCM#<x+'!'><y+'!'>
		 */
		if (k<len-3) {
		    ir.EventType			= MOUSE_EVENT;
		    ir.Event.MouseEvent.dwMousePosition.X = buf[k+2]-'!';
		    ir.Event.MouseEvent.dwMousePosition.Y = buf[k+3]-'!';
		    if (buf[k+1]=='#')
			ir.Event.MouseEvent.dwButtonState = 0;
		    else
			ir.Event.MouseEvent.dwButtonState = 1<<(buf[k+1]-' ');
		    ir.Event.MouseEvent.dwEventFlags	  = 0; /* FIXME */
		    assert(WriteConsoleInputA( data->hConIn, &ir, 1, &junk));
		    j=k+3;
		}
	    	break;
	    case 'c':
	    	j=k;
		break;
	    }
	    if (scancode) {
		ir.Event.KeyEvent.wVirtualScanCode = scancode;
		ir.Event.KeyEvent.wVirtualKeyCode  = mapvkey_1[scancode];
		assert(WriteConsoleInputA( data->hConIn, &ir, 1, &junk ));
		ir.Event.KeyEvent.bKeyDown		= 0;
		assert(WriteConsoleInputA( data->hConIn, &ir, 1, &junk ));
		j=k;
		continue;
	    }
	}
    }
}


/******************************************************************
 *		WCXTERM_MainLoop
 *
 *
 */
static int
WCXTERM_MainLoop( struct inner_data *data )
{
    char	*buf = HeapAlloc(GetProcessHeap(),0,1);
    int		len = 0, escape_seen = 0;

    while (1)
    {
	DWORD res;
	char inchar;
	struct timeval tv;
	fd_set readfds;

	memset(&tv,0,sizeof(tv));

	/* If we have at one time seen escape in this loop, we are 
	 * within an Escape sequence, so wait for a bit more input for the
	 * rest of the loop.
	 */

	if (escape_seen) {
	    tv.tv_sec  =      0;
	    tv.tv_usec =  50000;
	} else {
	    tv.tv_sec  =      0;
	    tv.tv_usec = 100000;
	}
	FD_ZERO(&readfds);
	FD_SET(data->xtermfd,&readfds);
	if (-1==(res=select(data->xtermfd+1,&readfds,NULL,NULL,&tv))) {
	    perror("select");
	    return 1;
	}
	/* Get events from server */
	if (!WINECON_GrabChanges(data))
	    return 0;

	if (res>0) {
	    while (1) {
		res = read( data->xtermfd, &inchar, 1 );
		switch (res) {
		case -1:if (errno==EAGAIN)
			    break; /* expected error for non blocking */
			perror("break");
			return 1;
		case  0:fprintf(stderr,"read returned 0, EOF on xterm?\n");
			break;
		default:break;
		}
		if (res==0)
		    return 0;
		if (res == -1) /* no more input, wait */
		    break;
		buf = HeapReAlloc(GetProcessHeap(),0,buf,len+1);
		buf[len++]=inchar;
		if (inchar == 27) {
			if (len>1) {
				/* If we spot an ESC, we flush all up to it
				 * since we can be sure that we have a complete
				 * sequence.
				 */
				WCXTERM_string_to_IR(data,buf,len-1);
				buf = HeapReAlloc(GetProcessHeap(),0,buf,1);
				buf[0] = 27;
				len = 1;
			}
			escape_seen = 1;
			continue;
		}
	    }
	} else {
	    /* we did not have a character above */
	    if (buf) {
		WCXTERM_string_to_IR(data,buf,len);
		len = 0;
		HeapFree(GetProcessHeap(),0,buf);
		buf = NULL;
		escape_seen = 0;
	    }
	}
    }
    return 0;
}

static BOOL CONSOLE_make_complex(struct inner_data *data)
{
	struct termios term;
	char buf[256];
	char c = '\0';
	int i,master,slave,flags;

	if (tcgetattr(0, &term) < 0) {
		/* ignore failure, or we can't run from a script */
	}
	term.c_lflag = ~(ECHO|ICANON);

        if (openpty(&master, &slave, NULL, &term, NULL) < 0)
            return FALSE;

	if ((data->xtermpid=fork()) == 0) {
		tcsetattr(slave, TCSADRAIN, &term);
                close( slave );
		sprintf(buf, "-Sxx%d", master);
		/* "-fn vga" for VGA font. Harmless if vga is not present:
		 *  xterm: unable to open font "vga", trying "fixed".... 
		 */
		execlp("xterm", "xterm", buf, "-fn","vga",NULL);
		perror("error creating AllocConsole xterm");
		exit(1);
	}
        close( master );

	/* most xterms like to print their window ID when used with -S;
	 * read it and continue before the user has a chance...
	 */
        for (i = 0; i < 10000; i++)
        {
            if (read( slave, &c, 1 ) == 1)
            {
                if (c == '\n') break;
            }
            else usleep(100); /* wait for xterm to be created */
        }
        if (i == 10000)
        {
            fprintf(stderr,"can't read xterm WID\n");
            close( slave );
            return FALSE;
	}
	data->xtermfd = slave;
	fcntl(data->xtermfd,F_GETFL,&flags);
	flags |= O_NDELAY;
	fcntl(data->xtermfd,F_SETFL,flags);
	/* Enable mouseclicks, disable 8bit charactercontrols */
	strcpy( buf, "\033[?1002h\033 F" );
	xwrite(data->xtermfd,buf,strlen(buf));
	return TRUE;
}

static void WCXTERM_Scroll(struct inner_data* data, int pos, BOOL horz) {
    fprintf(stderr,"WCXTERM_Scroll(%p,%d,%d), stub.\n",data,pos,horz);
}

static void WCXTERM_ShapeCursor(struct inner_data* data, int size, int vis, BOOL force) {
    char *escseq;

    if (vis)
	escseq="\033[?25h";
    else
	escseq="\033[?25l";
    data->cursor_visible = vis;
    xwrite(data->xtermfd,escseq,strlen(escseq));
}

static void WCXTERM_ComputePositions(struct inner_data* data) {
    fprintf(stderr,"WCXTERM_ComputePositions(%p), stub.\n",data);
}

/******************************************************************
 *		WCXTERM_InitBackend
 *
 * Initialisation part II: creation of window.
 *
 */
BOOL WCXTERM_InitBackend(struct inner_data* data)
{
    data->fnMainLoop = WCXTERM_MainLoop;
    data->fnPosCursor = WCXTERM_PosCursor;
    data->fnShapeCursor = WCXTERM_ShapeCursor;
    data->fnComputePositions = WCXTERM_ComputePositions;
    data->fnRefresh = WCXTERM_Refresh;
    data->fnResizeScreenBuffer = WCXTERM_ResizeScreenBuffer;
    data->fnSetTitle = WCXTERM_SetTitle;
    data->fnScroll = WCXTERM_Scroll;
    data->fnDeleteBackend = WCXTERM_DeleteBackend;

    CONSOLE_make_complex(data);
    /* force update of current data */
    WINECON_GrabChanges(data);
    return TRUE;
}
#endif


More information about the wine-patches mailing list