/************************************************************/ /* Windows Write, Copyright 1985-1992 Microsoft Corporation */ /************************************************************/ /* insert2.c - MW insertion routines */ #define NOGDICAPMASKS #define NOCLIPBOARD #define NOCTLMGR #define NOWINSTYLES #ifndef KOREA #define NOSYSMETRICS #endif #define NOMENUS #define NOICON #define NOKEYSTATE #define NOSYSCOMMANDS #define NOSHOWWINDOW #define NOATOM #define NOBRUSH #define NOCREATESTRUCT #define NOFONT #define NOCLIPBOARD #define NODRAWTEXT #define NOPEN #define NOREGION #define NOSCROLL #define NOMB #define NOOPENFILE #define NOSOUND #define NOCOMM #define NOWH #define NOWINOFFSETS #define NOWNDCLASS #include #include "mw.h" #include "doslib.h" #include "propdefs.h" #include "dispdefs.h" #include "fmtdefs.h" #include "cmddefs.h" #include "wwdefs.h" #include "docdefs.h" #define NOKCCODES #include "ch.h" #include "winddefs.h" #include "fontdefs.h" #include "debug.h" #ifdef DEBUG extern int vTune; #endif #ifdef KOREA /* Use in KcInputNext..., 90.12.27 sangl */ extern int IsInterim; #endif extern int vdlIns; extern int vxpIns; extern int vfTextBltValid; extern int vdypCursLineIns; extern struct FLI vfli; extern struct SEL selCur; extern int vdypBase; extern int vypBaseIns; extern int vxpMacIns; extern int vdypAfter; extern typeCP cpInsert; /* Beginning cp of insert block */ extern int ichInsert; /* Number of chars used in rgchInsert */ extern typeCP cpMinCur; extern typeCP cpMacCur; extern int docCur; extern struct CHP vchpInsert; extern struct WWD rgwwd[]; extern struct WWD *pwwdCur; extern int wwCur; extern int wwMac; extern int vfSeeSel; extern int vfFocus; #ifdef DBCS extern int donteat; /* see disp.c */ #endif unsigned WHsecGetTime() { /* Get the time (in hundredths of seconds) into a normalized word */ /* Ignore current hour, just minutes/seconds/hundredths */ struct TIM tim; OsTime( &tim ); return ( (unsigned)tim.minutes * 6000 + (unsigned)tim.sec * 100 + (unsigned)tim.hsec ); } /* V A L I D A T E T E X T B L T */ ValidateTextBlt() { /* Validate info sufficient for TextOut and ScrollCurWw calls in Insert */ /* In particular: vdlIns, vxpIns, vdypBase, vdypFont */ int NEAR FCpInsertInDl( typeCP, struct EDL * ); extern int vfInsFontTooTall; extern struct FMI vfmiScreen; extern int ferror; extern int vfInsEnd; int dypFontAscent; int dypFontDescent; register struct EDL *pedl; int yp; typeCP cpBegin; /* Routine assumes ww == wwDocument */ Assert( pwwdCur == &wwdCurrentDoc ); { /* Look for a valid dl containing selCur.cpFirst */ /* We should usually be able to find one */ int dlGuess = vdlIns; struct EDL *dndl=&(**wwdCurrentDoc.hdndl)[0]; if ( (dlGuess < wwdCurrentDoc.dlMac) && FCpInsertInDl( selCur.cpFirst, pedl = &dndl[ dlGuess ] )) { /* vdlIns is already correct */ cpBegin = pedl->cpMin; } else { /* Search for valid dl containing insertion point */ /* Use linear search, all dl's may not be valid */ int dl; for ( pedl = dndl, dl = 0; dl < wwdCurrentDoc.dlMac; dl++, pedl++ ) { if ( FCpInsertInDl( selCur.cpFirst, pedl ) ) { /* Found it */ vdlIns = dl; cpBegin = pedl->cpMin; break; } } if (dl >= wwdCurrentDoc.dlMac) { /* No valid dl contains the cp -- must update whole screen */ cpBegin = CpBeginLine( &vdlIns, selCur.cpFirst ); } } } /* Special case for splat: locate insert point at end of previous line */ pedl = &(**wwdCurrentDoc.hdndl) [vdlIns]; if (pedl->fSplat && (vdlIns > 0) && selCur.cpFirst == pedl->cpMin) { /* Splat on current line */ /* Check for pedl->cpMin above is necessary for the special case */ /* in which the QD buffer is at the beginning of the splat line */ pedl--; if (pedl->fValid && !pedl->fSplat) { /* Locate cursor at end of previous line */ vdlIns--; cpBegin = pedl->cpMin; ClearInsertLine(); selCur.fEndOfLine = TRUE; vfInsEnd = TRUE; ToggleSel( selCur.cpFirst, selCur.cpLim, TRUE ); } else { pedl++; goto CheckEnd; } } else { /* Eliminate end of line cursor if not before a splat */ CheckEnd: if (selCur.fEndOfLine) { ClearInsertLine(); selCur.fEndOfLine = FALSE; vfInsEnd = FALSE; ToggleSel( selCur.cpFirst, selCur.cpLim, TRUE ); } } /* Assure we obtained a good vdlIns */ Assert( vdlIns < wwdCurrentDoc.dlMac ); Assert( ((selCur.cpFirst >= pedl->cpMin) && (selCur.cpFirst <= pedl->cpMin + pedl->dcpMac))); FormatLine(docCur, cpBegin, 0, cpMacCur, flmSandMode); vxpIns = DxpDiff(0, (int) (selCur.cpFirst - cpBegin), &vxpIns) + vfli.xpLeft + xpSelBar - wwdCurrentDoc.xpMin; vdypBase = vfli.dypBase; vdypAfter = vfli.dypAfter; vdypCursLineIns = min(vfli.dypFont, vfli.dypLine - vdypAfter); vxpMacIns = vfli.xpMarg; LoadFont(docCur, &vchpInsert, mdFontChk); ferror = FALSE; // running out of memory here is OK. Must clear this // or important calls will needlessly fail. // (8.6.91) D. Kent vypBaseIns = (**wwdCurrentDoc.hdndl) [vdlIns].yp - vdypBase; dypFontAscent = vfmiScreen.dypAscent + vfmiScreen.dypLeading; dypFontDescent = vfmiScreen.dypDescent; if (vchpInsert.hpsPos) { if (vchpInsert.hpsPos < hpsNegMin) { vypBaseIns -= ypSubSuper; /* Superscript */ dypFontAscent += ypSubSuper; } else { vypBaseIns += ypSubSuper; /* Subscript */ dypFontDescent += ypSubSuper; } } /* Set if current font is too tall to display on insert line */ vfInsFontTooTall = (imax( dypFontAscent, vfli.dypLine - vfli.dypBase ) + imax( dypFontDescent, vfli.dypBase )) > vfli.dypLine; vfTextBltValid = true; } int NEAR FCpInsertInDl( cp, pedl ) typeCP cp; register struct EDL *pedl; { /* Return TRUE if insert point cp is in dl & dl is valid, FALSE otherwise */ if ( (pedl->fValid) && (cp >= pedl->cpMin) ) { /* dl is valid & cp is at or below starting cp of dl */ if ( (cp < pedl->cpMin + pedl->dcpMac) || ((cp == cpMacCur) && (cp == pedl->cpMin + pedl->dcpMac)) ) { /* cp is on line dl */ if (pedl->yp <= wwdCurrentDoc.ypMac) { /* dl is complete, i.e. not cut off at bottom of window */ return TRUE; } } } return FALSE; } #ifdef FOOTNOTES /* F E D I T F T N */ int FEditFtn(cpFirst, cpLim) typeCP cpFirst, cpLim; { /* Return true if edit includes an end of footnote mark */ struct FNTB **hfntb; typeCP cp; if ((hfntb = HfntbGet(docCur)) == 0 || cpLim < (cp = (*hfntb)->rgfnd[0].cpFtn)) return false; if (cpFirst < cp || CpRefFromFtn(docCur, cpFirst) != CpRefFromFtn(docCur, cpLim)) { Error(IDPMTFtnLoad); return fTrue; } return fFalse; } #endif /* FOOTNOTES */ /* U P D A T E O T H E R W W S */ #ifdef CASHMERE UpdateOtherWws(fInval) BOOL fInval; { int ww = 0; struct WWD *pwwd = rgwwd; {{ while (ww < wwMac) { if (ww != wwCur && (pwwd++)->doc == docCur) {{ typeCP cpI = cpInsert + ichInsert; typeCP cpH = CpMax(cpI, cpInsLastInval); typeCP cpL = CpMin(cpInsLastInval, cpI); typeCP dcp; if ((dcp = cpH - cpL) != cp0 || fInval) AdjustCp(docCur, cpL, dcp, dcp); cpInsLastInval = cpI; return; }} ww++; } }} } #endif /* CASHMERE */ /* K C I N P U T N E X T K E Y */ KcInputNextKey() { /* Get next available key/event from Windows */ /* Returns key code or kcNil if a non-key event */ /* Updates the screen if there is time before events arrive */ extern HWND vhWnd; /* WINDOWS: Handle of the current document display window*/ extern MSG vmsgLast; /* WINDOWS: last message gotten */ extern int vfInsLast; extern int vfCommandKey; extern int vfShiftKey; extern int vfAwfulNoise; int i; int kc; for ( ;; ) { if ( FImportantMsgPresent() ) goto GotMessage; /* No events waiting -- if none show up for a while, update the screen */ #ifdef CASHMERE UpdateOtherWws( FALSE ); #endif { /* Dawdle for a time, looking for keys, before updating the screen */ unsigned WHsecGetTime(); unsigned wHsec; wHsec = WHsecGetTime(); do { if ( FImportantMsgPresent() ) goto GotMessage; } while ( WHsecGetTime() - wHsec < dwHsecKeyDawdle ); } #ifdef DEBUG if (vTune) continue; /* Bag background update while debugging to see how we fare */ #endif Scribble( 8, 'U' ); ClearInsertLine(); UpdateWw(wwCur, fTrue); ToggleSel(selCur.cpFirst, selCur.cpLim, fTrue); Scribble( 8, ' ' ); if ( FImportantMsgPresent() ) goto GotMessage; vfAwfulNoise = FALSE; PutCpInWwHz( selCur.cpFirst ); EndLongOp( NULL ); if ( FImportantMsgPresent() ) goto GotMessage; if ( !vfTextBltValid ) ValidateTextBlt(); /* Nothing has happened for a while, let's blink the cursor */ { unsigned WHsecGetTime(); unsigned wHsecBlink = GetCaretBlinkTime() / 10; unsigned wHsecLastBlink=WHsecGetTime() + wHsecBlink/2; for ( ;; ) { unsigned wHsecT; if ( FImportantMsgPresent() ) goto GotMessage; /* Another app may have stolen the focus away from us while we called PeekMessage(), in which case we should end Alpha mode. */ if (!vfFocus) return kcNil; UpdateDisplay( TRUE ); if ( (wHsecT = WHsecGetTime()) - wHsecLastBlink >= wHsecBlink ) { DrawInsertLine(); wHsecLastBlink = wHsecT; } } } continue; GotMessage: #ifdef DBCS #ifdef KOREA /* Need to GetMessage for F-Key during Interim,90.12.27 sangl */ if ( ((kc=KcAlphaKeyMessage( &vmsgLast )) != kcNil) || IsInterim) #else if ((kc=KcAlphaKeyMessage( &vmsgLast )) != kcNil) #endif { if (vmsgLast.wParam == VK_EXECUTE) return( kcNil ); if (vmsgLast.message == WM_KEYDOWN) { switch (kc) { default: break; case kcAlphaVirtual: /* This means we can't anticipate the key's meaning before translation */ #ifdef KOREA /* Need GetMesssage for direc keys, etc during interim 90.12.26 sangl */ if ( FNonAlphaKeyMessage( &vmsgLast, FALSE ) && !IsInterim) #else if ( FNonAlphaKeyMessage( &vmsgLast, FALSE ) ) #endif /* This is a non-alpha key message */ return kcNil; if ( !donteat ) { GetMessage( (LPMSG)&vmsgLast, NULL, 0, 0 ); } else { /* not eat message because FimportantMsgPresent has ** eaten KEY_DOWN message */ donteat = FALSE; } /* ** When KKAPP window open, this message is offten wrong. ** we must check it is really WM_KEYDOWN */ #ifdef KOREA /* for level 3, 90.12.26 sangl */ if ((vmsgLast.message == WM_CHAR) || (vmsgLast.message == WM_INTERIM)) { #else if ( vmsgLast.message == WM_CHAR ) { #endif return vmsgLast.wParam; } if ( vmsgLast.message != WM_KEYDOWN ) { return kcNil; } TranslateMessage( &vmsgLast ); continue; } /* switch kc */ } /* if keydown */ if ( !donteat ) { GetMessage( (LPMSG) &vmsgLast, NULL, 0, 0 ); #ifdef KOREA /* for level 3, 91.1.21 by Sangl */ if ( (vmsgLast.message==WM_CHAR)||(vmsgLast.message==WM_INTERIM) ) { #else if ( vmsgLast.message == WM_CHAR ) { #endif return vmsgLast.wParam; } } /* dont eat */ else { donteat = FALSE; } } /* if kc != kcNil */ #else if ((kc=KcAlphaKeyMessage( &vmsgLast )) != kcNil) { if (vmsgLast.message == WM_KEYDOWN) { switch (kc) { default: break; case kcAlphaVirtual: /* This means we can't anticipate the key's meaning before translation */ if ( FNonAlphaKeyMessage( &vmsgLast, FALSE ) ) /* This is a non-alpha key message */ return kcNil; GetMessage( (LPMSG)&vmsgLast, NULL, 0, 0 ); TranslateMessage( &vmsgLast ); continue; } } GetMessage( (LPMSG) &vmsgLast, NULL, 0, 0 ); } #endif return kc; } /* End of for ( ;; ) loop to process messages */ } #ifdef KOREA /* 90.12.29 sangl */ KcInputNextHan() { /* Get next available key/event from Windows */ /* Returns key code or kcNil if a non-key event */ /* Updates the screen if there is time before events arrive */ extern HWND vhWnd; /* WINDOWS: Handle of the current document display window*/ extern MSG vmsgLast; /* WINDOWS: last message gotten */ extern int vfInsLast; extern int vfCommandKey; extern int vfShiftKey; extern int vfAwfulNoise; int i; int kc; int tmp; tmp = vfInsLast; tmp = vfCommandKey; tmp = vfShiftKey; tmp = vfAwfulNoise; tmp = vmsgLast.message; tmp = vmsgLast.wParam; for ( ;; ) { if ( FImportantMsgPresent() ) goto GotMessage; /* No events waiting -- if none show up for a while, update the screen */ { /* Dawdle for a time, looking for keys, before updating the screen */ unsigned WHsecGetTime(); unsigned wHsec; wHsec = WHsecGetTime(); do { if ( FImportantMsgPresent() ) goto GotMessage; } while ( WHsecGetTime() - wHsec < dwHsecKeyDawdle ); } #ifdef DEBUG if (vTune) continue; /* Bag background update while debugging to see how we fare */ #endif if ( FImportantMsgPresent() ) goto GotMessage; /* vfAwfulNoise = FALSE; PutCpInWwHz( selCur.cpFirst ); EndLongOp( NULL );*/ if ( FImportantMsgPresent() ) goto GotMessage; /* Nothing has happened for a while, let's blink the cursor */ { unsigned WHsecGetTime(); unsigned wHsecBlink = GetCaretBlinkTime() / 10; unsigned wHsecLastBlink=WHsecGetTime() + wHsecBlink/2; KillTimer( vhWnd, tidCaret ); for ( ;; ) { unsigned wHsecT; if ( FImportantMsgPresent() ) { SetTimer( vhWnd, tidCaret, GetCaretBlinkTime(), (FARPROC)NULL ); goto GotMessage; } /* Another app may have stolen the focus away from us while we called PeekMessage(), in which case we should end Alpha mode. */ if (!vfFocus) { SetTimer( vhWnd, tidCaret, GetCaretBlinkTime(), (FARPROC)NULL ); return kcNil; } if ( (wHsecT = WHsecGetTime()) - wHsecLastBlink >= wHsecBlink ) { DrawInsertLine(); wHsecLastBlink = wHsecT; } } } continue; GotMessage: if( vmsgLast.wParam == VK_EXECUTE ) vmsgLast.wParam = VK_RETURN; /* To GetMessage for Func/Ctrl/direc keys, 90.4.4, Sang-Weon */ if ( ((kc=KcAlphaKeyMessage(&vmsgLast))!=kcNil) || IsInterim ) { if( vmsgLast.wParam == VK_EXECUTE ) return kcNil; if (vmsgLast.message == WM_KEYDOWN) { switch (kc) { default: break; case kcAlphaVirtual: /* This means we can't anticipate the key's meaning before translation */ if ( FNonAlphaKeyMessage(&vmsgLast, FALSE) && !IsInterim ) /* This is a non-alpha key message */ return kcNil; if ( !donteat ) { GetMessage( (LPMSG)&vmsgLast, NULL, 0, 0 ); } else { /* not eat message because FimportantMsgPresent has ** eaten KEY_DOWN message */ donteat = FALSE; } /* ** When KKAPP window open, this message is offten wrong. ** we must check it is really WM_KEYDOWN */ if ( (vmsgLast.message==WM_CHAR)||(vmsgLast.message==WM_INTERIM) ) { return vmsgLast.wParam; } if ( vmsgLast.message != WM_KEYDOWN ) { return kcNil; } TranslateMessage( &vmsgLast ); continue; } /* switch kc */ } /* if keydown */ if ( !donteat ) { GetMessage( (LPMSG) &vmsgLast, NULL, 0, 0 ); if ( (vmsgLast.message==WM_CHAR)||(vmsgLast.message==WM_INTERIM) ) { return vmsgLast.wParam; } } /* dont eat */ else { donteat = FALSE; } } /* if kc != kcNil */ return kc; } /* End of for ( ;; ) loop to process messages */ } #endif /* ifdef KOREA */