/************************************************************/
/* 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 <windows.h>
#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>0xa1)&&(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 wbKanjiText;
}
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 wbKanjiText;
}
default:
return wbKanjiText;
}
}
#endif
#ifdef TAIWAN
{
switch (ch1) {
case 0xA1:
if (0x41 <= ch2 && ch2 <= 0xAC) {
return wbPunct;
}
else {
return wbKanjiText;
}
default:
return wbKanjiText;
}
}
#endif
}
#endif