view compat.c @ 1483:73f2ad84d4ec

Fixed OS/2 windows being shown when setting position/size. Moved the OS/2 specific DW_OS2_NEW_WINDOW flag into os2/dw.c. Deprecated and essentially removed DW_FCF_SHELLPOSITION and DW_FCF_NOBYTEALIGN. These were OS/2 specific and are set automatically now... FCF_SHELLPOSITION was causing the positioning problems that necessitated the window being shown to set the size and position. Right now SHELLPOSITION isn't used at all... causing shell positioning to not work. I hope to have a way to allow shell positioning to work again soon but the idea I had to do this did not work.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Fri, 23 Dec 2011 15:58:13 +0000
parents 184b3aedc2ff
children 007ed833ac79
line wrap: on
line source

/* $Id$ */

#include "compat.h"
#include "dw.h"
#if defined(__OS2__) || defined(__WIN32__)
#include <share.h>
#endif

#if defined(__UNIX__) || defined(__MAC__)
#if defined(__FreeBSD__) || defined(__MAC__)
#include <sys/param.h>
#include <sys/ucred.h>
#include <sys/mount.h>
#elif defined(__sun__)
#include <sys/mnttab.h>
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/statvfs.h>
#else
#include <mntent.h>
#include <sys/vfs.h>
#endif
#endif
#include <time.h>
#include <errno.h>

#if defined(__UNIX__) || defined(__MAC__)
void msleep(long period)
{
#ifdef __sun__
	/* usleep() isn't threadsafe on Solaris */
	struct timespec req;

	req.tv_sec = 0;
	if(period >= 1000)
	{
		req.tv_sec = (int)(period / 1000);
		period -= (req.tv_sec * 1000);
	}
	req.tv_nsec = period * 10000000;
	
	nanosleep(&req, NULL);
#else
	usleep((int)(period * 1000));
#if defined(__MAC__) && !defined(GARBAGE_COLLECT)
    _dw_pool_drain();
#endif
#endif
}
#endif

int API makedir(char *path)
{
#if defined(__IBMC__) || defined(__WATCOMC__) || (defined(__WIN32__) && !defined(__CYGWIN32__))
	return mkdir(path);
#else
	return mkdir(path,S_IRWXU);
#endif
}

char * API vargs(char *buf, int len, char *format, ...)
{
	va_list args;

	va_start(args, format);
#ifdef HAVE_VSNPRINTF
	vsnprintf(buf, len, format, args);
#else
	len = len;
	vsprintf(buf, format, args);
#endif
	va_end(args);

	return buf;
}

long double API drivefree(int drive)
{
#if defined(__EMX__) || defined(__OS2__)
	ULONG   aulFSInfoBuf[40] = {0};
	APIRET  rc               = NO_ERROR;

	DosError(FERR_DISABLEHARDERR);
	rc = DosQueryFSInfo(drive,
						FSIL_ALLOC,
						(PVOID)aulFSInfoBuf,
						sizeof(aulFSInfoBuf));

	DosError(FERR_ENABLEHARDERR);
	if (rc != NO_ERROR)
		return 0;

	return (long double)((double)aulFSInfoBuf[3] * (double)aulFSInfoBuf[1] * (double)aulFSInfoBuf[4]);
#elif defined(__WIN32__) || defined(WINNT)
	char buffer[10] = "C:\\";
	DWORD spc, bps, fc, tc;

	buffer[0] = drive + 'A' - 1;

	if(GetDiskFreeSpace(buffer, &spc, &bps, &fc, &tc) == 0)
		return 0;

	return (long double)((double)spc*(double)bps*(double)fc);
#elif defined(__FreeBSD__) || defined(__MAC__)
	struct statfs *fsp;
	int entries, index = 1;

	entries = getmntinfo (&fsp, MNT_NOWAIT);

	for (; entries-- > 0; fsp++)
	{
		if(index == drive)
			return (long double)((double)fsp->f_bsize * (double)fsp->f_bavail);
		index++;
	}
	return 0;
#elif defined(__sun__)
	FILE *fp = fopen("/etc/mnttab", "r");
	struct mnttab mnt;
	struct statvfs sfs;
	int index = 1;

	if(fp)
	{
		while((getmntent(fp, &mnt) == 0))
		{
			if(index == drive)
			{
				long double size = 0;

				if(mnt.mnt_mountp)
				{
					if(!statvfs(mnt.mnt_mountp, &sfs))
					{
						size = (long double)((double)sfs.f_bsize * (double)sfs.f_bavail);
					}
				}
				fclose(fp);
				return size;
			}
			index++;          
		}
		fclose(fp);
	}
	return 0;
#else
	FILE *fp = setmntent(MOUNTED, "r");
	struct mntent mnt;
	struct statfs sfs;
	char buffer[1024];
	int index = 1;

	if(fp)
	{
		while(getmntent_r(fp, &mnt, buffer, sizeof(buffer)))
		{
			if(index == drive)
			{
				long double size = 0;

				if(mnt.mnt_dir)
				{
					if(!statfs(mnt.mnt_dir, &sfs))
					{
						size = (long double)((double)sfs.f_bsize * (double)sfs.f_bavail);
					}
				}
				endmntent(fp);
				return size;
			}
			index++;          
		}
		endmntent(fp);
	}
	return 0;
#endif
}

