Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. #include <string.h>
  2. #include <process.h>
  3. #include <stdio.h>
  4. #include <math.h>
  5. #include <assert.h>
  6. #include <deque.h>
  7.  
  8. #include <kolibri.h>
  9. #include <kos_heap.h>
  10. #include <kos_file.h>
  11.  
  12. using namespace Kolibri;
  13. using namespace std;
  14.  
  15. const char file_prefix[] = "";
  16. bool WasThreadCreatedBool = false;
  17.  
  18. struct TExceptToMessageLoop
  19. {
  20.         TExceptToMessageLoop() {}
  21. };
  22.  
  23. struct TThreadDataStruct
  24. {
  25.         void *user;
  26.         void *stack_begin;
  27.         TWindowData *win_data;
  28.         HWND hwnd;
  29.         int flag;
  30.         unsigned int win_time, me_time;
  31.         void *picture;
  32.         unsigned int picture_width, picture_height;
  33.         deque<unsigned char> *keys;
  34.         unsigned int bmp_data_length;
  35.         unsigned int *bmp_data;
  36.         unsigned int mouse_state;
  37. };
  38.  
  39. TThreadDataStruct /*__thread*/ ThreadDataStruct;
  40. int nCmdShow;
  41. HINSTANCE hInstance;
  42. const char szWindowClass[] = "Kolibri window";
  43.  
  44. void FinalizeThreadData()
  45. {
  46.         if (ThreadDataStruct.keys)
  47.         {
  48.                 delete ThreadDataStruct.keys;
  49.                 ThreadDataStruct.keys = 0;
  50.         }
  51.         if (ThreadDataStruct.bmp_data)
  52.         {
  53.                 delete[] ThreadDataStruct.bmp_data;
  54.                 ThreadDataStruct.bmp_data = 0;
  55.         }
  56. }
  57.  
  58. unsigned int CalculateNewTime()
  59. {
  60.         unsigned int t = GetTickCount();
  61.         unsigned int dt = (unsigned int)(t - ThreadDataStruct.win_time) / 10U;
  62.         ThreadDataStruct.me_time += dt;
  63.         ThreadDataStruct.win_time += dt * 10;
  64.         return t;
  65. }
  66.  
  67. void DrawPicture(HDC hdc)
  68. {
  69.         TRecMutex xm;
  70.         InitRecMutex(&xm);
  71.         Lock(&xm);
  72.         UnLock(&xm);
  73.  
  74.         int w = ThreadDataStruct.picture_width, h = ThreadDataStruct.picture_height;
  75.         RECT rect;
  76.         if (!ThreadDataStruct.picture || !ThreadDataStruct.hwnd || w <= 0 || h <= 0) return;
  77.         if (GetClientRect(ThreadDataStruct.hwnd, &rect))
  78.         {
  79.                 rect.right -= rect.left; rect.left = 0;
  80.                 rect.bottom -= rect.top; rect.top = 0;
  81.                 if (rect.right <= 0 || rect.bottom <= 0) return;
  82.                 if (w > rect.right) w = rect.right;
  83.                 if (h > rect.bottom) h = rect.bottom;
  84.         }
  85.         if (!ThreadDataStruct.bmp_data || ThreadDataStruct.bmp_data_length < w * h)
  86.         {
  87.                 if (ThreadDataStruct.bmp_data) delete[] ThreadDataStruct.bmp_data;
  88.                 ThreadDataStruct.bmp_data_length = w * h;
  89.                 ThreadDataStruct.bmp_data = new unsigned int[ThreadDataStruct.bmp_data_length];
  90.         }
  91.         int i;
  92.         unsigned char *p = (unsigned char*)ThreadDataStruct.picture;
  93.         for (i = 0; i < w * h; i++)
  94.         {
  95.                 ThreadDataStruct.bmp_data[i] = ((unsigned int)p[0]) +
  96.                                 ((unsigned int)p[1] << 8) + ((unsigned int)p[2] << 16);
  97.                 p += 3;
  98.         }
  99.         HBITMAP bitmap = CreateBitmap(w, h, 1, 32, ThreadDataStruct.bmp_data);
  100.         if (bitmap)
  101.         {
  102.                 HDC memdc = CreateCompatibleDC(hdc);
  103.                 if (memdc)
  104.                 {
  105.                         SelectObject(memdc, bitmap);
  106.                         BitBlt(hdc, 0, 0, w, h, memdc, 0, 0, SRCCOPY);
  107.                         DeleteObject(memdc);
  108.                 }
  109.                 DeleteObject(bitmap);
  110.         }
  111. }
  112.  
  113. LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  114. {
  115.         const int timeout = 20;
  116.         unsigned int t;
  117.         PAINTSTRUCT ps;
  118.         HDC hdc;
  119.         if (hWnd == ThreadDataStruct.hwnd && ThreadDataStruct.flag != -1)
  120.         {
  121.                 int window_rect[4];
  122.                 switch (message)
  123.                 {
  124.                 case WM_CREATE:
  125.                         SetTimer(hWnd, 0, timeout, NULL);
  126.                         SendMessage(hWnd, WM_SIZE, SIZE_RESTORED, 0);
  127.                         return 0;
  128.                 case WM_TIMER:
  129.                         t = CalculateNewTime();
  130.                         while (KolibriOnIdle((TThreadData)(&ThreadDataStruct)) == 0 &&
  131.                                         GetTickCount() - t + 2 < timeout);
  132.                         return 0;
  133.                 case WM_MOUSEMOVE:
  134.                         KolibriOnMouse((TThreadData)(&ThreadDataStruct));
  135.                         return 0;
  136.                 case WM_LBUTTONDOWN:
  137.                         if (!ThreadDataStruct.mouse_state) SetCapture(hWnd);
  138.                         ThreadDataStruct.mouse_state |= 1;
  139.                         KolibriOnMouse((TThreadData)(&ThreadDataStruct));
  140.                         return 0;
  141.                 case WM_LBUTTONUP:
  142.                         if (ThreadDataStruct.mouse_state & 1)
  143.                         {
  144.                                 ThreadDataStruct.mouse_state &= ~1;
  145.                                 if (!ThreadDataStruct.mouse_state) ReleaseCapture();
  146.                                 KolibriOnMouse((TThreadData)(&ThreadDataStruct));
  147.                         }
  148.                         return 0;
  149.                 case WM_RBUTTONDOWN:
  150.                         if (!ThreadDataStruct.mouse_state) SetCapture(hWnd);
  151.                         ThreadDataStruct.mouse_state |= 2;
  152.                         KolibriOnMouse((TThreadData)(&ThreadDataStruct));
  153.                         return 0;
  154.                 case WM_RBUTTONUP:
  155.                         if (ThreadDataStruct.mouse_state & 2)
  156.                         {
  157.                                 ThreadDataStruct.mouse_state &= ~2;
  158.                                 if (!ThreadDataStruct.mouse_state) ReleaseCapture();
  159.                                 KolibriOnMouse((TThreadData)(&ThreadDataStruct));
  160.                         }
  161.                         return 0;
  162.                 case WM_CAPTURECHANGED:
  163.                         if (ThreadDataStruct.mouse_state)
  164.                         {
  165.                                 ThreadDataStruct.mouse_state = 0;
  166.                                 KolibriOnMouse((TThreadData)(&ThreadDataStruct));
  167.                         }
  168.                         return 0;
  169.                 //case WM_SYSKEYDOWN: case WM_KEYDOWN:
  170.                 case WM_CHAR:
  171.                         ThreadDataStruct.keys->push_back((unsigned char)wParam);
  172.                         KolibriOnKeyPress((TThreadData)(&ThreadDataStruct));
  173.                         return 0;
  174.                 case WM_SIZE:
  175.                         GetProcessInfo(0, 0, 0, 0, window_rect);
  176.                         KolibriOnSize(window_rect, (TThreadData)(&ThreadDataStruct));
  177.                         InvalidateRect(hWnd, 0, 0);
  178.                         return 0;
  179.                 case WM_PAINT:
  180.                         hdc = BeginPaint(hWnd, &ps);
  181.                         if (ThreadDataStruct.picture) DrawPicture(hdc);
  182.                         EndPaint(hWnd, &ps);
  183.                         return 0;
  184.                 case WM_CLOSE:
  185.                         if (KolibriOnClose((TThreadData)(&ThreadDataStruct)))
  186.                         {
  187.                                 ThreadDataStruct.flag = -1;
  188.                         }
  189.                         else return 0;
  190.                 case WM_DESTROY:
  191.                         PostQuitMessage(0);
  192.                         return 0;
  193.                 }
  194.         }
  195.         return DefWindowProc(hWnd, message, wParam, lParam);
  196. }
  197.  
  198. ATOM MyRegisterClass()
  199. {
  200.         HBRUSH background = CreateSolidBrush(RGB(0, 0, 0));
  201.         WNDCLASSEX wcex;
  202.         wcex.cbSize = sizeof(WNDCLASSEX);
  203.         wcex.style                      = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
  204.         wcex.lpfnWndProc        = (WNDPROC)WndProc;
  205.         wcex.cbClsExtra         = 0;
  206.         wcex.cbWndExtra         = 0;
  207.         wcex.hInstance          = hInstance;
  208.         wcex.hIcon                      = 0;
  209.         wcex.hCursor            = LoadCursor(NULL, IDC_ARROW);
  210.         wcex.hbrBackground      = background;
  211.         wcex.lpszMenuName       = NULL;
  212.         wcex.lpszClassName      = szWindowClass;
  213.         wcex.hIconSm            = 0;
  214.         ATOM ret = RegisterClassEx(&wcex);
  215.         DeleteObject(background);
  216.         return ret;
  217. }
  218.  
  219. HWND InitInstance(int x, int y, int w, int h)
  220. {
  221.         HWND hWnd;
  222.         MyRegisterClass();
  223.         DWORD style = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, exstyle = 0;
  224.         hWnd = CreateWindowEx(exstyle, szWindowClass, ThreadDataStruct.win_data->Title, style,
  225.                                 x, y, w, h, NULL, NULL, hInstance, NULL);
  226.         if (!hWnd) return NULL;
  227.         ShowWindow(hWnd, nCmdShow);
  228.         UpdateWindow(hWnd);
  229.         return hWnd;
  230. }
  231.  
  232. int ThreadMainProc(void *user)
  233. {
  234.         ThreadMain(user, 0);
  235.         return 0;
  236. }
  237.  
  238. namespace Kolibri
  239. {
  240.         void Main() {ThreadMain();}
  241.  
  242.         void* ThreadMain(void *user, void *stack_begin)
  243.         {
  244.                 TStartData start_data;
  245.                 ThreadDataStruct.user = user;
  246.                 ThreadDataStruct.stack_begin = stack_begin;
  247.                 ThreadDataStruct.win_data = &start_data.WinData;
  248.                 ThreadDataStruct.hwnd = 0;
  249.                 ThreadDataStruct.flag = 0;
  250.                 ThreadDataStruct.win_time = GetTickCount();
  251.                 ThreadDataStruct.me_time = ThreadDataStruct.win_time / 10;
  252.                 ThreadDataStruct.keys = new deque<unsigned char>;
  253.                 ThreadDataStruct.bmp_data_length = 0;
  254.                 ThreadDataStruct.bmp_data = 0;
  255.                 ThreadDataStruct.mouse_state = 0;
  256.                 start_data.Left = 50; start_data.Width = 256;
  257.                 start_data.Top = 50; start_data.Height = 256;
  258.                 start_data.WinData.WindowType = 0x03;
  259.                 start_data.WinData.HeaderType = 0x80;
  260.                 start_data.WinData.WindowColor = 0xFFFFFF;
  261.                 start_data.WinData.HeaderColor = 0x6060FF;
  262.                 start_data.WinData.BorderColor = 0x000000;
  263.                 start_data.WinData.TitleColor = 0xFFFF40;
  264.                 start_data.WinData.Title = 0;
  265.                 if (KolibriOnStart(start_data, (TThreadData)(&ThreadDataStruct)))
  266.                 {
  267.                         while (ThreadDataStruct.flag < 0)
  268.                         {
  269.                                 ThreadDataStruct.flag &= ~0x80000000;
  270.                                 if (KolibriOnClose((TThreadData)(&ThreadDataStruct)))
  271.                                 {
  272.                                         ThreadDataStruct.flag = -1;
  273.                                         break;
  274.                                 }
  275.                         }
  276.                         if (ThreadDataStruct.flag >= 0)
  277.                         {
  278.                                 assert((ThreadDataStruct.hwnd = InitInstance(start_data.Left,
  279.                                                         start_data.Top, start_data.Width, start_data.Height)) != NULL);
  280.                                 assert(SendMessage(ThreadDataStruct.hwnd, WM_CREATE, 0, 0) == 0);
  281.                                 MSG msg;
  282.                                 HACCEL hAccelTable = 0;
  283.                                 while (GetMessage(&msg, NULL, 0, 0))
  284.                                 {
  285.                                         if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
  286.                                         {
  287.                                                 TranslateMessage(&msg);
  288.                                                 DispatchMessage(&msg);
  289.                                         }
  290.                                 }
  291.                         }
  292.                         assert(ThreadDataStruct.flag == -1);
  293.                 }
  294.                 FinalizeThreadData();
  295.                 return ThreadDataStruct.stack_begin;
  296.         }
  297.  
  298.         void GetWindowData(TWindowData &win_data)
  299.         {
  300.                 win_data = *ThreadDataStruct.win_data;
  301.         }
  302.  
  303.         void GetWindowData(TWindowData &win_data, TThreadData thread_data)
  304.         {
  305.                 win_data = *((TThreadDataStruct*)thread_data)->win_data;
  306.         }
  307.  
  308.         void SetWindowData(const TWindowData &win_data)
  309.         {
  310.                 *ThreadDataStruct.win_data = win_data;
  311.                 if (ThreadDataStruct.hwnd)
  312.                 {
  313.                         SetWindowText(ThreadDataStruct.hwnd, ThreadDataStruct.win_data->Title);
  314.                         InvalidateRect(ThreadDataStruct.hwnd, NULL, FALSE);
  315.                 }
  316.         }
  317.  
  318.         void SetWindowData(const TWindowData &win_data, TThreadData thread_data)
  319.         {
  320.                 *((TThreadDataStruct*)thread_data)->win_data = win_data;
  321.                 if (((TThreadDataStruct*)thread_data)->hwnd)
  322.                 {
  323.                         SetWindowText(((TThreadDataStruct*)thread_data)->hwnd,
  324.                                                 ((TThreadDataStruct*)thread_data)->win_data->Title);
  325.                         InvalidateRect(((TThreadDataStruct*)thread_data)->hwnd, NULL, FALSE);
  326.                 }
  327.         }
  328.  
  329.         void CloseWindow()
  330.         {
  331.                 if (ThreadDataStruct.hwnd)
  332.                 {
  333.                         SendMessage(ThreadDataStruct.hwnd, WM_CLOSE, 0, 0);
  334.                 }
  335.                 else ThreadDataStruct.flag |= 0x80000000;
  336.         }
  337.  
  338.         void CloseWindow(TThreadData thread_data)
  339.         {
  340.                 if (((TThreadDataStruct*)thread_data)->hwnd)
  341.                 {
  342.                         SendMessage(((TThreadDataStruct*)thread_data)->hwnd, WM_CLOSE, 0, 0);
  343.                 }
  344.                 else ((TThreadDataStruct*)thread_data)->flag |= 0x80000000;
  345.         }
  346.  
  347.         void Redraw(int /*frame*/)
  348.         {
  349.                 if (ThreadDataStruct.hwnd)
  350.                 {
  351.                         InvalidateRect(ThreadDataStruct.hwnd, NULL, FALSE);
  352.                         SendMessage(ThreadDataStruct.hwnd, WM_PAINT, 0, 0);
  353.                 }
  354.         }
  355.  
  356.         void Redraw(int /*frame*/, TThreadData thread_data)
  357.         {
  358.                 if (((TThreadDataStruct*)thread_data)->hwnd)
  359.                 {
  360.                         InvalidateRect(((TThreadDataStruct*)thread_data)->hwnd, NULL, FALSE);
  361.                         SendMessage(((TThreadDataStruct*)thread_data)->hwnd, WM_PAINT, 0, 0);
  362.                 }
  363.         }
  364.  
  365.         void Invalidate(int /*frame*/)
  366.         {
  367.                 if (ThreadDataStruct.hwnd)
  368.                 {
  369.                         InvalidateRect(ThreadDataStruct.hwnd, NULL, FALSE);
  370.                 }
  371.         }
  372.  
  373.         void Invalidate(int /*frame*/, TThreadData thread_data)
  374.         {
  375.                 if (((TThreadDataStruct*)thread_data)->hwnd)
  376.                 {
  377.                         InvalidateRect(((TThreadDataStruct*)thread_data)->hwnd, NULL, FALSE);
  378.                 }
  379.         }
  380.  
  381.         void MoveWindow(const int window_rect[/* 4 */])
  382.         {
  383.                 if (!ThreadDataStruct.hwnd) return;
  384.                 RECT rect;
  385.                 if (window_rect[0] == -1 || window_rect[1] == -1 ||
  386.                         window_rect[2] == -1 || window_rect[3] == -1)
  387.                 {
  388.                         if (!GetWindowRect(ThreadDataStruct.hwnd, &rect)) return;
  389.                         ::MoveWindow(ThreadDataStruct.hwnd,
  390.                                         (window_rect[0] == -1) ? rect.left : window_rect[0],
  391.                                         (window_rect[1] == -1) ? rect.top : window_rect[1],
  392.                                         (window_rect[2] == -1) ? (rect.right - rect.left) : window_rect[2],
  393.                                         (window_rect[3] == -1) ? (rect.bottom - rect.top) : window_rect[3], TRUE);
  394.                 }
  395.                 else
  396.                 {
  397.                         ::MoveWindow(ThreadDataStruct.hwnd, window_rect[0],
  398.                                         window_rect[1], window_rect[2], window_rect[3], TRUE);
  399.                 }
  400.         }
  401.  
  402.         void Abort()
  403.         {
  404.                 if (ThreadDataStruct.hwnd) KillTimer(ThreadDataStruct.hwnd, 0);
  405.                 abort();
  406.         }
  407.  
  408.         void ExitProcess() {::ExitProcess(0);}
  409.  
  410.         void ExitThread() {FinalizeThreadData(); ::ExitThread(0);}
  411.  
  412.         void ExitThread(TThreadData) {FinalizeThreadData(); ::ExitThread(0);}
  413.  
  414.         void ReturnMessageLoop()
  415.         {
  416.                 TExceptToMessageLoop ex;
  417.                 throw(ex);
  418.         }
  419.  
  420.         void ReturnMessageLoop(TThreadData)
  421.         {
  422.                 TExceptToMessageLoop ex;
  423.                 throw(ex);
  424.         }
  425.  
  426.         void Delay(unsigned int time) {Sleep(time * 10);}
  427.  
  428.         unsigned int Clock() {CalculateNewTime(); return ThreadDataStruct.me_time;}
  429.  
  430.         int GetPackedTime()
  431.         {
  432.                 SYSTEMTIME time;
  433.                 GetSystemTime(&time);
  434.                 int t;
  435.                 t = (time.wSecond / 10) * 16 + (time.wSecond % 10);
  436.                 t = (time.wMinute / 10) * 16 + (time.wMinute % 10) + (t << 8);
  437.                 t = (time.wHour / 10) * 16 + (time.wHour % 10) + (t << 8);
  438.                 return t;
  439.         }
  440.  
  441.         void GetTime(int t[/* 3 */])
  442.         {
  443.                 SYSTEMTIME time;
  444.                 GetSystemTime(&time);
  445.                 t[0] = time.wSecond;
  446.                 t[1] = time.wMinute;
  447.                 t[2] = time.wHour;
  448.         }
  449.  
  450.         int GetPackedDate()
  451.         {
  452.                 SYSTEMTIME time;
  453.                 GetSystemTime(&time);
  454.                 int t;
  455.                 t = ((time.wYear / 10) % 10) * 16 + (time.wYear % 10);
  456.                 t = (time.wDay / 10) * 16 + (time.wDay % 10) + (t << 8);
  457.                 t = (time.wMonth / 10) * 16 + (time.wMonth % 10) + (t << 8);
  458.                 return t;
  459.         }
  460.  
  461.         void GetDate(int d[/* 3 */])
  462.         {
  463.                 SYSTEMTIME time;
  464.                 GetSystemTime(&time);
  465.                 d[0] = time.wDay;
  466.                 d[1] = time.wMonth;
  467.                 d[2] = time.wYear;
  468.         }
  469.  
  470.         void GetTimeDate(int t[/* 6 */])
  471.         {
  472.                 SYSTEMTIME time;
  473.                 GetSystemTime(&time);
  474.                 t[0] = time.wSecond;
  475.                 t[1] = time.wMinute;
  476.                 t[2] = time.wHour;
  477.                 t[3] = time.wDay;
  478.                 t[4] = time.wMonth;
  479.                 t[5] = time.wYear;
  480.         }
  481.  
  482.         void ReadCommonColors(unsigned int colors[/* 10 */])
  483.         {
  484.                 int i;
  485.                 for (i = 0; i < 10; i++) colors[i] = 0;
  486.         }
  487.  
  488.         unsigned int GetProcessInfo(unsigned int *use_cpu, char process_name[/* 13 */], unsigned int *use_memory,
  489.                                                                 unsigned int *pid, int window_rect[/* 4 */], unsigned int pid_for)
  490.         {
  491.                 if (use_cpu) *use_cpu = 0;
  492.                 if (process_name) strcpy(process_name, "noname");
  493.                 if (use_memory) *use_memory = 0;
  494.                 if (pid)
  495.                 {
  496.                         if ((pid_for | 15) == -1) pid_for = getpid();
  497.                         *pid = pid_for;
  498.                 }
  499.                 if (window_rect)
  500.                 {
  501.                         RECT rect;
  502.                         if (ThreadDataStruct.hwnd && GetWindowRect(ThreadDataStruct.hwnd, &rect))
  503.                         {
  504.                                 window_rect[0] = rect.left;
  505.                                 window_rect[1] = rect.top;
  506.                                 window_rect[2] = rect.right - rect.left;
  507.                                 window_rect[3] = rect.bottom - rect.top;
  508.                         }
  509.                         else
  510.                         {
  511.                                 window_rect[0] = 0; window_rect[1] = 0;
  512.                                 window_rect[2] = 0; window_rect[3] = 0;
  513.                         }
  514.                 }
  515.                 return 1;
  516.         }
  517.  
  518.         unsigned int GetPid() {return GetCurrentThreadId();}
  519.  
  520.         unsigned int GetPid(TThreadData /*thread_data*/) {return GetCurrentThreadId();}
  521.  
  522.         TThreadData GetThreadData() {return (TThreadData)(&ThreadDataStruct);}
  523.  
  524.         TThreadData GetThreadData(unsigned int /*pid*/) {return (TThreadData)(&ThreadDataStruct);}
  525.  
  526.         void* GetPicture(unsigned short &width, unsigned short &height)
  527.         {
  528.                 width = (unsigned short)ThreadDataStruct.picture_width;
  529.                 height = (unsigned short)ThreadDataStruct.picture_height;
  530.                 return ThreadDataStruct.picture;
  531.         }
  532.  
  533.         void* GetPicture(unsigned short &width, unsigned short &height, TThreadData thread_data)
  534.         {
  535.                 width = (unsigned short)((TThreadDataStruct*)thread_data)->picture_width;
  536.                 height = (unsigned short)((TThreadDataStruct*)thread_data)->picture_height;
  537.                 return ((TThreadDataStruct*)thread_data)->picture;
  538.         }
  539.        
  540.         void SetPicture(void *picture, unsigned short width, unsigned short height)
  541.         {
  542.                 ThreadDataStruct.picture_width = width;
  543.                 ThreadDataStruct.picture_height = height;
  544.                 ThreadDataStruct.picture = picture;
  545.                 if (ThreadDataStruct.hwnd)
  546.                 {
  547.                         InvalidateRect(ThreadDataStruct.hwnd, NULL, FALSE);
  548.                 }
  549.         }
  550.  
  551.         void SetPicture(void *picture, unsigned short width, unsigned short height, TThreadData thread_data)
  552.         {
  553.                 ((TThreadDataStruct*)thread_data)->picture_width = width;
  554.                 ((TThreadDataStruct*)thread_data)->picture_height = height;
  555.                 ((TThreadDataStruct*)thread_data)->picture = picture;
  556.                 if (((TThreadDataStruct*)thread_data)->hwnd)
  557.                 {
  558.                         InvalidateRect(((TThreadDataStruct*)thread_data)->hwnd, NULL, FALSE);
  559.                 }
  560.         }
  561.  
  562.         void GetBorderHeader(unsigned short &border_size, unsigned short &header_size)
  563.         {
  564.                 border_size = (unsigned short)GetSystemMetrics(SM_CXFRAME);
  565.                 header_size = (unsigned short)(GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION));
  566.         }
  567.  
  568.         void GetBorderHeader(unsigned short &border_size, unsigned short &header_size, TThreadData /*thread_data*/)
  569.         {
  570.                 border_size = (unsigned short)GetSystemMetrics(SM_CXFRAME);
  571.                 header_size = (unsigned short)(GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION));
  572.         }
  573.  
  574.         void GetClientSize(unsigned short &width, unsigned short &height)
  575.         {
  576.                 if (!ThreadDataStruct.hwnd) {width = 0; height = 0; return;}
  577.                 RECT rect;
  578.                 GetClientRect(ThreadDataStruct.hwnd, &rect);
  579.                 width = (unsigned short)(rect.right - rect.left);
  580.                 height = (unsigned short)(rect.bottom - rect.top);
  581.         }
  582.  
  583.         void GetClientSize(unsigned short &width, unsigned short &height, TThreadData thread_data)
  584.         {
  585.                 if (!((TThreadDataStruct*)thread_data)->hwnd) {width = 0; height = 0; return;}
  586.                 RECT rect;
  587.                 GetClientRect(((TThreadDataStruct*)thread_data)->hwnd, &rect);
  588.                 width = (unsigned short)(rect.right - rect.left);
  589.                 height = (unsigned short)(rect.bottom - rect.top);
  590.         }
  591.  
  592.         void GetClientSize(unsigned short &width, unsigned short &height, int win_width, int win_height)
  593.         {
  594.                 win_width -= 2*GetSystemMetrics(SM_CXFRAME);
  595.                 win_height -= 2*GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION);
  596.                 if (win_width < 0) win_width = 0;
  597.                 if (win_height < 0) win_height = 0;
  598.                 width = (unsigned short)win_width; height = (unsigned short)win_height;
  599.         }
  600.  
  601.         void GetClientSize(unsigned short &width, unsigned short &height,
  602.                                                 int win_width, int win_height, TThreadData /*thread_data*/)
  603.         {
  604.                 win_width -= 2*GetSystemMetrics(SM_CXFRAME);
  605.                 win_height -= 2*GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION);
  606.                 if (win_width < 0) win_width = 0;
  607.                 if (win_height < 0) win_height = 0;
  608.                 width = (unsigned short)win_width; height = (unsigned short)win_height;
  609.         }
  610.  
  611.         void GetScreenSize(unsigned short &width, unsigned short &height)
  612.         {
  613.                 width = (unsigned short)GetSystemMetrics(SM_CXFULLSCREEN);
  614.                 height = (unsigned short)GetSystemMetrics(SM_CYFULLSCREEN);
  615.         }
  616.  
  617.         TMutex::TMutex() {mut = (unsigned int)CreateMutex(NULL, FALSE, NULL);}
  618.  
  619.         TMutex::~TMutex() {if (mut) {CloseHandle((HANDLE)mut); mut = 0;}}
  620.  
  621.         TRecMutex::TRecMutex() {mut = (unsigned int)CreateMutex(NULL, FALSE, NULL);}
  622.  
  623.         TRecMutex::~TRecMutex() {if (mut) {CloseHandle((HANDLE)mut); mut = 0;}}
  624.  
  625.         void InitMutex(TMutex *mutex) {if (!mutex->mut) *mutex = TMutex();}
  626.  
  627.         void InitRecMutex(TRecMutex *mutex) {if (!mutex->mut) *mutex = TRecMutex();}
  628.  
  629.         bool TryLock(TMutex *mutex)
  630.         {
  631.                 DWORD ret = WaitForSingleObject((HANDLE)mutex->mut, 0);
  632.                 return ret == WAIT_OBJECT_0 || ret == WAIT_ABANDONED;
  633.         }
  634.  
  635.         bool TryLock(TRecMutex *mutex, unsigned int /*pid*/)
  636.         {
  637.                 DWORD ret = WaitForSingleObject((HANDLE)mutex->mut, 0);
  638.                 return ret == WAIT_OBJECT_0 || ret == WAIT_ABANDONED;
  639.         }
  640.  
  641.         bool TryLock(TRecMutex *mutex)
  642.         {
  643.                 DWORD ret = WaitForSingleObject((HANDLE)mutex->mut, 0);
  644.                 return ret == WAIT_OBJECT_0 || ret == WAIT_ABANDONED;
  645.         }
  646.  
  647.         bool TryLock(TRecMutex *mutex, TThreadData /*thread_data*/)
  648.         {
  649.                 DWORD ret = WaitForSingleObject((HANDLE)mutex->mut, 0);
  650.                 return ret == WAIT_OBJECT_0 || ret == WAIT_ABANDONED;
  651.         }
  652.  
  653.         void Lock(TMutex *mutex)
  654.         {
  655.                 WaitForSingleObject((HANDLE)mutex->mut, INFINITE);
  656.         }
  657.  
  658.         void Lock(TRecMutex *mutex, unsigned int /*pid*/)
  659.         {
  660.                 WaitForSingleObject((HANDLE)mutex->mut, INFINITE);
  661.         }
  662.  
  663.         void Lock(TRecMutex *mutex)
  664.         {
  665.                 WaitForSingleObject((HANDLE)mutex->mut, INFINITE);
  666.         }
  667.  
  668.         void Lock(TRecMutex *mutex, TThreadData /*thread_data*/)
  669.         {
  670.                 WaitForSingleObject((HANDLE)mutex->mut, INFINITE);
  671.         }
  672.  
  673.         bool LockTime(TMutex *mutex, unsigned int time)
  674.         {
  675.                 DWORD ret = WaitForSingleObject((HANDLE)mutex->mut, time * 10);
  676.                 return ret == WAIT_OBJECT_0 || ret == WAIT_ABANDONED;
  677.         }
  678.  
  679.         bool LockTime(TRecMutex *mutex, unsigned int time, unsigned int /*pid*/)
  680.         {
  681.                 DWORD ret = WaitForSingleObject((HANDLE)mutex->mut, time * 10);
  682.                 return ret == WAIT_OBJECT_0 || ret == WAIT_ABANDONED;
  683.         }
  684.  
  685.         bool LockTime(TRecMutex *mutex, unsigned int time)
  686.         {
  687.                 DWORD ret = WaitForSingleObject((HANDLE)mutex->mut, time * 10);
  688.                 return ret == WAIT_OBJECT_0 || ret == WAIT_ABANDONED;
  689.         }
  690.  
  691.         bool LockTime(TRecMutex *mutex, unsigned int time, TThreadData /*thread_data*/)
  692.         {
  693.                 DWORD ret = WaitForSingleObject((HANDLE)mutex->mut, time * 10);
  694.                 return ret == WAIT_OBJECT_0 || ret == WAIT_ABANDONED;
  695.         }
  696.  
  697.         void UnLock(TMutex *mutex)
  698.         {
  699.                 ReleaseMutex((HANDLE)mutex->mut);
  700.         }
  701.  
  702.         void UnLock(TRecMutex *mutex, unsigned int /*pid*/)
  703.         {
  704.                 ReleaseMutex((HANDLE)mutex->mut);
  705.         }
  706.  
  707.         void UnLock(TRecMutex *mutex)
  708.         {
  709.                 ReleaseMutex((HANDLE)mutex->mut);
  710.         }
  711.  
  712.         void UnLock(TRecMutex *mutex, TThreadData /*thread_data*/)
  713.         {
  714.                 ReleaseMutex((HANDLE)mutex->mut);
  715.         }
  716.  
  717.         void DebugPutChar(char c)
  718.         {
  719.                 DWORD num_written;
  720.                 WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), &c, 1, &num_written, NULL);
  721.         }
  722.  
  723.         void DebugPutString(const char *s)
  724.         {
  725.                 DWORD num_written;
  726.                 WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), s, strlen(s), &num_written, NULL);
  727.         }
  728.  
  729.         int GetKey()
  730.         {
  731.                 if (ThreadDataStruct.keys->empty()) return -1;
  732.                 else
  733.                 {
  734.                         unsigned char c = ThreadDataStruct.keys->front();
  735.                         ThreadDataStruct.keys->pop_front();
  736.                         return c;
  737.                 }
  738.         }
  739.  
  740.         int GetMouseButton()
  741.         {
  742.                 return ThreadDataStruct.mouse_state;
  743.         }
  744.  
  745.         void GetMousePosition(short &x, short &y, bool absolute)
  746.         {
  747.                 POINT point;
  748.                 if (!GetCursorPos(&point)) {x = -1; y = -1;}
  749.                 else if (absolute) {x = (short)point.x; y = (short)point.y;}
  750.                 else
  751.                 {
  752.                         RECT rect;
  753.                         if (!ThreadDataStruct.hwnd || !GetWindowRect(ThreadDataStruct.hwnd, &rect))
  754.                         {
  755.                                 x = -1; y = -1;
  756.                         }
  757.                         else
  758.                         {
  759.                                 x = (short)(point.x - rect.left);
  760.                                 y = (short)(point.y - rect.top);
  761.                         }
  762.                 }
  763.         }
  764.  
  765.         void GetMousePosPicture(short &x, short &y)
  766.         {
  767.                 POINT point;
  768.                 if (!GetCursorPos(&point)) {x = -1; y = -1;}
  769.                 else if (!ThreadDataStruct.hwnd || !ScreenToClient(ThreadDataStruct.hwnd, &point))
  770.                 {
  771.                         x = -1; y = -1;
  772.                 }
  773.                 else
  774.                 {
  775.                         x = (short)point.x;
  776.                         y = (short)point.y;
  777.                 }
  778.         }
  779.  
  780.         bool WasThreadCreated() {return WasThreadCreatedBool;}
  781.        
  782.         unsigned int CreateThread(void *user, unsigned int stack_size, void* /*stack_end*/)
  783.         {
  784.                 unsigned long pid = -1;
  785.                 WasThreadCreatedBool = true;
  786.                 if (!::CreateThread(NULL, stack_size, (LPTHREAD_START_ROUTINE)ThreadMainProc, user, 0, &pid))
  787.                 {
  788.                         return -1;
  789.                 }
  790.                 return pid;
  791.         }
  792.  
  793.         unsigned int StrLen(const char *str) {return ::strlen(str);}
  794.  
  795.         char *StrCopy(char *dest, const char *src) {return ::strcpy(dest, src);}
  796.  
  797.         void *MemCopy(void *dest, const void *src, unsigned int n) {return ::memcpy(dest, src, n);}
  798.  
  799.         void *MemSet(void *s, char c, unsigned int n) {return ::memset(s, c, n);}
  800.  
  801.         double Floor(double x) {return floor(x);}
  802.  
  803.         void *Alloc(unsigned int size) {return malloc(size);}
  804.  
  805.         void *ReAlloc(void *mem, unsigned int size) {return realloc(mem, size);}
  806.        
  807.         void Free(void *mem) {free(mem);}
  808.  
  809.         TFileData FileOpen(const char *name, unsigned int /*buffer_length*/)
  810.         {
  811.                 if (!name || !name[0]) return 0;
  812.                 TFileData file_data = (TFileData)Alloc(sizeof(unsigned int) +
  813.                                         strlen(file_prefix) + strlen(name) + 1);
  814.                 if (!file_data) return 0;
  815.                 file_data->data = 0;
  816.                 strcpy((char*)file_data + sizeof(unsigned int), file_prefix);
  817.                 strcat((char*)file_data + sizeof(unsigned int), name);
  818.                 return file_data;
  819.         }
  820.  
  821.         int FileClose(TFileData file_data)
  822.         {
  823.                 if (!file_data) return -1;
  824.                 if (file_data->data) CloseHandle((HANDLE)file_data->data);
  825.                 Free(file_data);
  826.                 return 0;
  827.         }
  828.  
  829.         bool FileEof(TFileData file_data)
  830.         {
  831.                 unsigned int pos;
  832.                 if (FileTestRead(file_data) < 0) return false;
  833.                 pos = SetFilePointer((HANDLE)file_data->data, 0, NULL, FILE_CURRENT);
  834.                 if (pos == -1) return false;
  835.                 return pos >= GetFileSize((HANDLE)file_data->data, NULL);
  836.         }
  837.  
  838.         unsigned int FileGetPosition(TFileData file_data)
  839.         {
  840.                 unsigned int pos;
  841.                 if (FileTestRead(file_data) < 0) return 0;
  842.                 pos = SetFilePointer((HANDLE)file_data->data, 0, NULL, FILE_CURRENT);
  843.                 return (pos == -1) ? 0 : pos;
  844.         }
  845.  
  846.         void FileSetPosition(TFileData file_data, unsigned int pos)
  847.         {
  848.                 if (FileTestRead(file_data) < 0) return;
  849.                 SetFilePointer((HANDLE)file_data->data, pos, NULL, FILE_BEGIN);
  850.         }
  851.  
  852.         void FileReset(TFileData file_data)
  853.         {
  854.                 if (!file_data || !file_data->data) return;
  855.                 FlushFileBuffers((HANDLE)file_data->data);
  856.         }
  857.  
  858.         unsigned int FileGetLength(TFileData file_data)
  859.         {
  860.                 if (FileTestRead(file_data) < 0) return -1;
  861.                 return GetFileSize((HANDLE)file_data->data, NULL);
  862.         }
  863.  
  864.         int FileTestRead(TFileData file_data)
  865.         {
  866.                 if (!file_data) return -1;
  867.                 if (!file_data->data)
  868.                 {
  869.                         file_data->data = (unsigned int)CreateFile((char*)file_data + sizeof(unsigned int),
  870.                                         GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING,
  871.                                         FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, 0);
  872.                         if (!file_data->data) return -512;
  873.                 }
  874.                 return 0;
  875.         }
  876.  
  877.         int FileRead(TFileData file_data, void *mem, int size)
  878.         {
  879.                 if (!file_data || !mem || size <= 0) return -1;
  880.                 int res = FileTestRead(file_data);
  881.                 if (res < 0) return res;
  882.                 if (!ReadFile((HANDLE)file_data->data, mem, size, (unsigned long*)&res, NULL))
  883.                 {
  884.                         return -512;
  885.                 }
  886.                 return (res >= 0) ? res : (-1);
  887.         }
  888. }
  889.  
  890. bool CheckAllocConsole(LPSTR lpCmdLine)
  891. {
  892.         char Console[] = "-console";
  893.         int ConsoleL = ::strlen(Console);
  894.         char *s;
  895.         for (s = lpCmdLine; *s; s++)
  896.         {
  897.                 if ((s == lpCmdLine || isspace(s[-1])) && memcmp(s, Console, ConsoleL) == 0 &&
  898.                         (!s[ConsoleL] || isspace(s[ConsoleL])))
  899.                 {
  900.                         AllocConsole();
  901.                         SetConsoleTitle("Debug Console");
  902.                         return true;
  903.                 }
  904.         }
  905.         return false;
  906. }
  907.  
  908. int APIENTRY WinMain(HINSTANCE hInstance,
  909.                                          HINSTANCE /*hPrevInstance*/,
  910.                                          LPSTR     lpCmdLine,
  911.                                          int       nCmdShow)
  912. {
  913.         ::nCmdShow = nCmdShow;
  914.         ::hInstance = hInstance;
  915.         CheckAllocConsole(lpCmdLine);
  916.         Main();
  917.         //::ExitThread(0);
  918.         return 0;
  919. }
  920.  
  921.