home *** CD-ROM | disk | FTP | other *** search
- /*
-
- WinUtil
-
- General Purpose Functions for Windows DDE
-
- by Phil Ford
- ________________________________________________________________________
-
- (C) Copyright 1990-1995 by Autodesk, Inc.
-
- Permission to use, copy, modify, and distribute this software and its
- documentation for any purpose and without fee is hereby granted.
-
- THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
- ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
- MERCHANTABILITY ARE HEREBY DISCLAIMED.
- ________________________________________________________________________
- */
-
- #include "options.h"
- #include <string.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include "winutil.h"
-
- /* Uses RTL's assert() which just exits the app */
- #ifndef ASSERT
- #define ASSERT assert
- #endif
-
- /* "+" so spreadsheet knows it's a number
- ".6" means 6 decimal places
- "lf" means double floating point number
- This can be changed by C application for
- more or less precision. */
- char RealFmt[10] = "%+.6lf";
- const char RealScan[] = "%lf";
- int FpPrecision = 6;
-
- char FldSep[30] = "\t";
- char *FldSepStr = FldSep;
- char FldSepChr = TAB;
-
- char RecSep[30] = "\r\n";
- char *RecSepStr = RecSep;
- char RecSepChr1 = CR;
- char RecSepChr2 = LF;
-
- const char NullStr[] = "";
- const char CrLf[] = "\r\n";
-
- /*
- The clib_xxxseparators are what C RTL use in functions like
- sscanf(), sprintf() etc. '.' is typically the decimal separator.
- */
- static const char clib_decseparator[] = "."; /* decimal separator used by RTL */
- static const char clib_tseparator[] = ","; /* thousand separator used by RTL */
- /*
- The win_xxxseparators are what Windows use, they can be
- changed from the control panel/international dialog box.
- */
- static char win_decseparator[ 3 ]; /* decimal separator used by Windows */
- static char win_tseparator[ 3 ]; /* thousand separator used by Windows */
- BOOL separator_inited = FALSE;
-
- static void WinDecimalChars( char *strbuf );
- static void ClibDecimalChars( char *strbuf );
- static BOOL InitDecimalChars();
-
- /*
-
- General Purpose Utilities
- */
-
-
-
-
- /*
-
- Text Linked List Functions
-
- */
-
-
-
- /* Save some text in a linked list of text strings.
- Text links are a simple special case of generic LINK
- structure. Send ADDRESS of the text list starting node,
- so it can be updated if necessary, instead of the value
- (TextList). E.g.,
- void *TextList = NULL;
- AddText(&TextList, "New text");
- AddText(&Textlist, "Next text");
- */
- void *AddText(void **TextList, char *Str)
- {
- Tlink *NewLink;
-
- if (!Str || !TextList)
- return NULL;
- NewLink = AddLink(TextList, sizeof(Tlink));
- if (!NewLink)
- return NULL;
- NewLink->text = _strdup(Str);
- return NewLink;
- }
-
-
- /* Is a certain string in a string list? Not case sensitive.
- */
- void *InTextList(void *TextList, char *Str)
- {
- Tlink *Link;
-
- for (Link = TextList; Link != NULL; Link = Link->next) {
- if (!_stricmp(Str, Link->text))
- return Link;
- }
- return NULL;
- }
-
-
- /* Remove a string from a list, or use NULL Str to remove
- entire list. Send addr of first node of list.
- */
- void *RemoveText(void **TextList, char *Str)
- {
- Tlink *link;
- Tlink *Next;
- Tlink *Prev = NULL;
-
- for (link = *TextList; link != NULL; link = Next) {
- Next = link->next;
- if (!Str) {
- free(link->text);
- free(link);
- }
-
- /* We're looking for topic, but
- this isn't it. */
- else if (!_stricmp(Str, link->text)) {
- Prev = FreeText(TextList, link);
- return Prev;
- }
- }
- if (!Str)
- *TextList = NULL; /* NULL list now--all links deleted. */
- return Prev;
- }
-
-
- /* Free a text link from list starting with TextList
- (ADDR of first link).
- */
- void *FreeText(void **TextList, void *TextLink)
- {
- Tlink *Prev, *tlink;
-
- if (!TextLink)
- return NULL;
- tlink = TextLink;
- free(tlink->text);
- Prev = FreeLink(TextList, tlink, sizeof(Tlink));
- return Prev;
- }
-
-
- /*
-
- Generic Link List Functions
-
- (First item in structure must
- be pointer to next.)
-
- */
-
-
- /* Allocate an object of LinkSize and add to list
- starting with List. Send address of first link in
- list, e.g.,
- void *List = NULL;
- void *Item;
- Item = AddLink(&List, 30);
- */
- void *AddLink(void **List, int LinkSize)
- {
- Tlink *link;
- Tlink *Last;
-
- link = calloc(1, LinkSize);
- if (!link)
- return NULL;
- if (!*List)
- *List = link;
- else {
- Last = GetLastLink(*List);
- Last->next = link;
- }
- return link;
- }
-
-
-
- /* Remove link (fix previous->next) and then
- free it. Send address of first link, as List.
- */
- void *FreeLink(void **List, void *link, int LinkSize)
- {
- Tlink *Prev;
-
- Prev = RemoveLink(List, link);
- free(link);
- return Prev;
- }
-
-
- /* Get link after LastLink. Set LastLink to NULL
- to get first link. Can use in a loop to cycle
- through list:
- Link = NULL;
- while (TRUE)
- {
- link = GetNextLink(List, link);
- if (!link)
- link = GetNextLink(List, link);
- ...
- }
- */
- void *GetNextLink(void *List, void *LastLink)
- {
- Tlink *link;
-
- if (!List)
- return NULL;
- if (!LastLink)
- return List;
- link = LastLink;
- return link->next;
- }
-
-
- /* Remove a link, Target, from a generic linked list whose
- starting link is List. List is updated if necessary.
- The previous link is returned, or next if no previous.
- The link is NOT freed, just unlinked. Use FreeLink to remove
- and then free, if the link doesn't contain pointers that
- need to be freed individually.
- E.g.,
- void *List = NULL;
- void *link;
- link = AddLink(&List, ITEMSIZE);
- RemoveLink(&List, link);
- */
- void *RemoveLink(void **List, void *Target)
- {
- Tlink *link;
- Tlink *Prev = NULL;
- int FoundIt = FALSE;
-
- /* Make sure the list exists. */
- if (*List == NULL || Target == NULL)
- return NULL;
- /* Scan list looking for the link to remove. */
- for (link = *List; link != NULL; link = link->next) {
- if (link == Target) {
- FoundIt = TRUE;
- break;
- }
- else
- Prev = link;
- }
- if (!FoundIt)
- return NULL;
- if (Prev == NULL) { /* first link in list */
- if (link->next == NULL) /* only link in list */
- *List = NULL; /* no more list */
- else
- *List = link->next; /* list starts with 2nd link, now */
- return *List; /* return neighbor after current
- link */
- }
- Prev->next = link->next; /* bypass removed link */
- return Prev; /* return neighbor before current link */
- }
-
-
- /* Free links in list, starting with link "List". E.g.,
- void *List = NULL;
- AddLink(&List, ITEMSIZE);
- FreeList(&List, ITEMSIZE);
- */
- void FreeList(void **List, int NodeSize)
- {
- Tlink *link;
- Tlink *Next;
-
- for (link = *List; link != NULL; link = Next) {
- Next = link->next;
- free(link);
- }
- *List = NULL;
- }
-
-
- /* Find last link in list starting with List link.
- */
- void *GetLastLink(void *ListStart)
- {
- Tlink *link, *Prev;
-
- if (!ListStart)
- return NULL;
- for (link = ListStart; link != NULL; link = link->next)
- Prev = link;
- return Prev;
- }
-
-
-
- /* Get the length of a linked list. First item in
- structure must be pointer to next.
- */
- int GetListLen(void *List)
- {
- int Len = 0;
- Tlink *link;
-
- for (link = List; link != NULL; link = link->next)
- ++Len;
- return Len;
- }
-
-
-
- /*
- Bit Field Functions
-
- Set, find, and clear empty bits in an array of int's.
-
- */
-
-
- /* Find the first empty bit in the bit map and set it.
- MapLen is length in int'S of your bit map.
- E.g.
- #define NUMOBJECTS 1024 must be multiple of 16
- #define MAPLEN (NUMOBJECTS / BITWORDLEN)
-
- USHORT BitMap[MAPLEN] = {0};
- Num = SetNextBit(BitMap, MAPLEN);
- CheckBit(BitMap, 3);
- etc.
- */
- int SetNextBit(USHORT *BitMap, UINT MapLen)
- {
- UINT Bit;
-
- Bit = FindEmptyBit(BitMap, MapLen);
- if (Bit != BITMAPFULL)
- SetBit(BitMap, Bit);
- return Bit;
- }
-
-
-
- /* Is bit, Number, set. Starts with 1.
- */
- int CheckBit(USHORT *BitMap, UINT Number)
- {
- USHORT BitMapWord;
- USHORT Bit = 1;
-
- if (!Number)
- return FALSE;
- --Number; /* make 0 based */
- Bit <<= (Number % BITWORDLEN);
- BitMapWord = Number / BITWORDLEN;
- if (BitMap[BitMapWord] & Bit)
- return 1;
- else
- return 0;
- }
-
- /* Clear the bit, Number. Starts with 1.
- */
- void ClearBit(USHORT *BitMap, UINT Number)
- {
- USHORT BitMapWord;
- USHORT Bit = 1;
-
- if (!Number)
- return;
- --Number; /* make 0 based */
- Bit <<= (Number % BITWORDLEN);
- BitMapWord = Number / BITWORDLEN;
- BitMap[BitMapWord] &= ~Bit;
- }
-
-
- /* Set bit corresponding to Number from
- 1 to MAPLEN.
- */
- int SetBit(USHORT *BitMap, UINT Number)
- {
- USHORT BitMapWord;
- USHORT Bit = 1;
-
- if (!Number)
- return FALSE;
- --Number; /* make 0 based */
- Bit <<= (Number % BITWORDLEN);
- BitMapWord = Number / BITWORDLEN;
- BitMap[BitMapWord] |= Bit;
- return TRUE;
- }
-
-
- /* Find an empty bit in the map. Returns -1 if none.
- The MapLen is the number of bits.
- */
- int FindEmptyBit(USHORT *BitMap, UINT MapLen)
- {
- USHORT Bit;
- USHORT BitMask;
- USHORT Word;
- UINT FoundEmpty = 0;
-
- for (Word = 0; Word < MapLen; ++Word) {
- if (BitMap[Word] != 0xffff) {
- FoundEmpty = 1;
- break;
- }
- }
- if (!FoundEmpty)
- return BITMAPFULL;
-
- BitMask = 1;
- for (Bit = 1; Bit <= BITWORDLEN; ++Bit) {
- if ((BitMap[Word] & BitMask) == 0)
- return ((Word * BITWORDLEN) + Bit);
- else
- BitMask <<= 1;
- }
- }
-
- /* Save string up to a TAB, CR, etc. Use free to
- free it. Mainly for getting floating point string from
- text stream with TABS and CRLFs.
- */
- char *FieldSave(char *Word)
- {
- char *src, *dest;
- char buf[120];
-
- src = Word;
- dest = buf;
- while ( *( ( unsigned char* )src ) >= ( unsigned char )SP )
- {
- *dest++ = *src++;
- }
- *dest = EOS;
- return _strdup(buf);
- }
-
- /* Limit string copy and put a 0 at the end of the destination
- string, even if the source exceeds the max (unlike standard strncpy).
- Protects against a string that's too long for the destination.
- "maxstr" is maximum string length (max storage - 1). The source
- may be a NULL pointer, but not the destination. Returns length of
- string. */
-
- int
- /*FCN*/strzcpy(dest, source, maxstr)
- char *dest;
- char *source;
- int maxstr;
- {
- int idx;
-
- if (source == dest)
- return 0;
- if (source == NULL) {
- dest[0] = EOS;
- return 0;
- }
- for (idx = 0; idx < maxstr; ++idx) {
- if ((dest[idx] = source[idx]) == EOS)
- return idx;
- }
- dest[maxstr] = EOS;
- return idx;
- }
-
-
-
-
- /*
-
- Memory Allocation
-
- */
-
- /* Allocate a far pointer with GlobalAlloc to data over 64k. Set ShareFlag
- TRUE to make it sharable memory. Use FreeFar to free it.
- */
- char huge *AllocHuge(long DataLen, int ShareFlag)
- {
- return (char huge *)AllocFar(DataLen, ShareFlag);
- }
-
- /* Flexible alloc: try to alloc Len, if fail, half Len, up
- to 16 times. Return pointer, return actual len in ActualLen.
- Use FreeFar to free it.
- */
- void huge *AllocFlex(long Len, long *ActualLen)
- {
- void huge *ptr;
- long ActLen;
- int cnt = 0;
-
- ActLen = Len;
- while ((ptr = AllocFar(ActLen, FALSE)) == NULL) {
- ++cnt;
- if (cnt > 16)
- break;
- ActLen /= 2;
- }
- *ActualLen = ActLen;
- return ptr;
- }
-
- /* Allocate a far pointer with GlobalAlloc. Set ShareFlag
- TRUE to make it sharable memory. Use FreeFar to free it.
- */
- char far *AllocFar(long DataLen, int ShareFlag)
- {
- #if USE_GLOBAL
- WORD wFlag;
- HANDLE hmem;
-
- wFlag = GMEM_MOVEABLE;
- if (ShareFlag)
- wFlag |= GMEM_DDESHARE;
-
- hmem = GlobalAlloc(wFlag, DataLen);
- if (!hmem)
- return NULL;
- return GlobalLock(hmem);
- #else
- return malloc((int)DataLen);
- #endif
- }
-
-
-
-
- /* Free far or huge pointer, acquired using AllocFar or AllocHuge.
- Returns 0 if no error.
- */
- int FreeFar(char *ptr)
- {
- #if USE_GLOBAL
- WORD wmem;
- DWORD hmem;
-
- wmem = HIWORD((LONG)ptr);
- if (wmem == (WORD)0)
- return 0;
- hmem = GlobalHandle(wmem);
- if (hmem == (DWORD)0)
- return 0;
- GlobalUnlock((HANDLE)hmem);
- return GlobalFree((HANDLE)hmem);
- #else
- free(ptr);
- return 0;
- #endif
- }
-
-
- /*
-
- Pop Up Message Box
-
- */
-
- /* Display a message box when a Windows system request fails */
-
- void resource_msg(void)
- {
- MsgBox("AutoCAD ADS",
- "System request failed.\nTry closing an application.");
- }
-
-
- /* Pop up a message box with 2 message strings, the
- first of which will be in the title bar. Waits for
- Enter key, space bar, or click on OK.
- */
- int MsgBox(char *Msg1, char *Msg2)
- {
- return MessageBox(GetActiveWindow(), Msg2, Msg1, MB_ICONHAND | MB_OK);
- }
-
-
- /* Check for break character on key down:
- ctrl-break or ctrl-C. Call from WM_CHAR msg.
- */
- BOOL CheckBreakKey(WPARAM wParam, LPARAM lParam)
- {
- if (wParam == 3)
- return TRUE;
- return FALSE;
- }
-
-
-
-
-
- /*
- Floating Point Conversion for DDE/Clipboard Text format
-
- */
-
- /* Fill an array of doubles from the DDE data returned from
- a range (e.g. of spreadsheet cells). For example,
-
- double RealAry[10][2];
- (or "ads_point PtAry[10];")
-
- StrToReals(pdde->pData, RealAry, 10, 2);
- pRealAry[0][0] has data from the first cell, etc.
- */
-
- short StrToReals(PHDATA DataStrm, double *RealAry,
- int nRow, int nCol)
- {
- double *pReal;
- PHDATA pStr;
- short Sep = 1;
- short cnt = 0;
- char chr;
- short CellCnt;
- short col = 0;
- short idx;
-
- CellCnt = nRow * nCol;
- pStr = DataStrm;
- pReal = RealAry;
- Sep = *DataStrm;
- do {
- chr = *pStr;
- /* separator before cell data. DDE text format is
- null terminated */
- if (Sep == 0)
- break;
- else if (Sep == RecSepChr1) { /* CR */
- if (col < nCol) { /* fill out missing
- fields in this line
- with 0.0's */
- for (idx = col; idx < nCol; ++idx) {
- *pReal++ = 0.0;
- ++cnt;
- if (cnt >= CellCnt)
- break;
- }
- }
- col = 0;
- }
- *pReal = StrToReal(pStr);
- ++pReal;
- ++cnt;
- ++col;
- if (cnt >= CellCnt)
- break;
- }
- while (pStr = GetNextFld(pStr, &Sep));
- return cnt;
- }
-
-
-
-
-
-
- /* From an array of doubles, build cell data nRow by nCol.
- Returns pointer to data string. Use FreeFar to free it.
- DataSize doesn't include the NULL, so add 1 to it, for strings.
- */
- PHDATA RealsToStr(double *RealAry, int nRow, int nCol,
- ULONG *DataSize)
- {
- double *pReal;
- PHDATA pStr;
- PHDATA pDataStrm;
- short FirstRow = TRUE;
- char RealStr[FPSTR+1];
- ULONG DataLen;
- int Row, Col;
- int RealSize;
-
- RealSize = sizeof (double);
-
- /* allow for CRLF or TAB separator, NULL at end */
- DataLen = nRow * nCol * (FPSTR + 1) + 4;
- pDataStrm = pStr = AllocHuge(DataLen, FALSE);
- if (!pStr)
- return NULL;
- pReal = RealAry;
- for (Row = 0; Row < nRow; ++Row) {
- for (Col = 0; Col < nCol; ++Col) {
- RealToStr(*pReal++, RealStr);
- strcpy(pStr, RealStr);
- pStr += strlen(RealStr);
- if (Col != (nCol-1))
- strcpy(pStr++, FldSepStr);
- }
- strcpy(pStr, RecSepStr);
- pStr += 2;
- }
- *pStr = 0;
-
- *DataSize = pStr - pDataStrm; /* get actual length */
- return pDataStrm;
- }
-
-
- /* From a point in a text stream (number<TAB>number...),
- get the next floating point value. See StrToReals, also.
- */
- double StrToReal(char *stream)
- {
- double RealVal;
- char strbuff[61];
- short idx, idxb;
- char chr;
-
- if (stream[0] < SP)
- return 0.0;
-
- idxb = 0;
-
- for (idx = 0; idx < 60; ++idx) {
- if ((chr = stream[idx]) >= SP) {
- if ( chr != *win_tseparator ) /* ignore comma used as 1000's */
- strbuff[idxb++] = chr; /* separator in spreadsheet values. */
- }
- else
- break;
- }
- strbuff[idxb] = EOS;
-
- /*
- Convert string to C library format so sscanf()
- can read it correctly.
- */
- ClibDecimalChars( strbuff );
- sscanf( strbuff, RealScan, &RealVal);
-
- return RealVal;
- }
-
-
- /* Convert double fvalue to a string in your buffer,
- strbuff, with decimal precision FpPrecision.
- */
- void RealToStr(double fvalue, char *strbuff)
- {
- char *temp_char = NULL;
- char *dec_char = NULL;
- sprintf(strbuff, RealFmt, fvalue);
- /*
- Convert the string to be Windows compatible.
- This ensures other Windows app can read the
- format correctly.
- */
- WinDecimalChars( strbuff );
- }
-
- /* get a pointer to the beginning of the next field
- in a cell data list, such as -1<TAB>60000012<TAB>3.4<CR><LF>
- 0<TAB>ARC<CR><LF>
- Returns separator, TAB, CR, or NULL
- */
- char *GetNextFld(PHDATA pData, short *separator)
- {
- char *ptr;
- char chr;
-
- ptr = pData;
- while (chr = *ptr) {
- if (chr < SP) /* End of word. SP is part
- of the word, here. */
- break;
- ++ptr;
- }
-
- *separator = chr; /* TAB, CRLF, or NULL */
- if (chr != EOS) {
- if (chr == CR && (*(ptr+1) == RecSepChr2))
- ptr += 2;
- else
- ++ptr;
- }
- return ptr;
- }
-
-
- /* STORE_STRING -- Store a string at a pointer that already points
- to a malloc'ed string or is NULL. Check if
- new string is larger--free and malloc if so.
- Copy the new string. The new pointer (or the
- old pointer) is returned in "poldstr". E.g.
- (where value is a (char *)),
- store_string(&tile->value, value);
- NOTE: make sure tile->value is initialized to NULL. */
-
- int
- /*FCN*/store_string(char **poldstr, char *newstr)
- {
- int newlen, oldlen;
- char *oldstr, *pstore;
-
- if (newstr == NULL)
- return FALSE;
- oldstr = *poldstr;
- newlen = strlen(newstr) + 1;
- if (oldstr != NULL) {
- /* Replacing previous string. See if new one is larger. */
- oldlen = strlen(oldstr) + 1;
- if (oldlen < newlen) {
- free(oldstr);
- oldstr = NULL;
- }
- }
- if (oldstr == NULL)
- pstore = malloc(newlen);
- else
- pstore = oldstr;
- *poldstr = pstore;
- if (pstore != NULL) {
- strcpy(pstore, newstr);
- return TRUE;
- }
- return FALSE;
- }
-
- /* separate the path and name from a full path\file name. Enter with
- fullname--fills in path and fname. Path has no trailing '\' unless
- it is just "\", the root path.
- */
- void getpath(char *fullname, char *path, char *fname)
- {
- int idx, maxidx, namestart;
- char *tmpptr;
- char chr;
-
- maxidx = strlen(fullname)-1;
- namestart = -1;
- for (idx = maxidx; idx >= 0; --idx) {
- chr = fullname[idx];
- if (chr == '\\' || chr == ':') {
- namestart = idx+1;
- break;
- }
- }
- if (namestart == -1) {
- strcpy(fname, fullname);
- path[0] = 0;
- }
- else {
- tmpptr = fullname;
- tmpptr += namestart;
- strcpy(fname, tmpptr);
- strzcpy(path, fullname, namestart);
- }
- /* "\" */
- if (special_path(path))
- return;
- delslash(path);
- }
-
- /* Remove file separator from end of name, if it exists. If the path
- is "\", it does nothing. */
- void
- delslash(char *filename)
- {
- char *plastchr;
-
- if (special_path(filename))
- return;
- plastchr = &filename[strlen(filename) - 1];
- if (*plastchr == '\\')
- *plastchr = EOS;
- }
-
-
-
- /* Is this a special path: "" "\"?" "f:" "f:\"? */
-
- int
- special_path(char *path)
- {
- /* "" or "\"? */
- if ((*path == EOS) || (*path == '\\' && *(path + 1) == EOS))
- return TRUE;
-
- /* "f:" or "f:\"? */
- ++path;
- if (*path == ':') {
- ++path;
- if ((*path == EOS) || (*path == '\\' && *(path + 1) == EOS))
- return TRUE;
- }
- return FALSE;
- }
-
-
- /* Delete dellen chars from the beginning of a string.
- Returns new string length. */
-
- int
- str_delete(char *str, int dellen)
- {
- int movlen;
-
- /* Include EOS in move */
- movlen = strlen(str) + 1 - dellen;
- if (movlen <= 0) {
- *str = EOS;
- return 0;
- }
- /* Overlapping memory OK for Microsoft C memmove. */
- memmove(str, str + dellen, movlen);
- return movlen - 1;
- }
-
- /*
- Change the decimal presentations from Windows to C library
- */
- void ClibDecimalChars( char *strbuf )
- {
- char *dec_char, *tdec_char;
-
- if ( !separator_inited )
- {
- if ( InitDecimalChars() != TRUE )
- {
- return;
- }
- }
-
- /*
- Check to see if the decimal points are different
- from the win_decseparator which is what Windows uses.
- if they are different, mark where it is and
- replace it with clib_decseparator later, after replacing
- thousand decimal chars.
- */
- if ( strcmp( clib_decseparator, win_decseparator ) == 0 )
- {
- dec_char = NULL;
- }
- else
- {
- dec_char = strstr( strbuf, win_decseparator );
- }
-
- /*
- Check to see if thousand decimal is different from
- the one from clib. Replace it if it is.
- */
- if ( strcmp( win_tseparator, clib_tseparator ) != 0 )
- {
- while ( ( tdec_char = strstr( strbuf, win_tseparator ) ) )
- {
- /*
- This may not work if the thousand decimal separator is
- 2 or more chars for example the kanji character set.
- */
- *tdec_char = *clib_tseparator;
- strbuf = tdec_char;
- }
- }
-
- /*
- Replace the decimal the last.
- */
- if ( dec_char )
- {
- /*
- This may not work if the decimal separator is
- 2 or more chars for example the kanji char set.
- */
- *dec_char = *clib_decseparator;
- }
- }
-
- /*
- Change the decimal presentation from clib to Windows
- */
- void WinDecimalChars( char *strbuf )
- {
- char *dec_char, *tdec_char;
-
- if ( !separator_inited )
- {
- if ( InitDecimalChars() != TRUE )
- {
- return;
- }
- }
-
- /*
- Check to see if the decimal points are different
- from the clib_decseparator which sprintf() uses.
- if they are different, mark where it is and
- replace it after replacing the thousand decimal chars.
- */
- if ( strcmp( win_decseparator, clib_decseparator ) == 0 )
- {
- dec_char = NULL;
- }
- else
- {
- dec_char = strstr( strbuf, clib_decseparator );
- }
-
- /*
- Check to see if the thousand decimal is different from
- the one from clib. Replace it if it is.
- */
- if ( strcmp( win_tseparator, clib_tseparator ) != 0 )
- {
- while ( ( tdec_char = strstr( strbuf, clib_tseparator ) ) )
- {
- /*
- This may not work if the thousand decimal separator is
- 2 or more chars for example the kanji character set.
- */
- *tdec_char = *win_tseparator;
- strbuf = tdec_char;
- }
- }
-
- /*
- Replace the decimal the last.
- */
- if ( dec_char )
- {
- /*
- This may not work if the thousand decimal separator is
- 2 or more chars; for example the kanji character set.
- */
- *dec_char = *win_decseparator;
- }
- }
-
- /*
- This routine query Windows for what it uses to represent
- decimal and thousand decimal.
- */
- BOOL InitDecimalChars()
- {
- HKEY hkey;
- DWORD valuetype;
- unsigned long len;
- char temp_buf[ 256 ];
- BOOL IsWin32s;
-
- IsWin32s = GetVersion() & 0x80000000;
-
- if ( IsWin32s )
- {
- len = GetProfileString( "intl"
- , "sThousand"
- , ","
- , win_tseparator
- , sizeof( win_tseparator ) );
- if ( GetProfileString( "intl"
- , "sDecimal"
- , "."
- , win_decseparator
- , sizeof( win_decseparator ) ) == 0
- || len == 0 )
- {
- separator_inited = FALSE;
- }
- separator_inited = TRUE;
- }
- else /* NT! */
- {
-
- if ( RegOpenKey( HKEY_CURRENT_USER
- , "Control Panel\\International"
- , &hkey ) == ERROR_SUCCESS )
-
- {
- ASSERT( hkey != 0 );
- len = sizeof( temp_buf ) - 1;
- RegQueryValueEx( hkey
- , "sDecimal"
- , NULL
- , &valuetype
- , temp_buf
- , &len );
- ASSERT( temp_buf[ 0 ] != 0 );
- temp_buf[ len ] = 0;
- strncpy( win_decseparator, temp_buf, sizeof( win_decseparator ) - 1 );
-
- len = sizeof( temp_buf ) - 1;
- RegQueryValueEx( hkey
- , "sThousand"
- , NULL
- , &valuetype
- , temp_buf
- , &len );
- ASSERT( temp_buf[ 0 ] != 0 );
- temp_buf[ len ] = 0;
- strncpy( win_tseparator, temp_buf, sizeof( win_tseparator ) - 1 );
-
- RegCloseKey( hkey );
- separator_inited = TRUE;
- }
- else
- {
- ASSERT( 0 );
- }
-
- }
- /*
- Check the length of Windows separators length to be 1 char
- only since we don't support multiple chars in the code.
- */
- ASSERT( win_decseparator[ 1 ] == EOS && win_tseparator[ 1 ] == EOS );
- return separator_inited;
- }
-