/************************************************************/ /* Windows Write, Copyright 1985-1992 Microsoft Corporation */ /************************************************************/ /* Select2.c -- Less-frequently-used selection routines */ #define NOCLIPBOARD #define NOGDICAPMASKS #define NOCTLMGR #define NOVIRTUALKEYCODES #define NOWINMESSAGES #define NOWINSTYLES #define NOSYSMETRICS #define NOMENUS #define NOSOUND #define NOCOMM #define NOPEN #define NOWNDCLASS #define NOICON #define NORASTEROPS #define NOSHOWWINDOW #define NOATOM #define NOKEYSTATE #define NOSYSCOMMANDS #define NOBITMAP #define NOBRUSH #define NOCOLOR #define NODRAWTEXT #define NOMB #define NOPOINT #define NOMSG #include #include "mw.h" #include "toolbox.h" #include "docdefs.h" #include "editdefs.h" #include "dispdefs.h" #include "cmddefs.h" #include "wwdefs.h" #include "ch.h" #include "fmtdefs.h" #include "propdefs.h" #ifdef DBCS #include "kanji.h" #endif extern int vfSeeSel; extern typeCP vcpFirstParaCache; extern typeCP vcpLimParaCache; extern typeCP vcpFetch; extern CHAR *vpchFetch; extern int vccpFetch; extern typeCP cpMinCur; extern typeCP cpMacCur; extern struct SEL selCur; extern int docCur; extern struct FLI vfli; extern struct WWD rgwwd[]; extern int vfSelHidden; extern int wwCur; extern struct CHP vchpFetch; extern struct PAP vpapAbs; extern struct WWD *pwwdCur; extern int vfInsEnd; extern typeCP CpBeginLine(); extern int vfPictSel; extern int vfSizeMode; extern struct CHP vchpNormal; extern int vfInsertOn; extern struct CHP vchpSel; /* Holds the props when the selection is an insert point */ extern int vfMakeInsEnd; extern typeCP vcpSelect; extern int vfSelAtPara; /* true iff the last selection was made by an Up/Down cursor key */ extern int vfLastCursor; #ifndef DBCS /* US version */ /* C P L I M S T Y S P E C I A L */ typeCP CpLimStySpecial(cp, sty) typeCP cp; int sty; { /* Return the first cp which is not part of the same sty unit */ int wb, ch, ich; struct EDL *pedl; /* Other cases covered in CpLimSty, our only caller */ Assert( cp < cpMacCur ); Assert( cp >= cpMinCur ); Assert( sty == styWord || sty == stySent ); /* Special kludge for picture paragraphs */ CachePara(docCur, cp); if (vpapAbs.fGraphics) return vcpLimParaCache; FetchCp(docCur, cp, 0, fcmChars + fcmNoExpand); Assert(vccpFetch != 0); /* Must be word or sentence */ wb = WbFromCh(ch = vpchFetch[ich = 0]); #ifdef CRLF if (ch == chReturn) return vcpFetch + 2; #endif if (ch == chEol || ch == chSect || ch == chNewLine || ch == chTab) /* EOL is its own unit */ return vcpFetch + 1; if (wb == wbWhite && sty == stySent) { /* Might be between sentences; go back to text */ FetchCp(docCur, CpFirstSty(cp, styWord), 0, fcmChars + fcmNoExpand); wb = WbFromCh(ch = vpchFetch[ich = 0]); } for (;;) { if (++ich >= vccpFetch) { /* Get next line and set up */ FetchCp(docNil, cpNil, 0, fcmChars); if (vcpFetch == cpMacCur) return cpMacCur; /* End of doc */ ich = 0; } if (sty == stySent) switch (ch) { case chDot: case chBang: case chQMark: sty = styWord; wb = wbPunct; } switch (ch = vpchFetch[ich]) { case chTab: case chEol: case chSect: case chNewLine: #ifdef CRLF case chReturn: #endif goto BreakFor; } if (sty == styWord) { /* Word ends after white space or on text/punct break */ int wbT = WbFromCh(ch); if (wb != wbT && (wb = wbT) != wbWhite) break; } } BreakFor: return vcpFetch + ich; } /* C P F I R S T S T Y S P E C I A L */ typeCP CpFirstStySpecial(cp, sty) typeCP cp; int sty; { /* Return the first cp of this sty unit. */ typeCP cpBegin; int wb, ch, dcpChunk; typeCP cpSent; CHAR rgch[dcpAvgSent]; int ich; typeCP cpT; /* Other cases were covered by CpFirstSty, our only caller */ Assert( cp > cpMinCur ); Assert( sty == stySent || sty == styWord ); if (cp >= cpMacCur) cpT = cp = cpMacCur; else cpT = cp++; CachePara(docCur, cpT ); if ((vcpFirstParaCache == cpT) || vpapAbs.fGraphics) return vcpFirstParaCache; dcpChunk = (sty == styWord) ? dcpAvgWord : dcpAvgSent; cpBegin = (cp > dcpChunk) ? cp - dcpChunk : cp0; FetchRgch(&ich, rgch, docCur, cpBegin, cp, dcpChunk); wb = WbFromCh(ch = rgch[--ich]); #ifdef CRLF if(cpBegin + ich == 0) return cp0; if (ch == chEol && rgch[ich-1] == chReturn) /* EOL is its own unit */ return cpBegin + ich - 1; if (ch == chEol || ch == chReturn || ch == chSect || ch == chNewLine || ch == chTab) return cpBegin + ich; #else /* not CRLF */ if (ch == chEol || ch == chSect || ch == chNewLine || ch == chTab) /* EOL is its own unit */ return cpBegin + ich; #endif /* CRLF */ if (wb == wbText) cpSent = cpBegin + ich; else cpSent = cpNil; for (;;) { if (ich == 0) { if (cpBegin == cpMinCur) return cpMinCur; /* beginning of doc */ cpBegin = (cpBegin > dcpChunk) ? cpBegin - dcpChunk : cp0; FetchRgch(&ich, rgch, docCur, cpBegin, cp, dcpChunk); } ch = rgch[--ich]; CachePara( docCur, cpBegin + ich ); /* Needed for pictures */ if (ch == chEol || ch == chSect || ch == chNewLine || ch == chTab || vpapAbs.fGraphics ) break; /* EOL Always ends a unit */ if (sty == styWord) { if (wb != wbWhite) { if (WbFromCh(ch) != wb) break; } else wb = WbFromCh(ch); } else { /* Test for sentence. */ switch (ch) { case chDot: case chBang: case chQMark: if (cpSent != cpNil) return cpSent; } switch (WbFromCh(ch)) { case wbText: cpSent = cpBegin + ich; wb = wbText; break; case wbPunct: switch (wb) { case wbWhite: wb = wbPunct; break; case wbText: cpSent = cpBegin + ich; } break; case wbWhite: if (wb == wbPunct) cpSent = cpBegin + ich + 1; wb = wbWhite; break; } } } return cpBegin + ich + 1; } #else /* DBCS version */ typeCP CpLimStySpecial(cp, sty) typeCP cp; int sty; { CHAR rgch[cchKanji]; int ch, ch2; int ich, wb; typeCP cpLim, cpT; /* Other cases covered in CpLimSty, our only caller */ Assert(cp < cpMacCur); Assert(cp >= cpMinCur); Assert(sty == styWord || sty == stySent); /* Picture paragraph? */ CachePara(docCur, cp); if (vpapAbs.fGraphics) { return vcpLimParaCache; } cpLim = vcpLimParaCache; if (vcpLimParaCache > cpMacCur) { /* No EOL at end of doc */ cpLim = cpMacCur; } FetchRgch(&ich, rgch, docCur, cp, ((cpT = cp + cchKanji) < cpLim) ? cpT : cpLim, cchKanji); ch = rgch[0]; #ifdef CRLF if (ch == chReturn) { return (cp + 2); } #endif /* CRLF */ if (ch == chEol || ch == chSect || ch == chNewLine || ch == chTab) { /* EOL is its own unit. */ return (cp + 1); } #ifdef KOREA wb=WbFromCh(ch); #else if (FKanji1(ch)) { wb = WbFromKanjiChCh(ch, (int) rgch[1]); if (sty == styWord && wb == wbKanjiText) { return (CpLimSty(cp, styChar)); } else { if (wb == wbKanjiText) { wb = wbKanjiTextFirst; } } } else { if (sty == styWord && FKanaText(ch)) { return (CpLimSty(cp, styChar)); } wb = WbFromCh(ch); } #endif for (; cp < cpLim;) { int wbT; if (sty == stySent) { if (FKanji1(ch)) { CHAR ch2; ch2 = rgch[1]; if (FKanjiKuten(ch, ch2) || FKanjiQMark(ch, ch2) || FKanjiBang(ch, ch2) || FKanjiPeriod(ch, ch2)) { sty = styWord; wb = wbPunct; goto lblNextFetch; } } else { switch (ch) { #ifndef KOREA case bKanjiKuten: #endif case chDot: case chBang: case chQMark: sty = styWord; wb = wbPunct; goto lblNextFetch; } } } switch (ch) { case chTab: case chEol: case chSect: case chNewLine: #ifdef CRLF case chReturn: #endif /* CRLF */ return cp; } if (sty == styWord) { #ifdef KOREA wbT = WbFromCh(ch); #else if (FKanji1(ch)) { wbT = WbFromKanjiChCh(ch, (int) rgch[1]); } else { wbT = WbFromCh(ch); } #endif if (wb != wbT && (wb = wbT) != wbWhite) { return (cp); } } lblNextFetch: cp = CpLimSty(cp, styChar); if (cp < cpLim) { /* Save some time and an untimely demise.... */ FetchRgch(&ich, rgch, docCur, cp, ((cpT = cp + cchKanji) < cpLim) ? cpT : cpLim, cchKanji); ch = rgch[0]; } } return (cpLim); } typeCP CpFirstStySpecial(cp, sty) typeCP cp; int sty; { /* Return the first cp of this sty unit. */ typeCP cpT, cpLim, cpFirstPara, cpFirstLastSent; /* cpFirst of the last possible sentence boundary */ CHAR rgch[cchKanji]; int ch; int wb; int ich; /* Other cases were covered by CpFirstSty, our only caller */ Assert( cp > cpMinCur ); Assert(CpFirstSty(cp, styChar) == cp); /* cp is on a char boundary */ Assert( sty == stySent || sty == styWord ); cpT = cp; if (cp >= cpMacCur) { cpT = cp = cpMacCur; } CachePara(docCur, cpT ); cpFirstPara = vcpFirstParaCache; if ((vcpFirstParaCache == cpT) || vpapAbs.fGraphics) { return vcpFirstParaCache; } #ifdef CRLF /* CR-LF is assumed. */ Assert(TRUE); #else Assert(FALSE); #endif /* CRLF */ FetchRgch(&ich, rgch, docCur, cp, ((cpT = cp + cchKanji) < cpMacCur) ? cpT : cpMacCur, cchKanji); ch = rgch[0]; if (ich == cchKanji && ch == chReturn && rgch[1] == chEol) { /* EOL is its own unit */ return cp; } if (ch == chEol || ch == chReturn || ch == chSect || ch == chNewLine || ch == chTab) { return cp; } cpFirstLastSent = cpNil; #ifdef KOREA wb = WbFromCh(ch); #else if (FKanji1(ch)) { wb = WbFromKanjiChCh(ch, (int) rgch[1]); if (sty == styWord && wb == wbKanjiText) { return (CpFirstSty(cp, styChar)); } else { if (wb == wbKanjiText) { wb = wbKanjiTextFirst; } } } else { if (sty == styWord && FKanaText(ch)) { return (CpFirstSty(cp, styChar)); } wb = WbFromCh(ch); } #endif for (; cpFirstPara < cp; ) { typeCP cpTemp; int wbT; cpTemp = CpFirstSty(cp - 1, styChar); FetchRgch(&ich, rgch, docCur, cpTemp, ((cpT = cpTemp + cchKanji) < cpMacCur) ? cpT : cpMacCur, cchKanji); ch = rgch[0]; #ifdef KOREA wbT = WbFromCh(ch); #else if (FKanji1(ch)) { wbT = WbFromKanjiChCh(ch, (int) rgch[1]); } else { wbT = WbFromCh(ch); } #endif if (wb == wbWhite) { #ifdef KOREA wb=wbT; #else wb = (wbT == wbKanjiText) ? wbKanjiTextFirst : wbT; #endif } else if (wb != wbT) { if (sty == styWord) { return (cp); } else /* sty == stySent */ { /* wb != wbWhite */ /* wb != wbT */ if (wbT == wbWhite || wbT == wbPunct) { cpFirstLastSent = cp; wb = wbWhite; } } } if (sty == stySent) { /* for the sentence */ if (FKanji1(ch)) { int ch2; ch2 = rgch[1]; if (FKanjiKuten(ch, ch2) || FKanjiQMark(ch, ch2) || FKanjiBang(ch, ch2) || FKanjiPeriod(ch, ch2)) { if (cpFirstLastSent != cpNil) { return (cpFirstLastSent); } else { cpFirstLastSent = cp; } } } else { switch(ch) { #ifndef KOREA case bKanjiKuten: #endif case chDot: case chBang: case chQMark: if (cpFirstLastSent != cpNil) { return (cpFirstLastSent); } else { cpFirstLastSent = cp; } } } } cp = cpTemp; } return (cpFirstPara); } #endif /* DBCS */ /* W B F R O M C H */ int WbFromCh(ch) int ch; { /* Return word-breakness of ch */ #if defined(DBCS) & !defined(KOREA) /* was in JAPAN; KenjiK '90-10-29 */ /* Brought from WIN2 source. */ if (FKanaPunct(ch)) { return wbPunct; } else if (FKanaText(ch)) { return wbKanjiText; } #endif switch (ch) { case chSpace: case chEol: #ifdef CRLF case chReturn: #endif case chSect: case chTab: case chNewLine: case chNBSFile: return wbWhite; case chNRHFile: return wbText; default: /* we are using the ANSI char set that windows used */ #ifdef KOREA return ((isalpha(ch) || isdigit(ch) || ((ch>0x81)&&(ch<0xfe)))? wbText : wbPunct); #else return ((isalpha(ch) || isdigit(ch))? wbText : wbPunct); #endif } } #ifdef DBCS /* was in JAPAN; KenjiK '90-10-29 */ /* Brought from WIN2 source. */ int WbFromKanjiChCh(ch1, ch2) int ch1, ch2; { if (ch1 == chReturn && ch2 == chEol) { return wbWhite; } else if (FKanjiSpace(ch1, ch2)) { return wbWhite; } else #ifdef JAPAN { switch (ch1) { case 0x81: if (0x57 <= ch2 && ch2 <= 0x59) { return wbKanjiText; } else { return wbPunct; } case 0x85: if ((0x40 <= ch2 && ch2 <= 0x4E) || (0x59 <= ch2 && ch2 <= 0x5F) || (0x7A <= ch2 && ch2 <= 0x7E) || (0x9B <= ch2 && ch2 <= 0xA3) || (0xDC <= ch2 && ch2 <= 0xDD)) { return wbPunct; } else { return wbKanjiText; } case 0x86: return wbPunct; case 0x87: return ((ch2 >= 0x90) ? wbPunct : wbKanjiText); default: return wbKanjiText; } } #endif #ifdef KOREA { switch (ch1) { case 0xa2: if (0xde <= ch2 && ch2 <= 0xe5) { return wbText; // wbKanjiText; MSCH bklee 01/26/95 } else { return wbPunct; } case 0xa3: if ((0xa1 <= ch2 && ch2 <= 0xaf) || (0xba <= ch2 && ch2 <= 0xc0) || (0xdb <= ch2 && ch2 <= 0xe0) || (0xfb <= ch2 && ch2 <= 0xfe)) { return wbPunct; } else { return wbText; //wbKanjiText; MSCH bklee 01/26/95 } default: return wbText; //wbKanjiText; MSCH bklee 01/26/95 } } #endif #ifdef PRC // brucere 11/16/95 { switch (ch1) { case 0xA1: return wbPunct; case 0xA3: if ((0xA1 <= ch2 && ch2 <= 0xAF) || (0xBA <= ch2 && ch2 <= 0xC0) || (0xDB <= ch2 && ch2 <= 0xE0) || (0xFB <= ch2 && ch2 <= 0xFE)) return wbPunct; else return wbKanjiText; case 0xA4: if (ch2 == 0x92) return wbPunct; else return wbKanjiText; default: return wbKanjiText; } } #elif TAIWAN { switch (ch1) { case 0xA1: if (0x41 <= ch2 && ch2 <= 0xAC) return wbPunct; else return wbKanjiText; default: return wbKanjiText; } } #endif } #endif