patch: background checks


Subject: patch: background checks
From: WJCarpenter (bill-abisource@carpenter.ORG)
Date: Mon Jul 24 2000 - 01:35:41 CDT


This patch is taken against 072300 nightly sources. It provides, as
hinted some days ago, a modification of the background spell checking
stuff into a general background checking mechanism. All code is XP
and tested on Linux.

Besides the familiar background spell-checking, there is a
demonstration background check that I call DebugFlash. If you set a
user preference item:

        DebugFlash="1"

and have spell-checking turned on, you'll see visual evidence of the
background check mechanism. Blocks (in the fl_BlockLayout sense) are
briefly underlined with squiggles as each block is considered. Since
that happens right before spell-checking, the squiggles look normal
after a quarter second or so. Oh, that doesn't happen for the initial
pass through the document (has to do with when preferences are read to
sensing DebugFlash), so "cut" out a few paragraphs and then "paste" it
back in the same place ... then you'll see the background checks on
the pasted text. (The DebugFlash preference item isn't in the
_builtin_ list. If it's not set to true, you just get the same old
spell-checking you're used to.)

I'll have more to say about how to add a background checking function
at some near-future date.

-- 
bill@carpenter.ORG (WJCarpenter)    PGP 0x91865119
38 95 1B 69 C9 C6 3D 25    73 46 32 04 69 D6 ED F3

diff -ru abi-072300-ORIG/src/text/fmt/xp/fl_BlockLayout.cpp abi-072300/src/text/fmt/xp/fl_BlockLayout.cpp --- abi-072300-ORIG/src/text/fmt/xp/fl_BlockLayout.cpp Thu Jul 20 20:07:37 2000 +++ abi-072300/src/text/fmt/xp/fl_BlockLayout.cpp Sun Jul 23 22:49:41 2000 @@ -95,7 +95,8 @@ m_bStartList = UT_FALSE; m_bStopList = UT_FALSE; m_bListLabelCreated = UT_FALSE; - m_bCursorErased = UT_FALSE; + m_bCursorErased = UT_FALSE; + m_uBackgroundCheckReasons = 0; m_pLayout = m_pSectionLayout->getDocLayout(); m_pDoc = m_pLayout->getDocument(); @@ -2963,7 +2964,7 @@ } // in case we've never checked this one - m_pLayout->dequeueBlock(this); + m_pLayout->dequeueBlockForBackgroundCheck(this); FV_View* pView = pSL->getDocLayout()->getView(); if (pView) @@ -3218,8 +3219,8 @@ { // this block may never have been checked // just to be safe, let's make sure both will - m_pLayout->queueBlockForSpell(this); - m_pLayout->queueBlockForSpell(pNewBL); + m_pLayout->queueBlockForBackgroundCheck(FL_DocLayout::bgcrSpelling, this); + m_pLayout->queueBlockForBackgroundCheck(FL_DocLayout::bgcrSpelling, pNewBL); } return UT_TRUE; @@ -4194,7 +4195,34 @@ m_bStopList = bValue; } +void fl_BlockLayout::debugFlashing(void) +{ + // Trivial background checker which puts on and takes off squiggles from + // the entire block that's being checked. This sort of messes up the + // spelling squiggles, but it's just a debug thing anyhow. Enable it + // by setting a preference DebugFlash="1" + UT_DEBUGMSG(("fl_BlockLayout::debugFlashing() was called\n")); + UT_GrowBuf pgb(1024); + UT_Bool bRes = getBlockBuf(&pgb); + UT_ASSERT(bRes); + const UT_UCSChar* pBlockText = pgb.getPointer(0); + UT_uint32 eor = pgb.getLength(); /* end of region */ + + FV_View* pView = m_pLayout->getView(); + _addSquiggle(0, eor, UT_FALSE); + pView->_eraseInsertionPoint(); + pView->updateScreen(); + pView->_drawInsertionPoint(); + usleep(250000); + //_deleteSquiggles(0, eor); + + pView->_eraseInsertionPoint(); + pView->updateScreen(); + pView->_drawInsertionPoint(); + + return; +} diff -ru abi-072300-ORIG/src/text/fmt/xp/fl_BlockLayout.h abi-072300/src/text/fmt/xp/fl_BlockLayout.h --- abi-072300-ORIG/src/text/fmt/xp/fl_BlockLayout.h Sun Jul 16 13:13:51 2000 +++ abi-072300/src/text/fmt/xp/fl_BlockLayout.h Sun Jul 23 20:14:35 2000 @@ -215,6 +215,7 @@ void checkForEndOnForcedBreak(void); void checkSpelling(void); + void debugFlashing(void); UT_Bool findNextTabStop(UT_sint32 iStartX, UT_sint32 iMaxX, UT_sint32& iPosition, unsigned char& iType); UT_Bool findNextTabStopInLayoutUnits(UT_sint32 iStartX, UT_sint32 iMaxX, UT_sint32& iPosition, unsigned char& iType); inline UT_sint32 getDefaultTabInterval(void) const { return m_iDefaultTabInterval; } @@ -270,6 +271,14 @@ static UT_Bool s_EnumTabStops(void * myThis, UT_uint32 k, UT_sint32 & iPosition, unsigned char & iType, UT_uint32 & iOffset); + inline void addBackgroundCheckReason(UT_uint32 reason) {m_uBackgroundCheckReasons |= reason;} + inline void removeBackgroundCheckReason(UT_uint32 reason) {m_uBackgroundCheckReasons &= ~reason;} + inline UT_Bool hasBackgroundCheckReason(UT_uint32 reason) const {return (m_uBackgroundCheckReasons & reason);} + + // The following is a set of bit flags giving the reason this block is + // queued for background checking. See specific values in fl_DocLayout.h + UT_uint32 m_uBackgroundCheckReasons; + #ifdef FMT_TEST void __dump(FILE * fp) const; #endif @@ -386,6 +395,7 @@ // spell check stuff UT_Vector m_vecSquiggles; + }; /* diff -ru abi-072300-ORIG/src/text/fmt/xp/fl_DocLayout.cpp abi-072300/src/text/fmt/xp/fl_DocLayout.cpp --- abi-072300-ORIG/src/text/fmt/xp/fl_DocLayout.cpp Wed Jul 19 18:12:52 2000 +++ abi-072300/src/text/fmt/xp/fl_DocLayout.cpp Sun Jul 23 22:38:11 2000 @@ -49,17 +49,18 @@ m_pDoc = doc; m_pG = pG; m_pView = NULL; - m_pSpellCheckTimer = NULL; + m_pBackgroundCheckTimer = NULL; m_pPendingBlock = NULL; m_pPendingWord = NULL; m_pFirstSection = NULL; m_pLastSection = NULL; - m_bAutoSpellCheck = UT_FALSE; m_bSpellCheckCaps = UT_TRUE; m_bSpellCheckNumbers = UT_TRUE; m_bSpellCheckInternet = UT_TRUE; m_pPrefs = NULL; + m_uBackgroundCheckReasons = 0; + m_pRedrawUpdateTimer = UT_Timer::static_constructor(_redrawUpdate, this, m_pG); if (m_pRedrawUpdateTimer) { @@ -93,12 +94,12 @@ DELETEP(m_pDocListener); - if (m_pSpellCheckTimer) + if (m_pBackgroundCheckTimer) { - m_pSpellCheckTimer->stop(); + m_pBackgroundCheckTimer->stop(); } - DELETEP(m_pSpellCheckTimer); + DELETEP(m_pBackgroundCheckTimer); DELETEP(m_pPendingWord); if (m_pRedrawUpdateTimer) @@ -150,6 +151,11 @@ // keep updating itself pPrefs->addListener ( _prefsListener, this ); + UT_Bool b; + if (m_pPrefs->getPrefsValueBool("DebugFlash",&b)) + { + addBackgroundCheckReason(bgcrDebugFlash); + } } } } @@ -526,29 +532,24 @@ } #endif -#define SPELL_CHECK_MSECS 100 +#define BACKGROUND_CHECK_MSECS 100 void FL_DocLayout::_toggleAutoSpell(UT_Bool bSpell) { - UT_Bool bOldAutoSpell = m_bAutoSpellCheck; - m_bAutoSpellCheck = bSpell; + UT_Bool bOldAutoSpell = getAutoSpellCheck(); + if (bSpell) + { + addBackgroundCheckReason(bgcrSpelling); + } + else + { + removeBackgroundCheckReason(bgcrSpelling); + } UT_DEBUGMSG(("FL_DocLayout::_toggleAutoSpell (%s)\n", bSpell ? "UT_TRUE" : "UT_FALSE" )); if (bSpell) { - // make sure the timer is started - if (!m_pSpellCheckTimer) - { - m_pSpellCheckTimer = UT_Timer::static_constructor(_spellCheck, this, m_pG); - if (m_pSpellCheckTimer) - m_pSpellCheckTimer->set(SPELL_CHECK_MSECS); - } - else - { - m_pSpellCheckTimer->start(); - } - // recheck the whole doc fl_DocSectionLayout * pSL = getFirstSection(); while (pSL) @@ -558,7 +559,7 @@ { // TODO: just check and remove matching squiggles // for now, destructively recheck the whole thing - queueBlockForSpell(b, UT_FALSE); + queueBlockForBackgroundCheck(bgcrSpelling, b); b = b->getNext(); } pSL = (fl_DocSectionLayout *) pSL->getNext(); @@ -566,10 +567,6 @@ } else { - // make sure the timer is stopped - if (m_pSpellCheckTimer) - m_pSpellCheckTimer->stop(); - // remove the squiggles, too fl_DocSectionLayout * pSL = getFirstSection(); while (pSL) @@ -593,7 +590,7 @@ } } -void FL_DocLayout::_spellCheck(UT_Timer * pTimer) +void FL_DocLayout::_backgroundCheck(UT_Timer * pTimer) { UT_ASSERT(pTimer); @@ -609,6 +606,10 @@ return; } + // prevent getting a new timer hit before we've finished this one by + // temporarily disabling the timer + pDocLayout->m_pBackgroundCheckTimer->stop(); + UT_Vector* vecToCheck = &pDocLayout->m_vecUncheckedBlocks; UT_ASSERT(vecToCheck); @@ -620,43 +621,71 @@ if (pB != NULL) { - vecToCheck->deleteNthItem(0); - i--; - - // note that we remove this block from queue before checking it - // (otherwise asserts could trigger redundant recursive calls) - pB->checkSpelling(); + for (unsigned int bitdex=0; bitdex<8*sizeof(pB->m_uBackgroundCheckReasons); ++bitdex) + { + // This looping seems like a lot of wasted effort when we + // don't define meaning for most of the bits, but it's small + // effort compared to all that squiggle stuff that goes on + // for the spelling stuff. + UT_uint32 mask; + mask = (1 << bitdex); + if (pB->hasBackgroundCheckReason(mask)) + { + // note that we remove this reason from queue before checking it + // (otherwise asserts could trigger redundant recursive calls) + pB->removeBackgroundCheckReason(mask); + switch (mask) + { + case bgcrDebugFlash: + pB->debugFlashing(); + break; + case bgcrSpelling: + pB->checkSpelling(); + break; + case bgcrSmartQuotes: + default: + break; + } + } + } + if (!pB->m_uBackgroundCheckReasons) + { + vecToCheck->deleteNthItem(0); + i--; + } } } - if (i == 0) + if (i != 0) { - // timer not needed any more, so suspend it - pDocLayout->m_pSpellCheckTimer->stop(); + // restart timer unless it's not needed any more + pDocLayout->m_pBackgroundCheckTimer->start(); } } -void FL_DocLayout::queueBlockForSpell(fl_BlockLayout *pBlock, UT_Bool bHead) +void FL_DocLayout::queueBlockForBackgroundCheck(UT_uint32 reason, fl_BlockLayout *pBlock, UT_Bool bHead) { /* - This routine queues up blocks for timer-driven spell checking. + This routine queues up blocks for timer-driven spell checking, etc. By default, this is a FIFO queue, but it can be explicitly reprioritized by setting bHead == UT_TRUE. */ + if (!m_pBackgroundCheckTimer) + { + m_pBackgroundCheckTimer = UT_Timer::static_constructor(_backgroundCheck, this, m_pG); + if (m_pBackgroundCheckTimer) + m_pBackgroundCheckTimer->set(BACKGROUND_CHECK_MSECS); + } + else + { + m_pBackgroundCheckTimer->start(); + } - if (m_bAutoSpellCheck) + if (hasBackgroundCheckReason(bgcrDebugFlash)) { - if (!m_pSpellCheckTimer) - { - m_pSpellCheckTimer = UT_Timer::static_constructor(_spellCheck, this, m_pG); - if (m_pSpellCheckTimer) - m_pSpellCheckTimer->set(SPELL_CHECK_MSECS); - } - else - { - m_pSpellCheckTimer->start(); - } + pBlock->addBackgroundCheckReason(bgcrDebugFlash); } + pBlock->addBackgroundCheckReason(reason); UT_sint32 i = m_vecUncheckedBlocks.findItem(pBlock); @@ -676,7 +705,7 @@ } } -void FL_DocLayout::dequeueBlock(fl_BlockLayout *pBlock) +void FL_DocLayout::dequeueBlockForBackgroundCheck(fl_BlockLayout *pBlock) { UT_sint32 i = m_vecUncheckedBlocks.findItem(pBlock); @@ -688,7 +717,7 @@ // when queue is empty, kill timer if (m_vecUncheckedBlocks.getItemCount() == 0) { - m_pSpellCheckTimer->stop(); + m_pBackgroundCheckTimer->stop(); } } diff -ru abi-072300-ORIG/src/text/fmt/xp/fl_DocLayout.h abi-072300/src/text/fmt/xp/fl_DocLayout.h --- abi-072300-ORIG/src/text/fmt/xp/fl_DocLayout.h Sun Jul 9 11:11:52 2000 +++ abi-072300/src/text/fmt/xp/fl_DocLayout.h Sun Jul 23 20:17:05 2000 @@ -126,8 +126,8 @@ void setPendingWord(fl_BlockLayout *pBlock, fl_PartOfBlock* pWord); UT_Bool checkPendingWord(void); - void queueBlockForSpell(fl_BlockLayout *pBlock, UT_Bool bHead=UT_FALSE); - void dequeueBlock(fl_BlockLayout *pBlock); + void queueBlockForBackgroundCheck(UT_uint32 reason, fl_BlockLayout *pBlock, UT_Bool bHead=UT_FALSE); + void dequeueBlockForBackgroundCheck(fl_BlockLayout *pBlock); void addSection(fl_DocSectionLayout*); void removeSection(fl_DocSectionLayout*); @@ -141,13 +141,27 @@ void deleteEmptyPages(void); - UT_Bool getAutoSpellCheck(void) const { return m_bAutoSpellCheck; } + UT_Bool getAutoSpellCheck(void) const { return (hasBackgroundCheckReason(bgcrSpelling)); } UT_Bool getSpellCheckCaps(void) const { return m_bSpellCheckCaps; } UT_Bool getSpellCheckNumbers(void) const { return m_bSpellCheckNumbers; } UT_Bool getSpellCheckInternet(void) const { return m_bSpellCheckInternet; } void recheckIgnoredWords(); + inline void addBackgroundCheckReason(UT_uint32 reason) {m_uBackgroundCheckReasons |= reason;} + inline void removeBackgroundCheckReason(UT_uint32 reason) {m_uBackgroundCheckReasons &= ~reason;} + inline UT_Bool hasBackgroundCheckReason(UT_uint32 reason) const {return (m_uBackgroundCheckReasons & reason);} + inline UT_uint32 getBackgroundCheckReasons() const {return (m_uBackgroundCheckReasons);} + + // These are used as bit flags in a UT_uint32. The enum is here just + // to get the namespace protection. + enum backgroundCheckReason + { + bgcrDebugFlash = (1 << 0), + bgcrSpelling = (1 << 1), + bgcrSmartQuotes = (1 << 2) + }; + #ifdef FMT_TEST static FL_DocLayout* m_pDocLayout; @@ -155,7 +169,7 @@ #endif protected: - static void _spellCheck(UT_Timer * pTimer); + static void _backgroundCheck(UT_Timer * pTimer); void _toggleAutoSpell(UT_Bool bSpell); static void _prefsListener(class XAP_App *, class XAP_Prefs *, @@ -178,14 +192,15 @@ UT_HashTable m_hashFontCache; // spell check stuff - UT_Timer* m_pSpellCheckTimer; UT_Vector m_vecUncheckedBlocks; fl_BlockLayout* m_pPendingBlock; // if NULL, then ignore m_pPendingWord fl_PartOfBlock* m_pPendingWord; - UT_Bool m_bAutoSpellCheck; UT_Bool m_bSpellCheckCaps; UT_Bool m_bSpellCheckNumbers; UT_Bool m_bSpellCheckInternet; + + UT_Timer* m_pBackgroundCheckTimer; + UT_uint32 m_uBackgroundCheckReasons; // bit flags XAP_Prefs * m_pPrefs; diff -ru abi-072300-ORIG/src/text/fmt/xp/fl_DocListener.cpp abi-072300/src/text/fmt/xp/fl_DocListener.cpp --- abi-072300-ORIG/src/text/fmt/xp/fl_DocListener.cpp Thu Jul 6 16:42:02 2000 +++ abi-072300/src/text/fmt/xp/fl_DocListener.cpp Sun Jul 23 20:17:37 2000 @@ -241,7 +241,7 @@ // BUGBUG: this is *not* thread-safe, but should work for now if (m_bScreen) - m_pLayout->queueBlockForSpell(pBL); + m_pLayout->queueBlockForBackgroundCheck(FL_DocLayout::bgcrSpelling, pBL); *psfh = (PL_StruxFmtHandle)pBL; } diff -ru abi-072300-ORIG/src/text/fmt/xp/fl_SectionLayout.cpp abi-072300/src/text/fmt/xp/fl_SectionLayout.cpp --- abi-072300-ORIG/src/text/fmt/xp/fl_SectionLayout.cpp Thu Jul 6 16:42:02 2000 +++ abi-072300/src/text/fmt/xp/fl_SectionLayout.cpp Sun Jul 23 20:17:53 2000 @@ -2006,7 +2006,7 @@ // BUGBUG: this is *not* thread-safe, but should work for now if (m_bScreen) - m_pLayout->queueBlockForSpell(pBL); + m_pLayout->queueBlockForBackgroundCheck(bgcrSpelling, pBL); #endif } diff -ru abi-072300-ORIG/src/text/fmt/xp/fv_View.cpp abi-072300/src/text/fmt/xp/fv_View.cpp --- abi-072300-ORIG/src/text/fmt/xp/fv_View.cpp Wed Jul 12 21:38:29 2000 +++ abi-072300/src/text/fmt/xp/fv_View.cpp Sun Jul 23 20:18:15 2000 @@ -5469,7 +5469,7 @@ { // TODO: just check and remove matching squiggles // for now, destructively recheck the whole thing - m_pLayout->queueBlockForSpell(b, UT_FALSE); + m_pLayout->queueBlockForBackgroundCheck(FL_DocLayout::bgcrSpelling, b); b = b->getNext(); } pSL = (fl_DocSectionLayout *) pSL->getNext(); @@ -5505,7 +5505,7 @@ { // TODO: just check and remove matching squiggles // for now, destructively recheck the whole thing - m_pLayout->queueBlockForSpell(b, UT_FALSE); + m_pLayout->queueBlockForBackgroundCheck(FL_DocLayout::bgcrSpelling, b); b = b->getNext(); } pSL = (fl_DocSectionLayout *) pSL->getNext(); diff -ru abi-072300-ORIG/src/wp/ap/xp/ap_Dialog_Spell.cpp abi-072300/src/wp/ap/xp/ap_Dialog_Spell.cpp --- abi-072300-ORIG/src/wp/ap/xp/ap_Dialog_Spell.cpp Mon Jun 26 14:46:02 2000 +++ abi-072300/src/wp/ap/xp/ap_Dialog_Spell.cpp Sun Jul 23 21:02:02 2000 @@ -128,7 +128,7 @@ // since we're done with this current block, put it // in the block spell queue so squiggles will be updated FL_DocLayout * docLayout = m_pSection->getDocLayout(); - docLayout->queueBlockForSpell(m_pBlock, UT_FALSE); + docLayout->queueBlockForBackgroundCheck(FL_DocLayout::bgcrSpelling, m_pBlock); m_pBlock = m_pBlock->getNext();



This archive was generated by hypermail 2b25 : Mon Jul 24 2000 - 01:39:57 CDT