| /**************************************************************************** |
| * |
| * SciTech OS Portability Manager Library |
| * |
| * ======================================================================== |
| * |
| * The contents of this file are subject to the SciTech MGL Public |
| * License Version 1.0 (the "License"); you may not use this file |
| * except in compliance with the License. You may obtain a copy of |
| * the License at http://www.scitechsoft.com/mgl-license.txt |
| * |
| * Software distributed under the License is distributed on an |
| * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or |
| * implied. See the License for the specific language governing |
| * rights and limitations under the License. |
| * |
| * The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc. |
| * |
| * The Initial Developer of the Original Code is SciTech Software, Inc. |
| * All Rights Reserved. |
| * |
| * ======================================================================== |
| * |
| * Language: ANSI C |
| * Environment: Any |
| * |
| * Description: Module containing code common to all platforms. |
| * |
| ****************************************************************************/ |
| |
| #include "pmapi.h" |
| #include "drvlib/os/os.h" |
| #if defined(__WIN32_VXD__) || defined(__OS2_VDD__) || defined(__NT_DRIVER__) |
| #include "sdd/sddhelp.h" |
| #else |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #endif |
| |
| /*---------------------------- Global variables ---------------------------*/ |
| |
| /* {secret} */ |
| long _VARAPI ___drv_os_type = _OS_UNSUPPORTED; |
| static char localBPDPath[PM_MAX_PATH] = ""; |
| |
| /*----------------------------- Implementation ----------------------------*/ |
| |
| /**************************************************************************** |
| PARAMETERS: |
| path - Local path to the Nucleus BPD driver files. |
| |
| REMARKS: |
| This function is used by the application program to override the location |
| of the Nucleus driver files that are loaded. Normally the loader code |
| will look in the system Nucleus directories first, then in the 'drivers' |
| directory relative to the current working directory, and finally relative |
| to the MGL_ROOT environment variable. By default the local BPD path is |
| always set to the current directory if not initialised. |
| ****************************************************************************/ |
| void PMAPI PM_setLocalBPDPath( |
| const char *path) |
| { |
| PM_init(); |
| strncpy(localBPDPath,path,sizeof(localBPDPath)); |
| localBPDPath[sizeof(localBPDPath)-1] = 0; |
| } |
| |
| /**************************************************************************** |
| PARAMETERS: |
| bpdpath - Place to store the actual path to the file |
| cachedpath - Place to store the cached BPD driver path |
| trypath - Path to try to find the BPD file in |
| subpath - Optional sub path to append to trypath |
| dllname - Name of the Binary Portable DLL to load |
| |
| RETURNS: |
| True if found, false if not. |
| |
| REMARKS: |
| Trys the specified path to see if the BPD file can be found or not. If so, |
| the path used is returned in bpdpath and cachedpath. |
| ****************************************************************************/ |
| static ibool TryPath( |
| char *bpdpath, |
| char *cachedpath, |
| const char *trypath, |
| const char *subpath, |
| const char *dllname) |
| { |
| char filename[256]; |
| FILE *f; |
| |
| strcpy(bpdpath, trypath); |
| PM_backslash(bpdpath); |
| strcat(bpdpath,subpath); |
| PM_backslash(bpdpath); |
| strcpy(filename,bpdpath); |
| strcat(filename,dllname); |
| if ((f = fopen(filename,"rb")) == NULL) |
| return false; |
| if (cachedpath) |
| strcpy(cachedpath,bpdpath); |
| fclose(f); |
| return true; |
| } |
| |
| /**************************************************************************** |
| RETURNS: |
| True if local override enabled, false if not. |
| |
| REMARKS: |
| Tests to see if the local override option is enabled, and if so it will |
| look for the Nucleus drivers in the local application directories in |
| preference to the Nucleus system directories. |
| ****************************************************************************/ |
| static ibool GetLocalOverride(void) |
| { |
| char filename[256]; |
| FILE *f; |
| static ibool local_override = -1; |
| |
| if (local_override == -1) { |
| local_override = false; |
| strcpy(filename,PM_getNucleusPath()); |
| PM_backslash(filename); |
| strcat(filename,"graphics.ini"); |
| if ((f = fopen(filename,"r")) != NULL) { |
| while (!feof(f) && fgets(filename,sizeof(filename),f)) { |
| if (strnicmp(filename,"uselocal",8) == 0) { |
| local_override = ((*(filename+9) - '0') == 1); |
| break; |
| } |
| } |
| fclose(f); |
| } |
| } |
| return local_override; |
| } |
| |
| /**************************************************************************** |
| DESCRIPTION: |
| Sets the location of the debug log file. |
| |
| HEADER: |
| pmapi.h |
| |
| PARAMETERS: |
| dllname - Name of the Binary Portable DLL to load |
| bpdpath - Place to store the actual path to the file |
| |
| RETURNS: |
| True if found, false if not. |
| |
| REMARKS: |
| Finds the location of a specific Binary Portable DLL, by searching all |
| the standard SciTech Nucleus driver locations. |
| ****************************************************************************/ |
| ibool PMAPI PM_findBPD( |
| const char *dllname, |
| char *bpdpath) |
| { |
| static char cachedpath[PM_MAX_PATH] = ""; |
| |
| /* On the first call determine the path to the Nucleus drivers */ |
| if (cachedpath[0] == 0) { |
| /* First try in the global system Nucleus driver path if |
| * the local override setting is not enabled. |
| */ |
| PM_init(); |
| if (!GetLocalOverride()) { |
| if (TryPath(bpdpath,cachedpath,PM_getNucleusPath(),"",dllname)) |
| return true; |
| } |
| |
| /* Next try in the local application directory if available */ |
| if (localBPDPath[0] != 0) { |
| if (TryPath(bpdpath,cachedpath,localBPDPath,"",dllname)) |
| return true; |
| } |
| else { |
| #if !defined(__WIN32_VXD__) && !defined(__NT_DRIVER__) |
| char *mgl_root; |
| if ((mgl_root = getenv("MGL_ROOT")) != NULL) { |
| if (TryPath(bpdpath,cachedpath,mgl_root,"drivers",dllname)) |
| return true; |
| } |
| #endif |
| PM_getCurrentPath(bpdpath,PM_MAX_PATH); |
| if (TryPath(bpdpath,cachedpath,bpdpath,"drivers",dllname)) |
| return true; |
| } |
| |
| /* Finally try in the global system path again so that we |
| * will still find the drivers in the global system path if |
| * the local override option is on, but the application does |
| * not have any local override drivers. |
| */ |
| if (TryPath(bpdpath,cachedpath,PM_getNucleusPath(),"",dllname)) |
| return true; |
| |
| /* Whoops, we can't find the BPD file! */ |
| return false; |
| } |
| |
| /* Always try in the previously discovered path */ |
| return TryPath(bpdpath,NULL,cachedpath,"",dllname); |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| Copies a string into another, and returns dest + strlen(src). |
| ****************************************************************************/ |
| static char *_stpcpy( |
| char *_dest, |
| const char *_src) |
| { |
| if (!_dest || !_src) |
| return 0; |
| while ((*_dest++ = *_src++) != 0) |
| ; |
| return --_dest; |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| Copies a string into another, stopping at the maximum length. The string |
| is properly terminated (unlike strncpy). |
| ****************************************************************************/ |
| static void safe_strncpy( |
| char *dst, |
| const char *src, |
| unsigned maxlen) |
| { |
| if (dst) { |
| if(strlen(src) >= maxlen) { |
| strncpy(dst, src, maxlen); |
| dst[maxlen] = 0; |
| } |
| else |
| strcpy(dst, src); |
| } |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| Determins if the dot separator is present in the string. |
| ****************************************************************************/ |
| static int findDot( |
| char *p) |
| { |
| if (*(p-1) == '.') |
| p--; |
| switch (*--p) { |
| case ':': |
| if (*(p-2) != '\0') |
| break; |
| case '/': |
| case '\\': |
| case '\0': |
| return true; |
| } |
| return false; |
| } |
| |
| /**************************************************************************** |
| DESCRIPTION: |
| Make a full pathname from split components. |
| |
| HEADER: |
| pmapi.h |
| |
| PARAMETERS: |
| path - Place to store full path |
| drive - Drive component for path |
| dir - Directory component for path |
| name - Filename component for path |
| ext - Extension component for path |
| |
| REMARKS: |
| Function to make a full pathname from split components. Under Unix the |
| drive component will usually be empty. If the drive, dir, name, or ext |
| parameters are null or empty, they are not inserted in the path string. |
| Otherwise, if the drive doesn't end with a colon, one is inserted in the |
| path. If the dir doesn't end in a slash, one is inserted in the path. |
| If the ext doesn't start with a dot, one is inserted in the path. |
| |
| The maximum sizes for the path string is given by the constant PM_MAX_PATH, |
| which includes space for the null-terminator. |
| |
| SEE ALSO: |
| PM_splitPath |
| ****************************************************************************/ |
| void PMAPI PM_makepath( |
| char *path, |
| const char *drive, |
| const char *dir, |
| const char *name, |
| const char *ext) |
| { |
| if (drive && *drive) { |
| *path++ = *drive; |
| *path++ = ':'; |
| } |
| if (dir && *dir) { |
| path = _stpcpy(path,dir); |
| if (*(path-1) != '\\' && *(path-1) != '/') |
| #ifdef __UNIX__ |
| *path++ = '/'; |
| #else |
| *path++ = '\\'; |
| #endif |
| } |
| if (name) |
| path = _stpcpy(path,name); |
| if (ext && *ext) { |
| if (*ext != '.') |
| *path++ = '.'; |
| path = _stpcpy(path,ext); |
| } |
| *path = 0; |
| } |
| |
| /**************************************************************************** |
| DESCRIPTION: |
| Split a full pathname into components. |
| |
| HEADER: |
| pmapi.h |
| |
| PARAMETERS: |
| path - Full path to split |
| drive - Drive component for path |
| dir - Directory component for path |
| name - Filename component for path |
| ext - Extension component for path |
| |
| RETURNS: |
| Flags indicating what components were parsed. |
| |
| REMARKS: |
| Function to split a full pathmame into separate components in the form |
| |
| X:\DIR\SUBDIR\NAME.EXT |
| |
| and splits path into its four components. It then stores those components |
| in the strings pointed to by drive, dir, name and ext. (Each component is |
| required but can be a NULL, which means the corresponding component will be |
| parsed but not stored). |
| |
| The maximum sizes for these strings are given by the constants PM_MAX_DRIVE |
| and PM_MAX_PATH. PM_MAX_DRIVE is always 4, and PM_MAX_PATH is usually at |
| least 256 characters. Under Unix the dir, name and ext components may be |
| up to the full path in length. |
| |
| SEE ALSO: |
| PM_makePath |
| ****************************************************************************/ |
| int PMAPI PM_splitpath( |
| const char *path, |
| char *drive, |
| char *dir, |
| char *name, |
| char *ext) |
| { |
| char *p; |
| int temp,ret; |
| char buf[PM_MAX_PATH+2]; |
| |
| /* Set all string to default value zero */ |
| ret = 0; |
| if (drive) *drive = 0; |
| if (dir) *dir = 0; |
| if (name) *name = 0; |
| if (ext) *ext = 0; |
| |
| /* Copy filename into template up to PM_MAX_PATH characters */ |
| p = buf; |
| if ((temp = strlen(path)) > PM_MAX_PATH) |
| temp = PM_MAX_PATH; |
| *p++ = 0; |
| strncpy(p, path, temp); |
| *(p += temp) = 0; |
| |
| /* Split the filename and fill corresponding nonzero pointers */ |
| temp = 0; |
| for (;;) { |
| switch (*--p) { |
| case '.': |
| if (!temp && (*(p+1) == '\0')) |
| temp = findDot(p); |
| if ((!temp) && ((ret & PM_HAS_EXTENSION) == 0)) { |
| ret |= PM_HAS_EXTENSION; |
| safe_strncpy(ext, p, PM_MAX_PATH - 1); |
| *p = 0; |
| } |
| continue; |
| case ':': |
| if (p != &buf[2]) |
| continue; |
| case '\0': |
| if (temp) { |
| if (*++p) |
| ret |= PM_HAS_DIRECTORY; |
| safe_strncpy(dir, p, PM_MAX_PATH - 1); |
| *p-- = 0; |
| break; |
| } |
| case '/': |
| case '\\': |
| if (!temp) { |
| temp++; |
| if (*++p) |
| ret |= PM_HAS_FILENAME; |
| safe_strncpy(name, p, PM_MAX_PATH - 1); |
| *p-- = 0; |
| if (*p == 0 || (*p == ':' && p == &buf[2])) |
| break; |
| } |
| continue; |
| case '*': |
| case '?': |
| if (!temp) |
| ret |= PM_HAS_WILDCARDS; |
| default: |
| continue; |
| } |
| break; |
| } |
| if (*p == ':') { |
| if (buf[1]) |
| ret |= PM_HAS_DRIVE; |
| safe_strncpy(drive, &buf[1], PM_MAX_DRIVE - 1); |
| } |
| return ret; |
| } |
| |
| /**************************************************************************** |
| DESCRIPTION: |
| Block until a specific time has elapsed since the last call |
| |
| HEADER: |
| pmapi.h |
| |
| PARAMETERS: |
| milliseconds - Number of milliseconds for delay |
| |
| REMARKS: |
| This function will block the calling thread or process until the specified |
| number of milliseconds have passed since the /last/ call to this function. |
| The first time this function is called, it will return immediately. On |
| subsquent calls it will block until the specified time has elapsed, or it |
| will return immediately if the time has already elapsed. |
| |
| This function is useful to provide constant time functionality in a |
| program, such as a frame rate limiter for graphics applications etc. |
| |
| SEE ALSO: |
| PM_sleep |
| ****************************************************************************/ |
| void PMAPI PM_blockUntilTimeout( |
| ulong milliseconds) |
| { |
| ulong microseconds = milliseconds * 1000L,msDelay; |
| static LZTimerObject tm; |
| static ibool firstTime = true; |
| |
| if (firstTime) { |
| firstTime = false; |
| LZTimerOnExt(&tm); |
| } |
| else { |
| if ((msDelay = (microseconds - LZTimerLapExt(&tm)) / 1000L) > 0) |
| PM_sleep(msDelay); |
| while (LZTimerLapExt(&tm) < microseconds) |
| ; |
| LZTimerOffExt(&tm); |
| LZTimerOnExt(&tm); |
| } |
| } |