home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / layout / editor.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  88.2 KB  |  2,633 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.  
  20. //
  21. // Public interface and shared subsystem data.
  22. //
  23.  
  24. #ifdef EDITOR
  25.  
  26. #include "editor.h"
  27.  
  28. #include "fsfile.h"
  29. // For XP Strings
  30. extern "C" {
  31. #include "xpgetstr.h"
  32. #define WANT_ENUM_STRING_IDS
  33. #include "allxpstr.h"
  34. #undef WANT_ENUM_STRING_IDS
  35. }
  36. #include "xp_str.h"
  37. #include "prefapi.h"
  38. #include "secnav.h"
  39. #include "msgcom.h"
  40. #include "intl_csi.h"
  41.  
  42. //extern "C" int XP_EDT_HEAD_FAILED;
  43.  
  44. CBitArray *edt_setNoEndTag = 0;
  45. CBitArray *edt_setWriteEndTag = 0;
  46. CBitArray *edt_setHeadTags = 0;
  47. CBitArray *edt_setSoloTags = 0;
  48. CBitArray *edt_setBlockFormat = 0;
  49. CBitArray *edt_setCharFormat = 0;
  50. CBitArray *edt_setList = 0;
  51. CBitArray *edt_setUnsupported = 0;
  52. CBitArray *edt_setAutoStartBody = 0;
  53. CBitArray *edt_setTextContainer = 0;
  54. CBitArray *edt_setListContainer = 0;
  55. CBitArray *edt_setParagraphBreak = 0;
  56. CBitArray *edt_setFormattedText = 0;
  57. CBitArray *edt_setContainerSupportsAlign = 0;
  58. CBitArray *edt_setIgnoreWhiteSpace = 0;
  59. CBitArray *edt_setSuppressNewlineBefore = 0;
  60. CBitArray *edt_setRequireNewlineAfter = 0;
  61. CBitArray *edt_setContainerBreakConvert = 0;
  62. CBitArray *edt_setContainerHasLineAfter = 0;
  63. CBitArray *edt_setIgnoreBreakAfterClose = 0;
  64.  
  65. //-----------------------------------------------------------------------------
  66. //  BitArrays
  67. //-----------------------------------------------------------------------------
  68.  
  69. static XP_Bool bBitsInited = FALSE;
  70.  
  71. void edt_InitBitArrays() {
  72.  
  73.     if( bBitsInited ){
  74.         return;
  75.     }
  76.     bBitsInited = TRUE;
  77.  
  78.     int size = P_MAX + 1; // +1 because CEditRootElements are of type P_MAX.
  79.  
  80.     // Note -- P_UNKNOWN can't be in these arrays because it has a value of -1.
  81.  
  82.     edt_setNoEndTag = new CBitArray(      size,
  83.                                     P_TEXT,
  84.                                     P_PARAGRAPH,
  85.                                     P_IMAGE,
  86.                                     P_NEW_IMAGE,
  87.                                     P_INPUT,
  88.                                     P_LIST_ITEM,
  89.                                     P_HRULE,
  90.                                     P_DESC_TITLE,
  91.                                     P_NSDT,
  92.                                     P_DESC_TEXT,
  93.                                     P_LINEBREAK,
  94.                                     P_WORDBREAK,
  95.                                     P_INDEX,
  96.                                     P_BASE,
  97.                                     P_LINK,
  98.                                     P_META,
  99.                                     P_GRID_CELL,
  100.                                     P_INPUT, //cmanske - forms End tag is "forbidden"
  101.                                     BIT_ARRAY_END );
  102.  
  103.     edt_setWriteEndTag = new CBitArray(   size,
  104.                                     P_HEADER_1,
  105.                                     P_HEADER_2,
  106.                                     P_HEADER_3,
  107.                                     P_HEADER_4,
  108.                                     P_HEADER_5,
  109.                                     P_HEADER_6,
  110.                                     P_PARAGRAPH,
  111.                                     P_ADDRESS,
  112.                                     P_PREFORMAT,
  113.                                     P_LIST_ITEM,
  114.                                     P_DESC_TITLE,
  115.                                     P_DESC_TEXT,
  116.                                     P_NSDT,
  117.                                     BIT_ARRAY_END );
  118.  
  119.  
  120.     edt_setHeadTags = new CBitArray(      size,
  121.                                     P_INDEX,
  122.                                     P_BASE,
  123.                                     P_LINK,
  124.                                     BIT_ARRAY_END );
  125.  
  126.     edt_setSoloTags = new CBitArray(      size,
  127.                                     P_TEXT,
  128.                                     P_IMAGE,
  129.                                     P_NEW_IMAGE,
  130.                                     P_HRULE,
  131.                                     P_LINEBREAK,
  132.                                     P_WORDBREAK,
  133.                                     P_AREA,
  134.                                     P_INPUT,
  135.                                     BIT_ARRAY_END );
  136.  
  137.  
  138.     edt_setBlockFormat = new CBitArray(   size,
  139.                                     P_ANCHOR,
  140.                                     P_CENTER,
  141.                                     P_DIVISION,
  142.                                     P_BLINK,
  143.                                     BIT_ARRAY_END );
  144.  
  145.  
  146.     //
  147.     // Character formatting tags
  148.     //
  149.     edt_setCharFormat = new CBitArray(    size,
  150.                                     P_BOLD,
  151.                                     P_ITALIC,
  152.                                     P_FONT,
  153.                                     P_EMPHASIZED,
  154.                                     P_STRONG,
  155.                                     P_SAMPLE,
  156.                                     P_KEYBOARD,
  157.                                     P_VARIABLE,
  158.                                     P_ANCHOR,
  159.                                     P_STRIKEOUT,
  160.                                     P_UNDERLINE,
  161.                                     P_FIXED,
  162.                                     P_EMPHASIZED,
  163.                                     P_STRONG,
  164.                                     P_CODE,
  165.                                     P_SAMPLE,
  166.                                     P_KEYBOARD,
  167.                                     P_VARIABLE,
  168.                                     P_CITATION,
  169.                                     P_CENTER,
  170.                                     P_BLINK,
  171.                                     P_BIG,
  172.                                     P_SMALL,
  173.                                     P_SUPER,
  174.                                     P_SUB,
  175.                                     P_NOBREAK,
  176.                                     P_SERVER,
  177.                                     P_SCRIPT,
  178.                                     P_STYLE,
  179.                                     P_SPELL,
  180.                                     P_INLINEINPUT,
  181.                                     P_INLINEINPUTTHICK,
  182.                                     P_INLINEINPUTDOTTED,
  183.                                     BIT_ARRAY_END );
  184.  
  185.     edt_setList = new CBitArray( size,
  186.                                     P_UNUM_LIST,
  187.                                     P_NUM_LIST,
  188.                                     P_DESC_LIST,
  189.                                     P_MENU,
  190.                                     P_DIRECTORY,
  191.                                     P_BLOCKQUOTE,
  192.                                     P_MQUOTE,
  193.                                     BIT_ARRAY_END );
  194.  
  195.     // All the tags that are known to navigator, but not to us.
  196.     edt_setUnsupported = new CBitArray( size,
  197.         P_AREA,
  198.         P_CELL,
  199.         P_CERTIFICATE,
  200.         P_ILAYER,
  201.         P_LAYER,
  202.         P_NOLAYER,     //cmanske - added 9/4/97
  203.         P_COLORMAP,
  204.         P_EMBED,
  205.         P_FORM,
  206.         P_INPUT,
  207.         P_OPTION,
  208.         P_SELECT,
  209.         P_TEXTAREA,
  210.         P_GRID,
  211.         P_GRID_CELL,
  212.         P_HYPE,
  213.         P_INDEX,
  214.         P_JAVA_APPLET,
  215.         P_KEYGEN,
  216.         P_MAP,
  217.         P_MULTICOLUMN,
  218.         P_NOEMBED,
  219.         P_NOGRIDS,
  220.         P_NOSCRIPT,
  221.         P_OBJECT,
  222.         P_PARAM,
  223.         P_SPACER,
  224.         P_SUBDOC,
  225.         P_WORDBREAK,
  226.         P_NOSCRIPT,
  227.         P_SPAN,
  228.         BIT_ARRAY_END );
  229.  
  230.     // Any of these tags, when they appear, automatically start the body of
  231.     // the document.
  232.     edt_setAutoStartBody = new CBitArray( size,
  233.         P_TEXT,
  234.         // P_TITLE,
  235.         // P_INDEX,
  236.         // P_BASE,
  237.         // P_LINK,
  238.         P_HEADER_1,
  239.         P_HEADER_2,
  240.         P_HEADER_3,
  241.         P_HEADER_4,
  242.         P_HEADER_5,
  243.         P_HEADER_6,
  244.         P_ANCHOR,
  245.         P_PARAGRAPH,
  246.         P_ADDRESS,
  247.         P_IMAGE,
  248.         P_PLAIN_TEXT,
  249.         P_PLAIN_PIECE,
  250.         P_PREFORMAT,
  251.         P_LISTING_TEXT,
  252.         P_UNUM_LIST,
  253.         P_NUM_LIST,
  254.         P_MENU,
  255.         P_DIRECTORY,
  256.         P_LIST_ITEM,
  257.         P_DESC_LIST,
  258.         P_DESC_TITLE,
  259.         P_DESC_TEXT,
  260.         P_STRIKEOUT,
  261.         P_FIXED,
  262.         P_BOLD,
  263.         P_ITALIC,
  264.         P_EMPHASIZED,
  265.         P_STRONG,
  266.         P_CODE,
  267.         P_SAMPLE,
  268.         P_KEYBOARD,
  269.         P_VARIABLE,
  270.         P_CITATION,
  271.         P_BLOCKQUOTE,
  272.         P_FORM,
  273.         P_INPUT,
  274.         P_SELECT,
  275.         P_OPTION,
  276.         P_TEXTAREA,
  277.         P_HRULE,
  278.         P_LINEBREAK,
  279.         P_WORDBREAK,
  280.         P_NOBREAK,
  281.         P_BASEFONT,
  282.         P_FONT,
  283.         P_BLINK,
  284.         P_NEW_IMAGE,
  285.         P_CENTER,
  286.         P_SUBDOC,
  287.         P_CELL,
  288.         P_TABLE,
  289.         P_CAPTION,
  290.         P_TABLE_ROW,
  291.         P_TABLE_HEADER,
  292.         P_TABLE_DATA,
  293.         P_EMBED,
  294.         // P_BODY,
  295.         // P_META,
  296.         P_COLORMAP,
  297.         P_HYPE,
  298.         P_BIG,
  299.         P_SMALL,
  300.         P_SUPER,
  301.         P_SUB,
  302.         // P_GRID,
  303.         // P_GRID_CELL,
  304.         // P_NOGRIDS,
  305.         P_JAVA_APPLET,
  306.         P_PARAM,
  307.         P_MAP,
  308.         P_AREA,
  309.         P_DIVISION,
  310.         P_KEYGEN,
  311.         // P_SCRIPT,
  312.         // P_NOSCRIPT,
  313.         P_NOEMBED,
  314.         // P_HEAD,
  315.         // P_HTML,
  316.         // P_SERVER,
  317.         P_CERTIFICATE,
  318.         P_ILAYER,
  319.         P_STRIKE,
  320.         P_UNDERLINE,
  321.         P_SPACER,
  322.         P_MULTICOLUMN,
  323.         P_NSCP_CLOSE,
  324.         P_NSCP_OPEN,
  325.         P_BLOCK,
  326.         P_LAYER, //cmanske - fix for bug
  327.         // P_STYLE,
  328.         P_MQUOTE,
  329.         P_SPAN,
  330.         P_SPELL,
  331.         P_INLINEINPUT,
  332.         P_NSCP_REBLOCK,
  333.         P_OBJECT,
  334.         P_NSDT,
  335.         P_INLINEINPUTTHICK,
  336.         P_INLINEINPUTDOTTED,
  337.         P_NOLAYER,
  338.         BIT_ARRAY_END );
  339.  
  340.     edt_setTextContainer = new CBitArray( size,
  341.                                     P_TITLE,
  342.                                     P_HEADER_1,
  343.                                     P_HEADER_2,
  344.                                     P_HEADER_3,
  345.                                     P_HEADER_4,
  346.                                     P_HEADER_5,
  347.                                     P_HEADER_6,
  348.                                     P_PARAGRAPH,
  349.                                     P_ADDRESS,
  350.                                     P_PREFORMAT,
  351.                                     P_LIST_ITEM,
  352.                                     P_DESC_TITLE,
  353.                                     P_DESC_TEXT,
  354.                                     P_NSDT,
  355.                                     BIT_ARRAY_END );
  356.  
  357.     edt_setContainerSupportsAlign = new CBitArray( size,
  358.  
  359.                                     P_HEADER_1,
  360.                                     P_HEADER_2,
  361.                                     P_HEADER_3,
  362.                                     P_HEADER_4,
  363.                                     P_HEADER_5,
  364.                                     P_HEADER_6,
  365.  
  366.     // unfortunately, HRules end paragraph containment, implictly.  So we
  367.     //  either need to change the way we deal with <HR> or change the
  368.     //  code.  until then, we can't generate "align=center" as part of a
  369.     //  paragraph.
  370.                                     //P_PARAGRAPH,
  371.  
  372.                                     //P_ADDRESS,
  373.                                     //P_PREFORMAT,
  374.                                     //P_LIST_ITEM,
  375.                                     //P_DESC_TITLE,
  376.                                     //P_DESC_TEXT,
  377.                                     BIT_ARRAY_END );
  378.  
  379.  
  380.     edt_setListContainer = new CBitArray( size,
  381.                                     P_UNUM_LIST,
  382.                                     P_NUM_LIST,
  383.                                     P_MENU,
  384.                                     P_DIRECTORY,
  385.                                     P_BLOCKQUOTE,
  386.                                     P_MQUOTE,
  387.                                     BIT_ARRAY_END );
  388.  
  389.     edt_setParagraphBreak = new CBitArray( size,
  390.                                     P_TITLE,
  391.                                     P_HEADER_1,
  392.                                     P_HEADER_2,
  393.                                     P_HEADER_3,
  394.                                     P_HEADER_4,
  395.                                     P_HEADER_5,
  396.                                     P_HEADER_6,
  397.                                     P_PARAGRAPH,
  398.                                     P_LINEBREAK,
  399.                                     P_ADDRESS,
  400.                                     P_PREFORMAT,
  401.                                     P_LIST_ITEM,
  402.                                     P_UNUM_LIST,
  403.                                     P_NUM_LIST,
  404.                                     P_LINEBREAK,
  405.                                     P_HRULE,
  406.                                     P_DESC_LIST,
  407.                                     P_DESC_TITLE,
  408.                                     P_DESC_TEXT,
  409.                                     P_NSDT,
  410.                                     P_MQUOTE,
  411.                                     P_TABLE,
  412.                                     BIT_ARRAY_END );
  413.  
  414.     edt_setContainerBreakConvert = new CBitArray( size,
  415.                                     P_PARAGRAPH,
  416.                                     P_LIST_ITEM,
  417.                                     P_ADDRESS,
  418.                                     P_LIST_ITEM,
  419.                                     P_DESC_TITLE,
  420.                                     P_DESC_TEXT,
  421.                                     P_NSDT ,
  422.                                     BIT_ARRAY_END );
  423.  
  424.     edt_setFormattedText = new CBitArray( size,
  425.                                     P_PREFORMAT,
  426.                                     P_PLAIN_PIECE,
  427.                                     P_PLAIN_TEXT,
  428.                                     P_LISTING_TEXT,
  429.                                     BIT_ARRAY_END );
  430.  
  431.     edt_setIgnoreWhiteSpace = new CBitArray( size,
  432.                                     P_TABLE,
  433.                                     P_TABLE_ROW,
  434.                                     BIT_ARRAY_END );
  435.  
  436.     //
  437.     // Suppress printing a newline before these tags.
  438.     //
  439.     edt_setSuppressNewlineBefore = new CBitArray(    size,
  440.                                     P_LINEBREAK,
  441.                                     BIT_ARRAY_END );
  442.  
  443.     //
  444.     // Print a newline after these tags.
  445.     //
  446.  
  447.     edt_setRequireNewlineAfter = new CBitArray(    size,
  448.                                     P_LINEBREAK,
  449.                                     BIT_ARRAY_END );
  450.  
  451.  
  452.     edt_setContainerHasLineAfter = new CBitArray( size, 
  453.                                     P_HEADER_1,
  454.                                     P_HEADER_2,
  455.                                     P_HEADER_3,
  456.                                     P_HEADER_4,
  457.                                     P_HEADER_5,
  458.                                     P_HEADER_6,
  459.                                     P_PREFORMAT,
  460.                                     BIT_ARRAY_END );
  461.  
  462.    edt_setIgnoreBreakAfterClose = new CBitArray( size,
  463.                                     P_HEADER_1,
  464.                                     P_HEADER_2,
  465.                                     P_HEADER_3,
  466.                                     P_HEADER_4,
  467.                                     P_HEADER_5,
  468.                                     P_HEADER_6,
  469.                                     P_PARAGRAPH,
  470.                                     P_ADDRESS,
  471.                                     P_PREFORMAT,
  472.                                     P_LIST_ITEM,
  473.                                     P_DESC_TITLE,
  474.                                     P_DESC_TEXT,
  475.                                     P_NSDT,
  476.                                     BIT_ARRAY_END );
  477. }
  478.  
  479.  
  480. char *edt_GetPathURL( char* pURL ){
  481.     char *pRet = XP_STRDUP(pURL);
  482.     char * pLastSlash = XP_STRRCHR( pRet, '/' );
  483.     if ( pLastSlash == NULL ) {
  484.         XP_FREE(pRet);
  485.         return NULL;
  486.     }
  487.     pLastSlash++;
  488.     *pLastSlash = 0;
  489.  
  490.     // Actually returning a string with unused space after the /0.
  491.     return pRet;
  492. }
  493.  
  494. //-----------------------------------------------------------------------------
  495. // External Interface
  496. //-----------------------------------------------------------------------------
  497.  
  498. char* EDT_GetEmptyDocumentString(){
  499.     return "<html></html>";
  500. }
  501.  
  502. ED_Buffer* EDT_MakeEditBuffer(MWContext *pContext){
  503.     return new CEditBuffer(pContext);
  504. }
  505.  
  506. XP_Bool EDT_HaveEditBuffer(MWContext * pContext){
  507.   return (LO_GetEDBuffer( pContext ) != NULL);
  508. }
  509.  
  510. ED_FileError EDT_SaveFile( MWContext * pContext,
  511.                            char * pSourceURL,
  512.                            char * pDestURL,
  513.                            XP_Bool   bSaveAs,
  514.                            XP_Bool   bKeepImagesWithDoc,
  515.                            XP_Bool   bAutoAdjustLinks ) {
  516.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) ED_ERROR_BLOCKED;
  517.  
  518.     // Create Abstract file system to write to disk.
  519.     char *pDestPathURL = edt_GetPathURL(pDestURL);
  520.     XP_ASSERT(pDestPathURL);
  521.     ITapeFileSystem *tapeFS = new CTapeFSFile(pDestPathURL,pDestURL);
  522.     XP_ASSERT(tapeFS);
  523.     XP_FREE(pDestPathURL);
  524.     // tapeFS freed by CEditSaveObject.
  525.  
  526.     // go to the newly saved document.
  527.     return pEditBuffer->SaveFile( ED_FINISHED_GOTO_NEW, pSourceURL, tapeFS, bSaveAs,
  528.                                   bKeepImagesWithDoc, bAutoAdjustLinks, 
  529.                                   FALSE, // not AutoSave
  530.                                   NULL ); // default files to send with doc
  531. }
  532.  
  533. // Declared here since it is only used by edt_publish_head_done and EDT_PublishFile.
  534. // Takes care of cleaning itself up.
  535. class CEditPublishData {
  536.     public:
  537.         CEditPublishData(CEditBuffer *b, ED_SaveFinishedOption finOpt, 
  538.                           char *src, char **inclFiles,
  539.                           char *loc, char *user, char *pass,
  540.                           XP_Bool keepIm, XP_Bool autoAdj)
  541.         :pBuf(b), finishedOpt(finOpt), pSourceURL(XP_STRDUP(src)), ppIncludedFiles(inclFiles),
  542.          pLocation(XP_STRDUP(loc)), pUsername(XP_STRDUP(user)), pPassword(XP_STRDUP(pass)), 
  543.          bKeepImagesWithDoc(keepIm),bAutoAdjustLinks(autoAdj) {} 
  544.  
  545.         ~CEditPublishData() {XP_FREEIF(pSourceURL); XP_FREEIF(pLocation); XP_FREE(pUsername); XP_FREEIF(pPassword);}
  546.     
  547.     CEditBuffer *pBuf;
  548.     ED_SaveFinishedOption finishedOpt;
  549.     char *pSourceURL;
  550.     char **ppIncludedFiles;
  551.  
  552. //    char *pDestFullURL;
  553.     char *pLocation;  // destination.
  554.     char *pUsername;
  555.     char *pPassword;
  556.  
  557.     XP_Bool bKeepImagesWithDoc;
  558.     XP_Bool bAutoAdjustLinks;
  559. };
  560.  
  561.  
  562.  
  563. // Characters that are not allowed in the destination URL for publishing.
  564. // RFC 1808 and RFC 2068, we are erring on the safe side and allowing
  565. // some potentially illegal URLs.
  566. #define ED_BAD_PUBLISH_URL_CHARS "# <>\""
  567.  
  568. // Return a STATIC string, don't free.
  569. PRIVATE int edt_CheckPublishURL(char *pURL) {
  570.   // NULL or empty string.
  571.   if (!pURL || !(*pURL)) {
  572.     return XP_EDT_PUBLISH_BAD_URL;
  573.   }
  574.  
  575.   // Bad characters.
  576.   char *p = pURL;
  577.   while (*p) {
  578.     if (XP_IS_CNTRL(*p) || XP_STRCHR(ED_BAD_PUBLISH_URL_CHARS,*p)) {
  579.       return XP_EDT_PUBLISH_BAD_CHAR;
  580.     }      
  581.     p++;
  582.   }
  583.  
  584.   // Must be ftp:// or http://
  585.   int result = NET_URL_Type(pURL);
  586.   if (result != FTP_TYPE_URL && 
  587.       result != HTTP_TYPE_URL && 
  588.       result != SECURE_HTTP_TYPE_URL) {
  589.     return XP_EDT_PUBLISH_BAD_PROTOCOL;
  590.   }
  591.  
  592.   // Must not end in a slash, i.e. no filename
  593.   if (pURL[XP_STRLEN(pURL)-1] == '/') {
  594.     return XP_EDT_PUBLISH_NO_FILE;
  595.   }
  596.   
  597.   // The part of the URL after the last slash must have a file extension.
  598.   // Maybe we should be more strict and require that the extension 
  599.   // be .html, .htm, or .shtml.
  600.   char *pLastSlash = XP_STRRCHR(pURL,'/');
  601.   if (!pLastSlash) {
  602.     return XP_EDT_PUBLISH_NO_EXTENSION;
  603.   }
  604.  
  605.   // Search for '.'.
  606.   if (!XP_STRCHR(pLastSlash,'.')) {
  607.     return XP_EDT_PUBLISH_NO_EXTENSION;
  608.   }
  609.  
  610.   return 0;
  611. }
  612.  
  613.  
  614. /* Check the URL that will be passed into EDT_PublishFile. */
  615. XP_Bool EDT_CheckPublishURL( MWContext *pContext, char *pURL) {
  616.   XP_Bool bRetVal = TRUE;
  617.  
  618.   int xpStrId = edt_CheckPublishURL(pURL);
  619.  
  620.   if (xpStrId) {
  621.     char *message = XP_GetString(xpStrId);
  622.     if (message) {
  623.       // Allocate memory for message.
  624.       message = XP_STRDUP(message);
  625.  
  626.       // Report the error, but give the user the option of trying to publish anyway.
  627.       StrAllocCat(message,"\n\n");
  628.       StrAllocCat(message,XP_GetString(XP_EDT_PUBLISH_ERROR_BODY));
  629.       bRetVal = FE_Confirm(pContext,message);
  630.       XP_FREEIF(message);
  631.     }
  632.     else {
  633.       XP_ASSERT(0);
  634.     }
  635.   }    
  636.  
  637.   return bRetVal;
  638. }
  639.  
  640. ED_FileError EDT_PublishFile( MWContext * pContext,
  641.                             ED_SaveFinishedOption finishedOpt,
  642.                            char * pSourceURL,
  643.                            char ** ppIncludedFiles,
  644.                            char * pDestFullURL, /* may not have trailing slash */
  645.                            XP_Bool   bKeepImagesWithDoc,
  646.                            XP_Bool   bAutoAdjustLinks,
  647.                            XP_Bool   bSavePassword ) {
  648.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) ED_ERROR_BLOCKED;
  649.  
  650.     int type = NET_URL_Type(pDestFullURL);
  651.     ED_FileError retVal;
  652.     char *pLocation = NULL;
  653.     char *pUsername = NULL;
  654.     char *pPassword = NULL;
  655.     if (!NET_ParseUploadURL( pDestFullURL, &pLocation, 
  656.                              &pUsername, &pPassword )) {
  657.         // This also checks if the URL is complete garbage.
  658.         return ED_ERROR_BAD_URL;
  659.     }                
  660.     
  661.     // Assemble a URL that includes username, but not password and filename
  662.     char * pDestDirectory = EDT_ReplaceFilename(pLocation, NULL, TRUE);
  663.     if( pDestDirectory ){
  664.         char * pPrefLocation = NULL;
  665.         if (NET_MakeUploadURL(&pPrefLocation,pDestDirectory,pUsername,NULL)) {
  666.             // Save as the "last location" in preferences
  667.                PREF_SetCharPref("editor.publish_last_loc", pPrefLocation);
  668.             
  669.             //  Save the password if user wants us to (and we have one!)
  670.             //  Also set the preference we use for initial state of "save password" checkbox
  671.             if( pPassword && *pPassword ){
  672.                 if( bSavePassword ){    
  673.                     // PROBLEM: If password was wrong, user may have
  674.                     // enterred it in prompted dialog, but we dont know that one!
  675.                     PREF_SetCharPref("editor.publish_last_pass",SECNAV_MungeString(pPassword));
  676.                     PREF_SetBoolPref("editor.publish_save_password",TRUE);
  677.                 } else {
  678.                     PREF_SetBoolPref("editor.publish_save_password",FALSE);
  679.                 }
  680.             }
  681.         }
  682.     }
  683.     
  684.     // FTP  
  685.     if (type == FTP_TYPE_URL) {
  686.         // For ftp, set dest URL to ftp://username@path, so will edit
  687.         // properly.  Explicitly put the username in the URL.
  688.        if (pUsername) {
  689.           char *pUsernameLocation = NULL;
  690.           if (NET_MakeUploadURL(&pUsernameLocation,pLocation,pUsername,NULL)) {
  691.               XP_FREEIF(pLocation);
  692.               pLocation = pUsernameLocation;
  693.           }
  694.        }
  695.  
  696.        retVal = pEditBuffer->PublishFile(finishedOpt,pSourceURL,ppIncludedFiles,
  697.                     pLocation,pUsername,pPassword,
  698.                     bKeepImagesWithDoc,bAutoAdjustLinks);
  699.     }
  700.  
  701.     // HTTP
  702.     else if (type == HTTP_TYPE_URL || type == SECURE_HTTP_TYPE_URL) {
  703.         retVal = pEditBuffer->PublishFile(finishedOpt,pSourceURL,ppIncludedFiles,
  704.                     pLocation,pUsername,pPassword,
  705.                     bKeepImagesWithDoc,bAutoAdjustLinks);
  706.     }
  707.     else {
  708.         // We should have already made sure pDestURL is ftp or http before getting here.
  709.         XP_ASSERT(0);
  710.         retVal = ED_ERROR_BLOCKED;
  711.     }
  712.  
  713.   XP_FREEIF(pLocation);
  714.   XP_FREEIF(pUsername);
  715.   XP_FREEIF(pPassword);
  716.   return retVal;
  717. }
  718.  
  719. ED_FileError EDT_SaveFileTo( MWContext * pContext,
  720.                            ED_SaveFinishedOption finishedOpt,
  721.                            char * pSourceURL,
  722.                            //ITapeFileSystem *tapeFS,
  723.                            void *_tapeFS,
  724.                            XP_Bool   bKeepImagesWithDoc,
  725.                            XP_Bool   bAutoAdjustLinks ) {
  726.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) ED_ERROR_BLOCKED;
  727.  
  728.     ITapeFileSystem *tapeFS = (ITapeFileSystem *)_tapeFS;    
  729.     XP_ASSERT(tapeFS);
  730.     // tapeFS freed by CEditSaveObject.
  731.  
  732.     // saveAs set to TRUE, why not?
  733.     return pEditBuffer->SaveFile( finishedOpt, pSourceURL, tapeFS, TRUE,
  734.                                   bKeepImagesWithDoc, bAutoAdjustLinks, 
  735.                                   FALSE, // not auto-saving
  736.                                   NULL ); // default files to send with doc
  737. }
  738.  
  739. char *EDT_GetDocTempDir(MWContext *pContext) {
  740.   GET_EDIT_BUF_OR_RETURN(pContext,pEditBuffer) NULL;
  741.   CEditCommandLog *pLog = CGlobalHistoryGroup::GetGlobalHistoryGroup()->GetLog(pEditBuffer);
  742.   return pLog ? pLog->GetDocTempDir() : 0;
  743. }
  744.  
  745. char *EDT_CreateDocTempFilename(MWContext *pContext,char *pPrefix,char *pExtension) {
  746.   GET_EDIT_BUF_OR_RETURN(pContext,pEditBuffer) NULL;
  747.   CEditCommandLog *pLog = CGlobalHistoryGroup::GetGlobalHistoryGroup()->GetLog(pEditBuffer);
  748.   return pLog ? pLog->CreateDocTempFilename(pPrefix,pExtension) : 0;
  749. }
  750.  
  751.  
  752. void EDT_SaveToTempFile(MWContext *pContext,EDT_SaveToTempCallbackFn doneFn, void *hook) {
  753.   GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  754.  
  755.   // Get a temporary file name.
  756.   CEditCommandLog *pLog = CGlobalHistoryGroup::GetGlobalHistoryGroup()->GetLog(pEditBuffer);
  757.   if (!pLog) {
  758.     return;
  759.   }
  760.  
  761. // For printing, ".TMP" doesn't work on Windows.
  762. #if defined(XP_WIN) || defined(XP_OS2)
  763.   char *pTemp = pLog->CreateDocTempFilename(NULL,"htm");
  764. #else
  765.   char *pTemp = pLog->CreateDocTempFilename(NULL,"html");
  766. #endif
  767.  
  768.   if (!pTemp) {
  769.     XP_ASSERT(0);
  770.     (*doneFn)(NULL,hook);
  771.     return;
  772.   }
  773.    
  774.   // pTemp is in xpURL format, so just prepend file://
  775.   char *pFileURL = PR_smprintf("file://%s",pTemp);
  776.   XP_FREE(pTemp);
  777.   if (!pFileURL) {
  778.     XP_ASSERT(0);
  779.     (*doneFn)(NULL,hook);
  780.     return;
  781.   }
  782.  
  783.   CEditSaveToTempData *pData = new CEditSaveToTempData;    
  784.   if (!pData) {
  785.     XP_ASSERT(0);
  786.     XP_FREE(pFileURL);
  787.     (*doneFn)(NULL,hook);
  788.     return;
  789.   }
  790.  
  791.  
  792.   // Fill CEditSaveToTempData structure.  
  793.   pData->doneFn = doneFn;
  794.   pData->hook = hook;
  795.   pData->pFileURL = pFileURL;  // Takes responsibility for this memory.
  796.  
  797.   History_entry * hist_entry = SHIST_GetCurrent(&(pContext->hist));
  798.     if(!hist_entry || !hist_entry->address) {
  799.     XP_ASSERT(0);
  800.     delete pData;
  801.     (*doneFn)(NULL,hook);
  802.     return;
  803.   }
  804.  
  805.   /////// ! Duplicating some code from EDT_SaveFile, but I didn't want to change
  806.   /////// ! the interface for EDT_SaveFile(), but we still need to pass in the
  807.   /////// ! CEditSaveToTempData.  We really need a better interface for these
  808.   /////// ! saving functions.  Need some sort of CEditSaveOptions structure.
  809.   // Create Abstract file system to write to disk.
  810.   char *pDestPathURL = edt_GetPathURL(pFileURL);
  811.   XP_ASSERT(pDestPathURL);
  812.   ITapeFileSystem *tapeFS = new CTapeFSFile(pDestPathURL,pFileURL);
  813.   XP_ASSERT(tapeFS);
  814.   XP_FREEIF(pDestPathURL);
  815.   // tapeFS freed by CEditSaveObject.
  816.  
  817.   if (!tapeFS) {
  818.     XP_ASSERT(0);
  819.     delete pData;
  820.     (*doneFn)(NULL,hook);
  821.     return;
  822.   }  
  823.  
  824.   char **ppEmptyList = (char **)XP_ALLOC(sizeof(char *));
  825.   XP_ASSERT(ppEmptyList);
  826.   ppEmptyList[0] = NULL;
  827.  
  828.   pEditBuffer->SaveFile(ED_FINISHED_REVERT_BUFFER, // Don't want to actually change the buffer.
  829.                         hist_entry->address,tapeFS,
  830.                         TRUE, // saveAs is true, probably doesn't matter.
  831.                         FALSE, // Don't move any images.
  832.                         TRUE, // Adjust the links
  833.                         FALSE, // not auto-saving
  834.                         ppEmptyList, // Don't send along any files, even LOCALDATA.
  835.                         pData); // So will callback.
  836. }
  837.  
  838. void EDT_RemoveTempFile(MWContext *pContext,char *pFileURL) {
  839.   GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  840.  
  841.   char *pFileURLPath = NET_ParseURL(pFileURL,GET_PATH_PART);
  842.   if (pFileURLPath) {
  843.     XP_FileRemove(pFileURLPath,xpURL);
  844.   }
  845. }
  846.  
  847. #if defined(MOZ_MAIL_COMPOSE) || defined(MOZ_MAIL_NEWS)
  848. PRIVATE void edt_MailDocumentCB(char *pFileURL,void *hook) {
  849.   if (!hook) {
  850.     XP_ASSERT(0);
  851.     return;
  852.   }
  853.   if (!pFileURL) {
  854.     // Failed to save temp file.
  855.     return;
  856.   }
  857.   MWContext *pContext = (MWContext *)hook;
  858.   MSG_MailDocumentURL(pContext,pFileURL);
  859. }
  860.  
  861. void EDT_MailDocument(MWContext *pContext) {
  862.   GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  863.   if (EDT_IS_NEW_DOCUMENT(pContext) || EDT_DirtyFlag(pContext)) {
  864.     // Write to temp file and mail that instead.
  865.     EDT_SaveToTempFile(pContext,(EDT_SaveToTempCallbackFn) edt_MailDocumentCB,(void *)pContext);
  866.   }
  867.   else {
  868.     MSG_MailDocumentURL(pContext,NULL);
  869.   }
  870. }
  871. #endif
  872.  
  873. void EDT_SaveToBuffer(MWContext* pContext, XP_HUGE_CHAR_PTR* pBuffer )
  874. {
  875.       GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  876.       pEditBuffer->WriteToBuffer(pBuffer, FALSE);
  877. }
  878.  
  879. void EDT_ReadFromBuffer(MWContext* pContext, XP_HUGE_CHAR_PTR pBuffer )
  880. {
  881.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  882.     pEditBuffer->ReadFromBuffer(pBuffer);
  883. }
  884.  
  885.  
  886.  
  887. void EDT_SaveCancel( MWContext *pContext ){
  888.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  889.     if( pEditBuffer->m_pSaveObject){
  890.         pEditBuffer->m_pSaveObject->Cancel();
  891.     }
  892. }
  893.  
  894. void EDT_SetAutoSavePeriod(MWContext *pContext, int32 minutes){
  895.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  896.     pEditBuffer->SetAutoSavePeriod( minutes );
  897. }
  898.  
  899. int32 EDT_GetAutoSavePeriod(MWContext *pContext){
  900.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) -1;
  901.     return pEditBuffer->GetAutoSavePeriod();
  902. }
  903.  
  904. //
  905. // we are blocked if we are blocked or saving an object.
  906. //
  907. XP_Bool EDT_IsBlocked( MWContext *pContext ){
  908.     CEditBuffer *pEditBuffer = LO_GetEDBuffer( pContext );
  909.     return (! pEditBuffer || pEditBuffer->IsBlocked() || pEditBuffer->m_pSaveObject != 0);
  910. }
  911.  
  912. //
  913. // Streams the edit buffer to a big buffer.
  914. //
  915. void EDT_DisplaySource( MWContext *pContext ){
  916.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  917.  
  918.     //char *pSource = 0;
  919.  
  920.     pEditBuffer->DisplaySource();
  921.  
  922.     //pEditBuffer->WriteToBuffer( &pSource );
  923.     //FE_DisplaySource( pContext, pSource );
  924. }
  925.  
  926.  
  927. void EDT_DestroyEditBuffer(MWContext * pContext){
  928.     if ( pContext ) {
  929.         int32 doc_id;
  930.         lo_TopState *top_state;
  931.  
  932.         /*
  933.          * Get the unique document ID, and retreive this
  934.          * documents layout state.
  935.          */
  936.         doc_id = XP_DOCID(pContext);
  937.         top_state = lo_FetchTopState(doc_id);
  938.         if ((top_state == NULL)||(top_state->doc_state == NULL))
  939.         {
  940.             return;
  941.         }
  942.         CEditBuffer *pEditBuffer = top_state->edit_buffer;
  943.         delete pEditBuffer;
  944.         top_state->edit_buffer = NULL;
  945.     }
  946. }
  947.  
  948.  
  949. //
  950. // Hooked into the GetURL state machine.  We do intermitent processing to
  951. //  let the layout engine to the initial processing and fetch all the nested
  952. //  images.
  953. //
  954. // Returns: 1 - Done ok, continuing.
  955. //    0 - Done ok, stopping.
  956. //   -1 - not done, error.
  957. //
  958. intn EDT_ProcessTag(void *data_object, PA_Tag *tag, intn status){
  959.     pa_DocData *pDocData = (pa_DocData*)data_object;
  960.     int parseRet = OK_CONTINUE;
  961.     intn retVal;
  962.     XP_Bool bCreatedEditor = FALSE;
  963.  
  964.     if( !EDT_IS_EDITOR(pDocData->window_id) ){
  965.         return LO_ProcessTag( data_object, tag, status );
  966.     }
  967.  
  968.     if( pDocData->edit_buffer == 0 ){
  969.         pDocData->edit_buffer = EDT_MakeEditBuffer( pDocData->window_id );
  970.         bCreatedEditor = pDocData->edit_buffer != NULL;
  971.     }
  972.  
  973. #if 0
  974.     // if parsing is complete and we didn't end up with anything, force a NOBR
  975.     //  space.
  976.     if( tag == NULL && status == PA_COMPLETE ) {
  977.         CEditRootDocElement* pRoot = pDocData->edit_buffer->m_pRoot;
  978.         XP_Bool bNoData = ! pRoot || ! pRoot->GetChild();
  979.         if ( bNoData ){
  980.             pDocData->edit_buffer->DummyCharacterAddedDuringLoad();
  981.             PA_Tag *pNewTag = XP_NEW( PA_Tag );
  982.             XP_BZERO( pNewTag, sizeof( PA_Tag ) );
  983.  
  984.             // Non-breaking-spaces cause a memory leak when they are laid out in 3.0b5.
  985.             // See bug 23404.
  986.             // And anyway, we strip out this character.
  987.             // So it can be any character.
  988.             // edt_SetTagData( pNewTag, NON_BREAKING_SPACE_STRING );
  989.             edt_SetTagData( pNewTag, "$" );
  990.  
  991.             pDocData->edit_buffer->ParseTag( pDocData, pNewTag, status );
  992.  
  993.             PA_FreeTag( pNewTag );
  994.         }
  995.     }
  996. #endif
  997.  
  998.     if( tag ){
  999.         // Fix bug 67427 - if the MWContext doesn't have an editor at this point, it
  1000.         // means that the editor has been deleted.
  1001.         CEditBuffer* pEditBuffer = (CEditBuffer*) LO_GetEDBuffer(pDocData->window_id);
  1002.         if ( pEditBuffer != pDocData->edit_buffer && ! bCreatedEditor ){
  1003.             return LO_ProcessTag( data_object, tag, status );
  1004.         }
  1005.         parseRet = pDocData->edit_buffer->ParseTag( pDocData, tag, status );
  1006.     }
  1007.  
  1008.     if( parseRet != OK_IGNORE ){
  1009.  
  1010. #if 0
  1011.         //
  1012.         // Check to see if the tag went away.  Text without an Edit Element
  1013.         //
  1014.         // LTNOTE: this case should now return OK_IGNORE, don't check.
  1015.         //
  1016.         if( tag
  1017.                 && tag->type == P_TEXT
  1018.                 && tag->data
  1019.                 && tag->edit_element == 0 )
  1020.             {
  1021.                 PA_FREE( tag->data );
  1022.                 return 1;
  1023.             }
  1024. #endif
  1025.         retVal = LO_ProcessTag( data_object, tag, status );
  1026.         if( tag == 0 ){
  1027.             //pDocData->edit_buffer->FinishedLoad();
  1028.         }
  1029.         return retVal;
  1030.     }
  1031.     else{
  1032.         PA_FreeTag(tag);
  1033.         return 1;
  1034.     }
  1035. }
  1036.  
  1037. #if 0
  1038.  
  1039. static char *loTypeNames[] = {
  1040.     "LO_NONE",
  1041.     "LO_TEXT",
  1042.     "LO_LINEFEED",
  1043.     "LO_HRULE",
  1044.     "LO_IMAGE",
  1045.     "LO_BULLET",
  1046.     "LO_FORM_ELE",
  1047.     "LO_SUBDOC",
  1048.     "LO_TABLE",
  1049.     "LO_CELL",
  1050.     "LO_EMBED",
  1051. };
  1052.  
  1053. //
  1054. // Debug routine
  1055. //
  1056. PRIVATE
  1057. void EDT_ShowElement( LO_Element* le ){
  1058.     char buff[512];
  1059.     CEditTextElement *pText;
  1060.     XP_TRACE(("  Type:          %s", loTypeNames[le->type] ));
  1061.     XP_TRACE(("  ele_id:        %d", le->lo_any.ele_id ));
  1062.     XP_TRACE(("  edit_element   0x%x", le->lo_any.edit_element));
  1063.     XP_TRACE(("  edit_offset    %d", le->lo_any.edit_offset));
  1064.     if( le->type == LO_TEXT && le->lo_any.edit_element->IsA( P_TEXT ) ){
  1065.         pText = le->lo_any.edit_element->Text();
  1066.         XP_TRACE(("  lo_element(text)     '%s'", le->lo_text.text ));
  1067.         XP_TRACE(("  edit_element(text)   '%s'", pText->GetText()));
  1068.         strncpy( buff, pText->GetText()+le->lo_any.edit_offset,
  1069.                     le->lo_text.text_len );
  1070.         buff[le->lo_text.text_len] = '\0';
  1071.         XP_TRACE(("  edit_element text( %d, %d ) = '%s' ",
  1072.                 le->lo_any.edit_offset, le->lo_text.text_len, buff));
  1073.     }
  1074. }
  1075.  
  1076. #endif
  1077.  
  1078. void EDT_SetInsertPoint( ED_Buffer *pBuffer, ED_Element* pElement, int iPosition, XP_Bool bStickyAfter ){
  1079.     if( pBuffer->IsBlocked() ){ return; }
  1080.     if ( ! pElement->IsLeaf() ){
  1081.         XP_ASSERT(FALSE);
  1082.         return;
  1083.     }
  1084.     pBuffer->SetInsertPoint( pElement->Leaf(), iPosition, bStickyAfter );
  1085. }
  1086.  
  1087.  
  1088. void EDT_SetLayoutElement( ED_Element* pElement, intn iEditOffset,
  1089.         intn lo_type, LO_Element *pLayoutElement ){
  1090.     // XP_TRACE(("EDT_SetLayoutElement pElement(0x%08x) iEditOffset(%d) pLayoutElement(0x%08x)", pElement, iEditOffset, pLayoutElement));
  1091.     if( pElement != 0 && pElement->IsLeaf() ) {
  1092.          pElement->Leaf()->SetLayoutElement( iEditOffset, lo_type, pLayoutElement );
  1093.     }
  1094. }
  1095.  
  1096. void EDT_ResetLayoutElement( ED_Element* /* pElement */, intn /* iEditOffset */,
  1097.         LO_Element * /*pLayoutElement */ ){
  1098.     /* The lifetime of a layout element can be greater than that of the
  1099.        corresponding edit element. An example is when you browse to the home page,
  1100.        hit edit, then cancel the save.
  1101.        When EDT_ResetLayoutElement happens, pElement
  1102.        may already have been deleted.
  1103.  
  1104.        We were only doing this book keeping to be neat. So it's OK to disable it.
  1105.      */
  1106. #if 0
  1107.     XP_TRACE(("EDT_ResetLayoutElement pElement(0x%08x) iEditOffset(%d) pLayoutElement(0x%08x)", pElement, iEditOffset, pLayoutElement));
  1108.     if( pElement != 0 && pElement->IsLeaf()) {
  1109.          pElement->Leaf()->ResetLayoutElement( iEditOffset, pLayoutElement );
  1110.     }
  1111. #endif
  1112. }
  1113.  
  1114. #ifdef DEBUG
  1115. void EDT_VerifyLayoutElement( MWContext *pContext, LO_Element *pLoElement,
  1116.         XP_Bool bPrint ){
  1117.     CEditElement *pElement = pLoElement->lo_any.edit_element;
  1118.     if( pElement ){
  1119.         if( !pElement->IsLeaf() ){
  1120.             // die here.
  1121.         }
  1122.  
  1123.         LO_Element *pEle;
  1124.         intn iLayoutOffset;
  1125.         if( !pElement->Leaf()->GetLOElementAndOffset(
  1126.                     pLoElement->lo_any.edit_offset, TRUE,
  1127.                     pEle,
  1128.                     iLayoutOffset ) ) {
  1129.             XP_TRACE((" couldn't find layout element %8x(%d) from edit_element %8x",
  1130.                     pLoElement, pLoElement->lo_any.ele_id, pElement ));
  1131.             XP_ASSERT(FALSE);
  1132.             return;
  1133.         }
  1134.  
  1135.         if( pEle != pLoElement ){
  1136.             XP_TRACE(("Found wrong layout element\n"
  1137.                         "    Original Element %8x(%d)\n"
  1138.                         "    Found Element %8x(%d)\n",
  1139.                     pLoElement, pLoElement->lo_any.ele_id,
  1140.                     pEle, pEle != NULL ? pEle->lo_any.ele_id : 0));
  1141.             XP_ASSERT(FALSE);
  1142.         }
  1143.     }
  1144. }
  1145. #endif //DEBUG
  1146.  
  1147. void EDT_DeleteTagChain( PA_Tag* pTag ){
  1148.     while( pTag ){
  1149.         PA_Tag* pNext = pTag->next;
  1150.         PA_FreeTag( pTag );
  1151.         pTag = pNext;
  1152.     }
  1153. }
  1154.  
  1155. PA_Tag* EDT_TagCursorGetNext( ED_TagCursor* pCursor ){
  1156.     return pCursor->GetNextTag();
  1157. }
  1158.  
  1159. PA_Tag* EDT_TagCursorGetNextState( ED_TagCursor* pCursor ){
  1160.     return pCursor->GetNextTagState();
  1161. }
  1162.  
  1163. XP_Bool EDT_TagCursorAtBreak( ED_TagCursor* pCursor, XP_Bool* pEndTag ){
  1164.     return pCursor->AtBreak(pEndTag);
  1165. }
  1166.  
  1167. int32 EDT_TagCursorCurrentLine( ED_TagCursor* pCursor ){
  1168.     return pCursor->CurrentLine();
  1169. }
  1170.  
  1171. XP_Bool EDT_TagCursorClearRelayoutState( ED_TagCursor* pCursor ){
  1172.     return pCursor->ClearRelayoutState();
  1173. }
  1174.  
  1175.  
  1176. ED_TagCursor* EDT_TagCursorClone( ED_TagCursor *pCursor ){
  1177.     return pCursor->Clone();
  1178. }
  1179.  
  1180. void EDT_TagCursorDelete( ED_TagCursor* pCursor ){
  1181.     delete pCursor;
  1182. }
  1183.  
  1184. //-----------------------------------------------------------------------------
  1185. // FE Keyboard interface.
  1186. //-----------------------------------------------------------------------------
  1187.  
  1188. EDT_ClipboardResult EDT_KeyDown( MWContext *pContext, uint16 nChar, uint16 /* b */, uint16 /* c */ ){
  1189.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) EDT_COP_DOCUMENT_BUSY;
  1190.     if( pEditBuffer && nChar >= ' ' ){
  1191.         return pEditBuffer->InsertChar(nChar, TRUE);
  1192.     }
  1193.     return EDT_COP_OK;
  1194. }
  1195.  
  1196. EDT_ClipboardResult EDT_InsertNonbreakingSpace( MWContext *pContext ){
  1197.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) EDT_COP_DOCUMENT_BUSY;
  1198.     EDT_ClipboardResult result = EDT_COP_OK;
  1199.     const char *p;
  1200.     INTL_CharSetInfo c = LO_GetDocumentCharacterSetInfo(pContext);
  1201.     // Nonbreaking space can be string for multibyte
  1202.     p = INTL_NonBreakingSpace(INTL_GetCSIWinCSID(c));
  1203.     for (; *p; p++){
  1204.         result = pEditBuffer->InsertChar(*p, TRUE);
  1205.         if ( result != EDT_COP_OK) break;
  1206.     }
  1207.     return result;
  1208. }
  1209.  
  1210. EDT_ClipboardResult EDT_DeletePreviousChar( MWContext *pContext ){
  1211.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) EDT_COP_DOCUMENT_BUSY;
  1212.     return pEditBuffer->DeletePreviousChar();
  1213. }
  1214.  
  1215. EDT_ClipboardResult EDT_DeleteChar( MWContext *pContext ){
  1216.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) EDT_COP_DOCUMENT_BUSY;
  1217.     return pEditBuffer->DeleteNextChar();
  1218. }
  1219.  
  1220. //---------------------------------------------------------------------------
  1221. //  Navigation
  1222. //---------------------------------------------------------------------------
  1223. void EDT_PreviousChar( MWContext *pContext, XP_Bool bSelect ){
  1224.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1225.     // pEditBuffer->PreviousChar( bSelect );
  1226.     pEditBuffer->NavigateChunk( bSelect, LO_NA_CHARACTER, FALSE );
  1227. }
  1228.  
  1229. void EDT_NextChar( MWContext *pContext, XP_Bool bSelect ){
  1230.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1231.     pEditBuffer->NavigateChunk( bSelect, LO_NA_CHARACTER, TRUE );
  1232. }
  1233.  
  1234. void EDT_Up( MWContext *pContext, XP_Bool bSelect ){
  1235.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1236.     pEditBuffer->UpDown( bSelect, FALSE );
  1237. }
  1238.  
  1239. void EDT_Down( MWContext *pContext, XP_Bool bSelect ){
  1240.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1241.     pEditBuffer->UpDown( bSelect, TRUE );
  1242. }
  1243.  
  1244. #endif //EDITOR
  1245.  
  1246. #ifdef EDITOR
  1247.  
  1248. void EDT_BeginOfLine( MWContext *pContext, XP_Bool bSelect ){
  1249.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1250.     pEditBuffer->NavigateChunk( bSelect, LO_NA_LINEEDGE, FALSE );
  1251. }
  1252.  
  1253. void EDT_EndOfLine( MWContext *pContext, XP_Bool bSelect ){
  1254.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1255.     pEditBuffer->NavigateChunk( bSelect, LO_NA_LINEEDGE, TRUE );
  1256. }
  1257.  
  1258. void EDT_BeginOfDocument( MWContext *pContext, XP_Bool bSelect ){
  1259.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1260.     pEditBuffer->NavigateDocument( bSelect, FALSE );
  1261. }
  1262.  
  1263. void EDT_EndOfDocument( MWContext *pContext, XP_Bool bSelect ){
  1264.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1265.     pEditBuffer->NavigateDocument( bSelect, TRUE );
  1266. }
  1267.  
  1268. void EDT_PageUp( MWContext *pContext, XP_Bool bSelect ){
  1269.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1270.     pEditBuffer->PageUpDown( bSelect, FALSE);
  1271. }
  1272.  
  1273. void EDT_PageDown( MWContext *pContext, XP_Bool bSelect ){
  1274.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1275.     pEditBuffer->PageUpDown( bSelect ,TRUE);
  1276. }
  1277.  
  1278. void EDT_PreviousWord( MWContext *pContext, XP_Bool bSelect ){
  1279.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1280.     pEditBuffer->NavigateChunk( bSelect, LO_NA_WORD, FALSE );
  1281. }
  1282.  
  1283. void EDT_NextWord( MWContext *pContext, XP_Bool bSelect ){
  1284.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1285.     pEditBuffer->NavigateChunk( bSelect, LO_NA_WORD, TRUE );
  1286. }
  1287.  
  1288. //CLM: Navigate from cell to cell
  1289. void EDT_NextTableCell( MWContext *pContext, XP_Bool bSelect ){
  1290.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1291.     pEditBuffer->NextTableCell(bSelect, TRUE);
  1292. }
  1293.  
  1294. void EDT_PreviousTableCell( MWContext *pContext, XP_Bool bSelect ){
  1295.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1296.     pEditBuffer->NextTableCell(bSelect, FALSE);
  1297. }
  1298.  
  1299. //
  1300. // Kind of a bizarre routine, Order of calls is as follows:
  1301. //  FE_OnMouseDown      - determines x and y in layout coords. calls:
  1302. //  EDT_PositionCaret   - clears movement and calls
  1303. //  LO_PositionCaret    - figures out which layout element is under caret and calls
  1304. //  EDT_SetInsertPoint  - which sets the edit element and offset and then calls
  1305. //  FE_DisplayTextCaret - which actually positions the caret.
  1306. //
  1307. // There are some more levels in there, but from an external view, this is how
  1308. //  it occurs.
  1309. //
  1310. void EDT_PositionCaret( MWContext *pContext, int32 x, int32 y ){
  1311.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1312.     pEditBuffer->PositionCaret(x, y);
  1313. }
  1314.  
  1315. void EDT_DeleteSelectionAndPositionCaret( MWContext *pContext, int32 x, int32 y ){
  1316.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1317.     pEditBuffer->DeleteSelectionAndPositionCaret(x, y);
  1318. }
  1319.  
  1320. XP_Bool EDT_PositionDropCaret( MWContext *pContext, int32 x, int32 y ){
  1321.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) FALSE;
  1322.     return pEditBuffer->PositionDropCaret(x, y);
  1323. }
  1324.  
  1325. XP_Bool EDT_StartDragTable( MWContext *pContext, int32 x, int32 y ){
  1326.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) FALSE;
  1327.     return pEditBuffer->StartDragTable(x, y);
  1328. }
  1329.  
  1330. void EDT_StopDragTable( MWContext *pContext )
  1331. {
  1332.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1333.     pEditBuffer->StopDragTable();
  1334. }
  1335.  
  1336. XP_Bool EDT_IsDraggingTable( MWContext *pContext )
  1337. {
  1338.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) FALSE;
  1339.     return pEditBuffer->IsDraggingTable();
  1340. }
  1341.  
  1342. void EDT_DoubleClick( MWContext *pContext, int32 x, int32 y ){
  1343.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1344.     pEditBuffer->StartSelection(x,y, TRUE);
  1345. }
  1346.  
  1347. void EDT_SelectObject( MWContext *pContext, int32 x, int32 y ){
  1348.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1349.     pEditBuffer->SelectObject(x,y);
  1350. }
  1351.  
  1352. void EDT_WindowScrolled( MWContext *pContext ){
  1353.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1354.     pEditBuffer->WindowScrolled();
  1355. }
  1356.  
  1357. EDT_ClipboardResult EDT_ReturnKey( MWContext *pContext ){
  1358.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) EDT_COP_DOCUMENT_BUSY;
  1359.     return pEditBuffer->ReturnKey(TRUE);
  1360. }
  1361.  
  1362. EDT_ClipboardResult EDT_TabKey( MWContext *pContext, XP_Bool bForward, XP_Bool bForceTabChar ){
  1363.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) EDT_COP_DOCUMENT_BUSY;
  1364.     return pEditBuffer->TabKey(bForward, bForceTabChar);
  1365. }
  1366.  
  1367. void EDT_Indent( MWContext *pContext ){
  1368.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1369.     {
  1370.         CEditSelection selection;
  1371.         pEditBuffer->GetSelection(selection);
  1372.         if ( selection.CrossesSubDocBoundary() ) {
  1373.             return;
  1374.         }
  1375.     }
  1376.     pEditBuffer->BeginBatchChanges(kIndentCommandID);
  1377.     pEditBuffer->Indent();
  1378.     pEditBuffer->EndBatchChanges();
  1379. }
  1380.  
  1381. void EDT_Outdent( MWContext *pContext ){
  1382.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1383.     pEditBuffer->BeginBatchChanges(kIndentCommandID);
  1384.     pEditBuffer->Outdent();
  1385.     pEditBuffer->EndBatchChanges();
  1386. }
  1387.  
  1388. void EDT_RemoveList( MWContext *pContext ){
  1389.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1390.     // Repeat removing indent until last Unnumbered list is gone
  1391.     pEditBuffer->BeginBatchChanges(kParagraphAlignCommandID);
  1392.     pEditBuffer->MorphContainer( P_NSDT );
  1393.  
  1394.     EDT_ListData * pListData;
  1395.     while ( (pListData = pEditBuffer->GetListData()) != NULL ){
  1396.         EDT_FreeListData(pListData);
  1397.         pEditBuffer->Outdent();
  1398.     }
  1399.     pEditBuffer->EndBatchChanges();
  1400. }
  1401.  
  1402. void EDT_ToggleList(MWContext *pContext, intn iTagType)
  1403. {
  1404.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1405.     EDT_BeginBatchChanges(pContext);
  1406.     pEditBuffer->ToggleList(iTagType);
  1407.     EDT_EndBatchChanges(pContext);
  1408. }
  1409.  
  1410. XP_Bool EDT_GetToggleListState(MWContext *pContext, intn iTagType)
  1411. {
  1412.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) FALSE;
  1413.        TagType nParagraphFormat = EDT_GetParagraphFormatting( pContext );
  1414.     EDT_ListData * pData = NULL;
  1415.     XP_Bool bIsMyList = FALSE;
  1416.     // Description list is a special case - it doesn't (and shouldn't)
  1417.     //   have <LI> items. It should contain <DT> (Desc.Title) and 
  1418.     //   <DD> (Desc. text) items.
  1419.     if ( nParagraphFormat == P_LIST_ITEM || iTagType == P_DESC_LIST ) {
  1420.         pData = EDT_GetListData(pContext);
  1421.         bIsMyList = ( pData && pData->iTagType == iTagType );
  1422.     }
  1423.     if ( pData ) {
  1424.         EDT_FreeListData( pData );
  1425.     }
  1426.     return bIsMyList;
  1427. }
  1428.  
  1429. void EDT_SetParagraphAlign( MWContext *pContext, ED_Alignment eAlign ){
  1430.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1431.     pEditBuffer->BeginBatchChanges(kParagraphAlignCommandID);
  1432.     pEditBuffer->SetParagraphAlign( eAlign );
  1433.     pEditBuffer->EndBatchChanges();
  1434. }
  1435.  
  1436. ED_Alignment EDT_GetParagraphAlign( MWContext *pContext){
  1437.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) ED_ALIGN_LEFT;
  1438.     return pEditBuffer->GetParagraphAlign();
  1439. }
  1440.  
  1441. void EDT_SetTableAlign( MWContext *pContext, ED_Alignment eAlign ){
  1442.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1443.     pEditBuffer->BeginBatchChanges(kParagraphAlignCommandID);
  1444.     pEditBuffer->SetTableAlign( eAlign );
  1445.     pEditBuffer->EndBatchChanges();
  1446. }
  1447.  
  1448. void EDT_MorphContainer( MWContext *pContext, TagType t ){
  1449.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1450.     pEditBuffer->BeginBatchChanges(kParagraphAlignCommandID);
  1451.     if( t == P_BLOCKQUOTE ||
  1452.         t == P_DIRECTORY ||
  1453.         t == P_MENU ||
  1454.         t == P_DESC_LIST){
  1455.         pEditBuffer->MorphListContainer( t );
  1456.     } else {
  1457.         pEditBuffer->MorphContainer( t );
  1458.     }
  1459.     pEditBuffer->EndBatchChanges();
  1460. }
  1461.  
  1462. void EDT_FormatCharacter( MWContext *pContext, ED_TextFormat tf ){
  1463.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1464.     pEditBuffer->FormatCharacter( tf );
  1465. }
  1466.  
  1467. EDT_CharacterData* EDT_GetCharacterData( MWContext *pContext ){
  1468.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) 0;
  1469.     return pEditBuffer->GetCharacterData();
  1470. }
  1471.  
  1472. void EDT_SetCharacterData( MWContext *pContext, EDT_CharacterData *pData ){
  1473.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1474.     pEditBuffer->SetCharacterData( pData );
  1475. }
  1476.  
  1477. EDT_CharacterData* EDT_NewCharacterData(){
  1478.     EDT_CharacterData* pData = XP_NEW( EDT_CharacterData );
  1479.     XP_BZERO( pData, sizeof( EDT_CharacterData ));
  1480.     return pData;
  1481. }
  1482.  
  1483. void EDT_FreeCharacterData( EDT_CharacterData *pData ){
  1484.     if( pData->pHREFData ){
  1485.         EDT_FreeHREFData( pData->pHREFData );
  1486.     }
  1487.     if( pData->pColor ){
  1488.         XP_FREE( pData->pColor );
  1489.     }
  1490.     if( pData->pFontFace ){
  1491.         XP_FREE( pData->pFontFace );
  1492.     }
  1493.     XP_FREE( pData );
  1494. }
  1495.  
  1496.  
  1497. #if 0
  1498. PRIVATE
  1499. ED_BitArray* EDT_BitArrayCreate(){
  1500.     return new CBitArray(P_MAX, 0);
  1501. }
  1502.  
  1503. PRIVATE
  1504. void EDT_BitArrayDestroy( ED_BitArray* pBitArray){
  1505.     delete pBitArray;
  1506. }
  1507.  
  1508. PRIVATE
  1509. XP_Bool EDT_BitArrayTest( ED_BitArray* pBitArray, TagType t ){
  1510.     return (*pBitArray)[t];
  1511. }
  1512. #endif
  1513.  
  1514. ED_TextFormat EDT_GetCharacterFormatting( MWContext *pContext){
  1515.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) 0;
  1516.     return pEditBuffer->GetCharacterFormatting();
  1517. }
  1518.  
  1519. /* CM: "Current" is superfluous! */
  1520. ED_ElementType EDT_GetCurrentElementType( MWContext *pContext){
  1521.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) ED_ELEMENT_TEXT;
  1522.     return pEditBuffer->GetCurrentElementType();
  1523. }
  1524.  
  1525. TagType EDT_GetParagraphFormatting( MWContext *pContext ){
  1526.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) P_UNKNOWN;
  1527.     return pEditBuffer->GetParagraphFormatting( );
  1528. }
  1529.  
  1530. int EDT_GetFontSize( MWContext *pContext ){
  1531.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) 0;
  1532.     return pEditBuffer->GetFontSize();
  1533. }
  1534.  
  1535. void EDT_SetFontSize( MWContext *pContext, int iSize ){
  1536.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1537.     pEditBuffer->SetFontSize(iSize);
  1538. }
  1539.  
  1540. int EDT_GetFontPointSize( MWContext *pContext ){
  1541.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) 0;
  1542.     return pEditBuffer->GetFontPointSize();
  1543. }
  1544.  
  1545. void EDT_SetFontPointSize( MWContext *pContext, int iPoints ){
  1546.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1547.     pEditBuffer->SetFontPointSize(iPoints);
  1548. }
  1549.  
  1550. int EDT_GetFontFaceIndex(MWContext *pContext){
  1551.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) -1;
  1552.     return pEditBuffer->GetFontFaceIndex();
  1553. }
  1554.  
  1555. char * EDT_GetFontFace(MWContext *pContext){
  1556.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) NULL;
  1557.     return pEditBuffer->GetFontFace();
  1558. }
  1559.  
  1560. //
  1561. // Some macros for packing and unpacking colors.
  1562. //
  1563.  
  1564. XP_Bool EDT_GetFontColor( MWContext *pContext, LO_Color* pDestColor ){
  1565.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) FALSE;
  1566.     ED_Color i = pEditBuffer->GetFontColor();
  1567.     if( i.IsDefined() ){
  1568.         pDestColor->red = EDT_RED(i);
  1569.         pDestColor->green = EDT_GREEN(i);
  1570.         pDestColor->blue = EDT_BLUE(i);
  1571.         return TRUE;
  1572.     }
  1573.     else {
  1574.         return FALSE;
  1575.     }
  1576. }
  1577.  
  1578. void EDT_SetFontColor( MWContext *pContext, LO_Color *pColor){
  1579.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1580.     if( pColor ){
  1581.         pEditBuffer->SetFontColor( EDT_LO_COLOR( pColor ) );
  1582.     }
  1583.     else {
  1584.         pEditBuffer->SetFontColor(ED_Color::GetUndefined());
  1585.     }
  1586. }
  1587.  
  1588. void EDT_StartSelection(MWContext *pContext, int32 x, int32 y){
  1589.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1590.     pEditBuffer->StartSelection(x,y, FALSE);
  1591. }
  1592.  
  1593. void EDT_ExtendSelection(MWContext *pContext, int32 x, int32 y){
  1594.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1595.     pEditBuffer->ExtendSelection(x,y);
  1596. }
  1597.  
  1598. void EDT_EndSelection(MWContext *pContext, int32 x, int32 y){
  1599.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1600.     pEditBuffer->EndSelection(x, y);
  1601. }
  1602.  
  1603. void EDT_SelectAll(MWContext *pContext){
  1604.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1605.     pEditBuffer->SelectAll();
  1606. }
  1607.  
  1608. void EDT_SelectTable(MWContext *pContext){
  1609.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1610.     pEditBuffer->SelectTable();
  1611. }
  1612.  
  1613. void EDT_SelectTableCell(MWContext *pContext){
  1614.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1615.     pEditBuffer->SelectTableCell();
  1616. }
  1617.  
  1618. void EDT_ClearTableAndCellSelection(MWContext *pContext)
  1619. {
  1620.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1621.     pEditBuffer->ClearTableAndCellSelection();
  1622. }
  1623.  
  1624. XP_Bool EDT_IsTableSelected(MWContext *pContext)
  1625. {
  1626.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) FALSE;
  1627.     return pEditBuffer->IsTableSelected();
  1628. }
  1629.  
  1630. int EDT_GetSelectedCellCount(MWContext *pContext)
  1631. {
  1632.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) 0;
  1633.     return pEditBuffer->GetSelectedCellCount();
  1634. }
  1635.  
  1636. void EDT_ClearCellSelectionIfNotInside(MWContext *pContext)
  1637. {
  1638.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1639.     pEditBuffer->ClearCellSelectionIfNotInside();
  1640. }
  1641.  
  1642. void EDT_StartSpecialCellSelection(MWContext *pContext, EDT_TableCellData *pCellData)
  1643. {
  1644.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1645.     pEditBuffer->StartSpecialCellSelection(pCellData);
  1646. }
  1647.  
  1648. void EDT_ClearSpecialCellSelection(MWContext *pContext)
  1649. {
  1650.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1651.     pEditBuffer->ClearSpecialCellSelection();
  1652. }
  1653.  
  1654. void EDT_ClearSelection(MWContext *pContext){
  1655.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1656.     CEditSelection selection;
  1657.     pEditBuffer->GetSelection(selection);
  1658.     selection.m_end = selection.m_start; // Leave cursor at left, so table cell change data works.
  1659.     CSetSelectionCommand* pSelectCommand = new CSetSelectionCommand(pEditBuffer, selection);
  1660.     pEditBuffer->AdoptAndDo(pSelectCommand);
  1661. }
  1662.  
  1663. EDT_ClipboardResult EDT_InsertText( MWContext *pContext, char *pText ) {
  1664.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) EDT_COP_DOCUMENT_BUSY;
  1665.     pEditBuffer->DeleteSelection();
  1666.     pEditBuffer->StartTyping(TRUE);
  1667.     EDT_ClipboardResult result = pEditBuffer->PasteText( pText, FALSE, TRUE, TRUE ,TRUE);
  1668.     return result;
  1669. }
  1670.  
  1671. EDT_ClipboardResult EDT_PasteText( MWContext *pContext, char *pText ) {
  1672.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) EDT_COP_DOCUMENT_BUSY;
  1673.     pEditBuffer->BeginBatchChanges(kPasteTextCommandID);
  1674.     EDT_ClipboardResult result;
  1675.  
  1676.     XP_Bool bPasteAsTable = FALSE;
  1677.  
  1678.     // Determine format of paste text - use tabs as cell delimiters, <CR><LF> as end of row
  1679.     intn iCols;
  1680.     intn iRows;
  1681.     XP_Bool bEqualCols = pEditBuffer->CountRowsAndColsInPasteText(pText, &iRows, &iCols);
  1682.     // Ask user for approval only if we have a well-formed table with > 1 column to paste
  1683.     if( bEqualCols && iCols > 1 && iRows > 0 )
  1684.     {
  1685.         char *pMessage = NULL;
  1686.         pMessage = PR_sprintf_append( pMessage, "Text can be pasted as %d rows and %d columns.\n\n", iRows, iCols);
  1687.         if( pEditBuffer->IsInsertPointInTableCell() )
  1688.         {
  1689.             // Give message about pasting into an existing table
  1690.             //TODO: MAKE XP STRINGS FOR EDT_PasteText INTO TABLES
  1691.             pMessage = PR_sprintf_append( pMessage, "Replace existing cells?");
  1692.  
  1693.             if( FE_Confirm(pEditBuffer->GetContext(), pMessage) )
  1694.             {
  1695.                 //TODO: Implement PasteIntoTable(TRUE); // TRUE = delete existing cells
  1696.                 bPasteAsTable = TRUE;
  1697.             } else {
  1698.                 //TODO: Implement PasteIntoTable(FALSE); // FALSE = append to existing cells
  1699.                 // For now, just paste into one cell
  1700.                 //bPasteAsTable = TRUE;
  1701.             }
  1702.             bPasteAsTable = TRUE;
  1703.         } else {
  1704.             // Give message about pasting as a new table
  1705.             pMessage = PR_sprintf_append( pMessage, "Paste text as a new table?");
  1706.             if( FE_Confirm(pEditBuffer->GetContext(), pMessage) )
  1707.             {
  1708.                 pEditBuffer->PasteTextAsNewTable(pText, iRows, iCols);
  1709.                 bPasteAsTable = TRUE;
  1710.             }
  1711.         }
  1712.         XP_FREEIF(pMessage);
  1713.     }
  1714.     else 
  1715.     {
  1716.         // No selected table cells Delete any existing selection so paste replaces it
  1717.         pEditBuffer->DeleteSelection();
  1718.     }
  1719.  
  1720.     // If we didn't do any special table pasting, do regular paste at caret location
  1721.     if( !bPasteAsTable )
  1722.         result = pEditBuffer->PasteText( pText, FALSE, FALSE, TRUE ,TRUE);
  1723.     pEditBuffer->EndBatchChanges();
  1724.     return result;
  1725. }
  1726.  
  1727. EDT_ClipboardResult EDT_PasteQuoteBegin( MWContext *pContext, XP_Bool bHTML ) {
  1728.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) EDT_COP_DOCUMENT_BUSY;
  1729.     EDT_ClipboardResult result = pEditBuffer->PasteQuoteBegin( bHTML );
  1730.     return result;
  1731. }
  1732.  
  1733. EDT_ClipboardResult EDT_PasteQuote( MWContext *pContext, char *pText ) {
  1734.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) EDT_COP_DOCUMENT_BUSY;
  1735.     EDT_ClipboardResult result = pEditBuffer->PasteQuote( pText );
  1736.     return result;
  1737. }
  1738.  
  1739. EDT_ClipboardResult EDT_PasteQuoteINTL( MWContext *pContext, char *pText, int16 csid ) {
  1740.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) EDT_COP_DOCUMENT_BUSY;
  1741.     EDT_ClipboardResult result = pEditBuffer->PasteQuoteINTL( pText, csid );
  1742.     return result;
  1743. }
  1744.  
  1745. EDT_ClipboardResult EDT_PasteQuoteEnd( MWContext *pContext ) {
  1746.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) EDT_COP_DOCUMENT_BUSY;
  1747.     EDT_ClipboardResult result = pEditBuffer->PasteQuoteEnd();
  1748.     return result;
  1749. }
  1750.  
  1751. EDT_ClipboardResult EDT_PasteHTML( MWContext *pContext, char *pText ){
  1752.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) EDT_COP_DOCUMENT_BUSY;
  1753.     pEditBuffer->BeginBatchChanges(kPasteHTMLCommandID);
  1754.     pEditBuffer->DeleteSelection();
  1755.     EDT_ClipboardResult result = pEditBuffer->PasteHTML( pText, FALSE );
  1756.     pEditBuffer->EndBatchChanges();
  1757.     return result;
  1758. }
  1759.  
  1760. EDT_ClipboardResult EDT_CopySelection( MWContext *pContext, char **ppText, int32* pTextLen,
  1761.             XP_HUGE_CHAR_PTR* ppHtml, int32* pHtmlLen){
  1762.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) EDT_COP_DOCUMENT_BUSY;
  1763.     return pEditBuffer->CopySelection( ppText, pTextLen, (char **)ppHtml, pHtmlLen );
  1764. }
  1765.  
  1766. EDT_ClipboardResult EDT_CutSelection( MWContext *pContext, char **ppText, int32* pTextLen,
  1767.             XP_HUGE_CHAR_PTR* ppHtml, int32* pHtmlLen){
  1768.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) EDT_COP_DOCUMENT_BUSY;
  1769.     EDT_ClipboardResult result = pEditBuffer->CutSelection( ppText, pTextLen, (char **)ppHtml, pHtmlLen );
  1770.     return result;
  1771. }
  1772.  
  1773. char *EDT_GetTabDelimitedTextFromSelectedCells( MWContext *pContext )
  1774. {
  1775.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) NULL;
  1776.     return pEditBuffer->GetTabDelimitedTextFromSelectedCells();
  1777. }
  1778.  
  1779.  
  1780. /* Convert Selected text into a table (put each paragraph in separate cell)
  1781.  * Number of rows is automatic - creates as many as needed
  1782. */
  1783. void EDT_ConvertTextToTable(MWContext *pMWContext, intn iColumns)
  1784. {
  1785.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pMWContext, pEditBuffer);
  1786.     pEditBuffer->ConvertTextToTable(iColumns);
  1787. }
  1788.  
  1789. /* Convert the table into text - unravel existing paragraphs in cells */
  1790. void EDT_ConvertTableToText(MWContext *pMWContext)
  1791. {
  1792.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pMWContext, pEditBuffer);
  1793.     pEditBuffer->ConvertTableToText();
  1794. }
  1795.  
  1796. /* Save the character and paragraph style of selection or at caret */
  1797. void EDT_CopyStyle(MWContext *pMWContext)
  1798. {
  1799.     GET_EDIT_BUF_OR_RETURN(pMWContext, pEditBuffer);
  1800.     pEditBuffer->CopyStyle();
  1801. }
  1802.  
  1803. /* TRUE if no mouse actions taken since last EDT_CopyStyle call */
  1804. XP_Bool EDT_CanPasteStyle(MWContext *pMWContext)
  1805. {
  1806.     GET_EDIT_BUF_OR_RETURN(pMWContext, pEditBuffer) FALSE;
  1807.     return pEditBuffer->CanPasteStyle();
  1808. }
  1809.  
  1810. /* Apply the style to selection or at caret */
  1811. void EDT_PasteStyle(MWContext *pMWContext, XP_Bool bApplyStyle)
  1812. {
  1813.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pMWContext, pEditBuffer);
  1814.     pEditBuffer->PasteStyle(bApplyStyle);
  1815. }
  1816.  
  1817.  
  1818. XP_Bool EDT_DirtyFlag( MWContext *pContext ){
  1819.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) FALSE;
  1820.     return pEditBuffer->GetDirtyFlag();
  1821. }
  1822.  
  1823. void EDT_SetDirtyFlag( MWContext *pContext, XP_Bool bValue ){
  1824.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1825.     if ( bValue ) {
  1826.         XP_ASSERT(FALSE); // Use BeginBatchChanges instead.
  1827.     }
  1828.     else {
  1829.         pEditBuffer->DocumentStored();
  1830.     }
  1831. }
  1832.  
  1833. EDT_ClipboardResult EDT_CanCut(MWContext *pContext, XP_Bool bStrictChecking){
  1834.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) EDT_COP_DOCUMENT_BUSY;
  1835.     return pEditBuffer->CanCut( bStrictChecking );
  1836. }
  1837.  
  1838. EDT_ClipboardResult EDT_CanCopy(MWContext *pContext, XP_Bool bStrictChecking){
  1839.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) EDT_COP_DOCUMENT_BUSY;
  1840.     return pEditBuffer->CanCopy( bStrictChecking );
  1841. }
  1842.  
  1843. EDT_ClipboardResult EDT_CanPaste(MWContext *pContext, XP_Bool bStrictChecking){
  1844.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) EDT_COP_DOCUMENT_BUSY;
  1845.     return pEditBuffer->CanPaste( bStrictChecking );
  1846. }
  1847.  
  1848. XP_Bool EDT_CanSetHREF( MWContext *pContext ){
  1849.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) FALSE;
  1850.     return pEditBuffer->CanSetHREF( );
  1851. }
  1852.  
  1853. char *EDT_GetHREF( MWContext *pContext ){
  1854.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) NULL;
  1855.     return pEditBuffer->GetHREF( );
  1856. }
  1857.  
  1858. char *EDT_GetHREFText(MWContext *pContext){
  1859.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) NULL;
  1860.     return pEditBuffer->GetHREFText();
  1861. }
  1862.  
  1863. void EDT_SetHREF(MWContext *pContext, char *pHREF ){
  1864.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1865.     pEditBuffer->SetHREF( pHREF, 0 );
  1866. }
  1867.  
  1868. /*
  1869.  * Returns colors of all the different fonts.
  1870.  * Must call XP_FREE( pDest ) after use.
  1871. */
  1872. int EDT_GetExtraColors( MWContext * /* pContext */, LO_Color ** /* pDest */ ){
  1873.     return 0;
  1874. }
  1875.  
  1876. void EDT_RefreshLayout( MWContext *pContext ){
  1877.     LO_RefetchWindowDimensions( pContext );
  1878.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1879.     pEditBuffer->RefreshLayout();
  1880. }
  1881.  
  1882. XP_Bool EDT_IsSelected( MWContext *pContext ){
  1883.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) FALSE;
  1884.     return pEditBuffer->IsSelected();
  1885. }
  1886.  
  1887. //  Check current file-update time and
  1888. //  return TRUE if it is different
  1889. XP_Bool EDT_IsFileModified( MWContext* pContext ){
  1890.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) FALSE;
  1891.     return pEditBuffer->IsFileModified();
  1892. }
  1893.  
  1894. //   This should probably be moved into CEditBuffer,
  1895. //     Note that we return FALSE if we are text type
  1896. //     and not selected, even if caret is in a link,
  1897. //     so don't use this to test for link.
  1898. // TODO: Move this into CEditBuffer::SelectionContainsLink()
  1899. //       after CharacterData functions are implemented
  1900. XP_Bool EDT_SelectionContainsLink( MWContext *pContext ){
  1901.     if( EDT_IsSelected(pContext) ||
  1902.         EDT_GetSelectedTableElement(pContext, NULL) )
  1903.     {
  1904.         ED_ElementType type = EDT_GetCurrentElementType(pContext);
  1905.         // If we have a Table selected, then we ignore character actions,
  1906.         //  but we do look into Table Rows, columns, and cells
  1907.         if( type == ED_ELEMENT_SELECTION || type > ED_ELEMENT_TABLE)
  1908.         {
  1909.             EDT_CharacterData *pData = EDT_GetCharacterData(pContext);
  1910.             if( pData )
  1911.             {
  1912.                 // We aren't certain about HREF state accross
  1913.                 //  entire selection if mask bit is off
  1914.                 XP_Bool bUncertain = ( (pData->mask & TF_HREF) == 0 ||
  1915.                                     ((pData->mask & TF_HREF) &&
  1916.                                      (pData->values & TF_HREF)) );
  1917.                 EDT_FreeCharacterData(pData);
  1918.                 return bUncertain;
  1919.             }
  1920.         }
  1921.         else if ( type == ED_ELEMENT_IMAGE )
  1922.         {
  1923.             LO_Element *pStart;
  1924.             //
  1925.             // Grab the current selection.
  1926.             //
  1927.             LO_GetSelectionEndPoints( pContext, &pStart, 0, 0, 0, 0, 0 );
  1928.             // Check if image has an HREF
  1929.             return (pStart && pStart->lo_image.anchor_href != NULL );
  1930.         }
  1931.     }
  1932.     return FALSE;
  1933. }
  1934.  
  1935. void EDT_DropHREF( MWContext *pContext, char *pHref, char* pTitle, int32 x,
  1936.             int32 y ){
  1937.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1938.     EDT_BeginBatchChanges(pContext);
  1939.     EDT_PositionCaret( pContext, x, y );
  1940.     EDT_PasteText( pContext, pHref );
  1941.     EDT_PasteText( pContext, pTitle );
  1942.     EDT_EndBatchChanges(pContext);
  1943. }
  1944.  
  1945. EDT_ClipboardResult EDT_PasteHREF( MWContext *pContext, char **ppHref, char **ppTitle, int iCount){
  1946.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) EDT_COP_DOCUMENT_BUSY;
  1947.     EDT_ClipboardResult result = EDT_COP_DOCUMENT_BUSY;
  1948.     pEditBuffer->BeginBatchChanges(kPasteHREFCommandID);
  1949.     pEditBuffer->DeleteSelection();
  1950.     result = pEditBuffer->PasteHREF( ppHref, ppTitle, iCount );
  1951.     pEditBuffer->EndBatchChanges();
  1952.     return result;
  1953. }
  1954.  
  1955. XP_Bool EDT_CanDropHREF( MWContext * pContext, int32 /* x */, int32 /* y */){
  1956.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) FALSE;
  1957.     return TRUE;
  1958. }
  1959.  
  1960. EDT_HREFData *EDT_GetHREFData( MWContext *pContext ){
  1961.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) 0;
  1962.     EDT_HREFData* pData = EDT_NewHREFData();
  1963.     if(pData){
  1964.         pEditBuffer->GetHREFData(pData);
  1965.     }
  1966.     return pData;
  1967. }
  1968.  
  1969. void EDT_SetHREFData( MWContext *pContext, EDT_HREFData *pData ){
  1970.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  1971.     /* Allow clearing existing HREF with NULL pURL */
  1972.     if(pData /*&& pData->pURL*/){
  1973.         pEditBuffer->SetHREFData(pData);
  1974.     }
  1975. }
  1976.  
  1977. EDT_HREFData *EDT_NewHREFData() {
  1978.     EDT_HREFData* pData = XP_NEW( EDT_HREFData );
  1979.     if( pData ){
  1980.         XP_BZERO( pData, sizeof( EDT_HREFData ) );
  1981.         return pData;
  1982.     }
  1983.     return NULL;
  1984. }
  1985.  
  1986. EDT_HREFData *EDT_DupHREFData( EDT_HREFData *pOldData) {
  1987.     EDT_HREFData* pData = EDT_NewHREFData();
  1988.     if( pOldData ){
  1989.         if(pOldData->pURL) pData->pURL = XP_STRDUP( pOldData->pURL );
  1990.         if(pOldData->pExtra) pData->pExtra = XP_STRDUP( pOldData->pExtra );
  1991.     }
  1992.     return pData;
  1993. }
  1994.  
  1995.  
  1996. void EDT_FreeHREFData(  EDT_HREFData *pData ) {
  1997.     //Move this to an EditBuffer function?
  1998.     if(pData){
  1999.         if(pData->pURL) XP_FREE(pData->pURL);
  2000.         if(pData->pExtra) XP_FREE(pData->pExtra);
  2001.         XP_FREE(pData);
  2002.     }
  2003. }
  2004.  
  2005. void EDT_FinishedLayout( MWContext *pContext ){
  2006.     /* we know that the buffer is not ready */
  2007.     /* we're actually not "ready" here because FinishedLoad will call */
  2008.     /* the timer which will ensure that FinishedLoad2 gets called which */
  2009.     /* completes the initialization of pEditBuffer */
  2010.     GET_EDIT_BUF_OR_RETURN_READY_OR_NOT(pContext, pEditBuffer);
  2011.     pEditBuffer->FinishedLoad();
  2012. }
  2013.  
  2014. // Page
  2015.  
  2016. EDT_PageData *EDT_GetPageData( MWContext *pContext ){
  2017.     GET_EDIT_BUF_OR_RETURN_READY_OR_NOT(pContext, pEditBuffer) NULL;
  2018.     return pEditBuffer->GetPageData();
  2019. }
  2020.  
  2021. EDT_PageData *EDT_NewPageData(){
  2022.     EDT_PageData* pData = XP_NEW( EDT_PageData );
  2023.     if( pData ){
  2024.         XP_BZERO( pData, sizeof( EDT_PageData ) );
  2025.         pData->bKeepImagesWithDoc = TRUE;
  2026.         return pData;
  2027.     }
  2028.     return NULL;
  2029. }
  2030.  
  2031. void EDT_SetPageData( MWContext *pContext, EDT_PageData *pData ){
  2032.     GET_WRITABLE_EDIT_BUF_OR_RETURN_READY_OR_NOT(pContext, pEditBuffer);
  2033.     pEditBuffer->AdoptAndDo(new CChangePageDataCommand(pEditBuffer, kChangePageDataCommandID));
  2034.     pEditBuffer->SetPageData( pData );
  2035. }
  2036.  
  2037. void EDT_FreePageData( EDT_PageData *pData ){
  2038.     CEditBuffer::FreePageData( pData );
  2039. }
  2040.  
  2041. void EDT_SetImageAsBackground( MWContext *pContext ){
  2042.     GET_WRITABLE_EDIT_BUF_OR_RETURN_READY_OR_NOT(pContext, pEditBuffer);
  2043.     pEditBuffer->SetImageAsBackground();
  2044. }
  2045.  
  2046. // Meta
  2047.  
  2048. intn EDT_MetaDataCount( MWContext *pContext ){
  2049.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) 0;
  2050.     return pEditBuffer->MetaDataCount();
  2051. }
  2052.  
  2053. EDT_MetaData* EDT_GetMetaData( MWContext *pContext, intn n ){
  2054.     GET_EDIT_BUF_OR_RETURN_READY_OR_NOT(pContext, pEditBuffer) NULL;
  2055.     return pEditBuffer->GetMetaData( n );
  2056. }
  2057.  
  2058. EDT_MetaData* EDT_NewMetaData(){
  2059.     EDT_MetaData *pData = XP_NEW( EDT_MetaData );
  2060.     if( pData ){
  2061.         XP_BZERO( pData, sizeof( EDT_MetaData ) );
  2062.         return pData;
  2063.     }
  2064.     return NULL;
  2065. }
  2066.  
  2067. void EDT_SetMetaData( MWContext *pContext, EDT_MetaData *pMetaData ){
  2068.     GET_WRITABLE_EDIT_BUF_OR_RETURN_READY_OR_NOT(pContext, pEditBuffer);
  2069.     // CSetMetaDataCommand actually performs the operation in the
  2070.     // constructor of the command. So in order for save-based undo to
  2071.     // work, we must wrap its constructor in BeginBatchChanges.
  2072.     pEditBuffer->BeginBatchChanges(kSetMetaDataCommandID);
  2073.     pEditBuffer->AdoptAndDo(new CSetMetaDataCommand(pEditBuffer, pMetaData, FALSE, kSetMetaDataCommandID));
  2074.     pEditBuffer->EndBatchChanges();
  2075. }
  2076.  
  2077. void EDT_DeleteMetaData( MWContext *pContext, EDT_MetaData *pMetaData ){
  2078.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2079.     // CSetMetaDataCommand actually performs the operation in the
  2080.     // constructor of the command. So in order for save-based undo to
  2081.     // work, we must wrap its constructor in BeginBatchChanges.
  2082.     pEditBuffer->BeginBatchChanges(kDeleteMetaDataCommandID);
  2083.     pEditBuffer->AdoptAndDo(new CSetMetaDataCommand(pEditBuffer, pMetaData, TRUE, kDeleteMetaDataCommandID));
  2084.     pEditBuffer->EndBatchChanges();
  2085. }
  2086.  
  2087. void EDT_FreeMetaData( EDT_MetaData *pMetaData ){
  2088.     CEditBuffer::FreeMetaData( pMetaData );
  2089. }
  2090.  
  2091. // Image
  2092.  
  2093. EDT_ImageData *EDT_GetImageData( MWContext *pContext ){
  2094.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) NULL;
  2095.     return pEditBuffer->GetImageData();
  2096. }
  2097.  
  2098. int32 EDT_GetDefaultBorderWidth( MWContext *pContext ){
  2099.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) NULL;
  2100.     return pEditBuffer->GetDefaultBorderWidth();
  2101. }
  2102.  
  2103. void EDT_SetImageData( MWContext *pContext, EDT_ImageData *pData, XP_Bool bKeepImagesWithDoc ){
  2104.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2105.     pEditBuffer->BeginBatchChanges(kSetImageDataCommandID);
  2106.     pEditBuffer->SetImageData( pData, bKeepImagesWithDoc );
  2107.     pEditBuffer->EndBatchChanges();
  2108. }
  2109.  
  2110.  
  2111. EDT_ImageData *EDT_NewImageData(){
  2112.     return edt_NewImageData( );
  2113. }
  2114.  
  2115. void EDT_FreeImageData( EDT_ImageData *pData ){
  2116.     edt_FreeImageData( pData );
  2117. }
  2118.  
  2119. void EDT_InsertImage( MWContext *pContext, EDT_ImageData *pData, XP_Bool bKeepImagesWithDoc ){
  2120.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2121.     pEditBuffer->BeginBatchChanges(kInsertImageCommandID);
  2122.     pEditBuffer->LoadImage( pData, bKeepImagesWithDoc, FALSE );
  2123.     pEditBuffer->EndBatchChanges();
  2124. }
  2125.  
  2126. void EDT_ImageLoadCancel( MWContext *pContext ){
  2127.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2128.     if( pEditBuffer->m_pLoadingImage ){
  2129.         delete pEditBuffer->m_pLoadingImage;
  2130.     }
  2131. }
  2132.  
  2133. void EDT_SetImageInfo(MWContext *pContext, int32 ele_id, int32 width, int32 height){
  2134.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2135.     if( pEditBuffer->m_pLoadingImage ){
  2136.         pEditBuffer->m_pLoadingImage->SetImageInfo( ele_id, width, height );
  2137.     }
  2138. }
  2139.  
  2140. // HorizRule
  2141.  
  2142. EDT_HorizRuleData *EDT_GetHorizRuleData( MWContext *pContext ){
  2143.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) NULL;
  2144.     return pEditBuffer->GetHorizRuleData();
  2145. }
  2146.  
  2147. void EDT_SetHorizRuleData( MWContext *pContext, EDT_HorizRuleData *pData ){
  2148.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2149.     pEditBuffer->BeginBatchChanges(kSetHorizRuleDataCommandID);
  2150.     pEditBuffer->SetHorizRuleData( pData );
  2151.     pEditBuffer->EndBatchChanges();
  2152. }
  2153.  
  2154. EDT_HorizRuleData* EDT_NewHorizRuleData(){
  2155.     return CEditHorizRuleElement::NewData( );
  2156. }
  2157.  
  2158. void EDT_FreeHorizRuleData( EDT_HorizRuleData *pData ){
  2159.     CEditHorizRuleElement::FreeData( pData );
  2160. }
  2161.  
  2162. void EDT_InsertHorizRule( MWContext *pContext, EDT_HorizRuleData *pData ){
  2163.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2164.     pEditBuffer->InsertHorizRule( pData );
  2165. }
  2166.  
  2167. // Targets
  2168. char *EDT_GetTargetData( MWContext *pContext ){
  2169.    GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) NULL;
  2170.    return pEditBuffer->GetTargetData();
  2171. }
  2172.  
  2173. void EDT_SetTargetData( MWContext *pContext, char *pData ){
  2174.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2175.     pEditBuffer->BeginBatchChanges(kSetTargetDataCommandID);
  2176.     pEditBuffer->SetTargetData( pData );
  2177.     pEditBuffer->EndBatchChanges();
  2178. }
  2179.  
  2180. void EDT_InsertTarget( MWContext *pContext, char* pData ){
  2181.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2182.     pEditBuffer->BeginBatchChanges(kInsertTargetCommandID);
  2183.     pEditBuffer->InsertTarget( pData );
  2184.     pEditBuffer->EndBatchChanges();
  2185. }
  2186.  
  2187. char *EDT_GetAllDocumentTargets( MWContext *pContext ){
  2188.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) NULL;
  2189.     return pEditBuffer->GetAllDocumentTargets();
  2190. }
  2191.  
  2192. char *EDT_GetAllDocumentTargetsInFile( MWContext *pContext, char *pHref ){
  2193.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) NULL;
  2194.     return pEditBuffer->GetAllDocumentTargetsInFile(pHref);
  2195. }
  2196.  
  2197. // For backwards compatibility with non-Windows Front Ends.
  2198. char *EDT_GetAllDocumentFiles( MWContext *pContext ){
  2199.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) NULL;
  2200.     return pEditBuffer->GetAllDocumentFiles(NULL,TRUE);
  2201. }
  2202. // New version.
  2203. char *EDT_GetAllDocumentFilesSelected( MWContext *pContext, XP_Bool **ppSelected, 
  2204.                                         XP_Bool bKeepImages ){
  2205.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) NULL;
  2206.     return pEditBuffer->GetAllDocumentFiles(ppSelected,bKeepImages);
  2207. }
  2208.  
  2209.  
  2210. // Unknown Tags
  2211. char *EDT_GetUnknownTagData( MWContext *pContext ){
  2212.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) NULL;
  2213.     return pEditBuffer->GetUnknownTagData();
  2214. }
  2215.  
  2216. void EDT_SetUnknownTagData( MWContext *pContext, char *pData ){
  2217.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2218.     pEditBuffer->BeginBatchChanges(kSetUnknownTagDataCommandID);
  2219.     pEditBuffer->SetUnknownTagData( pData );
  2220.     pEditBuffer->EndBatchChanges();
  2221. }
  2222.  
  2223. void EDT_InsertUnknownTag( MWContext *pContext, char* pData ){
  2224.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2225.     pEditBuffer->BeginBatchChanges(kInsertUnknownTagCommandID);
  2226.     pEditBuffer->InsertUnknownTag( pData );
  2227.     pEditBuffer->EndBatchChanges();
  2228. }
  2229.  
  2230. ED_TagValidateResult EDT_ValidateTag( char *pData, XP_Bool bNoBrackets ){
  2231.     return CEditIconElement::ValidateTag( pData, bNoBrackets );
  2232. }
  2233.  
  2234. // List
  2235.  
  2236. EDT_ListData *EDT_GetListData( MWContext *pContext ){
  2237.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) NULL;
  2238.     return pEditBuffer->GetListData();
  2239. }
  2240.  
  2241. void EDT_SetListData( MWContext *pContext, EDT_ListData *pData ){
  2242.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2243.     CSetListDataCommand* pCommand = new CSetListDataCommand(pEditBuffer, *pData);
  2244.     pEditBuffer->AdoptAndDo(pCommand);
  2245. }
  2246.  
  2247. void EDT_FreeListData( EDT_ListData *pData ){
  2248.     CEditListElement::FreeData( pData );
  2249. }
  2250.  
  2251. // Break
  2252.  
  2253. void EDT_InsertBreak( MWContext *pContext, ED_BreakType eBreak ){
  2254.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2255.     // A break is treated like a character as far as the typing command goes.
  2256.     // So we don't do a command at this level.
  2257.     pEditBuffer->InsertBreak( eBreak );
  2258. }
  2259.  
  2260. // Tables
  2261.  
  2262. XP_Bool EDT_IsInsertPointInTable(MWContext *pContext ){
  2263.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) FALSE;
  2264.     return pEditBuffer->IsInsertPointInTable();
  2265. }
  2266.  
  2267. XP_Bool EDT_IsInsertPointInNestedTable(MWContext *pContext ){
  2268.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) FALSE;
  2269.     return pEditBuffer->IsInsertPointInNestedTable();
  2270. }
  2271.  
  2272. EDT_TableData* EDT_GetTableData( MWContext *pContext ){
  2273.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) NULL;
  2274.     return pEditBuffer->GetTableData();
  2275. }
  2276.  
  2277. void EDT_GetTableParentSize( MWContext *pContext, XP_Bool bCell, int32 *pWidth, int32 *pHeight )
  2278. {
  2279.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2280.     CEditInsertPoint ip;
  2281.     pEditBuffer->GetInsertPoint(ip);
  2282.     CEditTableElement* pTable = ip.m_pElement->GetTableIgnoreSubdoc();
  2283.     if ( pTable )
  2284.     {
  2285.          if( bCell )
  2286.          {
  2287.              CEditTableCellElement* pCell = ip.m_pElement->GetTableCellIgnoreSubdoc();
  2288.              if( pCell )
  2289.              {
  2290.                 if( pWidth )
  2291.                     *pWidth = pCell->GetParentWidth();
  2292.                 if( pHeight )
  2293.                     *pHeight = pCell->GetParentHeight();
  2294.             }
  2295.          } else {
  2296.             pTable->GetParentSize(pEditBuffer->GetContext(), pWidth, pHeight, NULL);
  2297.         }
  2298.     }
  2299. }
  2300.  
  2301. void EDT_SetTableData( MWContext *pContext, EDT_TableData *pData )
  2302. {
  2303.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2304.  
  2305.     // jhp: We have to do this here, outside of the command.
  2306.     //CLM: Experimental kludge: allow changing row/columns by
  2307.     //      deleting old table and inserting a new one
  2308.     CEditInsertPoint ip;
  2309.     pEditBuffer->GetInsertPoint(ip);
  2310.     CEditTableElement* pTable = ip.m_pElement->GetTableIgnoreSubdoc();
  2311.     if ( pTable )
  2312.     {
  2313.         pEditBuffer->BeginBatchChanges(kSetTableDataCommandID);
  2314.         EDT_TableData* pOldData = pTable->GetData();
  2315.         if ( pOldData && (pOldData->iRows != pData->iRows ||
  2316.                           pOldData->iColumns != pData->iColumns) )
  2317.         {
  2318.             pEditBuffer->SetTableData(pData);
  2319.  
  2320. //            pEditBuffer->AdoptAndDo(new CDeleteTableCommand(pEditBuffer));
  2321.             // Get rid of extra carriage return before old table.
  2322.             EDT_DeletePreviousChar(pContext);
  2323.             EDT_InsertTable(pContext, pData);
  2324.         } else {
  2325.             pEditBuffer->SetTableData(pData);
  2326.  
  2327. //            CSetTableDataCommand* pCommand = new CSetTableDataCommand(pEditBuffer, pData);
  2328. //            pEditBuffer->AdoptAndDo(pCommand);
  2329.         }
  2330.         if( pOldData )
  2331.         {
  2332.             CEditTableElement::FreeData(pOldData);
  2333.         }
  2334.         pEditBuffer->EndBatchChanges();
  2335.     }
  2336. }
  2337.  
  2338. EDT_TableData* EDT_NewTableData() {
  2339.     return CEditTableElement::NewData();
  2340. }
  2341.  
  2342. void EDT_FreeTableData(  EDT_TableData *pData ) {
  2343.     CEditTableElement::FreeData( pData );
  2344. }
  2345.  
  2346. void EDT_InsertTable( MWContext *pContext, EDT_TableData *pData){
  2347.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2348.     pEditBuffer->InsertTable( pData );
  2349. }
  2350.  
  2351. void EDT_DeleteTable( MWContext *pContext ){
  2352.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2353.     pEditBuffer->DeleteTable();
  2354. }
  2355.  
  2356. ED_MergeType EDT_GetMergeTableCellsType( MWContext *pContext )
  2357. {
  2358.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) ED_MERGE_NONE;
  2359.     return pEditBuffer->GetMergeTableCellsType();
  2360. }
  2361.  
  2362. XP_Bool EDT_CanSplitTableCell( MWContext *pContext )
  2363. {
  2364.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) FALSE;
  2365.     return pEditBuffer->CanSplitTableCell();
  2366. }
  2367.  
  2368. void EDT_MergeTableCells( MWContext *pContext )
  2369. {
  2370.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2371.     pEditBuffer->MergeTableCells();
  2372. }
  2373.  
  2374. void EDT_SplitTableCell( MWContext *pContext )
  2375. {
  2376.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2377.     pEditBuffer->SplitTableCell();
  2378. }
  2379.  
  2380. // Table Caption
  2381.  
  2382. XP_Bool EDT_IsInsertPointInTableCaption(MWContext *pContext ){
  2383.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) FALSE;
  2384.     return pEditBuffer->IsInsertPointInTableCaption();
  2385. }
  2386.  
  2387. EDT_TableCaptionData* EDT_GetTableCaptionData( MWContext *pContext ){
  2388.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) NULL;
  2389.     return pEditBuffer->GetTableCaptionData();
  2390. }
  2391.  
  2392. void EDT_SetTableCaptionData( MWContext *pContext, EDT_TableCaptionData *pData ){
  2393.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2394.     // CSetTableCaptionDataCommand actually performs the operation in the
  2395.     // constructor of the command. So in order for save-based undo to
  2396.     // work, we must wrap its constructor in BeginBatchChanges.
  2397.     pEditBuffer->BeginBatchChanges(kSetTableCaptionDataCommandID);
  2398.     CSetTableCaptionDataCommand* pCommand = new CSetTableCaptionDataCommand(pEditBuffer, pData);
  2399.     pEditBuffer->AdoptAndDo(pCommand);
  2400.     pEditBuffer->EndBatchChanges();
  2401. }
  2402.  
  2403. EDT_TableCaptionData* EDT_NewTableCaptionData() {
  2404.     return CEditCaptionElement::NewData();
  2405. }
  2406.  
  2407. void EDT_FreeTableCaptionData(  EDT_TableCaptionData *pData ) {
  2408.     CEditCaptionElement::FreeData( pData );
  2409. }
  2410.  
  2411. void EDT_InsertTableCaption( MWContext *pContext, EDT_TableCaptionData *pData){
  2412.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2413.     pEditBuffer->InsertTableCaption( pData );
  2414. }
  2415.  
  2416. void EDT_DeleteTableCaption( MWContext *pContext){
  2417.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2418.     pEditBuffer->DeleteTableCaption();
  2419. }
  2420.  
  2421. // Table Row
  2422.  
  2423. XP_Bool EDT_IsInsertPointInTableRow(MWContext *pContext ){
  2424.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) FALSE;
  2425.     return pEditBuffer->IsInsertPointInTableRow();
  2426. }
  2427.  
  2428. EDT_TableRowData* EDT_GetTableRowData( MWContext *pContext ){
  2429.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) NULL;
  2430.     return pEditBuffer->GetTableRowData();
  2431. }
  2432.  
  2433. void EDT_SetTableRowData( MWContext *pContext, EDT_TableRowData *pData ){
  2434.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2435.     // CSetTableRowDataCommand actually performs the operation in the
  2436.     // constructor of the command. So in order for save-based undo to
  2437.     // work, we must wrap its constructor in BeginBatchChanges.
  2438.     pEditBuffer->BeginBatchChanges(kSetTableRowDataCommandID);
  2439.     CSetTableRowDataCommand* pCommand = new CSetTableRowDataCommand(pEditBuffer, pData);
  2440.     pEditBuffer->AdoptAndDo(pCommand);
  2441.     pEditBuffer->EndBatchChanges();
  2442. }
  2443.  
  2444. EDT_TableRowData* EDT_NewTableRowData() {
  2445.     return CEditTableRowElement::NewData();
  2446. }
  2447.  
  2448. void EDT_FreeTableRowData(  EDT_TableRowData *pData ) {
  2449.     CEditTableRowElement::FreeData( pData );
  2450. }
  2451.  
  2452. void EDT_InsertTableRows( MWContext *pContext, EDT_TableRowData *pData, XP_Bool bAfterCurrentRow, intn number){
  2453.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2454.     pEditBuffer->InsertTableRows( pData, bAfterCurrentRow, number );
  2455. }
  2456.  
  2457. void EDT_DeleteTableRows( MWContext *pContext, intn number){
  2458.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2459.     pEditBuffer->DeleteTableRows(number);
  2460. }
  2461.  
  2462. // Table Cell
  2463.  
  2464. XP_Bool EDT_IsInsertPointInTableCell(MWContext *pContext ){
  2465.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) FALSE;
  2466.     return pEditBuffer->IsInsertPointInTableCell();
  2467. }
  2468.  
  2469. EDT_TableCellData* EDT_GetTableCellData( MWContext *pContext ){
  2470.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) NULL;
  2471.     return pEditBuffer->GetTableCellData();
  2472. }
  2473.  
  2474. void EDT_ChangeTableSelection(MWContext *pContext, ED_HitType iHitType, ED_MoveSelType iMoveType, 
  2475.                               EDT_TableCellData *pData) {
  2476.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2477.     pEditBuffer->ChangeTableSelection(iHitType, iMoveType, pData);
  2478. }
  2479.  
  2480. void EDT_SetTableCellData( MWContext *pContext, EDT_TableCellData *pData ){
  2481.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2482.     // CSetTableCellDataCommand actually performs the operation in the
  2483.     // constructor of the command. So in order for save-based undo to
  2484.     // work, we must wrap its constructor in BeginBatchChanges.
  2485.     pEditBuffer->BeginBatchChanges(kSetTableCellDataCommandID);
  2486.     pEditBuffer->SetTableCellData(pData);
  2487. //    CSetTableCellDataCommand* pCommand = new CSetTableCellDataCommand(pEditBuffer, pData);
  2488. //    pEditBuffer->AdoptAndDo(pCommand);
  2489.     pEditBuffer->EndBatchChanges();
  2490. }
  2491.  
  2492. EDT_TableCellData* EDT_NewTableCellData() {
  2493.     return CEditTableCellElement::NewData();
  2494. }
  2495.  
  2496. void EDT_FreeTableCellData(  EDT_TableCellData *pData ) {
  2497.     CEditTableCellElement::FreeData( pData );
  2498. }
  2499.  
  2500. void EDT_InsertTableCells( MWContext *pContext, EDT_TableCellData *pData, XP_Bool bAfterCurrentColumn, intn number){
  2501.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2502.     pEditBuffer->InsertTableCells( pData, bAfterCurrentColumn, number );
  2503. }
  2504.  
  2505. void EDT_DeleteTableCells( MWContext *pContext, intn number){
  2506.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2507.     pEditBuffer->DeleteTableCells(number);
  2508. }
  2509.  
  2510. void EDT_InsertTableColumns( MWContext *pContext, EDT_TableCellData *pData, XP_Bool bAfterCurrentColumn, intn number){
  2511.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2512.     pEditBuffer->InsertTableColumns( pData, bAfterCurrentColumn, number );
  2513. }
  2514.  
  2515. void EDT_DeleteTableColumns( MWContext *pContext, intn number){
  2516.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2517.     pEditBuffer->DeleteTableColumns(number);
  2518. }
  2519.  
  2520. // Layer
  2521.  
  2522. XP_Bool EDT_IsInsertPointInLayer(MWContext *pContext ){
  2523.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) FALSE;
  2524.     return pEditBuffer->IsInsertPointInLayer();
  2525. }
  2526.  
  2527. EDT_LayerData* EDT_GetLayerData( MWContext *pContext ){
  2528.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) NULL;
  2529.     return pEditBuffer->GetLayerData();
  2530. }
  2531.  
  2532. void EDT_SetLayerData( MWContext *pContext, EDT_LayerData *pData ){
  2533.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2534.     CEditInsertPoint ip;
  2535.     pEditBuffer->GetInsertPoint(ip);
  2536.     CEditLayerElement* pLayer = ip.m_pElement->GetLayerIgnoreSubdoc();
  2537.     if ( pLayer ){
  2538.         pEditBuffer->BeginBatchChanges(kSetLayerDataCommandID);
  2539.         pLayer->SetData(pData);
  2540.         pEditBuffer->EndBatchChanges();
  2541.     }
  2542. }
  2543.  
  2544. EDT_LayerData* EDT_NewLayerData() {
  2545.     return CEditLayerElement::NewData();
  2546. }
  2547.  
  2548. void EDT_FreeLayerData(  EDT_LayerData *pData ) {
  2549.     CEditLayerElement::FreeData( pData );
  2550. }
  2551.  
  2552. void EDT_InsertLayer( MWContext *pContext, EDT_LayerData *pData){
  2553.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2554.     pEditBuffer->InsertLayer( pData );
  2555. }
  2556.  
  2557. void EDT_DeleteLayer( MWContext *pContext ){
  2558.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2559.     pEditBuffer->DeleteLayer();
  2560. }
  2561.  
  2562. // Undo/Redo
  2563.  
  2564. void EDT_Undo( MWContext *pContext ){
  2565.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2566.     pEditBuffer->Undo( );
  2567. }
  2568.  
  2569. void EDT_Redo( MWContext *pContext ){
  2570.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2571.     pEditBuffer->Redo( );
  2572. }
  2573. #if 0
  2574. PRIVATE
  2575. intn EDT_GetCommandHistoryLimit(MWContext *pContext){
  2576.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) 0;
  2577.     return pEditBuffer->GetCommandHistoryLimit( );
  2578. }
  2579.  
  2580. PRIVATE
  2581. void EDT_SetCommandHistoryLimit(MWContext *pContext, intn newLimit){
  2582.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2583.     pEditBuffer->SetCommandHistoryLimit( newLimit );
  2584. }
  2585. #endif
  2586.  
  2587. intn EDT_GetUndoCommandID( MWContext *pContext, intn index ){
  2588.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) CEDITCOMMAND_ID_NULL;
  2589.     return pEditBuffer->GetUndoCommand( index );
  2590. }
  2591.  
  2592. intn EDT_GetRedoCommandID( MWContext *pContext, intn index ){
  2593.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) CEDITCOMMAND_ID_NULL;
  2594.     return pEditBuffer->GetRedoCommand( index );
  2595. }
  2596.  
  2597. void EDT_BeginBatchChanges(MWContext *pContext){
  2598.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2599.     pEditBuffer->BeginBatchChanges(kGroupOfChangesCommandID);
  2600. }
  2601.  
  2602. void EDT_EndBatchChanges(MWContext *pContext){
  2603.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2604.     pEditBuffer->EndBatchChanges( );
  2605. }
  2606.  
  2607. void EDT_SetDisplayParagraphMarks(MWContext *pContext, XP_Bool display){
  2608.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2609.     pEditBuffer->SetDisplayParagraphMarks( display );
  2610. }
  2611.  
  2612. XP_Bool EDT_GetDisplayParagraphMarks(MWContext *pContext){
  2613.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) FALSE;
  2614.     return pEditBuffer->GetDisplayParagraphMarks();
  2615. }
  2616.  
  2617. void EDT_SetDisplayTables(MWContext *pContext, XP_Bool display){
  2618.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
  2619.     pEditBuffer->SetDisplayTables( display );
  2620. }
  2621.  
  2622. XP_Bool EDT_GetDisplayTables(MWContext *pContext){
  2623.     GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) FALSE;
  2624.     return pEditBuffer->GetDisplayTables();
  2625. }
  2626.  
  2627. XP_Bool EDT_IsWritableBuffer(MWContext *pContext){
  2628.     GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext,pEditBuffer) FALSE;
  2629.     return TRUE; 
  2630. }
  2631.  
  2632. #endif //EDITOR
  2633.