|
|
/************************************************************/ /* Windows Write, Copyright 1985-1992 Microsoft Corporation */ /************************************************************/
/* util.c -- more frequently used utility routines */ #define NOCOLOR
#define NOCOMM
#define NOCLIPBOARD
#define NOCTLMGR
#define NOGDICAPMASKS
#define NOMENUS
#define NOSOUND
#define NOVIRTUALKEYCODES
#define NOWINMESSAGES
#define NOWINSTYLES
#include <windows.h>
#if WINVER < 0x300
#define SM_CURSORLEVEL 25
#endif
#include "mw.h"
#include "doslib.h"
#include "str.h"
#include "machdefs.h"
#include "cmddefs.h"
#include "propdefs.h"
#include "fkpdefs.h"
#include "docdefs.h"
#include "debug.h"
#include "editdefs.h"
#include "wwdefs.h"
#define NOKCCODES
#include "ch.h"
extern struct DOD (**hpdocdod)[]; extern HANDLE hMmwModInstance;
CHAR *PchFillPchId(PCH, int);
typeCP CpMax(cp1, cp2) typeCP cp1, cp2; {{ /* return larger of two cps */ return((cp1 > cp2) ? cp1 : cp2); }} /* end of C p M a x */
typeCP CpMin(cp1, cp2) typeCP cp1, cp2; {{ /* return smaller of two cps */ return((cp1 < cp2) ? cp1 : cp2); }} /* end of C p M i n */
unsigned umin( w1, w2 ) register unsigned w1, w2; { return (w1 < w2) ? w1 : w2; }
unsigned umax( w1, w2 ) register unsigned w1, w2; { return (w1 > w2) ? w1 : w2; }
int imin( i1, i2 ) register int i1, i2; { return (i1 < i2) ? i1 : i2; }
int imax( i1, i2 ) register int i1, i2; { return (i1 > i2) ? i1 : i2; }
#define BZNATIVE
#ifndef BZNATIVE
/* C C H D I F F E R */ /* commented out, moved to native code in lib.asm bz 6/20/85 */ int CchDiffer(rgch1, rgch2, cch) register CHAR *rgch1, *rgch2; int cch; {{ /* Return cch of shortest prefix leaving a common remainder */ int ich;
for (ich = cch - 1; ich >= 0; ich--) if (rgch1[ich] != rgch2[ich]) break; return ich + 1; }} #endif
int CchSz(sz) register CHAR sz[]; { /* Returns length of string in bytes, including trailing 0 */ register int cch = 1; while (*sz++ != 0) cch++; return cch; } /* end of C c h S z */
typeCP CpMacText(doc) register int doc; { #ifdef FOOTNOTES
struct FNTB **hfntb; if ((hfntb = HfntbGet(doc)) != 0) return((**hfntb).rgfnd[0].cpFtn - ccpEol); else #endif /* FOOTNOTES */
return((**hpdocdod)[doc].cpMac);
} /* end of C p M a c T e x t */
struct FNTB **HfntbGet(doc) register int doc; { /* Return hfntb if doc has one, 0 if none or style sheet */ #ifdef STYLES
register struct DOD *pdod;
if ((pdod = &(**hpdocdod)[doc])->dty == dtySsht) return 0; else #endif
return (**hpdocdod)[doc].hfntb; } /* end of H F n t b G e t */
/* N O U N D O */ NoUndo() { extern struct UAB vuab; vuab.uac = uacNil; SetUndoMenuStr(IDSTRUndoBase); } /* end of N o U n d o */
SetUndoMenuStr(idstr) int idstr; { extern int idstrCurrentUndo;
idstrCurrentUndo = idstr; }
/* Returns number chars copied EXCLUDING zero terminator */
int CchCopySz(pchFrom, pchTo) register PCH pchFrom; register PCH pchTo; { int cch = 0; while ((*pchTo = *pchFrom++) != 0) { pchTo++; cch++; } return cch; } /* end of C c h C o p y S z */
/*---------------------------------------------------------------------------
-- Routine: WCompSz(psz1,psz2) -- Description and Usage: Alphabetically compares the two null-terminated strings lpsz1 and lpsz2. Upper case alpha characters are mapped to lower case. Comparison of non-alpha characters is by ascii code. Returns 0 if they are equal, a negative number if lpsz1 precedes lpsz2, and a non-zero positive number if lpsz2 precedes lpsz1. -- Arguments: psz1, psz2 - pointers to two null-terminated strings to compare -- Returns: a short - 0 if strings are equal, negative number if lpsz1 precedes lpsz2, and non-zero positive number if psz2 precedes psz1. -- Side-effects: none -- Bugs: -- History: 3/14/83 - created (tsr) 6/12/86 - Kanji Version (yxy) ----------------------------------------------------------------------------*/ short
WCompSz(psz1,psz2) register PCH psz1; register PCH psz2; { int ch1; int ch2;
for(ch1=ChLower(*psz1++),ch2=ChLower(*psz2++); ch1==ch2; ch1=ChLower(*psz1++),ch2=ChLower(*psz2++)) { if(ch1 == '\0') return(0); } return(ch1-ch2); } /* end of W C o m p S z */
/*---------------------------------------------------------------------------
-- Routine: ChLower(ch) -- Description and Usage: Converts its argument to lower case iff its argument is upper case. Returns the de-capitalized character or the initial char if it wasn't caps. -- Arguments: ch - character to be de-capitalized -- Returns: a character - initial character, de-capitalized if needed. -- Side-effects: -- Bugs: -- History: 3/14/83 - created (tsr) ----------------------------------------------------------------------------*/ int ChLower(ch) register CHAR ch; { /* use Windows' ANSI char set, the difference of upper/lower case
is also 20 (HEX) for foreign chars */ #ifdef JAPAN
// check for half-size katakana.
extern struct WWD rgwwd[]; extern BOOL IsKanaInDBCS(int); static TEXTMETRIC tm;
/**/ BOOL ret1; BOOL ret2; #if 0 //T-HIROYN
ret1 = IsWindow(wwdCurrentDoc.wwptr); ret2 = GetTextMetrics(wwdCurrentDoc.hDC,(LPTEXTMETRIC)&tm); if(ret1 && ret2) { if(tm.tmCharSet == SHIFTJIS_CHARSET && IsKanaInDBCS((int)ch)) return (int)(0x00ff&ch); } #else
ret1 = IsWindow(wwdCurrentDoc.wwptr); if (ret1) { ret2 = GetTextMetrics(wwdCurrentDoc.hDC,(LPTEXTMETRIC)&tm); if(ret2) { if(tm.tmCharSet == SHIFTJIS_CHARSET && IsKanaInDBCS((int)ch)) return (int)(0x00ff&ch); } } #endif
#if 0
if(IsWindow(wwdCurrentDoc.wwptr) && GetTextMetrics(wwdCurrentDoc.hDC,(LPTEXTMETRIC)&tm)){ if(tm.tmCharSet == SHIFTJIS_CHARSET && IsKanaInDBCS((int)ch)) return (int)(0x00ff&ch); } #endif
#endif
#ifdef KOREA
if(isupper(ch) && !((ch > 0xa1) && (ch < 0xfe))) #else
if(isupper(ch)) #endif
return(ch + ('a' - 'A')); /* foreign is taken care of */ else return ch; } /* end of C h L o w e r */
static int cLongOpCount = 0; /* to ensure we don't do too much hide cursor */
StartLongOp() { extern int vfInLongOperation; extern int vfCursorVisible; extern int vfMouseExist; extern HCURSOR vhcHourGlass;
int cursorlevel;
if (cLongOpCount++ == 0) { vfInLongOperation = TRUE; vfCursorVisible = TRUE;
if (!vfMouseExist) { /* in a mouseless system, set the cursor to middle of window */ extern HWND vhWndMsgBoxParent; extern HWND hParentWw; extern int vfInitializing; RECT rect; POINT pt; HWND hWnd = vhWndMsgBoxParent;
if (vhWndMsgBoxParent == NULL) hWnd = hParentWw; /* next choice */ if (!vfInitializing && hWnd != NULL && IsWindow(hWnd)) { /* we have a good window to put in */ GetClientRect(hWnd, (LPRECT)&rect); pt.x = (rect.right - rect.left) / 2; pt.y = (rect.bottom - rect.top) / 2; ClientToScreen(hWnd, (LPPOINT)&pt); } else { /* put in the middle of screen */ HDC hDCScreen = GetDC(NULL); if (hDCScreen == NULL) goto Out; /* the worst, setcursor only */ pt.x = GetDeviceCaps(hDCScreen, HORZRES) / 2; pt.y = GetDeviceCaps(hDCScreen, VERTRES) / 2; ReleaseDC(NULL, hDCScreen); } SetCursorPos(pt.x, pt.y); } Out: SetCursor(vhcHourGlass); #if WINVER < 0x300
ShowCursor(TRUE);
/* precaution - make sure the cusor is visible */ cursorlevel = GetSystemMetrics(SM_CURSORLEVEL); #else
/* use a supported method to get cursor level! ..pault 2/6/90 */ cursorlevel = ShowCursor(TRUE); #endif
while (cursorlevel++ < 0) ShowCursor(TRUE); } }
EndLongOp(hc) HCURSOR hc; /* cursor to be changed to */ { extern int vfInLongOperation; extern int vfCursorVisible; extern int vfMouseExist; extern int vfDeactByOtherApp;
int cursorlevel;
#ifdef JAPAN // added by Hiraisi (BUG#3628/WIN31)
{ RECT rc; POINT pt; extern int xpSelBar, dxpScrlBar, dypScrlBar; extern HWND hParentWw; extern HCURSOR vhcArrow, vhcBarCur;
GetClientRect(hParentWw, (LPRECT)&rc); rc.right -= dxpScrlBar; rc.bottom -= dypScrlBar; GetCursorPos((LPPOINT)&pt); ScreenToClient(hParentWw,(LPPOINT)&pt); if( !PtInRect((LPRECT)&rc, pt) ) // out of edit area
hc = vhcArrow; else if( pt.x <= xpSelBar ) // within selection bar
hc = vhcBarCur; } #endif
if (cLongOpCount > 0) { if (vfDeactByOtherApp && (cLongOpCount == 1)) // OLE presents this case
{ vfInLongOperation = FALSE; vfCursorVisible = FALSE; SetCursor(vfMouseExist ? hc : NULL); } else if (--cLongOpCount == 0) { vfInLongOperation = FALSE; vfCursorVisible = FALSE; #if WINVER < 0x300
ShowCursor(FALSE); SetCursor(vfMouseExist ? hc : NULL);
/* make sure the cursor is still visible in a mouse system
and invisible in a mouseless system */ cursorlevel = GetSystemMetrics(SM_CURSORLEVEL); #else
/* use a supported method to get cursor level! ..pault 2/6/90 */ cursorlevel = ShowCursor(FALSE); SetCursor(vfMouseExist ? hc : NULL); #endif
if (vfMouseExist) { while (cursorlevel++ < 0) ShowCursor(TRUE); } else /* no mouse */ { while (cursorlevel-- >= 0) ShowCursor(FALSE); } } } }
/* String utility functions - moved here from string.c */
/* I N D E X */ /* ** Returns pointer to first occurrence of character ch found in null-
terminated string pch, or 0 if ch does not appear. If ch==0, we return a pointer to the null terminator. */ /* In Kanji version, a kanji character is excluded from the search. */
CHAR *index(pch, ch) REG1 CHAR *pch; REG2 CHAR ch; // fixed bug, previously int (2.11.91) D. Kent
{ while (low(*pch)!=ch) { #ifdef DBCS /* KenjiK '90-11-20 */
if (*pch=='\0') #else
if (*pch++=='\0') #endif
return(NULL); #ifdef DBCS /* KenjiK '90-11-20 */
pch = AnsiNext(pch); #endif
} return(pch); }
/* We may want to make these 'type' functions into macros */ /* These are designed for ANSI character set (used by windows) only */
/* I S A L P H A */ /* ** TRUE if ch is a letter, FALSE otherwise */
isalpha(ch) REG1 CHAR ch; {/* Note: even though DF and FF are lowercase, they have no
corresponding uppercase, so they are excluded from the lowercase class, and simply mapped to themselves */ return(islower(ch) || isupper(ch) || ch == 0x00FF || ch == 0x00DF); }
/* ** TRUE if ch is a lowercase letter, FALSE otherwise */
/* I S L O W E R */ islower(ch) REG1 CHAR ch; {/* Note: even though DF and FF are lowercase, they have no
corresponding uppercase, so they are excluded from the lowercase class, and simply mapped to themselves */ return((ch >= 'a' && ch <= 'z') || /* foreign */ (ch >= 0x00E0 && ch <= 0x00F6) || (ch >= 0x00F8 && ch <= 0x00FE) ); }
/* ** TRUE if ch is an uppercase letter, FALSE otherwise */
isupper(ch) REG1 CHAR ch; { return((ch >= 'A' && ch <= 'Z') || /* foreign */ (ch >= 0x00C0 && ch <= 0x00D6) || (ch >= 0x00D8 && ch <= 0x00DE)); }
/* ** TRUE if ch is a digit, FALSE otherwise */
isdigit(ch) REG1 CHAR ch; { return(ch>='0' && ch<='9'); }
#ifdef ENABLE
/* ** TRUE if ch is a character or a digit, FALSE otherwise */
isalnum(ch) REG1 CHAR ch; { return(isalpha(ch) || isdigit(ch)); } #endif
int ChUpper(ch) REG1 CHAR ch; { #ifdef DBCS
return AnsiUpper( ch ); #else
#ifdef BOGUS
return (ch >= 'a' && ch <= 'z') ? ch + ('A' - 'a') : ch; #endif
/* use Windows' ANSI char set, the difference of upper/lower case
is also 20 (HEX) for foreign chars */
if (islower(ch)) return(ch + ('A' - 'a')); /* foreign is taken care of */ else return(ch); #endif
}
/* similar to blcomp except compares by bytes and is not case sensitive */ BOOL FRgchSame(rgch1, rgch2, cch) CHAR rgch1[], rgch2[]; int cch; { short ich;
for(ich = 0; ich < cch; ich++) { if(ChLower(rgch1[ich]) != ChLower(rgch2[ich])) return(FALSE); } return(TRUE); }
/* PchStartBaseNameSz() ---- returns a character pointer to the
beginning of a base file name. If the name only consists of a base name, sz is returned.
Note: If sz ends with a back-slash or a colon, pch returned is pointing to the null terminator of the given string. */
CHAR *PchStartBaseNameSz(sz) CHAR *sz; { CHAR *pchBS, *pchC, *pchLast; CHAR *PchLastSzCh();
pchBS = PchLastSzCh(sz, '\\'); pchC = PchLastSzCh(sz, ':'); pchLast = (pchBS > pchC) ? pchBS : pchC; if (pchLast == NULL) { pchLast = sz; } else { pchLast++; } return (pchLast); }
/* PchLastSzCh() ----- returns a pointer to the last occurrence of a given
character in a given string. If it does not occur in the string, it returns NULL. If the given character is '\0', it returns sz itself. Note: All kanji characters are excluded from the search. */
CHAR *PchLastSzCh(sz, ch) CHAR *sz; CHAR ch; { if (ch == '\0') { return (sz); } else { CHAR *pchCur, *pchLast;
#ifdef DBCS
for (pchLast = pchCur = sz; *pchCur != '\0'; pchCur = AnsiNext(pchCur)) #else
for (pchLast = pchCur = sz; *pchCur != '\0'; pchCur++) #endif
{ { if (low(*pchCur) == ch) { pchLast = pchCur; } } } return ((pchLast == sz) ? NULL : pchLast); } }
#ifdef DEBUG
_Assert(pch, line, f) PCH pch; int line; BOOL f; { if (!f) Do_Assert(pch, line, f); } #endif
#ifdef JAPAN /*t-Yoshio*/
myHantoZen(char *han_str,char *zen_str,int buffsize) { extern CHAR Zenstr1[256]; extern CHAR Zenstr2[256]; CHAR far *ZenTbl; int length = 0; int sub;
while((CHAR)*han_str) { if(length+3 > buffsize) break;
if((CHAR)*han_str >= 0x20 && (CHAR)*han_str < 0x7f) { ZenTbl = Zenstr1; sub = ((CHAR)*han_str-0x20)*2; han_str++; *zen_str = ZenTbl[sub]; *(zen_str+1) = ZenTbl[sub+1]; zen_str+=2; length+=2; continue; } else if((CHAR)*han_str >= 0xa1 && (CHAR)*han_str <= 0xdd) { ZenTbl = Zenstr2; if((CHAR)*han_str >= 0xca && (CHAR)*han_str <= 0xce) { if((CHAR)*(han_str+1) == 0xde ) { sub = ((CHAR)*han_str-0xa1+35)*2; han_str+=2; } else if((CHAR)*(han_str+1) == 0xdf ) { sub = ((CHAR)*han_str-0xa1+40)*2; han_str+=2; } else { sub = ((CHAR)*han_str-0xa1)*2; han_str++; } } else if((CHAR)*han_str >= 0xa6 && (CHAR)*han_str <= 0xc4) { if((CHAR)*(han_str+1) == 0xde ) { sub = ((CHAR)*han_str-0xa1+40)*2; han_str+=2; } else { sub = ((CHAR)*han_str-0xa1)*2; han_str++; } } else { sub = ((CHAR)*han_str-0xa1)*2; han_str++; }
*zen_str = ZenTbl[sub]; *(zen_str+1) = ZenTbl[sub+1]; zen_str+=2; length+=2; continue; } else { if(IsDBCSLeadByte((BYTE)(*han_str))) { *zen_str = *han_str; *(zen_str+1) = (CHAR)*(han_str+1); zen_str+=2; length+=2; han_str+=2; } else { *zen_str = *han_str; *zen_str++;length++;han_str++; } continue; } } *zen_str = '\0'; } myIsSonant(BYTE dbcshi,BYTE dbcslow) { static unsigned short hanzen[] = { 0x834b, 0x834d, 0x834f, 0x8351, 0x8353, 0x8355, 0x8357, 0x8359, 0x835b, 0x835d, 0x835f, 0x8361, 0x8364, 0x8366, 0x8368, 0x836f, 0x8370, 0x8372, 0x8373, 0x8375, 0x8376, 0x8378, 0x8379, 0x837b, 0x837c }; unsigned int dbyte; int i;
dbyte = (((WORD)(dbcshi) << 8) | ((WORD)(dbcslow) & 0x00ff)); for(i = 0;i < 25;i++) { if(dbyte == hanzen[i]) return TRUE; } return FALSE; } #elif defined(KOREA)
myHantoZen(char *han_str,char *zen_str,int buffsize) { extern CHAR Zenstr1[256]; CHAR far *ZenTbl; int length = 0; int sub;
while((CHAR)*han_str) { if(length+3 > buffsize) break;
if((CHAR)*han_str >= 0x20 && (CHAR)*han_str < 0x7f) { ZenTbl = Zenstr1; sub = ((CHAR)*han_str-0x20)*2; han_str++; *zen_str = ZenTbl[sub]; *(zen_str+1) = ZenTbl[sub+1]; zen_str+=2; length+=2; continue; } else { if(IsDBCSLeadByte((BYTE)(*han_str))) { *zen_str = *han_str; *(zen_str+1) = (CHAR)*(han_str+1); zen_str+=2; length+=2; han_str+=2; } else { *zen_str = *han_str; *zen_str++;length++;han_str++; } continue; } } *zen_str = '\0'; } myIsSonant(BYTE dbcshi,BYTE dbcslow) { static unsigned short hanzen[] = { 0x834b, 0x834d, 0x834f, 0x8351, 0x8353, 0x8355, 0x8357, 0x8359, 0x835b, 0x835d, 0x835f, 0x8361, 0x8364, 0x8366, 0x8368, 0x836f, 0x8370, 0x8372, 0x8373, 0x8375, 0x8376, 0x8378, 0x8379, 0x837b, 0x837c }; unsigned int dbyte; int i;
dbyte = (((WORD)(dbcshi) << 8) | ((WORD)(dbcslow) & 0x00ff)); for(i = 0;i < 25;i++) { if(dbyte == hanzen[i]) return TRUE; } return FALSE; } #endif
|