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.
--
[EMAIL PROTECTED] (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();