Visualage fixes for Stefan's socket implementations, some scrolling fixes and dir...
[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 #ifdef __EMX__
28 #include <dirent.h>
29 #endif
30
31 #include "wx/log.h"
32
33 #include <io.h>
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 //
39 // already defined via nerror.h in app.h so undef them
40 //
41 #ifdef EEXIST
42 #undef EEXIST
43 #endif
44 #ifdef ENOENT
45 #undef ENOENT
46 #endif
47 #ifdef EMFILE
48 #undef EMFILE
49 #endif
50 #ifdef EINTR
51 #undef EINTR
52 #endif
53 #ifdef EINVAL
54 #undef EINVAL
55 #endif
56 #ifdef ENOMEM
57 #undef ENOMEM
58 #endif
59 #ifdef EACCES
60 #undef EACCES
61 #endif
62 #include <errno.h>
63 #include <stdarg.h>
64
65 #define PURE_32
66
67 #ifndef __EMX__
68 #include <upm.h>
69 #include <netcons.h>
70 #include <netbios.h>
71 #endif
72
73 static const wxChar WX_SECTION[] = _T("wxWindows");
74 static const wxChar eHOSTNAME[] = _T("HostName");
75 static const wxChar eUSERID[] = _T("UserId");
76 static const wxChar eUSERNAME[] = _T("UserName");
77
78 // For the following functions we SHOULD fill in support
79 // for Windows-NT (which I don't know) as I assume it begin
80 // a POSIX Unix (so claims MS) that it has some special
81 // functions beyond those provided by WinSock
82
83 // Get full hostname (eg. DoDo.BSn-Germany.crg.de)
84 bool wxGetHostName(
85 wxChar* zBuf
86 , int nMaxSize
87 )
88 {
89 #if wxUSE_NET_API
90 char zServer[256];
91 char zComputer[256];
92 unsigned long ulLevel = 0;
93 unsigned char* zBuffer = NULL;
94 unsigned long ulBuffer = 256;
95 unsigned long* pulTotalAvail = NULL;
96
97 NetBios32GetInfo( (const unsigned char*)zServer
98 ,(const unsigned char*)zComputer
99 ,ulLevel
100 ,zBuffer
101 ,ulBuffer
102 ,pulTotalAvail
103 );
104 strcpy(zBuf, zServer);
105 #else
106 wxChar* zSysname;
107 const wxChar* zDefaultHost = _T("noname");
108
109 if ((zSysname = wxGetenv(_T("SYSTEM_NAME"))) == NULL)
110 {
111 ULONG n = ::PrfQueryProfileString( HINI_PROFILE
112 ,(PSZ)WX_SECTION
113 ,(PSZ)eHOSTNAME
114 ,(PSZ)zDefaultHost
115 ,(void*)zBuf
116 ,(ULONG)nMaxSize - 1
117 );
118 }
119 else
120 wxStrncpy(zBuf, zSysname, nMaxSize - 1);
121 zBuf[nMaxSize] = _T('\0');
122 #endif
123 return *zBuf ? TRUE : FALSE;
124 }
125
126 // Get user ID e.g. jacs
127 bool wxGetUserId(
128 wxChar* zBuf
129 , int nType
130 )
131 {
132 #ifndef __EMX__
133 long lrc;
134 // UPM procs return 0 on success
135 lrc = U32ELOCU((unsigned char*)zBuf, (unsigned long *)&nType);
136 if (lrc == 0) return TRUE;
137 #endif
138 return FALSE;
139 }
140
141 bool wxGetUserName(
142 wxChar* zBuf
143 , int nMaxSize
144 )
145 {
146 #ifdef USE_NET_API
147 wxGetUserId( zBuf
148 ,nMaxSize
149 );
150 #else
151 wxStrncpy(zBuf, _T("Unknown User"), nMaxSize);
152 #endif
153 return TRUE;
154 }
155
156 int wxKill(
157 long lPid
158 , int nSig
159 )
160 {
161 return((int)::DosKillProcess(0, (PID)lPid));
162 }
163
164 //
165 // Execute a program in an Interactive Shell
166 //
167 bool wxShell(
168 const wxString& rCommand
169 )
170 {
171 wxChar* zShell = _T("CMD.EXE");
172 wxString sInputs;
173 wxChar zTmp[255];
174 STARTDATA SData = {0};
175 PSZ PgmTitle = "Command Shell";
176 APIRET rc;
177 PID vPid = 0;
178 ULONG ulSessID = 0;
179 UCHAR achObjBuf[256] = {0}; //error data if DosStart fails
180 RESULTCODES vResult;
181
182 SData.Length = sizeof(STARTDATA);
183 SData.Related = SSF_RELATED_INDEPENDENT;
184 SData.FgBg = SSF_FGBG_FORE;
185 SData.TraceOpt = SSF_TRACEOPT_NONE;
186 SData.PgmTitle = PgmTitle;
187 SData.PgmName = zShell;
188
189 sInputs = "/C " + rCommand;
190 SData.PgmInputs = (BYTE*)sInputs.c_str();
191 SData.TermQ = 0;
192 SData.Environment = 0;
193 SData.InheritOpt = SSF_INHERTOPT_SHELL;
194 SData.SessionType = SSF_TYPE_WINDOWABLEVIO;
195 SData.IconFile = 0;
196 SData.PgmHandle = 0;
197 SData.PgmControl = SSF_CONTROL_VISIBLE | SSF_CONTROL_MAXIMIZE;
198 SData.InitXPos = 30;
199 SData.InitYPos = 40;
200 SData.InitXSize = 200;
201 SData.InitYSize = 140;
202 SData.Reserved = 0;
203 SData.ObjectBuffer = (char*)achObjBuf;
204 SData.ObjectBuffLen = (ULONG)sizeof(achObjBuf);
205
206 rc = ::DosStartSession(&SData, &ulSessID, &vPid);
207 if (rc == 0 || rc == 457) // NO_ERROR or SMG_START_IN_BACKGROUND
208 {
209 PTIB ptib;
210 PPIB ppib;
211
212 ::DosGetInfoBlocks(&ptib, &ppib);
213
214 ::DosWaitChild( DCWA_PROCESS
215 ,DCWW_WAIT
216 ,&vResult
217 ,&ppib->pib_ulpid
218 ,vPid
219 );
220 }
221 return (rc != 0);
222 }
223
224 // Get free memory in bytes, or -1 if cannot determine amount (e.g. on UNIX)
225 long wxGetFreeMemory()
226 {
227 void* pMemptr = NULL;
228 ULONG lSize;
229 ULONG lMemFlags;
230 APIRET rc;
231
232 lMemFlags = PAG_FREE;
233 rc = ::DosQueryMem(pMemptr, &lSize, &lMemFlags);
234 if (rc != 0)
235 return -1L;
236 return (long)lSize;
237 }
238
239 // ----------------------------------------------------------------------------
240 // env vars
241 // ----------------------------------------------------------------------------
242
243 bool wxGetEnv(const wxString& var, wxString *value)
244 {
245 // wxGetenv is defined as getenv()
246 wxChar *p = wxGetenv(var);
247 if ( !p )
248 return FALSE;
249
250 if ( value )
251 {
252 *value = p;
253 }
254
255 return TRUE;
256 }
257
258 bool wxSetEnv(const wxString& variable, const wxChar *value)
259 {
260 #if defined(HAVE_SETENV)
261 return setenv(variable.mb_str(), value ? wxString(value).mb_str().data()
262 : NULL, 1 /* overwrite */) == 0;
263 #elif defined(HAVE_PUTENV)
264 wxString s = variable;
265 if ( value )
266 s << _T('=') << value;
267
268 // transform to ANSI
269 const char *p = s.mb_str();
270
271 // the string will be free()d by libc
272 char *buf = (char *)malloc(strlen(p) + 1);
273 strcpy(buf, p);
274
275 return putenv(buf) == 0;
276 #else // no way to set an env var
277 return FALSE;
278 #endif
279 }
280
281
282 // Sleep for nSecs seconds. Attempt a Windows implementation using timers.
283 static bool inTimer = FALSE;
284
285 class wxSleepTimer: public wxTimer
286 {
287 public:
288 inline void Notify()
289 {
290 inTimer = FALSE;
291 Stop();
292 }
293 };
294
295 static wxTimer* wxTheSleepTimer = NULL;
296
297 void wxUsleep(
298 unsigned long ulMilliseconds
299 )
300 {
301 ::DosSleep(ulMilliseconds/1000l);
302 }
303
304 void wxSleep(
305 int nSecs
306 )
307 {
308 ::DosSleep(1000 * nSecs);
309 }
310
311 // Consume all events until no more left
312 void wxFlushEvents()
313 {
314 // wxYield();
315 }
316
317 // Output a debug mess., in a system dependent fashion.
318 void wxDebugMsg(
319 const wxChar* zFmt ...
320 )
321 {
322 va_list vAp;
323 static wxChar zBuffer[512];
324
325 if (!wxTheApp->GetWantDebugOutput())
326 return ;
327 va_start(vAp, zFmt);
328 sprintf(zBuffer, zFmt, vAp) ;
329 va_end(vAp);
330 }
331
332 // Non-fatal error: pop up message box and (possibly) continue
333 void wxError(
334 const wxString& rMsg
335 , const wxString& rTitle
336 )
337 {
338 wxBuffer = new wxChar[256];
339 wxSprintf(wxBuffer, "%s\nContinue?", WXSTRINGCAST rMsg);
340 if (::WinMessageBox( HWND_DESKTOP
341 ,NULL
342 ,(PSZ)wxBuffer
343 ,(PSZ)WXSTRINGCAST rTitle
344 ,0
345 ,MB_ICONEXCLAMATION | MB_YESNO
346 ) == MBID_YES)
347 delete[] wxBuffer;
348 wxExit();
349 }
350
351 // Fatal error: pop up message box and abort
352 void wxFatalError(
353 const wxString& rMsg
354 , const wxString& rTitle
355 )
356 {
357 unsigned long ulRc;
358
359 ulRc = ::WinMessageBox( HWND_DESKTOP
360 ,NULL
361 ,WXSTRINGCAST rMsg
362 ,WXSTRINGCAST rTitle
363 ,0
364 ,MB_NOICON | MB_OK
365 );
366 DosExit(EXIT_PROCESS, ulRc);
367 }
368
369 // Emit a beeeeeep
370 void wxBell()
371 {
372 DosBeep(1000,1000); // 1kHz during 1 sec.
373 }
374
375 // Chris Breeze 27/5/98: revised WIN32 code to
376 // detect WindowsNT correctly
377 int wxGetOsVersion(
378 int* pMajorVsn
379 , int* pMinorVsn
380 )
381 {
382 ULONG ulSysInfo[QSV_MAX] = {0};
383 APIRET ulrc;
384
385 ulrc = ::DosQuerySysInfo( 1L
386 ,QSV_MAX
387 ,(PVOID)ulSysInfo
388 ,sizeof(ULONG) * QSV_MAX
389 );
390 if (ulrc == 0L)
391 {
392 *pMajorVsn = ulSysInfo[QSV_VERSION_MAJOR];
393 *pMajorVsn = *pMajorVsn/10;
394 *pMinorVsn = ulSysInfo[QSV_VERSION_MINOR];
395 return wxWINDOWS_OS2;
396 }
397 return wxWINDOWS; // error if we get here, return generic value
398 }
399
400 // Reading and writing resources (eg WIN.INI, .Xdefaults)
401 #if wxUSE_RESOURCES
402 bool wxWriteResource(
403 const wxString& rSection
404 , const wxString& rEntry
405 , const wxString& rValue
406 , const wxString& rFile
407 )
408 {
409 HAB hab = 0;
410 HINI hIni = 0;
411
412 if (rFile != "")
413 {
414 hIni = ::PrfOpenProfile(hab, (PSZ)WXSTRINGCAST rFile);
415 if (hIni != 0L)
416 {
417 return (::PrfWriteProfileString( hIni
418 ,(PSZ)WXSTRINGCAST rSection
419 ,(PSZ)WXSTRINGCAST rEntry
420 ,(PSZ)WXSTRINGCAST rValue
421 ));
422 }
423 }
424 else
425 return (::PrfWriteProfileString( HINI_PROFILE
426 ,(PSZ)WXSTRINGCAST rSection
427 ,(PSZ)WXSTRINGCAST rEntry
428 ,(PSZ)WXSTRINGCAST rValue
429 ));
430 return FALSE;
431 }
432
433 bool wxWriteResource(
434 const wxString& rSection
435 , const wxString& rEntry
436 , float fValue
437 , const wxString& rFile
438 )
439 {
440 wxChar zBuf[50];
441
442 wxSprintf(zBuf, "%.4f", fValue);
443 return wxWriteResource( rSection
444 ,rEntry
445 ,zBuf
446 ,rFile
447 );
448 }
449
450 bool wxWriteResource(
451 const wxString& rSection
452 , const wxString& rEntry
453 , long lValue
454 , const wxString& rFile
455 )
456 {
457 wxChar zBuf[50];
458
459 wxSprintf(zBuf, "%ld", lValue);
460 return wxWriteResource( rSection
461 ,rEntry
462 ,zBuf
463 ,rFile
464 );
465 }
466
467 bool wxWriteResource(
468 const wxString& rSection
469 , const wxString& rEntry
470 , int lValue
471 , const wxString& rFile
472 )
473 {
474 wxChar zBuf[50];
475
476 wxSprintf(zBuf, "%d", lValue);
477 return wxWriteResource( rSection
478 ,rEntry
479 ,zBuf
480 ,rFile
481 );
482 }
483
484 bool wxGetResource(
485 const wxString& rSection
486 , const wxString& rEntry
487 , wxChar** ppValue
488 , const wxString& rFile
489 )
490 {
491 HAB hab = 0;
492 HINI hIni = 0;
493 wxChar zDefunkt[] = _T("$$default");
494 char zBuf[1000];
495
496 if (rFile != "")
497 {
498 hIni = ::PrfOpenProfile(hab, (PSZ)WXSTRINGCAST rFile);
499 if (hIni != 0L)
500 {
501 ULONG n = ::PrfQueryProfileString( hIni
502 ,(PSZ)WXSTRINGCAST rSection
503 ,(PSZ)WXSTRINGCAST rEntry
504 ,(PSZ)zDefunkt
505 ,(PVOID)zBuf
506 ,1000
507 );
508 if (zBuf == NULL)
509 return FALSE;
510 if (n == 0L || wxStrcmp(zBuf, zDefunkt) == 0)
511 return FALSE;
512 zBuf[n-1] = '\0';
513 }
514 else
515 return FALSE;
516 }
517 else
518 {
519 ULONG n = ::PrfQueryProfileString( HINI_PROFILE
520 ,(PSZ)WXSTRINGCAST rSection
521 ,(PSZ)WXSTRINGCAST rEntry
522 ,(PSZ)zDefunkt
523 ,(PVOID)zBuf
524 ,1000
525 );
526 if (zBuf == NULL)
527 return FALSE;
528 if (n == 0L || wxStrcmp(zBuf, zDefunkt) == 0)
529 return FALSE;
530 zBuf[n-1] = '\0';
531 }
532 strcpy((char*)*ppValue, zBuf);
533 return TRUE;
534 }
535
536 bool wxGetResource(
537 const wxString& rSection
538 , const wxString& rEntry
539 , float* pValue
540 , const wxString& rFile
541 )
542 {
543 wxChar* zStr = NULL;
544
545 zStr = new wxChar[1000];
546 bool bSucc = wxGetResource( rSection
547 ,rEntry
548 ,(wxChar **)&zStr
549 ,rFile
550 );
551
552 if (bSucc)
553 {
554 *pValue = (float)wxStrtod(zStr, NULL);
555 delete[] zStr;
556 return TRUE;
557 }
558 else
559 {
560 delete[] zStr;
561 return FALSE;
562 }
563 }
564
565 bool wxGetResource(
566 const wxString& rSection
567 , const wxString& rEntry
568 , long* pValue
569 , const wxString& rFile
570 )
571 {
572 wxChar* zStr = NULL;
573
574 zStr = new wxChar[1000];
575 bool bSucc = wxGetResource( rSection
576 ,rEntry
577 ,(wxChar **)&zStr
578 ,rFile
579 );
580
581 if (bSucc)
582 {
583 *pValue = wxStrtol(zStr, NULL, 10);
584 delete[] zStr;
585 return TRUE;
586 }
587 else
588 {
589 delete[] zStr;
590 return FALSE;
591 }
592 }
593
594 bool wxGetResource(
595 const wxString& rSection
596 , const wxString& rEntry
597 , int* pValue
598 , const wxString& rFile
599 )
600 {
601 wxChar* zStr = NULL;
602
603 zStr = new wxChar[1000];
604 bool bSucc = wxGetResource( rSection
605 ,rEntry
606 ,(wxChar **)&zStr
607 ,rFile
608 );
609
610 if (bSucc)
611 {
612 *pValue = (int)wxStrtol(zStr, NULL, 10);
613 delete[] zStr;
614 return TRUE;
615 }
616 else
617 {
618 delete[] zStr;
619 return FALSE;
620 }
621 }
622 #endif // wxUSE_RESOURCES
623
624 // ---------------------------------------------------------------------------
625 // helper functions for showing a "busy" cursor
626 // ---------------------------------------------------------------------------
627
628 HCURSOR gs_wxBusyCursor = 0; // new, busy cursor
629 HCURSOR gs_wxBusyCursorOld = 0; // old cursor
630 static int gs_wxBusyCursorCount = 0;
631
632 // Set the cursor to the busy cursor for all windows
633 void wxBeginBusyCursor(
634 wxCursor* pCursor
635 )
636 {
637 if ( gs_wxBusyCursorCount++ == 0 )
638 {
639 gs_wxBusyCursor = (HCURSOR)pCursor->GetHCURSOR();
640 ::WinSetPointer(HWND_DESKTOP, (HPOINTER)gs_wxBusyCursor);
641 }
642 //else: nothing to do, already set
643 }
644
645 // Restore cursor to normal
646 void wxEndBusyCursor()
647 {
648 wxCHECK_RET( gs_wxBusyCursorCount > 0
649 ,_T("no matching wxBeginBusyCursor() for wxEndBusyCursor()")
650 );
651
652 if (--gs_wxBusyCursorCount == 0)
653 {
654 ::WinSetPointer(HWND_DESKTOP, (HPOINTER)gs_wxBusyCursorOld);
655 gs_wxBusyCursorOld = 0;
656 }
657 }
658
659 // TRUE if we're between the above two calls
660 bool wxIsBusy()
661 {
662 return (gs_wxBusyCursorCount > 0);
663 }
664
665 // ---------------------------------------------------------------------------
666 const wxChar* wxGetHomeDir(
667 wxString* pStr
668 )
669 {
670 wxString& rStrDir = *pStr;
671
672 // OS/2 has no idea about home,
673 // so use the working directory instead?
674
675 // 256 was taken from os2def.h
676 #ifndef MAX_PATH
677 # define MAX_PATH 256
678 #endif
679
680 char zDirName[256];
681 ULONG ulDirLen;
682
683 ::DosQueryCurrentDir(0, zDirName, &ulDirLen);
684 rStrDir = zDirName;
685 return rStrDir.c_str();
686 }
687
688 // Hack for OS/2
689 wxChar* wxGetUserHome (
690 const wxString& rUser
691 )
692 {
693 wxChar* zHome;
694 wxString sUser1(rUser);
695
696 wxBuffer = new wxChar[256];
697 #ifndef __EMX__
698 if (sUser1 != _T(""))
699 {
700 wxChar zTmp[64];
701
702 if (wxGetUserId( zTmp
703 ,sizeof(zTmp)/sizeof(char)
704 ))
705 {
706 // Guests belong in the temp dir
707 if (wxStricmp(zTmp, _T("annonymous")) == 0)
708 {
709 if ((zHome = wxGetenv(_T("TMP"))) != NULL ||
710 (zHome = wxGetenv(_T("TMPDIR"))) != NULL ||
711 (zHome = wxGetenv(_T("TEMP"))) != NULL)
712 delete[] wxBuffer;
713 return *zHome ? zHome : (wxChar*)_T("\\");
714 }
715 if (wxStricmp(zTmp, WXSTRINGCAST sUser1) == 0)
716 sUser1 = _T("");
717 }
718 }
719 #endif
720 if (sUser1 == _T(""))
721 {
722 if ((zHome = wxGetenv(_T("HOME"))) != NULL)
723 {
724 wxStrcpy(wxBuffer, zHome);
725 Unix2DosFilename(wxBuffer);
726 wxStrcpy(zHome, wxBuffer);
727 delete[] wxBuffer;
728 return zHome;
729 }
730 }
731 delete[] wxBuffer;
732 return NULL; // No home known!
733 }
734
735 // Check whether this window wants to process messages, e.g. Stop button
736 // in long calculations.
737 bool wxCheckForInterrupt(
738 wxWindow* pWnd
739 )
740 {
741 if(pWnd)
742 {
743 QMSG vMsg;
744 HAB hab = 0;
745 HWND hwndFilter = NULLHANDLE;
746 HWND hwndWin= (HWND) pWnd->GetHWND();
747
748 while(::WinPeekMsg(hab, &vMsg, hwndFilter, 0, 0, PM_REMOVE))
749 {
750 ::WinDispatchMsg(hab, &vMsg);
751 }
752 return TRUE;//*** temporary?
753 }
754 else
755 {
756 wxFAIL_MSG(_T("pWnd==NULL !!!"));
757 return FALSE;//*** temporary?
758 }
759 }
760
761 void wxGetMousePosition(
762 int* pX
763 , int* pY
764 )
765 {
766 POINTL vPt;
767
768 ::WinQueryPointerPos(HWND_DESKTOP, &vPt);
769 *pX = vPt.x;
770 *pY = vPt.y;
771 };
772
773 // Return TRUE if we have a colour display
774 bool wxColourDisplay()
775 {
776 HPS hpsScreen;
777 HDC hdcScreen;
778 LONG lColors;
779
780 hpsScreen = ::WinGetScreenPS(HWND_DESKTOP);
781 hdcScreen = ::GpiQueryDevice(hpsScreen);
782 ::DevQueryCaps(hdcScreen, CAPS_COLORS, 1L, &lColors);
783 return(lColors > 1L);
784 }
785
786 // Returns depth of screen
787 int wxDisplayDepth()
788 {
789 HPS hpsScreen;
790 HDC hdcScreen;
791 LONG lPlanes;
792 LONG lBitsPerPixel;
793 LONG nDepth;
794
795 hpsScreen = ::WinGetScreenPS(HWND_DESKTOP);
796 hdcScreen = ::GpiQueryDevice(hpsScreen);
797 ::DevQueryCaps(hdcScreen, CAPS_COLOR_PLANES, 1L, &lPlanes);
798 ::DevQueryCaps(hdcScreen, CAPS_COLOR_BITCOUNT, 1L, &lBitsPerPixel);
799
800 nDepth = (int)(lPlanes * lBitsPerPixel);
801 DevCloseDC(hdcScreen);
802 return (nDepth);
803 }
804
805 // Get size of display
806 void wxDisplaySize(
807 int* pWidth
808 , int* pHeight
809 )
810 {
811 HPS hpsScreen;
812 HDC hdcScreen;
813 LONG lWidth;
814 LONG lHeight;
815
816 hpsScreen = ::WinGetScreenPS(HWND_DESKTOP);
817 hdcScreen = ::GpiQueryDevice(hpsScreen);
818 ::DevQueryCaps(hdcScreen, CAPS_WIDTH, 1L, &lWidth);
819 ::DevQueryCaps(hdcScreen, CAPS_HEIGHT, 1L, &lHeight);
820 DevCloseDC(hdcScreen);
821 *pWidth = (int)lWidth;
822 *pHeight = (int)lHeight;
823 }
824
825 void wxDisplaySizeMM(
826 int* pWidth
827 , int* pHeight
828 )
829 {
830 HPS hpsScreen;
831 HDC hdcScreen;
832
833 hpsScreen = ::WinGetScreenPS(HWND_DESKTOP);
834 hdcScreen = ::GpiQueryDevice(hpsScreen);
835
836 if (pWidth)
837 ::DevQueryCaps( hdcScreen
838 ,CAPS_HORIZONTAL_RESOLUTION
839 ,1L
840 ,(PLONG)pWidth
841 );
842 if (pHeight)
843 ::DevQueryCaps( hdcScreen
844 ,CAPS_VERTICAL_RESOLUTION
845 ,1L
846 ,(PLONG)pHeight
847 );
848 }
849
850 void wxClientDisplayRect(int *x, int *y, int *width, int *height)
851 {
852 // This is supposed to return desktop dimensions minus any window
853 // manager panels, menus, taskbars, etc. If there is a way to do that
854 // for this platform please fix this function, otherwise it defaults
855 // to the entire desktop.
856 if (x) *x = 0;
857 if (y) *y = 0;
858 wxDisplaySize(width, height);
859 }
860
861
862 bool wxDirExists(
863 const wxString& rDir
864 )
865 {
866 return (::DosSetCurrentDir(WXSTRINGCAST rDir));
867 }
868
869 // ---------------------------------------------------------------------------
870 // window information functions
871 // ---------------------------------------------------------------------------
872
873 wxString WXDLLEXPORT wxGetWindowText(
874 WXHWND hWnd
875 )
876 {
877 wxString vStr;
878 long lLen = ::WinQueryWindowTextLength((HWND)hWnd) + 1;
879
880 ::WinQueryWindowText((HWND)hWnd, lLen, vStr.GetWriteBuf((int)lLen));
881 vStr.UngetWriteBuf();
882
883 return vStr;
884 }
885
886 wxString WXDLLEXPORT wxGetWindowClass(
887 WXHWND hWnd
888 )
889 {
890 wxString vStr;
891 int nLen = 256; // some starting value
892
893 for ( ;; )
894 {
895 int nCount = ::WinQueryClassName((HWND)hWnd, nLen, vStr.GetWriteBuf(nLen));
896
897 vStr.UngetWriteBuf();
898 if (nCount == nLen )
899 {
900 // the class name might have been truncated, retry with larger
901 // buffer
902 nLen *= 2;
903 }
904 else
905 {
906 break;
907 }
908 }
909 return vStr;
910 }
911
912 WXWORD WXDLLEXPORT wxGetWindowId(
913 WXHWND hWnd
914 )
915 {
916 return ::WinQueryWindowUShort((HWND)hWnd, QWS_ID);
917 }
918
919 wxString WXDLLEXPORT wxPMErrorToStr(
920 ERRORID vError
921 )
922 {
923 wxString sError;
924
925 //
926 // Remove the high order byte -- it is useless
927 //
928 vError &= 0x0000ffff;
929 switch(vError)
930 {
931 case PMERR_INVALID_HWND:
932 sError = wxT("Invalid window handle specified");
933 break;
934
935 case PMERR_INVALID_FLAG:
936 sError = wxT("Invalid flag bit set");
937 break;
938
939 case PMERR_NO_MSG_QUEUE:
940 sError = wxT("No message queue available");
941 break;
942
943 case PMERR_INVALID_PARM:
944 sError = wxT("Parameter contained invalid data");
945 break;
946
947 case PMERR_INVALID_PARAMETERS:
948 sError = wxT("Parameter value is out of range");
949 break;
950
951 case PMERR_PARAMETER_OUT_OF_RANGE:
952 sError = wxT("Parameter value is out of range");
953 break;
954
955 case PMERR_INVALID_INTEGER_ATOM:
956 sError = wxT("Not a valid atom");
957 break;
958
959 case PMERR_INVALID_HATOMTBL:
960 sError = wxT("Atom table handle is invalid");
961 break;
962
963 case PMERR_INVALID_ATOM_NAME:
964 sError = wxT("Not a valid atom name");
965 break;
966
967 case PMERR_ATOM_NAME_NOT_FOUND:
968 sError = wxT("Valid name format, but cannot find name in atom table");
969 break;
970
971 default:
972 sError = wxT("Unknown error");
973 }
974 return(sError);
975 } // end of wxPMErrorToStr
976
977