long double API drivesize(int drive)
{
#if defined(__EMX__) || defined(__OS2__)
	ULONG   aulFSInfoBuf[40] = {0};
	APIRET  rc               = NO_ERROR;

	DosError(FERR_DISABLEHARDERR);
	rc = DosQueryFSInfo(drive,
						FSIL_ALLOC,
						(PVOID)aulFSInfoBuf,
						sizeof(aulFSInfoBuf));

	DosError(FERR_ENABLEHARDERR);
	if (rc != NO_ERROR)
		return 0;

	return (long double)((double)aulFSInfoBuf[2] * (double)aulFSInfoBuf[1] * (double)aulFSInfoBuf[4]);
#elif defined(__WIN32__) || defined(WINNT)
	char buffer[10] = "C:\\";
	DWORD spc, bps, fc, tc;

	buffer[0] = drive + 'A' - 1;

	if(GetDiskFreeSpace(buffer, &spc, &bps, &fc, &tc) == 0)
		return 0;

	return (long double)((double)spc*(double)bps*(double)tc);
#elif defined(__FreeBSD__) || defined(__MAC__)
	struct statfs *fsp;
	int entries, index = 1;

	entries = getmntinfo (&fsp, MNT_NOWAIT);

	for (; entries-- > 0; fsp++)
	{
		if(index == drive)
			return (long double)((double)fsp->f_bsize * (double)fsp->f_blocks);
		index++;
	}
	return 0;
#elif defined(__sun__)
	FILE *fp = fopen("/etc/mnttab", "r");
	struct mnttab mnt;
	struct statvfs sfs;
	int index = 1;

	if(fp)
	{
		while(getmntent(fp, &mnt) == 0)
		{
			if(index == drive)
			{
				long double size = 0;

				if(mnt.mnt_mountp)
				{
					if(!statvfs(mnt.mnt_mountp, &sfs))
					{
						size = (long double)((double)sfs.f_bsize * (double)sfs.f_blocks);
					}
				}
				fclose(fp);
				return size;
			}
			index++;          
		}
		fclose(fp);
	}
	return 0;
#else
	FILE *fp = setmntent(MOUNTED, "r");
	struct mntent mnt;
	char buffer[1024];
	struct statfs sfs;
	int index = 1;

	if(fp)
	{
		while(getmntent_r(fp, &mnt, buffer, sizeof(buffer)))
		{
			if(index == drive)
			{
				long double size = 0;

				if(mnt.mnt_dir)
				{
					if(!statfs(mnt.mnt_dir, &sfs))
					{
						size = (long double)((double)sfs.f_bsize * (double)sfs.f_blocks);
					}
				}
				endmntent(fp);
				return size;
			}
			index++;          
		}
		endmntent(fp);
	}
	return 0;
#endif
}

