On Fri, 2002-08-02 at 19:38, Dom Lachowicz wrote:
> Does anyone have a copy of this patch? Sam's archives are down.
Attached.
Jesper
// FV_Cursor.cpp
/* Part of AbiWord.
*
* Author: Mikael Nordell ([EMAIL PROTECTED])
* !!! Not yet released for public consumption!!!
* !!! Don NOT CVS commit this !!!
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include "fv_Cursor.h"
#include "ut_assert.h"
#include "ut_timer.h"
#include "ut_debugmsg.h"
#include "gr_Graphics.h"
#include "fp_Run.h"
#include "fp_Line.h"
#include "fl_BlockLayout.h"
#include "fv_View.h"
// Since this is not-committed code, and this is only for
// development and debugging purposes, I felt it acceptable
// (read appropriate) to use the real, suppported by all our
// current compilers, datatype 'bool'. Note that this will be
// gone before commit.
const bool bDebugMsg_setCurrentDocPos = false;
const bool bDebugMsg_setDocPos = false;
const bool bDebugBeepOnBlink = false;
//////////////////////////////////////////////////////////////////
//
// DOCUMENT POSITIONS
//
// PT_DocPosition is "byte offset" within the document.
//
// fl_BlockLayout::getPosition() returns DocPos of the line
// that this block belongs to (close enough explanation I think,
// but feel free to fill in/rewrite).
//
// FV_View::getPoint() returns the "insert point" in DocPos.
// This *will* probably go away, since FV_View should get this from
// FV_Cursor.
//
// fp_Run::getBlockOffset() returns offset for this run from its
// fl_BlockLayout in DocPos units.
//
// COORDINATE SYSTEMS - all in "display units/pixels".
// This was something that I had to research (since this is not mentioned
// anywhere else AFAIK) and it _might_ not be 100% correct.
// If so, please fix the comments.
//
// - fp_Run::getX() fp_Line relative x.
// - fp_Line::getX() fl_BlockLayout relative x.
// - fp_Run::findPointCoords() fp_Container (fp_Column) relative.
// - fp_Line::getOffsets() fp_Container (fp_Column) relative.
// - fl_BlockLayout::findPointCoords() fp_Container (fp_Column) relative.
//
// - fp_Run::mapXYToPosition() wants run-relative x coord.
//
//
class FV_Cursor_impl
{
public:
FV_Cursor_impl(FV_Cursor& owner, FV_View& view, FL_DocLayout& layout)
: m_layout(layout),
m_caret(owner, view),
m_docPos(0),
m_nStickyX(0),
m_xPoint(0),
m_yPoint(0),
m_nPointHeight(0),
m_bBOL(UT_FALSE),
m_bEOL(UT_FALSE)
{ }
void updateInternal();
// The 'bEOL' argument is needed since IP (Insert Position) might
// be at BOL at line two while the _cursor_ is at EOL at line 1.
// Think about it for a while, you'll get it.
fp_Run* setCurrentDocPos( PT_DocPosition dp,
UT_Bool bEOL = UT_FALSE);
fp_Run* getCurrentRun();
PT_DocPosition clampToDocument(PT_DocPosition dp);
FL_DocLayout& m_layout; // The layout for the view
FV_Caret m_caret; // The (possibly blinking) gfx caret
PT_DocPosition m_docPos; // Absolute DocPos of IP/Caret
UT_uint32 m_nStickyX; // fp_Container (fp_Column) relative
UT_sint32 m_xPoint; // fp_Container (fp_Column) relative
UT_sint32 m_yPoint; // fp_Container (fp_Column) relative
UT_sint32 m_nPointHeight; // Height of char at IP
UT_Bool m_bBOL; // self explanatory
UT_Bool m_bEOL; // self explanatory
};
void FV_Cursor_impl::updateInternal()
{
fp_Run* pRun = setCurrentDocPos(m_docPos, m_bEOL);
if (!pRun || !pRun->getLine() || !pRun->getBlock())
{
m_bBOL = UT_FALSE;
m_bEOL = UT_FALSE;
m_nStickyX = 0;
}
else
{
if (!pRun->isFirstRunOnLine())
{
m_bBOL = UT_FALSE;
}
if (!pRun->isLastRunOnLine())
{
m_bEOL = UT_FALSE;
}
}
}
// returns the run it got set to
fp_Run* FV_Cursor_impl::setCurrentDocPos(PT_DocPosition docPos, UT_Bool bEOL)
{
if (!docPos /* || docPos == m_docPos */)
{
return 0;
}
fl_BlockLayout* pBlock = m_layout.findBlockAtPosition(docPos);
UT_ASSERT(pBlock);
if (!pBlock)
{
// What to do?! Internal error!
// Should we crash here, or is it nicer to let the user continue?
return 0;
}
UT_sint32 nPosX;
UT_sint32 nPosY;
UT_sint32 nPtHeight;
fp_Run* pRun =
pBlock->findPointCoords(docPos /* [in] */,
m_bEOL /* [in] */,
nPosX /* [out] */,
nPosY /* [out] */,
nPtHeight /* [out] */ );
// If we don't get an fp_Run for a DocPos something is severely broken.
// What to do?!
UT_ASSERT(pRun);
if (pRun)
{
if (bDebugMsg_setCurrentDocPos)
{
UT_DEBUGMSG(("%s(%d): setCurrentDocPos(%d), EOL=%d\n",
__FILE__, __LINE__, docPos, (int)bEOL));
}
m_xPoint = nPosX;
m_yPoint = nPosY;
m_nPointHeight = nPtHeight;
m_docPos = docPos;
}
return pRun;
}
fp_Run* FV_Cursor_impl::getCurrentRun()
{
return setCurrentDocPos(m_docPos, m_bEOL);
}
PT_DocPosition FV_Cursor_impl::clampToDocument(PT_DocPosition dp)
{
PT_DocPosition dpMin;
PT_DocPosition dpMax;
const PD_Document* pDoc = m_layout.getDocument();
UT_ASSERT(pDoc);
if (!pDoc ||
!pDoc->getBounds(UT_FALSE, dpMin) ||
!pDoc->getBounds(UT_TRUE, dpMax))
{
// Internal error. What to do? Panic!
// When in trouble, when in doubt, run in circles, scream and shout.
return 0;
}
dp = MyMin(dp, dpMax);
dp = MyMax(dp, dpMin);
return dp;
}
//////////////////////////////////////////////////////////////////
FV_Cursor::FV_Cursor(FV_View& view, FL_DocLayout& layout)
: m_pimpl(new FV_Cursor_impl(*this, view, layout))
{
}
FV_Cursor::~FV_Cursor()
{
delete m_pimpl;
}
fp_Run* FV_Cursor::getCurrentRun()
{
return m_pimpl->getCurrentRun();
}
fp_Line* FV_Cursor::getCurrentLine()
{
fp_Run* pRun = getCurrentRun();
return pRun ? pRun->getLine() : 0;
}
// fl_BlockLayout for current DocPos
fl_BlockLayout* FV_Cursor::getCurrentBlockLayout()
{
fp_Line* pLine = getCurrentLine();
return pLine ? pLine->getBlock() : 0;
}
PT_DocPosition FV_Cursor::getDocPos() const
{
return m_pimpl->m_docPos;
}
UT_sint32 FV_Cursor::getContainerRelativeX() const
{
return m_pimpl->m_xPoint;
}
UT_sint32 FV_Cursor::getContainerRelativeY() const
{
return m_pimpl->m_yPoint;
}
UT_sint32 FV_Cursor::getPointHeight() const
{
return m_pimpl->m_nPointHeight;
}
void FV_Cursor::setDocPos(PT_DocPosition dp, UT_Bool bEOL)
{
if (bDebugMsg_setDocPos)
{
UT_DEBUGMSG(("%s(%d): setDocPos(%d)\n", __FILE__, __LINE__, dp));
}
dp = m_pimpl->clampToDocument(dp);
if (m_pimpl->m_docPos != dp)
{
disable();
m_pimpl->m_docPos = dp;
m_pimpl->setCurrentDocPos(dp, bEOL);
enable();
}
}
// painting
void FV_Cursor::disable()
{
m_pimpl->m_caret.disable();
}
void FV_Cursor::enable()
{
m_pimpl->m_caret.enable();
}
void FV_Cursor::setBlink(UT_Bool bBlink)
{
m_pimpl->m_caret.setBlink(bBlink);
}
//////////////////////////////////////////////////////////////////
// movement commands
// I know, it's bad form to use macros. But since all of these are
// just forwarders, and I wanted some reporting...
#if 1
#define THIS_REPORTER_(fn) UT_DEBUGMSG(("FV_Cursor::"#fn"\n"))
#define FV_CURSOR_DEF_FWD_FUN_(fn) \
void FV_Cursor::fn() { \
THIS_REPORTER_(fn); \
_do_movement(_ ## fn); \
}
FV_CURSOR_DEF_FWD_FUN_(up)
FV_CURSOR_DEF_FWD_FUN_(down)
FV_CURSOR_DEF_FWD_FUN_(left)
FV_CURSOR_DEF_FWD_FUN_(right)
FV_CURSOR_DEF_FWD_FUN_(pageUp)
FV_CURSOR_DEF_FWD_FUN_(pageDown)
FV_CURSOR_DEF_FWD_FUN_(home)
FV_CURSOR_DEF_FWD_FUN_(end)
FV_CURSOR_DEF_FWD_FUN_(wordLeft)
FV_CURSOR_DEF_FWD_FUN_(wordRight)
#undef FV_CURSOR_DEF_FWD_FUN_
#undef THIS_REPORTER_
#else
void FV_Cursor::up() { _do_movement(_up); }
void FV_Cursor::down() { _do_movement(_down); }
void FV_Cursor::left() { _do_movement(_left); }
void FV_Cursor::right() { _do_movement(_right); }
void FV_Cursor::pageUp() { _do_movement(_pageUp); }
void FV_Cursor::pageDown() { _do_movement(_pageDown); }
void FV_Cursor::home() { _do_movement(_home); }
void FV_Cursor::end() { _do_movement(_end); }
void FV_Cursor::wordLeft() { _do_movement(_wordLeft); }
void FV_Cursor::wordRight() { _do_movement(_wordRight); }
#endif
//////////////////////////////////////////////////////////////////
// accessors
UT_Bool FV_Cursor::isAtEOL() const
{
return m_pimpl->m_bEOL;
}
UT_Bool FV_Cursor::isAtBOL() const
{
return m_pimpl->m_bBOL;
}
//////////////////////////////////////////////////////////////////
// protected default handlers
// When we entered these, we KNOW that
// 1. We have a valid fp_Run pointer.
// 2. That run is on a fp_Line.
void FV_Cursor::_up()
{
fp_Line* pLine = _getPrevLine();
if (!pLine || pLine->isEmpty())
{
// beep?
return;
}
// now we need to find X-offset in display/layout coords,
// save that as stickyX, find closest x-pos from the
// previous line, find DocPos for that x-pos, and set
// our 'm_docPos' to the found value.
if (!_getStickyX())
{
_setStickyX(getContainerRelativeX());
}
fp_Run* pNewRun = _getRunAtColumnOffset(*pLine, _getStickyX());
UT_ASSERT(pNewRun);
UT_Bool bBOL = UT_FALSE; // dummy
UT_Bool bEOL = UT_FALSE; // dummy
const UT_sint32 nRunRelativeX = _containerToLineX(*pLine, _getStickyX()) -
pNewRun->getX();
pNewRun->mapXYToPosition( nRunRelativeX,
0, // unused arg
m_pimpl->m_docPos,
bBOL,
bEOL);
}
void FV_Cursor::_down()
{
fp_Line* pLine = _getNextLine();
if (!pLine || pLine->isEmpty())
{
// beep?
return;
}
// now we need to find X-offset in display/layout coords,
// save that as stickyX, find closest x-pos from the
// next line, find DocPos for that x-pos, and set
// our 'm_docPos' to the found value.
if (!_getStickyX())
{
_setStickyX(getContainerRelativeX());
}
fp_Run* pNewRun = _getRunAtColumnOffset(*pLine, _getStickyX());
UT_ASSERT(pNewRun);
UT_Bool bBOL = UT_FALSE; // dummy
UT_Bool bEOL = UT_FALSE; // dummy
const UT_sint32 nRunRelativeX = _containerToLineX(*pLine, _getStickyX()) -
pNewRun->getX();
pNewRun->mapXYToPosition( nRunRelativeX,
0, // unused arg
m_pimpl->m_docPos,
bBOL,
bEOL);
}
void FV_Cursor::_left()
{
PT_DocPosition dpMin;
PD_Document* pDoc = m_pimpl->m_layout.getDocument();
UT_ASSERT(pDoc);
if (!pDoc || !pDoc->getBounds(UT_FALSE, dpMin))
{
// Internal error. What to do?
return;
}
UT_ASSERT(getDocPos() >= dpMin);
if (getDocPos() == dpMin)
{
// Already at BOD
return;
}
if (isAtBOL())
{
UT_ASSERT(getCurrentRun()->isFirstRunOnLine());
fp_Line* pLine = _getPrevLine();
if (!pLine)
{
// we're already at the first line.
// beep?
return;
}
}
_setStickyX(0);
setDocPos(getDocPos() - 1);
}
void FV_Cursor::_right()
{
if (isAtEOL())
{
// EOL here means that the Caret is at EOL, but IP/DocPos
// is really before the first character of the next line.
UT_ASSERT(getCurrentRun()->isFirstRunOnLine());
_setBOL(); // don't change docPos!
return;
}
_setStickyX(0);
setDocPos(getDocPos() + 1);
}
void FV_Cursor::_pageUp()
{
UT_ASSERT(("C'mon, implement me!" == 0));
}
void FV_Cursor::_pageDown()
{
UT_ASSERT(("C'mon, implement me!" == 0));
}
void FV_Cursor::_home()
{
#if 1
if (isAtBOL())
#else
// the following is the same as IsAtBOL()
if (getCurrentRun()->isFirstRunOnLine() &&
getCurrentRun()->getBlockOffset() +
getCurrentBlockLayout()->getPosition() == m_pimpl->m_docPos)
#endif
{
return;
}
_setStickyX(0);
setDocPos(getCurrentLine()->getFirstRun()->getBlockOffset() +
getCurrentBlockLayout()->getPosition());
_setBOL();
}
void FV_Cursor::_end()
{
if (isAtEOL())
{
return;
}
_setStickyX(0);
// Note that the usage of 'getCurrentRun()->getLength()' gets us to the
// first DocPos _after_ that run. This is correct, and not an oversight.
setDocPos(getCurrentLine()->getLastRun()->getBlockOffset() +
getCurrentBlockLayout()->getPosition() +
getCurrentRun()->getLength());
_setEOL();
}
void FV_Cursor::_wordLeft()
{
UT_ASSERT(("C'mon, implement me!" == 0));
// This is hairy. You'll have to look at FV_View::_getDocPosFromPoint
// to even get a basic grip on it.
// Look into the switch FV_DOCPOS_BOW;
}
void FV_Cursor::_wordRight()
{
UT_ASSERT(("C'mon, implement me!" == 0));
// This is hairy. You'll have to look at FV_View::_getDocPosFromPoint
// to even get a basic grip on it.
// Look into the switch FV_DOCPOS_EOW;
}
// end of overridables
//////////////////////////////////////////////////////////////////
void FV_Cursor::_updateInternal()
{
m_pimpl->updateInternal();
}
void FV_Cursor::_setEOL(UT_Bool bEOL)
{
m_pimpl->m_bEOL = bEOL;
if (bEOL)
{
_setStickyX(0);
_setBOL(UT_FALSE);
}
}
void FV_Cursor::_setBOL(UT_Bool bBOL)
{
m_pimpl->m_bBOL = bBOL;
if (bBOL)
{
_setStickyX(0);
_setEOL(UT_FALSE);
}
}
void FV_Cursor::_setStickyX(UT_sint32 x)
{
m_pimpl->m_nStickyX = x;
}
UT_sint32 FV_Cursor::_getStickyX()
{
return m_pimpl->m_nStickyX;
}
fp_Line* FV_Cursor::_getPrevLine()
{
fl_BlockLayout* pBlockLayout = getCurrentBlockLayout();
UT_ASSERT(pBlockLayout);
return pBlockLayout ?
pBlockLayout->findPrevLineInDocument(getCurrentLine()) :
0;
}
fp_Line* FV_Cursor::_getNextLine()
{
fl_BlockLayout* pBlockLayout = getCurrentBlockLayout();
UT_ASSERT(pBlockLayout);
return pBlockLayout ?
pBlockLayout->findNextLineInDocument(getCurrentLine()) :
0;
}
//////////////////////////////////////////////////////////////////
// private (implementation specific) methods
// helper function
UT_sint32 FV_Cursor::_containerToLineX( const fp_Line& line,
UT_sint32 containerX)
{
UT_ASSERT(!line.isEmpty());
fp_Container* pContainer = line.getContainer();
UT_ASSERT(pContainer);
if (!pContainer)
{
// WHAT THE...?!
return 0;
}
// transpose the fp_Column relative x to fp_Line relative.
UT_sint32 xOffs;
UT_sint32 yOffs;
pContainer->getOffsets(&line, xOffs, yOffs);
return containerX - xOffs;
}
// 'x' is in fp_Container (fp_Column) relative coords.
// With legal input, this function returns either the correct run or, if
// that's not found, the last run. It returns 0 if no line is given.
fp_Run* FV_Cursor::_getRunAtColumnOffset(const fp_Line& line, UT_sint32 x)
{
x = _containerToLineX(line, x);
fp_Run* pRun = line.getFirstRun();
fp_Run* pEnd = line.getLastRun();
UT_ASSERT(pRun);
UT_ASSERT(pEnd);
// Current X might be on an indented line. stickyX is then
// to the left of current run.
if (x >= pRun->getX())
{
for (; pRun != pEnd; pRun = pRun->getNext())
{
UT_ASSERT(x >= pRun->getX());
if (x >= pRun->getX() &&
x < pRun->getX() + pRun->getWidth())
{
break;
}
}
}
return pRun;
}
UT_Bool FV_Cursor::_isRelativeMovementAllowed()
{
// Implementation detail: If we have a currentBlockLayout, we also
// have a currentLine and a currentRun.
// If implementation changes, theis must be reviewed.
return getCurrentBlockLayout() && !getCurrentLine()->isEmpty();
}
void FV_Cursor::_do_movement(void (FV_Cursor::*pmfn)())
{
UT_ASSERT(pmfn);
UT_ASSERT(getCurrentRun());
if (_isRelativeMovementAllowed())
{
FV_CursorDisabler disabler(*this);
(this->*pmfn)();
// If this assert triggers it's a sign that we have
// a SERIOUS bug!
UT_ASSERT(getCurrentRun());
_updateInternal();
}
}
//////////////////////////////////////////////////////////////////
// implementation of class FV_Caret
FV_Caret::FV_Caret(FV_Cursor& cursor, FV_View& view)
: m_cursor(cursor),
m_view(view),
m_pAutoCursorTimer(0),
m_nDisableCount(1),
m_bCursorBlink(UT_TRUE/*UT_FALSE*/),
m_bCursorIsOn(UT_FALSE)
{
}
FV_Caret::~FV_Caret()
{
delete m_pAutoCursorTimer;
}
void FV_Caret::enable()
{
// If it isn't disabled by the time we get this call, something is wrong.
UT_ASSERT(m_nDisableCount);
UT_DEBUGMSG(("FV_Caret::enable() , count = %d\n", m_nDisableCount));
if (--m_nDisableCount)
{
return;
}
// Caret should never be "on" when in disabled state. Let's assert so.
UT_ASSERT(!m_bCursorIsOn);
// Always start out with the caret in drawn state
if (!m_bCursorIsOn)
{
_blink();
}
if (m_bCursorBlink)
{
if (!m_pAutoCursorTimer && !_createTimer())
{
// TODO How should we report this error?
UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
return;
}
m_pAutoCursorTimer->set(AUTO_DRAW_POINT);
m_pAutoCursorTimer->start();
}
// Caret should always be "on" when leaving enable().
UT_ASSERT(m_bCursorIsOn); // post condition
}
void FV_Caret::disable()
{
UT_DEBUGMSG(("FV_Caret::disable(), count = %d\n", m_nDisableCount));
if (!m_nDisableCount++)
{
if (m_pAutoCursorTimer)
{
m_pAutoCursorTimer->stop();
}
if (m_bCursorIsOn)
{
_blink();
}
}
// Caret should never be "on" when leaving enable().
UT_ASSERT(!m_bCursorIsOn); // post condition
}
void FV_Caret::setBlink(UT_Bool bBlink)
{
m_bCursorBlink = bBlink;
}
// This is just to have an _instant_ report of what the caret class think
// is the carets state. A higher pitch beep (1500 Hz) means the class
// think it's drawing a caret, a lower pitch beep (1000 Hz) means it
// thinks it's erasing the caret.
// It will _probably_ go away before committing. But on the other hand,
// this code could be of use when adding another platform.
#ifdef UT_DEBUG
#ifdef _WIN32
extern "C" __declspec(dllimport) int __stdcall Beep(unsigned long dwFreq, unsigned long dwDuration);
#else // _WIN32
void Beep(UT_uint32 freq, UT_uint32 duration)
{
UT_UNUSED(freq);
UT_UNUSED(duration);
}
#endif // _WIN32
#endif // UT_DEBUG
void FV_Caret::_blink()
{
// toggle this as soon as possible, since timer blinks can possibly
// interfere with calls from enable()/disable().
// Since there's no synchronizing mechanism in XP, use a local
// (auto/stack) variable.
const UT_Bool bTurnCursorOn = !m_bCursorIsOn;
fp_Line* pCurrLine = m_cursor.getCurrentLine();
if (m_view.getWindowHeight() <= 0 ||
!m_view.isSelectionEmpty() ||
!pCurrLine ||
!m_cursor.getPointHeight())
{
return;
}
GR_Graphics* pG = m_view.getGraphics();
if (!pG)
{
return;
}
UT_sint32 xPageOffs;
UT_sint32 yPageOffs;
m_view.
getPageScreenOffsets( pCurrLine->getContainer()->getPage(),
xPageOffs,
yPageOffs);
const UT_uint32 x = m_cursor.getContainerRelativeX() + xPageOffs;
const UT_uint32 yMin = m_cursor.getContainerRelativeY() + yPageOffs;
const UT_uint32 yMax = yMin + m_cursor.getPointHeight();
UT_DEBUGMSG(("caret at %d,%d (%d,%d), docpos: %d\n",
x, yMin, x - xPageOffs, yMin - yPageOffs,
m_cursor.getDocPos()));
#ifdef UT_DEBUG
// This is just to have an _instant_ report of what the caret class think
// is the carets state. A higher pitch beep (1500 Hz) means the class
// think it's drawing a caret, a lower pitch beep (1000 Hz) means it
// thinks it's erasing the caret.
// It will _probably_ go away before committing. But on the other hand,
// this code could be of use when adding another platform.
if (bDebugBeepOnBlink)
{
Beep(bTurnCursorOn ? 1500 : 1000, 20);
}
#endif
UT_RGBColor clr(255,255,255);
pG->setColor(clr);
pG->xorLine(x-1, yMin, x-1, yMax);
pG->xorLine(x , yMin, x , yMax);
m_bCursorIsOn = !m_bCursorIsOn;
}
// This is really the only legal (C++ language-wise) function type
// we can use for callbacks as we do them now.
void FV_Caret_CursorTimerCallback(UT_Timer* pTimer)
{
UT_ASSERT(pTimer);
if (!pTimer)
{
// If we get no timer, things are really bad.
return;
}
FV_Caret* pCaret = static_cast<FV_Caret*>(pTimer->getInstanceData());
UT_ASSERT(pCaret);
FV_Caret::callbackHelper::_callback(*pCaret);
}
UT_Bool FV_Caret::_createTimer()
{
if (m_pAutoCursorTimer)
{
return UT_FALSE;
}
m_pAutoCursorTimer =
UT_Timer::static_constructor(FV_Caret_CursorTimerCallback,
this,
m_view.getGraphics());
return m_pAutoCursorTimer != 0;
}
// FV_Cursor.h
/* Part of the AbiWord.
*
* Author: Mikael Nordell ([EMAIL PROTECTED])
* !!! Not yet released for public consumption!!!
* !!! Don NOT CVS commit this !!!
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef FV_CURSOR_H
#define FV_CURSOR_H
#include "ut_types.h"
#include "pt_types.h"
// fwd. decl.
class FV_View;
class fp_Line;
class fp_Run;
class UT_Timer;
class FL_DocLayout;
class fl_BlockLayout;
class FV_Caret;
class FV_Cursor
{
public:
FV_Cursor(FV_View& view, FL_DocLayout& layout);
~FV_Cursor();
// the following accessors returns' are related to current DocPos.
fp_Run* getCurrentRun(); // returns 0 if no current run
fp_Line* getCurrentLine(); // returns 0 if no current line
fl_BlockLayout* getCurrentBlockLayout();// BlockLayout for current DocPos
PT_DocPosition getDocPos() const;
UT_sint32 getContainerRelativeX() const;
UT_sint32 getContainerRelativeY() const;
UT_sint32 getPointHeight() const;
// The bEOL argument is needed since a document position
// can have IP at either EOL line 1 or BOL line 2.
void setDocPos(PT_DocPosition dp, UT_Bool bEOL = UT_FALSE);
// should this really be in the public part of the interface?
// It returns the display/layout x-position of IP in
// fp_Container (fp_Column) relative coordinate system.
UT_uint32 getDisplayX();
// The user interface for FV_Caret.
void disable(); // visibly no-op if cursor already is drawn
void enable(); // visibly no-op if cursor already is erased
void setBlink(UT_Bool bBlink); // Tells it wether to "blink" or not.
// these are the move commands for the cursor.
void up(); // Implemented. Seems to work OK.
void down(); // Implemented. Seems to work OK.
void left(); // Implemented. Seems to work OK.
void right(); // Implemented. Seems to work OK.
void pageUp(); // Not implemented yet!
void pageDown(); // Not implemented yet!
void home(); // Implemented. Seems to work OK.
void end(); // Implemented. Seems to work OK.
void wordLeft(); // Not implemented yet!
void wordRight(); // Not implemented yet!
UT_Bool isAtEOL() const;
UT_Bool isAtBOL() const; // This might be dropped or put in protected.
protected:
// These are the [relative] movement handlers for the cursor.
// They are free for any derived classes to override and implement
// other behaviour. No calling of baseclass' version is needed.
virtual void _up();
virtual void _down();
virtual void _left();
virtual void _right();
virtual void _pageUp();
virtual void _pageDown();
virtual void _home();
virtual void _end();
virtual void _wordLeft();
virtual void _wordRight();
// interface for derived classes
void _updateInternal();
void _setEOL(UT_Bool bEOL = UT_TRUE);
void _setBOL(UT_Bool bBOL = UT_TRUE);
void _setStickyX(UT_sint32 x); // 0 is non-sticky
UT_sint32 _getStickyX(); // 0 is non-sticky
fp_Line* _getPrevLine(); // realtive current DocPos
fp_Line* _getNextLine(); // realtive current DocPos
// Coordinate system conversion
UT_sint32 _containerToLineX(const fp_Line& line, UT_sint32 containerX);
// Returns closest match.
// x < first run on line returns first run on line.
// x > last run on line returns last run on line.
fp_Run* _getRunAtColumnOffset(const fp_Line& line, UT_sint32 x);
private:
FV_Cursor(const FV_Cursor& rhs); // no impl.
void operator=(const FV_Cursor& rhs); // no impl.
UT_Bool _isRelativeMovementAllowed();
void _do_movement(void (FV_Cursor::*pmfn)());
// Since this class uses some hairy stuff inside, depends upon
// more than a few other classes, and has changed rather frequently
// during development, I decided to use the 'pimpl' idiom.
// This might (will?) change before the release of this class.
class FV_Cursor_impl* m_pimpl;
};
//////////////////////////////////////////////////////////////////
// The following class is used internally by FV_Cursor
// It should possibly (probably) be moved into its own file(s), but for
// now, during development, it's left here due to the close relationship
// with FV_Cursor.
class FV_Caret
{
public:
FV_Caret(FV_Cursor& cursor, FV_View& view);
~FV_Caret();
void enable();
void disable();
UT_Bool isEnabled() const { return m_nDisableCount == 0; }
void setBlink(UT_Bool bBlink);
class callbackHelper
{
// This [inner] class is here for two reasons.
// 1. To inhibit any function but the one in the
// friend declaration to make the caret blink.
// 2. To display how friendship actually can strengthen
// encapsulation (compared to giving this free function
// friendship to the class FV_Caret)..
friend void FV_Caret_CursorTimerCallback(UT_Timer* pTimer);
static void _callback(FV_Caret& caret)
{ if (caret.isEnabled()) { caret._blink(); } }
};
private:
friend callbackHelper;
FV_Caret(const FV_Caret& rhs); // no impl.
void operator=(const FV_Caret& rhs); // no impl.
void _blink();
UT_Bool _createTimer();
FV_Cursor& m_cursor;
FV_View& m_view;
UT_Timer* m_pAutoCursorTimer;
// without interlocked inc/dec the best we can do is to use volatile...
volatile UT_uint32 m_nDisableCount;
UT_Bool m_bCursorBlink;
UT_Bool m_bCursorIsOn;
};
class FV_CursorDisabler
{
public:
FV_CursorDisabler(FV_Cursor& cursor)
: m_cursor(cursor)
{
// The reson for using 'cursor' rather than 'm_cursor' is that this
// approach uses less memory (RAM) accesses.
cursor.disable();
}
~FV_CursorDisabler() { m_cursor.enable(); }
private:
FV_Cursor& m_cursor;
};
#endif // FV_CURSOR_H
--- ap_Win32Frame.cpp Thu May 18 11:01:12 2000
+++ \AbiWord\abi\src\wp\ap\win\ap_Win32Frame.cpp Mon May 22 17:54:22 2000
@@ -173,6 +173,10 @@
return UT_IE_IMPORTERROR;
}
+ // TMN: This is both ugly and dangeruous, but since it's already done
+ // and apparently accepted I did my part trying to clean it up... <sigh>
+ AP_FrameData* pData = static_cast<AP_FrameData*>(m_pData);
+
GR_Win32Graphics* pG
= 0;
FL_DocLayout* pDocLayout
= 0;
AV_View* pView
= 0;
@@ -268,22 +272,26 @@
****************************************************************/
// switch to new view, cleaning up previous settings
- if (static_cast<AP_FrameData*>(m_pData)->m_pDocLayout)
+ if (pData->m_pDocLayout)
{
- pOldDoc =
static_cast<AP_FrameData*>(m_pData)->m_pDocLayout->getDocument();
+ pOldDoc = pData->m_pDocLayout->getDocument();
}
- REPLACEP(static_cast<AP_FrameData*>(m_pData)->m_pG, pG);
- REPLACEP(static_cast<AP_FrameData*>(m_pData)->m_pDocLayout, pDocLayout);
+ REPLACEP(pData->m_pG, pG);
+ REPLACEP(pData->m_pDocLayout, pDocLayout);
if (pOldDoc != m_pDoc)
{
UNREFP(pOldDoc);
}
{
- const AV_Focus prevFocus = m_pView ? m_pView->getFocus() :
AV_FOCUS_NONE;
+ AV_View* pPrevView = m_pView;
+ const AV_Focus prevFocus = pPrevView ? pPrevView->getFocus() :
+AV_FOCUS_NONE;
REPLACEP(m_pView, pView);
- m_pView->setFocus(prevFocus);
+ if (pPrevView)
+ {
+ m_pView->focusChange(prevFocus);
+ }
}
REPLACEP(m_pScrollObj, pScrollObj);
@@ -300,14 +308,15 @@
// views, like we do for all the other objects. We also do not
// allocate the TopRuler, LeftRuler here; that is done as the frame is
// created.
- if (static_cast<AP_FrameData*>(m_pData)->m_pTopRuler)
- static_cast<AP_FrameData*>(m_pData)->m_pTopRuler->setView(pView,
iZoom);
- if (static_cast<AP_FrameData*>(m_pData)->m_pLeftRuler)
- static_cast<AP_FrameData*>(m_pData)->m_pLeftRuler->setView(pView,
iZoom);
- static_cast<AP_FrameData*>(m_pData)->m_pStatusBar->setView(pView);
+ if (pData->m_pTopRuler)
+ pData->m_pTopRuler->setView(pView, iZoom);
+ if (pData->m_pLeftRuler)
+ pData->m_pLeftRuler->setView(pView, iZoom);
- pView->setInsertMode(static_cast<AP_FrameData*>(m_pData)->m_bInsertMode);
- ((FV_View *) m_pView)->setShowPara(((AP_FrameData*)m_pData)->m_bShowPara);
+ pData->m_pStatusBar->setView(pView);
+
+ pView->setInsertMode(pData->m_bInsertMode);
+ static_cast<FV_View*>(m_pView)->setShowPara(pData->m_bShowPara);
RECT r;
GetClientRect(hwnd, &r);
@@ -322,11 +331,12 @@
if (point != 0)
((FV_View *) m_pView)->moveInsPtTo(point);
- if (static_cast<AP_FrameData*>(m_pData)->m_pTopRuler)
- static_cast<AP_FrameData*>(m_pData)->m_pTopRuler->draw(NULL);
- if (static_cast<AP_FrameData*>(m_pData)->m_pLeftRuler)
- static_cast<AP_FrameData*>(m_pData)->m_pLeftRuler->draw(NULL);
- static_cast<AP_FrameData*>(m_pData)->m_pStatusBar->draw();
+ if (pData->m_pTopRuler)
+ pData->m_pTopRuler->draw(NULL);
+ if (pData->m_pLeftRuler)
+ pData->m_pLeftRuler->draw(NULL);
+
+ pData->m_pStatusBar->draw();
return UT_OK;
@@ -341,7 +351,7 @@
// change back to prior document
UNREFP(m_pDoc);
- m_pDoc = static_cast<AP_FrameData*>(m_pData)->m_pDocLayout->getDocument();
+ m_pDoc = pData->m_pDocLayout->getDocument();
return UT_IE_ADDLISTENERERROR;
}
--- fv_View.cpp Fri May 19 11:01:14 2000
+++ \AbiWord\abi\src\text\fmt\xp\fv_View.cpp Mon May 22 17:50:02 2000
@@ -52,9 +52,18 @@
#include "ap_TopRuler.h"
#include "ap_LeftRuler.h"
#include "ap_Prefs.h"
+#include "fv_Cursor.h"
#include "sp_spell.h"
+// moved definition to header file fv_View.h
+//#define ABW_CURSOR_EXTERNAL_CLASS
+
+#ifndef ABW_CURSOR_EXTERNAL_CLASS
+#define FV_CursorDisabler //
+#endif
+
+
/****************************************************************/
class _fmtPair
@@ -76,8 +85,12 @@
FV_View::FV_View(XAP_App * pApp, void* pParentData, FL_DocLayout* pLayout)
-: AV_View(pApp, pParentData),
- m_bCursorIsOn(UT_FALSE)
+: AV_View(pApp, pParentData)
+#ifdef ABW_CURSOR_EXTERNAL_CLASS
+ ,m_pCursor(new FV_Cursor(*this, *pLayout))
+#else
+ ,m_iPointHeight(0)
+#endif
{
m_pLayout = pLayout;
m_pDoc = pLayout->getDocument();
@@ -85,16 +98,21 @@
// UT_ASSERT(m_pG->queryProperties(GR_Graphics::DGP_SCREEN));
m_iInsPoint = 0;
- m_iPointHeight = 0;
m_bPointEOL = UT_FALSE;
m_bSelection = UT_FALSE;
// m_bPointAP = UT_FALSE;
m_pAutoScrollTimer = NULL;
- m_pAutoCursorTimer = NULL;
- m_pParentData = pParentData;
+#ifdef ABW_CURSOR_EXTERNAL_CLASS
+ UT_Bool bCursorBlink;
+ if (pApp->getPrefsValueBool(AP_PREF_KEY_CursorBlink, &bCursorBlink))
+ {
+ m_pCursor->setBlink(bCursorBlink);
+ }
+#else
// initialize prefs cache
pApp->getPrefsValueBool(AP_PREF_KEY_CursorBlink, &m_bCursorBlink);
+#endif
// initialize prefs listener
pApp->getPrefs()->addListener( _prefsListener, this );
@@ -130,8 +148,11 @@
// remove prefs listener
m_pApp->getPrefs()->removeListener( _prefsListener, this );
+#ifdef ABW_CURSOR_EXTERNAL_CLASS
+ delete m_pCursor;
+#endif
+
DELETEP(m_pAutoScrollTimer);
- DELETEP(m_pAutoCursorTimer);
FREEP(_m_findNextString);
@@ -146,33 +167,20 @@
switch(focus)
{
case AV_FOCUS_HERE:
+ _enableCursor();
if (isSelectionEmpty())
{
_fixInsertionPointCoords();
- _drawInsertionPoint();
}
else
{
_drawSelection();
}
- m_pApp->rememberFocussedFrame( m_pParentData);
break;
case AV_FOCUS_NEARBY:
if (isSelectionEmpty())
{
_fixInsertionPointCoords();
- _drawInsertionPoint();
- }
- else
- {
- _drawSelection();
- }
- break;
- case AV_FOCUS_MODELESS:
- if (isSelectionEmpty())
- {
- _fixInsertionPointCoords();
- _drawInsertionPoint();
}
else
{
@@ -180,11 +188,8 @@
}
break;
case AV_FOCUS_NONE:
- if (isSelectionEmpty())
- {
- _eraseInsertionPoint();
- }
- else
+ _disableCursor();
+ if (!isSelectionEmpty())
{
if (!m_bSelection)
{
@@ -475,6 +480,11 @@
PT_DocPosition curPos = getPoint();
UT_ASSERT(curPos != m_iSelectionAnchor);
_setPoint(m_iSelectionAnchor);
+
+#ifdef ABW_CURSOR_EXTERNAL_CLASS
+ m_pCursor->setDocPos(m_iSelectionAnchor);
+#endif
+
m_iSelectionAnchor = curPos;
}
@@ -487,10 +497,10 @@
UT_ASSERT(!isSelectionEmpty());
- PT_DocPosition curPos = getPoint();
+ const PT_DocPosition curPos = getPoint();
UT_ASSERT(curPos != m_iSelectionAnchor);
- UT_Bool bForwardSelection = (m_iSelectionAnchor < curPos);
+ const UT_Bool bForwardSelection = (m_iSelectionAnchor < curPos);
if (bForward != bForwardSelection)
{
@@ -972,26 +982,36 @@
void FV_View::moveInsPtTo(FV_DocPos dp)
{
if (!isSelectionEmpty())
+ {
_clearSelection();
- else
- _eraseInsertionPoint();
+ }
PT_DocPosition iPos = _getDocPos(dp);
if (iPos != getPoint())
{
- UT_Bool bPointIsValid = (getPoint() >= _getDocPos(FV_DOCPOS_BOD));
+ const UT_Bool bPointIsValid = getPoint() >= _getDocPos(FV_DOCPOS_BOD);
if (bPointIsValid)
_clearIfAtFmtMark(getPoint());
}
_setPoint(iPos, (dp == FV_DOCPOS_EOL));
- if (!_ensureThatInsertionPointIsOnScreen())
+#ifdef ABW_CURSOR_EXTERNAL_CLASS
+ switch (dp)
{
- _fixInsertionPointCoords();
- _drawInsertionPoint();
+ case FV_DOCPOS_BOL:
+ m_pCursor->home();
+ break;
+ case FV_DOCPOS_EOL:
+ m_pCursor->end();
+ break;
+ default:
+ m_pCursor->setDocPos(iPos);
}
+#endif // ABW_CURSOR_EXTERNAL_CLASS
+
+ _updateInsertionPoint();
notifyListeners(AV_CHG_MOTION);
}
@@ -1001,10 +1021,22 @@
if (dp != getPoint())
_clearIfAtFmtMark(getPoint());
- _setPoint(dp, /* (dp == FV_DOCPOS_EOL) */ UT_FALSE); // is this bool correct?
+ // is this bool correct?
+ // TMN: No I don't think so.
+ _setPoint(dp, /* (dp == FV_DOCPOS_EOL) */ UT_FALSE);
+
+#ifdef ABW_CURSOR_EXTERNAL_CLASS
+ m_pCursor->setDocPos(dp);
+#endif
_fixInsertionPointCoords();
+
+#ifdef ABW_CURSOR_EXTERNAL_CLASS
+ cmdScroll(AV_SCROLLCMD_LINEDOWN, (UT_uint32) (m_yPoint +
+m_pCursor->getPointHeight()/2 - m_iWindowHeight/2));
+#else
cmdScroll(AV_SCROLLCMD_LINEDOWN, (UT_uint32) (m_yPoint + m_iPointHeight/2 -
m_iWindowHeight/2));
+#endif
+
cmdScroll(AV_SCROLLCMD_LINERIGHT, (UT_uint32) (m_xPoint - m_iWindowWidth/2));
notifyListeners(AV_CHG_MOTION);
}
@@ -1012,15 +1044,37 @@
void FV_View::cmdCharMotion(UT_Bool bForward, UT_uint32 count)
{
+ FV_CursorDisabler disabler(*m_pCursor);
+
if (!isSelectionEmpty())
{
+ --count;
_moveToSelectionEnd(bForward);
// Note: _moveToSelectionEnd() clears the selection
// but does not redraw the insertion point.
- _drawInsertionPoint();
}
- PT_DocPosition iPoint = getPoint();
+ const PT_DocPosition iPoint = getPoint();
+
+#ifdef ABW_CURSOR_EXTERNAL_CLASS
+
+ if (iPoint != m_pCursor->getDocPos()) {
+ UT_DEBUGMSG(("%s(%d): iPoint != m_pCursor->getDocPos()\n", __FILE__,
+__LINE__));
+ }
+
+ if (bForward)
+ {
+ for (UT_uint32 i=0; i<count; ++i)
+ m_pCursor->right();
+ }
+ else
+ {
+ for (UT_uint32 i=0; i<count; ++i)
+ m_pCursor->left();
+ }
+#endif // ABW_CURSOR_EXTERNAL_CLASS
+
+// if (!_charMotion(bForward, count))
if (!_charMotion(bForward, count))
{
_setPoint(iPoint);
@@ -1051,6 +1105,8 @@
{
UT_Bool bResult;
+ FV_CursorDisabler disabler(*m_pCursor);
+
if (!isSelectionEmpty())
{
m_pDoc->beginUserAtomicGlob();
@@ -1060,8 +1116,6 @@
}
else
{
- _eraseInsertionPoint();
-
UT_Bool bOverwrite = (!m_bInsertMode && !bForce);
if (bOverwrite)
@@ -1081,27 +1135,21 @@
_generalUpdate();
- if (!_ensureThatInsertionPointIsOnScreen())
- {
- _fixInsertionPointCoords();
- _drawInsertionPoint();
- }
+ _updateInsertionPoint();
return bResult;
}
void FV_View::insertSectionBreak(void)
{
+ FV_CursorDisabler disabler(*m_pCursor);
+
m_pDoc->beginUserAtomicGlob();
if (!isSelectionEmpty())
{
_deleteSelection();
}
- else
- {
- _eraseInsertionPoint();
- }
// insert a new paragraph with the same attributes/properties
// as the previous (or none if the first paragraph in the section).
@@ -1115,27 +1163,21 @@
_generalUpdate();
- if (!_ensureThatInsertionPointIsOnScreen())
- {
- _fixInsertionPointCoords();
- _drawInsertionPoint();
- }
+ _updateInsertionPoint();
}
void FV_View::insertParagraphBreak(void)
{
UT_Bool bDidGlob = UT_FALSE;
+ FV_CursorDisabler disabler(*m_pCursor);
+
if (!isSelectionEmpty())
{
bDidGlob = UT_TRUE;
m_pDoc->beginUserAtomicGlob();
_deleteSelection();
}
- else
- {
- _eraseInsertionPoint();
- }
// insert a new paragraph with the same attributes/properties
// as the previous (or none if the first paragraph in the section).
@@ -1147,11 +1189,7 @@
_generalUpdate();
- if (!_ensureThatInsertionPointIsOnScreen())
- {
- _fixInsertionPointCoords();
- _drawInsertionPoint();
- }
+ _updateInsertionPoint();
}
UT_Bool FV_View::setStyle(const XML_Char * style)
@@ -1190,11 +1228,6 @@
if (bCharStyle)
{
// set character-level style
- if (isSelectionEmpty())
- {
- _eraseInsertionPoint();
- }
-
_clearIfAtFmtMark(getPoint()); // TODO is this correct ??
_eraseSelection();
@@ -1203,8 +1236,6 @@
else
{
// set block-level style
- _eraseInsertionPoint();
-
_clearIfAtFmtMark(getPoint()); // TODO is this correct ??
// NB: clear explicit props at both block and char levels
@@ -1216,7 +1247,6 @@
if (isSelectionEmpty())
{
_fixInsertionPointCoords();
- _drawInsertionPoint();
}
return bRet;
}
@@ -1409,10 +1439,7 @@
{
UT_Bool bRet;
- if (isSelectionEmpty())
- {
- _eraseInsertionPoint();
- }
+ FV_CursorDisabler disabler(*m_pCursor);
PT_DocPosition posStart = getPoint();
PT_DocPosition posEnd = posStart;
@@ -1438,7 +1465,6 @@
if (isSelectionEmpty())
{
_fixInsertionPointCoords();
- _drawInsertionPoint();
}
return bRet;
@@ -1616,9 +1642,9 @@
{
UT_Bool bRet;
- _clearIfAtFmtMark(getPoint());
+ FV_CursorDisabler disabler(*m_pCursor);
- _eraseInsertionPoint();
+ _clearIfAtFmtMark(getPoint());
PT_DocPosition posStart = getPoint();
PT_DocPosition posEnd = posStart;
@@ -1642,7 +1668,6 @@
if (isSelectionEmpty())
{
_fixInsertionPointCoords();
- _drawInsertionPoint();
}
return bRet;
@@ -1908,7 +1933,6 @@
_generalUpdate();
_fixInsertionPointCoords();
- _drawInsertionPoint();
}
/*
@@ -1929,15 +1953,7 @@
UT_uint32 selLength = labs(m_iInsPoint - m_iSelectionAnchor);
- PT_DocPosition low;
- if (m_iInsPoint > m_iSelectionAnchor)
- {
- low = m_iSelectionAnchor;
- }
- else
- {
- low = m_iInsPoint;
- }
+ const PT_DocPosition low = UT_MIN(m_iInsPoint, m_iSelectionAnchor);
// get the current block the insertion point is in
fl_BlockLayout * block = m_pLayout->findBlockAtPosition(low);
@@ -1973,17 +1989,15 @@
const XML_Char ** props_in = NULL;
const XML_Char * currentfont;
+ FV_CursorDisabler disabler(*m_pCursor);
+
if (!isSelectionEmpty())
{
_deleteSelection();
_generalUpdate();
- if (!_ensureThatInsertionPointIsOnScreen())
- {
- _fixInsertionPointCoords();
- _drawInsertionPoint();
- }
+ _updateInsertionPoint();
}
else
{
@@ -1999,7 +2013,6 @@
currentfont = UT_getAttribute("font-family",props_in);
properties[1] = currentfont;
- _eraseInsertionPoint();
UT_uint32 amt = count;
UT_uint32 posCur = getPoint();
UT_uint32 nposCur = getPoint();
@@ -2051,16 +2064,29 @@
_generalUpdate();
free(props_in);
- if (!_ensureThatInsertionPointIsOnScreen())
- {
- _fixInsertionPointCoords();
- _drawInsertionPoint();
- }
+ _updateInsertionPoint();
}
}
void FV_View::_moveInsPtNextPrevLine(UT_Bool bNext)
{
+#ifdef ABW_CURSOR_EXTERNAL_CLASS
+ if (bNext)
+ {
+ m_pCursor->down();
+ }
+ else
+ {
+ m_pCursor->up();
+ }
+
+ _setPoint(m_pCursor->getDocPos(), m_pCursor->isAtEOL());
+
+ _updateInsertionPoint();
+
+#else // ABW_CURSOR_EXTERNAL_CLASS
+//#endif // ABW_CURSOR_EXTERNAL_CLASS
+
UT_sint32 xPoint;
UT_sint32 yPoint;
UT_sint32 iPointHeight, iLineHeight;
@@ -2191,7 +2217,6 @@
if (bNOOP)
{
// cannot move. should we beep?
- _drawInsertionPoint();
return;
}
@@ -2215,14 +2240,13 @@
_setPoint(iNewPoint, bEOL);
- if (!_ensureThatInsertionPointIsOnScreen())
- {
- _fixInsertionPointCoords();
- _drawInsertionPoint();
- }
+ _updateInsertionPoint();
// this is the only place where we override changes to m_xPointSticky
m_xPointSticky = xOldSticky;
+
+#endif // ABW_CURSOR_EXTERNAL_CLASS
+
}
UT_Bool FV_View::_ensureThatInsertionPointIsOnScreen(void)
@@ -2243,12 +2267,22 @@
cmdScroll(AV_SCROLLCMD_LINEUP, (UT_uint32) (-(m_yPoint)));
bRet = UT_TRUE;
}
+#ifdef ABW_CURSOR_EXTERNAL_CLASS
+ else if (((UT_uint32) (m_yPoint + m_pCursor->getPointHeight())) >=
+((UT_uint32) m_iWindowHeight))
+ {
+ cmdScroll(AV_SCROLLCMD_LINEDOWN, (UT_uint32)(m_yPoint +
+m_pCursor->getPointHeight() - m_iWindowHeight));
+ bRet = UT_TRUE;
+ }
+
+#else
else if (((UT_uint32) (m_yPoint + m_iPointHeight)) >= ((UT_uint32)
m_iWindowHeight))
{
cmdScroll(AV_SCROLLCMD_LINEDOWN, (UT_uint32)(m_yPoint + m_iPointHeight
- m_iWindowHeight));
bRet = UT_TRUE;
}
+#endif
+
/*
TODO: we really ought to try to do better than this.
*/
@@ -2297,6 +2331,20 @@
PT_DocPosition iNewPoint = pPage->getFirstLastPos(UT_TRUE);
_setPoint(iNewPoint, UT_FALSE);
+#ifdef ABW_CURSOR_EXTERNAL_CLASS
+ if (bNext)
+ {
+ m_pCursor->pageDown();
+ }
+ else
+ {
+ m_pCursor->pageUp();
+ }
+ // TMN: Remove when PgUp/PgDn is handled
+ m_pCursor->setDocPos(iNewPoint);
+
+#endif // ABW_CURSOR_EXTERNAL_CLASS
+
// explicit vertical scroll to top of page
UT_sint32 iPageOffset;
getPageYOffset(pPage, iPageOffset);
@@ -2317,32 +2365,45 @@
}
// also allow implicit horizontal scroll, if needed
- if (!_ensureThatInsertionPointIsOnScreen() && !bVScroll)
+ if (!bVScroll)
{
- _fixInsertionPointCoords();
- _drawInsertionPoint();
+ _updateInsertionPoint();
}
}
void FV_View::warpInsPtNextPrevPage(UT_Bool bNext)
{
if (!isSelectionEmpty())
+ {
_moveToSelectionEnd(bNext);
- else
- _eraseInsertionPoint();
+ }
_resetSelection();
_clearIfAtFmtMark(getPoint());
_moveInsPtNextPrevPage(bNext);
+
+#ifdef ABW_CURSOR_EXTERNAL_CLASS
+ if (bNext)
+ {
+ m_pCursor->pageDown();
+ }
+ else
+ {
+ m_pCursor->pageUp();
+ }
+#endif // ABW_CURSOR_EXTERNAL_CLASS
+
notifyListeners(AV_CHG_MOTION);
}
void FV_View::warpInsPtNextPrevLine(UT_Bool bNext)
{
+ FV_CursorDisabler disabler(*m_pCursor);
+
if (!isSelectionEmpty())
+ {
_moveToSelectionEnd(bNext);
- else
- _eraseInsertionPoint();
+ }
_resetSelection();
_clearIfAtFmtMark(getPoint());
@@ -2352,6 +2413,8 @@
void FV_View::extSelNextPrevLine(UT_Bool bNext)
{
+ FV_CursorDisabler disabler(*m_pCursor);
+
if (isSelectionEmpty())
{
_setSelectionAnchor();
@@ -2360,7 +2423,6 @@
if (isSelectionEmpty())
{
_fixInsertionPointCoords();
- _drawInsertionPoint();
}
else
{
@@ -2383,7 +2445,6 @@
{
_resetSelection();
_fixInsertionPointCoords();
- _drawInsertionPoint();
}
}
@@ -2394,7 +2455,6 @@
{
if (isSelectionEmpty())
{
- _eraseInsertionPoint();
_setSelectionAnchor();
_charMotion(bForward, count);
}
@@ -2405,6 +2465,11 @@
if (_charMotion(bForward, count) == UT_FALSE)
{
_setPoint(iOldPoint);
+
+#ifdef ABW_CURSOR_EXTERNAL_CLASS
+ m_pCursor->setDocPos(iOldPoint);
+#endif
+
return;
}
@@ -2423,7 +2488,6 @@
{
_resetSelection();
_fixInsertionPointCoords();
- _drawInsertionPoint();
}
else
{
@@ -2439,14 +2503,7 @@
_extSelToPos(iPos);
- if (!_ensureThatInsertionPointIsOnScreen())
- {
- if (isSelectionEmpty())
- {
- _fixInsertionPointCoords();
- _drawInsertionPoint();
- }
- }
+ _updateInsertionPoint();
notifyListeners(AV_CHG_MOTION);
}
@@ -2476,7 +2533,6 @@
if (!pView->_ensureThatInsertionPointIsOnScreen())
{
pView->_fixInsertionPointCoords();
-// pView->_drawInsertionPoint();
}
}
else
@@ -2770,24 +2826,18 @@
UT_Bool FV_View::findNext(const UT_UCSChar * find, UT_Bool matchCase, UT_Bool *
bDoneEntireDocument)
{
+ FV_CursorDisabler disabler(*m_pCursor);
+
if (!isSelectionEmpty())
{
_clearSelection();
}
- else
- {
- _eraseInsertionPoint();
- }
UT_Bool bRes = _findNext(find, matchCase, bDoneEntireDocument);
if (isSelectionEmpty())
{
- if (!_ensureThatInsertionPointIsOnScreen())
- {
- _fixInsertionPointCoords();
- _drawInsertionPoint();
- }
+ _updateInsertionPoint();
}
else
{
@@ -2834,6 +2884,11 @@
if (foundAt != -1)
{
_setPoint(block->getPosition(UT_FALSE) + offset + foundAt);
+
+#ifdef ABW_CURSOR_EXTERNAL_CLASS
+ m_pCursor->setDocPos(block->getPosition(UT_FALSE) + offset +
+foundAt);
+#endif
+
_setSelectionAnchor();
_charMotion(UT_TRUE, UT_UCS_strlen(find));
@@ -2991,6 +3046,8 @@
UT_Bool FV_View::findAgain()
{
+ FV_CursorDisabler disabler(*m_pCursor);
+
if (_m_findNextString && *_m_findNextString)
{
UT_Bool bRes = findNext(_m_findNextString, _m_matchCase, NULL);
@@ -3016,11 +3073,7 @@
if (isSelectionEmpty())
{
- if (!_ensureThatInsertionPointIsOnScreen())
- {
- _fixInsertionPointCoords();
- _drawInsertionPoint();
- }
+ _updateInsertionPoint();
}
else
{
@@ -3045,10 +3098,6 @@
{
_deleteSelection();
}
- else
- {
- _eraseInsertionPoint();
- }
// if we have a string with length, do an insert, else let it hang
// from the delete above
@@ -3145,6 +3194,10 @@
TODO WRONG! WRONG! WRONG! will get each view on the document.
*/
notifyListeners(AV_CHG_TYPING | AV_CHG_FMTCHAR | AV_CHG_FMTBLOCK);
+
+#ifdef ABW_CURSOR_EXTERNAL_CLASS
+ m_pCursor->setDocPos(getPoint());
+#endif
}
UT_uint32 FV_View::findReplaceAll(const UT_UCSChar * find, const UT_UCSChar * replace,
@@ -3182,11 +3235,7 @@
if (isSelectionEmpty())
{
- if (!_ensureThatInsertionPointIsOnScreen())
- {
- _fixInsertionPointCoords();
- _drawInsertionPoint();
- }
+ _updateInsertionPoint();
}
else
{
@@ -3359,20 +3408,25 @@
if (iNewPoint == iOldPoint)
return;
+ FV_CursorDisabler disabler(*m_pCursor);
+
if (isSelectionEmpty())
{
- _eraseInsertionPoint();
_clearIfAtFmtMark(getPoint());
_setSelectionAnchor();
}
_setPoint(iNewPoint);
+
+#ifdef ABW_CURSOR_EXTERNAL_CLASS
+ m_pCursor->setDocPos(iNewPoint);
+#endif
+
_extSel(iOldPoint);
if (isSelectionEmpty())
{
_resetSelection();
- _drawInsertionPoint();
}
notifyListeners(AV_CHG_MOTION);
@@ -3387,10 +3441,12 @@
UT_sint32 xClick, yClick;
fp_Page* pPage = _getPageForXY(xPos, yPos, xClick, yClick);
+ // This disabler is probably not needed here. It won't harm
+ // [noticable/much] though.
+ FV_CursorDisabler disabler(*m_pCursor);
+
if (!isSelectionEmpty())
_clearSelection();
- else
- _eraseInsertionPoint();
PT_DocPosition pos;
UT_Bool bBOL = UT_FALSE;
@@ -3402,8 +3458,12 @@
_clearIfAtFmtMark(getPoint());
_setPoint(pos, bEOL);
+
+#ifdef ABW_CURSOR_EXTERNAL_CLASS
+ m_pCursor->setDocPos(pos, bEOL);
+#endif
+
_fixInsertionPointCoords();
- _drawInsertionPoint();
notifyListeners(AV_CHG_MOTION);
}
@@ -3426,7 +3486,7 @@
}
yoff = y - m_yScrollOffset;
- xoff = fl_PAGEVIEW_MARGIN_Y - m_xScrollOffset;
+ xoff = fl_PAGEVIEW_MARGIN_X - m_xScrollOffset;
}
void FV_View::getPageYOffset(fp_Page* pThePage, UT_sint32& yoff)
@@ -3474,6 +3534,8 @@
{
UT_ASSERT(iPos1 < iPos2);
+ FV_CursorDisabler disabler(*m_pCursor);
+
fp_Run* pRun1;
fp_Run* pRun2;
UT_sint32 xoff;
@@ -3676,100 +3738,32 @@
void FV_View::_fixInsertionPointCoords()
{
+#ifdef ABW_CURSOR_EXTERNAL_CLASS
+ UT_uint32 nDummyPointHeight;
+ _findPositionCoords(m_pCursor->getDocPos(), m_bPointEOL, m_xPoint, m_yPoint,
+nDummyPointHeight, NULL, NULL);
+
+ // TMN: This call is possibly redundant
+ m_pCursor->setDocPos(getPoint(), m_bPointEOL);
+
+#else
_findPositionCoords(getPoint(), m_bPointEOL, m_xPoint, m_yPoint,
m_iPointHeight, NULL, NULL);
// hang onto this for _moveInsPtNextPrevLine()
m_xPointSticky = m_xPoint + m_xScrollOffset - fl_PAGEVIEW_MARGIN_X;
+
+#endif
}
void FV_View::_updateInsertionPoint()
{
- if (isSelectionEmpty())
- {
- _eraseInsertionPoint();
+ FV_CursorDisabler disabler(*m_pCursor);
if (!_ensureThatInsertionPointIsOnScreen())
{
_fixInsertionPointCoords();
- _drawInsertionPoint();
- }
}
}
-void FV_View::_xorInsertionPoint()
-{
- if (m_iPointHeight > 0)
- {
- UT_RGBColor clr(255,255,255);
-
- m_pG->setColor(clr);
- m_pG->xorLine(m_xPoint-1, m_yPoint, m_xPoint-1, m_yPoint +
m_iPointHeight);
- m_pG->xorLine(m_xPoint, m_yPoint, m_xPoint, m_yPoint + m_iPointHeight);
- }
-}
-
-void FV_View::_eraseInsertionPoint()
-{
- if (m_pAutoCursorTimer)
- m_pAutoCursorTimer->stop();
-
- if (!isSelectionEmpty() || !m_bCursorIsOn)
- {
- return;
- }
-
- _xorInsertionPoint();
-}
-
-void FV_View::_drawInsertionPoint()
-{
- if(m_focus==AV_FOCUS_NONE)
- return;
- if (m_bCursorBlink && (m_focus==AV_FOCUS_HERE || m_focus==AV_FOCUS_MODELESS) )
- {
- if (m_pAutoCursorTimer == NULL) {
- m_pAutoCursorTimer =
UT_Timer::static_constructor(_autoDrawPoint, this, m_pG);
- m_pAutoCursorTimer->set(AUTO_DRAW_POINT);
- }
-
- m_pAutoCursorTimer->start();
- }
-
- m_bCursorIsOn = UT_TRUE;
-
- if (m_iWindowHeight <= 0)
- {
- return;
- }
-
- if (!isSelectionEmpty())
- {
- return;
- }
-
- _xorInsertionPoint();
-}
-
-void FV_View::_autoDrawPoint(UT_Timer * pTimer)
-{
- UT_ASSERT(pTimer);
-
- FV_View * pView = (FV_View *) pTimer->getInstanceData();
- UT_ASSERT(pView);
-
- if (pView->m_iWindowHeight <= 0)
- {
- return;
- }
-
- if (!pView->isSelectionEmpty())
- {
- return;
- }
- pView->_xorInsertionPoint();
- pView->m_bCursorIsOn = !pView->m_bCursorIsOn;
-}
-
void FV_View::setXScrollOffset(UT_sint32 v)
{
UT_sint32 dx = v - m_xScrollOffset;
@@ -3842,6 +3836,8 @@
{
xxx_UT_DEBUGMSG(("FV_View::draw_1: [page %ld]\n",page));
+ FV_CursorDisabler disabler(*m_pCursor);
+
da->pG = m_pG;
fp_Page* pPage = m_pLayout->getNthPage(page);
if (pPage)
@@ -3877,6 +3873,8 @@
x,y,width,height,bClip,
m_yScrollOffset,m_iWindowHeight));
+ FV_CursorDisabler disabler(*m_pCursor);
+
// this can happen when the frame size is decreased and
// only the toolbars show...
if ((m_iWindowWidth <= 0) || (m_iWindowHeight <= 0))
@@ -4068,7 +4066,6 @@
if (!bDirtyRunsOnly)
{
_fixInsertionPointCoords();
- _drawInsertionPoint();
}
if (bClip)
@@ -4099,7 +4096,7 @@
UT_Bool bVertical = UT_FALSE;
UT_Bool bHorizontal = UT_FALSE;
- _eraseInsertionPoint();
+ FV_CursorDisabler disabler(*m_pCursor);
docHeight = m_pLayout->getHeight();
@@ -4170,12 +4167,9 @@
yoff = 0;
}
- UT_Bool bRedrawPoint = UT_TRUE;
-
if (bVertical && (yoff != m_yScrollOffset))
{
sendVerticalScrollEvent(yoff);
- bRedrawPoint = UT_FALSE;
}
if (xoff < 0)
@@ -4186,12 +4180,6 @@
if (bHorizontal && (xoff != m_xScrollOffset))
{
sendHorizontalScrollEvent(xoff);
- bRedrawPoint = UT_FALSE;
- }
-
- if (bRedrawPoint)
- {
- _drawInsertionPoint();
}
}
@@ -4217,9 +4205,9 @@
void FV_View::cmdSelect(UT_sint32 xPos, UT_sint32 yPos, FV_DocPos dpBeg, FV_DocPos
dpEnd)
{
- warpInsPtToXY(xPos, yPos);
+ FV_CursorDisabler disabler(*m_pCursor);
- _eraseInsertionPoint();
+ warpInsPtToXY(xPos, yPos);
PT_DocPosition iPosLeft = _getDocPos(dpBeg, UT_FALSE);
PT_DocPosition iPosRight = _getDocPos(dpEnd, UT_FALSE);
@@ -4235,10 +4223,13 @@
_setPoint(iPosRight);
+#ifdef ABW_CURSOR_EXTERNAL_CLASS
+ m_pCursor->setDocPos(iPosRight);
+#endif
+
if (iPosLeft == iPosRight)
{
_fixInsertionPointCoords();
- _drawInsertionPoint();
return;
}
@@ -4256,6 +4247,10 @@
m_iInsPoint = pt;
m_bPointEOL = bEOL;
+// TMN: I don't know if the following call will be needed or not.
+// Just in case someone wants to test, I leave it here for now.
+// m_pCursor->setDocPos(pt, bEOL);
+
_checkPendingWord();
}
@@ -4279,6 +4274,21 @@
}
}
+void FV_View::_disableCursor()
+{
+#ifdef ABW_CURSOR_EXTERNAL_CLASS
+ m_pCursor->disable();
+#endif
+}
+
+void FV_View::_enableCursor()
+{
+#ifdef ABW_CURSOR_EXTERNAL_CLASS
+ m_pCursor->enable();
+#endif
+}
+
+
UT_uint32 FV_View::_getDataCount(UT_uint32 pt1, UT_uint32 pt2)
{
UT_ASSERT(pt2>=pt1);
@@ -4359,10 +4369,12 @@
void FV_View::cmdUndo(UT_uint32 count)
{
+ FV_CursorDisabler disabler(*m_pCursor);
+
if (!isSelectionEmpty())
+ {
_clearSelection();
- else
- _eraseInsertionPoint();
+ }
m_pDoc->undoCmd(count);
@@ -4370,54 +4382,48 @@
notifyListeners(AV_CHG_DIRTY);
- if (isSelectionEmpty())
- {
- if (!_ensureThatInsertionPointIsOnScreen())
- {
- _fixInsertionPointCoords();
- _drawInsertionPoint();
- }
- }
+ _updateInsertionPoint();
}
void FV_View::cmdRedo(UT_uint32 count)
{
+ FV_CursorDisabler disabler(*m_pCursor);
+
if (!isSelectionEmpty())
+ {
_clearSelection();
- else
- _eraseInsertionPoint();
+ }
m_pDoc->redoCmd(count);
_generalUpdate();
- if (isSelectionEmpty())
- {
- if (!_ensureThatInsertionPointIsOnScreen())
- {
- _fixInsertionPointCoords();
- _drawInsertionPoint();
- }
- }
+ _updateInsertionPoint();
}
UT_Error FV_View::cmdSave(void)
{
- UT_Error tmpVar;
- tmpVar = m_pDoc->save();
- if (!tmpVar)
+ const UT_Error saveError = m_pDoc->save();
+
+ if (!saveError)
+ {
notifyListeners(AV_CHG_SAVE);
- return tmpVar;
+ }
+
+ return saveError;
}
UT_Error FV_View::cmdSaveAs(const char * szFilename, int ieft)
{
- UT_Error tmpVar;
- tmpVar = m_pDoc->saveAs(szFilename, ieft);
- if (!tmpVar)
+ const UT_Error saveError = m_pDoc->saveAs(szFilename, ieft);
+
+ if (!saveError)
+ {
notifyListeners(AV_CHG_SAVE);
- return tmpVar;
+ }
+
+ return saveError;
}
@@ -4435,7 +4441,6 @@
_generalUpdate();
_fixInsertionPointCoords();
- _drawInsertionPoint();
}
void FV_View::getDocumentRangeOfCurrentSelection(PD_DocumentRange * pdr)
@@ -4489,6 +4494,8 @@
// be a selection to paste when get there. this is sort of
// back door hack and should probably be re-thought.
+ // TMN: I agree. X11 code have NO business in XP code.
+
// set UAG markers around everything that the actual paste does
// so that undo/redo will treat it as one step.
@@ -4505,10 +4512,12 @@
{
// internal portion of paste operation.
+ FV_CursorDisabler disabler(*m_pCursor);
+
if (!isSelectionEmpty())
+ {
_deleteSelection();
- else
- _eraseInsertionPoint();
+ }
_clearIfAtFmtMark(getPoint());
PD_DocumentRange dr(m_pDoc,getPoint(),getPoint());
@@ -4516,18 +4525,15 @@
_generalUpdate();
- if (!_ensureThatInsertionPointIsOnScreen())
- {
- _fixInsertionPointCoords();
- _drawInsertionPoint();
- }
+ _updateInsertionPoint();
}
UT_Bool FV_View::setSectionFormat(const XML_Char * properties[])
{
UT_Bool bRet;
- _eraseInsertionPoint();
+ FV_CursorDisabler disabler(*m_pCursor);
+
_clearIfAtFmtMark(getPoint());
PT_DocPosition posStart = getPoint();
@@ -4548,7 +4554,6 @@
if (isSelectionEmpty())
{
_fixInsertionPointCoords();
- _drawInsertionPoint();
}
return bRet;
@@ -4686,6 +4691,8 @@
NULL, NULL
};
+ FV_CursorDisabler disabler(*m_pCursor);
+
if (!isSelectionEmpty())
{
m_pDoc->beginUserAtomicGlob();
@@ -4695,17 +4702,12 @@
}
else
{
- _eraseInsertionPoint();
bResult = m_pDoc->insertObject(getPoint(), PTO_Field, attributes,
NULL);
}
_generalUpdate();
- if (!_ensureThatInsertionPointIsOnScreen())
- {
- _fixInsertionPointCoords();
- _drawInsertionPoint();
- }
+ _updateInsertionPoint();
return bResult;
}
@@ -4729,10 +4731,6 @@
m_pDoc->beginUserAtomicGlob();
_deleteSelection();
}
- else
- {
- _eraseInsertionPoint();
- }
/*
First, find a unique name for the data item.
@@ -4756,11 +4754,7 @@
_generalUpdate();
- if (!_ensureThatInsertionPointIsOnScreen())
- {
- _fixInsertionPointCoords();
- _drawInsertionPoint();
- }
+ _updateInsertionPoint();
return errorCode;
}
@@ -4889,9 +4883,19 @@
// TODO selection region.
if (pxPos)
+ {
*pxPos = m_xPoint;
+ }
+
if (pyPos)
+ {
+#ifdef ABW_CURSOR_EXTERNAL_CLASS
+ *pyPos = m_yPoint + m_pCursor->getPointHeight();
+#else
*pyPos = m_yPoint + m_iPointHeight;
+#endif
+ }
+
return emc;
}
@@ -5096,6 +5100,15 @@
FV_View *pView = (FV_View *)data;
UT_Bool b;
UT_ASSERT(data && pPrefs);
+
+#ifdef ABW_CURSOR_EXTERNAL_CLASS
+ UT_Bool bCursorBlink;
+ if (pPrefs->getPrefsValueBool(AP_PREF_KEY_CursorBlink, &b))
+ {
+ pView->m_pCursor->setBlink(b);
+ pView->_updateInsertionPoint();
+ }
+#else
if ( pPrefs->getPrefsValueBool(AP_PREF_KEY_CursorBlink, &b) && b !=
pView->m_bCursorBlink )
{
UT_DEBUGMSG(("FV_View::_prefsListener m_bCursorBlink=%s
m_bCursorIsOn=%s\n",
@@ -5114,6 +5127,7 @@
pView->_updateInsertionPoint();
}
+#endif
}
/******************************************************
@@ -5222,4 +5236,4 @@
m_bShowPara = bShowPara;
draw();
}
-};
+}
--- fv_View.h Thu May 18 11:01:12 2000
+++ \AbiWord\abi\src\text\fmt\xp\fv_View.h Mon May 22 17:15:26 2000
@@ -31,6 +31,9 @@
// number of milliseconds between cursor blinks
const int AUTO_DRAW_POINT = 600;
+// Define if we're using the FV_Cursor class
+#define ABW_CURSOR_EXTERNAL_CLASS
+
class FL_DocLayout;
class fl_DocListener;
class fl_BlockLayout;
@@ -46,9 +49,10 @@
class XAP_App;
class XAP_Prefs;
class UT_AlphaHashTable;
+class FV_Cursor;
-typedef enum _FVDocPos
+enum FV_DocPos
{
FV_DOCPOS_BOB, FV_DOCPOS_EOB, // block
FV_DOCPOS_BOD, FV_DOCPOS_EOD, // document
@@ -56,13 +60,13 @@
FV_DOCPOS_BOL, FV_DOCPOS_EOL, // line
FV_DOCPOS_BOS, FV_DOCPOS_EOS, // sentence
FV_DOCPOS_BOW, FV_DOCPOS_EOW_MOVE, FV_DOCPOS_EOW_SELECT // word
-} FV_DocPos;
+};
-typedef enum _FVJumpTarget
+enum FV_JumpTarget
{
FV_JUMPTARGET_PAGE, // beginning of page
FV_JUMPTARGET_LINE // beginning of line
-} FV_JumpTarget;
+};
struct fv_ChangeState
{
@@ -97,7 +101,7 @@
~FV_View();
inline GR_Graphics* getGraphics(void) const { return m_pG; }
- inline UT_uint32 getPoint(void) const { return m_iInsPoint; }
+ inline PT_DocPosition getPoint(void) const { return m_iInsPoint; }
inline UT_uint32 getSelectionAnchor(void) const { return
m_bSelection? m_iSelectionAnchor : m_iInsPoint; }
virtual void focusChange(AV_Focus focus);
@@ -273,11 +277,8 @@
void _setSelectionAnchor(void);
void _deleteSelection(void);
UT_Bool _insertFormatPair(const XML_Char * szName,
const XML_Char * properties[]);
- void _eraseInsertionPoint();
- void _drawInsertionPoint();
void _updateInsertionPoint();
void _fixInsertionPointCoords();
- void _xorInsertionPoint();
void _drawSelection();
void _swapSelectionOrientation(void);
void _extSel(UT_uint32 iOldPoint);
@@ -287,7 +288,6 @@
UT_UCSChar * _lookupSuggestion(fl_BlockLayout* pBL, fl_PartOfBlock*
pPOB, UT_uint32 ndx);
static void _autoScroll(UT_Timer * pTimer);
- static void _autoDrawPoint(UT_Timer * pTimer);
// localize handling of insertion point logic
void _setPoint(UT_uint32 pt, UT_Bool bEOL =
UT_FALSE);
@@ -298,14 +298,20 @@
void _checkPendingWord(void);
+ // fl_BlockLayout seems to need these. Check if it can be removed!
+ void _disableCursor();
+ void _enableCursor();
PT_DocPosition m_iInsPoint;
UT_sint32 m_xPoint;
UT_sint32 m_yPoint;
+
+#ifndef ABW_CURSOR_EXTERNAL_CLASS
UT_uint32 m_iPointHeight;
UT_sint32 m_xPointSticky; // used only for
_moveInsPtNextPrevLine()
+#endif
UT_Bool m_bPointVisible;
UT_Bool m_bPointEOL;
@@ -313,7 +319,6 @@
FL_DocLayout* m_pLayout;
PD_Document* m_pDoc;
GR_Graphics* m_pG;
- void * m_pParentData;
PT_DocPosition m_iSelectionAnchor;
PT_DocPosition m_iSelectionLeftAnchor;
@@ -325,8 +330,6 @@
UT_sint32 m_xLastMouse;
UT_sint32 m_yLastMouse;
- UT_Timer * m_pAutoCursorTimer;
- UT_Bool m_bCursorIsOn;
UT_Bool m_bCursorBlink;
fv_ChangeState m_chg;
@@ -355,7 +358,16 @@
// prefs listener - to change cursor blink on/off (and possibly others)
static void _prefsListener( XAP_App *, XAP_Prefs *, UT_AlphaHashTable *, void
*);
+private:
+ // Not that FV_View can be copied, since its baseclass is non-copyable,
+ // but this puts this "documentation" closer to the user.
+ FV_View(const FV_View&); // no impl.
+ void operator=(const FV_View&); // no impl.
+
UT_Bool m_bShowPara;
+
+ // By ptr to minimize compile-time dependencies
+ FV_Cursor* m_pCursor;
};
#endif /* FV_VIEW_H */
--- fl_BlockLayout.cpp Thu May 18 11:01:12 2000
+++ \AbiWord\abi\src\text\fmt\xp\fl_BlockLayout.cpp Mon May 22 14:23:28 2000
@@ -879,7 +879,11 @@
return m_pDoc->getBlockBuf(m_sdh, pgb);
}
-fp_Run* fl_BlockLayout::findPointCoords(PT_DocPosition iPos, UT_Bool bEOL, UT_sint32&
x, UT_sint32& y, UT_sint32& height)
+fp_Run* fl_BlockLayout::findPointCoords(PT_DocPosition iPos,
+
+UT_Bool bEOL,
+
+UT_sint32& x,
+
+UT_sint32& y,
+
+UT_sint32& height)
{
// find the run which has this position inside it.
@@ -901,34 +905,35 @@
UT_uint32 iWhere = pRun->containsOffset(iRelOffset);
if (FP_RUN_JUSTAFTER == iWhere)
{
- if(pRun->getNext())
+ fp_Run* pNextRun = pRun->getNext();
+ if (bEOL)
{
- if(pRun->getNext()->containsOffset(iRelOffset) ==
FP_RUN_INSIDE)
+ const fp_Line* pNextLine = pNextRun ?
+pNextRun->getLine() : 0;
+
+ if (pNextLine != pRun->getLine())
{
pRun->findPointCoords(iRelOffset, x, y, height);
- return pRun->getNext();
- }
- }
+ return pRun;
}
- if (FP_RUN_INSIDE == iWhere)
+
+ if (pNextRun)
{
pRun->findPointCoords(iRelOffset, x, y, height);
- return pRun;
+ return pNextRun;
+ }
}
- else if (bEOL && (FP_RUN_JUSTAFTER == iWhere))
+ if (pNextRun &&
+ pNextRun->containsOffset(iRelOffset) == FP_RUN_INSIDE)
{
- fp_Run* pNext = pRun->getNext();
- fp_Line* pNextLine = NULL;
-
- if (pNext)
- pNextLine = pNext->getLine();
-
- if (pNextLine != pRun->getLine())
+ pNextRun->findPointCoords(iRelOffset, x, y, height);
+ return pNextRun;
+ }
+ }
+ if (FP_RUN_INSIDE == iWhere)
{
pRun->findPointCoords(iRelOffset, x, y, height);
return pRun;
}
- }
pRun = pRun->getNext();
}
@@ -940,7 +945,7 @@
if ((FP_RUN_JUSTAFTER == iWhere))
{
fp_Run* nextRun = pRun->getNext();
- if (nextRun)
+ if (nextRun && nextRun->canContainPoint())
{
nextRun->lookupProperties();
nextRun->findPointCoords(iRelOffset, x, y, height);
@@ -1561,7 +1566,7 @@
{
bUpdateScreen = UT_TRUE;
if (pView)
- pView->_eraseInsertionPoint();
+ pView->_disableCursor();
}
_updateSquiggle(pPOB);
@@ -1577,7 +1582,7 @@
if (bUpdateScreen && pView)
{
pView->updateScreen();
- pView->_drawInsertionPoint();
+ pView->_enableCursor();
}
}
@@ -1658,7 +1663,7 @@
FV_View* pView = m_pLayout->getView();
if (pView)
- pView->_eraseInsertionPoint();
+ pView->_disableCursor();
}
// squiggle it
@@ -2465,20 +2470,6 @@
delete pNuke;
}
-#if 0
- //BUG: Code from Mike that crashes hard
-
- UT_ASSERT(pRun);
-
- m_pFirstRun = pRun;
-
- // then link what's left
- m_pFirstRun->insertIntoRunListAfterThis(*pLastRun);
-
-
-#else
- //BUG: Quick and Dirty Replacement Code
-
m_pFirstRun = pRun;
//then link what's left
@@ -2488,7 +2479,6 @@
{
m_pFirstRun->setPrev(pLastRun);
}
-#endif
}
else
@@ -3329,7 +3319,10 @@
if (pView)
{
pView->_resetSelection();
+#if 0
+ // TMN: Can really a FmtMark change DocPos?!
pView->_setPoint(pcrfm->getPosition());
+#endif
pView->notifyListeners(AV_CHG_FMTCHAR);
}
@@ -3357,7 +3350,11 @@
if (pView)
{
pView->_resetSelection();
+#if 0
+ // TMN: If addition of a FmtMark can't change
+ // cursor DocPos, neither can removal of one.
pView->_setPoint(pcrfm->getPosition());
+#endif
pView->notifyListeners(AV_CHG_FMTCHAR);
}
@@ -3541,6 +3538,6 @@
if (bUpdate && pView)
{
pView->updateScreen();
- pView->_drawInsertionPoint();
+ pView->_enableCursor();
}
}