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