int API isdrive(int drive)
{
#if defined(__EMX__) || defined(__OS2__)
	APIRET  rc               = NO_ERROR;
	FSINFO  volinfo;

	DosError(FERR_DISABLEHARDERR);
	rc = DosQueryFSInfo(drive,
			    FSIL_VOLSER,
			    (PVOID)&volinfo,
			    sizeof(FSINFO));

	DosError(FERR_ENABLEHARDERR);
	if (rc == NO_ERROR)
		return 1;

#elif defined(__WIN32__) || defined(WINNT)
	char buffer[10] = "C:\\", volname[100];
	DWORD spc, bps, fc;

	buffer[0] = drive + 'A' - 1;

	if(GetVolumeInformation(buffer, volname, 100, &spc, &bps, &fc, NULL, 0) != 0)
		return 1;
#elif defined(__FreeBSD__) || defined(__MAC__)
	struct statfs *fsp;
	int entries, index = 1;

	entries = getmntinfo (&fsp, MNT_NOWAIT);

	for (; entries-- > 0; fsp++)
	{
		if(index == drive && fsp->f_blocks)
			return 1;
		index++;
	}
	return 0;
#elif defined(__sun__)
	FILE *fp = fopen("/etc/mnttab", "r");
	struct mnttab mnt;
	struct statvfs sfs;
	int index = 1;

	if(fp)
	{
		while(getmntent(fp, &mnt) == 0)
		{
			if(index == drive)
			{
				fclose(fp);
				if(mnt.mnt_mountp)
				{
					if(!statvfs(mnt.mnt_mountp, &sfs) && sfs.f_blocks)
						return 1;
				}
				return 0;
			}
			index++;          
		}
		fclose(fp);
	}
#else
	FILE *fp = setmntent(MOUNTED, "r");
	struct mntent mnt;
	char buffer[1024];
	struct statfs sfs;
	int index = 1;

	if(fp)
	{
		while(getmntent_r(fp, &mnt, buffer, sizeof(buffer)))
		{
			if(index == drive)
			{
				endmntent(fp);
				if(mnt.mnt_dir)
				{
					if(!statfs(mnt.mnt_dir, &sfs) && sfs.f_blocks)
					{
						return 1;
					}
				}
				return 0;
			}
			index++;          
		}
		endmntent(fp);
	}
#endif
	return 0;
}

void API getfsname(int drive, char *buf, int len)
{
#if defined(__UNIX__) || defined(__MAC__) 
#if defined(__FreeBSD__) || defined(__MAC__)
	struct statfs *fsp;
	int entries, index = 1;

	strncpy(buf, "Unknown", len);

	entries = getmntinfo (&fsp, MNT_NOWAIT);

	for (; entries-- > 0; fsp++)
	{
		if(index == drive)
			strncpy(buf, fsp->f_mntonname, len);
		index++;
	}
#elif defined(__sun__)
	FILE *fp = fopen("/etc/mnttab", "r");
	struct mnttab mnt;
	int index = 1;

	strncpy(buf, "Unknown", len);

	if(fp)
	{
		while(getmntent(fp, &mnt) == 0)
		{
			if(index == drive && mnt.mnt_mountp)
				strncpy(buf, mnt.mnt_mountp, len);
			index++;          
		}
		fclose(fp);
	}
#else
	FILE *fp = setmntent(MOUNTED, "r");
	struct mntent mnt;
	char buffer[1024];
	int index = 1;

	strncpy(buf, "Unknown", len);

	if(fp)
	{
		while(getmntent_r(fp, &mnt, buffer, sizeof(buffer)))
		{
			if(index == drive && mnt.mnt_dir)
				strncpy(buf, mnt.mnt_dir, len);
			index++;          
		}
		endmntent(fp);
	}
#endif
#elif defined(__OS2__)
	/* No snprintf() on OS/2 ??? */
	len = len;
	sprintf(buf, "Drive %c",  (char)drive + 'A' - 1);
#else
	_snprintf(buf, len, "Drive %c",  (char)drive + 'A' - 1);
#endif
}

