home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / winfe / edlayout.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  24.2 KB  |  698 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. // edlayout.cpp : implementation of Editor-only FE layout functions
  20. //
  21. // Created 9/16/96 by CLM
  22. //
  23. #include "stdafx.h"
  24.  
  25. #include "dialog.h"
  26. #include "mainfrm.h"
  27. #include "netsvw.h"
  28. #include "edview.h"
  29.  
  30. // Utility function to check if it is OK to show the caret. It is used in the FE functions that
  31. // are called by the back end to show caret.
  32. static BOOL IsOkToShowCaret(CNetscapeEditView *pView, char *FE_FuncName)
  33. {
  34.     // Prevent setting caret when we have a modal (e.g. property) dialog over us
  35.     CFrameWnd *pFrame = pView->GetFrame()->GetFrameWnd();
  36.     if(pFrame && pFrame->GetLastActivePopup() != pFrame){
  37.         return FALSE;
  38.     }
  39.  
  40.     // This will allow us to use the regular caret for drop-point feedback
  41.     //   even if window does not have focus
  42.     // Don't display caret if the editor view does not have focus.
  43.     //  unless we are dragging over our view
  44.     if( !pView->m_bDragOver && pView->GetFocus() != pView ){
  45.         return FALSE;
  46.     }
  47.     return TRUE;    // OK to show caret
  48. }
  49.  
  50. // Caret used during Drag&Drop - more visible than regular cursor
  51. extern CBitmap ed_DragCaretBitmap;
  52.  
  53. #define ED_DRAGCARET_HEIGHT 32
  54.  
  55. static void AdjustForDragCaret(CCaret * pCaret)
  56. {            
  57.     // NOTE: This assumes IDB_ED_DRAG bitmap is 3 by ED_DRAGCARET_HEIGHT
  58.     //        and regular caret is 2 pixels wide
  59.     
  60.     // Back off one on X 
  61.     pCaret->x--;
  62.     
  63.     // Only one size for drop caret, so reposition vertically
  64.     pCaret->y -=  ED_DRAGCARET_HEIGHT - pCaret->height;
  65.     
  66.     pCaret->width = 3;
  67.     pCaret->height = ED_DRAGCARET_HEIGHT;
  68. }
  69.  
  70. //
  71. // The text has been drawn.  This code will position the text caret in the
  72. //  proper position and height.
  73. //
  74. PUBLIC void
  75. FE_DisplayTextCaret(MWContext * context, int loc, LO_TextStruct * text_data, 
  76.     int char_offset)
  77. {
  78.     if(!context || !EDT_IS_EDITOR(context) || !text_data || !text_data->text_attr)
  79.         return;
  80.  
  81.     int32       xVal, yVal;
  82.     
  83.     CWinCX *pWinCX = VOID2CX(context->fe.cx, CWinCX);
  84.     CNetscapeEditView * pView = (CNetscapeEditView *)pWinCX->GetView();
  85.  
  86.     HDC hDC = pView->GetContextDC();
  87.  
  88.     int32       xOrigin = WINCX(context)->GetOriginX();
  89.  
  90.     // Figure out X and Y coords of the text in the View's coordinate system
  91.     xVal = text_data->x + text_data->x_offset - xOrigin;
  92.     yVal = text_data->y + text_data->y_offset - WINCX(context)->GetOriginY();
  93.  
  94.     CPoint cDocPoint(CASTINT(text_data->x), CASTINT(text_data->y));
  95.     if( pWinCX->PtInSelectedRegion(cDocPoint) && pView->m_caret.bEnabled ){
  96.         DestroyCaret();
  97.         pView->m_caret.cShown = 0;
  98.         pView->m_caret.bEnabled = FALSE;
  99.     }
  100.  
  101.     // Only draw text that falls within the curently viewed part of the frame
  102.     if((yVal < pWinCX->GetHeight()) && (yVal < 32000)) {
  103.  
  104.         //    Get the font so we can get its height
  105.         CyaFont    *pMyFont;
  106.         pWinCX->SelectNetscapeFontWithCache( hDC, text_data->text_attr, pMyFont );
  107.  
  108.         // Calculate offset within text 
  109.         CSize cSize(0,0);
  110.         const char *pText = (const char*)text_data->text;
  111.         // Win16 barfs on this if null string
  112.         if( char_offset > 0 && pText && *pText != '\0' ){
  113.             pWinCX->ResolveTextExtent(hDC, pText, char_offset, &cSize, pMyFont );
  114.         }
  115.  
  116.         pWinCX->ReleaseNetscapeFontWithCache( hDC, pMyFont );
  117.         //
  118.         // The caret has changed position and size.  Buffer the size and position
  119.         //  information        
  120.         //
  121.  
  122.         // Place caret half way between characters,
  123.         pView->m_caret.x = CASTINT(xVal + cSize.cx);
  124.         pView->m_caret.y = CASTINT(yVal);
  125.  
  126.         pView->m_caret.x = CASTINT(xVal + cSize.cx);
  127.         pView->m_caret.width = 2;
  128.         pView->m_caret.height = CASTINT(text_data->height);
  129.  
  130.         if(pView->m_bDragOver)
  131.             AdjustForDragCaret(&(pView->m_caret));
  132.  
  133.         // Don't show the caret if it is not ok to do so.
  134.         if (!IsOkToShowCaret(pView, "FE_DisplayTextCaret"))
  135.             return;
  136.  
  137.         if(pView->m_bDragOver)
  138.             pView->CreateCaret(&ed_DragCaretBitmap);
  139.         else
  140.             pView->CreateSolidCaret(pView->m_caret.width, pView->m_caret.height);
  141.  
  142.         pView->SetCaretPos(CPoint(pView->m_caret.x, pView->m_caret.y));
  143.         pView->m_caret.cShown = 1;
  144.         pView->m_caret.bEnabled = TRUE;
  145.         //TRACE0( "FE_DisplayTextCaret: Caret created and enabled\n");
  146.         pView->ShowCaret();
  147.         pView->SetEditChanged();
  148.  
  149.     } // end of if-then for when text was visible
  150. }
  151.  
  152. //
  153. // The text has been drawn.  This code will position the text carret in the
  154. //  proper position and height.
  155. //
  156. PUBLIC void
  157. FE_DisplayImageCaret(MWContext * context, LO_ImageStruct *pLoImage, 
  158.         ED_CaretObjectPosition pos) 
  159. {
  160.     int32   xVal, yVal;
  161.  
  162.     if(!context || !pLoImage )
  163.         return;
  164.  
  165.     CWinCX *pWinCX = VOID2CX(context->fe.cx, CWinCX);
  166.     CNetscapeEditView * pView = (CNetscapeEditView *)pWinCX->GetView();
  167.     xVal = pLoImage->x + pLoImage->x_offset - WINCX(context)->GetOriginX();
  168.     yVal = pLoImage->y - WINCX(context)->GetOriginY();
  169.  
  170.     CPoint cDocPoint(CASTINT(pLoImage->x), CASTINT(pLoImage->y));
  171.     if( pWinCX->PtInSelectedRegion(cDocPoint) && pView->m_caret.bEnabled ){
  172.         DestroyCaret();
  173.         pView->m_caret.cShown = 0;
  174.         pView->m_caret.bEnabled = FALSE;
  175.     }
  176.  
  177.     // Only draw text that falls within the curently viewed part of the frame
  178.     if((yVal < pWinCX->GetHeight()) && (yVal < 32000)) {
  179.  
  180.         pView->m_caret.width = 2;
  181.  
  182.         // Constrain caret size to between 10 and 40 else it looks too weird
  183.         if( pLoImage->line_height > 40 ){
  184.             pView->m_caret.height = 40;
  185.             yVal += (pLoImage->line_height - 45);
  186.         } else if( pLoImage->line_height < 10 ){
  187.             pView->m_caret.height = 10;
  188.             yVal -= (10  - pLoImage->line_height);
  189.         } else {
  190.             pView->m_caret.height = CASTINT(pLoImage->line_height);
  191.         }
  192.         pView->m_caret.y = CASTINT(yVal);
  193.         pView->m_caret.x = CASTINT(xVal);
  194.  
  195.         if( pos == ED_CARET_BEFORE ){
  196.             pView->m_caret.x -= 1;
  197.         }
  198.         else if( pos == ED_CARET_AFTER ){
  199.             pView->m_caret.x += CASTINT(pLoImage->width + 2 * pLoImage->border_width);
  200.         }
  201.         else {
  202.             pView->m_caret.width = CASTINT(pLoImage->width+ 2 * pLoImage->border_width);
  203.         }
  204.  
  205.         if(pView->m_bDragOver)
  206.             AdjustForDragCaret(&(pView->m_caret));
  207.  
  208.         // Don't show the caret if it is not ok to do so.
  209.         if (!IsOkToShowCaret(pView, "FE_DisplayImageCaret"))
  210.             return;
  211.  
  212.         if(pView->m_bDragOver)
  213.             pView->CreateCaret(&ed_DragCaretBitmap);
  214.         else
  215.             pView->CreateSolidCaret(pView->m_caret.width, pView->m_caret.height);
  216.  
  217.         pView->SetCaretPos(CPoint(pView->m_caret.x, pView->m_caret.y));
  218.         pView->m_caret.cShown = 1;
  219.         pView->m_caret.bEnabled = TRUE;
  220.         pView->ShowCaret();
  221.         ((CNetscapeEditView*)pView)->SetEditChanged();
  222.  
  223.     }
  224. }
  225.  
  226. PUBLIC void
  227. FE_DisplayGenericCaret(MWContext * context, LO_Any *pLoAny, 
  228.         ED_CaretObjectPosition pos) 
  229. {
  230.     int32       xVal, yVal;
  231.  
  232.     if(!context || !pLoAny )
  233.         return;
  234.  
  235.     CWinCX *pWinCX = VOID2CX(context->fe.cx, CWinCX);
  236.     CNetscapeEditView * pView = (CNetscapeEditView *)pWinCX->GetView();
  237.  
  238.     // Figure out X and Y coords of the text
  239.     xVal = pLoAny->x + pLoAny->x_offset - WINCX(context)->GetOriginX();
  240.     yVal = pLoAny->y - WINCX(context)->GetOriginY();
  241.  
  242.     CPoint cDocPoint(CASTINT(pLoAny->x), CASTINT(pLoAny->y));
  243.     if( pWinCX->PtInSelectedRegion(cDocPoint) && pView->m_caret.bEnabled ){
  244.         DestroyCaret();
  245.         pView->m_caret.cShown = 0;
  246.         pView->m_caret.bEnabled = FALSE;
  247.     }
  248.  
  249.     // Only draw text that falls within the curently viewed part of the frame
  250.     if((yVal < pWinCX->GetHeight()) && (yVal < 32000)) {
  251.  
  252.         pView->m_caret.width = 2;
  253.  
  254.         // Constrain caret size to between 10 and 40 else it looks too weird
  255.         if( pLoAny->line_height > 40 ){
  256.             pView->m_caret.height = 40;
  257.             yVal += (pLoAny->line_height - 45);
  258.         } else if( pLoAny->line_height < 10 ){
  259.             pView->m_caret.height = 10;
  260.             yVal -= (10 - pLoAny->line_height);
  261.         } else {
  262.             pView->m_caret.height = CASTINT(pLoAny->line_height);
  263.         }
  264.         pView->m_caret.y = CASTINT(yVal);
  265.         pView->m_caret.x = CASTINT(xVal);
  266.  
  267.         if( pos == ED_CARET_BEFORE ){
  268.             pView->m_caret.x -= 1;
  269.         }
  270.         else if( pos == ED_CARET_AFTER ){
  271.             pView->m_caret.x += CASTINT(pLoAny->width);
  272.         }
  273.         else {
  274.             pView->m_caret.width = CASTINT(pLoAny->width);
  275.         }
  276.  
  277.         if(pView->m_bDragOver)
  278.             AdjustForDragCaret(&(pView->m_caret));
  279.  
  280.         // Don't show the caret if it is not ok to do so.
  281.         if (!IsOkToShowCaret(pView, "FE_DisplayGenericCaret"))
  282.             return;
  283.  
  284.         if(pView->m_bDragOver)
  285.             pView->CreateCaret(&ed_DragCaretBitmap);
  286.         else
  287.             pView->CreateSolidCaret(pView->m_caret.width, pView->m_caret.height);
  288.  
  289.         pView->SetCaretPos(CPoint(pView->m_caret.x, pView->m_caret.y));
  290.         pView->m_caret.cShown = 1;
  291.         pView->m_caret.bEnabled = TRUE;
  292.         pView->ShowCaret();
  293.         ((CNetscapeEditView*)pView)->SetEditChanged();
  294.  
  295.     }
  296. }
  297.  
  298. // Note: The returned coordinates do NOT account for the current window
  299. // scroll. So you can't use them to set the windows caret until after
  300. // you subtract the current window WINCX(context)->GetOriginXXX
  301.  
  302. PUBLIC Bool
  303. FE_GetCaretPosition(MWContext *context, LO_Position* where,
  304.     int32* caretX, int32* caretYLow, int32* caretYHigh)
  305. {
  306.     if(!context || !EDT_IS_EDITOR(context) || !where->element )
  307.         return FALSE;
  308.  
  309.     HDC hDC;
  310.  
  311.     CWinCX *pWinCX = VOID2CX(context->fe.cx, CWinCX);
  312.     CNetscapeEditView * pView = (CNetscapeEditView *)pWinCX->GetView();
  313.     int32 xVal = where->element->lo_any.x + where->element->lo_any.x_offset;
  314.     int32 yVal = where->element->lo_any.y;
  315.     int32 yValHigh = yVal + where->element->lo_any.height;
  316.  
  317.     switch ( where->element->type )
  318.     {
  319.     case LO_TEXT:
  320.         {
  321.             LO_TextStruct* text_data = & where->element->lo_text;
  322.             if ( ! text_data->text_attr ) return FALSE;
  323.  
  324.             hDC = pView->GetContextDC();
  325.  
  326.             CyaFont    *pMyFont;
  327.             pWinCX->SelectNetscapeFontWithCache( hDC, text_data->text_attr, pMyFont );
  328.             SIZE cSize;
  329.             pWinCX->ResolveTextExtent(hDC, (const char*)text_data->text, 
  330.                     CASTINT(where->position), &cSize, pMyFont );
  331.             xVal += cSize.cx - 1;
  332.             // ??? Do we need to restore the old font ???
  333.             pWinCX->ReleaseNetscapeFontWithCache( hDC, pMyFont );
  334.  
  335.         }
  336.         break;
  337.     case LO_IMAGE:
  338.         {
  339.             LO_ImageStruct *pLoImage = & where->element->lo_image;
  340.             if( where->position == 0 ){
  341.                 xVal -= 1;
  342.             }
  343.             else {
  344.                 xVal += pLoImage->width + 2 * pLoImage->border_width;
  345.             }
  346.         }
  347.         break;
  348.     default:
  349.         {
  350.             LO_Any *any = & where->element->lo_any;
  351.             if( where->position == 0 ){
  352.                 xVal -= 1;
  353.             }
  354.             else {
  355.                 xVal += any->width;
  356.             }
  357.         }
  358.     }
  359.     *caretX = xVal;
  360.     *caretYLow = yVal;
  361.     *caretYHigh = yValHigh;
  362.    return TRUE;
  363. }
  364.  
  365. PUBLIC void
  366. FE_DestroyCaret(MWContext * context)
  367. {
  368.     CNetscapeEditView * pView = (CNetscapeEditView *)WINCX(context)->GetView();
  369.  
  370.     if(!context || pView->GetFocus() != pView ){
  371.         TRACE0( "FE_DestroyCaret called, but CNetscapeEditView does not have focus\n");
  372.         return;
  373.     }
  374.  
  375.     DestroyCaret();
  376.  
  377.     pView->m_caret.cShown = 0;
  378.     pView->m_caret.bEnabled = FALSE;
  379. }
  380.  
  381. PUBLIC void
  382. FE_ShowCaret(MWContext * context)
  383. {
  384.     CNetscapeEditView * pView = NULL;
  385.  
  386.     if(!context)
  387.         return;
  388.  
  389.     pView = (CNetscapeEditView *)WINCX(context)->GetView();
  390.     pView->m_caret.cShown = 1;
  391.     pView->m_caret.bEnabled = TRUE;
  392.     //TRACE0( "FE_ShowCaret: Caret created and enabled\n");
  393.     pView->ShowCaret();
  394. }
  395.  
  396.  
  397. //
  398. // FE_DocumentChanged.
  399. //  The editor is telling the front end that the document has changed.  This 
  400. //  occurs in the normal process of editing.  At any time, changeHeight can
  401. //  be -1 which means grey to the end of the window.  This routine has to 
  402. //  map document coordinates into window coordinates.
  403. //
  404. //  There are 4 possible cases here:
  405. //
  406. /*****
  407.  
  408.    case 0:
  409.  
  410.                0,0---------------------------------
  411.                   |                               | 
  412.                   |                               | 
  413.                   |                               | 
  414.                   |===============================| windowStart 
  415.                   |                               |  |
  416.     changeStartY  |-------------------------------|  |
  417.              |    |///////////////////////////////|  |
  418. changeHeight |    |///////////////////////////////|  | windowHeight
  419.              |    |///////////////////////////////|  |
  420.              V    |-------------------------------|  |
  421.                   |                               |  |
  422.                   |===============================|  V
  423.                   |                               | 
  424.                   |                               | 
  425.                   |                               | 
  426.                   --------------------------------- N,N
  427.  
  428.  
  429.    case 1:
  430.                0,0---------------------------------
  431.                   |                               | 
  432.                   |                               | 
  433.                   |===============================| windowStart 
  434.                   |                               |  |
  435.     changeStartY  |-------------------------------|  |
  436.              |    |///////////////////////////////|  |
  437. changeHeight |    |///////////////////////////////|  | windowHeight
  438.              |    |///////////////////////////////|  |
  439.              |    |///////////////////////////////|  |
  440.              |    |///////////////////////////////|  |
  441.              |    |===============================|  V
  442.              |    |                               | 
  443.              V    |-------------------------------|  
  444.                   |                               | 
  445.                   |                               | 
  446.                   --------------------------------- N,N
  447.  
  448.  
  449.  
  450.    case 2:
  451.                0,0---------------------------------
  452.                   |                               | 
  453.                   |                               | 
  454.     changeStartY  |-------------------------------|  
  455.              |    |                               | 
  456.              |    |                               | 
  457.              |    |===============================| windowStart 
  458.              |    |///////////////////////////////|  |
  459.              |    |///////////////////////////////|  |
  460.              |    |///////////////////////////////|  |
  461. changeHeight |    |///////////////////////////////|  | windowHeight
  462.              |    |///////////////////////////////|  |
  463.              |    |///////////////////////////////|  |
  464.              |    |///////////////////////////////|  |
  465.              |    |===============================|  V
  466.              |    |                               | 
  467.              V    |-------------------------------|  
  468.                   |                               | 
  469.                   |                               | 
  470.                   --------------------------------- N,N
  471.  
  472.  
  473.    case 3:
  474.                0,0---------------------------------
  475.                   |                               | 
  476.                   |                               | 
  477.     changeStartY  |-------------------------------|  
  478.              |    |                               | 
  479.              |    |                               | 
  480.              |    |===============================| windowStart 
  481.              |    |///////////////////////////////|  |
  482.              |    |///////////////////////////////|  |
  483. changeHeight |    |///////////////////////////////|  | windowHeight
  484.              |    |///////////////////////////////|  |
  485.              V    |-------------------------------|  |
  486.                   |                               |  |
  487.                   |===============================|  V
  488.                   |                               | 
  489.                   |                               | 
  490.                   |                               | 
  491.                   --------------------------------- N,N
  492.  
  493.  
  494.  
  495. ****/
  496. PUBLIC void 
  497. FE_DocumentChanged(MWContext * context, int32 changeStartY, int32 changeHeight )
  498. {
  499.     CNetscapeEditView * pView = NULL;
  500.     int32 left,right , windowStartY, windowHeight, windowBottom, changeBottom;
  501.     int32 top, bottom;
  502.  
  503.     CWinCX *pWinCX = VOID2CX(context->fe.cx, CWinCX);
  504.     pView = (CNetscapeEditView *)pWinCX->GetView();
  505.     HDC hDC = pView->GetContextDC();
  506.  
  507.  
  508.     // Figure out X and Y coords of the text
  509.     // Figure out X and Y coords of the text
  510.     
  511.     left = 0;
  512.     right = pWinCX->GetWidth();
  513.  
  514.     windowStartY =  WINCX(context)->GetOriginY();
  515.     windowHeight = pWinCX->GetHeight();
  516.     windowBottom = windowStartY + pWinCX->GetHeight();
  517.  
  518.     // if the window is before the start of any change, then we don't need to
  519.     //  redisplay anything.
  520.     if( windowBottom < changeStartY ){
  521.         return;
  522.     }
  523.  
  524.     // make sure there is an overlap
  525.     if( changeHeight == -1 ){
  526.         changeBottom = windowBottom;
  527.     }
  528.     else {
  529.         changeBottom = changeStartY + changeHeight;
  530.     }
  531.  
  532.     if( changeBottom < windowStartY ){
  533.         return;
  534.     }
  535.  
  536.     // If window width is expanded past document width,
  537.     //   the horizontal scroll bar disappears.
  538.     // If X origin is not 0, then we have a bad view and
  539.     //   you can't get to doc region to the left of window edge.
  540.     // Detect this and reset X origin to 0 to reposition the view
  541.     // Note: SetDocPosition,  Scroll, etc. all ignore this case
  542.     //       (Browser works by always doing NET_GetURL, which resets origins)
  543.     if( pWinCX->GetDocumentWidth() < pWinCX->GetWidth() ){
  544.         pWinCX->m_lOrgX = 0;
  545.     }
  546.     
  547.     //TODO: Is this the correct way to handle problem of not
  548.     //       refreshing area below the doc?
  549.     //      (Happens when doc shrinks (e.g., delete stuff) to less than window height)
  550.     if( pWinCX->GetDocumentHeight() < pWinCX->GetHeight() ){
  551.         bottom = windowBottom;
  552.     }
  553.     
  554.     top =  max( windowStartY, changeStartY ) - windowStartY;
  555.     bottom = min( windowBottom, changeBottom ) - windowStartY;
  556.  
  557.     RECT rect;
  558.     ::SetRect(&rect, CASTINT(left), CASTINT(top), CASTINT(right), CASTINT(bottom));
  559.  
  560.     ::LPtoDP(hDC, (POINT*)&rect, 2);
  561.     pView->InvalidateRect( &rect, TRUE );
  562. }
  563.  
  564.  
  565. void WFE_HideEditCaret(MWContext * pMWContext)
  566. {
  567.     if( EDT_IS_EDITOR(pMWContext) ){
  568.         CWinCX *pWinCX = VOID2CX(pMWContext->fe.cx, CWinCX);
  569.         CNetscapeEditView * pView = (CNetscapeEditView *)pWinCX->GetView();
  570.         if( !pView ) return;
  571.         if( pView && pView->m_caret.bEnabled && pView->m_caret.cShown ) {
  572.             pView->HideCaret();
  573.             pView->m_caret.cShown = 0;
  574.         } 
  575.     }
  576. }
  577.  
  578. void WFE_ShowEditCaret(MWContext * pMWContext)
  579. {
  580.     if( EDT_IS_EDITOR(pMWContext) ){
  581.         CWinCX *pWinCX = VOID2CX(pMWContext->fe.cx, CWinCX);
  582.         CNetscapeEditView * pView = (CNetscapeEditView *)pWinCX->GetView();
  583.         if( !pView ) return;
  584.         if( pView->m_caret.bEnabled ) {
  585.             pView->ShowCaret();
  586.             pView->m_caret.cShown = 1;
  587.         }
  588.     }
  589. }
  590.  
  591. void FE_DisplayAddRowOrColBorder(MWContext * pMWContext, XP_Rect *pRect, XP_Bool bErase)
  592. {
  593.     CWinCX *pCX = VOID2CX(pMWContext->fe.cx, CWinCX);
  594.     if( !pCX )
  595.         return;
  596.     if( bErase )
  597.     {
  598.         RECT rect = {pRect->left, pRect->top, pRect->right, pRect->bottom};
  599.         // Adjust for line thickness
  600.         if( pRect->left == pRect->right)
  601.         {
  602.             rect.right++;
  603.         } else {
  604.             rect.bottom++;
  605.         }
  606.         ::InvalidateRect(pCX->GetPane(), &rect, TRUE); 
  607.         ::UpdateWindow(pCX->GetPane());
  608.     } else {
  609.         HDC hdc = pCX->GetContextDC();
  610.         COLORREF rgbColor = RGB(0,0,0);
  611. //        Maybe draw in solid color?
  612. //        wfe_GetSelectionColors(pDC->m_rgbBackgroundColor, NULL, &rgbColor);
  613.         HPEN pPen = ::CreatePen(PS_DOT, 1, rgbColor);
  614.         HPEN pOldPen = (HPEN)::SelectObject(hdc, pPen);
  615.         // Use reverse effect
  616.         int OldRop = ::SetROP2( hdc, R2_NOT );
  617.    
  618.         ::MoveToEx(hdc, CASTINT(pRect->left), CASTINT(pRect->top), NULL);
  619.         ::LineTo(hdc, CASTINT(pRect->right), CASTINT(pRect->bottom));
  620.         ::SelectObject(hdc, pOldPen);
  621.         SetROP2(hdc, OldRop);
  622.         VERIFY(::DeleteObject(pPen));
  623.     }
  624. }
  625.  
  626. void FE_DisplayEntireTableOrCell(MWContext * pMWContext, LO_Element * pElement)
  627. {
  628.     if( pMWContext && pElement )
  629.     {
  630.         int32 iWidth, iHeight;
  631.         if( pElement->type == LO_TABLE )
  632.         {
  633.             iWidth = pElement->lo_table.width;
  634.             iHeight = pElement->lo_table.height;
  635.         }
  636.         else if ( pElement->type == LO_CELL )
  637.         {
  638.             iWidth = pElement->lo_cell.width;
  639.             iHeight = pElement->lo_cell.height;
  640.         }
  641.         else
  642.             return; // Only Table and Cell types allowed
  643.             
  644.         CWinCX *pCX = VOID2CX(pMWContext->fe.cx, CWinCX);
  645.         RECT rect;
  646.         rect.left = pElement->lo_any.x - pCX->GetOriginX();
  647.         rect.top = pElement->lo_any.y - pCX->GetOriginY();
  648.         rect.right = rect.left + iWidth;
  649.         rect.bottom = rect.top + iHeight;
  650.  
  651.         if( pElement->type == LO_TABLE && 
  652.             pElement->lo_table.border_left_width == 0 &&
  653.             pElement->lo_table.border_right_width == 0 &&
  654.             pElement->lo_table.border_top_width == 0 &&
  655.             pElement->lo_table.border_bottom_width == 0 )
  656.         {
  657.             // We are displaying a "zero-width" table,
  658.             //  increase rect by 1 pixel 'cause thats
  659.             //  where we drew the table's dotted-line border 
  660.             ::InflateRect(&rect, 1, 1);
  661.         }
  662.         // Include the inter-cell spacing area also used for highlighting a cell
  663.         int32 iExtraSpace;
  664.         if( pElement->type == LO_CELL && pElement->lo_cell.border_width < ED_SELECTION_BORDER &&
  665.             0 < (iExtraSpace = pElement->lo_cell.inter_cell_space / 2) )
  666.         {
  667.             ::InflateRect(&rect, iExtraSpace, iExtraSpace);
  668.         }
  669.  
  670.         InvalidateRect(pCX->GetPane(), &rect, TRUE);
  671.     }
  672. }
  673.  
  674. void FE_DisplayDropTableFeedback(MWContext * pMWContext, EDT_DragTableData *pDragData)
  675. {
  676.     if(!pMWContext || !EDT_IS_EDITOR(pMWContext) || !pDragData)
  677.         return;
  678.  
  679.     CWinCX *pWinCX = VOID2CX(pMWContext->fe.cx, CWinCX);
  680.     CNetscapeEditView * pView = (CNetscapeEditView *)pWinCX->GetView();
  681.     if( pView )
  682.     {
  683.         if( pDragData->iDropType == ED_DROP_REPLACE_CELL )
  684.         {
  685.             //TODO: FEEDBACK WHEN REPLACING
  686.             // THIS MAY BE DONE IN XP CODE BY SETTING LO_ELE_SELECTED_SPECIAL
  687.             // THEN JUST REDRAWING THE TABLE
  688.         } else {
  689.             // Use caret to show inserting between cells
  690.             pView->CreateSolidCaret(pDragData->iWidth, pDragData->iHeight);
  691.             pView->SetCaretPos(CPoint(pDragData->X, pDragData->Y));
  692.             pView->m_caret.cShown = 1;
  693.             pView->m_caret.bEnabled = TRUE;
  694.             pView->ShowCaret();
  695.         }
  696.     }
  697. }
  698.