]> git.saurik.com Git - wxWidgets.git/blob - src/msw/utils.cpp
wxListCtrl column resize bug corrected
[wxWidgets.git] / src / msw / utils.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: utils.cpp
3 // Purpose: Various utilities
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 // #pragma implementation "utils.h" // Note: this is done in utilscmn.cpp now.
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WX_PRECOMP
24 #include "wx/setup.h"
25 #include "wx/utils.h"
26 #include "wx/app.h"
27 #include "wx/cursor.h"
28 #endif //WX_PRECOMP
29
30 #include "wx/msw/private.h"
31 #include "wx/timer.h"
32 #include "wx/intl.h"
33
34 #include <windows.h>
35
36 #include <ctype.h>
37
38 #if !defined(__GNUWIN32__) && !defined(__SALFORDC__)
39 #include <direct.h>
40
41 #ifndef __MWERKS__
42 #include <dos.h>
43 #endif
44 #endif //GNUWIN32
45
46 #if defined(__GNUWIN32__) && !defined(__TWIN32__)
47 #include <sys/unistd.h>
48 #include <sys/stat.h>
49 #endif //GNUWIN32
50
51 #include "wx/log.h"
52
53 #ifdef __BORLANDC__ // Please someone tell me which version of Borland needs
54 // this (3.1 I believe) and how to test for it.
55 // If this works for Borland 4.0 as well, then no worries.
56 #include <dir.h>
57 #endif
58
59 #ifdef __WIN32__
60 #include <io.h>
61
62 #ifndef __GNUWIN32__
63 #include <shellapi.h>
64 #endif
65 #endif
66
67 #include <stdio.h>
68 #include <stdlib.h>
69 #include <string.h>
70 #ifndef __WATCOMC__
71 #if !(defined(_MSC_VER) && (_MSC_VER > 800))
72 #include <errno.h>
73 #endif
74 #endif
75 #include <stdarg.h>
76
77 //// BEGIN for console support: VC++ only
78 #ifdef __VISUALC__
79
80 #include "wx/msw/msvcrt.h"
81
82 #include <fcntl.h>
83
84 #include "wx/ioswrap.h"
85
86 #if wxUSE_IOSTREAMH
87 // N.B. BC++ doesn't have istream.h, ostream.h
88 # include <io.h>
89 # include <fstream.h>
90 #else
91 # include <fstream>
92 #endif
93
94 /* Need to undef new if including crtdbg.h */
95 # ifdef new
96 # undef new
97 # endif
98
99 #ifndef __WIN16__
100 # include <crtdbg.h>
101 #endif
102
103 # if defined(__WXDEBUG__) && wxUSE_GLOBAL_MEMORY_OPERATORS && wxUSE_DEBUG_NEW_ALWAYS
104 # define new new(__FILE__,__LINE__)
105 # endif
106
107 #endif
108 // __VISUALC__
109 /// END for console support
110
111 // In the WIN.INI file
112 static const char WX_SECTION[] = "wxWindows";
113 static const char eHOSTNAME[] = "HostName";
114 static const char eUSERID[] = "UserId";
115 static const char eUSERNAME[] = "UserName";
116
117 // For the following functions we SHOULD fill in support
118 // for Windows-NT (which I don't know) as I assume it begin
119 // a POSIX Unix (so claims MS) that it has some special
120 // functions beyond those provided by WinSock
121
122 // Get full hostname (eg. DoDo.BSn-Germany.crg.de)
123 bool wxGetHostName(char *buf, int maxSize)
124 {
125 #if defined(__WIN32__) && !defined(__TWIN32__)
126 DWORD nSize = maxSize;
127 return (::GetComputerName(buf, &nSize) != 0);
128 #else
129 char *sysname;
130 const char *default_host = "noname";
131
132 if ((sysname = getenv("SYSTEM_NAME")) == NULL) {
133 GetProfileString(WX_SECTION, eHOSTNAME, default_host, buf, maxSize - 1);
134 } else
135 strncpy(buf, sysname, maxSize - 1);
136 buf[maxSize] = '\0';
137 return *buf ? TRUE : FALSE;
138 #endif
139 }
140
141 // Get user ID e.g. jacs
142 bool wxGetUserId(char *buf, int maxSize)
143 {
144 #if defined(__WIN32__) && !defined(__win32s__) && !defined(__TWIN32__)
145
146 // VZ: why should it be so complicated??
147 #if 0
148 // Gets the current user's full name according to the MS article PSS ID
149 // Number: Q119670
150 // Seems to be the same as the login name for me?
151 char *UserName = new char[256];
152 char *Domain = new char[256];
153 DWORD maxCharacters = 255;
154 GetUserName( UserName, &maxCharacters );
155 GetComputerName( Domain, &maxCharacters );
156
157 WCHAR wszUserName[256]; // Unicode user name
158 WCHAR wszDomain[256];
159 LPBYTE ComputerName;
160
161 struct _SERVER_INFO_100 *si100; // Server structure
162 struct _USER_INFO_2 *ui; // User structure
163
164 // Convert ASCII user name and domain to Unicode.
165
166 MultiByteToWideChar( CP_ACP, 0, UserName,
167 strlen(UserName)+1, wszUserName, sizeof(wszUserName) );
168 MultiByteToWideChar( CP_ACP, 0, Domain,
169 strlen(Domain)+1, wszDomain, sizeof(wszDomain) );
170
171 // Get the computer name of a DC for the specified domain.
172 // >If you get a link error on this, include netapi32.lib<
173
174 NetGetDCName( NULL, wszDomain, &ComputerName );
175
176 // Look up the user on the DC.
177
178 if(NetUserGetInfo( (LPWSTR) ComputerName,
179 (LPWSTR) &wszUserName, 2, (LPBYTE *) &ui))
180 {
181 printf( "Error getting user information.\n" );
182 return( FALSE );
183 }
184
185 // Convert the Unicode full name to ASCII.
186
187 WideCharToMultiByte( CP_ACP, 0, ui->usri2_full_name,
188 -1, buf, 256, NULL, NULL );
189 }
190 return( TRUE );
191 #else // 1
192 DWORD nSize = maxSize;
193 if ( ::GetUserName(buf, &nSize) == 0 )
194 {
195 wxLogSysError("Can not get user name");
196
197 return FALSE;
198 }
199
200 return TRUE;
201 #endif // 0/1
202
203 #else // Win16 or Win32s
204 char *user;
205 const char *default_id = "anonymous";
206
207 // Can't assume we have NIS (PC-NFS) or some other ID daemon
208 // So we ...
209 if ( (user = getenv("USER")) == NULL &&
210 (user = getenv("LOGNAME")) == NULL ) {
211 // Use wxWindows configuration data (comming soon)
212 GetProfileString(WX_SECTION, eUSERID, default_id, buf, maxSize - 1);
213 } else
214 strncpy(buf, user, maxSize - 1);
215 return *buf ? TRUE : FALSE;
216 #endif
217 }
218
219 // Get user name e.g. Julian Smart
220 bool wxGetUserName(char *buf, int maxSize)
221 {
222 #if wxUSE_PENWINDOWS && !defined(__WATCOMC__) && !defined(__GNUWIN32__)
223 extern HANDLE g_hPenWin; // PenWindows Running?
224 if (g_hPenWin)
225 {
226 // PenWindows Does have a user concept!
227 // Get the current owner of the recognizer
228 GetPrivateProfileString("Current", "User", default_name, wxBuffer, maxSize - 1, "PENWIN.INI");
229 strncpy(buf, wxBuffer, maxSize - 1);
230 }
231 else
232 #endif
233 {
234 // Could use NIS, MS-Mail or other site specific programs
235 // Use wxWindows configuration data
236 bool ok = GetProfileString(WX_SECTION, eUSERNAME, "", buf, maxSize - 1) != 0;
237 if ( !ok )
238 {
239 ok = wxGetUserId(buf, maxSize);
240 }
241
242 if ( !ok )
243 {
244 strncpy(buf, "Unknown User", maxSize);
245 }
246 }
247
248 return TRUE;
249 }
250
251 int wxKill(long pid, int sig)
252 {
253 return 0;
254 }
255
256 //
257 // Execute a program in an Interactive Shell
258 //
259 bool
260 wxShell(const wxString& command)
261 {
262 char *shell;
263 if ((shell = getenv("COMSPEC")) == NULL)
264 shell = "\\COMMAND.COM";
265
266 char tmp[255];
267 if (command != "")
268 sprintf(tmp, "%s /c %s", shell, WXSTRINGCAST command);
269 else
270 strcpy(tmp, shell);
271
272 return (wxExecute((char *)tmp, FALSE) != 0);
273 }
274
275 // Get free memory in bytes, or -1 if cannot determine amount (e.g. on UNIX)
276 long wxGetFreeMemory(void)
277 {
278 #if defined(__WIN32__) && !defined(__BORLANDC__) && !defined(__TWIN32__)
279 MEMORYSTATUS memStatus;
280 memStatus.dwLength = sizeof(MEMORYSTATUS);
281 GlobalMemoryStatus(&memStatus);
282 return memStatus.dwAvailPhys;
283 #else
284 return (long)GetFreeSpace(0);
285 #endif
286 }
287
288 // Sleep for nSecs seconds. Attempt a Windows implementation using timers.
289 static bool inTimer = FALSE;
290 class wxSleepTimer: public wxTimer
291 {
292 public:
293 inline void Notify(void)
294 {
295 inTimer = FALSE;
296 Stop();
297 }
298 };
299
300 static wxTimer *wxTheSleepTimer = NULL;
301
302 void wxSleep(int nSecs)
303 {
304 #if 0 // WIN32 hangs app
305 Sleep( 1000*nSecs );
306 #else
307 if (inTimer)
308 return;
309
310 wxTheSleepTimer = new wxSleepTimer;
311 inTimer = TRUE;
312 wxTheSleepTimer->Start(nSecs*1000);
313 while (inTimer)
314 {
315 if (wxTheApp->Pending())
316 wxTheApp->Dispatch();
317 }
318 delete wxTheSleepTimer;
319 wxTheSleepTimer = NULL;
320 #endif
321 }
322
323 // Consume all events until no more left
324 void wxFlushEvents(void)
325 {
326 // wxYield();
327 }
328
329 // Output a debug mess., in a system dependent fashion.
330 void wxDebugMsg(const char *fmt ...)
331 {
332 va_list ap;
333 static char buffer[512];
334
335 if (!wxTheApp->GetWantDebugOutput())
336 return ;
337
338 va_start(ap, fmt);
339
340 wvsprintf(buffer,fmt,ap) ;
341 OutputDebugString((LPCSTR)buffer) ;
342
343 va_end(ap);
344 }
345
346 // Non-fatal error: pop up message box and (possibly) continue
347 void wxError(const wxString& msg, const wxString& title)
348 {
349 sprintf(wxBuffer, "%s\nContinue?", WXSTRINGCAST msg);
350 if (MessageBox(NULL, (LPCSTR)wxBuffer, (LPCSTR)WXSTRINGCAST title,
351 MB_ICONSTOP | MB_YESNO) == IDNO)
352 wxExit();
353 }
354
355 // Fatal error: pop up message box and abort
356 void wxFatalError(const wxString& msg, const wxString& title)
357 {
358 sprintf(wxBuffer, "%s: %s", WXSTRINGCAST title, WXSTRINGCAST msg);
359 FatalAppExit(0, (LPCSTR)wxBuffer);
360 }
361
362 // Emit a beeeeeep
363 void wxBell(void)
364 {
365 // Removed by RD because IHMO syncronous sound is a Bad Thing. MessageBeep
366 // will do a similar thing anyway if there is no sound card...
367 //#ifdef __WIN32__
368 // Beep(1000,1000) ; // 1kHz during 1 sec.
369 //#else
370 MessageBeep((UINT)-1) ;
371 //#endif
372 }
373
374 // Chris Breeze 27/5/98: revised WIN32 code to
375 // detect WindowsNT correctly
376 int wxGetOsVersion(int *majorVsn, int *minorVsn)
377 {
378 extern char *wxOsVersion;
379 if (majorVsn) *majorVsn = 0;
380 if (minorVsn) *minorVsn = 0;
381
382 #if defined(__WIN32__) && !defined(__SC__)
383 OSVERSIONINFO info;
384 memset(&info, 0, sizeof(OSVERSIONINFO));
385 info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
386 if (GetVersionEx(&info))
387 {
388 if (majorVsn) *majorVsn = info.dwMajorVersion;
389 if (minorVsn) *minorVsn = info.dwMinorVersion;
390 switch (info.dwPlatformId)
391 {
392 case VER_PLATFORM_WIN32s:
393 return wxWIN32S;
394 break;
395 case VER_PLATFORM_WIN32_WINDOWS:
396 return wxWIN95;
397 break;
398 case VER_PLATFORM_WIN32_NT:
399 return wxWINDOWS_NT;
400 break;
401 }
402 }
403 return wxWINDOWS; // error if we get here, return generic value
404 #else
405 // Win16 code...
406 int retValue = 0;
407 # ifdef __WINDOWS_386__
408 retValue = wxWIN386;
409 # else
410 # if !defined(__WATCOMC__) && !defined(GNUWIN32) && wxUSE_PENWINDOWS
411 extern HANDLE g_hPenWin;
412 retValue = g_hPenWin ? wxPENWINDOWS : wxWINDOWS ;
413 # endif
414 # endif
415 // @@@@ To be completed. I don't have the manual here...
416 if (majorVsn) *majorVsn = 3 ;
417 if (minorVsn) *minorVsn = 1 ;
418 return retValue ;
419 #endif
420 }
421
422 // Reading and writing resources (eg WIN.INI, .Xdefaults)
423 #if wxUSE_RESOURCES
424 bool wxWriteResource(const wxString& section, const wxString& entry, const wxString& value, const wxString& file)
425 {
426 if (file != "")
427 return (WritePrivateProfileString((LPCSTR)WXSTRINGCAST section, (LPCSTR)WXSTRINGCAST entry, (LPCSTR)value, (LPCSTR)WXSTRINGCAST file) != 0);
428 else
429 return (WriteProfileString((LPCSTR)WXSTRINGCAST section, (LPCSTR)WXSTRINGCAST entry, (LPCSTR)WXSTRINGCAST value) != 0);
430 }
431
432 bool wxWriteResource(const wxString& section, const wxString& entry, float value, const wxString& file)
433 {
434 char buf[50];
435 sprintf(buf, "%.4f", value);
436 return wxWriteResource(section, entry, buf, file);
437 }
438
439 bool wxWriteResource(const wxString& section, const wxString& entry, long value, const wxString& file)
440 {
441 char buf[50];
442 sprintf(buf, "%ld", value);
443 return wxWriteResource(section, entry, buf, file);
444 }
445
446 bool wxWriteResource(const wxString& section, const wxString& entry, int value, const wxString& file)
447 {
448 char buf[50];
449 sprintf(buf, "%d", value);
450 return wxWriteResource(section, entry, buf, file);
451 }
452
453 bool wxGetResource(const wxString& section, const wxString& entry, char **value, const wxString& file)
454 {
455 static const char defunkt[] = "$$default";
456 if (file != "")
457 {
458 int n = GetPrivateProfileString((LPCSTR)WXSTRINGCAST section, (LPCSTR)WXSTRINGCAST entry, (LPCSTR)defunkt,
459 (LPSTR)wxBuffer, 1000, (LPCSTR)WXSTRINGCAST file);
460 if (n == 0 || strcmp(wxBuffer, defunkt) == 0)
461 return FALSE;
462 }
463 else
464 {
465 int n = GetProfileString((LPCSTR)WXSTRINGCAST section, (LPCSTR)WXSTRINGCAST entry, (LPCSTR)defunkt,
466 (LPSTR)wxBuffer, 1000);
467 if (n == 0 || strcmp(wxBuffer, defunkt) == 0)
468 return FALSE;
469 }
470 if (*value) delete[] (*value);
471 *value = copystring(wxBuffer);
472 return TRUE;
473 }
474
475 bool wxGetResource(const wxString& section, const wxString& entry, float *value, const wxString& file)
476 {
477 char *s = NULL;
478 bool succ = wxGetResource(section, entry, (char **)&s, file);
479 if (succ)
480 {
481 *value = (float)strtod(s, NULL);
482 delete[] s;
483 return TRUE;
484 }
485 else return FALSE;
486 }
487
488 bool wxGetResource(const wxString& section, const wxString& entry, long *value, const wxString& file)
489 {
490 char *s = NULL;
491 bool succ = wxGetResource(section, entry, (char **)&s, file);
492 if (succ)
493 {
494 *value = strtol(s, NULL, 10);
495 delete[] s;
496 return TRUE;
497 }
498 else return FALSE;
499 }
500
501 bool wxGetResource(const wxString& section, const wxString& entry, int *value, const wxString& file)
502 {
503 char *s = NULL;
504 bool succ = wxGetResource(section, entry, (char **)&s, file);
505 if (succ)
506 {
507 *value = (int)strtol(s, NULL, 10);
508 delete[] s;
509 return TRUE;
510 }
511 else return FALSE;
512 }
513 #endif // wxUSE_RESOURCES
514
515 // Old cursor
516 static HCURSOR wxBusyCursorOld = 0;
517 static int wxBusyCursorCount = 0;
518
519 // Set the cursor to the busy cursor for all windows
520 void wxBeginBusyCursor(wxCursor *cursor)
521 {
522 wxBusyCursorCount ++;
523 if (wxBusyCursorCount == 1)
524 {
525 wxBusyCursorOld = ::SetCursor((HCURSOR) cursor->GetHCURSOR());
526 }
527 else
528 {
529 (void)::SetCursor((HCURSOR) cursor->GetHCURSOR());
530 }
531 }
532
533 // Restore cursor to normal
534 void wxEndBusyCursor(void)
535 {
536 if (wxBusyCursorCount == 0)
537 return;
538
539 wxBusyCursorCount --;
540 if (wxBusyCursorCount == 0)
541 {
542 ::SetCursor(wxBusyCursorOld);
543 wxBusyCursorOld = 0;
544 }
545 }
546
547 // TRUE if we're between the above two calls
548 bool wxIsBusy(void)
549 {
550 return (wxBusyCursorCount > 0);
551 }
552
553 const char* wxGetHomeDir(wxString *pstr)
554 {
555 wxString& strDir = *pstr;
556
557 #if defined(__UNIX__) && !defined(__TWIN32__)
558 const char *szHome = getenv("HOME");
559 if ( szHome == NULL ) {
560 // we're homeless...
561 wxLogWarning(_("can't find user's HOME, using current directory."));
562 strDir = ".";
563 }
564 else
565 strDir = szHome;
566
567 // add a trailing slash if needed
568 if ( strDir.Last() != '/' )
569 strDir << '/';
570 #else // Windows
571 #ifdef __WIN32__
572 const char *szHome = getenv("HOMEDRIVE");
573 if ( szHome != NULL )
574 strDir << szHome;
575 szHome = getenv("HOMEPATH");
576 if ( szHome != NULL ) {
577 strDir << szHome;
578
579 // the idea is that under NT these variables have default values
580 // of "%systemdrive%:" and "\\". As we don't want to create our
581 // config files in the root directory of the system drive, we will
582 // create it in our program's dir. However, if the user took care
583 // to set HOMEPATH to something other than "\\", we suppose that he
584 // knows what he is doing and use the supplied value.
585 if ( strcmp(szHome, "\\") != 0 )
586 return strDir.c_str();
587 }
588
589 #else // Win16
590 // Win16 has no idea about home, so use the working directory instead
591 #endif // WIN16/32
592
593 // 260 was taken from windef.h
594 #ifndef MAX_PATH
595 #define MAX_PATH 260
596 #endif
597
598 wxString strPath;
599 ::GetModuleFileName(::GetModuleHandle(NULL),
600 strPath.GetWriteBuf(MAX_PATH), MAX_PATH);
601 strPath.UngetWriteBuf();
602
603 // extract the dir name
604 wxSplitPath(strPath, &strDir, NULL, NULL);
605
606 #endif // UNIX/Win
607
608 return strDir.c_str();
609 }
610
611 // Hack for MS-DOS
612 char *wxGetUserHome (const wxString& user)
613 {
614 char *home;
615 wxString user1(user);
616
617 if (user1 != "") {
618 char tmp[64];
619 if (wxGetUserId(tmp, sizeof(tmp)/sizeof(char))) {
620 // Guests belong in the temp dir
621 if (Stricmp(tmp, "annonymous") == 0) {
622 if ((home = getenv("TMP")) != NULL ||
623 (home = getenv("TMPDIR")) != NULL ||
624 (home = getenv("TEMP")) != NULL)
625 return *home ? home : "\\";
626 }
627 if (Stricmp(tmp, WXSTRINGCAST user1) == 0)
628 user1 = "";
629 }
630 }
631 if (user1 == "")
632 if ((home = getenv("HOME")) != NULL)
633 {
634 strcpy(wxBuffer, home);
635 Unix2DosFilename(wxBuffer);
636 return wxBuffer;
637 }
638 return NULL; // No home known!
639 }
640
641 // Check whether this window wants to process messages, e.g. Stop button
642 // in long calculations.
643 bool wxCheckForInterrupt(wxWindow *wnd)
644 {
645 if(wnd){
646 MSG msg;
647 HWND win= (HWND) wnd->GetHWND();
648 while(PeekMessage(&msg,win,0,0,PM_REMOVE)){
649 TranslateMessage(&msg);
650 DispatchMessage(&msg);
651 }
652 return TRUE;//*** temporary?
653 }
654 else{
655 wxError("wnd==NULL !!!");
656 return FALSE;//*** temporary?
657 }
658 }
659
660 // MSW only: get user-defined resource from the .res file.
661 // Returns NULL or newly-allocated memory, so use delete[] to clean up.
662
663 #ifdef __WXMSW__
664 char *wxLoadUserResource(const wxString& resourceName, const wxString& resourceType)
665 {
666 char *s = NULL;
667 #if !defined(__WIN32__) || defined(__TWIN32__)
668 HRSRC hResource = ::FindResource(wxGetInstance(), WXSTRINGCAST resourceName, WXSTRINGCAST resourceType);
669 #else
670 #ifdef UNICODE
671 HRSRC hResource = ::FindResourceW(wxGetInstance(), WXSTRINGCAST resourceName, WXSTRINGCAST resourceType);
672 #else
673 HRSRC hResource = ::FindResourceA(wxGetInstance(), WXSTRINGCAST resourceName, WXSTRINGCAST resourceType);
674 #endif
675 #endif
676
677 if (hResource == 0)
678 return NULL;
679 HGLOBAL hData = ::LoadResource(wxGetInstance(), hResource);
680 if (hData == 0)
681 return NULL;
682 char *theText = (char *)LockResource(hData);
683 if (!theText)
684 return NULL;
685
686 s = copystring(theText);
687
688 // Obsolete in WIN32
689 #ifndef __WIN32__
690 UnlockResource(hData);
691 #endif
692
693 // No need??
694 // GlobalFree(hData);
695
696 return s;
697 }
698 #endif
699
700 void wxGetMousePosition( int* x, int* y )
701 {
702 POINT pt;
703 GetCursorPos( & pt );
704 *x = pt.x;
705 *y = pt.y;
706 };
707
708 // Return TRUE if we have a colour display
709 bool wxColourDisplay(void)
710 {
711 HDC dc = ::GetDC((HWND) NULL);
712 bool flag;
713 int noCols = GetDeviceCaps(dc, NUMCOLORS);
714 if ((noCols == -1) || (noCols > 2))
715 flag = TRUE;
716 else
717 flag = FALSE;
718 ReleaseDC((HWND) NULL, dc);
719 return flag;
720 }
721
722 // Returns depth of screen
723 int wxDisplayDepth(void)
724 {
725 HDC dc = ::GetDC((HWND) NULL);
726 int planes = GetDeviceCaps(dc, PLANES);
727 int bitsPerPixel = GetDeviceCaps(dc, BITSPIXEL);
728 int depth = planes*bitsPerPixel;
729 ReleaseDC((HWND) NULL, dc);
730 return depth;
731 }
732
733 // Get size of display
734 void wxDisplaySize(int *width, int *height)
735 {
736 HDC dc = ::GetDC((HWND) NULL);
737 *width = GetDeviceCaps(dc, HORZRES); *height = GetDeviceCaps(dc, VERTRES);
738 ReleaseDC((HWND) NULL, dc);
739 }
740
741 bool wxDirExists(const wxString& dir)
742 {
743 /* MATTHEW: [6] Always use same code for Win32, call FindClose */
744 #if defined(__WIN32__)
745 WIN32_FIND_DATA fileInfo;
746 #else
747 #ifdef __BORLANDC__
748 struct ffblk fileInfo;
749 #else
750 struct find_t fileInfo;
751 #endif
752 #endif
753
754 #if defined(__WIN32__)
755 HANDLE h = FindFirstFile((LPTSTR) WXSTRINGCAST dir,(LPWIN32_FIND_DATA)&fileInfo);
756
757 if (h==INVALID_HANDLE_VALUE)
758 return FALSE;
759 else {
760 FindClose(h);
761 return ((fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY);
762 }
763 #else
764 // In Borland findfirst has a different argument
765 // ordering from _dos_findfirst. But _dos_findfirst
766 // _should_ be ok in both MS and Borland... why not?
767 #ifdef __BORLANDC__
768 return ((findfirst(WXSTRINGCAST dir, &fileInfo, _A_SUBDIR) == 0 && (fileInfo.ff_attrib & _A_SUBDIR) != 0));
769 #else
770 return (((_dos_findfirst(WXSTRINGCAST dir, _A_SUBDIR, &fileInfo) == 0) && (fileInfo.attrib & _A_SUBDIR)) != 0);
771 #endif
772 #endif
773 }
774
775 wxString WXDLLEXPORT wxGetWindowText(WXHWND hWnd)
776 {
777 wxString str;
778 int len = GetWindowTextLength((HWND)hWnd) + 1;
779 GetWindowText((HWND)hWnd, str.GetWriteBuf(len), len);
780 str.UngetWriteBuf();
781
782 return str;
783 }
784
785 #if 0
786 //------------------------------------------------------------------------
787 // wild character routines
788 //------------------------------------------------------------------------
789
790 bool wxIsWild( const wxString& pattern )
791 {
792 wxString tmp = pattern;
793 char *pat = WXSTRINGCAST(tmp);
794 while (*pat) {
795 switch (*pat++) {
796 case '?': case '*': case '[': case '{':
797 return TRUE;
798 case '\\':
799 if (!*pat++)
800 return FALSE;
801 }
802 }
803 return FALSE;
804 };
805
806
807 bool wxMatchWild( const wxString& pat, const wxString& text, bool dot_special )
808 {
809 wxString tmp1 = pat;
810 char *pattern = WXSTRINGCAST(tmp1);
811 wxString tmp2 = text;
812 char *str = WXSTRINGCAST(tmp2);
813 char c;
814 char *cp;
815 bool done = FALSE, ret_code, ok;
816 // Below is for vi fans
817 const char OB = '{', CB = '}';
818
819 // dot_special means '.' only matches '.'
820 if (dot_special && *str == '.' && *pattern != *str)
821 return FALSE;
822
823 while ((*pattern != '\0') && (!done)
824 && (((*str=='\0')&&((*pattern==OB)||(*pattern=='*')))||(*str!='\0'))) {
825 switch (*pattern) {
826 case '\\':
827 pattern++;
828 if (*pattern != '\0')
829 pattern++;
830 break;
831 case '*':
832 pattern++;
833 ret_code = FALSE;
834 while ((*str!='\0')
835 && (!(ret_code=wxMatchWild(pattern, str++, FALSE))))
836 /*loop*/;
837 if (ret_code) {
838 while (*str != '\0')
839 str++;
840 while (*pattern != '\0')
841 pattern++;
842 }
843 break;
844 case '[':
845 pattern++;
846 repeat:
847 if ((*pattern == '\0') || (*pattern == ']')) {
848 done = TRUE;
849 break;
850 }
851 if (*pattern == '\\') {
852 pattern++;
853 if (*pattern == '\0') {
854 done = TRUE;
855 break;
856 }
857 }
858 if (*(pattern + 1) == '-') {
859 c = *pattern;
860 pattern += 2;
861 if (*pattern == ']') {
862 done = TRUE;
863 break;
864 }
865 if (*pattern == '\\') {
866 pattern++;
867 if (*pattern == '\0') {
868 done = TRUE;
869 break;
870 }
871 }
872 if ((*str < c) || (*str > *pattern)) {
873 pattern++;
874 goto repeat;
875 }
876 } else if (*pattern != *str) {
877 pattern++;
878 goto repeat;
879 }
880 pattern++;
881 while ((*pattern != ']') && (*pattern != '\0')) {
882 if ((*pattern == '\\') && (*(pattern + 1) != '\0'))
883 pattern++;
884 pattern++;
885 }
886 if (*pattern != '\0') {
887 pattern++, str++;
888 }
889 break;
890 case '?':
891 pattern++;
892 str++;
893 break;
894 case OB:
895 pattern++;
896 while ((*pattern != CB) && (*pattern != '\0')) {
897 cp = str;
898 ok = TRUE;
899 while (ok && (*cp != '\0') && (*pattern != '\0')
900 && (*pattern != ',') && (*pattern != CB)) {
901 if (*pattern == '\\')
902 pattern++;
903 ok = (*pattern++ == *cp++);
904 }
905 if (*pattern == '\0') {
906 ok = FALSE;
907 done = TRUE;
908 break;
909 } else if (ok) {
910 str = cp;
911 while ((*pattern != CB) && (*pattern != '\0')) {
912 if (*++pattern == '\\') {
913 if (*++pattern == CB)
914 pattern++;
915 }
916 }
917 } else {
918 while (*pattern!=CB && *pattern!=',' && *pattern!='\0') {
919 if (*++pattern == '\\') {
920 if (*++pattern == CB || *pattern == ',')
921 pattern++;
922 }
923 }
924 }
925 if (*pattern != '\0')
926 pattern++;
927 }
928 break;
929 default:
930 if (*str == *pattern) {
931 str++, pattern++;
932 } else {
933 done = TRUE;
934 }
935 }
936 }
937 while (*pattern == '*')
938 pattern++;
939 return ((*str == '\0') && (*pattern == '\0'));
940 };
941
942 #endif
943
944 #if defined(__WIN95__) && defined(__WXDEBUG__) && wxUSE_DBWIN32
945
946 /*
947 When I started programming with Visual C++ v4.0, I missed one of my favorite
948 tools -- DBWIN. Finding the code for a simple debug trace utility, DBMON,
949 on MSDN was a step in the right direction, but it is a console application
950 and thus has limited features and extensibility. DBWIN32 is my creation
951 to solve this problem.
952
953 The code is essentially a merging of a stripped down version of the DBWIN code
954 from VC 1.5 and DBMON.C with a few 32 bit changes.
955
956 As of version 1.2B, DBWIN32 supports both Win95 and NT. The NT support is
957 built into the operating system and works just by running DBWIN32. The Win95
958 team decided not to support this hook, so I have provided code that will do
959 this for you. See the file WIN95.TXT for instructions on installing this.
960
961 If you have questions, problems or suggestions about DBWIN32, I welcome your
962 feedback and plan to actively maintain the code.
963
964 Andrew Tucker
965 ast@halcyon.com
966
967 To download dbwin32, see e.g.:
968
969 http://ftp.digital.com/pub/micro/NT/WinSite/programr/dbwin32.zip
970 */
971
972 #if !defined(__MWERKS__) && !defined(__SALFORDC__) && !defined(__TWIN32__)
973 #include <process.h>
974 #endif
975
976 void OutputDebugStringW95(const char* lpOutputString, ...)
977 {
978 HANDLE heventDBWIN; /* DBWIN32 synchronization object */
979 HANDLE heventData; /* data passing synch object */
980 HANDLE hSharedFile; /* memory mapped file shared data */
981 LPSTR lpszSharedMem;
982 char achBuffer[500];
983
984 /* create the output buffer */
985 va_list args;
986 va_start(args, lpOutputString);
987 vsprintf(achBuffer, lpOutputString, args);
988 va_end(args);
989
990 /*
991 Do a regular OutputDebugString so that the output is
992 still seen in the debugger window if it exists.
993
994 This ifdef is necessary to avoid infinite recursion
995 from the inclusion of W95TRACE.H
996 */
997 #ifdef _UNICODE
998 ::OutputDebugStringW(achBuffer);
999 #else
1000 #ifdef __TWIN32__
1001 ::OutputDebugString(achBuffer);
1002 #else
1003 ::OutputDebugStringA(achBuffer);
1004 #endif
1005 #endif
1006
1007 /* bail if it's not Win95 */
1008 {
1009 OSVERSIONINFO VerInfo;
1010 VerInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
1011 GetVersionEx(&VerInfo);
1012 if ( VerInfo.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS )
1013 return;
1014 }
1015
1016 /* make sure DBWIN is open and waiting */
1017 heventDBWIN = OpenEvent(EVENT_MODIFY_STATE, FALSE, "DBWIN_BUFFER_READY");
1018 if ( !heventDBWIN )
1019 {
1020 //MessageBox(NULL, "DBWIN_BUFFER_READY nonexistent", NULL, MB_OK);
1021 return;
1022 }
1023
1024 /* get a handle to the data synch object */
1025 heventData = OpenEvent(EVENT_MODIFY_STATE, FALSE, "DBWIN_DATA_READY");
1026 if ( !heventData )
1027 {
1028 // MessageBox(NULL, "DBWIN_DATA_READY nonexistent", NULL, MB_OK);
1029 CloseHandle(heventDBWIN);
1030 return;
1031 }
1032
1033 hSharedFile = CreateFileMapping((HANDLE)-1, NULL, PAGE_READWRITE, 0, 4096, "DBWIN_BUFFER");
1034 if (!hSharedFile)
1035 {
1036 //MessageBox(NULL, "DebugTrace: Unable to create file mapping object DBWIN_BUFFER", "Error", MB_OK);
1037 CloseHandle(heventDBWIN);
1038 CloseHandle(heventData);
1039 return;
1040 }
1041
1042 lpszSharedMem = (LPSTR)MapViewOfFile(hSharedFile, FILE_MAP_WRITE, 0, 0, 512);
1043 if (!lpszSharedMem)
1044 {
1045 //MessageBox(NULL, "DebugTrace: Unable to map shared memory", "Error", MB_OK);
1046 CloseHandle(heventDBWIN);
1047 CloseHandle(heventData);
1048 return;
1049 }
1050
1051 /* wait for buffer event */
1052 WaitForSingleObject(heventDBWIN, INFINITE);
1053
1054 /* write it to the shared memory */
1055 #if defined( __BORLANDC__ ) || defined( __MWERKS__ ) || defined(__SALFORDC__)
1056 *((LPDWORD)lpszSharedMem) = getpid();
1057 #else
1058 *((LPDWORD)lpszSharedMem) = _getpid();
1059 #endif
1060
1061 wsprintf(lpszSharedMem + sizeof(DWORD), "%s", achBuffer);
1062
1063 /* signal data ready event */
1064 SetEvent(heventData);
1065
1066 /* clean up handles */
1067 CloseHandle(hSharedFile);
1068 CloseHandle(heventData);
1069 CloseHandle(heventDBWIN);
1070
1071 return;
1072 }
1073
1074
1075 #endif
1076
1077
1078 #if 0
1079
1080 // maximum mumber of lines the output console should have
1081 static const WORD MAX_CONSOLE_LINES = 500;
1082
1083 BOOL WINAPI MyConsoleHandler( DWORD dwCtrlType ) { // control signal type
1084 FreeConsole();
1085 return TRUE;
1086 }
1087
1088 void wxRedirectIOToConsole()
1089 {
1090 int hConHandle;
1091 long lStdHandle;
1092 CONSOLE_SCREEN_BUFFER_INFO coninfo;
1093 FILE *fp;
1094
1095 // allocate a console for this app
1096 AllocConsole();
1097
1098 // set the screen buffer to be big enough to let us scroll text
1099 GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),
1100 &coninfo);
1101 coninfo.dwSize.Y = MAX_CONSOLE_LINES;
1102 SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE),
1103 coninfo.dwSize);
1104
1105 // redirect unbuffered STDOUT to the console
1106 lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
1107 hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
1108 if(hConHandle <= 0) return;
1109 fp = _fdopen( hConHandle, "w" );
1110 *stdout = *fp;
1111 setvbuf( stdout, NULL, _IONBF, 0 );
1112
1113 // redirect unbuffered STDIN to the console
1114 lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE);
1115 hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
1116 if(hConHandle <= 0) return;
1117 fp = _fdopen( hConHandle, "r" );
1118 *stdin = *fp;
1119 setvbuf( stdin, NULL, _IONBF, 0 );
1120
1121 // redirect unbuffered STDERR to the console
1122 lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE);
1123 hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
1124 if(hConHandle <= 0) return;
1125 fp = _fdopen( hConHandle, "w" );
1126 *stderr = *fp;
1127 setvbuf( stderr, NULL, _IONBF, 0 );
1128
1129 // make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog
1130 // point to console as well
1131 ios::sync_with_stdio();
1132
1133 SetConsoleCtrlHandler(MyConsoleHandler, TRUE);
1134 }
1135 #else
1136 // Not supported
1137 void wxRedirectIOToConsole()
1138 {
1139 }
1140 #endif
1141
1142