1///////////////////////////////////////////////////////////////////////////// 2// Name: src/os2/utils.cpp 3// Purpose: Various utilities 4// Author: David Webster 5// Modified by: 6// Created: 09/17/99 7// RCS-ID: $Id: utils.cpp 54228 2008-06-15 11:22:52Z VZ $ 8// Copyright: (c) David Webster 9// Licence: wxWindows licence 10///////////////////////////////////////////////////////////////////////////// 11 12// For compilers that support precompilation, includes "wx.h". 13#include "wx/wxprec.h" 14 15#include "wx/utils.h" 16 17#ifndef WX_PRECOMP 18 #include "wx/intl.h" 19 #include "wx/log.h" 20#endif //WX_PRECOMP 21 22#include "wx/os2/private.h" 23#include "wx/apptrait.h" 24#include "wx/filename.h" 25 26#include <ctype.h> 27#ifdef __EMX__ 28#include <dirent.h> 29#endif 30 31 32#include <io.h> 33 34#include <stdio.h> 35#include <stdlib.h> 36#include <string.h> 37#include <errno.h> 38#include <stdarg.h> 39 40#define PURE_32 41 42#if defined(__WATCOMC__) 43extern "C" 44{ 45 #include <upm.h> 46} 47#elif !defined(__EMX__) 48 #include <upm.h> 49 #include <netcons.h> 50 #include <netbios.h> 51#endif 52 53static const wxChar WX_SECTION[] = _T("wxWidgets"); 54static const wxChar eHOSTNAME[] = _T("HostName"); 55 56// For the following functions we SHOULD fill in support 57// for Windows-NT (which I don't know) as I assume it begin 58// a POSIX Unix (so claims MS) that it has some special 59// functions beyond those provided by WinSock 60 61// Get full hostname (eg. DoDo.BSn-Germany.crg.de) 62bool wxGetHostName( wxChar* zBuf, int nMaxSize ) 63{ 64 if (!zBuf) return false; 65 66#if defined(wxUSE_NET_API) && wxUSE_NET_API 67 char zServer[256]; 68 char zComputer[256]; 69 unsigned long ulLevel = 0; 70 unsigned char* zBuffer = NULL; 71 unsigned long ulBuffer = 256; 72 unsigned long* pulTotalAvail = NULL; 73 74 NetBios32GetInfo( (const unsigned char*)zServer 75 ,(const unsigned char*)zComputer 76 ,ulLevel 77 ,zBuffer 78 ,ulBuffer 79 ,pulTotalAvail 80 ); 81 strcpy(zBuf, zServer); 82#else 83 wxChar* zSysname; 84 const wxChar* zDefaultHost = _T("noname"); 85 86 if ((zSysname = wxGetenv(_T("SYSTEM_NAME"))) == NULL && 87 (zSysname = wxGetenv(_T("HOSTNAME"))) == NULL) 88 { 89 ::PrfQueryProfileString( HINI_PROFILE 90 ,(PSZ)WX_SECTION 91 ,(PSZ)eHOSTNAME 92 ,(PSZ)zDefaultHost 93 ,(void*)zBuf 94 ,(ULONG)nMaxSize - 1 95 ); 96 } 97 else 98 { 99 wxStrncpy(zBuf, zSysname, nMaxSize - 1); 100 } 101 102 zBuf[nMaxSize] = _T('\0'); 103#endif 104 105 return *zBuf ? true : false; 106} 107 108// Get user ID e.g. jacs 109bool wxGetUserId(wxChar* zBuf, int nType) 110{ 111#if defined(__VISAGECPP__) || defined(__WATCOMC__) 112 // UPM procs return 0 on success 113 long lrc = U32ELOCU((PUCHAR)zBuf, (PULONG)&nType); 114 if (lrc == 0) return true; 115#endif 116 return false; 117} 118 119bool wxGetUserName( wxChar* zBuf, int nMaxSize ) 120{ 121#ifdef USE_NET_API 122 wxGetUserId( zBuf, nMaxSize ); 123#else 124 wxStrncpy(zBuf, _T("Unknown User"), nMaxSize); 125#endif 126 return true; 127} 128 129int wxKill(long lPid, 130 wxSignal WXUNUSED(eSig), 131 wxKillError* WXUNUSED(peError), 132 int WXUNUSED(flags)) 133{ 134 return((int)::DosKillProcess(0, (PID)lPid)); 135} 136 137// 138// Execute a program in an Interactive Shell 139// 140bool wxShell( const wxString& rCommand ) 141{ 142 wxChar* zShell = _T("CMD.EXE"); 143 wxString sInputs; 144 STARTDATA SData = {0}; 145 PSZ PgmTitle = "Command Shell"; 146 APIRET rc; 147 PID vPid = 0; 148 ULONG ulSessID = 0; 149 UCHAR achObjBuf[256] = {0}; //error data if DosStart fails 150 RESULTCODES vResult; 151 152 SData.Length = sizeof(STARTDATA); 153 SData.Related = SSF_RELATED_INDEPENDENT; 154 SData.FgBg = SSF_FGBG_FORE; 155 SData.TraceOpt = SSF_TRACEOPT_NONE; 156 SData.PgmTitle = PgmTitle; 157 SData.PgmName = (char*)zShell; 158 159 sInputs = _T("/C ") + rCommand; 160 SData.PgmInputs = (BYTE*)sInputs.c_str(); 161 SData.TermQ = 0; 162 SData.Environment = 0; 163 SData.InheritOpt = SSF_INHERTOPT_SHELL; 164 SData.SessionType = SSF_TYPE_WINDOWABLEVIO; 165 SData.IconFile = 0; 166 SData.PgmHandle = 0; 167 SData.PgmControl = SSF_CONTROL_VISIBLE | SSF_CONTROL_MAXIMIZE; 168 SData.InitXPos = 30; 169 SData.InitYPos = 40; 170 SData.InitXSize = 200; 171 SData.InitYSize = 140; 172 SData.Reserved = 0; 173 SData.ObjectBuffer = (char*)achObjBuf; 174 SData.ObjectBuffLen = (ULONG)sizeof(achObjBuf); 175 176 rc = ::DosStartSession(&SData, &ulSessID, &vPid); 177 if (rc == 0 || rc == 457) // NO_ERROR or SMG_START_IN_BACKGROUND 178 { 179 PTIB ptib; 180 PPIB ppib; 181 182 ::DosGetInfoBlocks(&ptib, &ppib); 183 184 ::DosWaitChild( DCWA_PROCESS 185 ,DCWW_WAIT 186 ,&vResult 187 ,&ppib->pib_ulpid 188 ,vPid 189 ); 190 } 191 return (rc != 0); 192} 193 194// Shutdown or reboot the PC 195bool wxShutdown(wxShutdownFlags WXUNUSED(wFlags)) 196{ 197 // TODO 198 return false; 199} 200 201// Get free memory in bytes, or -1 if cannot determine amount (e.g. on UNIX) 202wxMemorySize wxGetFreeMemory() 203{ 204 void* pMemptr = NULL; 205 LONG lSize; 206 ULONG lMemFlags; 207 APIRET rc; 208 209 lMemFlags = PAG_FREE; 210 rc = ::DosQueryMem(pMemptr, (PULONG)&lSize, &lMemFlags); 211 if (rc != 0) 212 lSize = -1L; 213 return (wxMemorySize)lSize; 214} 215 216// Get Process ID 217unsigned long wxGetProcessId() 218{ 219 return (unsigned long)getpid(); 220} 221 222// ---------------------------------------------------------------------------- 223// env vars 224// ---------------------------------------------------------------------------- 225 226bool wxGetEnv(const wxString& var, wxString *value) 227{ 228 // wxGetenv is defined as getenv() 229 wxChar *p = wxGetenv(var); 230 if ( !p ) 231 return false; 232 233 if ( value ) 234 { 235 *value = p; 236 } 237 238 return true; 239} 240 241bool wxSetEnv(const wxString& variable, const wxChar *value) 242{ 243#if defined(HAVE_SETENV) 244 if ( !value ) 245 { 246#ifdef HAVE_UNSETENV 247 return unsetenv(variable.mb_str()) == 0; 248#else 249 value = _T(""); // mustn't pass NULL to setenv() 250#endif 251 } 252 return setenv(variable.mb_str(), 253 wxString(value).mb_str(), 254 1 /* overwrite */) == 0; 255#elif defined(HAVE_PUTENV) 256 wxString s = variable; 257 if ( value ) 258 s << _T('=') << value; 259 260 // transform to ANSI 261 const char *p = s.mb_str(); 262 263 // the string will be free()d by libc 264 char *buf = (char *)malloc(strlen(p) + 1); 265 strcpy(buf, p); 266 267 return putenv(buf) == 0; 268#else // no way to set an env var 269 wxUnusedVar(variable); 270 wxUnusedVar(value); 271 return false; 272#endif 273} 274 275void wxMilliSleep( 276 unsigned long ulMilliseconds 277) 278{ 279 ::DosSleep(ulMilliseconds); 280} 281 282void wxMicroSleep( 283 unsigned long ulMicroseconds 284) 285{ 286 ::DosSleep(ulMicroseconds/1000); 287} 288 289void wxSleep( 290 int nSecs 291) 292{ 293 ::DosSleep(1000 * nSecs); 294} 295 296// Consume all events until no more left 297void wxFlushEvents() 298{ 299// wxYield(); 300} 301 302// Emit a beeeeeep 303void wxBell() 304{ 305 DosBeep(1000,1000); // 1kHz during 1 sec. 306} 307 308wxString wxGetOsDescription() 309{ 310 wxString strVer(_T("OS/2")); 311 ULONG ulSysInfo = 0; 312 313 if (::DosQuerySysInfo( QSV_VERSION_MINOR, 314 QSV_VERSION_MINOR, 315 (PVOID)&ulSysInfo, 316 sizeof(ULONG) 317 ) == 0L ) 318 { 319 wxString ver; 320 ver.Printf( _T(" ver. %d.%d"), 321 int(ulSysInfo / 10), 322 int(ulSysInfo % 10) 323 ); 324 strVer += ver; 325 } 326 327 return strVer; 328} 329 330bool wxIsPlatform64Bit() 331{ 332 // FIXME: No idea how to test for 64 bit processor 333 // (Probably irrelevant anyhow, though). 334 return false; 335} 336 337void wxAppTraits::InitializeGui(unsigned long &WXUNUSED(ulHab)) 338{ 339} 340 341void wxAppTraits::TerminateGui(unsigned long WXUNUSED(ulHab)) 342{ 343} 344 345wxOperatingSystemId wxGetOsVersion(int *verMaj, int *verMin) 346{ 347 ULONG ulSysInfo = 0; 348 APIRET ulrc; 349 350 ulrc = ::DosQuerySysInfo( QSV_VERSION_MINOR, 351 QSV_VERSION_MINOR, 352 (PVOID)&ulSysInfo, 353 sizeof(ULONG) 354 ); 355 356 if (ulrc == 0L) 357 { 358 if ( verMaj ) 359 *verMaj = ulSysInfo / 10; 360 if ( verMin ) 361 *verMin = ulSysInfo % 10; 362 } 363 364 return wxOS_OS2; 365} 366 367 368// --------------------------------------------------------------------------- 369const wxChar* wxGetHomeDir( 370 wxString* pStr 371) 372{ 373 wxString& rStrDir = *pStr; 374 375 // OS/2 has no idea about home, 376 // so use the working directory instead. 377 // However, we might have a valid HOME directory, 378 // as is used on many machines that have unix utilities 379 // on them, so we should use that, if available. 380 381 // 256 was taken from os2def.h 382#ifndef MAX_PATH 383# define MAX_PATH 256 384#endif 385 386 const wxChar *szHome = wxGetenv((wxChar*)"HOME"); 387 if ( szHome == NULL ) { 388 // we're homeless, use current directory. 389 rStrDir = wxT("."); 390 } 391 else 392 rStrDir = szHome; 393 394 return rStrDir.c_str(); 395} 396 397// Hack for OS/2 398#if wxUSE_UNICODE 399const wxMB2WXbuf wxGetUserHome( const wxString &rUser ) 400#else // just for binary compatibility -- there is no 'const' here 401wxChar* wxGetUserHome ( const wxString &rUser ) 402#endif 403{ 404 wxChar* zHome; 405 wxString sUser1(rUser); 406 407 wxChar *wxBuffer = new wxChar[256]; 408#ifndef __EMX__ 409 if (!sUser1.empty()) 410 { 411 wxChar zTmp[64]; 412 413 if (wxGetUserId( zTmp 414 ,sizeof(zTmp)/sizeof(char) 415 )) 416 { 417 // Guests belong in the temp dir 418 if (wxStricmp(zTmp, _T("annonymous")) == 0) 419 { 420 if ((zHome = wxGetenv(_T("TMP"))) != NULL || 421 (zHome = wxGetenv(_T("TMPDIR"))) != NULL || 422 (zHome = wxGetenv(_T("TEMP"))) != NULL) 423 delete[] wxBuffer; 424 return *zHome ? zHome : (wxChar*)_T("\\"); 425 } 426 if (wxStricmp(zTmp, WXSTRINGCAST sUser1) == 0) 427 sUser1 = wxEmptyString; 428 } 429 } 430#endif 431 if (sUser1.empty()) 432 { 433 if ((zHome = wxGetenv(_T("HOME"))) != NULL) 434 { 435 wxStrcpy(wxBuffer, zHome); 436 wxUnix2DosFilename(wxBuffer); 437#if wxUSE_UNICODE 438 wxWCharBuffer retBuffer (wxBuffer); 439 delete[] wxBuffer; 440 return retBuffer; 441#else 442 wxStrcpy(zHome, wxBuffer); 443 delete[] wxBuffer; 444 return zHome; 445#endif 446 } 447 } 448 delete[] wxBuffer; 449 return (wxChar*)wxEmptyString; // No home known! 450} 451 452bool wxGetDiskSpace(const wxString& path, 453 wxDiskspaceSize_t *pTotal, 454 wxDiskspaceSize_t *pFree) 455{ 456 if (path.empty()) 457 return false; 458 459 wxFileName fn(path); 460 FSALLOCATE fsaBuf = {0}; 461 APIRET rc = NO_ERROR; 462 ULONG disknum = 0; 463 464 fn.MakeAbsolute(); 465 466 if (wxDirExists(fn.GetFullPath()) == false) 467 return false; 468 469 disknum = 1 + wxToupper(fn.GetVolume().GetChar(0)) - _T('A'); 470 471 rc = ::DosQueryFSInfo(disknum, // 1 = A, 2 = B, 3 = C, ... 472 FSIL_ALLOC, // allocation info 473 (PVOID)&fsaBuf, 474 sizeof(FSALLOCATE)); 475 476 if (rc != NO_ERROR) 477 return false; 478 else 479 { 480 if(pTotal) 481 { 482 // to try to avoid 32-bit overflow, let's not multiply right away 483 // (num of alloc units) 484 *pTotal = fsaBuf.cUnit; 485 // * (num of sectors per alloc unit) * (num of bytes per sector) 486 (*pTotal) *= fsaBuf.cSectorUnit * fsaBuf.cbSector; 487 } 488 if(pFree) 489 { 490 *pFree = fsaBuf.cUnitAvail; 491 (*pFree) *= fsaBuf.cSectorUnit * fsaBuf.cbSector; 492 } 493 return true; 494 } 495} 496 497wxString wxPMErrorToStr(ERRORID vError) 498{ 499 wxString sError; 500 501 // 502 // Remove the high order byte -- it is useless 503 // 504 vError &= 0x0000ffff; 505 switch(vError) 506 { 507 case PMERR_INVALID_HWND: 508 sError = wxT("Invalid window handle specified"); 509 break; 510 511 case PMERR_INVALID_FLAG: 512 sError = wxT("Invalid flag bit set"); 513 break; 514 515 case PMERR_NO_MSG_QUEUE: 516 sError = wxT("No message queue available"); 517 break; 518 519 case PMERR_INVALID_PARM: 520 sError = wxT("Parameter contained invalid data"); 521 break; 522 523 case PMERR_INVALID_PARAMETERS: 524 sError = wxT("Parameter value is out of range"); 525 break; 526 527 case PMERR_PARAMETER_OUT_OF_RANGE: 528 sError = wxT("Parameter value is out of range"); 529 break; 530 531 case PMERR_INVALID_INTEGER_ATOM: 532 sError = wxT("Not a valid atom"); 533 break; 534 535 case PMERR_INVALID_HATOMTBL: 536 sError = wxT("Atom table handle is invalid"); 537 break; 538 539 case PMERR_INVALID_ATOM_NAME: 540 sError = wxT("Not a valid atom name"); 541 break; 542 543 case PMERR_ATOM_NAME_NOT_FOUND: 544 sError = wxT("Valid name format, but cannot find name in atom table"); 545 break; 546 547 case PMERR_INV_HPS: 548 sError = wxT("PMERR_INV_HPS"); 549 break; 550 551 case PMERR_PS_BUSY: 552 sError = wxT("PMERR_PS_BUSY"); 553 break; 554 555 case PMERR_INV_PRIMITIVE_TYPE: 556 sError = wxT("PMERR_INV_PRIMITIVE_TYPE"); 557 break; 558 559 case PMERR_UNSUPPORTED_ATTR: 560 sError = wxT("PMERR_UNSUPPORTED_ATTR"); 561 break; 562 563 case PMERR_INV_COLOR_ATTR: 564 sError = wxT("PMERR_INV_COLOR_ATTR"); 565 break; 566 567 case PMERR_INV_BACKGROUND_COL_ATTR: 568 sError = wxT("PMERR_INV_BACKGROUND_COL_ATTR"); 569 break; 570 571 case PMERR_INV_MIX_ATTR: 572 sError = wxT("PMERR_INV_MIX_ATTR"); 573 break; 574 575 case PMERR_INV_LINE_WIDTH_ATTR: 576 sError = wxT("PMERR_INV_LINE_WIDTH_ATTR"); 577 break; 578 579 case PMERR_INV_GEOM_LINE_WIDTH_ATTR: 580 sError = wxT("PMERR_INV_GEOM_LINE_WIDTH_ATTR"); 581 break; 582 583 case PMERR_INV_LINE_TYPE_ATTR: 584 sError = wxT("PMERR_INV_LINE_TYPE_ATTR"); 585 break; 586 587 case PMERR_INV_LINE_END_ATTR: 588 sError = wxT("PMERR_INV_LINE_END_ATTR"); 589 break; 590 591 case PMERR_INV_LINE_JOIN_ATTR: 592 sError = wxT("PMERR_INV_LINE_JOIN_ATTR"); 593 break; 594 595 case PMERR_INV_CHAR_SET_ATTR: 596 sError = wxT("PMERR_INV_CHAR_SET_ATTR"); 597 break; 598 599 case PMERR_INV_CHAR_MODE_ATTR: 600 sError = wxT("PMERR_INV_CHAR_MODE_ATTR"); 601 break; 602 603 case PMERR_INV_CHAR_DIRECTION_ATTR: 604 sError = wxT("PMERR_INV_CHAR_DIRECTION_ATTR"); 605 break; 606 607 case PMERR_INV_CHAR_SHEAR_ATTR: 608 sError = wxT("PMERR_INV_CHAR_SHEAR_ATTR"); 609 break; 610 611 case PMERR_INV_CHAR_ANGLE_ATTR: 612 sError = wxT("PMERR_INV_CHAR_ANGLE_ATTR"); 613 break; 614 615 case PMERR_INV_MARKER_SET_ATTR: 616 sError = wxT("PMERR_INV_MARKER_SET_ATTR"); 617 break; 618 619 case PMERR_INV_MARKER_SYMBOL_ATTR: 620 sError = wxT("PMERR_INV_MARKER_SYMBOL_ATTR"); 621 break; 622 623 case PMERR_INV_PATTERN_SET_ATTR: 624 sError = wxT("PMERR_INV_PATTERN_SET_ATTR"); 625 break; 626 627 case PMERR_INV_PATTERN_ATTR: 628 sError = wxT("PMERR_INV_PATTERN_ATTR"); 629 break; 630 631 case PMERR_INV_COORDINATE: 632 sError = wxT("PMERR_INV_COORDINATE"); 633 break; 634 635 case PMERR_UNSUPPORTED_ATTR_VALUE: 636 sError = wxT("PMERR_UNSUPPORTED_ATTR_VALUE"); 637 break; 638 639 case PMERR_INV_PATTERN_SET_FONT: 640 sError = wxT("PMERR_INV_PATTERN_SET_FONT"); 641 break; 642 643 case PMERR_HUGE_FONTS_NOT_SUPPORTED: 644 sError = wxT("PMERR_HUGE_FONTS_NOT_SUPPORTED"); 645 break; 646 647 default: 648 sError = wxT("Unknown error"); 649 } 650 return sError; 651} // end of wxPMErrorToStr 652 653// replacement for implementation in unix/utilsunx.cpp, 654// to be used by all X11 based ports. 655struct wxEndProcessData; 656 657void wxHandleProcessTermination(wxEndProcessData *WXUNUSED(proc_data)) 658{ 659 // For now, just do nothing. To be filled in as needed. 660} 661