void API setfileinfo(char *filename, char *url, char *logfile)
{
	time_t		ltime;
	struct tm	*tm;
    char buffer[200], timebuf[200];
#ifdef __OS2__
	const unsigned fea2listsize = 6000;
	char *pData;
	EAOP2 eaop2;
	PFEA2 pFEA2;
#else
	FILE *urlfile;
#endif

	ltime = time(NULL);

	tm = localtime(&ltime);

	strftime(timebuf, 200, "%c", tm);

	sprintf(buffer, "%s %s", url, timebuf);

#ifdef __OS2__
	logfile = logfile;
	eaop2.fpGEA2List = 0;
	eaop2.fpFEA2List = (PFEA2LIST)malloc(fea2listsize);
	pFEA2 = &eaop2.fpFEA2List->list[0];

	pFEA2->fEA = 0;
    /* .COMMENTS is 9 characters long */
	pFEA2->cbName = 9;

	/* space for the type and length field. */
	pFEA2->cbValue = strlen(buffer)+2*sizeof(USHORT);

	strcpy(pFEA2->szName, ".COMMENTS");
	pData = pFEA2->szName+pFEA2->cbName+1;
	/* data begins at first byte after the name */

	*(USHORT*)pData = EAT_ASCII;             /* type */
	*((USHORT*)pData+1) = strlen(buffer);  /* length */
	strcpy(pData+2*sizeof(USHORT), buffer);/* content */

	pFEA2->oNextEntryOffset = 0;

	eaop2.fpFEA2List->cbList = ((PCHAR)pData+2*sizeof(USHORT)+
									 pFEA2->cbValue)-((PCHAR)eaop2.fpFEA2List);

	DosSetPathInfo((PSZ)filename,
						FIL_QUERYEASIZE,
						&eaop2,
						sizeof(eaop2),
						0);

	free((void *)eaop2.fpFEA2List);
#else

	if((urlfile = fopen(logfile, "a"))!=NULL)
	{
		fprintf(urlfile, "%s\n", buffer);
		fclose(urlfile);
	}
#endif
}

#if defined(__OS2__) || defined(__WIN32__)
typedef struct _fsinfo {
	FILE *fp;
	int fd;
} FSInfo;

FSInfo *FSIRoot = NULL;

#define FSI_MAX 100
#endif

/* Sharable fopen() and fclose() calls. */
FILE * API fsopen(char *path, char *modes)
{
#if (defined(__OS2__) && !defined(__WATCOMC__)) || defined(__WIN32__)
	int z;

	if(!FSIRoot)
		FSIRoot = calloc(sizeof(struct _fsinfo), FSI_MAX);

	for(z=0;z<FSI_MAX;z++)
	{
		if(FSIRoot[z].fd < 1)
		{
			int s, sopenmode = 0, wrmode = 0;

			/* Check the flags passed */
			for(s=0;s<3;s++)
			{
				if(modes[s] == 'b')
					sopenmode |= O_BINARY;
				if(modes[s] == 'r')
					wrmode |= O_RDONLY;
				if(modes[s] == 'w')
					wrmode |= O_WRONLY;
				if(modes[s] == 'a')
					sopenmode |= O_APPEND;
				if(modes[s] == 't')
					sopenmode |= O_TEXT;
			}

			/* Check the read/write request */
			if((wrmode & O_RDONLY) && (wrmode & O_WRONLY))
				sopenmode |= O_RDWR;
			else
				sopenmode |= wrmode;
			FSIRoot[z].fd = _sopen(path, sopenmode, SH_DENYNO, S_IREAD|S_IWRITE);
			if(FSIRoot[z].fd > 0)
			{
				FSIRoot[z].fp = fdopen(FSIRoot[z].fd, modes);

				return FSIRoot[z].fp;
			}
		}
	}
	return NULL;
#else
	return fopen(path, modes);
#endif
}

