0031171: Draw - support Unicode input / output in console on Windows
[occt.git] / src / Draw / CommandWindow.cxx
1 // Created on: 1998-08-06
2 // Created by: Administrateur Atelier MDL
3 // Copyright (c) 1998-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #ifdef _WIN32
18 #include <windows.h>
19
20 #include <Draw_Window.hxx>
21 #include <Draw_Appli.hxx>
22 #include <TCollection_AsciiString.hxx>
23
24 #include <MainWindow.h>
25 #include <CommandWindow.h>
26
27 #define CLIENTWND 0
28
29 #define THE_PROMPT L"Command >> "
30 #define COMMANDSIZE 1000 // Max nb of characters for a command
31
32 Standard_Boolean Draw_Interprete (const char* command);
33
34 namespace
35 {
36   // Definition of global variables
37   static WNDPROC OldEditProc;  // Save the standard procedure of the edition (sub-class)
38 }
39
40 /*--------------------------------------------------------*\
41 |  CREATE COMMAND WINDOW PROCEDURE
42 \*--------------------------------------------------------*/
43 HWND CreateCommandWindow(HWND hWnd, int /*nitem*/)
44 {
45   HINSTANCE hInstance = (HINSTANCE )GetWindowLongPtrW (hWnd, GWLP_HINSTANCE);
46
47         HWND hWndCommand = CreateWindowW (COMMANDCLASS, COMMANDTITLE,
48                                     WS_CLIPCHILDREN | WS_OVERLAPPED | WS_THICKFRAME | WS_CAPTION,
49                                     0, 0, 400, 100,
50                                     hWnd, NULL, hInstance, NULL);
51
52         ShowWindow(hWndCommand, SW_SHOW);       
53         return hWndCommand;
54 }
55
56
57 /*--------------------------------------------------------*\
58 |  COMMAND WINDOW PROCEDURE
59 \*--------------------------------------------------------*/
60 LRESULT APIENTRY CommandProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam )
61 {
62   switch (wMsg)
63   {
64     case WM_CREATE:
65     {
66       CommandCreateProc (hWnd);
67       HWND hWndEdit = (HWND )GetWindowLongPtrW (hWnd, CLIENTWND);
68       SendMessageW (hWndEdit, EM_REPLACESEL, 0, (LPARAM )THE_PROMPT);
69       return 0;
70     }
71     case WM_GETMINMAXINFO:
72     {
73       MINMAXINFO* lpmmi = (MINMAXINFO* )lParam;
74       lpmmi->ptMinTrackSize.x = 200;
75       lpmmi->ptMinTrackSize.y = 50;
76       return 0;
77     }
78     case WM_SIZE:
79     {
80       HWND hWndEdit = (HWND )GetWindowLongPtrW(hWnd, CLIENTWND);
81       MoveWindow (hWndEdit, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
82       // Place the cursor at the end of the buffer
83       // Nb of characters in the buffer of hWndEdit
84       LRESULT index = SendMessageW (hWnd, WM_GETTEXTLENGTH, 0l, 0l);
85       SendMessageW (hWnd, EM_SETSEL, index, index);
86       return 0;
87     }
88     case WM_SETFOCUS:
89     {
90       HWND hWndEdit = (HWND )GetWindowLongPtrW (hWnd, CLIENTWND);
91       SetFocus (hWndEdit);
92       return 0;
93     }
94   }
95   return DefWindowProcW(hWnd, wMsg, wParam, lParam);
96 }
97
98 LRESULT APIENTRY EditProc(HWND, UINT, WPARAM, LPARAM);
99 /*--------------------------------------------------------*\
100 |  COMMAND CREATE PROCEDURE
101 \*--------------------------------------------------------*/
102 BOOL CommandCreateProc(HWND hWnd)
103 {
104   HINSTANCE hInstance = (HINSTANCE)GetWindowLongPtrW(hWnd, GWLP_HINSTANCE);
105   HWND hWndEdit = CreateWindowW (L"EDIT", NULL,
106                                  WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL,
107                                  0, 0, 0, 0,
108                                  hWnd, 0,
109                                  hInstance, NULL);
110
111   // Save hWndEdit in the extra memory in 0 of CommandWindow
112   if (hWndEdit != NULL)
113   {
114     SetWindowLongPtrW  (hWnd, CLIENTWND, (LONG_PTR )hWndEdit);
115   }
116
117   // Sub-Class of the window
118   //-------
119   // Save the pointer on the existing procedure
120   OldEditProc = (WNDPROC )GetWindowLongPtrW (hWndEdit, GWLP_WNDPROC);
121   // Implement the new function
122   SetWindowLongPtrW (hWndEdit, GWLP_WNDPROC, (LONG_PTR) EditProc);
123   return TRUE;
124 }
125
126 /*--------------------------------------------------------*\
127 |  GET COMMAND
128 |    
129 \*--------------------------------------------------------*/
130 int GetCommand (HWND hWnd, wchar_t* theBuffer)
131 {
132   bool isAgain = true;
133   wchar_t aTempBuff[COMMANDSIZE] = L"";
134
135   int aNbLine = (int )SendMessageW (hWnd, EM_GETLINECOUNT, 0l, 0l);
136   int aNbChar = 0;
137   theBuffer[0] = L'\0';
138   while (isAgain && aNbLine > -1 && aNbChar < COMMANDSIZE - 1)
139   {
140     wcscat (theBuffer, _wcsrev (aTempBuff));
141     // Initialization of the 1st WORD to the nb of characters to read
142     WORD* aNbMaxChar = (WORD* )aTempBuff;
143     *aNbMaxChar = COMMANDSIZE - 1;
144       
145     const int aNbCharRead = (int )SendMessageW (hWnd, EM_GETLINE, aNbLine - 1, (LPARAM )aTempBuff);
146     aNbChar += aNbCharRead;
147     const bool isPromp = wcsncmp (aTempBuff, THE_PROMPT, 10) == 0;
148     aTempBuff[aNbCharRead]='\0';
149     if (isPromp)
150     {
151       wcscat (theBuffer, _wcsrev (aTempBuff));
152       isAgain = false;
153     }
154     aNbLine -= 1;
155   }
156   _wcsrev (theBuffer);
157   return aNbChar;
158 }
159
160 /*--------------------------------------------------------*\
161 |  EDIT WINDOW PROCEDURE
162 \*--------------------------------------------------------*/
163 LRESULT APIENTRY EditProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam )
164 {
165         static LRESULT nbline; // Process the buffer of the edit window 
166   switch (wMsg)
167   {
168     case WM_CHAR:
169     {
170       if (console_semaphore != WAIT_CONSOLE_COMMAND)
171       {
172         return 0;
173       }
174       switch (LOWORD(wParam))
175       {
176         // Overload of character \n
177         case 0x0d:
178         {
179           wchar_t aCmdBuffer[COMMANDSIZE];
180           GetCommand (hWnd, aCmdBuffer);
181           // Standard processing
182           CallWindowProcW (OldEditProc, hWnd, wMsg, wParam, lParam);
183           // Display of PROMPT
184           POINT pos;
185           GetCaretPos (&pos);
186           SendMessageW (hWnd, EM_REPLACESEL, 0, (LPARAM )THE_PROMPT);
187           // Display the command in the console
188           //std::wcout << aCmdBuffer << std::endl; // wcout does not work well with UTF-8
189           TCollection_AsciiString aCmdUtf8 (aCmdBuffer + sizeof(THE_PROMPT) / sizeof(wchar_t) - 1);
190           std::cout << aCmdUtf8.ToCString() << std::endl;
191           //Draw_Interprete (aCmdUtf8.ToCString());
192           //if (toExit) { DestroyProc (hWnd); }
193           wcscpy_s (console_command, aCmdBuffer + sizeof(THE_PROMPT) / sizeof(wchar_t) - 1);
194           console_semaphore = HAS_CONSOLE_COMMAND;
195           // Purge the buffer
196           nbline = SendMessageW (hWnd, EM_GETLINECOUNT, 0l, 0l);
197           if (nbline > 200)
198           {
199             nbline = 0;
200             GetCommand (hWnd, aCmdBuffer);
201             LRESULT index = SendMessageW (hWnd, EM_LINEINDEX, 100, 0);
202             SendMessageW (hWnd, EM_SETSEL, 0, index);
203             SendMessageW (hWnd, WM_CUT, 0, 0);
204             // Place the cursor at the end of text
205             index =  SendMessageW (hWnd, WM_GETTEXTLENGTH, 0l, 0l);
206             SendMessageW (hWnd, EM_SETSEL, index, index);
207           }
208           return 0;
209         }
210         default:
211         {
212           if (IsAlphanumeric ((Standard_Character)LOWORD(wParam)))
213           {
214             // Place the cursor at the end of text before display
215             LRESULT index =  SendMessageW (hWnd, WM_GETTEXTLENGTH, 0l, 0l);
216             SendMessageW (hWnd, EM_SETSEL, index, index);
217             CallWindowProcW (OldEditProc, hWnd, wMsg, wParam, lParam);
218             return 0;
219           }
220           break;
221         }
222       }
223       break;
224     }
225     case WM_KEYDOWN:
226     {
227       if (console_semaphore != WAIT_CONSOLE_COMMAND)
228       {
229         return 0;
230       }
231       break;
232     }
233   }
234   return CallWindowProcW (OldEditProc, hWnd, wMsg, wParam, lParam);
235 }
236 #endif