sdk: const correctness
[sdk] / ecere / src / gui / drivers / Win32ConsoleInterface.ec
1 namespace gui::drivers;
2
3 import "instance"
4
5 #if defined(__WIN32__)
6
7 #define WIN32_LEAN_AND_MEAN
8 #define Method _Method
9 #define String _String
10 #include <windows.h>
11 #include <mmsystem.h>
12
13 #undef Method
14 #undef String
15
16 import "Display"
17
18 default:
19 WINBASEAPI HWND WINAPI GetConsoleWindow ();
20
21 private:
22
23 static HANDLE hStdin, hStdout;
24 static byte keys[256];
25 static Point mousePosition;
26 static Box mouseRange;
27
28 default:
29 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit;
30 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown;
31 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp;
32
33 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMouseMove;
34 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonDown;
35 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonDown;
36 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonDown;
37 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftDoubleClick;
38 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightDoubleClick;
39 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleDoubleClick;
40 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonUp;
41 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonUp;
42 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonUp;
43
44 private:
45
46 /****************************************************************************
47    /// DRIVER IMPLEMENTATION /////////////
48 ****************************************************************************/
49
50 class Win32ConsoleInterface : Interface
51 {
52    class_property(name) = "Win32Console";
53
54    // --- User Interface System ---
55    bool Initialize()
56    {
57       CONSOLE_CURSOR_INFO cursor;
58
59       // FreeConsole();
60       AllocConsole();
61       {
62          WINDOWPLACEMENT placement = { 0 };
63
64          placement.length = sizeof(WINDOWPLACEMENT);
65          placement.showCmd = SW_NORMAL;
66          placement.rcNormalPosition.top = 10;
67          placement.rcNormalPosition.left = 10;
68          placement.rcNormalPosition.right = 810;
69          placement.rcNormalPosition.bottom = 610;
70          SetWindowPlacement(GetConsoleWindow(), &placement);
71          ShowWindow(GetConsoleWindow(), SW_SHOW);
72          SetForegroundWindow(GetConsoleWindow());
73       }
74
75       hStdin = GetStdHandle(STD_INPUT_HANDLE);
76       SetConsoleMode(hStdin, ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT);
77       hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
78       //SetConsoleMode(hStdout, 0);
79       FillBytes(keys, 0, sizeof(keys));
80
81       SetConsoleTitle(guiApp.desktop.text ? guiApp.desktop.text : "");
82       cursor.bVisible = FALSE;
83       cursor.dwSize = 100;
84       SetConsoleCursorInfo(hStdout, &cursor);
85       SetTimer(null, 0, (uint)(1000.0 / 18.2), null);
86
87         return true;
88    }
89
90    void Terminate()
91    {
92       CONSOLE_CURSOR_INFO cursor;
93       SetConsoleMode(hStdout, ENABLE_PROCESSED_OUTPUT);
94       cursor.bVisible = TRUE;
95       cursor.dwSize = 100;
96       SetConsoleCursorInfo(hStdout, &cursor);
97       DumpErrors(true);
98
99       // ShowWindow(GetConsoleWindow(), SW_HIDE);
100       /*
101       FreeConsole();
102       if(AllocConsole())
103       */
104       {
105          // SetForegroundWindow(GetActiveWindow());
106          WINDOWPLACEMENT placement = { 0 };
107          placement.length = sizeof(WINDOWPLACEMENT);
108          placement.showCmd = SW_HIDE;
109          SetWindowPlacement(GetConsoleWindow(), &placement);
110       }
111    }
112
113    bool ProcessInput(bool processAll)
114    {
115       DWORD numInput;
116       int c;
117       GetNumberOfConsoleInputEvents(hStdin, &numInput);
118       if(numInput)
119       {
120          for(c = 0; c<numInput; c++)
121          {
122             INPUT_RECORD event;
123             DWORD readInputs;
124             ReadConsoleInput(hStdin, &event, 1, &readInputs);
125             switch(event.EventType)
126             {
127                case KEY_EVENT:
128                {
129                   byte key = (byte)event.Event.KeyEvent.wVirtualScanCode;
130                   byte ch = event.Event.KeyEvent.uChar.AsciiChar;
131                   Key keyFlags;
132
133                   if(event.Event.KeyEvent.dwControlKeyState & ENHANCED_KEY)
134                      key = (byte)GetExtendedKey(key);
135
136                   keyFlags = key;
137                   if(event.Event.KeyEvent.dwControlKeyState&SHIFT_PRESSED)
138                      keyFlags.shift = true;
139                   if(event.Event.KeyEvent.dwControlKeyState&LEFT_ALT_PRESSED ||
140                      event.Event.KeyEvent.dwControlKeyState&RIGHT_ALT_PRESSED)
141                      keyFlags.alt = true;
142                   if(event.Event.KeyEvent.dwControlKeyState&LEFT_CTRL_PRESSED ||
143                      event.Event.KeyEvent.dwControlKeyState&RIGHT_CTRL_PRESSED)
144                      keyFlags.ctrl = true;
145
146                   if(event.Event.KeyEvent.bKeyDown)
147                   {
148                      if(keys[key])
149                         guiApp.desktop.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit,keyFlags,ch);
150                      else
151                      {
152                         keys[key] = (byte)bool::true;
153                         guiApp.desktop.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown,keyFlags,ch);
154                      }
155                   }
156                   else
157                   {
158                      keys[key] = (byte)bool::false;
159                      guiApp.desktop.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp,keyFlags,ch);
160                   }
161                   break;
162                }
163                case MOUSE_EVENT:
164                {
165                   Modifiers keyFlags = 0;
166                   static MouseButtons lastButtonState = 0;
167                   MouseButtons buttonState = event.Event.MouseEvent.dwButtonState;
168
169                   if(event.Event.MouseEvent.dwControlKeyState&SHIFT_PRESSED)
170                      keyFlags.shift = true;
171                   if(event.Event.MouseEvent.dwControlKeyState&LEFT_ALT_PRESSED ||
172                      event.Event.MouseEvent.dwControlKeyState&RIGHT_ALT_PRESSED)
173                      keyFlags.alt = true;
174                   if(event.Event.MouseEvent.dwControlKeyState&LEFT_CTRL_PRESSED ||
175                      event.Event.MouseEvent.dwControlKeyState&RIGHT_CTRL_PRESSED)
176                      keyFlags.ctrl = true;
177
178                   switch(event.Event.MouseEvent.dwEventFlags)
179                   {
180                      case MOUSE_MOVED:
181                      {
182                         int x = event.Event.MouseEvent.dwMousePosition.X * textCellW;
183                         int y = event.Event.MouseEvent.dwMousePosition.Y * textCellH;
184
185                         x = Min(Max(x, mouseRange.left), mouseRange.right);
186                         y = Min(Max(y, mouseRange.top), mouseRange.bottom);
187
188                         if(x != mousePosition.x || y != mousePosition.y)
189                         {
190                            mousePosition.x = x;
191                            mousePosition.y = y;
192                            guiApp.desktop.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMouseMove, x, y, &keyFlags, false, false);
193                         }
194                         break;
195                      }
196                      case DOUBLE_CLICK:
197                         if(buttonState.left && !(lastButtonState.left))
198                         {
199                            if(!guiApp.desktop.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftDoubleClick,
200                               mousePosition.x, mousePosition.y, &keyFlags, false, true))
201                               break;
202                         }
203                         else if(buttonState.middle && !(lastButtonState.middle))
204                         {
205                            if(!guiApp.desktop.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleDoubleClick,
206                               mousePosition.x, mousePosition.y, &keyFlags, false, true))
207                               break;
208                         }
209                         else if(buttonState.right && !(lastButtonState.right))
210                         {
211                            if(!guiApp.desktop.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightDoubleClick,
212                               mousePosition.x, mousePosition.y, &keyFlags, false, true))
213                               break;
214                         }
215                      default:
216                         if(buttonState.left && !(lastButtonState.left))
217                            guiApp.desktop.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonDown,
218                               mousePosition.x, mousePosition.y, &keyFlags, false,
219                               (event.Event.MouseEvent.dwEventFlags == DOUBLE_CLICK) ? false : true) ;
220                         else if(buttonState.middle && !(lastButtonState.middle))
221                            guiApp.desktop.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonDown,
222                               mousePosition.x, mousePosition.y, &keyFlags, false,
223                               (event.Event.MouseEvent.dwEventFlags == DOUBLE_CLICK) ? false : true);
224                         else if(buttonState.right && !(lastButtonState.right))
225                            guiApp.desktop.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonDown,
226                               mousePosition.x, mousePosition.y, &keyFlags, false,
227                               (event.Event.MouseEvent.dwEventFlags == DOUBLE_CLICK) ? false : true);
228                         else if(!(buttonState.left) && lastButtonState.left)
229                            guiApp.desktop.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonUp,
230                               mousePosition.x, mousePosition.y, &keyFlags, false, false);
231                         else if(!(buttonState.middle) && lastButtonState.middle)
232                            guiApp.desktop.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonUp,
233                               mousePosition.x, mousePosition.y, &keyFlags, false, false);
234                         else if(!(buttonState.right) && lastButtonState.right)
235                            guiApp.desktop.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonUp,
236                               mousePosition.x, mousePosition.y, &keyFlags, false, false);
237                   }
238                   lastButtonState = buttonState;
239                   break;
240                }
241                case WINDOW_BUFFER_SIZE_EVENT:
242                {
243                   COORD coord =
244                   {
245                      event.Event.WindowBufferSizeEvent.dwSize.X,
246                      event.Event.WindowBufferSizeEvent.dwSize.Y
247                   };
248                   SetConsoleScreenBufferSize(hStdout,coord);
249                   guiApp.SetDesktopPosition(0,0, coord.X * textCellW, coord.Y * textCellH, true);
250                   break;
251                }
252             }
253
254             if(!processAll) break;
255          }
256          return true;
257       }
258       return false;
259    }
260
261    void Wait()
262    {
263       void * objects[2] = { hStdin, *((uint **)guiApp.semaphore) };
264       if(MsgWaitForMultipleObjects(2, objects, FALSE, INFINITE, QS_TIMER) == WAIT_OBJECT_0 + 2)
265       {
266          MSG msg;
267          GetMessage(&msg, null,0,0);
268       }
269    }
270
271    void Lock(Window window)
272    {
273
274    }
275
276    void Unlock(Window window)
277    {
278
279    }
280
281    const char ** GraphicsDrivers(int * numDrivers)
282    {
283       static const char *graphicsDrivers[] = { "Win32Console" };
284       *numDrivers = sizeof(graphicsDrivers) / sizeof(char *);
285       return (const char **)graphicsDrivers;
286    }
287
288    void GetCurrentMode(bool * fullScreen, Resolution * resolution, PixelFormat * colorDepth, int * refreshRate)
289    {
290       *fullScreen = true;
291       *colorDepth = pixelFormatText;
292    }
293
294    void EnsureFullScreen(bool *fullScreen)
295    {
296       *fullScreen = true;
297    }
298
299    bool ScreenMode(bool fullScreen, Resolution resolution, PixelFormat colorDepth, int refreshRate, bool * textMode)
300    {
301       if(fullScreen)
302       {
303          CONSOLE_SCREEN_BUFFER_INFO info;
304
305          ChangeDisplaySettings(null, 0);
306
307          if(GetConsoleScreenBufferInfo(hStdout, &info))
308          {
309             COORD coord;
310             coord.X = info.srWindow.Right+1;
311             coord.Y = info.srWindow.Bottom+1;
312             SetConsoleScreenBufferSize(hStdout,coord);
313             guiApp.SetDesktopPosition(0,0, coord.X * textCellW, coord.Y * textCellH, false);
314             *textMode = true;
315             mouseRange.right = MAXINT;
316             mouseRange.bottom = MAXINT;
317               return true;
318          }
319       }
320       return false;
321    }
322
323    // --- Window Creation ---
324    void * CreateRootWindow(Window window)
325    {
326       return (void *) hStdout;
327    }
328
329    void DestroyRootWindow(void * windowHandle)
330    {
331    }
332
333    // -- Window manipulation ---
334
335    void SetRootWindowCaption(void * windowHandle, const char * name)
336    {
337       if(windowHandle == guiApp.desktop)
338          SetConsoleTitle(name);
339    }
340
341    void PositionRootWindow(void * windowHandle, int x, int y, int w, int h, bool move, bool resize)
342    {
343    }
344
345    void OrderRootWindow(void * windowHandle, bool topMost)
346    {
347    }
348
349    void SetRootWindowColor(Window window)
350    {
351    }
352
353    void OffsetWindow(void * windowHandle, int * x, int * y)
354    {
355
356    }
357
358    void UpdateRootWindow(void * windowHandle)
359    {
360    }
361
362    void SetRootWindowState(void * windowHandle, int state, bool visible)
363    {
364    }
365
366    void ActivateRootWindow(void * windowHandle)
367    {
368    }
369
370    // --- Mouse-based window movement ---
371
372    void StartMoving(void * windowHandle, int x, int y, bool fromKeyBoard)
373    {
374    }
375
376    void StopMoving(void * windowHandle)
377    {
378    }
379
380    // -- Mouse manipulation ---
381
382    void GetMousePosition(int *x, int *y)
383    {
384       *x = mousePosition.x;
385       *y = mousePosition.y;
386    }
387
388    void SetMousePosition(int x, int y)
389    {
390       mousePosition.x = x;
391       mousePosition.y = y;
392    }
393
394    void SetMouseRange(Window window, Box box)
395    {
396       if(box != null)
397       {
398          mouseRange = box;
399       }
400       else
401       {
402          mouseRange.left = mouseRange.top = 0;
403          mouseRange.right = mouseRange.bottom = MAXINT;
404       }
405    }
406
407    void SetMouseCapture(void * windowHandle)
408    {
409
410    }
411
412    // -- Mouse cursor ---
413
414    void SetMouseCursor(Window window, int cursor)
415    {
416
417    }
418
419    // --- Caret ---
420
421    void SetCaret(int x, int y, int size)
422    {
423       COORD coords = { (short)(x / textCellW), (short)(y / textCellH) };
424       CONSOLE_CURSOR_INFO cursor =
425       {
426          size ? size : 99,
427          (size && x >= 0 && y >= 0 && x < guiApp.desktop.clientSize.w && y < guiApp.desktop.clientSize.h) ? TRUE : FALSE
428       };
429       SetConsoleCursorInfo(hStdout, &cursor);
430       SetConsoleCursorPosition(hStdout, coords);
431    }
432
433    // --- Clipboard manipulation ---
434
435    void ClearClipboard()
436    {
437         if(OpenClipboard(null))
438         {
439          EmptyClipboard();
440            CloseClipboard();
441       }
442    }
443
444    bool AllocateClipboard(ClipBoard clipBoard, uint size)
445    {
446       bool result = false;
447       clipBoard.handle=GlobalAlloc(GHND | GMEM_DDESHARE, size);
448       if(clipBoard.handle)
449       {
450          clipBoard.text=GlobalLock(clipBoard.handle);
451          if(clipBoard.text)
452             result = true;
453          else
454             GlobalFree(clipBoard.handle);
455       }
456       return result;
457    }
458
459    bool SaveClipboard(ClipBoard clipBoard)
460    {
461       bool status = false;
462       if(clipBoard.handle)
463       {
464          GlobalUnlock(clipBoard.handle);
465            if(OpenClipboard(null))
466            {
467             EmptyClipboard();
468               if(SetClipboardData(CF_TEXT,clipBoard.handle))
469             {
470                  CloseClipboard();
471                status = true;
472             }
473          }
474          if(!status)
475             GlobalFree(clipBoard.handle);
476       }
477       return status;
478    }
479
480    bool LoadClipboard(ClipBoard clipBoard)
481    {
482       bool result = false;
483         if(OpenClipboard(null))
484         {
485          if((clipBoard.handle = GetClipboardData(CF_TEXT)))
486          {
487             if((clipBoard.text = GlobalLock(clipBoard.handle)))
488                result = true;
489          }
490          CloseClipboard();
491       }
492       return result;
493    }
494
495    void UnloadClipboard(ClipBoard clipBoard)
496    {
497       if(clipBoard.handle)
498          GlobalUnlock(clipBoard.handle);
499    }
500
501    // --- State based input ---
502
503    bool AcquireInput(void * windowHandle, bool state)
504    {
505       return false;
506    }
507
508    bool GetMouseState(MouseButtons * buttons, int * x, int * y)
509    {
510       bool result = false;
511
512       return result;
513    }
514
515    bool GetJoystickState(int device, Joystick joystick)
516    {
517       bool result = false;
518
519       return result;
520    }
521
522    bool GetKeyState(Key key)
523    {
524       if(key < 256)
525          return keys[key] != 0;
526       else if(key == capsState)
527          return GetKeyState(VK_CAPITAL) & 0x00000001;
528       else if(key == numState)
529          return GetKeyState(VK_NUMLOCK) & 0x00000001;
530       else if(key == scrollState)
531          return GetKeyState(VK_SCROLL) & 0x00000001;
532       return 0;
533    }
534 };
535
536 #endif