Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/src/ui/ui-drv/win32/ui_win32.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui/ui-drv/win32/ui_win32.c')
-rw-r--r--src/ui/ui-drv/win32/ui_win32.c1886
1 files changed, 1886 insertions, 0 deletions
diff --git a/src/ui/ui-drv/win32/ui_win32.c b/src/ui/ui-drv/win32/ui_win32.c
new file mode 100644
index 0000000..fff810c
--- /dev/null
+++ b/src/ui/ui-drv/win32/ui_win32.c
@@ -0,0 +1,1886 @@
+/* This file actually implements three drivers (win32 and DirectX
+ windowed/fullscreen) drivers, because they have a lot of common stuff. */
+#include <config.h>
+#ifdef WIN32_DRIVER
+#define _WIN32_WINNT 0x0501 /* Enable access to Windows XP APIs */
+#include <windows.h>
+#ifdef HTML_HELP
+#include <htmlhelp.h>
+#endif
+#ifdef DDRAW_DRIVER
+#include <ddraw.h>
+#endif
+#include <malloc.h>
+#include <string.h>
+#include <stdio.h>
+#include <xmenu.h>
+#include <xerror.h>
+#include "ui.h"
+#include "ui_win32.h"
+#include "resource.h"
+#include "xio.h"
+#include <cursor.h>
+
+#define MAXRESOLUTIONS 256
+#define DXWIDTH 320
+#define DXHEIGHT 200
+#define DXBPP 8
+#define WWIDTH (480+4*48)
+#define WHEIGHT (360+4*36)
+
+#define DXFULLSCREEN 1
+#define DXWINDOWED 2
+
+#define MOUSEWIDTH 16
+#define MOUSEHEIGHT 16
+
+#ifdef HAVE_GETTEXT
+
+#include <libintl.h>
+
+#include <locale.h>
+
+#else
+
+#define gettext(STRING) STRING
+
+#endif
+
+
+
+HINSTANCE hInstance;
+HWND hWnd;
+CONST char *helptopic = "main";
+
+struct ui_driver win32_driver;
+struct ui_driver dxw_driver, dxf_driver;
+
+static int initialized = 0, needredraw = 0;
+
+static char *helpname = NULL;
+
+/* This variables are used by drivers in initializetion */
+static int windowpos;
+static CONST char *size = "520x430";
+static CONST char *dxsize = "320x200x8";
+
+
+/* Display information */
+static int displayX, displayY, bitDepth;
+static int lineSize;
+static int fontWidth, fontHeight;
+static HPALETTE hPalette = NULL;
+static char *buffer1;
+static char *buffer2;
+static int currentbuff = 0;
+static BITMAPINFO *bmp = NULL;
+
+/* Mouse */
+static int mouseX, mouseY, mouseButtons = 0;
+static int captured = 0, tmpcaptured = 0;
+
+/* Keyboard state */
+static int altPressed;
+static int arrowsPressed;
+
+/* WindowProc comunication variables */
+static BOOL closeFlag;
+static int resized = 0;
+static int active = 1;
+
+/* Curent class information */
+static HICON hIcon;
+static HICON hIconSm;
+static HFONT hFont = NULL;
+
+/* DirectX stuff */
+#ifdef DDRAW_DRIVER
+int directX = 0;
+static LPDIRECTDRAWPALETTE dxPalette = NULL;
+static LPDIRECTDRAW lpDD = NULL;
+static LPDIRECTDRAW2 lpDD2 = NULL;
+static LPDIRECTDRAWSURFACE lpSurfaces[2], BackSurface[2];
+static DDSURFACEDESC surface[2];
+static CONST char *mousepointer = mouse_pointer_data;
+static char *storeddata = NULL;
+static HMODULE hModule = NULL;
+static int oldmouseX, oldmouseY;
+#else
+#define directX 0
+#endif
+static PUCHAR backpalette[256][4];
+static HMODULE hModule2;
+static RECT rcWindow;
+static RECT rcViewport;
+static RECT rcScreen;
+static int MyHelpMsg;
+/*clipboard*/
+static WORD clipboard_format;
+
+/* forward declarations */
+#ifdef DDRAW_DRIVER
+static void DeInitDD(void);
+static void PaintDD(void);
+static void UpdateMouseDD(void);
+#endif
+static void Paint(HDC hDC);
+static void CalculateBITMAPINFO(void);
+static void win32_display(void);
+static void DeInitWindow(void);
+
+#ifdef DDRAW_DRIVER
+ /* FIXME: In windowed mode we don't support 8bpp yet! */
+#define DXSUPPORTEDDEPTH(fullscreen,depth) \
+ (!(depth < 8 || (!fullscreen && depth != 16 && depth !=24 && depth != 32)))
+
+static char *store(char *data, int depth, int lpitch, int width,
+ int height, int xpos, int ypos)
+{
+ int d = depth / 8;
+ char *store = malloc(d * MOUSEWIDTH * MOUSEHEIGHT);
+ int y;
+ if (xpos + MOUSEWIDTH > width)
+ xpos = width - MOUSEWIDTH;
+ if (ypos + MOUSEHEIGHT > height)
+ ypos = height - MOUSEHEIGHT;
+ if (xpos < 0)
+ xpos = 0;
+ if (ypos < 0)
+ ypos = 0;
+ for (y = 0; y < MOUSEHEIGHT; y++)
+ memcpy(store + d * MOUSEWIDTH * y,
+ data + xpos * d + (ypos + y) * lpitch, MOUSEWIDTH * d);
+ return store;
+}
+
+static void
+restore(char *data, CONST char *store, int depth, int lpitch, int width,
+ int height, int xpos, int ypos)
+{
+ int y;
+ int d = depth / 8;
+ if (xpos + MOUSEWIDTH > width)
+ xpos = width - MOUSEWIDTH;
+ if (ypos + MOUSEHEIGHT > height)
+ ypos = height - MOUSEHEIGHT;
+ if (xpos < 0)
+ xpos = 0;
+ if (ypos < 0)
+ ypos = 0;
+ for (y = 0; y < MOUSEHEIGHT; y++)
+ memcpy(data + xpos * d + (ypos + y) * lpitch,
+ store + d * MOUSEWIDTH * y, MOUSEWIDTH * d);
+}
+
+static void
+drawmouse(char *data, CONST char *mouse, int depth, int lpitch, int width,
+ int height, int xpos, int ypos)
+{
+ int x, y, z, c;
+ int d = depth / 8;
+ for (y = 0; y < MOUSEWIDTH; y++)
+ for (x = 0; x < MOUSEWIDTH; x++)
+ if (mouse[x + MOUSEWIDTH * y] && x + xpos > 0
+ && (x + xpos) < width && y + ypos > 0
+ && y + ypos < height) {
+ c = mouse[x + MOUSEWIDTH * y] == 2 ? (d ==
+ 1 ? 1 : 255) : 0;
+ for (z = 0; z < d; z++)
+ data[z + d * (x + xpos) + (y + ypos) * lpitch] = c;
+ }
+}
+#endif
+static void getdimens(float *width, float *height)
+{
+ HDC hDC = GetDC(hWnd);
+ *width = GetDeviceCaps(hDC, HORZSIZE) / 10.0;
+ *height = GetDeviceCaps(hDC, VERTSIZE) / 10.0;
+ if (*width > 100 || *width < 1)
+ *width = 29.0;
+ if (*height > 100 || *height < 1)
+ *height = 21.0;
+ ReleaseDC(hWnd, hDC);
+}
+
+static void getres(float *width, float *height)
+{
+ HDC hDC = GetDC(hWnd);
+ *width = 2.54 / GetDeviceCaps(hDC, LOGPIXELSX);
+ *height = 2.54 / GetDeviceCaps(hDC, LOGPIXELSY);
+ ReleaseDC(hWnd, hDC);
+}
+
+/******************************************************************************
+ Win32 driver helper routines
+ */
+
+static LRESULT CALLBACK WindowProc(HWND hWnd, // handle to window
+ UINT uMsg, // message identifier
+ WPARAM wParam, // first message parameter
+ LPARAM lParam // second message parameter
+ )
+{
+ PAINTSTRUCT paintStruct;
+ HDC hDC;
+ if (uMsg == (unsigned int) MyHelpMsg) {
+ win32_help(NULL, helptopic);
+ return 0;
+ }
+ switch (uMsg) {
+ case WM_COMMAND:
+ win32_pressed(wParam);
+ break;
+ case WM_SIZE:
+ // resize window
+ if (directX == DXFULLSCREEN)
+ return 0;
+ if (LOWORD(lParam) == 0 && HIWORD(lParam) == 0) {
+ active = 0;
+ break;
+ } /*Minimized window */
+ active = 1;
+ if (displayX != LOWORD(lParam) || displayY != HIWORD(lParam))
+ resized = 1;
+ displayX = LOWORD(lParam);
+ displayY = HIWORD(lParam);
+ break;
+ case WM_DISPLAYCHANGE:
+ if (directX == DXFULLSCREEN)
+ return 0;
+ mouseButtons = 0;
+ resized = 1;
+ hDC = GetDC(hWnd);
+ bitDepth = GetDeviceCaps(hDC, BITSPIXEL);
+ ReleaseDC(hWnd, hDC);
+ break;
+ case WM_CLOSE:
+ // close window
+ closeFlag = TRUE;
+ return 0;
+ case WM_MOUSEMOVE:
+ case WM_LBUTTONUP:
+ case WM_LBUTTONDOWN:
+ case WM_RBUTTONUP:
+ case WM_RBUTTONDOWN:
+ case WM_MBUTTONUP:
+ case WM_MBUTTONDOWN:
+ // handle mouse move and mouse buttons
+ mouseButtons = wParam;
+ if (!captured) {
+ if (mouseButtons && !tmpcaptured)
+ SetCapture(hWnd), tmpcaptured = 1;
+ if (!mouseButtons && tmpcaptured)
+ ReleaseCapture(), tmpcaptured = 0;
+ }
+ mouseX = (short) LOWORD(lParam);
+ mouseY = (short) HIWORD(lParam);
+#ifdef DDRAW_DRIVER
+ if (directX == DXFULLSCREEN) {
+ POINT p;
+ GetCursorPos(&p);
+ mouseX = p.x;
+ mouseY = p.y;
+ UpdateMouseDD();
+ }
+#endif
+ break;
+ case WM_PAINT:
+ // redraw screen
+ if (directX == DXFULLSCREEN)
+ return 0;
+ needredraw = 1;
+ if (GetUpdateRect(hWnd, NULL, FALSE)) {
+ HDC hDC = BeginPaint(hWnd, &paintStruct);
+ if (hDC) {
+#ifdef DDRAW_DRIVER
+ if (directX)
+ PaintDD();
+ else
+#endif
+ Paint(hDC);
+ EndPaint(hWnd, &paintStruct);
+ }
+ }
+ return 0;
+ case WM_QUERYNEWPALETTE:
+ // windows calls this when window is reactivated.
+ if (directX == DXFULLSCREEN)
+ return 0;
+ hDC = GetDC(hWnd);
+#ifdef DDRAW_DRIVER
+ if (directX == DXWINDOWED) {
+ if (dxPalette) {
+ IDirectDrawSurface_SetPalette(lpSurfaces[0], dxPalette);
+ IDirectDrawPalette_SetEntries(dxPalette, 0, 0, 255,
+ (PALETTEENTRY *)
+ backpalette);
+ }
+ } else
+#endif
+ {
+ SelectPalette(hDC, hPalette, FALSE);
+ RealizePalette(hDC);
+ }
+ ReleaseDC(hWnd, hDC);
+ return TRUE;
+ case WM_MOVE:
+ if (directX != DXFULLSCREEN) {
+ GetWindowRect(hWnd, &rcWindow);
+ GetClientRect(hWnd, &rcViewport);
+ GetClientRect(hWnd, &rcScreen);
+ ClientToScreen(hWnd, (POINT *) & rcScreen.left);
+ ClientToScreen(hWnd, (POINT *) & rcScreen.right);
+ }
+ break;
+ case WM_SETCURSOR:
+ if (directX == DXFULLSCREEN) {
+ SetCursor(NULL);
+ return TRUE;
+ }
+ break;
+#ifdef DDRAW_DRIVER
+ case WM_ACTIVATEAPP:
+ {
+ int oldactive = active;
+ mouseButtons = 0;
+ if (directX == DXFULLSCREEN) {
+ needredraw = 1;
+ active = (wParam == WA_ACTIVE)
+ || (wParam == WA_CLICKACTIVE) /*(BOOL) wParam */ ;
+ PaintDD();
+ if (!oldactive && active && captured)
+ SetCursor(NULL), SetCapture(hWnd);
+ if (oldactive && !active && captured)
+ ReleaseCapture();
+ return 0L;
+ }
+ }
+#endif
+ break;
+ }
+ return DefWindowProc(hWnd, uMsg, wParam, lParam);
+}
+
+/*Create Xaos Window. It is either used for normal window mode or
+ as basis for DirectX */
+static int InitWindow(void)
+{
+ int width = CW_USEDEFAULT, height = CW_USEDEFAULT;
+ int xpos = CW_USEDEFAULT, ypos = CW_USEDEFAULT;
+ LOGPALETTE *logPalette;
+ WNDCLASS wndClass;
+ LOGFONT logFont;
+ ATOM a;
+ HDC hDC;
+ TEXTMETRIC textMetric;
+ HGLOBAL oldFont;
+ RECT r;
+ closeFlag = FALSE;
+
+ altPressed = arrowsPressed = 0;
+ if (hIcon == NULL)
+ hIcon = LoadIcon(hInstance, "BIG");
+ mouseButtons = 0;
+ mouseX = 0;
+ mouseY = 0;
+ {
+ static FARPROC proc;
+ if (hModule2 == NULL) {
+ hModule2 = LoadLibrary("user32");
+ proc = GetProcAddress(hModule2, "RegisterClassExA");
+ }
+ if (proc != NULL) {
+ WNDCLASSEX ExWndClass;
+ memset(&ExWndClass, 0, sizeof(WNDCLASSEX));
+ if (hIconSm == NULL)
+ hIconSm = LoadIcon(hInstance, "SMALL");
+ ExWndClass.hIconSm = hIconSm;
+ memset(&ExWndClass, 0, sizeof(WNDCLASSEX));
+ ExWndClass.style = CS_OWNDC;
+ ExWndClass.cbSize = sizeof(WNDCLASSEX);
+ ExWndClass.lpfnWndProc = WindowProc;
+ ExWndClass.hInstance = hInstance;
+ ExWndClass.hIcon = hIcon;
+ ExWndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
+ ExWndClass.lpszClassName = "XaosWindow";
+ ExWndClass.hbrBackground =
+ (HBRUSH) GetStockObject(BLACK_BRUSH);
+ a = (ATOM) proc(&ExWndClass);
+ } else {
+ memset(&wndClass, 0, sizeof(WNDCLASS));
+ wndClass.style = CS_OWNDC;
+ wndClass.lpfnWndProc = WindowProc;
+ wndClass.hInstance = hInstance;
+ wndClass.hIcon = hIcon;
+ wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wndClass.lpszClassName = "XaosWindow";
+ wndClass.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);
+ a = RegisterClass(&wndClass);
+ }
+ }
+ if (!a) {
+ x_error("Unable to create windows class");
+ return 0;
+ }
+
+ /* First time use defaut size, otherwise use saved sizes */
+ if (sscanf(size, "%ix%ix", &width, &height) != 2) {
+ width = WWIDTH;
+ height = WHEIGHT;
+ }
+ if (windowpos) {
+ xpos = rcWindow.left;
+ ypos = rcWindow.top;
+ width = rcWindow.right - rcWindow.left;
+ height = rcWindow.bottom - rcWindow.top;
+ }
+
+ /* create main window */
+ if (directX == DXFULLSCREEN)
+ hWnd =
+ CreateWindowEx(WS_EX_TOPMOST, "XaoSWindow", "XaoS", WS_POPUP,
+ 0, 0, GetSystemMetrics(SM_CXSCREEN),
+ GetSystemMetrics(SM_CYSCREEN), NULL, NULL,
+ hInstance, NULL);
+ else
+
+ hWnd = CreateWindowEx(WS_EX_CLIENTEDGE, "XaoSWindow", "XaoS",
+ WS_OVERLAPPEDWINDOW | WS_EX_LEFTSCROLLBAR,
+ xpos, ypos, width, height, NULL, NULL,
+ hInstance, NULL);
+
+ if (!hWnd) {
+ x_error("Unable to create app window");
+ return 0;
+ }
+
+ clipboard_format = RegisterClipboardFormat("image/x-xaos.position");
+
+
+ /* create font */
+ memset(&logFont, 0, sizeof(LOGFONT));
+ hDC = CreateDC("DISPLAY", NULL, NULL, NULL);
+ logFont.lfHeight = -MulDiv(12, GetDeviceCaps(hDC, LOGPIXELSY), 72);
+ logFont.lfWeight = FW_NORMAL;
+ logFont.lfPitchAndFamily = FIXED_PITCH;
+ strcpy(logFont.lfFaceName, "Courier");
+
+ hFont = CreateFontIndirect(&logFont);
+ oldFont = SelectObject(hDC, hFont);
+ GetTextMetrics(hDC, &textMetric);
+ SelectObject(hDC, oldFont);
+ DeleteDC(hDC);
+
+ fontHeight = textMetric.tmHeight;
+ fontWidth = textMetric.tmAveCharWidth;
+
+ ShowWindow(hWnd, SW_NORMAL);
+
+ GetClientRect(hWnd, &r);
+ displayX = r.right;
+ displayY = r.bottom;
+
+ /* create palette */
+ CalculateBITMAPINFO(); /* calculate BITMAPINFO structure */
+ logPalette = malloc(sizeof(LOGPALETTE) + 4 * 256);
+ logPalette->palVersion = 0x300;
+ logPalette->palNumEntries = 256;
+ memcpy(logPalette->palPalEntry, bmp->bmiColors, 4 * 256);
+ hPalette = CreatePalette(logPalette);
+ free(logPalette);
+
+ /* select and realize palette */
+ hDC = GetDC(hWnd);
+ SelectPalette(hDC, hPalette, FALSE);
+ RealizePalette(hDC);
+ ReleaseDC(hWnd, hDC);
+
+ // increase priority of XaoS
+ SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
+
+ MyHelpMsg = RegisterWindowMessage(HELPMSGSTRING);
+
+ return 1;
+}
+
+static void DeInitWindow()
+{
+ if (tmpcaptured)
+ ReleaseCapture();
+ if (directX != DXFULLSCREEN)
+ windowpos = 1, GetWindowRect(hWnd, &rcWindow);
+ /* normalize priority */
+ SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
+ if (helpname)
+ WinHelp(hWnd, helpname, HELP_QUIT, 0), free(helpname), helpname =
+ NULL;
+
+ /* destroy windows and other objects */
+ DeleteObject(hFont);
+ DestroyWindow(hWnd);
+ UnregisterClass("XaosWindow", hInstance);
+ if (bmp) {
+ free(bmp);
+ bmp = NULL;
+ }
+ if (hModule2 != NULL)
+ FreeLibrary(hModule2);
+ hModule2 = NULL;
+ win32_uninitializewindows();
+}
+
+/* Display buffer to screen */
+static void Paint(HDC hDC)
+{
+ if (!initialized || !buffer1)
+ return;
+ StretchDIBits(hDC, 0, 0, displayX, displayY,
+ 0, 0, displayX, displayY,
+ (currentbuff == 0) ? buffer1 : buffer2,
+ bmp, DIB_RGB_COLORS, SRCCOPY);
+ needredraw = 0;
+}
+
+
+
+static int Init(void)
+{
+ HDC hDC;
+ buffer1 = buffer2 = NULL;
+
+ // get bit depth
+ hDC = CreateDC("DISPLAY", NULL, NULL, NULL);
+ bitDepth = GetDeviceCaps(hDC, BITSPIXEL);
+ if (bitDepth < 8)
+ bitDepth = 16;
+ if (bitDepth < 10)
+ bitDepth = 8;
+ if (bitDepth >= 10 && bitDepth < 20)
+ bitDepth = 16;
+ if (bitDepth >= 20 && bitDepth < 28)
+ bitDepth = 24;
+ if (bitDepth >= 32 && bitDepth < 32)
+ bitDepth = 32;
+ DeleteDC(hDC);
+
+ // create windows and other objects
+ if (!InitWindow())
+ return 0;
+
+ CalculateBITMAPINFO(); /* calculate BITMAPINFO structure */
+
+
+ return 1;
+}
+
+static void getmouse(int *mx, int *my, int *mb)
+{
+ *mb = 0;
+ if (mouseButtons & MK_LBUTTON)
+ *mb |= 256;
+ if (mouseButtons & MK_MBUTTON)
+ *mb |= 512;
+ if (mouseButtons & MK_RBUTTON)
+ *mb |= 1024;
+ *mx = mouseX;
+ *my = mouseY;
+}
+
+static void
+Processevents(int wait, int *mx, int *my, int *mb, int *k, int *c)
+{
+ MSG msg;
+ int r;
+ if (wait) {
+ // wait for message if in wait mode
+ r = GetMessage(&msg, hWnd, 0, 0);
+ wait = 0;
+ } else {
+ // don't wait for message
+ r = PeekMessage(&msg, hWnd, 0, 0, PM_REMOVE);
+ }
+#if 0
+ if (needredraw) {
+ if (directX)
+ PaintDD();
+ else
+ win32_display();
+ }
+#endif
+ if (r > 0) {
+ if (msg.message == WM_CHAR) {
+ // ascii char
+ *c = msg.wParam;
+ }
+ if (msg.message == WM_KEYUP)
+ switch (msg.wParam) {
+ case VK_MENU:
+ altPressed = 0;
+ break;
+ case VK_UP:
+ arrowsPressed &= ~4;
+ break;
+ case VK_DOWN:
+ arrowsPressed &= ~8;
+ break;
+ case VK_LEFT:
+ arrowsPressed &= ~1;
+ break;
+ case VK_RIGHT:
+ arrowsPressed &= ~2;
+ break;
+ }
+ if (msg.message == WM_KEYDOWN) {
+ // any key
+ switch (msg.wParam) {
+ case VK_MENU:
+ /*x_message("Alt"); */
+ altPressed = 1;
+ break;
+ case VK_UP:
+ *c = UIKEY_UP;
+ arrowsPressed |= 4;
+ break;
+ case VK_DOWN:
+ *c = UIKEY_DOWN;
+ arrowsPressed |= 8;
+ break;
+ case VK_LEFT:
+ *c = UIKEY_LEFT;
+ arrowsPressed |= 1;
+ break;
+ case VK_RIGHT:
+ *c = UIKEY_RIGHT;
+ arrowsPressed |= 2;
+ break;
+ case VK_ESCAPE:
+ *c = UIKEY_ESC;
+ break;
+ case VK_BACK:
+ *c = UIKEY_BACKSPACE;
+ break;
+ case VK_TAB:
+ *c = UIKEY_TAB;
+ break;
+ case VK_HOME:
+ *c = UIKEY_HOME;
+ break;
+ case VK_END:
+ *c = UIKEY_END;
+ break;
+ case VK_PRIOR:
+ *c = UIKEY_PGUP;
+ break;
+ case VK_NEXT:
+ *c = UIKEY_PGDOWN;
+ break;
+#ifdef DDRAW_DRIVER
+ case VK_RETURN:
+ /*x_message("Enter %i",altPressed); */
+ if (altPressed) {
+ HDC hDC;
+ CONST char *cmd;
+ CONST menuitem *item;
+ if (directX == DXFULLSCREEN) {
+ int depth;
+ cmd = "dX-windowed";
+ hDC = CreateDC("DISPLAY", NULL, NULL, NULL);
+ depth = GetDeviceCaps(hDC, BITSPIXEL);
+ DeleteDC(hDC);
+ if (!DXSUPPORTEDDEPTH(0, depth))
+ cmd = "win32";
+ } else {
+ cmd = "dX-fullscreen";
+ }
+ item = menu_findcommand(cmd);
+ ui_menuactivate(item, NULL);
+ }
+ break;
+#endif
+ }
+ }
+ // forward messages to window
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ getmouse(mx, my, mb); // get mouse position
+
+ *k = arrowsPressed;
+
+ if (closeFlag)
+ *c = -2; // force quit if so requested
+
+}
+
+// calculate BITMAPINFO structure. It is used to copy bitmaps
+static void CalculateBITMAPINFO()
+{
+ int i;
+ if (!bmp)
+ bmp = (BITMAPINFO *) malloc(sizeof(BITMAPINFOHEADER) + 4 * 256);
+
+ memset(bmp, 0, sizeof(BITMAPINFOHEADER));
+ bmp->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bmp->bmiHeader.biWidth = displayX;
+ bmp->bmiHeader.biHeight = -displayY;
+ bmp->bmiHeader.biPlanes = 1;
+ bmp->bmiHeader.biBitCount = bitDepth;
+
+ // create default palette
+ for (i = 0; i < 256; i++) {
+ bmp->bmiColors[i].rgbRed = i;
+ bmp->bmiColors[i].rgbGreen = i;
+ bmp->bmiColors[i].rgbBlue = i;
+ }
+}
+
+#ifdef DDRAW_DRIVER
+
+/**************************************************************************************
+ DirectDraw driver helper routines
+ */
+static char *resstr[MAXRESOLUTIONS];
+static struct resolutions {
+ int width, height;
+} ressize[MAXRESOLUTIONS];
+static int nresolutions;
+/* callback for DirectX resolutions */
+static HRESULT WINAPI
+EnumModesCallback(LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext)
+{
+ if (nresolutions < MAXRESOLUTIONS)
+ if (lpDDSurfaceDesc->ddpfPixelFormat.u1.dwRGBBitCount == 8 ||
+ lpDDSurfaceDesc->ddpfPixelFormat.u1.dwRGBBitCount == 16 ||
+ lpDDSurfaceDesc->ddpfPixelFormat.u1.dwRGBBitCount == 24 ||
+ lpDDSurfaceDesc->ddpfPixelFormat.u1.dwRGBBitCount == 32) {
+ int i;
+ char s[20];
+ for (i = 0; i < nresolutions; i++)
+ if ((int) ressize[i].width ==
+ (int) lpDDSurfaceDesc->dwWidth
+ && (int) ressize[i].height ==
+ (int) lpDDSurfaceDesc->dwHeight)
+ return DDENUMRET_OK;
+ ressize[nresolutions].width = lpDDSurfaceDesc->dwWidth;
+ ressize[nresolutions].height = lpDDSurfaceDesc->dwHeight;
+ sprintf(s, "%ix%i", lpDDSurfaceDesc->dwWidth,
+ lpDDSurfaceDesc->dwHeight);
+ resstr[nresolutions] = strdup(s);
+ nresolutions++;
+ }
+ return DDENUMRET_OK;
+}
+
+typedef HRESULT WINAPI(*ddrawcreateptr) (GUID FAR * lpGUID,
+ LPDIRECTDRAW FAR * lplpDD,
+ IUnknown FAR * pUnkOuter);
+static ddrawcreateptr DirectDrawCreatePtr;
+
+static int ResizeDD(int fullscreen)
+{
+ HRESULT ddrval;
+ DDSURFACEDESC ddsd;
+ /*DDCAPS2 ddscaps; */
+ LPDIRECTDRAWCLIPPER pClipper;
+ int dxwidth;
+ int dxheight;
+ int dxbpp;
+
+ // free DirectX objects
+ if (lpSurfaces[0])
+ IDirectDrawSurface_Release(lpSurfaces[0]);
+ lpSurfaces[0] = NULL;
+ if (dxPalette)
+ IDirectDrawPalette_Release(dxPalette);
+ dxPalette = NULL;
+ /* Set cooperative level */
+ ddrval = IDirectDraw2_SetCooperativeLevel(lpDD2, hWnd,
+ fullscreen
+ ? (DDSCL_FULLSCREEN |
+ DDSCL_EXCLUSIVE |
+ DDSCL_ALLOWREBOOT)
+ : DDSCL_NORMAL);
+ if (ddrval != DD_OK) {
+ DeInitDD();
+ x_error("Failed to set cooperative level");
+ return 0;
+ }
+
+ if (fullscreen) {
+ if (sscanf(dxsize, "%ix%ix%i", &dxwidth, &dxheight, &dxbpp) != 3) {
+ dxwidth = DXWIDTH;
+ dxheight = DXHEIGHT;
+ dxbpp = DXBPP;
+ }
+ displayX = dxwidth;
+ displayY = dxheight;
+ bitDepth = dxbpp;
+ if (bitDepth < 10)
+ bitDepth = 8;
+ if (bitDepth >= 10 && bitDepth < 20)
+ bitDepth = 16;
+ if (bitDepth >= 20 && bitDepth < 28)
+ bitDepth = 24;
+ if (bitDepth >= 32 && bitDepth < 32)
+ bitDepth = 32;
+
+ /* set resolution and bit depth */
+ ddrval =
+ IDirectDraw2_SetDisplayMode(lpDD2, displayX, displayY,
+ bitDepth, 0, 0);
+ if (ddrval != DD_OK) {
+ /* The display mode cannot be changed.
+ The mode is either not supported or
+ another application has exclusive mode.
+
+ Try 320x200x256 and 640x480x256 modes before giving up */
+ displayX = 320;
+ displayY = 200;
+ bitDepth = 8;
+ ddrval =
+ IDirectDraw2_SetDisplayMode(lpDD2, displayX, displayY,
+ bitDepth, 0, 0);
+ if (ddrval != DD_OK) {
+ displayY = 240;
+ if (ddrval != DD_OK) {
+ displayX = 640;
+ displayY = 480;
+ ddrval =
+ IDirectDraw2_SetDisplayMode(lpDD2, displayX,
+ displayY, bitDepth, 0,
+ 0);
+ if (ddrval != DD_OK) {
+ /* Bad luck... give up. */
+ DeInitDD();
+ return 0;
+ }
+ }
+ }
+ }
+ SetRect(&rcViewport, 0, 0, displayX, displayY);
+ rcScreen = rcViewport;
+ } else {
+ /* Get the dimensions of the viewport and screen bounds */
+ GetClientRect(hWnd, &rcViewport);
+ GetClientRect(hWnd, &rcScreen);
+ ClientToScreen(hWnd, (POINT *) & rcScreen.left);
+ ClientToScreen(hWnd, (POINT *) & rcScreen.right);
+ /*bitDepth = GetDeviceCaps (hDC, BITSPIXEL); */
+
+ /* Create clipper object for window */
+ ddrval = IDirectDraw_CreateClipper(lpDD, 0, &pClipper, NULL);
+ if (ddrval != DD_OK) {
+ DeInitDD();
+ x_error("Failed to create clipper object");
+ return 0;
+ }
+ /* Asociate it */
+ IDirectDrawClipper_SetHWnd(pClipper, 0, hWnd);
+ }
+ /* Create the primary surface with one back buffer */
+ CalculateBITMAPINFO(); // calculate BITMAPINFO structure
+
+ memset(&ddsd, 0, sizeof(ddsd));
+ ddsd.dwSize = sizeof(ddsd);
+ ddsd.dwFlags = DDSD_CAPS;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+
+ ddrval = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpSurfaces[0], NULL);
+ if (ddrval != DD_OK) {
+ DeInitDD();
+ x_error("Failed to create flipping surface");
+ return 0;
+ }
+
+ if (!fullscreen) {
+ IDirectDrawSurface_SetClipper(lpSurfaces[0], pClipper);
+ IDirectDrawClipper_Release(pClipper);
+ if (IDirectDrawSurface_GetSurfaceDesc(lpSurfaces[0], &ddsd) !=
+ DD_OK) {
+ DeInitDD();
+ x_error("Failed to get pixel format");
+ return 0;
+ }
+ bitDepth = ddsd.ddpfPixelFormat.u1.dwRGBBitCount;
+ }
+
+ if (bitDepth == 8) {
+ /* create palette */
+ ddrval =
+ IDirectDraw_CreatePalette(lpDD, DDPCAPS_8BIT,
+ (LPPALETTEENTRY) bmp->bmiColors,
+ &dxPalette, NULL);
+ if (ddrval != DD_OK) {
+ DeInitDD();
+ x_error("Failed to create palette");
+ return 0;
+ }
+
+ /* set palette */
+ IDirectDrawSurface_SetPalette(lpSurfaces[0], dxPalette);
+ }
+ if (fullscreen)
+ SetCursor(NULL);
+ needredraw = 1;
+ return 1;
+
+}
+
+/* init DirectX */
+static int InitDD(int fullscreen)
+{
+ HRESULT ddrval;
+ HDC hDC;
+ directX = fullscreen ? DXFULLSCREEN : DXWINDOWED;
+
+ if (!hModule)
+ hModule = LoadLibrary("ddraw");
+ if (!hModule) {
+ /*x_error ("Unable to load DirectX (ddraw.dll)"); */
+ return 0;
+ }
+ /* DirectDraw don't support 16 color modes. Don't even try to initialize
+ it then. Also avoid unsupported bit depths in the windowed driver */
+ hDC = CreateDC("DISPLAY", NULL, NULL, NULL);
+ bitDepth = GetDeviceCaps(hDC, BITSPIXEL);
+ DeleteDC(hDC);
+
+ if (!DXSUPPORTEDDEPTH(fullscreen, bitDepth))
+ return 0;
+
+
+ DirectDrawCreatePtr =
+ (ddrawcreateptr) GetProcAddress(hModule, "DirectDrawCreate");
+ if (!DirectDrawCreatePtr) {
+ x_error
+ ("Unable to get hook DirectDrawCreate in ddraw.dll. Check your DirectX installation");
+ return 0;
+ }
+
+ lpDD = NULL;
+ lpDD2 = NULL;
+ lpSurfaces[0] = NULL;
+ lpSurfaces[1] = NULL;
+ buffer1 = buffer2 = NULL;
+
+ bitDepth = 8;
+
+ InitWindow();
+ UpdateWindow(hWnd);
+ SetFocus(hWnd);
+
+
+ /* contact DirectX */
+ ddrval = DirectDrawCreatePtr(NULL, &lpDD, NULL);
+ if (ddrval != DD_OK) {
+ DeInitDD();
+ x_error("Failed to create DirectDraw object");
+ return 0;
+ }
+
+ /* get IDirectDraw2 interface */
+ ddrval =
+ IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw2,
+ (LPVOID *) & lpDD2);
+ if (ddrval != DD_OK) {
+ DeInitDD();
+ x_error("Failed to get DirectDraw2 object");
+ return 0;
+ }
+ /* enumerate modes */
+#ifdef DDRAW_DRIVER
+ if (!nresolutions && directX == DXFULLSCREEN)
+ IDirectDraw2_EnumDisplayModes(lpDD2, 0, NULL, NULL,
+ EnumModesCallback);
+#endif
+
+
+ if (!ResizeDD(fullscreen))
+ return 0;
+ if (fullscreen) {
+ SetCapture(hWnd); // make sure no other windows get mouse messages
+
+ captured = 1;
+ }
+
+ return 1;
+}
+
+/* uninitialize DirectX */
+static void DeInitDD(void)
+{
+ if (captured)
+ ReleaseCapture(), captured = 0; // free mouse
+
+ // free DirectX objects
+ if (lpSurfaces[0])
+ IDirectDrawSurface_Release(lpSurfaces[0]);
+ lpSurfaces[0] = NULL;
+ if (BackSurface[0])
+ IDirectDrawSurface_Release(BackSurface[0]);
+ BackSurface[0] = NULL;
+ if (BackSurface[1])
+ IDirectDrawSurface_Release(BackSurface[1]);
+ BackSurface[1] = NULL;
+ if (dxPalette)
+ IDirectDrawPalette_Release(dxPalette);
+ dxPalette = NULL;
+ if (lpDD2)
+ IDirectDraw2_Release(lpDD2);
+ lpDD2 = NULL;
+ if (lpDD)
+ IDirectDraw_Release(lpDD);
+ lpDD = NULL;
+ DeInitWindow();
+ if (hModule != NULL)
+ FreeLibrary(hModule), hModule = NULL;
+ hWnd = NULL;
+ directX = 0;
+}
+
+static LRESULT CALLBACK WindowProc(HWND hwnd, // handle to window
+ UINT uMsg, // message identifier
+ WPARAM wParam, // first message parameter
+ LPARAM lParam // second message parameter
+ );
+static void UpdateMouseDD()
+{
+ DDSURFACEDESC m_surface;
+ PUCHAR dst;
+ DWORD ddrval;
+ memset(&m_surface, 0, sizeof(DDSURFACEDESC));
+ m_surface.dwSize = sizeof(DDSURFACEDESC);
+ ddrval = IDirectDrawSurface_Lock(lpSurfaces[0], NULL, &m_surface,
+ DDLOCK_WAIT, NULL);
+ if (ddrval != DD_OK) {
+ return;
+ }
+
+ dst = (PUCHAR) m_surface.lpSurface;
+ if (storeddata) {
+ restore(dst, storeddata, bitDepth, m_surface.u1.lPitch, displayX,
+ displayY, oldmouseX, oldmouseY);
+ free(storeddata);
+ }
+ storeddata =
+ store(dst, bitDepth, m_surface.u1.lPitch, displayX, displayY,
+ mouseX, mouseY);
+ drawmouse(dst, mousepointer, bitDepth, m_surface.u1.lPitch, displayX,
+ displayY, mouseX, mouseY);
+ oldmouseX = mouseX;
+ oldmouseY = mouseY;
+ IDirectDrawSurface_Unlock(lpSurfaces[0], m_surface.lpSurface);
+}
+
+/* Display buffer */
+static void PaintDD()
+{
+ DWORD ddrval;
+ if (!IsWindowVisible(hWnd) || !active || !initialized
+ || !BackSurface[0])
+ return;
+ IDirectDrawSurface_Unlock(BackSurface[0], surface[0].lpSurface);
+ IDirectDrawSurface_Unlock(BackSurface[1], surface[1].lpSurface);
+ if (directX == DXFULLSCREEN) {
+ if (storeddata)
+ free(storeddata), storeddata = NULL;
+ storeddata =
+ store(currentbuff ? buffer2 : buffer1, bitDepth, lineSize,
+ displayX, displayY, mouseX, mouseY);
+ drawmouse(currentbuff ? buffer2 : buffer1, mousepointer, bitDepth,
+ lineSize, displayX, displayY, mouseX, mouseY);
+ ddrval =
+ IDirectDrawSurface_BltFast(lpSurfaces[0], 0, 0,
+ BackSurface[currentbuff], &rcScreen,
+ FALSE);
+ restore(currentbuff ? buffer2 : buffer1, storeddata, bitDepth,
+ lineSize, displayX, displayY, mouseX, mouseY);
+ oldmouseX = mouseX;
+ oldmouseY = mouseY;
+ } else {
+ ddrval = IDirectDrawSurface_Blt(lpSurfaces[0], &rcScreen,
+ BackSurface[currentbuff],
+ &rcViewport, DDBLT_WAIT, NULL);
+ }
+ if (ddrval != DD_OK) {
+ if ((int) ddrval == (int) DDERR_SURFACELOST) {
+ IDirectDrawSurface_Restore(lpSurfaces[0]);
+ IDirectDrawSurface_Restore(BackSurface[0]);
+ IDirectDrawSurface_Restore(BackSurface[1]);
+ ddrval = IDirectDrawSurface_Blt(lpSurfaces[0], &rcScreen,
+ BackSurface[currentbuff],
+ &rcViewport, DDBLT_WAIT, NULL);
+ //if (ddrval == DDERR_SURFACELOST) resized=1; /*We've lost our fractal*/
+ }
+ }
+ ddrval = IDirectDrawSurface_Lock(BackSurface[0], NULL, &surface[0],
+ DDLOCK_WAIT, NULL);
+ ddrval = IDirectDrawSurface_Lock(BackSurface[1], NULL, &surface[1],
+ DDLOCK_WAIT, NULL);
+ if (buffer1 != (char *) surface[0].lpSurface ||
+ buffer2 != (char *) surface[1].lpSurface) {
+ DeInitDD();
+ x_fatalerror
+ ("Unexpected event - buffers moved! Please contact authors!");
+ }
+ needredraw = 0;
+
+}
+#endif
+
+/**************************************************************************************
+ Drivers implementation
+ */
+
+
+
+static void flip_buffers(void)
+{
+ currentbuff ^= 1;
+}
+
+
+static void processevents(int wait, int *mx, int *my, int *mb, int *k)
+{
+ int c = -1;
+ *mb = 0;
+ *k = 0;
+ Processevents(wait, mx, my, mb, k, &c);
+ if (c > -1) {
+ ui_key(c);
+ }
+
+ if (c == -2)
+ ui_quit(); // -2 signals program exit
+
+ if (resized) {
+ ui_resize(); // tell Xaos to resize
+
+ }
+}
+
+static void print(int x, int y, CONST char *text)
+{
+ HDC hDC;
+ static char current[256];
+ char s[256];
+#ifdef DDRAW_DRIVER
+ if (directX == DXFULLSCREEN) {
+ HGLOBAL oldFont;
+ if (IDirectDrawSurface_GetDC(lpSurfaces[0], &hDC) != DD_OK)
+ return;
+ SetTextColor(hDC, 0xffffff);
+ SetBkColor(hDC, 0x000000);
+ oldFont = SelectObject(hDC, hFont);
+ ExtTextOut(hDC, x, y, 0, NULL, text, strlen(text), NULL);
+ SelectObject(hDC, oldFont);
+ IDirectDrawSurface_ReleaseDC(lpSurfaces[0], hDC);
+ return;
+ }
+#endif
+ if (!text[0])
+ strcpy(s, "XaoS");
+ else
+ sprintf(s, "XaoS - %s", text);
+ if (strcmp(current, s))
+ strcpy(current, s), SetWindowText(hWnd, s);
+}
+
+static void mousetype(int type)
+{
+ char *cursor;
+ switch (type) {
+ default:
+ case 0:
+ cursor = IDC_ARROW;
+ break;
+ case 1:
+ cursor = IDC_WAIT;
+ break;
+ case 2:
+ cursor = IDC_NO;
+ break;
+ }
+ SetCursor(LoadCursor(NULL, cursor));
+}
+
+static void set_palette(ui_palette pal1, int start, int end)
+{
+ PUCHAR pal = (PUCHAR) pal1;
+ HDC hDC;
+ int i;
+ // store new palette entries locally
+ memcpy(backpalette + 4 * start, pal, (end - start) * 4);
+ for (i = start; i <= end; i++) {
+ bmp->bmiColors[i].rgbRed = *(pal + 4 * (i - start) + 0);
+ bmp->bmiColors[i].rgbGreen = *(pal + 4 * (i - start) + 1);
+ bmp->bmiColors[i].rgbBlue = *(pal + 4 * (i - start) + 2);
+ bmp->bmiColors[i].rgbReserved = 0;
+ }
+ // update window/screen
+#ifdef DDRAW_DRIVER
+ if (directX) {
+ IDirectDrawPalette_SetEntries(dxPalette, 0, start, end - start + 1,
+ (PALETTEENTRY *) pal);
+ } else
+#endif
+ {
+ SetPaletteEntries(hPalette, start, end - start + 1,
+ (PALETTEENTRY *) pal);
+ hDC = GetDC(hWnd);
+ UnrealizeObject(hPalette);
+ RealizePalette(hDC);
+ ReleaseDC(hWnd, hDC);
+ win32_display();
+ }
+}
+
+static void win32_copy(struct uih_context *uih)
+{
+ char *c = ui_getpos();
+ HANDLE hData = GlobalAlloc(GMEM_DDESHARE, strlen(c) + 1);
+ char *data;
+ if (!hData) {
+ x_error("Out of memory");
+ free(c);
+ return;
+ }
+ if (!(data = GlobalLock(hData))) {
+ x_error("Out of memory");
+ free(c);
+ return;
+ }
+ memcpy(hData, c, strlen(c) + 1);
+ GlobalUnlock(hData);
+ if (OpenClipboard(hWnd)) {
+ EmptyClipboard();
+ SetClipboardData(clipboard_format, hData);
+ }
+ free(c);
+}
+
+static void win32_paste(void)
+{
+ if (OpenClipboard(hWnd)) {
+ HANDLE hClipData;
+ char *text;
+ if (!(hClipData = GetClipboardData(clipboard_format))) {
+ CloseClipboard();
+ return;
+ }
+ if (!(text = GlobalLock(hClipData))) {
+ x_error("Out of memory");
+ CloseClipboard();
+ }
+ ui_loadstr(strdup(text));
+ GlobalUnlock(hClipData);
+ CloseClipboard();
+ }
+}
+
+#define MAX_MENUITEMS_I18N 7
+static menuitem menuitems_i18n[MAX_MENUITEMS_I18N];
+
+int uiw_no_menuitems_i18n, uiw_no_cutpasteitems_i18n;
+
+static menuitem *cutpasteitems;
+static void add_cutpasteitems()
+{
+ // General method (not needed currently):
+ int no_menuitems_i18n = uiw_no_menuitems_i18n; /* This variable must be local. */
+ MENUSEPARATOR_I("edit");
+ MENUNOP_I("edit", NULL, gettext("Copy"), "copy", 0, win32_copy);
+ MENUNOP_I("edit", NULL, gettext("Paste"), "paste", 0, win32_paste);
+ MENUNOP_I("misc", NULL, "Generate .dlg files", "genresources", 0,
+ win32_genresources);
+ MENUSEPARATOR_I("helpmenu");
+ MENUNOP_I("helpmenu", NULL, gettext("About"), "about", 0, AboutBox);
+ no_menuitems_i18n -= uiw_no_menuitems_i18n;
+ cutpasteitems = &(menuitems_i18n[uiw_no_menuitems_i18n]);
+ uiw_no_cutpasteitems_i18n = no_menuitems_i18n;
+ menu_add(cutpasteitems, uiw_no_cutpasteitems_i18n);
+ uiw_no_menuitems_i18n += no_menuitems_i18n;
+
+}
+
+
+static int win32_init(void)
+{
+ int r;
+
+#ifdef DDRAW_DRIVER
+ directX = 0;
+#endif
+ r = Init();
+ if (!r)
+ return r;
+ win32_driver.textwidth = fontWidth;
+ win32_driver.textheight = fontHeight;
+ getres(&win32_driver.width, &win32_driver.height);
+ win32_createrootmenu();
+ uiw_no_menuitems_i18n = 0;
+ add_cutpasteitems();
+ return r;
+}
+
+static void win32_uninitialize(void)
+{
+ DeInitWindow();
+ menu_delete(cutpasteitems, uiw_no_cutpasteitems_i18n);
+}
+
+static void win32_getsize(int *width, int *height)
+{
+ resized = 0;
+ *width = displayX;
+ *height = displayY;
+ switch (bitDepth) {
+ case 8:
+ win32_driver.imagetype = UI_C256;
+ break;
+ case 16:
+ /* Windows seems to always use 15bpp mode */
+ win32_driver.imagetype = UI_TRUECOLOR16;
+ win32_driver.rmask = 31 * 32 * 32;
+ win32_driver.gmask = 31 * 32;
+ win32_driver.bmask = 31;
+ break;
+ case 24:
+ win32_driver.imagetype = UI_TRUECOLOR24;
+ win32_driver.rmask = 0xff0000;
+ win32_driver.gmask = 0x00ff00;
+ win32_driver.bmask = 0x0000ff;
+ break;
+ case 32:
+ win32_driver.imagetype = UI_TRUECOLOR;
+ win32_driver.rmask = 0xff0000;
+ win32_driver.gmask = 0x00ff00;
+ win32_driver.bmask = 0x0000ff;
+ break;
+ }
+ CalculateBITMAPINFO();
+}
+
+
+
+static void win32_display()
+{
+ HDC hDC = GetDC(hWnd);
+ if (IsWindowVisible(hWnd))
+ Paint(hDC);
+ ReleaseDC(hWnd, hDC);
+}
+
+static int win32_alloc_buffers(char **b1, char **b2)
+{
+ currentbuff = 0;
+ // calculate DWORD aligned line length
+ lineSize = displayX * ((bitDepth + 7) / 8);
+ lineSize += 3 - ((lineSize - 1) & 3);
+
+ buffer1 = (char *) malloc(displayY * lineSize);
+ buffer2 = (char *) malloc(displayY * lineSize);
+ *b1 = buffer1;
+ *b2 = buffer2;
+ initialized = 1;
+ return lineSize;
+}
+
+static void win32_free_buffers(char *b1, char *b2)
+{
+ initialized = 0;
+ free(buffer1);
+ free(buffer2);
+ buffer1 = buffer2 = NULL;
+}
+
+static CONST char *CONST dx_depth[] = { "8bpp (256 colors)",
+ "16bpp (65536 colors)",
+ "24bpp (16777216 colors)",
+ "32bpp (16777216 colors)",
+ NULL
+};
+
+#ifdef DDRAW_DRIVER
+static menudialog dx_resdialog[] = {
+ DIALOGCHOICE("Resolution", resstr, 0),
+ DIALOGCHOICE("Depth", dx_depth, 0),
+ {NULL}
+};
+
+static menudialog *dx_resizedialog(struct uih_context *c)
+{
+ int i;
+ switch (bitDepth) {
+ case 8:
+ dx_resdialog[1].defint = 0;
+ break;
+ case 16:
+ dx_resdialog[1].defint = 1;
+ break;
+ case 24:
+ dx_resdialog[1].defint = 2;
+ break;
+ case 32:
+ dx_resdialog[1].defint = 3;
+ }
+ for (i = 0; i < MAXRESOLUTIONS; i++)
+ if (displayX == ressize[i].width && displayY == ressize[i].height) {
+ dx_resdialog[0].defint = i;
+ break;
+ }
+ return dx_resdialog;
+}
+
+static void dx_resize(struct uih_context *c, dialogparam * p)
+{
+ static char s[10];
+ CONST static char *CONST st[] = { "8", "16", "24", "32" };
+ sprintf(s, "%sx%s", resstr[p[0].dint], st[p[1].dint]);
+ dxsize = s;
+ resized = 1;
+ ui_call_resize();
+}
+
+int uiw_no_resizeitems_i18n;
+
+static menuitem *resizeitems;
+
+static void add_resizeitems()
+{
+ // General method, it's needed:
+ int no_menuitems_i18n = uiw_no_menuitems_i18n; /* This variable must be local. */
+ MENUCDIALOG_I("ui", "=", gettext("Resize"), "resize", 0, dx_resize,
+ dx_resizedialog);
+ no_menuitems_i18n -= uiw_no_menuitems_i18n;
+ resizeitems = &(menuitems_i18n[uiw_no_menuitems_i18n]);
+ uiw_no_resizeitems_i18n = no_menuitems_i18n;
+ menu_add(resizeitems, uiw_no_resizeitems_i18n);
+ uiw_no_menuitems_i18n += no_menuitems_i18n;
+
+}
+
+
+static int dx_alloc_buffers(char **b1, char **b2)
+{
+ DWORD ddrval;
+ DDSURFACEDESC ddsd;
+ int i;
+ currentbuff = 0;
+ memset(surface, 0, sizeof(DDSURFACEDESC) * 2);
+ memset(&ddsd, 0, sizeof(DDSURFACEDESC));
+ ddsd.dwSize = sizeof(ddsd);
+ if (IDirectDrawSurface_GetSurfaceDesc(lpSurfaces[0], &ddsd) != DD_OK) {
+ DeInitDD();
+ x_error("Failed to get pixel format");
+ return 0;
+ }
+ for (i = 0; i < 2; i++) {
+ ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
+ ddsd.dwWidth = displayX;
+ ddsd.dwHeight = displayY;
+ ddsd.ddsCaps.dwCaps =
+ DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
+
+ ddrval =
+ IDirectDraw_CreateSurface(lpDD, &ddsd, &BackSurface[i], NULL);
+ if (ddrval != DD_OK) {
+ DeInitDD();
+ x_error("Failed to create back surface");
+ return 0;
+ }
+ }
+ for (i = 0; i < 2; i++) {
+ surface[i].dwSize = sizeof(DDSURFACEDESC);
+ ddrval = IDirectDrawSurface_Lock(BackSurface[i], NULL, surface + i,
+ DDLOCK_WAIT, NULL);
+ if (ddrval != DD_OK) {
+ DeInitDD();
+ x_fatalerror("Failed to lock offscreen surfaces");
+ }
+ }
+ buffer1 = *b1 = (char *) surface[0].lpSurface;
+ buffer2 = *b2 = (char *) surface[1].lpSurface;
+ lineSize = surface[0].u1.lPitch;
+ initialized = 1;
+ return lineSize;
+}
+
+static void dx_free_buffers(char *b1, char *b2)
+{
+ IDirectDrawSurface_Unlock(BackSurface[0], surface[0].lpSurface);
+ IDirectDrawSurface_Unlock(BackSurface[1], surface[1].lpSurface);
+ if (BackSurface[0])
+ IDirectDrawSurface_Release(BackSurface[0]);
+ if (BackSurface[1])
+ IDirectDrawSurface_Release(BackSurface[1]);
+ BackSurface[0] = NULL;
+ BackSurface[1] = NULL;
+ initialized = 0;
+ buffer1 = buffer2 = NULL;
+}
+
+static int dx_imgparams(void)
+{
+ DDSURFACEDESC s;
+ memset(&s, 0, sizeof(s));
+ s.dwSize = sizeof(s);
+ if (IDirectDrawSurface_GetSurfaceDesc(lpSurfaces[0], &s) != DD_OK) {
+ DeInitDD();
+ x_error("Failed to get pixel format");
+ return 0;
+ }
+ switch (s.ddpfPixelFormat.u1.dwRGBBitCount) {
+ case 8:
+ dxw_driver.imagetype = UI_C256;
+ dxf_driver.imagetype = UI_C256;
+ break;
+ case 16:
+ case 15:
+ dxw_driver.imagetype = UI_TRUECOLOR16;
+ dxf_driver.imagetype = UI_TRUECOLOR16;
+ break;
+ case 24:
+ dxw_driver.imagetype = UI_TRUECOLOR24;
+ dxf_driver.imagetype = UI_TRUECOLOR24;
+ break;
+ case 32:
+ dxw_driver.imagetype = UI_TRUECOLOR;
+ dxf_driver.imagetype = UI_TRUECOLOR;
+ break;
+ default:
+ x_fatalerror
+ ("Unsupported bit depth! Only 8bpp, 16bpp, 24bpp and 32bpp modes supported\n");
+ return 0;
+ }
+ dxw_driver.rmask = s.ddpfPixelFormat.u2.dwRBitMask;
+ dxw_driver.gmask = s.ddpfPixelFormat.u3.dwGBitMask;
+ dxw_driver.bmask = s.ddpfPixelFormat.u4.dwBBitMask;
+ dxf_driver.rmask = s.ddpfPixelFormat.u2.dwRBitMask;
+ dxf_driver.gmask = s.ddpfPixelFormat.u3.dwGBitMask;
+ dxf_driver.bmask = s.ddpfPixelFormat.u4.dwBBitMask;
+ dxf_driver.textwidth = fontWidth;
+ dxf_driver.textheight = fontHeight;
+ dxw_driver.textwidth = fontWidth;
+ dxw_driver.textheight = fontHeight;
+ return 1;
+}
+
+static int dxw_init(void)
+{
+ int r;
+
+ r = InitDD(0);
+ if (!r)
+ return r;
+
+ if (!dx_imgparams())
+ return 0;
+ win32_createrootmenu();
+ getres(&dxw_driver.width, &dxw_driver.height);
+ uiw_no_menuitems_i18n = 0;
+ add_cutpasteitems();
+ return r;
+}
+
+static int dxf_init(void)
+{
+ int r;
+
+ getdimens(&dxf_driver.width, &dxf_driver.height);
+ r = InitDD(1);
+ if (!r)
+ return r;
+
+ if (!dx_imgparams())
+ return 0;
+ uiw_no_menuitems_i18n = 0;
+ add_resizeitems();
+ add_cutpasteitems();
+ return r;
+}
+
+
+
+static void dx_uninitialize(void)
+{
+ if (directX == DXFULLSCREEN)
+ menu_delete(resizeitems, uiw_no_resizeitems_i18n);
+ menu_delete(cutpasteitems, uiw_no_cutpasteitems_i18n);
+ DeInitDD();
+}
+
+
+
+
+static void dx_getsize(int *width, int *height)
+{
+ if (resized) {
+ resized = 0;
+ if (!ResizeDD(directX == DXFULLSCREEN)) {
+ DeInitDD();
+ x_fatalerror("Failed to resize");
+ }
+ if (!dx_imgparams()) {
+ DeInitDD();
+ x_fatalerror("Internal program error #34234");
+ }
+ }
+ *width = displayX;
+ *height = displayY;
+ CalculateBITMAPINFO();
+}
+
+static void dx_mousetype(int type)
+{
+ switch (type) {
+ default:
+ case 0:
+ mousepointer = mouse_pointer_data;
+ break;
+ case 1:
+ mousepointer = wait_pointer_data;
+ break;
+ case 2:
+ mousepointer = replay_pointer_data;
+ break;
+ }
+ UpdateMouseDD();
+}
+#endif
+
+void win32_help(struct uih_context *c, CONST char *name)
+{
+#ifdef HTML_HELP
+ FILE *f;
+ char *n;
+ if (helpname == NULL) {
+ if (directX == DXFULLSCREEN)
+ ShowWindow(hWnd, SW_MINIMIZE);
+ n = xio_fixpath("\01\\help\\xaoshelp.chm");
+ if ((f = fopen(n, "r"))) {
+ fclose(f);
+ } else {
+ free(n);
+ n = xio_fixpath("\01\\..\\help\\xaoshelp.chm");
+ if ((f = fopen(n, "r"))) {
+ fclose(f);
+ } else
+ n = strdup("..\\help\\xaoshelp.chm");
+ }
+ helpname = n;
+ }
+ HH_AKLINK link;
+ link.cbStruct = sizeof(HH_AKLINK) ;
+ link.fReserved = FALSE ;
+ link.pszKeywords = name ;
+ link.pszUrl = NULL ;
+ link.pszMsgText = NULL ;
+ link.pszMsgTitle = NULL ;
+ link.pszWindow = NULL ;
+ link.fIndexOnFail = TRUE ;
+
+ if (!HtmlHelp(hWnd, helpname, HH_ALINK_LOOKUP, (DWORD) &link)) {
+ x_error("Could not display help for topic %s from file %s", name, helpname);
+ }
+#else
+ x_error("Help support not included in this executable.");
+#endif
+}
+
+
+static struct params params[] = {
+ {"", P_HELP, NULL, "Win32 driver options:"},
+ {"-size", P_STRING, &size,
+ "Window size in format WIDTHxHEIGHT (320x200)"},
+ {NULL, 0, NULL, NULL}
+};
+
+static struct params dxfparams[] = {
+ {"", P_HELP, NULL, "DirectX fullscreen driver options:"},
+ {"-mode", P_STRING, &dxsize,
+ "Select preffered graphics mode in format WIDTHxHEIGHTxDEPTH (320x200x8)"},
+ {NULL, 0, NULL, NULL}
+};
+
+static struct params dxwparams[] = {
+ {"", P_HELP, NULL, "DirectX windowed driver options:"},
+ {"-size", P_STRING, &size,
+ "Window size in format WIDTHxHEIGHT (320x200)"},
+ {NULL, 0, NULL, NULL}
+};
+
+extern int XaoS_main(int argc, char **argv);
+int STDCALL
+WinMain(HINSTANCE hInstance1,
+ HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
+{
+ static char name0[256];
+ static char *argv[256];
+ int argc = 1;
+ int i;
+
+ GetModuleFileName(hInstance1, name0, 256);
+ /* Allocate everything virtually - be on the safe side */
+ argv[0] = strdup(name0);
+ lpCmdLine = strdup(lpCmdLine);
+
+ for (i = 0; lpCmdLine[i]; i++) {
+ if (lpCmdLine[i] == ' ' || lpCmdLine[i] == '\t')
+ lpCmdLine[i] = 0;
+ else if (!i || !lpCmdLine[i - 1])
+ argv[argc] = lpCmdLine + i, argc++;
+ }
+
+ /* Attach to parent console if available so output will be visible */
+ if (AttachConsole(ATTACH_PARENT_PROCESS)) {
+ /* make sure stdout is not already redirected before redefining */
+ if (_fileno(stdout) == -1 || _get_osfhandle(fileno(stdout)) == -1)
+ freopen("CON", "w", stdout);
+ }
+
+ hInstance = hInstance1;
+ return XaoS_main(argc, argv);
+}
+
+static CONST struct gui_driver win32_gui_driver = {
+ win32_dorootmenu,
+ win32_enabledisable,
+ win32_menu,
+ win32_dialog,
+ win32_help
+};
+
+static CONST struct gui_driver win32_fullscreen_gui_driver = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ win32_help
+};
+
+struct ui_driver win32_driver = {
+ "win32",
+ win32_init,
+ win32_getsize,
+ processevents,
+ getmouse,
+ win32_uninitialize,
+ NULL, // win32_set_color,
+ set_palette,
+ print,
+ win32_display,
+ win32_alloc_buffers,
+ win32_free_buffers,
+ flip_buffers,
+ mousetype,
+ NULL,
+ 16 + 16,
+ 12,
+ params,
+ PIXELSIZE | UPDATE_AFTER_PALETTE,
+ 0.0, 0.0,
+ 0, 0,
+ UI_C256,
+ 0, 256, 255,
+ 0, 0, 0,
+ &win32_gui_driver
+};
+
+#ifdef DDRAW_DRIVER
+struct ui_driver dxw_driver = {
+ "dX-window",
+ dxw_init,
+ dx_getsize,
+ processevents,
+ getmouse,
+ dx_uninitialize,
+ NULL, // dx_set_color,
+ set_palette,
+ print,
+ PaintDD,
+ dx_alloc_buffers,
+ dx_free_buffers,
+ flip_buffers,
+ mousetype,
+ NULL,
+ 16 + 16,
+ 12,
+ dxwparams,
+ PIXELSIZE,
+ 0.0, 0.0,
+ 0, 0,
+ UI_C256,
+ 0, 256, 255,
+ 0, 0, 0,
+ &win32_gui_driver
+};
+
+struct ui_driver dxf_driver = {
+ "dX-fullscreen",
+ dxf_init,
+ dx_getsize,
+ processevents,
+ getmouse,
+ dx_uninitialize,
+ NULL, // dx_set_color,
+ set_palette,
+ print,
+ PaintDD,
+ dx_alloc_buffers,
+ dx_free_buffers,
+ flip_buffers,
+ dx_mousetype,
+ NULL,
+ 16 + 16,
+ 12,
+ dxfparams,
+ FULLSCREEN | SCREENSIZE,
+ 0.0, 0.0,
+ 0, 0,
+ UI_C256,
+ 0, 256, 255,
+ 0, 0, 0,
+ &win32_fullscreen_gui_driver
+};
+#endif
+
+void x_message(const char *text, ...)
+{
+ va_list ap;
+ char buf[4096];
+ va_start(ap, text);
+ vsprintf(buf, text, ap);
+ if (directX == DXFULLSCREEN)
+ ShowWindow(hWnd, SW_MINIMIZE);
+ MessageBox(NULL, buf, "XaoS", MB_OK | MB_ICONINFORMATION);
+ va_end(ap);
+}
+
+void x_error(const char *text, ...)
+{
+ va_list ap;
+ char buf[4096];
+ va_start(ap, text);
+ vsprintf(buf, text, ap);
+ if (directX == DXFULLSCREEN)
+ ShowWindow(hWnd, SW_MINIMIZE);
+ MessageBox(NULL, buf, "XaoS have problem", MB_OK | MB_ICONEXCLAMATION);
+ va_end(ap);
+}
+
+void x_fatalerror(const char *text, ...)
+{
+ va_list ap;
+ char buf[4096];
+ va_start(ap, text);
+ vsprintf(buf, text, ap);
+ if (directX == DXFULLSCREEN)
+ ShowWindow(hWnd, SW_MINIMIZE);
+ MessageBox(NULL, buf, "Unrecovable XaoS error", MB_OK | MB_ICONSTOP);
+ va_end(ap);
+ exit(1);
+}
+
+
+#endif /* WIN32_DRIVER */