/************************************************************/ /* Windows Write, Copyright 1985-1992 Microsoft Corporation */ /************************************************************/ /* disp.c -- MW display routines */ #define NOKEYSTATE #define NOSYSCOMMANDS #define NOSHOWWINDOW //#define NOATOM #define NOCLIPBOARD #define NOGDICAPMASKS #define NOCTLMGR #define NOWINSTYLES //#define NOVIRTUALKEYCODES #ifndef DBCS #define NOSYSMETRICS #endif #define NOMENUS #define NOSOUND #define NOCOMM #define NOOPENFILE #define NOWH #define NOWINOFFSETS #define NOMETAFILE #ifndef DBCS #define NOMB #endif #define NODRAWTEXT #include #define NOUAC #include "mw.h" #include "debug.h" #include "cmddefs.h" #include "dispdefs.h" #include "wwdefs.h" #define NOKCCODES /* Removes all kc code defines */ #include "ch.h" #include "docdefs.h" #include "fmtdefs.h" #include "propdefs.h" #include "macro.h" #include "printdef.h" #include "fontdefs.h" #if defined(OLE) #include "obj.h" #endif #ifdef DBCS #include "dbcs.h" #include "kanji.h" #endif #ifdef DBCS_IME #include #ifdef JAPAN #include "prmdefs.h" //IME3.1J BOOL ConvertEnable = FALSE; BOOL bClearCall = TRUE; #endif /* JAPAN */ #endif /* DBCS_IME */ #ifdef CASHMERE /* No VisiMode in WinMemo */ extern int vfVisiMode; #endif /* CASHMERE */ extern int vcchBlted; extern int vidxpInsertCache; extern int vdlIns; extern int vfInsLast; extern struct PAP vpapAbs; extern struct SEP vsepAbs; extern int rgval[]; extern struct DOD (**hpdocdod)[]; extern typeCP cpMacCur; extern int vfSelHidden; extern struct WWD rgwwd[]; extern int wwCur, wwMac; extern struct FLI vfli; extern struct SEL selCur; extern struct WWD *pwwdCur; extern int docCur; extern struct CHP (**vhgchpFormat)[]; extern int vichpFormat; extern typeCP cpMinCur; extern typeCP cpMinDocument; extern int vfInsertOn; extern int vfTextBltValid; extern typeCP vcpFirstParaCache; extern typeCP vcpLimParaCache; extern unsigned vpgn; extern struct SEP vsepAbs; extern CHAR stBuf[]; extern typeCP CpEdge(); extern typeCP CpMacText(); extern int vdocPageCache; extern int vfPictSel; extern int vfAwfulNoise; extern int vfSkipNextBlink; extern int dypMax; extern HDC vhMDC; extern HWND vhWndPageInfo; extern struct FMI vfmiScreen; extern int docScrap; extern long rgbBkgrnd; extern long ropErase; extern BOOL vfMonochrome; extern int dxpbmMDC; extern int dypbmMDC; extern HBITMAP hbmNull; extern int vfOutOfMemory; extern int vfSeeSel; extern int vfInsEnd; /* Is insert point at end-of-line? */ extern int vipgd; extern typeCP vcpMinPageCache; extern typeCP vcpMacPageCache; /* actual position of the cursor line */ extern int vxpCursLine; extern int vypCursLine; extern int vdypCursLine; extern int vfScrollInval; /* means scroll did not take and UpdateWw must be repeated */ extern BOOL vfDead; extern HRGN vhrgnClip; #if defined(JAPAN) & defined(IME_HIDDEN) //IME3.1J extern typeCP selUncpFirst; extern typeCP selUncpLim; extern HANDLE hImeUnAttrib; extern int vfImeHidden; int HiddenTextTop = 0; int HiddenTextBottom = 0; //if TRUE we are managing IR_UNDETERMINE BOOL whileUndetermine = FALSE; //12/28/92 LPSTR Attrib; WORD AttribPos = 0; #define IMEDEFCOLORS 6 // IME Define colors #define IMESPOT 0 // IME Spot background color #define IMESPOTTEXT 1 // IME Spot text color #define IMEINPUT 2 // IME Input background color #define IMEINPUTTEXT 3 // IME Input text color #define IMEOTHER 4 // IME Other background color #define IMEOTHERTEXT 5 // IME Other text color COLORREF rgbIMEHidden[IMEDEFCOLORS] = {0L,0L,0L,0L,0L,0L}; #endif /* G L O B A L S int dlsMac = 0;*/ #ifdef DBCS int donteat = 0; /* propagate not to eat message */ #endif #if defined(TAIWAN) || defined(PRC) //Daniel/MSTC, 1993/02/25, for jcBoth #define FKana(_ch) FALSE #endif /* D I S P L A Y F L I */ /* Display formatted line in window ww at line dl */ DisplayFli(ww, dl, fDontDisplay) int ww; int dl; int fDontDisplay; /* True if we set up dl info but don't display */ { typeCP dcp; typeCP dcpMac; struct WWD *pwwd = &rgwwd[ww]; HDC hDC = pwwd->hDC; int xp; /* Current xp to write text */ int yp; /* Current yp to write text */ int xpMin = pwwd->xpMin; /* Minimum xp in window */ int xpMac = pwwd->xpMac; /* Maximum xp in window */ int ypLine; /* Screen yp for current line */ int dxp; /* Width of current run */ int dyp; /* Line height */ int dxpExtra; /* Width of pad for each space */ typeCP cpMin; typeCP cpMac; int xpSel; /* xp of the start of the selection */ int dxpSel = 0; /* Width of the selection. */ CHAR chMark = '\0'; /* style character */ struct CHP *pchp; BOOL fTabsKludge = (vfli.ichLastTab >= 0); BOOL fInsertOn = FALSE; int cBreakRun; /* break characters in run (no relation to Dick or Jane) */ #ifdef SMFONT RECT rcOpaque; #endif /* SMFONT */ #ifdef JAPAN // added 19 Jun. 1992 by Hiraisi extern int vfWordWrap; /* WordWrap flag : TRUE=ON, FALSE=OFF */ extern int iNonWideSpaces; int iRun; typeCP RealcpFirst; #elif defined(TAIWAN) || defined(PRC) extern int vfWordWrap; /* WordWrap flag : TRUE=ON, FALSE=OFF */ extern int iNonWideSpaces; int iRun; typeCP RealcpFirst; #endif #ifdef DDISP CommSzNumNum(" DisplayFli: dl/fDontDisplay ", dl, fDontDisplay); #endif Assert(ww >= 0 && ww < wwMax); #ifdef SMFONT Assert(!fDontDisplay || vfli.fGraphics) #endif /* SMFONT */ Scribble(5,'D'); /* Fill up EDL and set some useful locals */ { register struct EDL *pedl = &(**pwwd->hdndl)[dl]; if (dl == vdlIns) { /* Overwriting chars blted during fast insert; reset blt count */ vcchBlted = 0; vidxpInsertCache = -1; } pedl->xpLeft = vfli.xpLeft; pedl->xpMac = vfli.xpReal; cpMin = pedl->cpMin = vfli.cpMin; #ifdef JAPAN RealcpFirst = cpMin; #endif pedl->dcpMac = (cpMac = vfli.cpMac) - cpMin; dyp = pedl->dyp = vfli.dypLine; pedl->ichCpMin = vfli.ichCpMin; pedl->dcpDepend = (cpMin == cpMac) ? 0xff : vfli.dcpDepend; pedl->fValid = TRUE; pedl->fGraphics = vfli.fGraphics; pedl->fSplat = vfli.fSplat; /* The position of current line equals the position of the previous line + height of this line. */ #ifdef SMFONT pedl->yp = rcOpaque.bottom = dyp + (ypLine = rcOpaque.top = (dl == 0 ? pwwd->ypMin : (pedl - 1)->yp)); #else /* not SMFONT */ pedl->yp = dyp + (ypLine = (dl == 0 ? pwwd->ypMin : (pedl - 1)->yp)); #endif /* SMFONT */ if (pedl->fIchCpIncr = (vfli.ichCpMac != 0)) { /* Look at final text column */ ++cpMac; /* Since this is true, we can compress pedl->ichCpMac to 1 bit. */ Assert(vfli.ichCpMac == pedl->ichCpMin + 1); } } if (vfli.doc == docNil) { /* This is the space beyond the end mark. */ PatBlt(hDC, 0, ypLine, xpMac, dyp, ropErase); goto Finished; } /* Is there a character in the "style bar"? */ if (cpMin != cpMac) { #ifdef CASHMERE /* This line is not completely empty (not after the end mark); check for painting marks on the style bar. */ if (cpMin == vcpFirstParaCache && vpapAbs.rhc != 0) { /* This is a running-head. */ chMark = chStatRH; } else if ((**hpdocdod)[vfli.doc].hpgtb != 0) #else /* not CASHMERE */ if (vpapAbs.rhc == 0 && (**hpdocdod)[vfli.doc].hpgtb != 0) #endif /* CASHMERE */ { if (vdocPageCache != vfli.doc || cpMac > vcpMacPageCache || cpMac <= vcpMinPageCache) { CachePage(vfli.doc, cpMac - 1); } /* We are now guaranteed that cpMac is within the cached page. */ if (cpMin <= vcpMinPageCache && (!vfli.fGraphics || vfli.ichCpMin == 0)) { /* This is the first line of new page; show page mark. */ chMark = chStatPage; } } } #ifdef SMFONT #ifdef DDISP /* black out this line to test how efficiently/correctly we overwrite pixels from previously-resident lines of text */ PatBlt(hDC, 0, ypLine, xpMac, dyp, BLACKNESS); { long int i; for (i=0; i < 500000; i++) ; } #endif /* Calculate dcpMac now, so we might be able to know how much to erase. */ dcpMac = vfli.fSplat ? vfli.ichMac : vfli.ichReal; /* Erase any character that might be in the style bar. */ dxp = xpSelBar + 1; if (!vfli.fGraphics) { dxp = xpMac; // clear the whole line } PatBlt(hDC, 0, ypLine, dxp, dyp, ropErase); /* If this is graphics then go draw any characters in the style bar. */ if (vfli.fGraphics) { goto DrawMark; } /* If there are no "real" characters on this line then we can skip alot of this. */ if (dcpMac == 0) { goto EndLine2; } #else /* not SMFONT */ if (vfli.fGraphics || fDontDisplay) { /* Erase any character that might be in the style bar. */ PatBlt(hDC, 0, ypLine, xpSelBar, dyp, ropErase); goto DrawMark; } #endif /* SMFONT */ ValidateMemoryDC(); if (vhMDC == NULL) { Error: /* Notify the user that an error has occured and simply erase this line. */ WinFailure(); PatBlt(hDC, xpSelBar, ypLine, xpMac - xpSelBar, dyp, ropErase); goto Finished; } #ifndef SMFONT /* Create a new bitmap for the memory DC if the current bitmap is not big enough. */ if (xpMac > dxpbmMDC || dyp > dypbmMDC) { HBITMAP hbm; /* If there is an old bitmap, then delete it. */ if (dxpbmMDC != 0 || dypbmMDC != 0) { DeleteObject(SelectObject(vhMDC, hbmNull)); } /* Create the new bitmap and select it in. */ if ((hbm = CreateBitmap(dxpbmMDC = xpMac, dypbmMDC = dyp, 1, 1, (LPSTR)NULL)) == NULL) { /* There should be a graceful way to recover if the bitmap is ever NULL (e.g we don't have enough memory for it). */ dxpbmMDC = dypbmMDC = 0; goto Error; } SelectObject(vhMDC, hbm); } /* Erase the are of the bitmap we are going to use. */ PatBlt(vhMDC, xpSelBar, 0, xpMac, dyp, vfMonochrome ? ropErase : WHITENESS); #endif /* not SMFONT */ /* Initialize some of the variables we'll need. */ pchp = &(**vhgchpFormat)[0]; #ifdef SMFONT xp = rcOpaque.left = rcOpaque.right = vfli.xpLeft + xpSelBar - xpMin + 1; #else /* not SMFONT */ dcpMac = vfli.fSplat ? vfli.ichMac : vfli.ichReal; xp = vfli.xpLeft + xpSelBar - xpMin + 1; #endif /* SMFONT */ dxpExtra = fTabsKludge ? 0 : vfli.dxpExtra; #ifdef SMFONT /* If we are horizontally scrolled, then set the clip area to the area outside of the selection bar. */ if (xpMin != 0) { IntersectClipRect(hDC, xpSelBar, rcOpaque.top, xpMac, rcOpaque.bottom); } #endif /* SMFONT */ #ifdef JAPAN // added 19 Jun. 1992 by Hiraisi iRun = 0; #elif defined(TAIWAN) || defined(PRC) //Daniel/MSTC, 1993/02/25, for jcBoth iRun = 0; #endif for (dcp = 0; dcp < dcpMac; pchp++) { /* For all runs do: */ int ichFirst; /* First character in the current run */ int cchRun; /* Number of characters in the current run */ dcp = ichFirst = pchp->ichRun; dcp += pchp->cchRun; if (dcp > dcpMac) { dcp = dcpMac; } cchRun = dcp - ichFirst; /* Compute dxp = sum of width of characters in current run (formerly DxaFromIcpDcp). */ { register int *pdxp; register int cchT = cchRun; PCH pch = vfli.rgch + ichFirst; dxp = cBreakRun = 0; pdxp = &vfli.rgdxp[ichFirst]; while (cchT-- > 0) { dxp += *pdxp++; if (*pch++ == chSpace) ++cBreakRun; } #ifdef DDISP CommSzNum(" dxp=",dxp); #endif } if (dxp > 0) { int cchDone; PCH pch = &vfli.rgch[ichFirst]; #ifdef JAPAN // added 08 Jul. 1992 by Hiraisi int *pdxpT = &vfli.rgdxp[ichFirst]; #elif defined(TAIWAN) || defined(PRC) //Daniel/MSTC, 1993/02/25, for jcBoth int *pdxpT = &vfli.rgdxp[ichFirst]; #endif LoadFont(vfli.doc, pchp, mdFontScreen); yp = (dyp - (vfli.dypBase + (pchp->hpsPos != 0 ? (pchp->hpsPos < hpsNegMin ? ypSubSuper : -ypSubSuper) : 0))) - vfmiScreen.dypBaseline; /* Note: tabs and other special characters are guaranteed to come at the start of a run. */ #ifdef JAPAN // added 19 Jun. 1992 by Hiraisi if( vpapAbs.jc != jcBoth || fTabsKludge ) SetTextJustification(vhMDC, dxpExtra * cBreakRun, cBreakRun); #elif defined(TAIWAN) || defined(PRC) // Daniel/MSTC, 1993/02/25, for jcBoth if( vpapAbs.jc != jcBoth) SetTextJustification(vhMDC, dxpExtra * cBreakRun, cBreakRun); #else SetTextJustification(vhMDC, dxpExtra * cBreakRun, cBreakRun); #endif /* JAPAN */ #ifdef SMFONT #ifdef JAPAN // added 19 Jun. 1992 by Hiraisi if( vpapAbs.jc != jcBoth || fTabsKludge ) SetTextJustification(hDC, dxpExtra * cBreakRun, cBreakRun); #elif defined(TAIWAN) || defined(PRC) //Daniel/MSTC, 1993/02/25, for jcBoth if( vpapAbs.jc != jcBoth) SetTextJustification(hDC, dxpExtra * cBreakRun, cBreakRun); #else SetTextJustification(hDC, dxpExtra * cBreakRun, cBreakRun); #endif /* JAPAN */ #endif /* SMFONT */ cchDone = 0; while (cchDone < cchRun) { int cch; /* Does the wide-space zone begin in this run? */ if (vfli.fAdjSpace && (vfli.ichFirstWide < ichFirst + cchRun) && (ichFirst + cchDone <= vfli.ichFirstWide)) { int cchDoneT = cchDone; /* Is this the beginning of the wide-space zone? */ if (ichFirst + cchDone == vfli.ichFirstWide) { /* Reset the width of the spaces. */ #ifdef JAPAN // added 19 Jun. 1992 by Hiraisi if( vpapAbs.jc != jcBoth || fTabsKludge ) SetTextJustification(vhMDC, ++dxpExtra * cBreakRun, cBreakRun); #elif defined(TAIWAN) || defined(PRC) //Daniel/MSTC, 1993/02/25, for jcBoth if( vpapAbs.jc != jcBoth || fTabsKludge ) SetTextJustification(vhMDC, ++dxpExtra * cBreakRun, cBreakRun); #else SetTextJustification(vhMDC, ++dxpExtra * cBreakRun, cBreakRun); #endif /* JAPAN */ #ifdef SMFONT #ifdef JAPAN // added 19 Jun. 1992 by Hiraisi if( vpapAbs.jc != jcBoth || fTabsKludge ) SetTextJustification(hDC, dxpExtra * cBreakRun, cBreakRun); #elif defined(TAIWAN) || defined(PRC) //Daniel/MSTC, 1993/02/25, for jcBoth if( vpapAbs.jc != jcBoth) SetTextJustification(hDC, dxpExtra * cBreakRun, cBreakRun); #else SetTextJustification(hDC, dxpExtra * cBreakRun, cBreakRun); #endif /* JAPAN */ #endif /* SMFONT */ cch = cchRun - cchDone; cchDone = cchRun; } else { cchDone = cch = vfli.ichFirstWide - ichFirst; } /* This run is cut short because of a wide space, so we need to calculate a new width. */ { register int *pdxp; register int cchT = cch; PCH pch = &vfli.rgch[ichFirst + cchDoneT]; dxp = 0; pdxp = &vfli.rgdxp[ichFirst + cchDoneT]; while (cchT-- > 0) { dxp += *pdxp++; if (*pch++ == chSpace) ++cBreakRun; } } } else { cchDone = cch = cchRun; } while (cch > 0) { switch (*pch) { CHAR ch; int dxpT; case chTab: #ifdef CASHMERE /* chLeader contains tab leader character (see FormatLine) */ if ((ch = pchp->chLeader) != chSpace) { int cxpTab; CHAR rgch[32]; int dxpLeader = CharWidth(ch); int xpT = xp; int iLevelT = SaveDC(vhMDC); SetBytes(&rgch[0], ch, 32); dxpT = vfli.rgdxp[ichFirst]; cxpTab = ((dxpT + dxpLeader - 1) / dxpLeader + 31) >> 5; xp += dxpT; while (cxpTab-- > 0) { TextOut(vhMDC, xpT, yp, (LPSTR)rgch, 32); xpT += dxpLeader << 5; } RestoreDC(vhMDC, iLevelT); } else #endif /* CASHMERE */ { #ifdef SMFONT /* Expand the opaque rectangle to include the tab. */ rcOpaque.right += vfli.rgdxp[ichFirst]; #endif /* SMFONT */ xp += vfli.rgdxp[ichFirst]; } if (fTabsKludge && ichFirst >= vfli.ichLastTab) { #ifdef JAPAN // added 19 Jun. 1992 by Hiraisi if( vpapAbs.jc != jcBoth ) SetTextJustification(vhMDC, (dxpExtra = vfli.dxpExtra) * cBreakRun, cBreakRun); else dxpExtra = vfli.dxpExtra; #elif defined(TAIWAN) || defined(PRC) //Daniel/MSTC, 1993/02/25, for jcBoth if( vpapAbs.jc != jcBoth ) SetTextJustification(vhMDC, (dxpExtra = vfli.dxpExtra) * cBreakRun, cBreakRun); else dxpExtra = vfli.dxpExtra; #else SetTextJustification(vhMDC, (dxpExtra = vfli.dxpExtra) * cBreakRun, cBreakRun); #endif /* JAPAN */ #ifdef SMFONT #ifdef JAPAN // added 19 Jun. 1992 by Hiraisi if( vpapAbs.jc != jcBoth ) SetTextJustification(hDC, dxpExtra * cBreakRun, cBreakRun); #elif defined(TAIWAN) || defined(PRC) //Daniel/MSTC, 1993/02/25, for jcBoth if( vpapAbs.jc != jcBoth ) SetTextJustification(hDC, dxpExtra * cBreakRun, cBreakRun); #else SetTextJustification(hDC, dxpExtra * cBreakRun, cBreakRun); #endif /* JAPAN */ #endif /* SMFONT */ fTabsKludge = FALSE; } dxp -= vfli.rgdxp[ichFirst]; pch++; cch--; #ifdef JAPAN // added 19 Jun. 1992 by Hiraisi iRun++; pdxpT++; #elif defined(TAIWAN) || defined(PRC) //Daniel/MSTC, 1993/02/25, for jcBoth iRun++; pdxpT++; #endif goto EndLoop; #ifdef CASHMERE case schPage: if (!pchp->fSpecial) { goto EndLoop; } stBuf[0] = CchExpPgn(&stBuf[1], vpgn, vsepAbs.nfcPgn, flmSandMode, ichMaxLine); goto DrawSpecial; case schFootnote: if (!pchp->fSpecial) { goto EndLoop; } stBuf[0] = CchExpFtn(&stBuf[1], cpMin + ichFirst, flmSandMode, ichMaxLine); DrawSpecial: #else /* not CASHMERE */ case schPage: case schFootnote: if (!pchp->fSpecial) { goto EndLoop; } stBuf[0] = *pch == schPage && (wwdCurrentDoc.fEditHeader || wwdCurrentDoc.fEditFooter) ? CchExpPgn(&stBuf[1], vpgn, 0, flmSandMode, ichMaxLine) : CchExpUnknown(&stBuf[1], flmSandMode, ichMaxLine); #endif /* not CASHMERE */ #ifdef SMFONT /* Calculate the opaque rectangle. */ rcOpaque.right += vfli.rgdxp[ichFirst] + vfmiScreen.dxpOverhang; TextOut(hDC, xp, ypLine+yp, &stBuf[1], stBuf[0]); #else /* not SMFONT */ TextOut(vhMDC, xp, yp, (LPSTR)&stBuf[1], stBuf[0]); #endif /* SMFONT */ break; #ifdef DBCS #if !defined(JAPAN) && !defined(KOREA) /* Write ver3.1j endmark is 1charcter t-yoshio May 26,92*/ case chMark1: if(*(pch+1) == chEMark) { /* This run only contains EndMark */ rcOpaque.right += dxp + vfmiScreen.dxpOverhang; #if defined (TAIWAN) || defined(PRC) // solve italic font overhang truncation problem, MSTC - pisuih, 2/19/93 TextOut(hDC, xp, (yp>0?(ypLine+yp):ypLine), (LPSTR)pch, cch ); #else ExtTextOut(hDC, xp, (yp>0?(ypLine+yp):ypLine), 2, (LPRECT)&rcOpaque,(LPSTR)pch, cch, (LPSTR)NULL); #endif pch += cch; cch = 0; xp += dxp; rcOpaque.left = (rcOpaque.right = xp) + vfmiScreen.dxpOverhang; } /* else fall through */ #endif /*JAPAN*/ #endif default: goto EndLoop; } dxp -= vfli.rgdxp[ichFirst]; #ifdef SMFONT /* End the line if no more will fit into the window. */ if ((xp += vfli.rgdxp[ichFirst++]) >= xpMac) { goto EndLine; } rcOpaque.left = (rcOpaque.right = xp) + vfmiScreen.dxpOverhang; #else /* not SMFONT */ xp += vfli.rgdxp[ichFirst++]; #endif /* SMFONT */ pch++; cch--; #ifdef JAPAN // added 09 Jul. 1992 by Hiraisi pdxpT++; #endif } EndLoop: #ifdef SMFONT if (cch == 0) { Assert(dxp == 0); } else { /* Calculate the opaque rectangle. */ rcOpaque.right += dxp + vfmiScreen.dxpOverhang; #if 0 { char msg[180]; wsprintf(msg,"putting out %d characters\n\r",cch); OutputDebugString(msg); } #endif #ifdef JAPAN // added 19 Jun. 1992 by Hiraisi if( vpapAbs.jc == jcBoth&&!fTabsKludge ) { CHAR *ptr1, *ptr2; int len, cnt; int iExtra, iSpace, iWid; BOOL bFlag; typeCP RealcpEnd; ptr2 = pch; for( cnt=0 ; cnt < cch ; ) { ptr1 = ptr2; iExtra = dxpExtra; iWid = len = 0; bFlag = TRUE; if( IsDBCSLeadByte(*ptr2) ) { for( ; cnt < cch ; ) { iWid += *pdxpT; pdxpT += 2; cnt += 2; len += 2; iRun += 2; ptr2 += 2; if( --iNonWideSpaces == 0 ) { dxpExtra++; break; } if( iRun == dcp - 2 ) break; if( iRun == dcp ) { /* lastDBC(maybe) */ iExtra = 0; break; } if( !IsDBCSLeadByte(*ptr2) ) break; } } else { if( FKana( (int)*ptr2) ) { for( ; cnt < cch ; ) { iWid += *pdxpT++; cnt++; len++; iRun++; ptr2++; if( --iNonWideSpaces == 0 ) { dxpExtra++; break; } if( iRun == dcp - 1 ) break; if( iRun == dcp ) { /* last SBC(maybe) */ iExtra = 0; break; } if( !FKana( (int)*ptr2) ) break; } } else { for( bFlag = FALSE,iSpace = 0; cnt < cch ; ) { iWid += *pdxpT++; cnt++; len++; iRun++; if( *ptr2++ == chSpace || !vfWordWrap ) { iSpace++; if( --iNonWideSpaces == 0 ) { dxpExtra++; break; } } if( iRun == dcp - 1 ) break; if( iRun == dcp ) { /* lastSBC(maybe) */ iExtra = 0; break; } if( IsDBCSLeadByte(*ptr2 ) || FKana((int)*ptr2) ) break; } } } if( vfWordWrap && !bFlag ) { SetTextCharacterExtra( hDC, 0 ); SetTextJustification( hDC, iExtra*iSpace,iSpace); } else { SetTextJustification(hDC,0,0); SetTextCharacterExtra(hDC,iExtra); } /*-TextOut-*/ #if defined(JAPAN) & defined(IME_HIDDEN) //IME3.1J /*Undetermine*/ if( (selUncpFirst != selUncpLim) && *ptr1 != chEMark) { RealcpEnd = RealcpFirst + len; UndetermineString(hDC, xp, ypLine+yp, ptr1, len, RealcpFirst, RealcpEnd); } else TextOut(hDC,xp,ypLine+yp,ptr1,len); #else TextOut(hDC,xp,ypLine+yp,ptr1,len); #endif RealcpFirst+=len; xp+=iWid; } } else{ iRun += cch; SetTextCharacterExtra( hDC, 0 ); /*Undetermine*/ #if defined(JAPAN) & defined(IME_HIDDEN) //IME3.1J if((selUncpFirst != selUncpLim) && *pch != chEMark) UndetermineString( hDC, xp, ypLine+yp, pch, cch, RealcpFirst, RealcpFirst+cch ); else /* Output cch characters starting at pch */ TextOut(hDC, xp, ypLine+yp, pch, cch); #else /* Output cch characters starting at pch */ TextOut(hDC, xp, ypLine+yp, pch, cch); #endif /* End the line if no more will fit into the window. */ xp += dxp; RealcpFirst+=cch; } if (xp >= xpMac) #elif defined(TAIWAN) || defined(PRC) //Daniel/MSTC, 1993/02/25, for jcBoth if( vpapAbs.jc == jcBoth) { //&& !fTabsKludge ) { CHAR *ptr1, *ptr2; int len, cnt; int iExtra, iSpace, iWid; BOOL bFlag; typeCP RealcpEnd; ptr2 = pch; for( cnt=0 ; cnt < cch ; ) { ptr1 = ptr2; iExtra = dxpExtra; iWid = len = 0; bFlag = TRUE; if( IsDBCSLeadByte(*ptr2) ) { for( ; cnt < cch ; ) { iWid += *pdxpT; pdxpT += 2; cnt += 2; len += 2; iRun += 2; ptr2 += 2; if( --iNonWideSpaces == 0 ) { dxpExtra++; break; } if( iRun == dcp - 2 ) break; if( iRun == dcp ) { /* lastDBC(maybe) */ iExtra = 0; break; } if( !IsDBCSLeadByte(*ptr2) ) break; } } else { if( FKana( (int)*ptr2) ) { for( ; cnt < cch ; ) { iWid += *pdxpT++; cnt++; len++; iRun++; ptr2++; if( --iNonWideSpaces == 0 ) { dxpExtra++; break; } if( iRun == dcp - 1 ) break; if( iRun == dcp ) { /* last SBC(maybe) */ iExtra = 0; break; } if( !FKana( (int)*ptr2) ) break; } } else { for( bFlag = FALSE,iSpace = 0; cnt < cch ; ) { iWid += *pdxpT++; cnt++; len++; iRun++; if( *ptr2++ == chSpace || !vfWordWrap ) { iSpace++; if( --iNonWideSpaces == 0 ) { dxpExtra++; break; } } if( iRun == dcp - 1 ) break; if( iRun == dcp ) { /* lastSBC(maybe) */ iExtra = 0; break; } if( IsDBCSLeadByte(*ptr2 ) || FKana((int)*ptr2) ) break; } } } if( vfWordWrap && !bFlag ) { SetTextCharacterExtra( hDC, 0 ); SetTextJustification( hDC, iExtra*iSpace,iSpace); } else { SetTextJustification(hDC,0,0); SetTextCharacterExtra(hDC,iExtra); } /*-TextOut-*/ //#if defined(JAPAN) & defined(IME_HIDDEN) //IME3.1J // /*Undetermine*/ // if( (selUncpFirst != selUncpLim) && // *ptr1 != chEMark) { // RealcpEnd = RealcpFirst + len; // UndetermineString(hDC, xp, ypLine+yp, ptr1, // len, RealcpFirst, RealcpEnd); // } else // TextOut(hDC,xp,ypLine+yp,ptr1,len); //#else TextOut(hDC,xp,ypLine+yp,ptr1,len); //#endif RealcpFirst+=len; xp+=iWid; } } else{ iRun += cch; SetTextCharacterExtra( hDC, 0 ); /*Undetermine*/ //#if defined(JAPAN) & defined(IME_HIDDEN) //IME3.1J // if((selUncpFirst != selUncpLim) && *pch != chEMark) // UndetermineString( hDC, xp, ypLine+yp, // pch, cch, RealcpFirst, RealcpFirst+cch ); // else // /* Output cch characters starting at pch */ // TextOut(hDC, xp, ypLine+yp, pch, cch); //#else /* Output cch characters starting at pch */ TextOut(hDC, xp, ypLine+yp, pch, cch); //#endif /* End the line if no more will fit into the window. */ xp += dxp; RealcpFirst+=cch; } if (xp >= xpMac) #else /* Output cch characters starting at pch */ #if defined(KOREA) if ((cch == 1) && (pch[0] == chEMark)) { int iPrevBkMode; iPrevBkMode = SetBkMode(hDC, OPAQUE); TextOut(hDC, xp, ypLine+yp, pch, cch); SetBkMode(hDC, iPrevBkMode); } else TextOut(hDC, xp, ypLine+yp, pch, cch); #else TextOut(hDC, xp, ypLine+yp, pch, cch); #endif /* End the line if no more will fit into the window. */ if ((xp += dxp) >= xpMac) #endif // JAPAN { goto EndLine; } rcOpaque.left = (rcOpaque.right = xp) + vfmiScreen.dxpOverhang; pch += cch; } #else /* not SMFONT */ /* Output cch characters starting at pch */ TextOut(vhMDC, xp, yp, (LPSTR)pch, cch); xp += dxp; pch += cch; #endif /* SMFONT */ } /* end while (cchDone0) */ } /* end for dcp=0..dcpMac */ #ifdef SMFONT EndLine: /* Restore the clip region if need be. */ if (xpMin != 0) { SelectClipRgn(hDC, NULL); } EndLine2: #endif /* SMFONT */ #ifdef CASHMERE if (vfVisiMode) { AddVisiSpaces(ww, &(**pwwd->hdndl)[dl], vfli.dypBase, vfli.dypAfter + vfli.dypFont); } #endif /* CASHMERE */ vfTextBltValid = FALSE; if ((ww == wwCur) && (pwwd->doc != docScrap) && !vfSelHidden && (selCur.cpLim >= cpMin)) { if (selCur.cpFirst <= cpMac) { /* Show selection */ int xpFirst; int xpLim; #ifdef ENABLE if (vfli.fSplatNext && selCur.cpFirst == selCur.cpLim && selCur.cpFirst == cpMac) { vfInsEnd = TRUE; ClearInsertLine(); } vfInsertOn = FALSE; #endif /* ENABLE */ if (selCur.cpFirst <= cpMin && selCur.cpLim >= cpMac) { xpFirst = vfli.xpLeft; xpLim = vfli.xpReal; } else if (selCur.cpFirst < cpMac || (selCur.cpLim == cpMac && vfInsEnd)) { typeCP cpBegin = CpMax(cpMin, selCur.cpFirst); typeCP cpEnd = CpMin(cpMac, selCur.cpLim); dxp = DxpDiff((int)(cpBegin - cpMin), (int)(cpEnd - cpBegin), &xpFirst); xpLim = min(xpMin + vfli.xpReal, xpFirst + dxp); } else { goto DidntHighlight; } xpSel = xpSelBar + max(xpFirst - xpMin, 0); if (xpLim > xpFirst) { /* Set highlighting at desired screen position. */ dxpSel = max(xpLim - max(xpFirst, xpMin), 0); } else if (selCur.cpFirst == selCur.cpLim && ((selCur.cpLim != cpMac) ^ vfInsEnd)) { vfInsertOn = FALSE; /* Because we redisplayed insert pt line */ #ifdef CASHMERE vdypCursLine = min(vfli.dypFont, vfli.dypLine - vfli.dypAfter); vypCursLine = ypLine + dyp - vfli.dypAfter; #else /* not CASHMERE */ #ifdef DBCS // Some double byte fonts have bigger character // face than the line hight. vdypCursLine = min(vfli.dypFont, vfli.dypLine - vfli.dypAfter); #else vdypCursLine = vfli.dypFont; #endif vypCursLine = ypLine + dyp; #endif /* not CASHMERE */ vxpCursLine = xpSel; /* Start blinking in a while */ vfSkipNextBlink = TRUE; fInsertOn = xpFirst >= xpMin; } DidntHighlight:; } } #ifdef SMFONT /* Invert the selection */ if (dxpSel != 0) { PatBlt(hDC, xpSel, ypLine, dxpSel, dyp, DSTINVERT); } #else /* not SMFONT */ /* Blt the line of text onto the screen. */ PatBlt(vhMDC, 0, 0, xpSelBar, dyp, vfMonochrome ? ropErase : WHITENESS); if (dxpSel == 0) { BitBlt(hDC, 0, ypLine, xpMac, dyp, vhMDC, 0, 0, SRCCOPY); } else { BitBlt(hDC, 0, ypLine, xpSel, dyp, vhMDC, 0, 0, SRCCOPY); BitBlt(hDC, xpSel, ypLine, dxpSel, dyp, vhMDC, xpSel, 0, NOTSRCCOPY); xpSel += dxpSel; BitBlt(hDC, xpSel, ypLine, xpMac - xpSel, dyp, vhMDC, xpSel, 0, SRCCOPY); } #endif /* SMFONT */ /* Draw the insertion bar if necessary. */ if (fInsertOn) { DrawInsertLine(); } #if defined(JAPAN) & defined(DBCS_IME) // Set a flag for IME management. else { bClearCall = TRUE; } #endif DrawMark: /* Draw the character in the style bar if necessary. */ if (chMark != '\0') { #ifdef SYSENDMARK #ifdef DBCS // prepare buf for double-byte end mark. CHAR rgch[cchKanji]; #endif struct CHP chpT; extern struct CHP vchpNormal; blt(&vchpNormal, &chpT, cwCHP); chpT.ftc = ftcSystem; chpT.ftcXtra = 0; chpT.hps = hpsDefault; /* Draw the style character in the standard font. */ LoadFont(vfli.doc, &chpT, mdFontScreen); #ifdef DBCS // we use double byte end mark. #if defined(JAPAN) || defined(KOREA) /*t-yoshio May 26,92*/ #if defined(KOREA) { int iPrevBkMode; iPrevBkMode = SetBkMode(hDC, OPAQUE); TextOut(hDC, 0, ypLine + dyp - vfli.dypBase - vfmiScreen.dypBaseline, (LPSTR)&chMark, 1); SetBkMode(hDC, iPrevBkMode); } #else TextOut(hDC, 0, ypLine + dyp - vfli.dypBase - vfmiScreen.dypBaseline, (LPSTR)&chMark, 1); #endif #else rgch[0] = chMark1; rgch[1] = chMark; rcOpaque.left = 0; rcOpaque.right = DxpFromCh(chMark1,FALSE); rcOpaque.top = ypLine; rcOpaque.bottom = ypLine+dyp; /* When this line string is lower than system font,it remains dust, so we must clip this mark. */ ExtTextOut(hDC, 0, ypLine + dyp - vfli.dypBase - vfmiScreen.dypBaseline, ETO_CLIPPED, (LPRECT)&rcOpaque,(LPSTR)rgch, cchKanji, (LPSTR)NULL); #endif /*JAPAN*/ #else TextOut(hDC, 0, ypLine + dyp - vfli.dypBase - vfmiScreen.dypBaseline, (LPSTR)&chMark, 1); #endif /* DBCS */ #else /* ifdef SYSENDMARK */ /*T-HIROYN sync 3.0 disp.c */ #if 0 /* Draw the style character in the standard font. */ LoadFont(vfli.doc, NULL, mdFontScreen); TextOut(hDC, 0, ypLine + dyp - vfli.dypBase - vfmiScreen.dypBaseline, (LPSTR)&chMark, 1); #endif #if defined(JAPAN) || defined(KOREA) /* KenjiK '90-10-26 */ /* Draw the style character in the standard font. */ { CHAR rgch[cchKanji]; LoadFont(vfli.doc, NULL, mdFontScreen); rgch[0] = chMark1; rgch[1] = chMark; #if defined(KOREA) { int iPrevBkMode; iPrevBkMode = SetBkMode(hDC, OPAQUE); ExtTextOut(hDC, 0, ypLine + dyp - vfli.dypBase - vfmiScreen.dypBaseline,ETO_CLIPPED, (LPRECT)&rcOpaque,(LPSTR)rgch, cchKanji, (LPSTR)NULL); SetBkMode(hDC, iPrevBkMode); } #else ExtTextOut(hDC, 0, ypLine + dyp - vfli.dypBase - vfmiScreen.dypBaseline,ETO_CLIPPED, (LPRECT)&rcOpaque,(LPSTR)rgch, cchKanji, (LPSTR)NULL); #endif } #else /* JAPAN */ /* Draw the style character in the standard font. */ LoadFont(vfli.doc, NULL, mdFontScreen); TextOut(hDC, 0, ypLine + dyp - vfli.dypBase - vfmiScreen.dypBaseline, (LPSTR)&chMark, 1); #endif /* JAPAN */ #endif /* if-else-def SYSENDMARK */ } if (vfli.fGraphics) { DisplayGraphics(ww, dl, fDontDisplay); } Finished: Scribble(5,' '); } /* D X P D I F F */ DxpDiff(dcpFirst, dcp, pdxpFirst) int dcpFirst; int dcp; int *pdxpFirst; { #if 1 register int *pdxp = &vfli.rgdxp[0]; register int cch; int dxp = vfli.xpLeft; #ifdef ENABLE /* Not used */ int ichLim = dcpFirst + dcp; #endif if (dcp > vfli.ichMac - dcpFirst) { /* This should not be, but is when we have a CR */ //Assert( dcpFirst < vfli.ichMac ); dcp = vfli.ichMac - dcpFirst; } for (cch = 0; cch < dcpFirst; ++cch) { dxp += *pdxp++; } *pdxpFirst = dxp; dxp = 0; for (cch = 0; cch < dcp; ++cch) { dxp += *pdxp++; } return dxp; #else int dxp; if (dcp > vfli.ichMac - dcpFirst) { /* This should not be, but is when we have a CR */ Assert( dcpFirst < vfli.ichMac ); dcp = vfli.ichMac - dcpFirst; } /* first get space up to first character */ *pdxpFirst = LOWORD(GetTextExtent(hDC,vfli.rgch,dcpFirst)) + vfli.xpLeft; /* now get space between first and first+dcp */ dxp = LOWORD(GetTextExtent(hDC,vfli.rgch+dcpFirst,dcp)); return dxp; #endif } UpdateDisplay(fAbortOK) int fAbortOK; { int ww; if (wwMac <= 0) { return; } #ifdef CASHMERE for (ww = 0; ww < wwMac; ww++) if ( rgwwd[ww].doc != docScrap ) { UpdateWw(ww, fAbortOK); if (rgwwd[ww].fDirty || vfOutOfMemory) { return; /* update has been interrupted */ } } #else /* not CASHMERE */ UpdateWw(wwDocument, fAbortOK); if (wwdCurrentDoc.fDirty || vfOutOfMemory) { /* Update has been interrupted */ return; } #endif /* not CASHMERE */ if (wwdCurrentDoc.fRuler) { UpdateRuler(); } } /* U P D A T E W W */ UpdateWw(ww, fAbortOK) int ww, fAbortOK; { /* Redisplay ww as necessary */ extern int vfWholePictInvalid; register struct WWD *pwwd = &rgwwd[ww]; int dlMac; int dlOld, dlNew; int doc; int ichCp; struct EDL *pedlNew; register struct EDL *pedl; struct EDL (**hdndl)[]=pwwd->hdndl; int dypDiff; int ypTop; int ypFirstInval; int dr; int fLastNotShown; typeCP cp, cpMacWw; if (!pwwd->fDirty) { return; } if (!((**hpdocdod)[pwwd->doc].fDisplayable)) return; if (fAbortOK && FImportantMsgPresent()) return; #if 0 // how to get first and last cp's in invalid rect? #if defined(OLE) /* Load visible objects. Do it now rather than in DisplayGraphics() because here it has less chance of disrupting the state variables upon which UpdateWw depends. */ ObjEnumInRange(docCur,cpMinCur,cpMacCur,ObjLoadObjectInDoc); #endif #endif dlMac = pwwd->dlMac; ypTop = pwwd->ypMin; Assert( ww >= 0 && ww < wwMax ); vfli.doc = docNil; /* An aid to Fast Insert */ UpdateInvalid(); /* InvalBand for what Windows considers to be invalid */ ypFirstInval = pwwd->ypFirstInval; #ifndef CASHMERE Assert( ww == wwCur ); /* A MEMO-only assumption */ #endif /* CASHMERE */ Scribble(5, 'U'); ValidateMemoryDC(); /* to do any update, we need a good memory DC */ if (vhMDC == NULL) { WinFailure(); return; } doc = pwwd->doc; vfli.doc = docNil; if (pwwd->fCpBad) { /* cp first displayed has not been blessed */ #ifdef CASHMERE /* Must do this if ww != wwCur assertion is FALSE */ int wwT = wwCur; if (ww != wwCur && wwCur >= 0) /* CtrBackTrs cache is only good for wwCur. Treat != case */ { if (pwwdCur->fDirty) /* Do wwCur first, saving cache */ UpdateWw(wwCur, fAbortOK); if (fAbortOK && FImportantMsgPresent()) return; ChangeWw(ww, false); CtrBackDypCtr( 0, 0 ); /* Validate pwwdCur->cpFirst */ ChangeWw(wwT, false); } else #endif /* CASHMERE */ { if (fAbortOK && FImportantMsgPresent()) return; CtrBackDypCtr( 0, 0 ); /* Validate pwwdCur->cpFirst */ } } /* check for cpMin accessible in this ww */ RestartUpdate: vfWholePictInvalid = fTrue; /* Tells DisplayGraphics to abandon accumulated partial pict rect */ fLastNotShown = fFalse; cp = CpMax(pwwd->cpMin, pwwd->cpFirst); cpMacWw = pwwd->cpMac; ichCp = pwwd->ichCpFirst; /* Note test for dlNew==0 that guarantees that there will be at least one dl -- this was added for WRITE because we do not have the ability to enforce a minimum window size */ for (dlNew = dlOld = 0; ypTop < pwwd->ypMac || (dlNew == 0) ; dlNew++) /* we have: cp, ichCP: pints to text desired on the coming line dlNew ypTop: desired position for top of dlNew -1 dlOld: next line to be considered for re-use */ /* check for having to extend dndl array */ { if (dlNew >= (int)pwwd->dlMax) { /* extend the array with uninitialized dl's, increment max, break if no space. We assume that dlMac(Old) was <= dlMax, so the dl's will not be looked at but used only to store new lines */ #define ddlIncr 5 if (!FChngSizeH(hdndl, (pwwd->dlMax + ddlIncr) * cwEDL, fFalse)) break; pwwd->dlMax += ddlIncr; } /* discard unusable dl's */ for (; dlOld < dlMac; dlOld++) { /* Set dlOld and pedl to the next good dl */ int ypTopOld, ypOld; /* Re-entrant Heap Movement */ if (fAbortOK && !fLastNotShown && FImportantMsgPresent()) goto RetInval; pedl = &(**hdndl)[dlOld]; ypOld = pedl->yp; /* loop if: invalid, passed over in cp space, passed over in dl space, passed over in yp space, in invalid band, passed over in ich space */ if (!pedl->fValid || dlOld < dlNew || pedl->cpMin < cp || (ypTopOld = (ypOld - pedl->dyp)) < ypTop || (ypOld >= ypFirstInval && ypTopOld <= pwwd->ypLastInval) || (pedl->cpMin == cp && pedl->ichCpMin < ichCp)) continue; /* now we have dlOld, an acceptable if not necessarily useful dl. now compute dlNew either from scratch or by re-using dlOld. To be re-useable, dlOld must have right cp/ichCp pair, plus be totally on screen or, if it is a partial line, it must stay still or move down - not up */ if (pedl->cpMin == cp && pedl->ichCpMin == ichCp && (ypOld <= pwwd->ypMac || ypTopOld <= ypTop)) { /* Re-use this dl */ int yp = ypTop; if (fLastNotShown) { /* HEAP MOVEMENT */ DisplayFli(ww, dlNew - 1, fLastNotShown = fFalse); pedl = &(**hdndl)[dlOld]; } cp = pedl->cpMin + pedl->dcpMac; ichCp = pedl->fIchCpIncr ? pedl->ichCpMin + 1 : 0; ypTop += pedl->dyp; if (dlOld != dlNew || ypTopOld != yp) { DypScroll(ww, dlOld, dlNew - dlOld, yp); if (vfScrollInval) { /* There was a popup; invalid region might have changed */ /* fLastNotShown test is for interrupting picture display */ /* before we've really displayed it */ (**hdndl) [dlOld].fValid = fFalse; goto Restart1; } dlMac += dlNew - dlOld; } dlOld = dlNew + 1; goto NextDlNew; } break; } /* cpMin > cp, the line is not anywhere so it will have to be formatted from scratch */ if (fAbortOK && !fLastNotShown && FImportantMsgPresent()) goto RetInval; FormatLine(doc, cp, ichCp, cpMacWw, flmSandMode); /* Creates vfli */ if (vfOutOfMemory) goto RetInval; ichCp = vfli.ichCpMac; cp = vfli.cpMac; /* advance invalid band so that update can resume after an interruption */ pwwd->ypFirstInval = (ypTop += vfli.dypLine); pedl = &(**hdndl)[dlOld]; if (dlOld < dlMac && pedl->cpMin == cp && pedl->ichCpMin == ichCp) { int dlT = dlOld; /* line at dlOld is a valid, existing line that will abutt the line just about to be displayed. */ if (dlOld == dlNew && pedl->yp - pedl->dyp <= ypTop) /* the line about to be overwritten will be re-used in the next loop. Hence, it is worthwhile to save this line and its dl */ DypScroll(ww, dlOld++, 1, ypTop); else /* Move the next line to its abutting position. We know that it has not yet been overwritten (yp, dlOld all > than ypTop, dlNew) */ DypScroll(ww, dlOld, 0, ypTop); if (vfScrollInval) { /* There was a popup; invalid region might have changed */ /* fLastNotShown test is for interrupting picture display */ /* before we've really displayed it */ (**hdndl) [dlT].fValid = fFalse; Restart1: if (fLastNotShown) { pwwd->ypFirstInval = pwwd->ypMin; } ypFirstInval = pwwd->ypFirstInval; ypTop = pwwd->ypMin; goto RestartUpdate; } } /* true in 3rd param means put off picture redisplay till later */ /* condition: graphics & not last in picture & not last in y space and not in front of a invalid or valid transition in the picture */ DisplayFli(ww, dlNew, fLastNotShown = (vfli.fGraphics && vfli.ichCpMac!=0 && ypTop < pwwd->ypMac)); NextDlNew:; } Break1: pwwd->dlMac = dlNew; #ifdef CASHMERE /* condition is here to avoid swapping */ if (pwwd->fSplit && rgwwd[pwwd->ww].fFtn) CalcFtnLimits(pwwd); #endif /* CASHMERE */ SetCurWwVScrollPos(); /* Set Scroll bar position */ vfTextBltValid = false; /* reset invalid indications */ pwwd->fDirty = false; pwwd->ypFirstInval = ypMaxAll; pwwd->ypLastInval = 0; /* so that max in InvalBand will work */ Scribble(5, ' '); goto Validate; /* Before returning from an interrupt, invalidate lines that were overwritten within the present update. */ RetInval: Scribble(5, ' '); for (; dlOld < dlMac; dlOld++) { pedl = &(**hdndl)[dlOld]; if ((pedl->yp - pedl->dyp) < ypTop) pedl->fValid = fFalse; else break; } Validate: ; #ifdef ENABLE /* We will let UpdateInvalid handle this in case further invalidation occurred during the update */ { /* Tell Windows that the part we updated is valid */ RECT rc; rc.left = 0; rc.top = pwwd->ypMin; rc.right = pwwd->xpMac; rc.bottom = imin( pwwd->ypMac, ypTop ); ValidateRect( pwwd->wwptr, (LPRECT)&rc ); } #endif } /* D Y P S C R O L L */ DypScroll(ww, dlFirst, ddl, ypTo) int ww, dlFirst, ddl, ypTo; { /* Scroll dl's in a window, from dlFirst to end, down ddl lines (or up -ddl). Bitmap is moved from top of dlFirst to ypTo. The yp's of the dl's are updated. Returns the amount scrolled. (positive means down). */ register struct WWD *pwwd = &rgwwd[ww]; int dlMac; int dlT; int ypFrom; int dypChange; int cdlBelow; struct EDL *pedl; struct EDL *pedlT; /* Do not call procedures while dndl is loaded up to avoid heap movement */ struct EDL *dndl = &(**(pwwd->hdndl))[0]; Assert( ww >= 0 && ww < wwMax ); vfScrollInval = fFalse; /* Number of dl's below (and including) the first one to be scrolled */ cdlBelow = pwwd->dlMac - dlFirst; pwwd->dlMac = min(pwwd->dlMac + ddl, pwwd->dlMax); cdlBelow = max(0, min(cdlBelow, pwwd->dlMac - ddl - dlFirst)); pedlT = &dndl[dlFirst]; ypFrom = pedlT->yp - pedlT->dyp; /* Length of area to be moved */ dypChange = ypTo - ypFrom; if (cdlBelow > 0) { int dlTo = dlFirst + ddl; int ypMac = pwwd->ypMac; pedlT = &dndl[dlTo]; if (ddl != 0) { blt(&dndl[dlFirst], pedlT, cwEDL * cdlBelow); } for (dlT = dlTo; dlT < pwwd->dlMac; ++dlT, ++pedlT) { if (dypChange < 0 && pedlT->yp > ypMac) { /* Invalidate dl's that are pulled in from the ozone below ypMac */ pedlT->fValid = fFalse; } else { pedlT->yp += dypChange; } } } if (dypChange != 0) { RECT rc; SetRect( (LPRECT)&rc, 0, min(ypFrom, ypTo), pwwd->xpMac, pwwd->ypMac ); Assert( ww == wwCur ); /* A MEMO-only assumption */ ScrollCurWw( &rc, 0, dypChange ); } return dypChange; } FImportantMsgPresent() { /* If the next message is important enough to interrupt a screen update, we return TRUE; if it can wait, we return FALSE */ BOOL fToggledKey; extern MSG vmsgLast; #ifdef DEBUG unsigned wHeapVal = *(pLocalHeap + 1); Assert( wHeapVal == 0 ); /* Heap should not be frozen */ #endif #ifdef DBCS if( donteat ) return TRUE; #endif while (PeekMessage((LPMSG) &vmsgLast, NULL, NULL, NULL, PM_NOREMOVE)) { #if defined(JAPAN) & defined(DBCS_IME) /* If IME Cnv window open,we have to avoid ourselves to get into AlphaMode. ** So we do getmessage here to fill vmsgLast with app queue message. */ extern BOOL bImeCnvOpen; #if defined(JAPAN) & defined(IME_HIDDEN) //IME3.1J if( bImeCnvOpen || vfImeHidden) { #else if( bImeCnvOpen ) { #endif //JAPAN & IME_HIDDEN GetMessage((LPMSG) &vmsgLast, NULL, NULL, NULL); donteat = TRUE; return TRUE; } #endif /*T-HIROYN sync 3.1 disp.c */ #if 0 /* Filter uninteresting or easily handled events */ if (fToggledKey = FCheckToggleKeyMessage(&vmsgLast) || (vmsgLast.message == WM_KEYUP && vmsgLast.hwnd == wwdCurrentDoc.wwptr)) { if (((vmsgLast.wParam == VK_MENU) || (vmsgLast.wParam == VK_CONTROL))) return TRUE; #endif #ifdef JAPAN // 03/22/93 #ifdef PENWIN // 03/22/93 if (((vmsgLast.message == WM_KEYDOWN) || (vmsgLast.message == WM_KEYUP) || (vmsgLast.message == WM_SYSKEYDOWN) || (vmsgLast.message == WM_SYSKEYUP)) && ((vmsgLast.wParam == VK_MENU) || (vmsgLast.wParam == VK_CONTROL))) #else //PENWIN if (((vmsgLast.wParam == VK_MENU) || (vmsgLast.wParam == VK_CONTROL))) #endif #elif defined(KOREA) #define VK_PROCESSKEY 0xE5 // New finalize message. bklee. // bug #3191, In HWin3.1, WM_NCLBUTTONDOWN message is reached this if statement. // Because HTBOTTOMDOWN's value is same with VK_CONTROL's, we can't resize write window if (((vmsgLast.message == WM_KEYDOWN) || (vmsgLast.message == WM_KEYUP) || (vmsgLast.message == WM_SYSKEYDOWN) || (vmsgLast.message == WM_SYSKEYUP)) && ((vmsgLast.wParam == VK_MENU) || (vmsgLast.wParam == VK_CONTROL) || (vmsgLast.wParam == VK_PROCESSKEY) )) #else //JAPAN if (((vmsgLast.wParam == VK_MENU) || (vmsgLast.wParam == VK_CONTROL))) #endif { if (vmsgLast.wParam == VK_CONTROL) { GetMessage((LPMSG) &vmsgLast, NULL, NULL, NULL); SetShiftFlags(); } return TRUE; } /* Filter uninteresting or easily handled events */ else if (fToggledKey = FCheckToggleKeyMessage(&vmsgLast) || (vmsgLast.message == WM_KEYUP && vmsgLast.hwnd == wwdCurrentDoc.wwptr)) { /* This is so the Windows keyboard interface mechanism will see toggle key and key-up transitions */ GetMessage((LPMSG) &vmsgLast, NULL, NULL, NULL); #ifdef WIN30 /* PeekMessage has been changed in Win 3.0 so that GetKeyState() called from FCheckToggleKeyMessage() is really only valid if you've done a PeekMessage(...,PM_REMOVE) or GetMessage() first. That is, while the FCheckToggleKeyMessage() call might succeed above, it will NOT have set the vfShiftKey/vfCommandKey flags correctly -- so we do it here ..pault */ if (fToggledKey) FCheckToggleKeyMessage(&vmsgLast); #endif if (vmsgLast.hwnd != wwdCurrentDoc.wwptr) { /* Just in case a modeless dialog's window proc cares */ TranslateMessage((LPMSG)&vmsgLast); DispatchMessage((LPMSG)&vmsgLast); } #ifdef DBCS /* I hate it */ if (vmsgLast.message == WM_CHAR #ifdef JAPAN // We've been reported by one of OEM about LED not disapearing // problem. // they know it is bug of write. So I added this code from win2.x // write source. 27 sep 91 Yutakan || (vmsgLast.message == WM_KEYUP && vmsgLast.wParam == VK_KANA) #endif #ifdef KOREA || vmsgLast.message == WM_INTERIM #endif || vmsgLast.message == WM_KEYDOWN) { donteat = TRUE; return( TRUE ); } /* else Ok, you are KEYUP message. do normal */ #endif } else { switch (vmsgLast.message) { case WM_MOUSEMOVE: #ifdef KOREA case WM_NCMOUSEMOVE: #endif /* Process mouse move messages immediately; they are not really important. NOTE: This assumes that we have not captured all mouse events; in which case, they are important. */ DispatchMessage((LPMSG)&vmsgLast); case WM_TIMER: case WM_SYSTIMER: /* Remove timer and mouse move messages from the queue. */ GetMessage((LPMSG) &vmsgLast, NULL, NULL, NULL); break; default: Assert( *(pLocalHeap+1) == 0 ); /* Heap should still not be frozen */ return (TRUE); } } } Assert( *(pLocalHeap + 1) == 0 ); /* Heap should still not be frozen */ return (FALSE); } /* C P B E G I N L I N E */ typeCP CpBeginLine(pdl, cp) int *pdl; typeCP cp; { /* return the cp and dl containing cp */ int dlMin, dlLim; typeCP cpGuess; struct EDL *dndl; do { UpdateWw(wwCur, false); PutCpInWwVert(cp); /* Ensure cp on screen */ } while (pwwdCur->fDirty && !vfOutOfMemory); dndl = &(**(pwwdCur->hdndl))[0]; dlMin = 0; dlLim = pwwdCur->dlMac; while (dlMin + 1 < dlLim) { /* Binary search the ww */ int dlGuess = (dlMin + dlLim) >> 1; struct EDL *pedl = &dndl[dlGuess]; if ((cpGuess = pedl->cpMin) <= cp && (cpGuess != cp || pedl->ichCpMin == 0)) { /* guess is low or right */ dlMin = dlGuess; if (cp == cpGuess && pedl->cpMin + pedl->dcpMac != cp) break; /* Got it right */ } else /* Guess is high */ dlLim = dlGuess; } *pdl = dlMin; return dndl[dlMin].cpMin; } /* T O G G L E S E L */ ToggleSel(cpFirst, cpLim, fOn) typeCP cpFirst, cpLim; /* selection bounds */ int fOn; { /* Flip selection highlighting on and off */ extern int vfPMS; struct EDL *pedl; int dlT; int xpMin; int dxpRoom; int xpFirst; int xpLim; int fInsertPoint = (cpFirst == cpLim); if (vfSelHidden || cpFirst > cpLim || cpLim < /*cp0*/ cpMinCur || vfDead) return; if ( vfPictSel && vfPMS && (CachePara( docCur, cpFirst ), vpapAbs.fGraphics) && (vcpLimParaCache == cpLim) ) { /* Don't show inversion if we're moving or sizing a picture */ return; } dxpRoom = pwwdCur->xpMac - xpSelBar; xpMin = pwwdCur->xpMin; for (dlT = 0; dlT < pwwdCur->dlMac; dlT++) { typeCP cpMin, cpMac; /* line bounds */ pedl = &(**(pwwdCur->hdndl))[dlT]; if (!pedl->fValid) continue; cpMin = pedl->cpMin; if (cpMin > cpLim || cpMin > cpMacCur || (cpMin == cpLim && cpLim != cpFirst)) break; cpMac = cpMin + pedl->dcpMac; if (cpFirst <= cpMin && cpLim >= cpMac) { /* entire line is highlighted */ xpFirst = pedl->xpLeft; if (pedl->fGraphics && cpLim == cpMac && cpMin == cpMac) /* Special kludge for graphics paras */ xpLim = xpFirst; else xpLim = pedl->xpMac; } else if (fInsertPoint && cpFirst == cpMac && vfInsEnd) { /* Special kludge for an insert point at the end of a line */ xpLim = xpFirst = pedl->xpMac; } else if (cpFirst < cpMac) { /* Bite the bullet */ int dxp; typeCP cpBegin = CpMax(cpMin, cpFirst); typeCP cpEnd = CpMin(cpMac, cpLim); FormatLine(docCur, cpMin, pedl->ichCpMin, cpMacCur, flmSandMode); dxp = DxpDiff((int) (cpBegin - cpMin), (int) (cpEnd - cpBegin), &xpFirst); xpLim = xpFirst + dxp; /* reload pedl because procedures were called */ pedl = &(**(pwwdCur->hdndl))[dlT]; } else continue; /* now we have: pedl valid, xpFirst, xpLast describe highlight */ /* xpFirst = max(xpFirst, xpMin); */ xpLim = min(xpLim, xpMin + pedl->xpMac); if (xpLim > xpFirst) { if (xpLim > xpMin) { RECT rc; rc.top = pedl->yp - pedl->dyp; rc.left = xpSelBar + max(xpFirst - xpMin, 0); rc.bottom = pedl->yp; rc.right = xpSelBar + xpLim - xpMin; InvertRect( wwdCurrentDoc.hDC, (LPRECT)&rc); } } /* ToggleSel modified 7/28/85 -- added explicit check for fInsertPoint, since the xpLim == xpFirst test sometimes succeeded bogusly when a selection was extended backwards. BL */ else if (fInsertPoint && (xpLim == xpFirst)) /* Insertion point */ { /* vfli should usually be cached already, so will be fast. */ int yp = pedl->yp; FormatLine(docCur, cpMin, pedl->ichCpMin, cpMacCur, flmSandMode); if (fOn ^ vfInsertOn) { if (!vfInsertOn) { vxpCursLine = xpSelBar + xpFirst - xpMin; vypCursLine = yp - vfli.dypAfter; vdypCursLine = min(vfli.dypFont, vfli.dypLine - vfli.dypAfter); /* Start blinking in a while */ vfSkipNextBlink = TRUE; } DrawInsertLine(); } return; } } } /* T R A S H W W */ TrashWw(ww) { /* Invalidate all dl's in ww */ Assert( ww >= 0 && ww < wwMax ); InvalBand(&rgwwd[ww], 0, ypMaxAll); } /* I N V A L B A N D */ /* invalidate the band ypFirst, ypLast inclusive */ InvalBand(pwwd, ypFirst, ypLast) struct WWD *pwwd; int ypFirst, ypLast; { /* this covers some peculiar rects received from update event after a window resize by 1 pixel. CS */ if (ypLast < 0 || ypFirst == ypLast) return; pwwd->fDirty = true; pwwd->ypFirstInval = min(pwwd->ypFirstInval, ypFirst); pwwd->ypLastInval = max(ypLast, pwwd->ypLastInval); } /* T R A S H A L L W W S */ TrashAllWws() { /* trash them all */ int ww; #ifdef CASHMERE for (ww = 0; ww < wwMac; ++ww) TrashWw(ww); #else TrashWw( wwDocument ); #endif vfli.doc = docNil; /* Mark vfli invalid */ } /* T U R N O F F S E L */ TurnOffSel() { /* Remove sel highlighting from screen */ /* HideSel has no effect */ if (!vfSelHidden) { ToggleSel(selCur.cpFirst, selCur.cpLim, false); vfSelHidden = true; } } #ifdef JAPAN /* We handle IME convert window. */ //int FontHeight = 0; 01/19/93 // 03/29/93 int ImePosSize = 0; //01/19/93 int ImePosSize = 256; //03/29/93 #5484 BOOL bGetFocus = FALSE; // Handle to the IME communication block - 061491 Yukini HANDLE hImeMem = NULL; // to prevent unwanted caret traveling - 061591 Yukini BOOL bForceBlock = FALSE; // To avoid ilreagal setting for IME rectangle static BOOL bResetIMERect=FALSE; static BOOL bDefaultBlock = FALSE; //IME3.1J t-hiroyn /* * ForceImeBlock controls IME input display to the screen. * When Write program is writing string to the screen, the caret * doesn't move with string. After completing text display, * then caret is moved to appropriate position. During this * period, if user type something by using IME, char is displayed on the * screen. This makes mixing ugly result. This routine will * prevent this. Yukini */ void ForceImeBlock( hWnd, bFlag ) HWND hWnd; BOOL bFlag; { WORD x, y; LPIMESTRUCT lpmem; if (bForceBlock = bFlag) { if (lpmem = (LPIMESTRUCT)GlobalLock(hImeMem)) { /* Move bounding rectangle to out of the world */ lpmem->fnc = IME_MOVECONVERTWINDOW; x = GetSystemMetrics(SM_CXSCREEN); y = GetSystemMetrics(SM_CYSCREEN); lpmem->wParam = MCW_SCREEN | MCW_RECT; #if 1 //01/19/93 lpmem->lParam1 = (DWORD)MAKELONG(x+x/2,y+y/2); lpmem->lParam2 = (DWORD)MAKELONG(x+x/2,y+y/2); lpmem->lParam3 = (DWORD)MAKELONG(x*2,y*2); #else lpmem->lParam1 = (DWORD)MAKELONG(x+1,y+1); lpmem->lParam2 = (DWORD)MAKELONG(x+1,y+1); lpmem->lParam3 = (DWORD)MAKELONG(x*2,y*2); #endif GlobalUnlock(hImeMem); MySendIMEMessageEx(hWnd,MAKELONG(hImeMem,NULL)); bResetIMERect = FALSE; } } } void DefaultImeBlock(hWnd) HWND hWnd; { LPIMESTRUCT lpmem; if (bDefaultBlock == FALSE) { if (lpmem = (LPIMESTRUCT)GlobalLock(hImeMem)) { /* Move bounding rectangle to default */ lpmem->fnc = IME_MOVECONVERTWINDOW; lpmem->wParam = MCW_DEFAULT; GlobalUnlock(hImeMem); MySendIMEMessageEx(hWnd,MAKELONG(hImeMem,NULL)); bResetIMERect = FALSE; } } } /* use these veriables to optimize IME call. This will prevent task switching * overhead. - Yukini */ static RECT rcOldRect = {-1, -1, -1, -1}; static DWORD dwCurpos = -1; static WORD wModeMCW = MCW_DEFAULT; void SetIMEConvertWindow(hWnd,x,y,bFlag) HWND hWnd; int x,y; BOOL bFlag; { LPIMESTRUCT lpmem; //Yukini:HANDLE hIMEBlock; DWORD dwXY = MAKELONG(x,y); BOOL bRetSendIme; RECT rcRect; extern BOOL bImeCnvOpen; // Yutakan:08/06/91 /* Do nothing if in text drawing to the screen */ if (bForceBlock) return; /* we allocate the Ime communication area. freeing of this * area will be done by wrap up routine MmwDestroy() of Quit.C. * This will improve the performance than previous code. - Yukini */ if (hImeMem == NULL) { if ((hImeMem = GlobalAlloc(GMEM_MOVEABLE|GMEM_SHARE|GMEM_LOWER, (DWORD)sizeof(IMESTRUCT))) == NULL) return; // something wrong } //Yukini: /* Get comunication area with IME */ //Yukini: hIMEBlock=GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE | GMEM_LOWER, //Yukini: (DWORD)sizeof(IMESTRUCT)); //Yukini: if(!hIMEBlock) return; if(!bGetFocus) bFlag = FALSE; GetWindowRect(hWnd,&rcRect); // [yutakan:08/06/91] IF out of Window Rect, force MCW_DEFAULT. // if(rcRect.top > y || rcRect.bottom < y) bFlag = TRUE; // if (bFlag) { /* Add ResetIMERect check . If we've not done MOVECONVERTWINDOW after ** ForceIMEblock(), don't pass by SendIMEMessage to avoid ilreagal setting ** for bounding rectangle. [Yutakan.] */ // bResetIMERect FALSE when just after ForceImeBlock() if ( bResetIMERect == TRUE && dwCurpos == dwXY && EqualRect(&rcRect, &rcOldRect)){ //OutputDebugString("Write:optimized\r\n"); return; } } else dwCurpos = -1; // invalidate cache //Yukini: lpmem = (LPIMESTRUCT)GlobalLock(hIMEBlock); //Yukini: lpmem->fnc = IME_MOVECONVERTWINDOW; //Yukini: lpmem->wParam = bFlag?MCW_WINDOW:MCW_DEFAULT; //Yukini: lpmem->lParam1 = (DWORD)MAKELONG(x,y); //Yukini: GlobalUnlock(hIMEBlock); //Yukini: SendIMEMessage(hWnd,MAKELONG(hIMEBlock,NULL)); //Yukini: GlobalFree(hIMEBlock); #if defined(JAPAN) & defined(IME_HIDDEN) //IME3.1J if(vfImeHidden) { DWORD dwXY1, dwXY2, dwXY3; int x1,x2,x3,y1,y2,y3; RECT hiRect; //12/28/92 if(whileUndetermine == TRUE) // we are managing IR_UNDETERMINE return; CopyRect(&hiRect, &rcRect); if(x < 0) x = 0; x1 = x + hiRect.left; y1 = (vypCursLine - vdypCursLine) + hiRect.top; if(y1 < 0) y1 = 0; x2 = hiRect.left; if(HiddenTextTop == 0) y2 = y1; else y2 = hiRect.top + HiddenTextTop; x3 = hiRect.right; if(vdypCursLine <= 0) y3 = y1 + (19+1); else { if(HiddenTextBottom == 0) y3 = y1 + (vdypCursLine+1); else y3 = hiRect.top + HiddenTextBottom + 1; if(y3 < (y1 + (vdypCursLine+1))) y3 = y1 + (vdypCursLine+1); } if(y2 > y1) y2 = y1; if(x3 <= x1 || y3 <= y1) goto dontHidden; if(x3 <= x2 || y3 <= y2) goto dontHidden; dwXY1 = MAKELONG(x1, y1); dwXY2 = MAKELONG(x2, y2); dwXY3 = MAKELONG(x3, y3); if (lpmem = (LPIMESTRUCT)GlobalLock(hImeMem)) { lpmem->fnc = IME_MOVECONVERTWINDOW; lpmem->wParam = MCW_HIDDEN; dwCurpos = dwXY; CopyRect(&rcOldRect, &rcRect); lpmem->lParam1 = dwXY1; lpmem->lParam2 = dwXY2; lpmem->lParam3 = dwXY3; GlobalUnlock(hImeMem); bResetIMERect = TRUE; if(MySendIMEMessageEx(hWnd,MAKELONG(hImeMem,NULL))) { vfImeHidden = 1; //Hidden OK return; } else { vfImeHidden = 0; //Hidden ERR we set MCW_WINDOW } } } dontHidden: if(selUncpLim > selUncpFirst) { return; } #endif if (lpmem = (LPIMESTRUCT)GlobalLock(hImeMem)) { lpmem->fnc = IME_MOVECONVERTWINDOW; if ((lpmem->wParam = bFlag ? MCW_WINDOW : MCW_DEFAULT) == MCW_WINDOW) { /* update previous state */ dwCurpos = dwXY; CopyRect(&rcOldRect, &rcRect); lpmem->lParam1 = dwXY; wModeMCW = MCW_WINDOW; //01/25/93 } else { wModeMCW = MCW_DEFAULT; //01/25/93 } GlobalUnlock(hImeMem); if(FALSE == MySendIMEMessageEx(hWnd,MAKELONG(hImeMem,NULL))) wModeMCW = MCW_DEFAULT; //01/25/93 bResetIMERect = TRUE; // yutakan:08/06/91 } } HANDLE hImeSetFont = NULL; BOOL bImeFontEx = FALSE; //T-HIROYN 02/25/93 SetImeFont(HWND hWnd) { LPIMESTRUCT lpmem; HANDLE hImeLogfont; LOGFONT lf; LPLOGFONT lpLogfont; HANDLE hfont; void IMEManage(BOOL); //Get IME use LOGFONT if (FALSE == GetLogfontImeFont((LPLOGFONT)(&lf))) return; if(TRUE == bImeFontEx) { if ((hImeLogfont = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE | GMEM_LOWER, (DWORD)sizeof(LOGFONT))) == NULL) return; // something wrong if (lpmem = (LPIMESTRUCT)GlobalLock(hImeMem)) { lpmem->fnc = IME_SETCONVERSIONFONTEX; lpmem->lParam1 = 0L; if (lpLogfont = (LPLOGFONT)GlobalLock(hImeLogfont)) { bltbx((LPLOGFONT)(&lf), lpLogfont, sizeof(LOGFONT)); lpmem->lParam1 = MAKELONG(hImeLogfont,NULL); GlobalUnlock(hImeLogfont); } GlobalUnlock(hImeMem); MySendIMEMessageEx(hWnd,MAKELONG(hImeMem,NULL)); } GlobalFree(hImeLogfont); } else { hfont = CreateFontIndirect(&lf); if (lpmem = (LPIMESTRUCT)GlobalLock(hImeMem)) { lpmem->fnc = IME_SETCONVERSIONFONT; lpmem->wParam = hfont; GlobalUnlock(hImeMem); MySendIMEMessageEx(hWnd,MAKELONG(hImeMem,NULL)); } // prev font deleate; if(hImeSetFont != NULL) { HDC hdc; HANDLE oldhfont; hdc = GetDC(NULL); oldhfont = SelectObject(hdc,hImeSetFont); SelectObject(hdc,oldhfont); DeleteObject(hImeSetFont); ReleaseDC(NULL, hdc); } hImeSetFont = hfont; } //display: bResetIMERect = FALSE; IMEManage( FALSE ); } int GetLogfontImeFont(lplf) LPLOGFONT lplf; { extern struct FCE *vpfceScreen; extern struct CHP vchpSel; struct CHP chp; blt(&vchpSel, &chp, cwCHP); /* CHP for use in comparisons */ //change CHARSET to KANJI_CHARSET { int ftc; if( ftcNil != (ftc = GetKanjiFtc(&chp))) { ApplyCLooks(&chp, sprmCFtc, ftc); } } LoadFont(docCur, &chp, mdFontJam); bltbcx(lplf, 0, sizeof(LOGFONT)); GetObject(vpfceScreen->hfont, sizeof(LOGFONT), lplf); //Ime SETCONVERSIONWINDOW set point (vypCursLine - ImePosSize) ImePosSize = vfmiScreen.dypBaseline + vfli.dypBase; if(chp.hpsPos != 0 ) { if (chp.hpsPos < hpsNegMin) ImePosSize += ypSubSuper; else ImePosSize -= ypSubSuper; } return TRUE; } void IMEManage( bFlag ) BOOL bFlag; /* Flag to indicate real default or virtual default in case of requesting IME convert line to be default. Real default (value TRUE) is selected when I am loosing the focus. In this case, IME convert line will be default. Virtual default (value FALSE) is selected when I lost a caret position. In this case, IME convert line will be out of the screen. You can type characters, but not displayed to the screen correctly. Yukini */ { int x,y; BOOL bCE = ConvertEnable; /*IME3.1J if(!FontHeight) { TEXTMETRIC tm; GetTextMetrics(wwdCurrentDoc.hDC,&tm); FontHeight = tm.tmHeight; } */ x = vxpCursLine; // y = vypCursLine-(vdypCursLine+FontHeight)/2; IME3.1J // y = vypCursLine - FontHeight; if(ImePosSize > vdypCursLine) y = vypCursLine - vdypCursLine; else y = vypCursLine - ImePosSize; if (x < 0 || y < 0) bCE = FALSE; /* Sometime caret position will be less than zero. Do no set IME window in this case. Yukini */ #if defined(JAPAN) & defined(IME_HIDDEN) //IME3.1J if (bCE == FALSE && bFlag == FALSE && bForceBlock == FALSE && 0 == vfImeHidden) { #else if (bCE == FALSE && bFlag == FALSE && bForceBlock == FALSE) { #endif // get out of the world, babe. //IME3.1J if( vypCursLine > 0 && ImePosSize > vypCursLine ) { DefaultImeBlock( wwdCurrentDoc.wwptr); //t-hiroyn bDefaultBlock = TRUE; //IME3.1J } else { ForceImeBlock( wwdCurrentDoc.wwptr, TRUE ); bForceBlock = FALSE; bDefaultBlock = FALSE; //IME3.1J } // yutakan:08/16/91 dwCurpos = 1; // invalidate optimize cache dwCurpos = -1; } else { SetIMEConvertWindow(wwdCurrentDoc.wwptr, x, y, bCE); bDefaultBlock = FALSE; //IME3.1J } } #endif // JAPAN #if defined(JAPAN) & defined(IME_HIDDEN) //IME3.1J //IME3.1J call by MENU selecting. ChangeImeConversionMode() { extern BOOL bImeCnvOpen; vfImeHidden = (vfImeHidden ? 0 : 1); // 12/28/92 if(vfImeHidden) // bImeCnvOpen = TRUE; bResetIMERect = FALSE; IMEManage( FALSE ); } #endif /* D R A W I N S E R T L I N E */ DrawInsertLine() { #if defined(JAPAN) & defined(DBCS_IME) extern BOOL bImeCnvOpen; #if defined(IME_HIDDEN) extern BOOL ImeClearInsert; #endif #endif /* Draw (in Xor mode) a vertical bar at screen position v*CursLine */ /* Toggles both the display and the vfInsertOn flag */ /* Adjustments in cursor draw must be reflected in DisplayFli, above */ /* Last-minute correction for a bug: assure that the insert line does not extend above ypMin */ if (!vfInsertOn && vdypCursLine > vypCursLine - wwdCurrentDoc.ypMin) vdypCursLine = vypCursLine - wwdCurrentDoc.ypMin; /* Tell GDI to invert the caret line */ //#3221 01/25/93 #if defined(JAPAN) & defined(DBCS_IME) #if defined(IME_HIDDEN) if(ImeClearInsert || (bImeCnvOpen && wModeMCW == MCW_WINDOW) ) { #else if(bImeCnvOpen && wModeMCW == MCW_WINDOW) { #endif if(vfInsertOn) { PatBlt( wwdCurrentDoc.hDC, vxpCursLine, vypCursLine - vdypCursLine, 2, vdypCursLine , DSTINVERT ); vfInsertOn = 1 - vfInsertOn; } } else { PatBlt( wwdCurrentDoc.hDC, vxpCursLine, vypCursLine - vdypCursLine, 2, vdypCursLine , DSTINVERT ); vfInsertOn = 1 - vfInsertOn; } #else PatBlt( wwdCurrentDoc.hDC, vxpCursLine, vypCursLine - vdypCursLine, 2, vdypCursLine , DSTINVERT ); vfInsertOn = 1 - vfInsertOn; #endif /*T-HIROYN sync 3.0 disp.c */ #ifdef JAPAN /* KenjiK '90-10-30 */ if(bClearCall) { if((vxpCursLine>=0) && (vxpCursLine<=wwdCurrentDoc.xpMac) && (vypCursLine>=0) && (vypCursLine<=wwdCurrentDoc.ypMac)) ConvertEnable = TRUE; } IMEManage( FALSE ); #endif } /* C L E A R I N S E R T L I N E */ ClearInsertLine() { #if defined(JAPAN) & defined(DBCS_IME) /* So we do some IME manage when clearning the line */ if((vxpCursLine<0) || (vxpCursLine>=wwdCurrentDoc.xpMac) || (vypCursLine<0) || (vypCursLine>=wwdCurrentDoc.ypMac)) { ConvertEnable = FALSE; //OutputDebugString("ClearInsertLine\r\n"); } bClearCall = FALSE; if ( vfInsertOn) DrawInsertLine(); else IMEManage( FALSE ); bClearCall = TRUE; #else if ( vfInsertOn) DrawInsertLine(); #endif } #if defined(JAPAN) & defined(IME_HIDDEN) //IME3.1J UndetermineTextOut(HDC hDC, int xp, int yp, PCH ptr, int cch, LPSTR Attrib) { int Length; long rgbBack; long rgbText; int bkMode; PCH ptr1 = ptr; TEXTMETRIC tm; GetTextMetrics(hDC, &tm); bkMode = SetBkMode(hDC, OPAQUE); rgbBack = GetBkColor(hDC); rgbText = GetTextColor(hDC); while( cch ) { switch((*Attrib) & 0x03) { case 1: SetBkColor(hDC, GetNearestColor(hDC, rgbIMEHidden[IMESPOT])); SetTextColor(hDC, GetNearestColor(hDC, rgbIMEHidden[IMESPOTTEXT])); // 12/28/92 if(HiddenTextTop == 0) HiddenTextTop = yp; if(HiddenTextTop > yp) HiddenTextTop = yp; if(HiddenTextBottom == 0) HiddenTextBottom = yp + tm.tmHeight; if(HiddenTextBottom > (yp + tm.tmHeight)) HiddenTextBottom = yp + tm.tmHeight; break; case 0: SetBkColor(hDC, GetNearestColor(hDC, rgbIMEHidden[IMEINPUT])); SetTextColor(hDC, GetNearestColor(hDC, rgbIMEHidden[IMEINPUTTEXT])); break; case 2: default: SetBkColor(hDC, GetNearestColor(hDC, rgbIMEHidden[IMEOTHER])); SetTextColor(hDC, GetNearestColor(hDC, rgbIMEHidden[IMEOTHERTEXT])); break; } Length = ( (IsDBCSLeadByte((BYTE)(*ptr1)) ) ? 2 : 1 ); TextOut(hDC, xp, yp, ptr1, Length); xp += LOWORD(GetTextExtent(hDC, ptr1, Length)); xp-=tm.tmOverhang; ptr1+=Length; Attrib+=Length; AttribPos+=Length; cch-=Length; } SetBkColor(hDC,rgbBack); SetTextColor(hDC,rgbText); SetBkMode(hDC, bkMode); } UndetermineString(HDC hDC, int xp, int yp, PCH ptr, int cch, typeCP cpFirst, typeCP cpEnd) { int Length; int len = cch; PCH ptr1; TEXTMETRIC tm; GetTextMetrics(hDC, &tm); ptr1 = ptr; if((cpEnd <= selUncpFirst) || (cpFirst >= selUncpLim)) TextOut(hDC, xp, yp, ptr1, len); else { Attrib = GlobalLock(hImeUnAttrib); if(cpFirst < selUncpFirst) { Length = selUncpFirst - cpFirst; TextOut(hDC, xp, yp, ptr1, Length); xp+=LOWORD(GetTextExtent(hDC, ptr1, Length)); xp-=tm.tmOverhang; len-=Length; ptr1+=Length; } if(selUncpLim <= cpEnd) { if(cpFirst > selUncpFirst) { Length = (int)(selUncpLim - cpFirst); Attrib += (cpFirst-selUncpFirst); } else { Length = (int)(selUncpLim - selUncpFirst); } UndetermineTextOut(hDC, xp, yp, ptr1, Length, Attrib); AttribPos = 0; xp+=LOWORD(GetTextExtent(hDC, ptr1, Length)); xp-=tm.tmOverhang; ptr1+=Length; len-=Length; if ( Length = (int)(cpEnd - selUncpLim) ) { TextOut(hDC, xp, yp, ptr1, Length); } } else if(Attrib) { if(cpFirst > selUncpFirst) { Attrib += (cpFirst-selUncpFirst); } UndetermineTextOut(hDC, xp, yp, ptr1,len, Attrib); } GlobalUnlock(hImeUnAttrib); Attrib = NULL; } } DoHiddenRectSend() { bResetIMERect = FALSE; IMEManage( FALSE ); } GetImeHiddenTextColors() { COLORREF NEAR PASCAL GetIMEColor(WORD); int i; for (i = 0; i < IMEDEFCOLORS; i++) rgbIMEHidden[i] = GetIMEColor(i); } /* GetIMEColor - Retrieve IME color scheme from [colors] in win.ini */ #define MAX_SCHEMESIZE 190 COLORREF NEAR PASCAL GetIMEColor(WORD wIndex) { static char *pszWinStrings[IMEDEFCOLORS] = { "IMESpot", "IMESpotText", "IMEInput", "IMEInputText", "IMEOther", "IMEOtherText"}; BYTE szTemp[MAX_SCHEMESIZE]; LPBYTE szLP; COLORREF colRGB; int i, v; if (wIndex >= IMEDEFCOLORS) return RGB(0,0,0); GetProfileString("colors", pszWinStrings[wIndex], "", szTemp, MAX_SCHEMESIZE); if (!lstrlen(szTemp)) { switch(wIndex) { case IMESPOT: return GetSysColor(COLOR_HIGHLIGHTTEXT); case IMESPOTTEXT: return GetSysColor(COLOR_HIGHLIGHT); case IMEINPUT: return GetSysColor(COLOR_WINDOW); case IMEINPUTTEXT: return GetSysColor(COLOR_HIGHLIGHT); case IMEOTHER: return GetSysColor(COLOR_WINDOW); case IMEOTHERTEXT: return GetSysColor(COLOR_HIGHLIGHT); } } colRGB = RGB(0,0,0); szLP = szTemp; for (i = 0; i < 3; i++) { v = 0; while(*szLP < '0' || *szLP > '9') szLP++; while(*szLP >= '0' && *szLP <= '9') v = v * 10 + (*szLP++ - '0'); switch(i) { case 0: colRGB |= RGB(v,0,0); break; case 1: colRGB |= RGB(0,v,0); break; case 2: colRGB |= RGB(0,0,v); break; } } return colRGB; } #endif