int API fsclose(FILE *fp)
{
#if defined(__OS2__) || defined(__WIN32__)
	if(FSIRoot)
	{

		int z;
		for(z=0;z<FSI_MAX;z++)
		{
			if(fp == FSIRoot[z].fp)
			{
				int ret = fclose(fp);
				close(FSIRoot[z].fd);
				FSIRoot[z].fd = 0;
				FSIRoot[z].fp = NULL;
				return ret;
			}
		}
	}
#endif
	return fclose(fp);
}

char * API fsgets(char *str, int size, FILE *stream)
{
	return fgets(str, size, stream);
}

int API fsseek(FILE *stream, long offset, int whence)
{
	return fseek(stream, offset, whence);
}

void API nice_strformat(char *dest, long double val, int dec)
{
	char formatbuf[10];
	char format = 0;
	double printval;

	/* 1024 ^ 3 = Gigabytes */
	if(val >= 1073741824L)
	{
		printval = val/(1073741824L);
		format = 'G';
	}
	/* 1024 ^ 2 = Megabytes */
	else if(val >= 1048576)
	{
		printval = val/(1048576);
		format = 'M';
	}
	/* 1024 = Kilobytes */
	else if(val > 1024)
	{
		printval = val/1024;
		format = 'K';
	}
	else
		printval = val;

	/* Generate the format string */
	sprintf(formatbuf, "%%.%df%c", dec, format);
	/* Create the pretty value */
	sprintf(dest, formatbuf, printval);
}

/* Update the current working directory based on the
 * path of the executable being executed.
 */
void API initdir(int argc, char *argv[])
{
	if(argc > 0)
	{
		char *tmpdir = strdup(argv[0]);
		int z, len = (int)strlen(argv[0]);

		for(z=len;z > -1;z--)
		{
			if(tmpdir[z] == '/')
			{
				tmpdir[z+1] = 0;
				setpath(tmpdir);
				free(tmpdir);
				return;
			}
		}
		free(tmpdir);
	}
}

/*
 * Sets	the current directory (and drive) information.
 * Parameters:
 *	 path: A buffer	containing the new path.
 * Returns:
 *	 -1 on error.
 */
int API setpath(char *path)
{
#if defined(__OS2__) || defined(__WIN32__)
	if(strlen(path)	> 2)
	{
		if(path[1] == ':')
		{
			char drive = toupper(path[0]);
			_chdrive((drive - 'A')+1);
		}
	}
#endif
	return chdir(path);
}

static int locale_number = -1, locale_count = 0;
static char **locale_text = NULL;

void _compat_free_locale(void)
{
	if(locale_text)
	{
		int z;

		for(z=0;z<locale_count;z++)
		{
			if(locale_text[z])
				free(locale_text[z]);
		}
		free(locale_text);
		locale_text = NULL;
	}
}

int _stripcrlf(char *buf)
{
	int z, len = (int)strlen(buf);

	for(z=0;z<len;z++)
	{
		if(buf[z] == '\r' || buf[z] == '\n')
		{
			buf[z] = 0;
			return 1;
		}
	}
	return 1;
}

