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