mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-27 10:50:35 +00:00
712 lines
24 KiB
C++
712 lines
24 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public License
|
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
* http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
* for the specific language governing rights and limitations under the
|
|
* NPL.
|
|
*
|
|
* The Initial Developer of this code under the NPL is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
* Reserved.
|
|
*/
|
|
|
|
// edlayout.cpp : implementation of Editor-only FE layout functions
|
|
//
|
|
// Created 9/16/96 by CLM
|
|
//
|
|
#include "stdafx.h"
|
|
|
|
#include "dialog.h"
|
|
#include "mainfrm.h"
|
|
#include "netsvw.h"
|
|
#include "edview.h"
|
|
|
|
// Utility function to check if it is OK to show the caret. It is used in the FE functions that
|
|
// are called by the back end to show caret.
|
|
static BOOL IsOkToShowCaret(CNetscapeEditView *pView, char *FE_FuncName)
|
|
{
|
|
// Prevent setting caret when we have a modal (e.g. property) dialog over us
|
|
CFrameWnd *pFrame = pView->GetFrame()->GetFrameWnd();
|
|
if(pFrame && pFrame->GetLastActivePopup() != pFrame){
|
|
return FALSE;
|
|
}
|
|
|
|
// This will allow us to use the regular caret for drop-point feedback
|
|
// even if window does not have focus
|
|
// Don't display caret if the editor view does not have focus.
|
|
// unless we are dragging over our view
|
|
if( !pView->m_bDragOver && pView->GetFocus() != pView ){
|
|
return FALSE;
|
|
}
|
|
return TRUE; // OK to show caret
|
|
}
|
|
|
|
// Caret used during Drag&Drop - more visible than regular cursor
|
|
extern CBitmap ed_DragCaretBitmap;
|
|
|
|
#define ED_DRAGCARET_HEIGHT 32
|
|
|
|
static void AdjustForDragCaret(CCaret * pCaret)
|
|
{
|
|
// NOTE: This assumes IDB_ED_DRAG bitmap is 3 by ED_DRAGCARET_HEIGHT
|
|
// and regular caret is 2 pixels wide
|
|
|
|
// Back off one on X
|
|
pCaret->x--;
|
|
|
|
// Only one size for drop caret, so reposition vertically
|
|
pCaret->y -= ED_DRAGCARET_HEIGHT - pCaret->height;
|
|
|
|
pCaret->width = 3;
|
|
pCaret->height = ED_DRAGCARET_HEIGHT;
|
|
}
|
|
|
|
//
|
|
// The text has been drawn. This code will position the text caret in the
|
|
// proper position and height.
|
|
//
|
|
PUBLIC void
|
|
FE_DisplayTextCaret(MWContext * context, int loc, LO_TextStruct * text_data,
|
|
int char_offset)
|
|
{
|
|
if(!context || !EDT_IS_EDITOR(context) || !text_data || !text_data->text_attr)
|
|
return;
|
|
|
|
int32 xVal, yVal;
|
|
|
|
CWinCX *pWinCX = VOID2CX(context->fe.cx, CWinCX);
|
|
CNetscapeEditView * pView = (CNetscapeEditView *)pWinCX->GetView();
|
|
|
|
HDC hDC = pView->GetContextDC();
|
|
|
|
int32 xOrigin = WINCX(context)->GetOriginX();
|
|
|
|
// Figure out X and Y coords of the text in the View's coordinate system
|
|
xVal = text_data->x + text_data->x_offset - xOrigin;
|
|
yVal = text_data->y + text_data->y_offset - WINCX(context)->GetOriginY();
|
|
|
|
CPoint cDocPoint(CASTINT(text_data->x), CASTINT(text_data->y));
|
|
if( pWinCX->PtInSelectedRegion(cDocPoint) && pView->m_caret.bEnabled ){
|
|
DestroyCaret();
|
|
pView->m_caret.cShown = 0;
|
|
pView->m_caret.bEnabled = FALSE;
|
|
}
|
|
|
|
// Only draw text that falls within the curently viewed part of the frame
|
|
if((yVal < pWinCX->GetHeight()) && (yVal < 32000)) {
|
|
|
|
// Get the font so we can get its height
|
|
CyaFont *pMyFont;
|
|
pWinCX->SelectNetscapeFontWithCache( hDC, text_data->text_attr, pMyFont );
|
|
|
|
// Calculate offset within text
|
|
CSize cSize(0,0);
|
|
const char *pText = (const char*)text_data->text;
|
|
// Win16 barfs on this if null string
|
|
if( char_offset > 0 && pText && *pText != '\0' ){
|
|
pWinCX->ResolveTextExtent(hDC, pText, char_offset, &cSize, pMyFont );
|
|
}
|
|
|
|
pWinCX->ReleaseNetscapeFontWithCache( hDC, pMyFont );
|
|
//
|
|
// The caret has changed position and size. Buffer the size and position
|
|
// information
|
|
//
|
|
|
|
// Place caret half way between characters,
|
|
pView->m_caret.x = CASTINT(xVal + cSize.cx);
|
|
pView->m_caret.y = CASTINT(yVal);
|
|
|
|
pView->m_caret.x = CASTINT(xVal + cSize.cx);
|
|
pView->m_caret.width = 2;
|
|
pView->m_caret.height = CASTINT(text_data->height);
|
|
|
|
if(pView->m_bDragOver)
|
|
AdjustForDragCaret(&(pView->m_caret));
|
|
|
|
// Don't show the caret if it is not ok to do so.
|
|
if (!IsOkToShowCaret(pView, "FE_DisplayTextCaret"))
|
|
return;
|
|
|
|
if(pView->m_bDragOver)
|
|
pView->CreateCaret(&ed_DragCaretBitmap);
|
|
else
|
|
pView->CreateSolidCaret(pView->m_caret.width, pView->m_caret.height);
|
|
|
|
pView->SetCaretPos(CPoint(pView->m_caret.x, pView->m_caret.y));
|
|
pView->m_caret.cShown = 1;
|
|
pView->m_caret.bEnabled = TRUE;
|
|
//TRACE0( "FE_DisplayTextCaret: Caret created and enabled\n");
|
|
pView->ShowCaret();
|
|
pView->SetEditChanged();
|
|
|
|
} // end of if-then for when text was visible
|
|
}
|
|
|
|
//
|
|
// The text has been drawn. This code will position the text carret in the
|
|
// proper position and height.
|
|
//
|
|
PUBLIC void
|
|
FE_DisplayImageCaret(MWContext * context, LO_ImageStruct *pLoImage,
|
|
ED_CaretObjectPosition pos)
|
|
{
|
|
int32 xVal, yVal;
|
|
|
|
if(!context || !pLoImage )
|
|
return;
|
|
|
|
CWinCX *pWinCX = VOID2CX(context->fe.cx, CWinCX);
|
|
CNetscapeEditView * pView = (CNetscapeEditView *)pWinCX->GetView();
|
|
xVal = pLoImage->x + pLoImage->x_offset - WINCX(context)->GetOriginX();
|
|
yVal = pLoImage->y - WINCX(context)->GetOriginY();
|
|
|
|
CPoint cDocPoint(CASTINT(pLoImage->x), CASTINT(pLoImage->y));
|
|
if( pWinCX->PtInSelectedRegion(cDocPoint) && pView->m_caret.bEnabled ){
|
|
DestroyCaret();
|
|
pView->m_caret.cShown = 0;
|
|
pView->m_caret.bEnabled = FALSE;
|
|
}
|
|
|
|
// Only draw text that falls within the curently viewed part of the frame
|
|
if((yVal < pWinCX->GetHeight()) && (yVal < 32000)) {
|
|
|
|
pView->m_caret.width = 2;
|
|
|
|
// Constrain caret size to between 10 and 40 else it looks too weird
|
|
if( pLoImage->line_height > 40 ){
|
|
pView->m_caret.height = 40;
|
|
yVal += (pLoImage->line_height - 45);
|
|
} else if( pLoImage->line_height < 10 ){
|
|
pView->m_caret.height = 10;
|
|
yVal -= (10 - pLoImage->line_height);
|
|
} else {
|
|
pView->m_caret.height = CASTINT(pLoImage->line_height);
|
|
}
|
|
pView->m_caret.y = CASTINT(yVal);
|
|
pView->m_caret.x = CASTINT(xVal);
|
|
|
|
if( pos == ED_CARET_BEFORE ){
|
|
pView->m_caret.x -= 1;
|
|
}
|
|
else if( pos == ED_CARET_AFTER ){
|
|
pView->m_caret.x += CASTINT(pLoImage->width + 2 * pLoImage->border_width);
|
|
}
|
|
else {
|
|
pView->m_caret.width = CASTINT(pLoImage->width+ 2 * pLoImage->border_width);
|
|
}
|
|
|
|
if(pView->m_bDragOver)
|
|
AdjustForDragCaret(&(pView->m_caret));
|
|
|
|
// Don't show the caret if it is not ok to do so.
|
|
if (!IsOkToShowCaret(pView, "FE_DisplayImageCaret"))
|
|
return;
|
|
|
|
if(pView->m_bDragOver)
|
|
pView->CreateCaret(&ed_DragCaretBitmap);
|
|
else
|
|
pView->CreateSolidCaret(pView->m_caret.width, pView->m_caret.height);
|
|
|
|
pView->SetCaretPos(CPoint(pView->m_caret.x, pView->m_caret.y));
|
|
pView->m_caret.cShown = 1;
|
|
pView->m_caret.bEnabled = TRUE;
|
|
pView->ShowCaret();
|
|
((CNetscapeEditView*)pView)->SetEditChanged();
|
|
|
|
}
|
|
}
|
|
|
|
PUBLIC void
|
|
FE_DisplayGenericCaret(MWContext * context, LO_Any *pLoAny,
|
|
ED_CaretObjectPosition pos)
|
|
{
|
|
int32 xVal, yVal;
|
|
|
|
if(!context || !pLoAny )
|
|
return;
|
|
|
|
CWinCX *pWinCX = VOID2CX(context->fe.cx, CWinCX);
|
|
CNetscapeEditView * pView = (CNetscapeEditView *)pWinCX->GetView();
|
|
|
|
// Figure out X and Y coords of the text
|
|
xVal = pLoAny->x + pLoAny->x_offset - WINCX(context)->GetOriginX();
|
|
yVal = pLoAny->y - WINCX(context)->GetOriginY();
|
|
|
|
CPoint cDocPoint(CASTINT(pLoAny->x), CASTINT(pLoAny->y));
|
|
if( pWinCX->PtInSelectedRegion(cDocPoint) && pView->m_caret.bEnabled ){
|
|
DestroyCaret();
|
|
pView->m_caret.cShown = 0;
|
|
pView->m_caret.bEnabled = FALSE;
|
|
}
|
|
|
|
// Only draw text that falls within the curently viewed part of the frame
|
|
if((yVal < pWinCX->GetHeight()) && (yVal < 32000)) {
|
|
|
|
pView->m_caret.width = 2;
|
|
|
|
// Constrain caret size to between 10 and 40 else it looks too weird
|
|
if( pLoAny->line_height > 40 ){
|
|
pView->m_caret.height = 40;
|
|
yVal += (pLoAny->line_height - 45);
|
|
} else if( pLoAny->line_height < 10 ){
|
|
pView->m_caret.height = 10;
|
|
yVal -= (10 - pLoAny->line_height);
|
|
} else {
|
|
pView->m_caret.height = CASTINT(pLoAny->line_height);
|
|
}
|
|
pView->m_caret.y = CASTINT(yVal);
|
|
pView->m_caret.x = CASTINT(xVal);
|
|
|
|
if( pos == ED_CARET_BEFORE ){
|
|
pView->m_caret.x -= 1;
|
|
}
|
|
else if( pos == ED_CARET_AFTER ){
|
|
pView->m_caret.x += CASTINT(pLoAny->width);
|
|
}
|
|
else {
|
|
pView->m_caret.width = CASTINT(pLoAny->width);
|
|
}
|
|
|
|
if(pView->m_bDragOver)
|
|
AdjustForDragCaret(&(pView->m_caret));
|
|
|
|
// Don't show the caret if it is not ok to do so.
|
|
if (!IsOkToShowCaret(pView, "FE_DisplayGenericCaret"))
|
|
return;
|
|
|
|
if(pView->m_bDragOver)
|
|
pView->CreateCaret(&ed_DragCaretBitmap);
|
|
else
|
|
pView->CreateSolidCaret(pView->m_caret.width, pView->m_caret.height);
|
|
|
|
pView->SetCaretPos(CPoint(pView->m_caret.x, pView->m_caret.y));
|
|
pView->m_caret.cShown = 1;
|
|
pView->m_caret.bEnabled = TRUE;
|
|
pView->ShowCaret();
|
|
((CNetscapeEditView*)pView)->SetEditChanged();
|
|
|
|
}
|
|
}
|
|
|
|
// Note: The returned coordinates do NOT account for the current window
|
|
// scroll. So you can't use them to set the windows caret until after
|
|
// you subtract the current window WINCX(context)->GetOriginXXX
|
|
|
|
PUBLIC Bool
|
|
FE_GetCaretPosition(MWContext *context, LO_Position* where,
|
|
int32* caretX, int32* caretYLow, int32* caretYHigh)
|
|
{
|
|
if(!context || !EDT_IS_EDITOR(context) || !where->element )
|
|
return FALSE;
|
|
|
|
HDC hDC;
|
|
|
|
CWinCX *pWinCX = VOID2CX(context->fe.cx, CWinCX);
|
|
CNetscapeEditView * pView = (CNetscapeEditView *)pWinCX->GetView();
|
|
int32 xVal = where->element->lo_any.x + where->element->lo_any.x_offset;
|
|
int32 yVal = where->element->lo_any.y;
|
|
int32 yValHigh = yVal + where->element->lo_any.height;
|
|
|
|
switch ( where->element->type )
|
|
{
|
|
case LO_TEXT:
|
|
{
|
|
LO_TextStruct* text_data = & where->element->lo_text;
|
|
if ( ! text_data->text_attr ) return FALSE;
|
|
|
|
hDC = pView->GetContextDC();
|
|
|
|
CyaFont *pMyFont;
|
|
pWinCX->SelectNetscapeFontWithCache( hDC, text_data->text_attr, pMyFont );
|
|
SIZE cSize;
|
|
pWinCX->ResolveTextExtent(hDC, (const char*)text_data->text,
|
|
CASTINT(where->position), &cSize, pMyFont );
|
|
xVal += cSize.cx - 1;
|
|
// ??? Do we need to restore the old font ???
|
|
pWinCX->ReleaseNetscapeFontWithCache( hDC, pMyFont );
|
|
|
|
}
|
|
break;
|
|
case LO_IMAGE:
|
|
{
|
|
LO_ImageStruct *pLoImage = & where->element->lo_image;
|
|
if( where->position == 0 ){
|
|
xVal -= 1;
|
|
}
|
|
else {
|
|
xVal += pLoImage->width + 2 * pLoImage->border_width;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
LO_Any *any = & where->element->lo_any;
|
|
if( where->position == 0 ){
|
|
xVal -= 1;
|
|
}
|
|
else {
|
|
xVal += any->width;
|
|
}
|
|
}
|
|
}
|
|
*caretX = xVal;
|
|
*caretYLow = yVal;
|
|
*caretYHigh = yValHigh;
|
|
return TRUE;
|
|
}
|
|
|
|
PUBLIC void
|
|
FE_DestroyCaret(MWContext * context)
|
|
{
|
|
CNetscapeEditView * pView = (CNetscapeEditView *)WINCX(context)->GetView();
|
|
|
|
if(!context || pView->GetFocus() != pView ){
|
|
//TRACE0( "FE_DestroyCaret called, but CNetscapeEditView does not have focus\n");
|
|
return;
|
|
}
|
|
|
|
DestroyCaret();
|
|
//TRACE0( "FE_DestroyCaret\n");
|
|
|
|
pView->m_caret.cShown = 0;
|
|
pView->m_caret.bEnabled = FALSE;
|
|
}
|
|
|
|
PUBLIC void
|
|
FE_ShowCaret(MWContext * context)
|
|
{
|
|
CNetscapeEditView * pView = NULL;
|
|
|
|
if(!context)
|
|
return;
|
|
|
|
pView = (CNetscapeEditView *)WINCX(context)->GetView();
|
|
pView->m_caret.cShown = 1;
|
|
pView->m_caret.bEnabled = TRUE;
|
|
//TRACE0( "FE_ShowCaret: Caret created and enabled\n");
|
|
pView->ShowCaret();
|
|
}
|
|
|
|
|
|
//
|
|
// FE_DocumentChanged.
|
|
// The editor is telling the front end that the document has changed. This
|
|
// occurs in the normal process of editing. At any time, changeHeight can
|
|
// be -1 which means grey to the end of the window. This routine has to
|
|
// map document coordinates into window coordinates.
|
|
//
|
|
// There are 4 possible cases here:
|
|
//
|
|
/*****
|
|
|
|
case 0:
|
|
|
|
0,0---------------------------------
|
|
| |
|
|
| |
|
|
| |
|
|
|===============================| windowStart
|
|
| | |
|
|
changeStartY |-------------------------------| |
|
|
| |///////////////////////////////| |
|
|
changeHeight | |///////////////////////////////| | windowHeight
|
|
| |///////////////////////////////| |
|
|
V |-------------------------------| |
|
|
| | |
|
|
|===============================| V
|
|
| |
|
|
| |
|
|
| |
|
|
--------------------------------- N,N
|
|
|
|
|
|
case 1:
|
|
0,0---------------------------------
|
|
| |
|
|
| |
|
|
|===============================| windowStart
|
|
| | |
|
|
changeStartY |-------------------------------| |
|
|
| |///////////////////////////////| |
|
|
changeHeight | |///////////////////////////////| | windowHeight
|
|
| |///////////////////////////////| |
|
|
| |///////////////////////////////| |
|
|
| |///////////////////////////////| |
|
|
| |===============================| V
|
|
| | |
|
|
V |-------------------------------|
|
|
| |
|
|
| |
|
|
--------------------------------- N,N
|
|
|
|
|
|
|
|
case 2:
|
|
0,0---------------------------------
|
|
| |
|
|
| |
|
|
changeStartY |-------------------------------|
|
|
| | |
|
|
| | |
|
|
| |===============================| windowStart
|
|
| |///////////////////////////////| |
|
|
| |///////////////////////////////| |
|
|
| |///////////////////////////////| |
|
|
changeHeight | |///////////////////////////////| | windowHeight
|
|
| |///////////////////////////////| |
|
|
| |///////////////////////////////| |
|
|
| |///////////////////////////////| |
|
|
| |===============================| V
|
|
| | |
|
|
V |-------------------------------|
|
|
| |
|
|
| |
|
|
--------------------------------- N,N
|
|
|
|
|
|
case 3:
|
|
0,0---------------------------------
|
|
| |
|
|
| |
|
|
changeStartY |-------------------------------|
|
|
| | |
|
|
| | |
|
|
| |===============================| windowStart
|
|
| |///////////////////////////////| |
|
|
| |///////////////////////////////| |
|
|
changeHeight | |///////////////////////////////| | windowHeight
|
|
| |///////////////////////////////| |
|
|
V |-------------------------------| |
|
|
| | |
|
|
|===============================| V
|
|
| |
|
|
| |
|
|
| |
|
|
--------------------------------- N,N
|
|
|
|
|
|
|
|
****/
|
|
PUBLIC void
|
|
FE_DocumentChanged(MWContext * context, int32 changeStartY, int32 changeHeight )
|
|
{
|
|
CNetscapeEditView * pView = NULL;
|
|
int32 left,right , windowStartY, windowHeight, windowBottom, changeBottom;
|
|
int32 top, bottom;
|
|
|
|
CWinCX *pWinCX = VOID2CX(context->fe.cx, CWinCX);
|
|
pView = (CNetscapeEditView *)pWinCX->GetView();
|
|
HDC hDC = pView->GetContextDC();
|
|
|
|
|
|
// Figure out X and Y coords of the text
|
|
// Figure out X and Y coords of the text
|
|
|
|
left = 0;
|
|
right = pWinCX->GetWidth();
|
|
|
|
windowStartY = WINCX(context)->GetOriginY();
|
|
windowHeight = pWinCX->GetHeight();
|
|
windowBottom = windowStartY + pWinCX->GetHeight();
|
|
|
|
// if the window is before the start of any change, then we don't need to
|
|
// redisplay anything.
|
|
if( windowBottom < changeStartY ){
|
|
return;
|
|
}
|
|
|
|
// make sure there is an overlap
|
|
if( changeHeight == -1 ){
|
|
changeBottom = windowBottom;
|
|
}
|
|
else {
|
|
changeBottom = changeStartY + changeHeight;
|
|
}
|
|
|
|
if( changeBottom < windowStartY ){
|
|
return;
|
|
}
|
|
|
|
// If window width is expanded past document width,
|
|
// the horizontal scroll bar disappears.
|
|
// If X origin is not 0, then we have a bad view and
|
|
// you can't get to doc region to the left of window edge.
|
|
// Detect this and reset X origin to 0 to reposition the view
|
|
// Note: SetDocPosition, Scroll, etc. all ignore this case
|
|
// (Browser works by always doing NET_GetURL, which resets origins)
|
|
if( pWinCX->GetDocumentWidth() < pWinCX->GetWidth() ){
|
|
pWinCX->m_lOrgX = 0;
|
|
}
|
|
|
|
//TODO: Is this the correct way to handle problem of not
|
|
// refreshing area below the doc?
|
|
// (Happens when doc shrinks (e.g., delete stuff) to less than window height)
|
|
if( pWinCX->GetDocumentHeight() < pWinCX->GetHeight() ){
|
|
bottom = windowBottom;
|
|
}
|
|
|
|
top = max( windowStartY, changeStartY ) - windowStartY;
|
|
bottom = min( windowBottom, changeBottom ) - windowStartY;
|
|
|
|
RECT rect;
|
|
::SetRect(&rect, CASTINT(left), CASTINT(top), CASTINT(right), CASTINT(bottom));
|
|
|
|
::LPtoDP(hDC, (POINT*)&rect, 2);
|
|
pView->InvalidateRect( &rect, TRUE );
|
|
}
|
|
|
|
|
|
void WFE_HideEditCaret(MWContext * pMWContext)
|
|
{
|
|
if( EDT_IS_EDITOR(pMWContext) ){
|
|
CWinCX *pWinCX = VOID2CX(pMWContext->fe.cx, CWinCX);
|
|
CNetscapeEditView * pView = (CNetscapeEditView *)pWinCX->GetView();
|
|
if( !pView ) return;
|
|
if( pView && pView->m_caret.bEnabled && pView->m_caret.cShown ) {
|
|
pView->HideCaret();
|
|
pView->m_caret.cShown = 0;
|
|
//TRACE0("WFE_HideCaret\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
void WFE_ShowEditCaret(MWContext * pMWContext)
|
|
{
|
|
if( EDT_IS_EDITOR(pMWContext) ){
|
|
CWinCX *pWinCX = VOID2CX(pMWContext->fe.cx, CWinCX);
|
|
CNetscapeEditView * pView = (CNetscapeEditView *)pWinCX->GetView();
|
|
if( !pView ) return;
|
|
if( pView->m_caret.bEnabled ) {
|
|
pView->ShowCaret();
|
|
pView->m_caret.cShown = 1;
|
|
//TRACE0("WFE_ShowCaret\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
void FE_DisplayAddRowOrColBorder(MWContext * pMWContext, XP_Rect *pRect, XP_Bool bErase)
|
|
{
|
|
CWinCX *pCX = VOID2CX(pMWContext->fe.cx, CWinCX);
|
|
if( !pCX )
|
|
return;
|
|
if( bErase )
|
|
{
|
|
RECT rect = {pRect->left, pRect->top, pRect->right, pRect->bottom};
|
|
// Adjust for line thickness
|
|
if( pRect->left == pRect->right)
|
|
{
|
|
rect.right++;
|
|
} else {
|
|
rect.bottom++;
|
|
}
|
|
::InvalidateRect(pCX->GetPane(), &rect, TRUE);
|
|
::UpdateWindow(pCX->GetPane());
|
|
} else {
|
|
HDC hdc = pCX->GetContextDC();
|
|
COLORREF rgbColor = RGB(0,0,0);
|
|
// Maybe draw in solid color?
|
|
// wfe_GetSelectionColors(pDC->m_rgbBackgroundColor, NULL, &rgbColor);
|
|
HPEN pPen = ::CreatePen(PS_DOT, 1, rgbColor);
|
|
HPEN pOldPen = (HPEN)::SelectObject(hdc, pPen);
|
|
// Use reverse effect
|
|
int OldRop = ::SetROP2( hdc, R2_NOT );
|
|
|
|
::MoveToEx(hdc, CASTINT(pRect->left), CASTINT(pRect->top), NULL);
|
|
::LineTo(hdc, CASTINT(pRect->right), CASTINT(pRect->bottom));
|
|
::SelectObject(hdc, pOldPen);
|
|
SetROP2(hdc, OldRop);
|
|
VERIFY(::DeleteObject(pPen));
|
|
}
|
|
}
|
|
|
|
void FE_DisplayEntireTableOrCell(MWContext * pMWContext, LO_Element * pElement)
|
|
{
|
|
if( pMWContext && pElement )
|
|
{
|
|
int32 iWidth, iHeight;
|
|
if( pElement->type == LO_TABLE )
|
|
{
|
|
iWidth = pElement->lo_table.width;
|
|
// Calculate the full height instead of just the table height
|
|
// in case table has a caption
|
|
iHeight = pElement->lo_table.line_height + pElement->lo_table.border_bottom_width
|
|
+ pElement->lo_table.inter_cell_space;
|
|
}
|
|
else if ( pElement->type == LO_CELL )
|
|
{
|
|
iWidth = pElement->lo_cell.width;
|
|
iHeight = pElement->lo_cell.height;
|
|
}
|
|
else
|
|
return; // Only Table and Cell types allowed
|
|
|
|
CWinCX *pCX = VOID2CX(pMWContext->fe.cx, CWinCX);
|
|
RECT rect;
|
|
rect.left = pElement->lo_any.x - pCX->GetOriginX();
|
|
rect.top = pElement->lo_any.y - pCX->GetOriginY();
|
|
rect.right = rect.left + iWidth;
|
|
rect.bottom = rect.top + iHeight;
|
|
|
|
if( pElement->type == LO_TABLE &&
|
|
pElement->lo_table.border_left_width == 0 &&
|
|
pElement->lo_table.border_right_width == 0 &&
|
|
pElement->lo_table.border_top_width == 0 &&
|
|
pElement->lo_table.border_bottom_width == 0 )
|
|
{
|
|
// We are displaying a "zero-width" table,
|
|
// increase rect by 1 pixel 'cause thats
|
|
// where we drew the table's dotted-line border
|
|
::InflateRect(&rect, 1, 1);
|
|
}
|
|
// Include the inter-cell spacing area also used for highlighting a cell
|
|
int32 iExtraSpace;
|
|
if( pElement->type == LO_CELL && pElement->lo_cell.border_width < ED_SELECTION_BORDER &&
|
|
0 < (iExtraSpace = pElement->lo_cell.inter_cell_space / 2) )
|
|
{
|
|
::InflateRect(&rect, iExtraSpace, iExtraSpace);
|
|
}
|
|
|
|
InvalidateRect(pCX->GetPane(), &rect, TRUE);
|
|
}
|
|
}
|
|
|
|
void FE_DisplayDropTableFeedback(MWContext * pMWContext, EDT_DragTableData *pDragData)
|
|
{
|
|
if(!pMWContext || !EDT_IS_EDITOR(pMWContext) || !pDragData)
|
|
return;
|
|
|
|
CWinCX *pWinCX = VOID2CX(pMWContext->fe.cx, CWinCX);
|
|
CNetscapeEditView * pView = (CNetscapeEditView *)pWinCX->GetView();
|
|
if( pView )
|
|
{
|
|
if( pDragData->iDropType != ED_DROP_REPLACE_CELLS )
|
|
{
|
|
// Figure out X and Y coords of the cell in the View's coordinate system
|
|
CWinCX *pWinCX = VOID2CX(pMWContext->fe.cx, CWinCX);
|
|
int32 xVal = pDragData->X + pDragData->pDragOverCell->lo_cell.x_offset
|
|
- pWinCX->GetOriginX();
|
|
int32 yVal = pDragData->Y + pDragData->pDragOverCell->lo_cell.y_offset
|
|
- pWinCX->GetOriginY();
|
|
|
|
// Use caret to show inserting between cells
|
|
pView->CreateSolidCaret(pDragData->iWidth, pDragData->iHeight);
|
|
pView->SetCaretPos(CPoint(xVal, yVal));
|
|
pView->m_caret.cShown = 1;
|
|
pView->m_caret.bEnabled = TRUE;
|
|
pView->ShowCaret();
|
|
}
|
|
// Note that feedback for ED_DROP_REPLACE_CELLS is marking cells to
|
|
// be replaced with the "special selection"
|
|
// XP code handles this, calling FE_DisplayEntireTableOrCell for
|
|
// each cell marked as "special"
|
|
|
|
}
|
|
}
|