gfx gui abstraction
[swftools.git] / lib / gfxwindow_win32.c
diff --git a/lib/gfxwindow_win32.c b/lib/gfxwindow_win32.c
new file mode 100644 (file)
index 0000000..ae661b0
--- /dev/null
@@ -0,0 +1,430 @@
+/* gfxwindow.h \r
+\r
+   Simple GUI abstraction- Windows implementation\r
+\r
+   Part of the swftools package.\r
+\r
+   Copyright (c) 2005 Matthias Kramm <kramm@quiss.org> \r
+\r
+   This program is free software; you can redistribute it and/or modify\r
+   it under the terms of the GNU General Public License as published by\r
+   the Free Software Foundation; either version 2 of the License, or\r
+   (at your option) any later version.\r
+\r
+   This program is distributed in the hope that it will be useful,\r
+   but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+   GNU General Public License for more details.\r
+\r
+   You should have received a copy of the GNU General Public License\r
+   along with this program; if not, write to the Free Software\r
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */\r
+\r
+#include <windows.h>\r
+#include <commctrl.h>\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include "gfx.h"\r
+\r
+static LRESULT CALLBACK WindowFunc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);\r
+\r
+static char szWinName[] = "MyWin";\r
+static HDC hdc;\r
+static HWND hwnd;\r
+static char*text="";\r
+static int textx;\r
+static int texty;\r
+static int a = 0;\r
+static HDC dc, memDc;\r
+static HBITMAP   piccy;\r
+\r
+static int sizex=640;\r
+static int sizey=388;\r
+static char *screen;\r
+static char *offscreen;\r
+static int screensize;\r
+\r
+static DWORD threadID;\r
+static DWORD mainthreadID;\r
+static HANDLE thread;\r
+static HINSTANCE me,prev;\r
+static int nWinMode;\r
+static int posx,posy;\r
+static RECT desktopSize;\r
+static int initialized = 0;\r
+\r
+static int cwidth=640,cheight=388;\r
+\r
+#define DIB\r
+\r
+static void openWindow(int _sizex, int _sizey)\r
+{\r
+    RECT r;int ok;\r
+\r
+    sizex = _sizex;\r
+    sizey = _sizey;\r
+    \r
+    ok = (int)GetClientRect(GetDesktopWindow(), &r);\r
+    if(!ok) {\r
+       r.left = r.top = 0;\r
+       r.right = 1280;\r
+       r.bottom = 1024;\r
+    }\r
+    desktopSize = r;\r
+\r
+    hwnd=CreateWindow(szWinName,\r
+                     0, //window title\r
+                     WS_POPUP|WS_VISIBLE,\r
+                     posx=100, //CW_USEDEFAULT,\r
+                     posy=200, //CW_USEDEFAULT,\r
+                     640,388,\r
+                     HWND_DESKTOP,\r
+                     NULL,me,NULL);\r
+    SendMessage(hwnd, 1024+5 /*SB_SETBORDERS*/, 0, 0);\r
+    \r
+    ShowWindow(hwnd,nWinMode);\r
+    UpdateWindow(hwnd);\r
+\r
+    dc=GetDC(hwnd);\r
+    memDc=CreateCompatibleDC(dc);\r
+//    SetTimer(hwnd,1,1000,NULL);\r
+//    SetTimer(hwnd,1,33,NULL);\r
+\r
+#ifdef DIB\r
+    void * ppvBits = 0;\r
+    BITMAPINFO info;\r
+    memset(&info, sizeof(info), 0);\r
+    info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);\r
+    info.bmiHeader.biWidth = sizex;\r
+    info.bmiHeader.biHeight = sizey;\r
+    info.bmiHeader.biPlanes= 1;\r
+    info.bmiHeader.biBitCount = 24;\r
+    info.bmiHeader.biCompression = BI_RGB;\r
+    info.bmiHeader.biSizeImage = sizex*sizey*3;\r
+\r
+    piccy = CreateDIBSection(0, &info, DIB_RGB_COLORS, &ppvBits, 0,0);\r
+    screen = (char*)ppvBits;\r
+    offscreen = (char*)malloc(sizex*sizey*4);\r
+    screensize = sizex*sizey*3;\r
+    GdiFlush();\r
+#else\r
+    screen = (char*)malloc(sizex*sizey*3);\r
+    offscreen = (char*)malloc(sizex*sizey*4);\r
+    screensize = sizex*sizey*3;\r
+    piccy = CreateBitmap(sizex, sizey, 1, 24, screen);\r
+#endif\r
+\r
+    SelectObject(memDc,piccy);\r
+    \r
+}\r
+\r
+static void closeWindow()\r
+{\r
+    DeleteDC(memDc);\r
+    ReleaseDC(hwnd,dc);\r
+    KillTimer(hwnd,1);\r
+}\r
+\r
+static int initwin32()\r
+{\r
+    MSG msg;\r
+    int ret;\r
+    WNDCLASS wcl;\r
+\r
+    me =  GetModuleHandle(NULL);\r
+    prev = NULL;\r
+    nWinMode = SW_SHOW;\r
+\r
+    if(GetClassInfo(0, szWinName, &wcl)) {\r
+       /* already registered */\r
+       exit(1);\r
+    }\r
+    wcl.hInstance    =me;\r
+    wcl.lpszClassName=szWinName;\r
+    wcl.lpfnWndProc  =WindowFunc;\r
+    wcl.style        =2;\r
+    wcl.hIcon        =LoadIcon  (NULL, IDI_HAND);\r
+    wcl.hCursor      =LoadCursor(NULL, IDC_HAND);//IDC_CROSS);\r
+    wcl.lpszMenuName =NULL;\r
+    wcl.cbClsExtra   =0;\r
+    wcl.cbWndExtra   =0;\r
+    wcl.hbrBackground=(HBRUSH)GetStockObject(NULL_BRUSH);//WHITE_BRUSH);\r
+\r
+    if(!RegisterClass(&wcl)) \r
+       exit(1);\r
+\r
+    //mainthreadID = GetCurrentThreadId();\r
+\r
+    //openWindow(640,388);\r
+\r
+    //thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(maincaller), (/*data*/0), 0, (LPDWORD)&(threadID));\r
+  \r
+    /*while(GetMessage(&msg,NULL,0,0))\r
+    {\r
+        TranslateMessage(&msg);\r
+        DispatchMessage(&msg);\r
+    }*/\r
+\r
+    //closeWindow();\r
+    //ret = msg.wParam;\r
+\r
+    initialized = 1;\r
+\r
+    return ret;\r
+}\r
+\r
+#define Q_REDRAW 0x7f01\r
+#define Q_DUMMY  0x7f02\r
+\r
+static LRESULT CALLBACK WindowFunc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)\r
+{\r
+ switch(message)\r
+ {\r
+   case WM_DESTROY:\r
+    PostQuitMessage(0);\r
+    break;\r
+   case WM_PAINT:\r
+    BitBlt(dc,0,0,sizex,sizey,memDc,0,0,SRCCOPY);\r
+   break;\r
+   case Q_DUMMY:\r
+   break;\r
+   case Q_REDRAW: {\r
+    int x,y;\r
+    for(y=0;y<sizey;y++) {\r
+       unsigned char*o = (unsigned char*)&offscreen[y*sizex*4];\r
+       unsigned char*s = (unsigned char*)&screen[(sizey-y-1)*sizex*3];\r
+       for(x=0;x<sizex;x++) {\r
+           s[0] = o[0];\r
+           s[1] = o[1];\r
+           s[2] = o[2];\r
+           s+=3;\r
+           o+=4;\r
+       }\r
+    }\r
+\r
+#ifndef DIB\r
+    SetBitmapBits(piccy, screensize, screen);\r
+    InvalidateRect(hwnd,NULL,1);\r
+#endif\r
+\r
+#ifdef DIB\r
+    //SetDIBitsToDevice\r
+    BitBlt(dc,0,0,sizex,sizey,memDc,0,0,SRCCOPY);\r
+#else\r
+    BitBlt(dc,0,0,sizex,sizey,memDc,0,0,SRCCOPY);\r
+#endif\r
+   break;\r
+   }\r
+   case WM_TIMER:\r
+    //InvalidateRect(hwnd,NULL,1);\r
+   default:\r
+    return DefWindowProc(hwnd, message, wParam, lParam);\r
+ }\r
+ return 0;\r
+}\r
+\r
+static void ModeRGB_on(window_t*win)\r
+{\r
+    MSG msg;\r
+    //printf("on()\n");\r
+    openWindow(sizex, sizey);\r
+    win->currentscr = (unsigned char*)offscreen;\r
+\r
+    while(GetMessage(&msg,NULL,0,0))\r
+    {\r
+        TranslateMessage(&msg);\r
+        DispatchMessage(&msg);\r
+       if(msg.message == WM_PAINT)\r
+           break;\r
+    }\r
+}\r
+static void ModeRGB_off(window_t*win)\r
+{\r
+    MSG msg;\r
+    //printf("off()\n");\r
+    //TODO: shouldn't this be DestroyWindow(hwnd)?\r
+    PostMessage(hwnd, WM_DESTROY, 0, 0);\r
+    while(GetMessage(&msg,NULL,0,0))\r
+    {\r
+        TranslateMessage(&msg);\r
+        DispatchMessage(&msg);\r
+       if(msg.message == WM_DESTROY)\r
+           break;\r
+    }\r
+    closeWindow();\r
+    win->currentscr = win->lastscr = 0;\r
+}\r
+static void ModeRGB_flippage(window_t*win)\r
+{\r
+    MSG msg;\r
+    PostMessage(hwnd, Q_REDRAW, 0, 0);\r
+    while(GetMessage(&msg,NULL,0,0))\r
+    {\r
+        TranslateMessage(&msg);\r
+        DispatchMessage(&msg);\r
+       if(msg.message == Q_REDRAW)\r
+           break;\r
+    }\r
+    win->currentscr = (byte*)offscreen;\r
+}\r
+static gfxevent_t ModeRGB_getEvent(window_t*win)\r
+{\r
+    MSG msg;\r
+    WPARAM wParam;\r
+    LPARAM lParam;\r
+    gfxevent_t event;\r
+\r
+    //PostMessage(hwnd, Q_DUMMY, 0, 0);\r
+\r
+    event.type = GFXEVENT_NOTHING;\r
+    event.key = 0;\r
+    event.x = 0;\r
+    event.y = 0;\r
+    event.type = 0;\r
+    event.button = 0;\r
+\r
+    if(!PeekMessage(&msg,NULL,0,0,0))\r
+       return event;//nothing\r
+\r
+    while(GetMessage(&msg,NULL,0,0))\r
+    {\r
+       lParam = msg.lParam;\r
+       wParam = msg.wParam;\r
+       if(msg.message == Q_DUMMY) {\r
+           event.type = GFXEVENT_NOTHING;\r
+           break;\r
+       } else if(msg.message == WM_LBUTTONDOWN) {\r
+           event.type = GFXEVENT_MOUSEPRESS;\r
+           event.button = 1;\r
+           event.x = (signed short int)LOWORD(lParam);\r
+           event.y = (signed short int)HIWORD(lParam);\r
+           SetCapture(hwnd);\r
+           break;\r
+       } else if(msg.message == WM_LBUTTONUP) {\r
+           event.type = GFXEVENT_MOUSERELEASE;\r
+           event.button = 1;\r
+           event.x = (signed short int)LOWORD(lParam);\r
+           event.y = (signed short int)HIWORD(lParam);\r
+           ReleaseCapture();\r
+           break;\r
+       } else if(msg.message == WM_MBUTTONDOWN) {\r
+           event.type = GFXEVENT_MOUSEPRESS;\r
+           event.button = 2;\r
+           event.x = (signed short int)LOWORD(lParam);\r
+           event.y = (signed short int)HIWORD(lParam);\r
+           SetCapture(hwnd);\r
+           break;\r
+       } else if(msg.message == WM_MBUTTONUP) {\r
+           event.type = GFXEVENT_MOUSERELEASE;\r
+           event.button = 1;\r
+           event.x = (signed short int)LOWORD(lParam);\r
+           event.y = (signed short int)HIWORD(lParam);\r
+           ReleaseCapture();\r
+           break;\r
+       } else if(msg.message == WM_RBUTTONDOWN) {\r
+           event.type = GFXEVENT_MOUSEPRESS;\r
+           event.button = 3;\r
+           event.x = (signed short int)LOWORD(lParam);\r
+           event.y = (signed short int)HIWORD(lParam);\r
+           SetCapture(hwnd);\r
+           break;\r
+       } else if(msg.message == WM_RBUTTONUP) {\r
+           event.type = GFXEVENT_MOUSERELEASE;\r
+           event.button = 3;\r
+           event.x = (signed short int)LOWORD(lParam);\r
+           event.y = (signed short int)HIWORD(lParam);\r
+           ReleaseCapture();\r
+           break;\r
+       } else if(msg.message == WM_MOUSEMOVE) {\r
+           event.type = GFXEVENT_MOUSEMOVE;\r
+           event.x = (signed short int)LOWORD(lParam);\r
+           event.y = (signed short int)HIWORD(lParam);\r
+           break;\r
+       } else if(msg.message == WM_CHAR) {\r
+           event.type = GFXEVENT_KEYPRESS;\r
+           event.key = (char)wParam;\r
+           break;\r
+       } else {\r
+           TranslateMessage(&msg);\r
+           DispatchMessage(&msg);\r
+           event.type = GFXEVENT_NOTHING;\r
+           break;\r
+       }\r
+    }\r
+    return event;\r
+}\r
+static void ModeRGB_move(window_t*win, int relx,int rely)\r
+{\r
+    MSG msg;\r
+    PostMessage(hwnd, Q_DUMMY, 0, 0);\r
+    while(GetMessage(&msg,NULL,0,0))\r
+    {\r
+       if(msg.message == WM_LBUTTONUP) {\r
+           SendMessage(hwnd, msg.message, msg.wParam, msg.lParam);\r
+           return;\r
+       }\r
+        TranslateMessage(&msg);\r
+        DispatchMessage(&msg);\r
+       if(msg.message == Q_DUMMY)\r
+           break;\r
+    }\r
+    posx+=relx;\r
+    posy+=rely;\r
+   \r
+    if(posx > desktopSize.right-cwidth) posx = desktopSize.right-cwidth;\r
+    if(posy > desktopSize.bottom-cheight) posy = desktopSize.bottom-cheight;\r
+    if(posx < desktopSize.left) posx = desktopSize.left;\r
+    if(posy < desktopSize.top) posy = desktopSize.top;\r
+\r
+    SetWindowPos(hwnd, HWND_TOP, posx, posy, 0, 0, SWP_NOSIZE);\r
+    PostMessage(hwnd, Q_DUMMY, 0, 0);\r
+    while(GetMessage(&msg,NULL,0,0))\r
+    {\r
+       if(msg.message == WM_LBUTTONUP) {\r
+           SendMessage(hwnd, msg.message, msg.wParam, msg.lParam);\r
+           break;;\r
+       }\r
+        TranslateMessage(&msg);\r
+        DispatchMessage(&msg);\r
+       if(msg.message == Q_DUMMY)\r
+           break;\r
+    }\r
+}\r
+static void ModeRGB_resize(window_t*win, int width,int height)\r
+{\r
+    if(width>sizex || height>sizey) {\r
+       printf("mode24::resize: can only make windows smaller\n");\r
+       return;\r
+    }\r
+    if(width<1) width=1;\r
+    if(height<1) height=1;\r
+    cwidth = width;\r
+    cheight = height;\r
+    SetWindowPos(hwnd, HWND_TOP, 0, 0, width, height, SWP_NOMOVE);\r
+    win->move(win,0,0);\r
+}\r
+\r
+\r
+window_t* window_new(window_t*win, int width, int height)\r
+{\r
+    window_t*w = (window_t*)malloc(sizeof(window_t));\r
+    memset(w, 0, sizeof(window_t));\r
+    if(!initialized)\r
+       initwin32();\r
+    w->currentscr = w->lastscr = 0;\r
+    sizex = width;\r
+    sizey = height;\r
+    cwidth = sizex;\r
+    cheight = sizey;\r
+    //printf("contruct(%d, %d)\n", x, y);\r
+    w->on = ModeRGB_on;\r
+    w->off = ModeRGB_off;\r
+    w->move = ModeRGB_move;\r
+    w->resize = ModeRGB_resize;\r
+    w->flippage = ModeRGB_flippage;\r
+    w->getEvent = ModeRGB_getEvent;\r
+    w->width = width;\r
+    w->height = height;\r
+    return w;\r
+}\r
+\r