#ifdef __WIN32__
#define LOCALE_CHARACTERS 62
static char locale_table[LOCALE_CHARACTERS * 2] = {
	0xc0, 0xb7, 0xc1, 0xb5, 0xc2, 0xb6, 0xc3, 0xc7, 0xc4, 0x8e, 0xc5, 0x8f,
	0xc6, 0x92, 0xc7, 0x80, 0xc8, 0xd4, 0xc9, 0x90, 0xcb, 0xd3, 0xcc, 0xde,
	0xcd, 0xd6, 0xce, 0xd7, 0xcf, 0xd8, 0xd0, 0xd1, 0xd1, 0xa5, 0xd2, 0xe3,
	0xd3, 0xe0, 0xd4, 0xe2, 0xd5, 0xe5, 0xd6, 0x99, 0xd8, 0x9d, 0xd9, 0xeb,
	0xda, 0xe9, 0xdb, 0xea, 0xdc, 0x9a, 0xde, 0xed, 0xde, 0xe8, 0xdf, 0xe1,
	0xe0, 0x85, 0xe1, 0xa0, 0xe2, 0x83, 0xe3, 0xc6, 0xe4, 0x84, 0xe5, 0x86,
	0xe6, 0x91, 0xe7, 0x87, 0xe8, 0x8a, 0xe9, 0x82, 0xea, 0x88, 0xeb, 0x89,
	0xec, 0x8d, 0xed, 0xa1, 0xee, 0x8c, 0xef, 0x8b, 0xf0, 0xd0, 0xf1, 0xa4,
	0xf2, 0x95, 0xf3, 0xa3, 0xf4, 0x93, 0xf5, 0xe4, 0xf6, 0x94, 0xf7, 0xf6,
	0xf8, 0x9b, 0xf9, 0x97, 0xfa, 0xa3, 0xfb, 0x96, 0xfc, 0x81, 0xfd, 0xec,
    0xfe, 0xe7, 0xff, 0x9e

};

char locale_convert(int codepage, char c)
{
	int z;

	for(z=0;z<LOCALE_CHARACTERS;z++)
	{
		if(locale_table[(z*2)+1] == c)
			return locale_table[z*2];
	}
	return c;
}
#endif

/* Initialize the locale engine
 * Returns: TRUE on success, FALSE on failure.
 */
int API locale_init(char *filename, int my_locale)
{
	FILE *fp = fopen(filename, FOPEN_READ_TEXT);
	static char text[1025];
	int count = 0;

	_compat_free_locale();

	if(fp)
	{
		if(fgets(text, 1024, fp) && strncasecmp(text, "MESSAGES=", 9) == 0 && (count = atoi(&text[9])) > 0)
		{
			int current = -1;

			locale_text = calloc(count, sizeof(char *));

			while(!feof(fp))
			{
				if(fgets(text, 1024, fp) && _stripcrlf(text) &&
				   strncasecmp(text, "LOCALE=", 7) == 0)
				{
					if(current > -1)
					{
						fclose(fp);
						locale_count = count;
						locale_number = my_locale;
						return 1;
					}
					if(atoi(&text[7]) == my_locale)
						current = 0;
				}
				else if(current > -1 && current < count)
				{
					/* Use defaults on blank lines */
					if(text[0])
					{
						int x = 0, z, len = (int)strlen(text);

						locale_text[current] = calloc(1, len + 1);

						for(z=0;z<len;z++)
						{
							if(text[z] == '\\' && (text[z+1] == 'r' || text[z+1] == 'n'
							   || text[z+1] == '\"'  || text[z+1] == '\''))
							{
								switch(text[z+1])
								{
								case 'r':
									locale_text[current][x] = '\r';
                                    break;
								case 'n':
									locale_text[current][x] = '\n';
                                    break;
								case '\"':
									locale_text[current][x] = '\"';
                                    break;
								case '\'':
									locale_text[current][x] = '\'';
                                    break;
								}
								x++;
								z++;
							}
							else
							{
#ifdef __WIN32__
								locale_text[current][x] = locale_convert(1252, text[z]);
#else
								locale_text[current][x] = text[z];
#endif
								x++;
							}
						}
					}
					current++;
				}
			}
		}
		fclose(fp);
	}
	if(locale_text && count)
	{
		locale_count = count;
		locale_number = my_locale;
		return 1;
	}
	return 0;
}

/* Retrieve a localized string if available */
char * API locale_string(char *default_text, int message)
{
	if(locale_number > -1 && message < locale_count && message > -1 && locale_text[message])
		return locale_text[message];
	return default_text;
}