Execution control stuff
[wxWidgets.git] / src / os2 / utils.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: utils.cpp
3 // Purpose: Various utilities
4 // Author: David Webster
5 // Modified by:
6 // Created: 09/17/99
7 // RCS-ID: $Id$
8 // Copyright: (c) David Webster
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #ifndef WX_PRECOMP
16 #include "wx/setup.h"
17 #include "wx/utils.h"
18 #include "wx/app.h"
19 #include "wx/cursor.h"
20 #endif //WX_PRECOMP
21
22 #include "wx/os2/private.h"
23 #include "wx/timer.h"
24 #include "wx/intl.h"
25
26 #include <ctype.h>
27 #include <direct.h>
28
29 #include "wx/log.h"
30
31 #include <io.h>
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <errno.h>
37 #include <stdarg.h>
38
39 #define INCL_DOS
40 #define INCL_PM
41 #define INCL_GPI
42 #include <os2.h>
43 #include<netdb.h>
44 #define PURE_32
45 #include <upm.h>
46 #include <netcons.h>
47 #include <netbios.h>
48
49 static const wxChar WX_SECTION[] = _T("wxWindows");
50 static const wxChar eHOSTNAME[] = _T("HostName");
51 static const wxChar eUSERID[] = _T("UserId");
52 static const wxChar eUSERNAME[] = _T("UserName");
53
54 // For the following functions we SHOULD fill in support
55 // for Windows-NT (which I don't know) as I assume it begin
56 // a POSIX Unix (so claims MS) that it has some special
57 // functions beyond those provided by WinSock
58
59 // Get full hostname (eg. DoDo.BSn-Germany.crg.de)
60 bool wxGetHostName(
61 wxChar* zBuf
62 , int nMaxSize
63 )
64 {
65 #if wxUSE_NET_API
66 char zServer[256];
67 char zComputer[256];
68 unsigned short nLevel = 0;
69 unsigned char* zBuffer;
70 unsigned short nBuffer;
71 unsigned short* pnTotalAvail;
72
73 NetBios32GetInfo( (const unsigned char*)zServer
74 ,(const unsigned char*)zComputer
75 ,nLevel
76 ,zBuffer
77 ,nBuffer
78 ,pnTotalAvail
79 );
80 strcpy(zBuf, zServer);
81 #else
82 wxChar* zSysname;
83 const wxChar* zDefaultHost = _T("noname");
84
85 if ((zSysname = wxGetenv(_T("SYSTEM_NAME"))) == NULL)
86 {
87 ULONG n = ::PrfQueryProfileString( HINI_PROFILE
88 ,(PSZ)WX_SECTION
89 ,(PSZ)eHOSTNAME
90 ,(PSZ)zDefaultHost
91 ,(void*)zBuf
92 ,(ULONG)nMaxSize - 1
93 );
94 }
95 else
96 wxStrncpy(zBuf, zSysname, nMaxSize - 1);
97 zBuf[nMaxSize] = _T('\0');
98 #endif
99 return *zBuf ? TRUE : FALSE;
100 }
101
102 // Get user ID e.g. jacs
103 bool wxGetUserId(
104 wxChar* zBuf
105 , int nType
106 )
107 {
108 long lrc;
109 // UPM procs return 0 on success
110 lrc = U32ELOCU((unsigned char*)zBuf, (unsigned long *)&nType);
111 if (lrc == 0) return TRUE;
112 return FALSE;
113 }
114
115 bool wxGetUserName(
116 wxChar* zBuf
117 , int nMaxSize
118 )
119 {
120 #ifdef USE_NET_API
121 wxGetUserId( zBuf
122 ,nMaxSize
123 );
124 #else
125 wxStrncpy(zBuf, _T("Unknown User"), nMaxSize);
126 #endif
127 return TRUE;
128 }
129
130 int wxKill(
131 long lPid
132 , int nSig
133 )
134 {
135 return((int)::DosKillProcess(0, (PID)lPid));
136 }
137
138 //
139 // Execute a program in an Interactive Shell
140 //
141 bool wxShell(
142 const wxString& rCommand
143 )
144 {
145 wxChar* zShell;
146
147 if ((zShell = wxGetenv(_T("COMSPEC"))) == NULL)
148 zShell = _T("\\CMD.EXE");
149
150 wxChar zTmp[255];
151
152 if (rCommand != "")
153 wxSprintf( zTmp
154 ,"%s /c %s"
155 ,zShell
156 ,WXSTRINGCAST rCommand
157 );
158 else
159 wxStrcpy(zTmp, zShell);
160
161 return (wxExecute((wxChar*)zTmp, FALSE) != 0);
162 }
163
164 // Get free memory in bytes, or -1 if cannot determine amount (e.g. on UNIX)
165 long wxGetFreeMemory(
166 void* pMemptr
167 )
168 {
169 ULONG lSize;
170 ULONG lMemFlags;
171 APIRET rc;
172
173 lMemFlags = PAG_FREE;
174 rc = ::DosQueryMem(pMemptr, &lSize, &lMemFlags);
175 if (rc != 0)
176 return -1L;
177 return (long)lSize;
178 }
179
180 // Sleep for nSecs seconds. Attempt a Windows implementation using timers.
181 static bool inTimer = FALSE;
182
183 class wxSleepTimer: public wxTimer
184 {
185 public:
186 inline void Notify()
187 {
188 inTimer = FALSE;
189 Stop();
190 }
191 };
192
193 static wxTimer* wxTheSleepTimer = NULL;
194
195 void wxUsleep(
196 unsigned long ulMilliseconds
197 )
198 {
199 ::DosSleep(ulMilliseconds);
200 }
201
202 void wxSleep(
203 int nSecs
204 )
205 {
206 ::DosSleep(1000 * nSecs);
207 }
208
209 // Consume all events until no more left
210 void wxFlushEvents()
211 {
212 // wxYield();
213 }
214
215 // Output a debug mess., in a system dependent fashion.
216 void wxDebugMsg(
217 const wxChar* zFmt ...
218 )
219 {
220 va_list vAp;
221 static wxChar zBuffer[512];
222
223 if (!wxTheApp->GetWantDebugOutput())
224 return ;
225 va_start(vAp, zFmt);
226 sprintf(zBuffer, zFmt, vAp) ;
227 va_end(vAp);
228 }
229
230 // Non-fatal error: pop up message box and (possibly) continue
231 void wxError(
232 const wxString& rMsg
233 , const wxString& rTitle
234 )
235 {
236 wxSprintf(wxBuffer, "%s\nContinue?", WXSTRINGCAST rMsg);
237 if (::WinMessageBox( HWND_DESKTOP
238 ,NULL
239 ,(PSZ)wxBuffer
240 ,(PSZ)WXSTRINGCAST rTitle
241 ,0
242 ,MB_ICONEXCLAMATION | MB_YESNO
243 ) == MBID_YES)
244 wxExit();
245 }
246
247 // Fatal error: pop up message box and abort
248 void wxFatalError(
249 const wxString& rMsg
250 , const wxString& rTitle
251 )
252 {
253 unsigned long ulRc;
254
255 ulRc = ::WinMessageBox( HWND_DESKTOP
256 ,NULL
257 ,WXSTRINGCAST rMsg
258 ,WXSTRINGCAST rTitle
259 ,0
260 ,MB_NOICON | MB_OK
261 );
262 DosExit(EXIT_PROCESS, ulRc);
263 }
264
265 // Emit a beeeeeep
266 void wxBell()
267 {
268 DosBeep(1000,1000); // 1kHz during 1 sec.
269 }
270
271 // Chris Breeze 27/5/98: revised WIN32 code to
272 // detect WindowsNT correctly
273 int wxGetOsVersion(
274 int* pMajorVsn
275 , int* pMinorVsn
276 )
277 {
278 ULONG ulSysInfo[QSV_MAX] = {0};
279
280 if (::DosQuerySysInfo( 1L
281 ,QSV_MAX
282 ,(PVOID)ulSysInfo
283 ,sizeof(ULONG) * QSV_MAX
284 ))
285 {
286 *pMajorVsn = ulSysInfo[QSV_VERSION_MAJOR];
287 *pMinorVsn = ulSysInfo[QSV_VERSION_MINOR];
288 return wxWINDOWS_OS2;
289 }
290 return wxWINDOWS; // error if we get here, return generic value
291 }
292
293 // Reading and writing resources (eg WIN.INI, .Xdefaults)
294 #if wxUSE_RESOURCES
295 bool wxWriteResource(
296 const wxString& rSection
297 , const wxString& rEntry
298 , const wxString& rValue
299 , const wxString& rFile
300 )
301 {
302 HAB hab;
303 HINI hIni;
304
305 if (rFile != "")
306 {
307 hIni = ::PrfOpenProfile(hab, (PSZ)WXSTRINGCAST rFile);
308 if (hIni != 0L)
309 {
310 return (::PrfWriteProfileString( hIni
311 ,(PSZ)WXSTRINGCAST rSection
312 ,(PSZ)WXSTRINGCAST rEntry
313 ,(PSZ)WXSTRINGCAST rValue
314 ));
315 }
316 }
317 else
318 return (::PrfWriteProfileString( HINI_PROFILE
319 ,(PSZ)WXSTRINGCAST rSection
320 ,(PSZ)WXSTRINGCAST rEntry
321 ,(PSZ)WXSTRINGCAST rValue
322 ));
323 return FALSE;
324 }
325
326 bool wxWriteResource(
327 const wxString& rSection
328 , const wxString& rEntry
329 , float fValue
330 , const wxString& rFile
331 )
332 {
333 wxChar zBuf[50];
334
335 wxSprintf(zBuf, "%.4f", fValue);
336 return wxWriteResource( rSection
337 ,rEntry
338 ,zBuf
339 ,rFile
340 );
341 }
342
343 bool wxWriteResource(
344 const wxString& rSection
345 , const wxString& rEntry
346 , long lValue
347 , const wxString& rFile
348 )
349 {
350 wxChar zBuf[50];
351
352 wxSprintf(zBuf, "%ld", lValue);
353 return wxWriteResource( rSection
354 ,rEntry
355 ,zBuf
356 ,rFile
357 );
358 }
359
360 bool wxWriteResource(
361 const wxString& rSection
362 , const wxString& rEntry
363 , int lValue
364 , const wxString& rFile
365 )
366 {
367 wxChar zBuf[50];
368
369 wxSprintf(zBuf, "%d", lValue);
370 return wxWriteResource( rSection
371 ,rEntry
372 ,zBuf
373 ,rFile
374 );
375 }
376
377 bool wxGetResource(
378 const wxString& rSection
379 , const wxString& rEntry
380 , wxChar** ppValue
381 , const wxString& rFile
382 )
383 {
384 HAB hab;
385 HINI hIni;
386 static const wxChar zDefunkt[] = _T("$$default");
387
388 if (rFile != "")
389 {
390 hIni = ::PrfOpenProfile(hab, (PSZ)WXSTRINGCAST rFile);
391 if (hIni != 0L)
392 {
393 ULONG n = ::PrfQueryProfileString( hIni
394 ,(PSZ)WXSTRINGCAST rSection
395 ,(PSZ)WXSTRINGCAST rEntry
396 ,(PSZ)zDefunkt
397 ,(void*)wxBuffer
398 ,1000
399 );
400 if (n == 0L || wxStrcmp(wxBuffer, zDefunkt) == 0)
401 return FALSE;
402 }
403 else
404 return FALSE;
405 }
406 else
407 {
408 ULONG n = ::PrfQueryProfileString( HINI_PROFILE
409 ,(PSZ)WXSTRINGCAST rSection
410 ,(PSZ)WXSTRINGCAST rEntry
411 ,(PSZ)zDefunkt
412 ,(void*)wxBuffer
413 ,1000
414 );
415 if (n == 0L || wxStrcmp(wxBuffer, zDefunkt) == 0)
416 return FALSE;
417 }
418 if (*ppValue)
419 delete[] (*ppValue);
420 *ppValue = copystring(wxBuffer);
421 return TRUE;
422 }
423
424 bool wxGetResource(
425 const wxString& rSection
426 , const wxString& rEntry
427 , float* pValue
428 , const wxString& rFile
429 )
430 {
431 wxChar* zStr = NULL;
432 bool bSucc = wxGetResource( rSection
433 ,rEntry
434 ,(wxChar **)&zStr
435 ,rFile
436 );
437
438 if (bSucc)
439 {
440 *pValue = (float)wxStrtod(zStr, NULL);
441 delete[] zStr;
442 return TRUE;
443 }
444 else return FALSE;
445 }
446
447 bool wxGetResource(
448 const wxString& rSection
449 , const wxString& rEntry
450 , long* pValue
451 , const wxString& rFile
452 )
453 {
454 wxChar* zStr = NULL;
455 bool bSucc = wxGetResource( rSection
456 ,rEntry
457 ,(wxChar **)&zStr
458 ,rFile
459 );
460
461 if (bSucc)
462 {
463 *pValue = wxStrtol(zStr, NULL, 10);
464 delete[] zStr;
465 return TRUE;
466 }
467 else return FALSE;
468 }
469
470 bool wxGetResource(
471 const wxString& rSection
472 , const wxString& rEntry
473 , int* pValue
474 , const wxString& rFile
475 )
476 {
477 wxChar* zStr = NULL;
478 bool bSucc = wxGetResource( rSection
479 ,rEntry
480 ,(wxChar **)&zStr
481 ,rFile
482 );
483
484 if (bSucc)
485 {
486 *pValue = (int)wxStrtol(zStr, NULL, 10);
487 delete[] zStr;
488 return TRUE;
489 }
490 else return FALSE;
491 }
492 #endif // wxUSE_RESOURCES
493
494 // ---------------------------------------------------------------------------
495 // helper functions for showing a "busy" cursor
496 // ---------------------------------------------------------------------------
497
498 HCURSOR gs_wxBusyCursor = 0; // new, busy cursor
499 HCURSOR gs_wxBusyCursorOld = 0; // old cursor
500 static int gs_wxBusyCursorCount = 0;
501
502 // Set the cursor to the busy cursor for all windows
503 void wxBeginBusyCursor(
504 wxCursor* pCursor
505 )
506 {
507 if ( gs_wxBusyCursorCount++ == 0 )
508 {
509 gs_wxBusyCursor = (HCURSOR)pCursor->GetHCURSOR();
510 ::WinSetPointer(HWND_DESKTOP, (HPOINTER)gs_wxBusyCursor);
511 }
512 //else: nothing to do, already set
513 }
514
515 // Restore cursor to normal
516 void wxEndBusyCursor()
517 {
518 wxCHECK_RET( gs_wxBusyCursorCount > 0
519 ,_T("no matching wxBeginBusyCursor() for wxEndBusyCursor()")
520 );
521
522 if (--gs_wxBusyCursorCount == 0)
523 {
524 ::WinSetPointer(HWND_DESKTOP, (HPOINTER)gs_wxBusyCursorOld);
525 gs_wxBusyCursorOld = 0;
526 }
527 }
528
529 // TRUE if we're between the above two calls
530 bool wxIsBusy()
531 {
532 return (gs_wxBusyCursorCount > 0);
533 }
534
535 // ---------------------------------------------------------------------------
536 const wxChar* wxGetHomeDir(
537 wxString* pStr
538 )
539 {
540 wxString& rStrDir = *pStr;
541
542 // OS/2 has no idea about home,
543 // so use the working directory instead?
544
545 // 256 was taken from os2def.h
546 #ifndef MAX_PATH
547 # define MAX_PATH 256
548 #endif
549
550 char zDirName[256];
551 ULONG ulDirLen;
552
553 ::DosQueryCurrentDir(0, zDirName, &ulDirLen);
554 rStrDir = zDirName;
555 return rStrDir.c_str();
556 }
557
558 // Hack for OS/2
559 wxChar* wxGetUserHome (
560 const wxString& rUser
561 )
562 {
563 wxChar* zHome;
564 wxString sUser1(rUser);
565
566 if (sUser1 != _T(""))
567 {
568 wxChar zTmp[64];
569
570 if (wxGetUserId( zTmp
571 ,sizeof(zTmp)/sizeof(char)
572 ))
573 {
574 // Guests belong in the temp dir
575 if (wxStricmp(zTmp, _T("annonymous")) == 0)
576 {
577 if ((zHome = wxGetenv(_T("TMP"))) != NULL ||
578 (zHome = wxGetenv(_T("TMPDIR"))) != NULL ||
579 (zHome = wxGetenv(_T("TEMP"))) != NULL)
580 return *zHome ? zHome : (wxChar*)_T("\\");
581 }
582 if (wxStricmp(zTmp, WXSTRINGCAST sUser1) == 0)
583 sUser1 = _T("");
584 }
585 }
586 if (sUser1 == _T(""))
587 if ((zHome = wxGetenv(_T("HOME"))) != NULL)
588 {
589 wxStrcpy(wxBuffer, zHome);
590 Unix2DosFilename(wxBuffer);
591 return wxBuffer;
592 }
593 return NULL; // No home known!
594 }
595
596 // Check whether this window wants to process messages, e.g. Stop button
597 // in long calculations.
598 bool wxCheckForInterrupt(
599 wxWindow* pWnd
600 )
601 {
602 if(pWnd)
603 {
604 QMSG vMsg;
605 HAB hab;
606 HWND hwndFilter;
607 HWND hwndWin= (HWND) pWnd->GetHWND();
608
609 while(::WinPeekMsg(hab, &vMsg, hwndFilter, 0, 0, PM_REMOVE))
610 {
611 ::WinDispatchMsg(hab, &vMsg);
612 }
613 return TRUE;//*** temporary?
614 }
615 else
616 {
617 wxFAIL_MSG(_T("pWnd==NULL !!!"));
618 return FALSE;//*** temporary?
619 }
620 }
621
622 void wxGetMousePosition(
623 int* pX
624 , int* pY
625 )
626 {
627 POINTL vPt;
628
629 ::WinQueryPointerPos(HWND_DESKTOP, &vPt);
630 *pX = vPt.x;
631 *pY = vPt.y;
632 };
633
634 // Return TRUE if we have a colour display
635 bool wxColourDisplay()
636 {
637 HPS hpsScreen;
638 HDC hdcScreen;
639 LONG lColors;
640
641 hpsScreen = ::WinGetScreenPS(HWND_DESKTOP);
642 hdcScreen = ::GpiQueryDevice(hpsScreen);
643 ::DevQueryCaps(hdcScreen, CAPS_COLORS, 1L, &lColors);
644 return(lColors > 1L);
645 }
646
647 // Returns depth of screen
648 int wxDisplayDepth()
649 {
650 HPS hpsScreen;
651 HDC hdcScreen;
652 LONG lPlanes;
653 LONG lBitsPerPixel;
654 LONG nDepth;
655
656 hpsScreen = ::WinGetScreenPS(HWND_DESKTOP);
657 hdcScreen = ::GpiQueryDevice(hpsScreen);
658 ::DevQueryCaps(hdcScreen, CAPS_COLOR_PLANES, 1L, &lPlanes);
659 ::DevQueryCaps(hdcScreen, CAPS_COLOR_BITCOUNT, 1L, &lBitsPerPixel);
660
661 nDepth = (int)(lPlanes * lBitsPerPixel);
662 DevCloseDC(hdcScreen);
663 return (nDepth);
664 }
665
666 // Get size of display
667 void wxDisplaySize(
668 int* pWidth
669 , int* pHeight
670 )
671 {
672 HPS hpsScreen;
673 HDC hdcScreen;
674
675 hpsScreen = ::WinGetScreenPS(HWND_DESKTOP);
676 hdcScreen = ::GpiQueryDevice(hpsScreen);
677 ::DevQueryCaps(hdcScreen, CAPS_WIDTH, 1L, (PLONG)pWidth);
678 ::DevQueryCaps(hdcScreen, CAPS_HEIGHT, 1L, (PLONG)pHeight);
679 DevCloseDC(hdcScreen);
680 }
681
682 bool wxDirExists(
683 const wxString& rDir
684 )
685 {
686 return (::DosSetCurrentDir(WXSTRINGCAST rDir));
687 }
688
689 // ---------------------------------------------------------------------------
690 // window information functions
691 // ---------------------------------------------------------------------------
692
693 wxString WXDLLEXPORT wxGetWindowText(
694 WXHWND hWnd
695 )
696 {
697 wxString vStr;
698 long lLen = ::WinQueryWindowTextLength((HWND)hWnd) + 1;
699
700 ::WinQueryWindowText((HWND)hWnd, lLen, vStr.GetWriteBuf((int)lLen));
701 vStr.UngetWriteBuf();
702
703 return vStr;
704 }
705
706 wxString WXDLLEXPORT wxGetWindowClass(
707 WXHWND hWnd
708 )
709 {
710 wxString vStr;
711 int nLen = 256; // some starting value
712
713 for ( ;; )
714 {
715 int nCount = ::WinQueryClassName((HWND)hWnd, nLen, vStr.GetWriteBuf(nLen));
716
717 vStr.UngetWriteBuf();
718 if (nCount == nLen )
719 {
720 // the class name might have been truncated, retry with larger
721 // buffer
722 nLen *= 2;
723 }
724 else
725 {
726 break;
727 }
728 }
729 return vStr;
730 }
731
732 WXWORD WXDLLEXPORT wxGetWindowId(
733 WXHWND hWnd
734 )
735 {
736 return ::WinQueryWindowUShort((HWND)hWnd, QWS_ID);
737 }
738