1998-12-02 20:58:08 +01:00
|
|
|
/* interface.c */
|
|
|
|
|
|
|
|
/* The primary purpose of this function is to provide CONSOLE_*
|
|
|
|
reotines that immediately call the appropiate driver handler.
|
|
|
|
This cleans up code in the individual modules considerably.
|
|
|
|
This could be done using a macro, but additional functionality
|
|
|
|
may be provided here in the future. */
|
|
|
|
|
1998-12-09 16:43:03 +01:00
|
|
|
#include <stdio.h>
|
1998-12-25 09:48:56 +01:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
1998-12-09 16:43:03 +01:00
|
|
|
|
1999-02-20 17:42:49 +01:00
|
|
|
#include "config.h"
|
1999-02-17 14:51:06 +01:00
|
|
|
#include "windef.h"
|
1998-12-02 20:58:08 +01:00
|
|
|
#include "console.h"
|
1999-02-20 17:42:49 +01:00
|
|
|
#include "options.h"
|
1998-12-02 20:58:08 +01:00
|
|
|
|
1999-04-18 11:25:27 +02:00
|
|
|
CONSOLE_device driver;
|
|
|
|
|
1998-12-25 09:48:56 +01:00
|
|
|
static int pop_driver(char **, char **, int *);
|
1998-12-09 16:43:03 +01:00
|
|
|
|
1999-02-14 12:15:47 +01:00
|
|
|
static int console_initialized = FALSE;
|
1998-12-02 20:58:08 +01:00
|
|
|
|
2000-02-19 21:50:00 +01:00
|
|
|
static int CONSOLE_Init(void)
|
1998-12-02 20:58:08 +01:00
|
|
|
{
|
2000-02-19 21:50:00 +01:00
|
|
|
char buffer[256];
|
|
|
|
char *single, *drivers = buffer;
|
1998-12-25 09:48:56 +01:00
|
|
|
int length;
|
1999-02-20 17:42:49 +01:00
|
|
|
char initial_rows[5];
|
|
|
|
char initial_columns[5];
|
|
|
|
|
1998-12-09 16:43:03 +01:00
|
|
|
/* Suitable defaults... */
|
|
|
|
driver.console_out = stdout;
|
|
|
|
driver.console_in = stdin;
|
1998-12-02 20:58:08 +01:00
|
|
|
|
2000-02-19 21:50:00 +01:00
|
|
|
/* drivers should be a string that consists of driver names
|
|
|
|
followed by plus (+) signs to denote additions.
|
|
|
|
|
|
|
|
For example:
|
|
|
|
drivers = tty Load just the tty driver
|
|
|
|
drivers = ncurses+xterm Load ncurses then xterm
|
|
|
|
|
|
|
|
The "default" value is just tty.
|
|
|
|
*/
|
|
|
|
PROFILE_GetWineIniString( "console", "Drivers", CONSOLE_DEFAULT_DRIVER,
|
|
|
|
buffer, sizeof(buffer) );
|
|
|
|
|
1998-12-25 09:48:56 +01:00
|
|
|
while (pop_driver(&drivers, &single, &length))
|
|
|
|
{
|
|
|
|
if (!strncmp(single, "tty", length))
|
|
|
|
TTY_Start();
|
|
|
|
#ifdef WINE_NCURSES
|
|
|
|
else if (!strncmp(single, "ncurses", length))
|
|
|
|
NCURSES_Start();
|
|
|
|
#endif /* WINE_NCURSES */
|
|
|
|
else if (!strncmp(single, "xterm", length))
|
|
|
|
XTERM_Start();
|
|
|
|
}
|
|
|
|
|
1999-02-20 17:42:49 +01:00
|
|
|
/* Read in generic configuration */
|
|
|
|
/* This is primarily to work around a limitation in nxterm where
|
|
|
|
this information is not correctly passed to the ncurses layer
|
|
|
|
through the terminal. At least, I'm not doing it correctly if there
|
|
|
|
is a way. But this serves as a generic way to do the same anyway. */
|
|
|
|
|
|
|
|
/* We are setting this to 80x25 here which is *not* the default for
|
|
|
|
most xterm variants... It is however the standard VGA resolution */
|
|
|
|
|
|
|
|
/* FIXME: We need to be able to be able to specify that the window's
|
|
|
|
dimensions should be used. This is required for correct emulation
|
|
|
|
of Win32's console and Win32's DOS emulation */
|
|
|
|
|
|
|
|
PROFILE_GetWineIniString("console", "InitialRows",
|
|
|
|
"24", initial_rows, 5);
|
|
|
|
PROFILE_GetWineIniString("console", "InitialColumns",
|
|
|
|
"80", initial_columns, 5);
|
|
|
|
|
|
|
|
sscanf(initial_rows, "%d", &driver.y_res);
|
|
|
|
sscanf(initial_columns, "%d", &driver.x_res);
|
|
|
|
|
1998-12-25 09:48:56 +01:00
|
|
|
GENERIC_Start();
|
1998-12-09 16:43:03 +01:00
|
|
|
|
1998-12-02 20:58:08 +01:00
|
|
|
if (driver.init)
|
|
|
|
driver.init();
|
1999-02-14 12:15:47 +01:00
|
|
|
|
1999-02-20 17:42:49 +01:00
|
|
|
/* Not all terminals let our programs know the proper resolution
|
|
|
|
if the resolution is set on the command-line... */
|
|
|
|
CONSOLE_NotifyResizeScreen(driver.x_res, driver.y_res);
|
|
|
|
|
2000-08-06 04:42:46 +02:00
|
|
|
atexit(CONSOLE_Close);
|
|
|
|
|
1999-02-14 12:15:47 +01:00
|
|
|
/* For now, always return TRUE */
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CONSOLE_Write(char out, int fg_color, int bg_color, int attribute)
|
|
|
|
{
|
|
|
|
if (!console_initialized)
|
2000-02-19 21:50:00 +01:00
|
|
|
console_initialized = CONSOLE_Init();
|
1999-02-14 12:15:47 +01:00
|
|
|
|
|
|
|
if (driver.write)
|
|
|
|
{
|
|
|
|
driver.write(out, fg_color, bg_color, attribute);
|
|
|
|
if (!driver.norefresh)
|
|
|
|
CONSOLE_Refresh();
|
|
|
|
}
|
1998-12-02 20:58:08 +01:00
|
|
|
}
|
|
|
|
|
2000-08-06 04:42:46 +02:00
|
|
|
void CONSOLE_Close(void)
|
1998-12-02 20:58:08 +01:00
|
|
|
{
|
|
|
|
if (driver.close)
|
|
|
|
driver.close();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CONSOLE_MoveCursor(char row, char col)
|
|
|
|
{
|
1999-02-14 12:15:47 +01:00
|
|
|
if (!console_initialized)
|
2000-02-19 21:50:00 +01:00
|
|
|
console_initialized = CONSOLE_Init();
|
1999-02-14 12:15:47 +01:00
|
|
|
|
1998-12-02 20:58:08 +01:00
|
|
|
if (driver.moveCursor)
|
|
|
|
{
|
|
|
|
driver.moveCursor(row, col);
|
|
|
|
if (!driver.norefresh)
|
|
|
|
CONSOLE_Refresh();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CONSOLE_ClearWindow(char row1, char col1, char row2, char col2,
|
|
|
|
int bg_color, int attribute)
|
|
|
|
{
|
1999-02-14 12:15:47 +01:00
|
|
|
if (!console_initialized)
|
2000-02-19 21:50:00 +01:00
|
|
|
console_initialized = CONSOLE_Init();
|
1999-02-14 12:15:47 +01:00
|
|
|
|
1998-12-02 20:58:08 +01:00
|
|
|
if (driver.clearWindow)
|
|
|
|
{
|
|
|
|
driver.clearWindow(row1, col1, row2, col2, bg_color, attribute);
|
|
|
|
if (!driver.norefresh)
|
|
|
|
CONSOLE_Refresh();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CONSOLE_ScrollUpWindow(char row1, char col1, char row2, char col2,
|
|
|
|
char lines, int bg_color, int attribute)
|
|
|
|
{
|
1999-02-14 12:15:47 +01:00
|
|
|
if (!console_initialized)
|
2000-02-19 21:50:00 +01:00
|
|
|
console_initialized = CONSOLE_Init();
|
1999-02-14 12:15:47 +01:00
|
|
|
|
1998-12-02 20:58:08 +01:00
|
|
|
if (driver.scrollUpWindow)
|
|
|
|
{
|
|
|
|
driver.scrollUpWindow(row1, col1, row2, col2, lines, bg_color,
|
|
|
|
attribute);
|
|
|
|
if (!driver.norefresh)
|
|
|
|
CONSOLE_Refresh();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CONSOLE_ScrollDownWindow(char row1, char col1, char row2, char col2,
|
|
|
|
char lines, int bg_color, int attribute)
|
|
|
|
{
|
1999-02-14 12:15:47 +01:00
|
|
|
if (!console_initialized)
|
2000-02-19 21:50:00 +01:00
|
|
|
console_initialized = CONSOLE_Init();
|
1999-02-14 12:15:47 +01:00
|
|
|
|
1998-12-02 20:58:08 +01:00
|
|
|
if (driver.scrollDownWindow)
|
|
|
|
{
|
|
|
|
driver.scrollDownWindow(row1, col1, row2, col2, lines, bg_color,
|
|
|
|
attribute);
|
|
|
|
if (!driver.norefresh)
|
|
|
|
CONSOLE_Refresh();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int CONSOLE_CheckForKeystroke(char *scan, char *ascii)
|
|
|
|
/* These functions need to go through a conversion layer. Scancodes
|
|
|
|
should *not* be determined by the driver, rather they should have
|
|
|
|
a conv_* function in int16.c. Yuck. */
|
|
|
|
{
|
1999-02-14 12:15:47 +01:00
|
|
|
if (!console_initialized)
|
2000-02-19 21:50:00 +01:00
|
|
|
console_initialized = CONSOLE_Init();
|
1999-02-14 12:15:47 +01:00
|
|
|
|
1998-12-02 20:58:08 +01:00
|
|
|
if (driver.checkForKeystroke)
|
|
|
|
return driver.checkForKeystroke(scan, ascii);
|
|
|
|
else
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CONSOLE_GetKeystroke(char *scan, char *ascii)
|
|
|
|
{
|
1999-02-14 12:15:47 +01:00
|
|
|
if (!console_initialized)
|
2000-02-19 21:50:00 +01:00
|
|
|
console_initialized = CONSOLE_Init();
|
1999-02-14 12:15:47 +01:00
|
|
|
|
1998-12-02 20:58:08 +01:00
|
|
|
if (driver.getKeystroke)
|
1998-12-25 09:48:56 +01:00
|
|
|
driver.getKeystroke(scan, ascii);
|
1998-12-02 20:58:08 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void CONSOLE_GetCursorPosition(char *row, char *col)
|
|
|
|
{
|
1999-02-14 12:15:47 +01:00
|
|
|
if (!console_initialized)
|
2000-02-19 21:50:00 +01:00
|
|
|
console_initialized = CONSOLE_Init();
|
1999-02-14 12:15:47 +01:00
|
|
|
|
1998-12-02 20:58:08 +01:00
|
|
|
if (driver.getCursorPosition)
|
1998-12-25 09:48:56 +01:00
|
|
|
driver.getCursorPosition(row, col);
|
1998-12-02 20:58:08 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void CONSOLE_GetCharacterAtCursor(char *ch, int *fg, int *bg, int *a)
|
|
|
|
{
|
1999-02-14 12:15:47 +01:00
|
|
|
if (!console_initialized)
|
2000-02-19 21:50:00 +01:00
|
|
|
console_initialized = CONSOLE_Init();
|
1999-02-14 12:15:47 +01:00
|
|
|
|
1998-12-02 20:58:08 +01:00
|
|
|
if (driver.getCharacterAtCursor)
|
1998-12-25 09:48:56 +01:00
|
|
|
driver.getCharacterAtCursor(ch, fg, bg, a);
|
1998-12-02 20:58:08 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void CONSOLE_Refresh()
|
|
|
|
{
|
1999-02-14 12:15:47 +01:00
|
|
|
if (!console_initialized)
|
2000-02-19 21:50:00 +01:00
|
|
|
console_initialized = CONSOLE_Init();
|
1999-02-14 12:15:47 +01:00
|
|
|
|
1998-12-02 20:58:08 +01:00
|
|
|
if (driver.refresh)
|
1998-12-25 09:48:56 +01:00
|
|
|
driver.refresh();
|
1998-12-02 20:58:08 +01:00
|
|
|
}
|
|
|
|
|
1999-01-30 13:51:09 +01:00
|
|
|
int CONSOLE_AllocColor(int color)
|
|
|
|
{
|
1999-02-14 12:15:47 +01:00
|
|
|
if (!console_initialized)
|
2000-02-19 21:50:00 +01:00
|
|
|
console_initialized = CONSOLE_Init();
|
1999-02-14 12:15:47 +01:00
|
|
|
|
1999-01-30 13:51:09 +01:00
|
|
|
if (driver.allocColor)
|
|
|
|
return driver.allocColor(color);
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1998-12-02 20:58:08 +01:00
|
|
|
void CONSOLE_ClearScreen()
|
|
|
|
{
|
1999-02-14 12:15:47 +01:00
|
|
|
if (!console_initialized)
|
2000-02-19 21:50:00 +01:00
|
|
|
console_initialized = CONSOLE_Init();
|
1999-02-14 12:15:47 +01:00
|
|
|
|
1998-12-02 20:58:08 +01:00
|
|
|
if (driver.clearScreen)
|
1998-12-25 09:48:56 +01:00
|
|
|
{
|
|
|
|
driver.clearScreen();
|
|
|
|
if (!driver.norefresh)
|
|
|
|
CONSOLE_Refresh();
|
|
|
|
}
|
1998-12-02 20:58:08 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
char CONSOLE_GetCharacter()
|
|
|
|
{
|
1999-02-14 12:15:47 +01:00
|
|
|
if (!console_initialized)
|
2000-02-19 21:50:00 +01:00
|
|
|
console_initialized = CONSOLE_Init();
|
1999-02-14 12:15:47 +01:00
|
|
|
|
1998-12-02 20:58:08 +01:00
|
|
|
/* I'm not sure if we need this really. This is a function that can be
|
|
|
|
accelerated that returns the next *non extended* keystroke */
|
|
|
|
if (driver.getCharacter)
|
|
|
|
return driver.getCharacter();
|
|
|
|
else
|
|
|
|
return (char) 0; /* Sure, this will probably break programs... */
|
|
|
|
}
|
1998-12-25 09:48:56 +01:00
|
|
|
|
|
|
|
void CONSOLE_ResizeScreen(int x, int y)
|
|
|
|
{
|
1999-02-14 12:15:47 +01:00
|
|
|
if (!console_initialized)
|
2000-02-19 21:50:00 +01:00
|
|
|
console_initialized = CONSOLE_Init();
|
1999-02-14 12:15:47 +01:00
|
|
|
|
1998-12-25 09:48:56 +01:00
|
|
|
if (driver.resizeScreen)
|
|
|
|
driver.resizeScreen(x, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CONSOLE_NotifyResizeScreen(int x, int y)
|
|
|
|
{
|
1999-01-03 17:15:39 +01:00
|
|
|
if (driver.notifyResizeScreen)
|
|
|
|
driver.notifyResizeScreen(x, y);
|
|
|
|
}
|
|
|
|
|
1999-01-30 13:51:09 +01:00
|
|
|
void CONSOLE_SetBackgroundColor(int fg, int bg)
|
|
|
|
{
|
1999-02-14 12:15:47 +01:00
|
|
|
if (!console_initialized)
|
2000-02-19 21:50:00 +01:00
|
|
|
console_initialized = CONSOLE_Init();
|
1999-02-14 12:15:47 +01:00
|
|
|
|
1999-01-30 13:51:09 +01:00
|
|
|
if (driver.setBackgroundColor)
|
|
|
|
driver.setBackgroundColor(fg, bg);
|
|
|
|
}
|
|
|
|
|
1999-02-24 12:08:29 +01:00
|
|
|
void CONSOLE_GetBackgroundColor(int *fg, int *bg)
|
|
|
|
{
|
|
|
|
if (!console_initialized)
|
2000-02-19 21:50:00 +01:00
|
|
|
console_initialized = CONSOLE_Init();
|
1999-02-24 12:08:29 +01:00
|
|
|
|
|
|
|
if (driver.getBackgroundColor)
|
|
|
|
driver.getBackgroundColor(fg, bg);
|
|
|
|
}
|
|
|
|
|
1999-01-03 17:15:39 +01:00
|
|
|
void CONSOLE_WriteRawString(char *str)
|
|
|
|
{
|
1999-02-14 12:15:47 +01:00
|
|
|
if (!console_initialized)
|
2000-02-19 21:50:00 +01:00
|
|
|
console_initialized = CONSOLE_Init();
|
1999-02-14 12:15:47 +01:00
|
|
|
|
1999-01-03 17:15:39 +01:00
|
|
|
/* This is a special function that is only for internal use and
|
|
|
|
does not actually call any of the console drivers. It's
|
|
|
|
primary purpose is to provide a way for higher-level drivers
|
|
|
|
to write directly to the underlying terminal without worry that
|
|
|
|
there will be any retranslation done by the assorted drivers. Care
|
|
|
|
should be taken to ensure that this only gets called when the thing
|
|
|
|
written does not actually produce any output or a CONSOLE_Redraw()
|
|
|
|
is called immediately afterwards.
|
|
|
|
CONSOLE_Redraw() is not yet implemented.
|
|
|
|
*/
|
|
|
|
fprintf(driver.console_out, "%s", str);
|
1998-12-25 09:48:56 +01:00
|
|
|
}
|
|
|
|
|
1999-02-14 12:15:47 +01:00
|
|
|
/* This function is only at the CONSOLE level. */
|
|
|
|
/* Admittably, calling the variable norefresh might be a bit dumb...*/
|
|
|
|
void CONSOLE_SetRefresh(int setting)
|
|
|
|
{
|
|
|
|
if (setting)
|
|
|
|
driver.norefresh = FALSE;
|
|
|
|
else
|
|
|
|
driver.norefresh = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This function is only at the CONSOLE level. */
|
|
|
|
int CONSOLE_GetRefresh()
|
|
|
|
{
|
|
|
|
if (driver.norefresh)
|
|
|
|
return FALSE;
|
|
|
|
else
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1998-12-25 09:48:56 +01:00
|
|
|
/* Utility functions... */
|
|
|
|
|
|
|
|
int pop_driver(char **drivers, char **single, int *length)
|
|
|
|
{
|
|
|
|
/* Take the string in drivers and extract the first "driver" entry */
|
|
|
|
/* Advance the pointer in drivers to the next entry, put the origional
|
|
|
|
pointer in single, and put the length in length. */
|
|
|
|
/* Return TRUE if we found one */
|
|
|
|
|
|
|
|
if (!*drivers)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
*single = *drivers;
|
|
|
|
*length = 0;
|
|
|
|
|
|
|
|
while ((*drivers[0] != NULL) && (*drivers[0] != '+'))
|
|
|
|
{
|
|
|
|
(*drivers)++;
|
|
|
|
(*length)++;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (*drivers[0] == '+')
|
|
|
|
(*drivers)++;
|
|
|
|
|
|
|
|
if (*length)
|
|
|
|
return TRUE;
|
|
|
|
else
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
}
|