home *** CD-ROM | disk | FTP | other *** search
- /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * The contents of this file are subject to the Netscape Public License
- * Version 1.0 (the "NPL"); you may not use this file except in
- * compliance with the NPL. You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- *
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1998 Netscape Communications Corporation. All Rights
- * Reserved.
- */
-
-
- //
- // Public interface and shared subsystem data.
- //
-
- #ifdef EDITOR
-
- #include "editor.h"
-
- typedef struct PA_AmpEsc_struct {
- char *str;
- char value;
- intn len;
- } PA_AmpEsc;
-
- #ifndef XP_MAC
- static PA_AmpEsc PA_AmpEscapes[] = {
- {"lt", '<', 2},
- {"LT", '<', 2},
- {"gt", '>', 2},
- {"GT", '>', 2},
- {"amp", '&', 3},
- {"AMP", '&', 3},
- {"quot", '\"', 4},
- {"QUOT", '\"', 4},
- {"nbsp", '\240', 4},
- {"reg", '\256', 3},
- {"REG", '\256', 3},
- {"copy", '\251', 4},
- {"COPY", '\251', 4},
-
- {"iexcl", '\241', 5},
- {"cent", '\242', 4},
- {"pound", '\243', 5},
- {"curren", '\244', 6},
- {"yen", '\245', 3},
- {"brvbar", '\246', 6},
- {"sect", '\247', 4},
-
- {"uml", '\250', 3},
- {"ordf", '\252', 4},
- {"laquo", '\253', 5},
- {"not", '\254', 3},
- {"shy", '\255', 3},
- {"macr", '\257', 4},
-
- {"deg", '\260', 3},
- {"plusmn", '\261', 6},
- {"sup2", '\262', 4},
- {"sup3", '\263', 4},
- {"acute", '\264', 5},
- {"micro", '\265', 5},
- {"para", '\266', 4},
- {"middot", '\267', 6},
-
- {"cedil", '\270', 5},
- {"sup1", '\271', 4},
- {"ordm", '\272', 4},
- {"raquo", '\273', 5},
- {"frac14", '\274', 6},
- {"frac12", '\275', 6},
- {"frac34", '\276', 6},
- {"iquest", '\277', 6},
-
- {"Agrave", '\300', 6},
- {"Aacute", '\301', 6},
- {"Acirc", '\302', 5},
- {"Atilde", '\303', 6},
- {"Auml", '\304', 4},
- {"Aring", '\305', 5},
- {"AElig", '\306', 5},
- {"Ccedil", '\307', 6},
-
- {"Egrave", '\310', 6},
- {"Eacute", '\311', 6},
- {"Ecirc", '\312', 5},
- {"Euml", '\313', 4},
- {"Igrave", '\314', 6},
- {"Iacute", '\315', 6},
- {"Icirc", '\316', 5},
- {"Iuml", '\317', 4},
-
- {"ETH", '\320', 3},
- {"Ntilde", '\321', 6},
- {"Ograve", '\322', 6},
- {"Oacute", '\323', 6},
- {"Ocirc", '\324', 5},
- {"Otilde", '\325', 6},
- {"Ouml", '\326', 4},
- {"times", '\327', 5},
-
- {"Oslash", '\330', 6},
- {"Ugrave", '\331', 6},
- {"Uacute", '\332', 6},
- {"Ucirc", '\333', 5},
- {"Uuml", '\334', 4},
- {"Yacute", '\335', 6},
- {"THORN", '\336', 5},
- {"szlig", '\337', 5},
-
- {"agrave", '\340', 6},
- {"aacute", '\341', 6},
- {"acirc", '\342', 5},
- {"atilde", '\343', 6},
- {"auml", '\344', 4},
- {"aring", '\345', 5},
- {"aelig", '\346', 5},
- {"ccedil", '\347', 6},
-
- {"egrave", '\350', 6},
- {"eacute", '\351', 6},
- {"ecirc", '\352', 5},
- {"euml", '\353', 4},
- {"igrave", '\354', 6},
- {"iacute", '\355', 6},
- {"icirc", '\356', 5},
- {"iuml", '\357', 4},
-
- {"eth", '\360', 3},
- {"ntilde", '\361', 6},
- {"ograve", '\362', 6},
- {"oacute", '\363', 6},
- {"ocirc", '\364', 5},
- {"otilde", '\365', 6},
- {"ouml", '\366', 4},
- {"divide", '\367', 6},
-
- {"oslash", '\370', 6},
- {"ugrave", '\371', 6},
- {"uacute", '\372', 6},
- {"ucirc", '\373', 5},
- {"uuml", '\374', 4},
- {"yacute", '\375', 6},
- {"thorn", '\376', 5},
- {"yuml", '\377', 4},
-
- {NULL, '\0', 0},
- };
- #else /* ! XP_MAC */
- /* Entities encoded in MacRoman. */
- static PA_AmpEsc PA_AmpEscapes[] = {
- {"lt", '<', 2},
- {"LT", '<', 2},
- {"gt", '>', 2},
- {"GT", '>', 2},
- {"amp", '&', 3},
- {"AMP", '&', 3},
- {"quot", '\"', 4},
- {"QUOT", '\"', 4},
- {"nbsp", '\007', 4},
- {"reg", '\250', 3},
- {"REG", '\250', 3},
- {"copy", '\251', 4},
- {"COPY", '\251', 4},
-
- {"iexcl", '\301', 5},
- {"cent", '\242', 4},
- {"pound", '\243', 5},
- {"curren", '\333', 6},
- {"yen", '\264', 3},
-
- /*
- * Navigator Gold currently inverts this table in such a way that
- * ASCII characters (less than 128) get converted to the names
- * listed here. For things like ampersand (&) this is the
- * right thing to do, but for this one (brvbar), it isn't since
- * both broken vertical bar and vertical bar are mapped to the same
- * character by the Latin-1 to Mac Roman table.
- *
- * Punt for now. This needs to be fixed later. -- erik
- */
- /* {"brvbar", '\174', 6}, */
-
- {"sect", '\244', 4},
-
- {"uml", '\254', 3},
- {"ordf", '\273', 4},
- {"laquo", '\307', 5},
- {"not", '\302', 3},
- {"shy", '\320', 3},
- {"macr", '\370', 4},
-
- {"deg", '\241', 3},
- {"plusmn", '\261', 6},
- /* {"sup2", '\62', 4}, see comment above */
- /* {"sup3", '\63', 4}, see comment above */
- {"acute", '\253', 5},
- {"micro", '\265', 5},
- {"para", '\246', 4},
- {"middot", '\341', 6},
-
- {"cedil", '\374', 5},
- /* {"sup1", '\61', 4}, see comment above */
- {"ordm", '\274', 4},
- {"raquo", '\310', 5},
- {"frac14", '\271', 6},
- {"frac12", '\270', 6},
- {"frac34", '\262', 6},
- {"iquest", '\300', 6},
-
- {"Agrave", '\313', 6},
- {"Aacute", '\347', 6},
- {"Acirc", '\345', 5},
- {"Atilde", '\314', 6},
- {"Auml", '\200', 4},
- {"Aring", '\201', 5},
- {"AElig", '\256', 5},
- {"Ccedil", '\202', 6},
-
- {"Egrave", '\351', 6},
- {"Eacute", '\203', 6},
- {"Ecirc", '\346', 5},
- {"Euml", '\350', 4},
- {"Igrave", '\355', 6},
- {"Iacute", '\352', 6},
- {"Icirc", '\353', 5},
- {"Iuml", '\354', 4},
-
- {"ETH", '\334', 3}, /* Icelandic MacRoman: ETH ('D' w/horiz bar) */
- {"Ntilde", '\204', 6},
- {"Ograve", '\361', 6},
- {"Oacute", '\356', 6},
- {"Ocirc", '\357', 5},
- {"Otilde", '\315', 6},
- {"Ouml", '\205', 4},
- /* {"times", '\170', 5}, see comment above */
-
- {"Oslash", '\257', 6},
- {"Ugrave", '\364', 6},
- {"Uacute", '\362', 6},
- {"Ucirc", '\363', 5},
- {"Uuml", '\206', 4},
- {"Yacute", '\240', 6}, /* Icelandic MacRoman: Yacute */
- {"THORN", '\336', 5}, /* Icelandic MacRoman: THORN (kinda like 'P') */
- {"szlig", '\247', 5},
-
- {"agrave", '\210', 6},
- {"aacute", '\207', 6},
- {"acirc", '\211', 5},
- {"atilde", '\213', 6},
- {"auml", '\212', 4},
- {"aring", '\214', 5},
- {"aelig", '\276', 5},
- {"ccedil", '\215', 6},
-
- {"egrave", '\217', 6},
- {"eacute", '\216', 6},
- {"ecirc", '\220', 5},
- {"euml", '\221', 4},
- {"igrave", '\223', 6},
- {"iacute", '\222', 6},
- {"icirc", '\224', 5},
- {"iuml", '\225', 4},
-
- {"eth", '\335', 3}, /* Icelandic MacRoman: eth ('d' w/horiz bar) */
- {"ntilde", '\226', 6},
- {"ograve", '\230', 6},
- {"oacute", '\227', 6},
- {"ocirc", '\231', 5},
- {"otilde", '\233', 6},
- {"ouml", '\232', 4},
- {"divide", '\326', 6},
-
- {"oslash", '\277', 6},
- {"ugrave", '\235', 6},
- {"uacute", '\234', 6},
- {"ucirc", '\236', 5},
- {"uuml", '\237', 4},
- {"yacute", '\340', 6}, /* Icelandic MacRoman: yacute */
- {"thorn", '\337', 5}, /* Icelandic MacRoman: thorn (kinda like 'p') */
- {"yuml", '\330', 4},
-
- {NULL, '\0', 0},
- };
-
- #endif
-
-
- // For XP Strings
- extern "C" {
- #include "xpgetstr.h"
- #define WANT_ENUM_STRING_IDS
- #include "allxpstr.h"
- #undef WANT_ENUM_STRING_IDS
- }
- #include "prefapi.h"
- #include "secnav.h"
- #include "xp_str.h"
-
- char* edt_CopyFromHuge(int16 /*csid*/, XP_HUGE_CHAR_PTR text, int32 length, int32* pOutLength){
- int len2 = length;
-
- #ifdef XP_WIN16
- const int32 kMax = 65530;
- XP_Bool bTruncated = FALSE;
- if ( len2 > kMax ) {
- XP_TRACE(("Truncating huge data. original size: %d bytes", len2));
- bTruncated = TRUE;
- len2 = kMax;
- }
- #endif
-
- char* pData = (char*) XP_ALLOC(len2 + 1);
- if ( pData == NULL ) return NULL;
- for(int32 i = 0; i < len2; i++ ){
- // No XP way of transfering from HUGE to normal
- pData[i] = text[i];
- }
-
- #ifdef XP_WIN16
- if ( bTruncated ) {
- int nboc = INTL_NthByteOfChar(csid, pData, (int)(len2));
- // nboc is one-based. Stupid!
- if ( nboc > 1 ){
- len2 -= (nboc - 1);
- }
- if ( len2 < 0 ) {
- len2 = 0;
- }
- XP_TRACE(("Final size: %d bytes", len2));
- }
- #endif
-
- pData[len2] = '\0';
- if ( pOutLength ) {
- *pOutLength = len2;
- }
- return pData;
- }
-
- void edt_StripAtHashOrQuestionMark(char *pUrl)
- {
- if( !pUrl )
- return;
-
- char *pStart = XP_STRRCHR(pUrl, '/');
-
- if(!pStart)
- pStart = pUrl;
-
- char * pSuffix = XP_STRCHR(pStart, '?');
-
- if(pSuffix)
- *pSuffix = '\0';
-
- pSuffix = XP_STRRCHR(pStart, '#');
- if(pSuffix)
- *pSuffix = '\0';
- }
-
- char *edt_StripUsernamePassword(char *pUrl) {
- int iType = NET_URL_Type(pUrl);
- if (iType != FTP_TYPE_URL &&
- iType != HTTP_TYPE_URL &&
- iType != SECURE_HTTP_TYPE_URL) {
- return XP_STRDUP(pUrl);
- }
-
- char *pRet = NULL;
- if (NET_ParseUploadURL(pUrl,&pRet,NULL,NULL) && pRet) {
- return pRet;
- }
- else {
- return XP_STRDUP(pUrl);
- }
- }
-
-
- // Always returns newly allocated memory or NULL.
- PRIVATE char *edt_remove_trailing_slash(const char *pStr) {
- if (pStr) {
- char *pNew = XP_STRDUP(pStr);
- if (pNew && *pNew) {
- // Only do strlen() if pNew is non-NULL.
- int iLen = XP_STRLEN(pNew);
-
- // Kill trailing slash.
- if (pNew[iLen-1] == '/') {
- pNew[iLen-1] = '\0';
- }
- }
- return pNew;
- }
- else {
- return NULL;
- }
- }
-
-
-
- // Just wrappers around the XP_* functions. The only difference is that
- // these functions will work if the directory ends in a trailing slash,
- // avoiding obscure bugs on Win16.
- XP_Dir edt_OpenDir(const char * name, XP_FileType type) {
- XP_ASSERT(type == xpURL);
- char *pNew = edt_remove_trailing_slash(name);
- XP_Dir ret = XP_OpenDir(pNew,type);
- XP_FREEIF(pNew);
- return ret;
- }
-
- int edt_MakeDirectory(const char* name, XP_FileType type) {
- XP_ASSERT(type == xpURL);
- char *pNew = edt_remove_trailing_slash(name);
- int ret = XP_MakeDirectory(pNew,type);
- XP_FREEIF(pNew);
- return ret;
- }
-
- int edt_RemoveDirectory(const char *name, XP_FileType type) {
- XP_ASSERT(type == xpURL);
- char *pNew = edt_remove_trailing_slash(name);
- int ret = XP_RemoveDirectory(pNew,type);
- XP_FREEIF(pNew);
- return ret;
- }
-
-
-
- // Recursively kill everything under pNameArg, which is in xpURL format.
- void edt_RemoveDirectoryR(char *pNameArg) {
- // non-NULL and non-zero-length.
- if (!(pNameArg && *pNameArg))
- return;
-
- // Make sure name ends in slash.
- char *pName = XP_STRDUP(pNameArg);
- if (!pName) {
- return;
- }
- if (pName[XP_STRLEN(pName)-1] != '/') {
- StrAllocCat(pName,"/");
- }
-
-
- XP_Dir dir = edt_OpenDir(pName, xpURL);
- if (dir) {
- XP_DirEntryStruct *entry = NULL;
- for (entry = XP_ReadDir(dir); entry; entry = XP_ReadDir(dir)) {
- // Don't touch "." or ".."
- if (entry->d_name && XP_STRCMP(entry->d_name,".") && XP_STRCMP(entry->d_name,"..")) {
-
- // Create filename inside directory.
- char *subName = XP_STRDUP(pName);
- if (entry->d_name[0] == '/') {
- // skip the slash.
- StrAllocCat(subName,entry->d_name + 1);
- }
- else {
- StrAllocCat(subName,entry->d_name);
- }
-
- // Recurse, will do nothing if not a directory.
- edt_RemoveDirectoryR(subName);
- // If subName is a directory, it will already be gone, so this does nothing.
- XP_FileRemove(subName,xpURL);
-
-
- XP_FREEIF(subName);
- }
- }
-
- XP_CloseDir(dir);
- edt_RemoveDirectory(pName,xpURL);
- }
-
-
- XP_FREE(pName);
- }
-
-
- // Timer
-
-
- void CEditTimerCallback (void * closure){
- if (closure) {
- CEditTimer* pTimer = (CEditTimer*) closure;
- pTimer->Callback();
- }
- }
-
- CEditTimer::CEditTimer(){
- m_timeoutEnabled = FALSE;
- m_timerID = NULL;
- }
-
- CEditTimer::~CEditTimer(){
- Cancel();
- }
-
- void CEditTimer::Callback() {
- m_timeoutEnabled = FALSE;
- OnCallback();
- }
-
- void CEditTimer::Cancel(){
- if ( m_timeoutEnabled ) {
- FE_ClearTimeout(m_timerID);
- m_timeoutEnabled = FALSE;
- m_timerID = NULL;
- }
- }
-
- void CEditTimer::OnCallback() {}
-
- void CEditTimer::SetTimeout(uint32 msecs){
- Cancel();
- m_timerID = FE_SetTimeout(&CEditTimerCallback, this, msecs);
- m_timeoutEnabled = TRUE;
- }
-
- // Color with a defined/undefined boolean
-
- ED_Color::ED_Color() {
- m_bDefined = TRUE;
- m_color.red = 0;
- m_color.green = 0;
- m_color.blue = 0;
- }
- ED_Color::ED_Color(LO_Color& pLoColor) {
- m_bDefined = TRUE;
- m_color = pLoColor;
- }
-
- static int ED_Color_Clip(int c) {
- if ( c < 0 ) {
- XP_ASSERT(FALSE);
- c = 0;
- }
- if ( c > 255 ) {
- XP_ASSERT(FALSE);
- c = 255;
- }
- return c;
- }
-
- ED_Color::ED_Color(int r, int g, int b) {
- m_bDefined = TRUE;
- m_color.red = ED_Color_Clip(r);
- m_color.green = ED_Color_Clip(g);
- m_color.blue = ED_Color_Clip(b);
- }
-
- ED_Color::ED_Color(int32 rgb) {
- if ( rgb == -1 ) {
- m_bDefined = FALSE;
- m_color.red = 0;
- m_color.green = 0;
- m_color.blue = 0;
- }
- else {
- m_bDefined = TRUE;
- m_color.red = (rgb >> 16) & 255;
- m_color.green = (rgb >> 8) & 255;
- m_color.blue = rgb & 255;
- }
- }
-
- ED_Color::ED_Color(LO_Color* pLoColor) {
- if ( pLoColor ) {
- m_color.red = ED_Color_Clip(pLoColor->red);
- m_color.green = ED_Color_Clip(pLoColor->green);
- m_color.blue = ED_Color_Clip(pLoColor->blue);
- m_bDefined = TRUE;
- }
- else {
- m_bDefined = FALSE;
- }
- }
-
- XP_Bool ED_Color::operator==(const ED_Color& other) const {
- return m_bDefined == other.m_bDefined &&
- (!m_bDefined || m_color.red == other.m_color.red &&
- m_color.green == other.m_color.green &&
- m_color.blue == other.m_color.blue );
- }
-
- XP_Bool ED_Color::operator!=(const ED_Color& other) const {
- return ! operator==(other);
- }
-
- XP_Bool ED_Color::IsDefined() { return m_bDefined; }
- int ED_Color::Red() { XP_ASSERT(m_bDefined); return m_color.red; }
- int ED_Color::Green() { XP_ASSERT(m_bDefined); return m_color.green; }
- int ED_Color::Blue() { XP_ASSERT(m_bDefined); return m_color.blue; }
- LO_Color ED_Color::GetLOColor() {XP_ASSERT(m_bDefined); return m_color; }
-
- long ED_Color::GetAsLong() {
- if ( ! m_bDefined ) return -1;
- return (((long)m_color.red << 16) | ((long)m_color.green << 8) | (long)m_color.blue);
- }
-
- void
- ED_Color::SetUndefined() {
- m_bDefined = FALSE;
- m_color.red = 0;
- m_color.green = 0;
- m_color.blue = 0;
- }
-
- ED_Color
- ED_Color::GetUndefined()
- {
- ED_Color undef;
- undef.SetUndefined();
- return undef;
- }
-
- //-----------------------------------------------------------------------------
- // Helper functions.
- //-----------------------------------------------------------------------------
-
- //
- // Convert a tagtype to a string
- //
-
- static char* TagString(int32 tagType)
- {
- switch(tagType)
- {
- case P_UNKNOWN:
- return "";
- case P_TEXT:
- return "text";
- case P_TITLE:
- return PT_TITLE;
- case P_INDEX:
- return PT_INDEX;
- case P_BASE:
- return PT_BASE;
- case P_LINK:
- return PT_LINK;
- case P_HEADER_1:
- return PT_HEADER_1;
- case P_HEADER_2:
- return PT_HEADER_2;
- case P_HEADER_3:
- return PT_HEADER_3;
- case P_HEADER_4:
- return PT_HEADER_4;
- case P_HEADER_5:
- return PT_HEADER_5;
- case P_HEADER_6:
- return PT_HEADER_6;
- case P_ANCHOR:
- return PT_ANCHOR;
- case P_PARAGRAPH:
- return PT_PARAGRAPH;
- case P_ADDRESS:
- return PT_ADDRESS;
- case P_IMAGE:
- return PT_IMAGE;
- case P_NEW_IMAGE:
- return PT_NEW_IMAGE;
- case P_PLAIN_TEXT:
- return PT_PLAIN_TEXT;
- case P_PLAIN_PIECE:
- return PT_PLAIN_PIECE;
- case P_PREFORMAT:
- return PT_PREFORMAT;
- case P_LISTING_TEXT:
- return PT_LISTING_TEXT;
- case P_UNUM_LIST:
- return PT_UNUM_LIST;
- case P_NUM_LIST:
- return PT_NUM_LIST;
- case P_MENU:
- return PT_MENU;
- case P_DIRECTORY:
- return PT_DIRECTORY;
- case P_LIST_ITEM:
- return PT_LIST_ITEM;
- case P_DESC_LIST:
- return PT_DESC_LIST;
- case P_DESC_TITLE:
- return PT_DESC_TITLE;
- case P_DESC_TEXT:
- return PT_DESC_TEXT;
- case P_STRIKEOUT:
- return PT_STRIKEOUT;
- case P_STRIKE:
- return PT_STRIKE;
- case P_UNDERLINE:
- return PT_UNDERLINE;
- case P_FIXED:
- return PT_FIXED;
- case P_CENTER:
- return PT_CENTER;
- case P_EMBED:
- return PT_EMBED;
- case P_SUBDOC:
- return PT_SUBDOC;
- case P_CELL:
- return PT_CELL;
- case P_TABLE:
- return PT_TABLE;
- case P_CAPTION:
- return PT_CAPTION;
- case P_TABLE_ROW:
- return PT_TABLE_ROW;
- case P_TABLE_HEADER:
- return PT_TABLE_HEADER;
- case P_TABLE_DATA:
- return PT_TABLE_DATA;
- case P_BOLD:
- return PT_BOLD;
- case P_ITALIC:
- return PT_ITALIC;
- case P_EMPHASIZED:
- return PT_EMPHASIZED;
- case P_STRONG:
- return PT_STRONG;
- case P_CODE:
- return PT_CODE;
- case P_SAMPLE:
- return PT_SAMPLE;
- case P_KEYBOARD:
- return PT_KEYBOARD;
- case P_VARIABLE:
- return PT_VARIABLE;
- case P_CITATION:
- return PT_CITATION;
- case P_BLOCKQUOTE:
- return PT_BLOCKQUOTE;
- case P_FORM:
- return PT_FORM;
- case P_INPUT:
- return PT_INPUT;
- case P_SELECT:
- return PT_SELECT;
- case P_OPTION:
- return PT_OPTION;
- case P_TEXTAREA:
- return PT_TEXTAREA;
- case P_HRULE:
- return PT_HRULE;
- case P_BODY:
- return PT_BODY;
- case P_COLORMAP:
- return PT_COLORMAP;
- case P_HYPE:
- return PT_HYPE;
- case P_META:
- return PT_META;
- case P_LINEBREAK:
- return PT_LINEBREAK;
- case P_WORDBREAK:
- return PT_WORDBREAK;
- case P_NOBREAK:
- return PT_NOBREAK;
- case P_BASEFONT:
- return PT_BASEFONT;
- case P_FONT:
- return PT_FONT;
- case P_BLINK:
- return PT_BLINK;
- case P_BIG:
- return PT_BIG;
- case P_SMALL:
- return PT_SMALL;
- case P_SUPER:
- return PT_SUPER;
- case P_SUB:
- return PT_SUB;
- case P_GRID:
- return PT_GRID;
- case P_GRID_CELL:
- return PT_GRID_CELL;
- case P_NOGRIDS:
- return PT_NOGRIDS;
- case P_JAVA_APPLET:
- return PT_JAVA_APPLET;
- case P_MAP:
- return PT_MAP;
- case P_AREA:
- return PT_AREA;
- case P_DIVISION:
- return PT_DIVISION;
- case P_KEYGEN:
- return PT_KEYGEN;
- case P_MAX:
- return "HTML";
- case P_SCRIPT:
- return PT_SCRIPT;
- case P_NOEMBED:
- return PT_NOEMBED;
- case P_SERVER:
- return PT_SERVER;
- case P_PARAM:
- return PT_PARAM;
- case P_MULTICOLUMN:
- return PT_MULTICOLUMN;
- case P_SPACER:
- return PT_SPACER;
- case P_NOSCRIPT:
- return PT_NOSCRIPT;
- case P_HEAD:
- return PT_HEAD;
- case P_HTML:
- return PT_HTML;
- case P_CERTIFICATE:
- return PT_CERTIFICATE;
- case P_MQUOTE:
- return PT_MQUOTE;
- case P_STYLE:
- return PT_STYLE;
- case P_LAYER:
- return PT_LAYER;
- case P_ILAYER:
- return PT_ILAYER;
- case P_OBJECT:
- return PT_OBJECT;
- case P_SPAN:
- return PT_SPAN;
- case P_SPELL:
- return PT_SPELL;
- case P_INLINEINPUT:
- return PT_INLINEINPUT;
- case P_INLINEINPUTTHICK:
- return PT_INLINEINPUTTHICK;
- case P_INLINEINPUTDOTTED:
- return PT_INLINEINPUTDOTTED;
- case P_NSDT:
- return PT_NSDT;
- case P_NSCP_CLOSE:
- return PT_NSCP_OPEN;
- case P_NSCP_OPEN:
- return PT_NSDT;
- case P_NSCP_REBLOCK:
- return PT_NSCP_REBLOCK;
- case P_BLOCK:
- return "block"; // PT_BLOCK
- case P_NOLAYER:
- return PT_NOLAYER; // (?) jrm 97/03/08 according to instructions below.
- default:
- // If we get here, then it's a new tag that's been added to lib\libparse\pa_tags.h
- // The fix is to add this new tag to the case statement above.
- XP_ASSERT(FALSE);
- return "UNKNOWN";
- }
- }
-
- const int kTagBufferSize = 40;
- static char tagBuffer[kTagBufferSize];
-
- char* EDT_UpperCase(char* tagString)
- {
- int i = 0;
- if ( tagString ) {
- for ( i = 0; i < kTagBufferSize-1 && tagString[i] != '\0'; i++ ) {
- tagBuffer[i] = XP_TO_UPPER(tagString[i]);
- }
- }
- tagBuffer[i] = '\0';
- return tagBuffer;
- }
-
- char *EDT_TagString(int32 tagType){
- return EDT_UpperCase(TagString(tagType));
- }
-
- char* EDT_AlignString(ED_Alignment align){
- if ( align < ED_ALIGN_CENTER ) {
- XP_ASSERT(FALSE);
- align = ED_ALIGN_CENTER;
- }
- if ( align > ED_ALIGN_ABSTOP ) {
- XP_ASSERT(FALSE);
- align = ED_ALIGN_ABSTOP;
- }
- return EDT_UpperCase(lo_alignStrings[align]);
- }
-
- ED_TextFormat edt_TagType2TextFormat( TagType t ){
- switch(t){
- case P_BOLD:
- case P_STRONG:
- return TF_BOLD;
-
- case P_ITALIC:
- case P_EMPHASIZED:
- case P_VARIABLE:
- case P_CITATION:
- return TF_ITALIC;
-
- case P_FIXED:
- case P_CODE:
- case P_KEYBOARD:
- case P_SAMPLE:
- return TF_FIXED;
-
- case P_SUPER:
- return TF_SUPER;
-
- case P_SUB:
- return TF_SUB;
-
- case P_NOBREAK:
- return TF_NOBREAK;
-
- case P_STRIKEOUT:
- return TF_STRIKEOUT;
-
- case P_UNDERLINE:
- return TF_UNDERLINE;
-
- case P_BLINK:
- return TF_BLINK;
-
- case P_SERVER:
- return TF_SERVER;
-
- case P_SCRIPT:
- return TF_SCRIPT;
-
- case P_STYLE:
- return TF_STYLE;
-
- case P_SPELL:
- return TF_SPELL;
-
- case P_INLINEINPUT:
- return TF_INLINEINPUT;
-
- case P_INLINEINPUTTHICK:
- return TF_INLINEINPUTTHICK;
-
- case P_INLINEINPUTDOTTED:
- return TF_INLINEINPUTDOTTED;
- }
- return TF_NONE;
- }
-
- static int workBufSize = 0;
- static char* workBuf = 0;
-
- char *edt_WorkBuf( int iSize ){
- if( iSize > workBufSize ){
- if( workBuf != 0 ){
- delete[] workBuf;
- }
- workBuf = new char[ iSize ];
- }
- return workBuf;
- }
-
- char *edt_QuoteString( char* pString ){
- int iLen = 0;
- char *p = pString;
- while( p && *p ){
- if( *p == '"' ){
- iLen += 6; // "
- }
- else {
- iLen++;
- }
- p++;
- }
- iLen++;
-
- char *pRet = edt_WorkBuf( iLen+1 );
- p = pRet;
- while( pString && *pString ){
- if( *pString == '"' ){
- strcpy( p, """ );
- p += 6;
- }
- else {
- *p++ = *pString;
- }
- pString++;
- }
- *p = 0;
- return pRet;
- }
-
-
- char *edt_MakeParamString( char* pString ){
- int iLen = 0;
- char *p = pString;
- while( p && *p ){
- if( *p == '"' ){
- iLen += 6; // "
- }
- else {
- iLen++;
- }
- p++;
- }
- iLen += 3; // the beginning and ending quote and the trailing 0.
-
- char *pRet = edt_WorkBuf( iLen+1 );
- p = pRet;
- if( pString && *pString == '`' ){
- do {
- *p++ = *pString++;
- } while( *pString && *pString != '`' );
- *p++ = '`';
- *p = 0;
- }
- else {
- *p = '"';
- p++;
- while( pString && *pString ){
- if( *pString == '"' ){
- strcpy( p, """ );
- p += 6;
- }
- else {
- *p++ = *pString;
- }
- pString++;
- }
- *p++ = '"';
- *p = 0;
- }
- return pRet;
- }
-
- char *edt_FetchParamString( PA_Tag *pTag, char* param, int16 win_csid ){
- PA_Block buff;
- char *str;
- char *retVal = 0;
-
- buff = PA_FetchParamValue(pTag, param, win_csid);
- if (buff != NULL)
- {
- PA_LOCK(str, char *, buff);
- lo_StripTextWhitespace(str, XP_STRLEN(str));
- if( str ) {
- retVal = XP_STRDUP( str );
- }
- PA_UNLOCK(buff);
- PA_FREE(buff);
- }
- return retVal;
- }
-
- XP_Bool edt_FetchParamBoolExist( PA_Tag *pTag, char* param, int16 csid ){
- PA_Block buff;
-
- buff = PA_FetchParamValue(pTag, param, csid);
- if (buff != NULL){
- PA_FREE(buff);
- return TRUE;
- }
- else {
- return FALSE;
- }
- }
-
- XP_Bool edt_FetchDimension( PA_Tag *pTag, char* param,
- int32 *pValue, XP_Bool *pPercent,
- int32 nDefaultValue, XP_Bool bDefaultPercent, int16 csid ){
- PA_Block buff;
- char *str;
- int32 value;
-
- // Fill in defaults
- *pValue = nDefaultValue;
- *pPercent = bDefaultPercent;
-
- buff = PA_FetchParamValue(pTag, param, csid);
- XP_Bool result = buff != NULL;
- if( buff != NULL )
- {
- PA_LOCK(str, char *, buff);
- if( str != 0 ){
- value = XP_ATOI(str);
- *pValue = value;
- *pPercent = (NULL != XP_STRCHR(str, '%'));
- }
- PA_UNLOCK(buff);
- PA_FREE(buff);
- }
- return result;
- }
-
- ED_Alignment edt_FetchParamAlignment( PA_Tag* pTag, ED_Alignment eDefault, XP_Bool bVAlign, int16 csid ){
- PA_Block buff;
- char *str;
- ED_Alignment retVal = eDefault;
-
- buff = PA_FetchParamValue(pTag, bVAlign ? PARAM_VALIGN : PARAM_ALIGN, csid);
- if (buff != NULL)
- {
- XP_Bool floating;
-
- floating = FALSE;
- PA_LOCK(str, char *, buff);
- lo_StripTextWhitespace(str, XP_STRLEN(str));
- // LTNOTE: this is a hack. We should do a better job maping these
- // could cause problems in the future.
- retVal = (ED_Alignment) lo_EvalAlignParam(str, &floating);
- PA_UNLOCK(buff);
- PA_FREE(buff);
- }
- return retVal;
- }
-
- int32 edt_FetchParamInt( PA_Tag *pTag, char* param, int32 defValue, int16 csid ){
- return edt_FetchParamInt(pTag, param, defValue, defValue, csid);
- }
-
- int32 edt_FetchParamInt( PA_Tag *pTag, char* param, int32 defValue, int32 defValueIfParamButNoValue, int16 csid ){
- PA_Block buff;
- char *str;
- int32 retVal = defValue;
-
- buff = PA_FetchParamValue(pTag, param, csid);
- if (buff != NULL)
- {
- PA_LOCK(str, char *, buff);
- if( str != 0 ){
- if ( *str == '\0' ) { /* They mentioned the param, but gave to value. */
- retVal = defValueIfParamButNoValue;
- }
- else {
- retVal = XP_ATOI(str);
- }
- }
- PA_UNLOCK(buff);
- PA_FREE(buff);
- }
- return retVal;
- }
-
- ED_Color edt_FetchParamColor( PA_Tag *pTag, char* param, int16 csid ){
- PA_Block buff = PA_FetchParamValue(pTag, param, csid);
- ED_Color retVal;
- retVal.SetUndefined();
- if (buff != NULL)
- {
- char *color_str;
- PA_LOCK(color_str, char *, buff);
- lo_StripTextWhitespace(color_str, XP_STRLEN(color_str));
- uint8 red, green, blue;
- LO_ParseRGB(color_str, &red, &green, &blue);
- retVal = EDT_RGB(red,green,blue);
- PA_UNLOCK(buff);
- PA_FREE(buff);
- }
- return retVal;
- }
-
- PRIVATE
- XP_Bool edt_NameInList( char* pName, char** ppNameList ){
- int i = 0;
- while( ppNameList && ppNameList[i] ){
- if( XP_STRCASECMP( pName, ppNameList[i]) == 0 ){
- return TRUE;
- }
- i++;
- }
- return FALSE;
- }
-
- char* edt_FetchParamExtras( PA_Tag *pTag, char**ppKnownParams, int16 win_csid ){
- char** ppNames;
- char** ppValues;
- char* pRet = 0;
- int i = 0;
- char *pSpace = "";
- int iMax;
-
- iMax = PA_FetchAllNameValues( pTag, &ppNames, &ppValues, win_csid );
-
- while( i < iMax ){
- if( !edt_NameInList( ppNames[i], ppKnownParams ) ){
- if( ppValues[i] ){
- pRet = PR_sprintf_append( pRet, "%s%s=%s",
- pSpace, ppNames[i], edt_MakeParamString( ppValues[i] ) );
- }
- else {
- pRet = PR_sprintf_append( pRet, "%s%s", pSpace, ppNames[i] );
- }
- pSpace = " ";
- }
- i++;
- }
-
- i = 0;
- while( i < iMax ){
- if( ppNames[i] ) XP_FREE( ppNames[i] );
- if( ppValues[i] ) XP_FREE( ppValues[i] );
- i++;
- }
-
- if( ppNames ) XP_FREE( ppNames );
- if( ppValues ) XP_FREE( ppValues );
-
- return pRet;
- }
-
- // Override existing.
- void edt_FetchParamString2(PA_Tag* pTag, char* param, char*& data, int16 win_csid){
- char* result = edt_FetchParamString( pTag, param, win_csid );
- if ( result ) {
- if ( data ){
- XP_FREE(data);
- }
- data = result;
- }
- }
-
- // Override existing.
- void edt_FetchParamColor2( PA_Tag *pTag, char* param, ED_Color& data, int16 csid ){
- ED_Color result = edt_FetchParamColor(pTag, param, csid);
- if ( result.IsDefined() ) {
- data = result;
- }
- }
-
- // Append to existing extras. To Do: Have new versions of a parameter overwrite the old ones.
- void edt_FetchParamExtras2( PA_Tag *pTag, char**ppKnownParams, char*& data, int16 win_csid ){
- char* result = edt_FetchParamExtras( pTag, ppKnownParams, win_csid );
- if ( result ) {
- if ( data ) {
- data = PR_sprintf_append(data, " %s", result);
- XP_FREE(result);
- }
- else {
- data = result;
- }
- }
- }
-
- XP_Bool edt_ReplaceParamValue( PA_Tag *pTag, char * pName, char * pValue, int16 csid ){
- XP_ASSERT(pName);
- XP_ASSERT(pTag);
-
- char** ppNames;
- char** ppValues;
- char* pNew = 0;
- int i = 0;
- char *pSpace = "";
- int iMax;
- XP_Bool bFound = FALSE;
-
- iMax = PA_FetchAllNameValues( pTag, &ppNames, &ppValues, csid );
-
- while( i < iMax ){
- if( XP_STRCASECMP( pName, ppNames[i]) == 0 ){
- bFound = TRUE;
- if( pValue){
- pNew = PR_sprintf_append( pNew, "%s%s=%s",
- pSpace, pName, edt_MakeParamString( pValue ) );
- }
- } else {
- if( ppValues[i] ){
- pNew = PR_sprintf_append( pNew, "%s%s=%s",
- pSpace, ppNames[i], edt_MakeParamString( ppValues[i] ) );
- }
- else {
- pNew = PR_sprintf_append( pNew, "%s%s", pSpace, ppNames[i] );
- }
- pSpace = " ";
- }
- i++;
- }
- // Add value at end if not found
- if( !bFound && pValue ){
- pNew = PR_sprintf_append( pNew, "%s%s=%s", pSpace, pName, pValue );
- }
- // Terminate
- pNew = PR_sprintf_append( pNew, "%s", ">" );
-
- // Cleanup memory
- i = 0;
- while( i < iMax ){
- if( ppNames[i] ) XP_FREE( ppNames[i] );
- if( ppValues[i] ) XP_FREE( ppValues[i] );
- i++;
- }
-
- if( ppNames ) XP_FREE( ppNames );
- if( ppValues ) XP_FREE( ppValues );
-
- // Now replace with new data
-
- PA_Block buff;
- char *locked_buff;
- int iLen;
-
- iLen = XP_STRLEN(pNew);
- buff = (PA_Block)PA_ALLOC((iLen+1) * sizeof(char));
- if (buff != NULL) {
- PA_LOCK(locked_buff, char *, buff);
- XP_BCOPY(pNew, locked_buff, iLen);
- locked_buff[iLen] = '\0';
- PA_UNLOCK(buff);
-
- if( pTag->data ) XP_FREE(pTag->data);
- pTag->data = buff;
- pTag->data_len = iLen;
- } else {
- // LTNOTE: out of memory, should throw an exception
- }
- return bFound;
- }
-
- LO_Color* edt_MakeLoColor(ED_Color c) {
- if( !c.IsDefined()){
- return 0;
- }
- LO_Color *pColor = XP_NEW( LO_Color );
- pColor->red = EDT_RED(c);
- pColor->green = EDT_GREEN(c);
- pColor->blue = EDT_BLUE(c);
- return pColor;
- }
-
- void edt_SetLoColor( ED_Color c, LO_Color *pColor ){
- if( !c.IsDefined()){
- XP_ASSERT(FALSE);
- return;
- }
- pColor->red = EDT_RED(c);
- pColor->green = EDT_GREEN(c);
- pColor->blue = EDT_BLUE(c);
- }
-
-
- #define CHARSET_SIZE 256
- static PA_AmpEsc *ed_escapes[CHARSET_SIZE];
-
- void edt_InitEscapes(int16 /*csid*/, XP_Bool bQuoteHiBits){
- PA_AmpEsc *pEsc = PA_AmpEscapes;
-
- XP_BZERO( ed_escapes, CHARSET_SIZE * sizeof( PA_AmpEsc* ) );
-
- while( pEsc->value ){
- int ch = 0xff & (int) pEsc->value;
- if( ed_escapes[ ch ] == 0 ){
- if ( ch == '&' || ch == '<'
- || (NON_BREAKING_SPACE == ((char) ch))
- || (ch > 128 && bQuoteHiBits ) ) {
- ed_escapes[ ch ] = pEsc;
- }
- }
- pEsc++;
- }
- }
-
- void edt_PrintWithEscapes( CPrintState *ps, char *p, XP_Bool bBreakLines ){
- int csid = ps->m_pBuffer->GetRAMCharSetID();
- char *pBegin;
- PA_AmpEsc *pEsc;
-
- // break the lines after 70 characters if we can, but don't really do it
- // in the formatted case.
- while( p && *p ){
- pBegin = p;
- while( *p && ps->m_iCharPos < 70 && ed_escapes[(unsigned char)*p] == 0
- && ((unsigned char) *p) != ((unsigned char) NON_BREAKING_SPACE) ){
- char* p2 = INTL_NextChar(csid, p);
- int charWidth = p2 - p;
- ps->m_iCharPos += charWidth;
- p = p2;
- }
- while( *p && *p != ' ' && ed_escapes[(unsigned char)*p] == 0
- && ((unsigned char) *p) != ((unsigned char) NON_BREAKING_SPACE)){
- char* p2 = INTL_NextChar(csid, p);
- int charWidth = p2 - p;
- ps->m_iCharPos += charWidth;
- p = p2;
- }
- ps->m_pOut->Write( pBegin, p-pBegin);
-
- if( *p && *p == ' ' && ps->m_iCharPos >= 70 ){
- if( bBreakLines ){
- ps->m_pOut->Write( "\n", 1 );
- }
- else {
- ps->m_pOut->Write( " ", 1 );
- }
- ps->m_iCharPos = 0;
- }
- else if( *p && (pEsc = ed_escapes[(unsigned char)*p]) != 0 ){
- ps->m_pOut->Write( "&",1 );
- ps->m_pOut->Write( pEsc->str, pEsc->len );
- ps->m_pOut->Write( ";",1 );
- ps->m_iCharPos += pEsc->len+2;
- }
- else if (((unsigned char) *p) == ((unsigned char) NON_BREAKING_SPACE) ){
- const char* nbsp = INTL_NonBreakingSpace(csid);
- int nbsp_len = XP_STRLEN(nbsp);
- ps->m_pOut->Write( (char*) nbsp, XP_STRLEN(nbsp));
- }
-
- // move past the space or special char
- if( *p ){
- p = INTL_NextChar(csid, p);
- }
- }
- }
-
- char *edt_LocalName( char *pURL ){
- char *pDest = FE_URLToLocalName( pURL );
- #if 0
- if( pDest && FE_EditorPrefConvertFileCaseOnWrite( ) ){
- char *url_ptr = pDest;
- while ( *url_ptr != '\0' ){
- *url_ptr = XP_TO_LOWER(*url_ptr);
- url_ptr++;
- }
- }
- #endif
- return pDest;
- }
-
- PA_Block PA_strdup( char* s ){
- char *new_str;
- PA_Block new_buff;
-
- if( s == 0 ){
- return 0;
- }
-
- new_buff = (PA_Block)PA_ALLOC(XP_STRLEN(s) + 1);
- if (new_buff != NULL)
- {
- PA_LOCK(new_str, char *, new_buff);
- XP_STRCPY(new_str, s);
- PA_UNLOCK(new_buff);
- }
- return new_buff;
- }
-
- void edt_SetTagData( PA_Tag* pTag, char* pTagData){
- PA_Block buff;
- char *locked_buff;
- int iLen;
-
- iLen = XP_STRLEN(pTagData);
- buff = (PA_Block)PA_ALLOC((iLen+1) * sizeof(char));
- if (buff != NULL)
- {
- PA_LOCK(locked_buff, char *, buff);
- XP_BCOPY(pTagData, locked_buff, iLen);
- locked_buff[iLen] = '\0';
- PA_UNLOCK(buff);
- }
- else {
- // LTNOTE: out of memory, should throw an exception
- return;
- }
- pTag->data = buff;
- pTag->data_len = iLen;
- pTag->next = NULL;
- return;
- }
-
- //
- // Create a tag and add it to the list
- //
- void edt_AddTag( PA_Tag*& pStart, PA_Tag*& pEnd, TagType t, XP_Bool bIsEnd,
- char *pTagData ){
- PA_Tag *pTag = XP_NEW( PA_Tag );
- XP_BZERO( pTag, sizeof( PA_Tag ) );
- pTag->type = t;
- pTag->is_end = bIsEnd;
- edt_SetTagData(pTag, pTagData ? pTagData : ">" );
- if( pStart == 0 ){
- pStart = pTag;
- }
- if( pEnd ){
- pEnd->next = pTag;
- }
- pEnd = pTag;
- }
-
-
-
- //-----------------------------------------------------------------------------
- // CEditPosition
- //-----------------------------------------------------------------------------
-
- void CEditPositionComparable::CalcPosition( TXP_GrowableArray_int32* pA,
- CEditPosition *pPos ){
-
- CEditElement *pElement, *pParent, *pSib;
- int i;
-
- pA->Empty();
- pA->Add( pPos->Offset() );
- pElement = pPos->Element();
- if( pElement ){
- while( (pParent = pElement->GetParent()) != NULL ){
- i = 0;
- pSib = pParent->GetChild();
- while( pSib != pElement ){
- pSib = pSib->GetNextSibling();
- i++;
- }
- pA->Add(i);
- pElement = pParent;
- }
- }
- }
-
- int CEditPositionComparable::Compare( CEditPosition *pPos ){
- TXP_GrowableArray_int32 toArray;
-
- CalcPosition( &toArray, pPos );
-
- int32 i = m_Array.Size();
- int32 iTo = toArray.Size();
- int32 iDiff;
-
- while( i && iTo ){
- iDiff = toArray[--iTo] - m_Array[--i];
- if( iDiff != 0 ) {
- return (iDiff > 0 ? 1 : -1 );
- }
- }
- if( i == 0 && iTo == 0){
- return 0;
- }
- iDiff = iTo - i;
- return (iDiff > 0 ? 1 : -1 );
- }
-
-
- // CEditInsertPoint
-
- CEditInsertPoint::CEditInsertPoint() {
- m_pElement = 0;
- m_iPos = 0;
- m_bStickyAfter = FALSE;
- }
-
- CEditInsertPoint::CEditInsertPoint(CEditLeafElement* pElement, ElementOffset iPos) {
- m_pElement = pElement;
- m_iPos = iPos;
- m_bStickyAfter = FALSE;
- }
-
- CEditInsertPoint::CEditInsertPoint(CEditElement* pElement, ElementOffset iPos){
- m_pElement = pElement->Leaf();
- m_iPos = iPos;
- m_bStickyAfter = FALSE;
- }
-
- CEditInsertPoint::CEditInsertPoint(CEditElement* pElement, ElementOffset iPos, XP_Bool bStickyAfter){
- m_pElement = pElement->Leaf();
- m_iPos = iPos;
- m_bStickyAfter = bStickyAfter;
- }
-
- XP_Bool CEditInsertPoint::operator==(const CEditInsertPoint& other ) {
- return m_pElement == other.m_pElement && m_iPos == other.m_iPos;
- }
-
- XP_Bool CEditInsertPoint::operator!=(const CEditInsertPoint& other ) {
- return ! (*this == other);
- }
-
- XP_Bool CEditInsertPoint::operator<(const CEditInsertPoint& other ) {
- return Compare(other) < 0;
- }
-
- XP_Bool CEditInsertPoint::operator<=(const CEditInsertPoint& other ) {
- return Compare(other) <= 0;
- }
-
- XP_Bool CEditInsertPoint::operator>=(const CEditInsertPoint& other ) {
- return Compare(other) >= 0;
- }
-
- XP_Bool CEditInsertPoint::operator>(const CEditInsertPoint& other ) {
- return Compare(other) > 0;
- }
-
- CEditElement* CEditInsertPoint::FindNonEmptyElement( CEditElement *pStartElement ){
- CEditElement* pOldElement = NULL;
- while ( pStartElement && pStartElement != pOldElement ) {
- pOldElement = pStartElement;
- if( !pStartElement->IsLeaf() ){
- pStartElement = pStartElement->PreviousLeaf();
- }
- else if( pStartElement->Leaf()->GetLayoutElement() == 0 ){
- pStartElement = pStartElement->PreviousLeaf();
- }
- }
- return pStartElement;
- }
-
- int CEditInsertPoint::Compare(const CEditInsertPoint& other ) {
- XP_Bool bAIsBreak = FALSE;
- LO_Element* pA = m_pElement->GetLayoutElement();
- if ( ! pA ) {
- bAIsBreak = TRUE;
- pA = FindNonEmptyElement(m_pElement)->Leaf()->GetLayoutElement();
- }
- XP_Bool bBIsBreak = FALSE;
- LO_Element* pB = other.m_pElement->GetLayoutElement();
- if ( ! pB ) {
- bBIsBreak = TRUE;
- pB = FindNonEmptyElement(other.m_pElement)->Leaf()->GetLayoutElement();
- }
- if ( !pA || !pB ) {
- XP_ASSERT(FALSE); // Phantom insert points.
- return 0;
- }
- int32 aIndex = pA->lo_any.ele_id;
- int32 bIndex = pB->lo_any.ele_id;
- if ( aIndex < bIndex ) {
- return -1;
- }
- else if ( aIndex == bIndex ) {
- // Same element. Compare positions.
- if ( m_iPos < other.m_iPos ) {
- return -1;
- }
- else if ( m_iPos == other.m_iPos ) {
- if ( bAIsBreak < bBIsBreak ) {
- return -1;
- }
- else if ( bAIsBreak == bBIsBreak ) {
- return 0;
- }
- else {
- return 1;
- }
- }
- else {
- return 1;
- }
- }
- else {
- return 1;
- }
- }
-
- XP_Bool CEditInsertPoint::IsDenormalizedVersionOf(const CEditInsertPoint& other){
- return other.m_iPos == 0 &&
- m_iPos == m_pElement->GetLen() &&
- m_pElement->NextLeaf() == other.m_pElement;
- }
-
- XP_Bool CEditInsertPoint::IsStartOfElement() {
- return m_iPos <= 0;
- }
-
- XP_Bool CEditInsertPoint::IsEndOfElement() {
- return m_iPos >= m_pElement->GetLen();
- }
-
- XP_Bool CEditInsertPoint::IsStartOfContainer() {
- return IsStartOfElement()
- && m_pElement->PreviousLeafInContainer() == NULL;
- }
-
- XP_Bool CEditInsertPoint::IsEndOfContainer() {
- return IsEndOfElement()
- && m_pElement->LeafInContainerAfter() == NULL;
- }
-
- XP_Bool CEditInsertPoint::IsStartOfDocument(){
- return IsStartOfElement() &&
- m_pElement->PreviousLeaf() == NULL;
- }
-
- XP_Bool CEditInsertPoint::IsEndOfDocument(){
- return m_pElement->IsEndOfDocument();
- }
-
- XP_Bool CEditInsertPoint::GapWithBothSidesAllowed(){
- XP_Bool bResult = FALSE;
- XP_Bool bAllowBothSidesOfGap = m_pElement->AllowBothSidesOfGap();
- if ( bAllowBothSidesOfGap
- && IsEndOfElement()
- && !IsEndOfContainer() ) {
- bResult = TRUE;
- }
- else if ( IsStartOfElement() && ! IsStartOfContainer() ) {
- if ( bAllowBothSidesOfGap ) {
- bResult = TRUE;
- }
- else {
- CEditLeafElement* pPrev = m_pElement->PreviousLeaf();
- if ( pPrev && pPrev->AllowBothSidesOfGap() ) {
- bResult = TRUE;
- }
- }
- }
- return bResult;
- }
-
- XP_Bool CEditInsertPoint::IsLineBreak(){
- return IsHardLineBreak() || IsSoftLineBreak();
- }
-
- XP_Bool CEditInsertPoint::IsSoftLineBreak(){
- XP_Bool result = FALSE;
- CEditTextElement* pText = CEditTextElement::Cast(m_pElement);
- if ( pText ){
- int iOffset;
- LO_Element* pLOElement;
- if ( pText->GetLOElementAndOffset(m_iPos, m_bStickyAfter,
- pLOElement, iOffset) ){
- if ( pLOElement->type == LO_LINEFEED ){
- result = TRUE;
- }
- }
- }
- return result;
- }
-
- XP_Bool CEditInsertPoint::IsHardLineBreak(){
- return IsStartOfElement() && m_pElement->CausesBreakBefore()
- || IsEndOfElement() && m_pElement->CausesBreakAfter();
- }
-
- XP_Bool CEditInsertPoint::IsSpace() {
- XP_Bool result = FALSE;
- if ( m_pElement->IsA(P_TEXT) ) {
- if ( m_iPos == m_pElement->GetLen() ){
- CEditLeafElement *pNext = m_pElement->TextInContainerAfter();
- if( pNext
- && pNext->IsA(P_TEXT)
- && pNext->Text()->GetLen() != 0
- && pNext->Text()->GetText()[0] == ' ') {
- result = TRUE;
- }
- }
- else if ( m_pElement->Text()->GetText()[m_iPos] == ' ' ) {
- result = TRUE;
- }
- }
- return result;
- }
-
- XP_Bool CEditInsertPoint::IsSpaceBeforeOrAfter() {
- XP_Bool result = IsSpace();
- if ( !result ) {
- CEditInsertPoint before = PreviousPosition();
- if ( before != *this ) {
- result = before.IsSpace();
- }
- }
- return result;
- }
-
- CEditInsertPoint CEditInsertPoint::NextPosition(){
- CEditInsertPoint result;
- m_pElement->NextPosition(m_iPos, result.m_pElement, result.m_iPos);
- return result;
- }
-
- CEditInsertPoint CEditInsertPoint::PreviousPosition(){
- CEditInsertPoint result;
- m_pElement->PrevPosition(m_iPos, result.m_pElement, result.m_iPos);
- // Work around what is probably a bug in PrevPosition.
- if ( m_iPos == 0 && result.m_iPos == result.m_pElement->GetLen() ) {
- result.m_pElement->PrevPosition(result.m_iPos, result.m_pElement, result.m_iPos);
- }
- return result;
- }
-
- #ifdef DEBUG
- void CEditInsertPoint::Print(IStreamOut& stream) {
- stream.Printf("0x%08lx.%d%s", m_pElement, m_iPos, m_bStickyAfter ? "+" : "" );
- }
- #endif
-
-
-
- // CEditSelection
-
- CEditSelection::CEditSelection(){
- m_bFromStart = FALSE;
- }
-
- CEditSelection::CEditSelection(CEditElement* pStart, intn iStartPos,
- CEditElement* pEnd, intn iEndPos, XP_Bool fromStart)
- : m_start(pStart, iStartPos), m_end(pEnd, iEndPos), m_bFromStart(fromStart)
- {
- }
-
- CEditSelection::CEditSelection(const CEditInsertPoint& start,
- const CEditInsertPoint& end, XP_Bool fromStart)
- : m_start(start), m_end(end), m_bFromStart(fromStart)
- {
- }
-
- XP_Bool CEditSelection::operator==(const CEditSelection& other ){
- return m_start == other.m_start &&
- m_end == other.m_end && m_bFromStart == other.m_bFromStart;
- }
-
- XP_Bool CEditSelection::operator!=(const CEditSelection& other ){
- return ! (*this == other);
- }
-
- XP_Bool CEditSelection::EqualRange(CEditSelection& other){
- return m_start == other.m_start && m_end == other.m_end;
- }
-
- XP_Bool CEditSelection::IsInsertPoint() {
- /* It's an insert point if the two edges are equal, OR if the
- * start is at the end of an element, and the
- * end is at the start of an element, and
- * the two elements are next to each other,
- * and they're in the same container. (Whew!)
- */
- return m_start == m_end ||
- ( m_start.IsEndOfElement() &&
- m_end.IsStartOfElement() &&
- m_start.m_pElement->LeafInContainerAfter() == m_end.m_pElement
- );
- }
-
- CEditInsertPoint* CEditSelection::GetEdge(XP_Bool bEnd){
- if ( bEnd ) return &m_end;
- else return &m_start;
- }
-
- CEditInsertPoint* CEditSelection::GetActiveEdge(){
- return GetEdge(!m_bFromStart);
- }
-
- CEditInsertPoint* CEditSelection::GetAnchorEdge(){
- return GetEdge(m_bFromStart);
- }
-
- XP_Bool CEditSelection::Intersects(CEditSelection& other) {
- return m_start < other.m_end && other.m_start < m_end;
- }
-
- XP_Bool CEditSelection::Contains(CEditInsertPoint& point) {
- return m_start <= point && point < m_end;
- }
-
- XP_Bool CEditSelection::Contains(CEditSelection& other) {
- return ContainsStart(other) && other.m_end <= m_end;
- }
-
- XP_Bool CEditSelection::ContainsStart(CEditSelection& other) {
- return Contains(other.m_start);
- }
-
- XP_Bool CEditSelection::ContainsEnd(CEditSelection& other) {
- return Contains(other.m_end) || other.m_end == m_end;
- }
-
- XP_Bool CEditSelection::ContainsEdge(CEditSelection& other, XP_Bool bEnd){
- if ( bEnd )
- return ContainsEnd(other);
- else
- return ContainsStart(other);
- }
-
- XP_Bool CEditSelection::CrossesOver(CEditSelection& other) {
- XP_Bool bContainsStart = ContainsStart(other);
- XP_Bool bContainsEnd = ContainsEnd(other);
- return bContainsStart ^ bContainsEnd;
- }
-
- XP_Bool CEditSelection::ClipTo(CEditSelection& other) {
- // True if the result is defined. No change to this if it isn't
- XP_Bool intersects = Intersects(other);
- if ( intersects ) {
- if ( m_start < other.m_start ) {
- m_start = other.m_start;
- }
- if ( other.m_end < m_end ) {
- m_end = other.m_end;
- }
- }
- return intersects;
- }
-
- CEditElement* CEditSelection::GetCommonAncestor(){
- return m_start.m_pElement->GetCommonAncestor(m_end.m_pElement);
- }
-
- XP_Bool CEditSelection::CrossesSubDocBoundary(){
- // The intent of this method is "If this selection were cut, would the
- // document become malformed?"
-
- // A document could be malformed if the selection crosses the table
- // boundary, or if it would leave a table without it's protective
- // buffer of containers.
-
- XP_Bool result = FALSE;
- if ( ! IsInsertPoint() ){
- CEditElement* pStartCell = m_start.m_pElement->GetSubDocOrLayerSkipRoot();
- CEditElement* pEndCell = m_end.m_pElement->GetSubDocOrLayerSkipRoot();
- CEditElement* pClosedEndCell = GetClosedEndContainer()->GetSubDocOrLayerSkipRoot();
- result = pStartCell != pEndCell || pStartCell != pClosedEndCell;
- if ( result ) {
- // This is only OK if the selection spans an entire table.
- Bool bStartBad = FALSE;
- Bool bEndBad = FALSE;
- if ( pStartCell ) {
- CEditSelection all;
- pStartCell->GetTableOrLayerIgnoreSubdoc()->GetAll(all);
- bStartBad = ! Contains(all);
- }
-
- if ( pEndCell ) {
- CEditSelection all;
- pEndCell->GetTableOrLayerIgnoreSubdoc()->GetAll(all);
- bEndBad = ! Contains(all);
- }
- result = bStartBad || bEndBad;
- }
- else if ( pStartCell && pEndCell != pClosedEndCell ) {
- // If the selection spans an entire cell, but not an entire table, that's bad
- CEditSelection all;
- pStartCell->GetTableOrLayerIgnoreSubdoc()->GetAll(all);
- result = *this != all;
- }
- else {
- // One further check: If the selection starts at the start of
- // a paragraph, and the selection ends at the end of a paragraph
- // and the previous item is a table, and the
- // next item is not a container, then we can't cut. The reason is
- // that tables need to have containers after them.
-
- // Note that m_end is one more than is selected.
- if ( m_start.IsStartOfContainer() &&
- m_end.IsStartOfContainer() ) {
- // The selection spans whole containers.
- CEditContainerElement* pStartContainer = GetStartContainer();
- CEditElement* pPreviousSib = pStartContainer->GetPreviousSibling();
-
- if ( pPreviousSib && pPreviousSib->IsTable() ) {
- CEditContainerElement* pEndContainer = GetClosedEndContainer();
- CEditElement* pNextSib = pEndContainer->GetNextSibling();
- if ( !pNextSib || pNextSib->IsEndContainer() || pNextSib->IsTable() ) {
- result = TRUE;
- }
- }
- }
- }
- }
- return result;
- }
-
- CEditSubDocElement* CEditSelection::GetEffectiveSubDoc(XP_Bool bEnd){
- CEditInsertPoint* pEdge = GetEdge(bEnd);
- CEditSubDocElement* pSubDoc = pEdge->m_pElement->GetSubDoc();
- while ( pSubDoc ) {
- // If the edge is actually the edge of a subdoc, skip out of the subdoc.
- CEditSelection wholeSubDoc;
- pSubDoc->GetAll(wholeSubDoc);
- // If this is a wholeSubDoc Selection, bump up
- if ( *this != wholeSubDoc ) {
- if ( *pEdge != *wholeSubDoc.GetEdge(bEnd) )
- break;
- // If the other end of the selection is is in this same subdoc, stop
- if ( wholeSubDoc.ContainsEdge(*this, !bEnd) )
- break;
- }
- CEditElement* pSubDocParent = pSubDoc->GetParent();
- if ( !pSubDocParent )
- break;
- CEditSubDocElement* pParentSubDoc = pSubDocParent->GetSubDoc();
- if ( ! pParentSubDoc )
- break;
- pSubDoc = pParentSubDoc;
- }
- return pSubDoc;
- }
-
- XP_Bool CEditSelection::ExpandToNotCrossStructures(){
- XP_Bool bChanged = FALSE;
- if ( ! IsInsertPoint() ){
- CEditElement* pGrandfatherStart = m_start.m_pElement->GetParent()->GetParent();
- CEditElement* pGrandfatherEnd;
- CEditElement* pEffectiveEndContianer;
- if ( m_end.IsEndOfDocument() || EndsAtStartOfContainer()) {
- pEffectiveEndContianer = m_end.m_pElement->PreviousLeaf()->GetParent();
- }
- else {
- pEffectiveEndContianer = m_end.m_pElement->GetParent();
- }
- pGrandfatherEnd = pEffectiveEndContianer->GetParent();
- if ( pGrandfatherStart != pGrandfatherEnd ){
- bChanged = TRUE;
- CEditElement* pAncestor = pGrandfatherStart->GetCommonAncestor(pGrandfatherEnd);
- if ( ! pAncestor ) {
- XP_ASSERT(FALSE);
- return FALSE;
- }
- // If we're in a table, we need to return the whole table.
- if ( pAncestor->IsTableRow() ) {
- pAncestor = pAncestor->GetTable();
- if ( ! pAncestor ) {
- XP_ASSERT(FALSE);
- return FALSE;
- }
- }
- if ( pAncestor->IsTable() ) {
- pAncestor->GetAll(*this);
- return TRUE;
- }
- CEditLeafElement* pCleanStart = pAncestor->GetChildContaining(m_start.m_pElement)->GetFirstMostChild()->Leaf();
- CEditLeafElement* pCleanEnd = pAncestor->GetChildContaining(pEffectiveEndContianer)->GetLastMostChild()->NextLeaf();
- m_start.m_pElement = pCleanStart;
- m_start.m_iPos = 0;
- if ( pCleanEnd ) {
- m_end.m_pElement = pCleanEnd;
- m_end.m_iPos = 0;
- }
- else {
- XP_ASSERT(FALSE); // Somehow we've lost the end of the document element.
- pCleanEnd = m_end.m_pElement->GetParent()->GetLastMostChild()->Leaf();
- m_end.m_pElement = pCleanEnd;
- m_end.m_iPos = pCleanEnd->Leaf()->GetLen();
- }
- }
- }
- return bChanged;
- }
-
- void CEditSelection::ExpandToBeCutable(){
- // Very similar to ExpandToNotCrossDocumentStructures, except that
- // the result is always Cutable.
- if ( ! IsInsertPoint() ){
- CEditElement* pGrandfatherStart = m_start.m_pElement->GetParent()->GetParent();
- CEditElement* pGrandfatherEnd;
- CEditElement* pEffectiveEndContianer;
- if ( m_end.IsEndOfDocument()) {
- pEffectiveEndContianer = m_end.m_pElement->PreviousLeaf()->GetParent();
- }
- else {
- pEffectiveEndContianer = m_end.m_pElement->GetParent();
- }
- pGrandfatherEnd = pEffectiveEndContianer->GetParent();
- if ( pGrandfatherStart != pGrandfatherEnd ){
- CEditElement* pAncestor = pGrandfatherStart->GetCommonAncestor(pGrandfatherEnd);
- if ( ! pAncestor ) {
- XP_ASSERT(FALSE);
- return;
- }
- // If we're in a table, we need to return the whole table.
- if ( pAncestor->IsTableRow() ) {
- pAncestor = pAncestor->GetTable();
- if ( ! pAncestor ) {
- XP_ASSERT(FALSE);
- return;
- }
- }
- if ( pAncestor->IsTable() ) {
- pAncestor->GetAll(*this);
- return;
- }
- CEditLeafElement* pCleanStart = pAncestor->GetChildContaining(m_start.m_pElement)->GetFirstMostChild()->Leaf();
- CEditLeafElement* pCleanEnd = pAncestor->GetChildContaining(pEffectiveEndContianer)->GetLastMostChild()->NextLeaf();
- m_start.m_pElement = pCleanStart;
- m_start.m_iPos = 0;
- if ( pCleanEnd ) {
- m_end.m_pElement = pCleanEnd;
- m_end.m_iPos = 0;
- }
- else {
- XP_ASSERT(FALSE); // Somehow we've lost the end of the document element.
- pCleanEnd = m_end.m_pElement->GetParent()->GetLastMostChild()->Leaf();
- m_end.m_pElement = pCleanEnd;
- m_end.m_iPos = pCleanEnd->Leaf()->GetLen();
- }
- }
- }
- }
-
- void CEditSelection::ExpandToIncludeFragileSpaces() {
- // Expand the selection to include spaces that will be
- // trimmed if we did a cut of the original selection.
- if ( ! IsInsertPoint() ){
- CEditInsertPoint before = m_start.PreviousPosition();
- // Either we backed up one position, or we hit the beginning
- // of the document.
- if ( before == m_start || before.IsSpace() ) {
- if ( m_end.IsSpace() ) {
- if ( ! m_end.m_pElement->InFormattedText() ) {
- m_end = m_end.NextPosition();
- }
- }
- }
- }
- }
-
- void CEditSelection::ExpandToEncloseWholeContainers(){
- XP_Bool bWasInsertPoint = IsInsertPoint();
- CEditLeafElement* pCleanStart = m_start.m_pElement->GetParent()->GetFirstMostChild()->Leaf();
- m_start.m_pElement = pCleanStart;
- m_start.m_iPos = 0;
- if ( !m_end.IsStartOfContainer() || bWasInsertPoint ) {
- CEditLeafElement* pCleanEnd = m_end.m_pElement->GetParent()->GetLastMostChild()->NextLeaf();
- if ( pCleanEnd ) {
- m_end.m_pElement = pCleanEnd;
- m_end.m_iPos = 0;
- }
- else {
- XP_ASSERT(FALSE); // Somehow we've lost the end of the document element.
- pCleanEnd = m_end.m_pElement->GetParent()->GetLastMostChild()->Leaf();
- m_end.m_pElement = pCleanEnd;
- m_end.m_iPos = pCleanEnd->Leaf()->GetLen();
- }
- }
- }
-
-
- XP_Bool CEditSelection::EndsAtStartOfContainer() {
- return m_end.IsStartOfContainer();
- }
-
- XP_Bool CEditSelection::StartsAtEndOfContainer() {
- return m_start.IsEndOfContainer();
- }
-
- XP_Bool CEditSelection::AnyLeavesSelected(){
- // FALSE if insert point or container end.
- return ! (IsInsertPoint() || IsContainerEnd());
- }
-
- XP_Bool CEditSelection::IsContainerEnd(){
- XP_Bool result = FALSE;
- if ( ! IsInsertPoint() && EndsAtStartOfContainer()
- && StartsAtEndOfContainer() ) {
- CEditContainerElement* pStartContainer = m_start.m_pElement->FindContainer();
- CEditContainerElement* pEndContainer = m_end.m_pElement->FindContainer();
- if ( pStartContainer && pEndContainer ) {
- CEditContainerElement* pNextContainer =
- CEditContainerElement::Cast(pStartContainer->FindNextElement(&CEditElement::FindContainer, 0));
- if ( pNextContainer == pEndContainer) {
- result = TRUE;
- }
- }
- }
- return result;
- }
-
- void CEditSelection::ExcludeLastDocumentContainerEnd() {
- // Useful for cut & delete, where you don't replace the final container mark
- if ( ContainsLastDocumentContainerEnd() ){
- CEditLeafElement* pEnd = m_end.m_pElement;
- pEnd = pEnd->PreviousLeaf();
- if ( pEnd ) {
- m_end.m_pElement = pEnd;
- m_end.m_iPos = pEnd->Leaf()->GetLen();
- if ( m_start > m_end ) {
- m_start = m_end;
- }
- }
- }
- }
-
- XP_Bool CEditSelection::ContainsLastDocumentContainerEnd() {
- // Useful for cut & delete, where you don't replace the final container mark
- XP_Bool bResult = FALSE;
- CEditLeafElement* pEnd = m_end.m_pElement;
- if ( pEnd && pEnd->GetElementType() == eEndElement ){
- bResult = TRUE;
- }
- return bResult;
- }
-
- CEditContainerElement* CEditSelection::GetStartContainer() {
- CEditElement* pParent = m_start.m_pElement->GetParent();
- if ( pParent && pParent->IsContainer() ) return pParent->Container();
- else return NULL;
- }
-
- CEditContainerElement* CEditSelection::GetClosedEndContainer() {
- CEditElement* pEnd = m_end.m_pElement;
- if ( m_end.IsStartOfContainer() ) {
- // Back up one
- CEditElement* pPrev = pEnd->PreviousLeaf();
- if ( pPrev ) {
- pEnd = pPrev;
- }
- else pEnd = m_start.m_pElement;
- }
- CEditElement* pParent = pEnd->GetParent();
- if ( pParent && pParent->IsContainer() ) return pParent->Container();
- else return NULL;
- }
-
- #ifdef DEBUG
- void CEditSelection::Print(IStreamOut& stream){
- stream.Printf("start ");
- m_start.Print(stream);
- stream.Printf(" end ");
- m_end.Print(stream);
- stream.Printf(" FromStart %ld", (long)m_bFromStart);
- }
- #endif
-
- // Persistent selections
- CPersistentEditInsertPoint::CPersistentEditInsertPoint()
- {
- m_index = -1;
- m_bStickyAfter = TRUE;
- }
-
- CPersistentEditInsertPoint::CPersistentEditInsertPoint(ElementIndex index)
- : m_index(index), m_bStickyAfter(TRUE)
- {}
-
- CPersistentEditInsertPoint::CPersistentEditInsertPoint(ElementIndex index, XP_Bool bStickyAfter)
- : m_index(index), m_bStickyAfter(bStickyAfter)
- {
- }
-
- XP_Bool CPersistentEditInsertPoint::operator==(const CPersistentEditInsertPoint& other ) {
- return m_index == other.m_index;
- }
-
- XP_Bool CPersistentEditInsertPoint::operator!=(const CPersistentEditInsertPoint& other ) {
- return ! (*this == other);
- }
-
- XP_Bool CPersistentEditInsertPoint::operator<(const CPersistentEditInsertPoint& other ) {
- return m_index < other.m_index;
- }
-
- XP_Bool CPersistentEditInsertPoint::operator<=(const CPersistentEditInsertPoint& other ) {
- return *this < other || *this == other;
- }
-
- XP_Bool CPersistentEditInsertPoint::operator>=(const CPersistentEditInsertPoint& other ) {
- return ! (*this < other);
- }
-
- XP_Bool CPersistentEditInsertPoint::operator>(const CPersistentEditInsertPoint& other ) {
- return ! (*this <= other);
- }
-
- #ifdef DEBUG
- void CPersistentEditInsertPoint::Print(IStreamOut& stream) {
- stream.Printf("%ld%s", (long)m_index, m_bStickyAfter ? "+" : "" );
- }
- #endif
-
- void CPersistentEditInsertPoint::ComputeDifference(
- CPersistentEditInsertPoint& other, CPersistentEditInsertPoint& delta){
- // delta = this - other;
- delta.m_index = m_index - other.m_index;
- }
-
- void CPersistentEditInsertPoint::AddRelative(
- CPersistentEditInsertPoint& delta, CPersistentEditInsertPoint& result){
- // result = this + delta;
- result.m_index = m_index + delta.m_index;
- }
-
- XP_Bool CPersistentEditInsertPoint::IsEqualUI(
- const CPersistentEditInsertPoint& other ) {
- return m_index == other.m_index && m_bStickyAfter == other.m_bStickyAfter;
- }
-
- // class CPersistentEditSelection
-
- CPersistentEditSelection::CPersistentEditSelection()
- {
- m_bFromStart = FALSE;
- }
-
- CPersistentEditSelection::CPersistentEditSelection(const CPersistentEditInsertPoint& start, const CPersistentEditInsertPoint& end)
- : m_start(start), m_end(end)
- {
- m_bFromStart = FALSE;
- }
-
- ElementIndex CPersistentEditSelection::GetCount() {
- return m_end.m_index - m_start.m_index;
- }
-
- XP_Bool CPersistentEditSelection::IsInsertPoint(){
- return m_start == m_end;
- }
-
- XP_Bool CPersistentEditSelection::operator==(const CPersistentEditSelection& other ) {
- return SelectedRangeEqual(other) && m_bFromStart == other.m_bFromStart;
- }
-
- XP_Bool CPersistentEditSelection::operator!=(const CPersistentEditSelection& other ) {
- return ! ( *this == other );
- }
-
- XP_Bool CPersistentEditSelection::SelectedRangeEqual(const CPersistentEditSelection& other ) {
- return m_start == other.m_start && m_end == other.m_end;
- }
-
- CPersistentEditInsertPoint* CPersistentEditSelection::GetEdge(XP_Bool bEnd){
- return bEnd ? &m_end : &m_start;
- }
-
- #ifdef DEBUG
- void CPersistentEditSelection::Print(IStreamOut& stream) {
- stream.Printf("start ");
- m_start.Print(stream);
- stream.Printf(" end ");
- m_end.Print(stream);
- stream.Printf(" FromStart %ld", (long)m_bFromStart);
- }
- #endif
-
- // Used for undo
- // change this by the same way that original was changed into modified.
- void CPersistentEditSelection::Map(CPersistentEditSelection& original,
- CPersistentEditSelection& modified){
- CPersistentEditSelection delta;
- CPersistentEditSelection result;
- modified.m_start.ComputeDifference(original.m_start, delta.m_start);
- modified.m_end.ComputeDifference(original.m_end, delta.m_end);
- m_start.AddRelative(delta.m_start, result.m_start);
- m_end.AddRelative(delta.m_end, result.m_end);
- *this = result;
- }
-
- //
- // Call this constructor with a maximum number, a series of bits and
- // BIT_ARRAY_END for example: CBitArray a(100, 1 ,4 9 ,7, BIT_ARRAY_END);
- //
- CBitArray::CBitArray(long n, int iFirst, ...) {
-
- m_Bits = 0;
- size = 0;
-
- int i;
-
- if( n ) {
- SetSize(n);
- }
- va_list stack;
- #ifdef OSF1
- va_start( stack, n );
- #else
- va_start( stack, iFirst );
-
- (*this)[iFirst] = 1;
- #endif
-
- while( (i = va_arg(stack,int)) != BIT_ARRAY_END ){
- (*this)[i] = 1;
- }
- }
-
- void CBitArray::SetSize(long n){
- // On Win16 we can't have a size larger that int.
- XP_ASSERT(size < (1L << (16 + 3)));
- uint8 *oldBits = m_Bits;
- m_Bits = new uint8[n/8+1];
- memset(m_Bits,0,(int) (n/8+1));
- if(oldBits){
- memcpy(m_Bits,oldBits,(int) (min(n,size)/8+1));
- delete oldBits;
- }
- size = n;
- }
-
- void CBitArray::ClearAll(){
- memset(m_Bits,0, (int) (size/8+1) );
- }
-
- /* CLM: Helper to gray UI items not allowed when inside Java Script
- * Note that the return value is FALSE if partial selection,
- * allowing the non-script text to be changed
- * Current Font Size, Color, and Character attributes will suppress
- * setting other attributes, so it is OK to call these when mixed
- */
- #ifdef USE_SCRIPT
-
- XP_Bool EDT_IsJavaScript(MWContext * pMWContext)
- {
- if(!pMWContext) return FALSE;
- XP_Bool bRetVal = FALSE;
- EDT_CharacterData * pData = EDT_GetCharacterData(pMWContext);
- if( pData) {
- bRetVal = ( (0 != (pData->mask & TF_SERVER)) &&
- (0 != (pData->values & TF_SERVER)) ) ||
- ( (0 != (pData->mask & TF_STYLE)) &&
- (0 != (pData->values & TF_STYLE)) ) ||
- ( (0 != (pData->mask & TF_SCRIPT )) &&
- (0 != (pData->values & TF_SCRIPT)) );
- EDT_FreeCharacterData(pData);
- }
- return bRetVal;
- }
-
- #else
-
- XP_Bool EDT_IsJavaScript(MWContext *)
- {
- return FALSE;
- }
-
- #endif
-
- /* Helper to use for enabling Character properties
- * (Bold, Italic, etc., but DONT use for clearing (TF_NONE)
- * or setting Java Script (Server or Client)
- * Tests for:
- * 1. Good edit buffer and not blocked because of some action,
- * 2. Caret or selection is NOT entirely within Java Script,
- * 3. Caret or selection has some text or is mixed selection
- * (thus FALSE if single non-text object is selected)
- */
- XP_Bool EDT_CanSetCharacterAttribute(MWContext * pMWContext)
- {
- if( !pMWContext || pMWContext->waitingMode || EDT_IsBlocked(pMWContext) ){
- return FALSE;
- }
- ED_ElementType type = EDT_GetCurrentElementType(pMWContext);
- return ( (type == ED_ELEMENT_TEXT || type == ED_ELEMENT_SELECTION ||
- type >= ED_ELEMENT_TABLE) && !EDT_IsJavaScript(pMWContext) );
- }
-
- // XP string defines for FontFaces
-
- extern "C" {
- #include "xpgetstr.h"
- #define WANT_ENUM_STRING_IDS
- #include "allxpstr.h"
- #undef WANT_ENUM_STRING_IDS
- }
-
- int iFontFaces[] = {
- XP_NSFONT_DEFAULT,
- XP_NSFONT_FIXED,
- XP_NSFONT_ARIAL,
- XP_NSFONT_TIMES,
- XP_NSFONT_COURIER
- };
-
- // IDs for the list of fonts written to the tags
- // MUST CORRESPOND IN NUMBER AND LOCATION TO iFontFaces!
- int iFontFaceTags[] = {
- 0, 0,
- XP_NSFONTLIST_ARIAL,
- XP_NSFONTLIST_TIMES,
- XP_NSFONTLIST_COURIER
- };
- #define ED_NSFONT_MAX ((sizeof(iFontFaceTags))/sizeof(int))
-
- // Cache the lists of font faces that we show to user
- // and list of tags (no shown to user)
- static char * pFontFaces = NULL;
- static char * pFontFaceTags = NULL;
-
- char *EDT_GetFontFaces()
- {
- if( pFontFaces ){
- return pFontFaces;
- }
- intn iSize = 512;
- int iCur = 0;
- pFontFaces = (char*)XP_ALLOC( iSize );
-
- if( !pFontFaces )
- return NULL;
-
- pFontFaces[0] = 0;
- pFontFaces[1] = 0;
-
- for( int i = 0; i < ED_NSFONT_MAX; i++ ){
- char *pFont = XP_GetString(iFontFaces[i]);
-
- if( pFont && *pFont ){
- int iLen = XP_STRLEN( pFont );
- if( iCur + iLen + 2 > iSize ){
- iSize += 512;
- pFontFaces = (char*)XP_REALLOC( pFontFaces, iSize );
-
- if( ! pFontFaces ){
- return NULL;
- }
- }
- XP_STRCPY( &pFontFaces[iCur], pFont );
- iCur += iLen+1;
- }
- }
- // Append extra '\0' at end
- pFontFaces[iCur] = 0;
-
- return pFontFaces;
- }
-
- char *EDT_GetFontFaceTags()
- {
- if( pFontFaceTags ){
- return pFontFaceTags;
- }
- intn iSize = 2024;
- pFontFaceTags = (char*)XP_ALLOC( iSize );
-
- if( !pFontFaceTags )
- return NULL;
-
- // First 2 strings are ignored - map to default proportional and fixed
- XP_STRCPY(pFontFaceTags, " ");
- XP_STRCPY(&pFontFaceTags[2], " ");
- int iCur = 4; // Start at 4th character - after above strings
- pFontFaceTags[5] = 0; // Add extra 0 in case there are no more strings
-
- for( int i = 2; i < ED_NSFONT_MAX; i++ ){
- char *pFont = XP_GetString(iFontFaceTags[i]);
-
- if( pFont && *pFont ){
- int iLen = XP_STRLEN( pFont );
- if( iCur + iLen + 2 > iSize ){
- iSize += 2024;
- pFontFaceTags = (char*)XP_REALLOC( pFontFaceTags, iSize );
-
- if( ! pFontFaceTags ){
- return NULL;
- }
- }
- XP_STRCPY( &pFontFaceTags[iCur], pFont );
- iCur += iLen+1;
- }
- }
- // Append extra '\0' at end
- pFontFaceTags[iCur] = 0;
-
- return pFontFaceTags;
- }
-
- #define EDT_CLEAR_BIT(x,tf) x &= ~tf
- #define EDT_SET_BIT(x,tf) x |= tf
-
- void EDT_SetFontFace(MWContext * pMWContext, EDT_CharacterData * pCharacterData,
- int iFontIndex, char * pFontFace )
- {
- // Must have one or the other
- if( pMWContext == NULL && pCharacterData == NULL )
- return;
- #if defined(XP_WIN) || defined(XP_OS2)
- // Windows may give us this if click off of the font combobox
- if( (long)pFontFace == -1L )
- return;
- #endif
-
- EDT_CharacterData * pData;
- XP_Bool bCanCopy;
- XP_Bool bHaveData;
-
- // Only 0 and 1 have any meaning now that XP groups are "automatic"
- if( iFontIndex < 0 || iFontIndex > 1 ){
- iFontIndex = -1;
- }
- if( pCharacterData ){
- // Use supplied structure
- pData = pCharacterData;
- bHaveData = TRUE;
- // If pointer to existing data is same as new, don't copy it
- bCanCopy = pData->pFontFace != pFontFace;
- // We will respect the TF_FONT_FACE bit in existing data,
- // but we are also interested in FIXED if we are doing
- if( pData->mask & TF_FONT_FACE ){
- EDT_SET_BIT(pData->mask, TF_FIXED);
- }
- } else {
- // No data supplied, get from current selection or at caret
- bHaveData = FALSE;
- pData = EDT_GetCharacterData(pMWContext);
- if( !pData )
- return;
- bCanCopy = TRUE;
- // Set the bit to tell that we are interested in font face
- // and fixed width
- pData->mask = TF_FONT_FACE | TF_FIXED;
- }
-
- // Remove any existing font face data if not same as new data
- if( pData->pFontFace && bCanCopy){
- XP_FREEIF(pData->pFontFace);
- }
-
- // This will force using whatever user string was supplied
- if( pFontFace ){
- // So it will be skipped in test below
- iFontIndex = -1;
- if( bCanCopy) {
- // Translate into XP font "group" if face is found in any group
- char *pTranslated = EDT_TranslateToXPFontFace(pFontFace);
- if( *pTranslated == '_' ){
- // First character may have signal for separator - skip over it
- pTranslated++;
- }
- // Detect the 1st two items -- the Default Variable and Fixed Width fonts
- if( 0 == XP_STRCMP(pTranslated, XP_GetString(iFontFaces[0])) ){
- iFontIndex = 0;
- } else if( 0 == XP_STRCMP(pTranslated, XP_GetString(iFontFaces[1])) ){
- iFontIndex = 1;
- } else {
- // Copy the font face - either same as pFontFace or the entire group if translated
- pData->pFontFace = XP_STRDUP(pTranslated);
- // Set font face tag - note that it is set
- EDT_SET_BIT(pData->values, TF_FONT_FACE);
- // We can't be fixed width if here
- EDT_CLEAR_BIT(pData->values, TF_FIXED);
- }
- }
- }
-
- if( iFontIndex == 0 || iFontIndex == 1 ){
- // No font face tag will be set
- EDT_CLEAR_BIT(pData->values, TF_FONT_FACE);
-
- if( iFontIndex == 1){
- // Fixed Width
- EDT_SET_BIT(pData->values, TF_FIXED);
- } else {
- // Default proportional font
- EDT_CLEAR_BIT(pData->values, TF_FIXED);
- }
- }
-
- if( pMWContext ){
- EDT_SetCharacterData(pMWContext, pData);
- }
- // Free only the data we obtained
- if( !bHaveData ){
- EDT_FreeCharacterData(pData);
- }
- }
-
- char * EDT_TranslateToXPFontFace( char * pFontFace )
- {
- char * pFontFaceTags = EDT_GetFontFaceTags();
- if( pFontFaceTags ){
- char * pFace = pFontFace;
- // Skip over initial separator signal
- if( *pFace == '_' ){
- pFace++;
- }
- // Skip over first two strings (each contains " ")
- char * pTag = pFontFaceTags+4;
- int iLen;
- int i = 0;
- while( (iLen = XP_STRLEN(pTag)) > 0 ) {
- char * pComma;
- char * pTagFace = pTag;
- // Scan for comma separating the next font in group
- while( (pComma = XP_STRCHR(pTagFace,',')) != 0 ){
- *pComma = '\0';
- int iFaceLen = XP_STRLEN(pTagFace);
- XP_Bool bFound = (0 == XP_STRCMP(pTagFace, pFace));
- *pComma = ',';
- if( bFound ){
- // We found the font in the list - we're done
- return pTag;
- }
- pTagFace += iFaceLen+1;
- }
- // Check one more time - either no commas found or
- // pFace is on the last font in the group
- if( 0 == XP_STRCMP(pTagFace, pFace) ){
- return pTag;
- }
-
- pTag += iLen+1;
- i++;
- }
- }
- // Return exactly what we were passed if not found in font groups
- return pFontFace;
- }
-
-
- // Cache the list of colors that we show to user
- //static char * pFontColors = NULL;
-
- // Use this array instead of pFontColor list
- // This replaces the XP_Strings colors
- uint8 NSColors[MAX_NS_COLORS][3] =
- { { 255,255,255 },
- { 204,204,204 },
- { 192,192,192 },
- { 153,153,153 },
- { 102,102,102 },
- { 51,51,51 },
- { 0,0,0 },
- { 255,204,204 },
- { 255,102,102 },
- { 255,0,0 },
- { 204,0,0 },
- { 153,0,0 },
- { 102,0,0 },
- { 51,0,0 },
- { 255,204,153 },
- { 255,204,51 },
- { 255,153,0 },
- { 255,102,0 },
- { 204,102,0 },
- { 153,51,0 },
- { 102,51,0 },
- { 255,255,153 },
- { 255,255,102 },
- { 255,204,102 },
- { 255,204,51 },
- { 204,153,51 },
- { 153,102,51 },
- { 102,51,51 },
- { 255,255,204 },
- { 255,255,153 },
- { 255,255,0 },
- { 255,204,0 },
- { 153,153,0 },
- { 102,102,0 },
- { 51,51,0 },
- { 153,255,153 },
- { 102,255,153 },
- { 51,255,51 },
- { 0,204,0 },
- { 0,153,0 },
- { 0,102,0 },
- { 0,51,0 },
- { 153,255,255 },
- { 51,255,255 },
- { 102,204,204 },
- { 0,204,204 },
- { 51,153,153 },
- { 51,102,102 },
- { 0,51,51 },
- { 204,255,255 },
- { 102,255,255 },
- { 51,204,255 },
- { 51,102,255 },
- { 51,51,255 },
- { 0,0,153 },
- { 0,0,102 },
- { 204,204,255 },
- { 153,153,204 },
- { 102,102,204 },
- { 102,51,255 },
- { 102,0,204 },
- { 51,51,153 },
- { 51,0,153 },
- { 255,204,255 },
- { 255,153,255 },
- { 204,102,204 },
- { 204,51,204 },
- { 153,51,102 },
- { 102,51,102 },
- { 51,0,51 } };
-
- void EDT_GetNSColor(intn iIndex, LO_Color * pLoColor)
- {
- if( pLoColor && iIndex < MAX_NS_COLORS )
- {
- pLoColor->red = NSColors[iIndex][0];
- pLoColor->green = NSColors[iIndex][1];
- pLoColor->blue = NSColors[iIndex][2];
- }
- }
-
- /* Return list of font colors in format: "r,g,b,ColorName" where colors for r,g,b
- * are decimal strings in range 0-255
- */
- #if defined(XP_UNIX)
- char *EDT_GetFontColors()
- {
- return NULL;
-
- #if 0
- if( pFontColors )
- return pFontColors;
-
- intn iSize = 512;
- int iCur = 0;
- pFontColors = (char*)XP_ALLOC( iSize );
-
- if( !pFontColors )
- return NULL;
-
- pFontColors[0] = 0;
- pFontColors[1] = 0;
-
- int nIDColor = XP_NSCOLOR_BASE;
- while( nIDColor < XP_NSCOLOR_END){
- char *pColor = XP_GetString(nIDColor);
-
- if( pColor && *pColor ){
- int iLen = XP_STRLEN( pColor );
- if( iCur + iLen + 2 > iSize ){
- iSize += 512;
- pFontColors = (char*)XP_REALLOC( pFontColors, iSize );
-
- if( ! pFontColors ){
- return NULL;
- }
- }
- XP_STRCPY( &pFontColors[iCur], pColor );
- iCur += iLen+1;
- }
- // Next color ID
- nIDColor++;
- }
- // Append extra '\0' at end
- pFontColors[iCur] = 0;
- return pFontColors;
- #endif
- }
- #endif
-
- char * EDT_ParseColorString(LO_Color * pLoColor, char * pColorString)
- {
- XP_ASSERT(pLoColor);
- XP_ASSERT(pColorString);
-
- char *pComma = XP_STRCHR(pColorString, ',');
- if(!pComma) return pColorString;
-
- *pComma = '\0';
- pLoColor->red = (uint8)atoi(pColorString);
- *pComma = ',';
- char *pColor = pComma+1;
-
- pComma = XP_STRCHR(pColor, ',');
- if(!pComma) return pColor;
- *pComma = '\0';
- pLoColor->green = (uint8)atoi(pColor);
- *pComma = ',';
- pColor = pComma+1;
-
- pComma = XP_STRCHR(pColor, ',');
- // If no comma found, assume color string
- // doesn't have HTML-HEX format and
- // all thats left is the blue value
- if(pComma)
- *pComma = '\0';
- pLoColor->blue = (uint8)atoi(pColor);
- if(pComma)
- {
- *pComma = ',';
- pColor = pComma+1;
- // Return rest of string, assumned to be Hex representation
- return pColor;
- }
-
- // Supply a hex translation
- static char pHexColor[16];
- XP_SPRINTF(pHexColor, "#%02X%02X%02X", pLoColor->red, pLoColor->green, pLoColor->blue);
- return pHexColor;
- }
-
- /* Scan our list of colors and return index of matching color
- * or -1 if no match found. We NEVER return 0 (default color)
- */
- int EDT_GetMatchingFontColorIndex(LO_Color * pLOColor)
- {
- for( intn i = 0; i < MAX_NS_COLORS; i++ )
- {
- if( NSColors[i][0] == pLOColor->red &&
- NSColors[i][1] == pLOColor->green &&
- NSColors[i][2] == pLOColor->blue ){
- return (i+1);
- }
- }
- return -1;
- }
-
-
- #ifdef DEBUG
-
- // Automated test routine hook
-
- const char* CEditTestManager::m_kTrigger = "$$$Test";
-
- CEditTestManager::CEditTestManager(CEditBuffer* pBuffer)
- : m_pBuffer(pBuffer),
- m_bTesting(FALSE),
- m_iTriggerIndex(0),
- m_pSaveBuffer(0),
- m_pTempFileURL(0)
- {
- #ifdef XP_WIN32
- _CrtMemCheckpoint( &m_state ); // In theorey, avoid measuring the data before we were created.
- #endif
-
- PowerOnTest();
- }
-
- void CEditTestManager::DumpMemoryDelta() {
- m_pBuffer->Trim(); // Clear out undo/redo log to simplify memory statistics.
- #ifdef XP_WIN32
- _CrtMemDumpAllObjectsSince( &m_state );
- _CrtMemCheckpoint( &m_state );
- #else
- XP_TRACE(("Not supported on this OS.\n"));
- #endif
- }
-
- XP_Bool CEditTestManager::Key(char key) {
- XP_Bool result = m_bTesting;
- if ( ! m_bTesting ){
- if ( key == m_kTrigger[m_iTriggerIndex] ) {
- m_iTriggerIndex++;
- if ( m_kTrigger[m_iTriggerIndex] == '\0' ) {
- m_bTesting = TRUE;
- XP_TRACE(("Testing on! Type # of test, or Q to quit."));
- }
- }
- else {
- m_iTriggerIndex = 0;
- }
- }
- else {
- int bQuitTesting = FALSE;
- m_bTesting = FALSE; // So when the tests type, it doesn't cause a recursion into the test code.
- intn bTestResult = -1;
- if ( key >= 'A' && key <= 'Z' ) key = key + ('a' - 'A');
- switch (key) {
- case 'q':
- bQuitTesting = TRUE;
- XP_TRACE(("Quitting test mode."));
- break;
- case 'a':
- DumpLoElements();
- break;
- case 'b':
- VerifyLoElements();
- break;
- case 'c':
- DumpDocumentContents();
- break;
- case 'd':
- DumpMemoryDelta();
- break;
- case 'g':
- GetDocTempDir();
- break;
- case '!':
- PasteINTL();
- break;
- case 'w':
- PasteINTLText();
- break;
-
- case 'x':
- CopyDocumentToBuffer();
- break;
- case 'y':
- CopyBufferToDocument();
- break;
- #ifdef EDITOR_JAVA
- case 'j':
- DumpPlugins();
- break;
- case 'k':
- PerformFirstPlugin();
- break;
- case 'l':
- PerformPluginByName();
- break;
- case 'm':
- PerformFirstEncoder();
- break;
- case 'n':
- PerformPreOpen();
- break;
- #endif
- case 's':
- SaveToTempFile();
- break;
- case 't':
- RemoveTempFile();
- break;
- case 'v':
- TestHTMLPaste();
- break;
- case '0':
- bTestResult = EveryNavigationKeyEverywhereTest();
- break;
- case '1':
- bTestResult = ArrowTest();
- break;
- case '2':
- bTestResult = BackspaceKeyTest();
- break;
- case '3':
- bTestResult = DeleteKeyTest();
- break;
- case '4':
- bTestResult = ZeroDocumentCursorTest();
- break;
- case '5':
- bTestResult = OneCharDocumentCursorTest();
- break;
- case '6':
- bTestResult = BoldTest(10); // OneDayTest(1);
- break;
- case '7':
- m_pBuffer->m_bSkipValidation = TRUE;
- bTestResult = OneDayTest(100);
- m_pBuffer->m_bSkipValidation = FALSE;
- break;
- case '8':
- bTestResult = TextFETest();
- break;
- case '?':
- XP_TRACE(("? - type this help\n"
- "Q - quit.\n"
- "a - print lo-elements.\n"
- "b - verify lo-elements.\n"
- "c - print document contents (elements, undo history, etc.)\n"
- "d - dump memory usage delta.\n"
- "g - get doc temp directory. \n"
- ));
- #ifdef EDITOR_JAVA
- XP_TRACE(("j - show Composer Plugin and Image Encoder information.\n"
- "k - run the first composer plugin.\n"
- "l - run a composer plugin by name.\n"
- "m - run the first image encoder.\n"
- "n - test the EDT_PreOpen call.\n"
- ));
- #endif
- XP_TRACE(("q - test HTML Paste Quoted.\n"
- ));
- XP_TRACE(("s - save doc to temporary file.\n"
- ));
- XP_TRACE(("t - remove saved temporary file.\n"
- ));
- XP_TRACE(("x - save document state.\n"
- "y - restore document state.\n"
- ));
- XP_TRACE((
- "0 - navigation key crash test.\n"
- "1 - arrow completeness test.\n"
- "2 - destructive backspace test.\n"
- "3 - destructive delete test.\n"
- "4 - empty document cursor test.\n"
- "5 - one character document cursor test.\n"
- "6 - one day document test - simulate editing for one whole day 1 cycle.\n"
- "7 - one day document test - simulate editing for one whole day 500 cycle.\n"
- "8 - write buffer to out.txt as plain text.\n"
- ));
- break;
- default:
- XP_TRACE(("Type ? for help, Type # of test, or Q to quit."));
- break;
- }
- if ( ! bQuitTesting )
- {
- m_bTesting = TRUE;
- }
- if ( bTestResult >= 0 ){
- XP_TRACE(("Test %s", bTestResult ? "Passed": "Failed"));
- }
- }
- return result;
- }
-
- void CEditTestManager::PowerOnTest() {
- // Test some things that have to be tested by code. This method is
- // called whenever the editor starts up in debug mode. Don't take too long.
-
- // Test that we know about all the existing tags.
- for(int i = 0; i < P_MAX; i++ ){
- EDT_TagString(i);
- }
- }
-
- void CEditTestManager::DumpLoElements() {
- lo_PrintLayout(m_pBuffer->m_pContext);
- }
-
- void CEditTestManager::VerifyLoElements() {
- lo_VerifyLayout(m_pBuffer->m_pContext);
- }
-
- void CEditTestManager::DumpDocumentContents(){
- CStreamOutMemory buffer;
- m_pBuffer->printState.Reset( &buffer, m_pBuffer );
- m_pBuffer->DebugPrintTree( m_pBuffer->m_pRoot );
- m_pBuffer->DebugPrintState(buffer);
- TraceLargeString(buffer.GetText());
- }
-
- void TraceLargeString(char* b){
- // have to dump one line at a time. XP_TRACE has a 512 char limit on Windows.
- while ( *b != '\0' ) {
- char* b2 = b;
- while ( *b2 != '\0' && *b2 != '\n'){
- b2++;
- }
- char old = *b2;
- *b2 = '\0';
- XP_TRACE(("%s", b));
- *b2 = old;
- b = b2 + 1;
- if ( old == '\0' ) break;
- }
- }
-
- void CEditTestManager::PasteINTL(){
- unsigned char testStringJIS[] = {'J','I','S',' ','[',27,'$','B',30,21,']',' ',0};
- unsigned char testStringEUC1[] = {'E','U','C',' ','[', 0xb0, 0};
- unsigned char tesrStringEUC2[] = {0xa1,']',' ',0};
- unsigned char testStringSJIS[] = {'S','J','I','S',' ','[',0x88,0x9f,']',0};
-
- MWContext* pContext = m_pBuffer->m_pContext;
- EDT_PasteQuoteBegin(pContext, TRUE);
- EDT_PasteQuoteINTL(pContext, (char*) testStringJIS, CS_JIS);
- EDT_PasteQuoteINTL(pContext, (char*) testStringEUC1, CS_EUCJP);
- EDT_PasteQuoteINTL(pContext, (char*) tesrStringEUC2, CS_EUCJP);
- EDT_PasteQuoteINTL(pContext, (char*) testStringSJIS, CS_SJIS);
- EDT_PasteQuoteEnd(pContext);
- }
-
- void CEditTestManager::PasteINTLText(){
- unsigned char testStringJIS[] = {'J','I','S',' ','[',27,'$','B',30,21,']',' ',0};
- unsigned char testStringEUC[] = {'E','U','C',' ','[', 0xb0, 0xa1,']',' ',0};
- unsigned char testStringSJIS[] = {'S','J','I','S',' ','[',0x88,0x9f,']',0};
-
- MWContext* pContext = m_pBuffer->m_pContext;
- EDT_PasteQuoteBegin(pContext, FALSE);
- EDT_PasteQuoteINTL(pContext, (char*) testStringJIS, CS_JIS);
- EDT_PasteQuoteINTL(pContext, (char*) testStringEUC, CS_EUCJP);
- EDT_PasteQuoteINTL(pContext, (char*) testStringSJIS, CS_SJIS);
- EDT_PasteQuoteEnd(pContext);
- }
-
- void CEditTestManager::CopyDocumentToBuffer(){
- if ( m_pSaveBuffer){
- delete[] m_pSaveBuffer;
- m_pSaveBuffer = 0;
- }
- m_pBuffer->WriteToBuffer(&m_pSaveBuffer, TRUE);
- XP_TRACE(("Buffer size: %d bytes", XP_STRLEN(m_pSaveBuffer)));
- }
-
- void CEditTestManager::CopyBufferToDocument(){
- if ( m_pSaveBuffer == NULL ) {
- XP_TRACE(("The save buffer is empty."));
- }
- else {
- m_pBuffer->ReadFromBuffer(m_pSaveBuffer);
- }
- }
-
- static const char* kChunkName[EDT_NA_COUNT] = {
- "character", "word", "line edge", "document", "updown"
- };
-
- XP_Bool CEditTestManager::ZeroDocumentCursorTest(){
- XP_TRACE(("ZeroDocumentCursorTest"));
- // [selection][chunk][direction][edge]
- const ElementIndex kExpectedResults[2][EDT_NA_COUNT][2][2] =
- { // no selection
- {
- {{ 0, 0}, {0, 0} }, // EDT_NA_CHARACTER
- {{ 0, 0}, {0, 0} }, // EDT_NA_WORD
- {{ 0, 0}, {0, 0} }, // EDT_NA_LINEEDGE
- {{ 0, 0}, {0, 0} }, // EDT_NA_DOCUMENT
- {{ 0, 0}, {0, 0} } // EDT_NA_UPDOWN
- },
- // selection
- {
- {{ 0, 0}, {0, 1} }, // EDT_NA_CHARACTER
- {{ 0, 0}, {0, 1} }, // EDT_NA_WORD
- {{ 0, 0}, {0, 1} }, // EDT_NA_LINEEDGE
- {{ 0, 0}, {0, 1} }, // EDT_NA_DOCUMENT
- {{ 0, 0}, {0, 1} } // EDT_NA_UPDOWN
- }
- };
-
- XP_Bool result = TRUE;
- // Clear everything from existing document
- EDT_SelectAll(m_pBuffer->m_pContext);
- EDT_DeleteChar(m_pBuffer->m_pContext);
- CPersistentEditInsertPoint zero(0,FALSE);
- // Verify the cursor does the right thing for every possible cursor
- for ( int select = 0; select < 2; select++ ) {
- for ( int chunk = 0; chunk < EDT_NA_COUNT; chunk++ ) {
- for ( int direction = 0; direction < 2; direction++ ) {
- m_pBuffer->SetInsertPoint(zero);
- m_pBuffer->NavigateChunk(select, chunk, direction);
- CPersistentEditSelection selection;
- m_pBuffer->GetSelection(selection);
- for ( int edge = 0; edge < 2; edge++ ) {
- ElementIndex expected = kExpectedResults[select][chunk][direction][edge];
- ElementIndex actual = selection.GetEdge(edge)->m_index;
- if ( expected != actual ){
- result = FALSE;
- XP_TRACE(("selection: %s chunk: %s direction: %s edge: %s. Expected %d got %d",
- select ? "TRUE" : "FALSE",
- kChunkName[chunk],
- direction ? "forward" : "back",
- edge ? "end" : "start",
- expected,
- actual));
- }
- }
- }
- }
- }
- return result;
- }
-
-
- XP_Bool CEditTestManager::OneCharDocumentCursorTest(){
- XP_TRACE(("OneCharDocumentCursorTest"));
- // [startPos][selection][chunk][direction][edge]
- const ElementIndex kExpectedResults[2][2][EDT_NA_COUNT][2][2] =
- {
- // position 0
- { // no selection
- {
- {{ 0, 0}, {1, 1} }, // EDT_NA_CHARACTER
- {{ 0, 0}, {1, 1} }, // EDT_NA_WORD
- {{ 0, 0}, {1, 1} }, // EDT_NA_LINEEDGE
- {{ 0, 0}, {1, 1} }, // EDT_NA_DOCUMENT
- {{ 0, 0}, {0, 0} } // EDT_NA_UPDOWN
- },
- // selection
- {
- {{ 0, 0}, {0, 1} }, // EDT_NA_CHARACTER
- {{ 0, 0}, {0, 1} }, // EDT_NA_WORD
- {{ 0, 0}, {0, 2} }, // EDT_NA_LINEEDGE
- {{ 0, 0}, {0, 2} }, // EDT_NA_DOCUMENT
- {{ 0, 0}, {0, 2} } // EDT_NA_UPDOWN
- }
- },
- // position 1
- { // no selection
- {
- {{ 0, 0}, {1, 1} }, // EDT_NA_CHARACTER
- {{ 0, 0}, {1, 1} }, // EDT_NA_WORD
- {{ 0, 0}, {1, 1} }, // EDT_NA_LINEEDGE
- {{ 0, 0}, {1, 1} }, // EDT_NA_DOCUMENT
- {{ 1, 1}, {1, 1} } // EDT_NA_UPDOWN
- },
- // selection
- {
- {{ 0, 1}, {1, 2} }, // EDT_NA_CHARACTER
- {{ 0, 1}, {1, 2} }, // EDT_NA_WORD
- {{ 0, 1}, {1, 2} }, // EDT_NA_LINEEDGE
- {{ 0, 1}, {1, 2} }, // EDT_NA_DOCUMENT
- {{ 0, 1}, {1, 2} } // EDT_NA_UPDOWN
- }
- }
- };
-
- XP_Bool result = TRUE;
- // Clear everything from existing document
- EDT_SelectAll(m_pBuffer->m_pContext);
- EDT_DeleteChar(m_pBuffer->m_pContext);
- m_pBuffer->InsertChar( 'X', FALSE );
- // Verify the cursor does the right thing for every possible cursor
- for ( int startPos = 0; startPos < 2; startPos++ ){
- CPersistentEditInsertPoint p(startPos,FALSE);
- for ( int select = 0; select < 2; select++ ) {
- for ( int chunk = 0; chunk < EDT_NA_COUNT; chunk++ ) {
- for ( int direction = 0; direction < 2; direction++ ) {
- m_pBuffer->SetInsertPoint(p);
- m_pBuffer->NavigateChunk(select, chunk, direction);
- CPersistentEditSelection selection;
- m_pBuffer->GetSelection(selection);
- for ( int edge = 0; edge < 2; edge++ ) {
- ElementIndex expected = kExpectedResults[startPos][select][chunk][direction][edge];
- ElementIndex actual = selection.GetEdge(edge)->m_index;
- if ( expected != actual ){
- result = FALSE;
- XP_TRACE(("position: %d selection: %s chunk: %s direction: %s edge: %s. Expected %d got %d",
- startPos,
- select ? "TRUE" : "FALSE",
- kChunkName[chunk],
- direction ? "forward" : "back",
- edge ? "end" : "start",
- expected,
- actual));
- }
- }
- }
- }
- }
- }
- return result;
- }
-
- XP_Bool CEditTestManager::OneDayTest(int32 rounds) {
- char* kTitle = "One Day Test\n";
- XP_TRACE(("%s", kTitle));
- EDT_SelectAll(m_pBuffer->m_pContext);
- EDT_DeleteChar(m_pBuffer->m_pContext);
- EDT_PasteText(m_pBuffer->m_pContext, kTitle);
- for( int32 i = 0; i < rounds; i++ ) {
- XP_TRACE(("Round %d", i));
- const char* kTestString = "All work and no play makes Jack a dull boy.\nRedrum.\n";
- char c;
- for ( int j = 0;
- (c = kTestString[j]) != '\0';
- j++ ) {
- if ( c == '\n' || c == '\r') {
- EDT_ReturnKey(m_pBuffer->m_pContext);
- }
- else {
- EDT_KeyDown(m_pBuffer->m_pContext, c,0,0);
- }
- }
- // And delete a little.
- for ( int k = 0; k < 8; k++ ) {
- EDT_DeletePreviousChar(m_pBuffer->m_pContext);
- }
- }
- XP_TRACE(("End of %s.", kTitle));
- return TRUE;
- }
-
- static void TextFETestDone(PrintSetup *setup) {
- XP_FileClose(setup->out);
- XP_TRACE(("Finished TextFETest."));
- }
-
-
- XP_Bool CEditTestManager::TextFETest() {
- PrintSetup setup;
- char *_srcName = 0;
- char *srcName = 0;
- char *srcURL = 0;
- char *destName = 0;
- XP_File destFile = 0;
- URL_Struct *srcURLS = 0;
- XP_Bool ret = FALSE;
- ED_FileError result;
-
- //// Write the edit buffer to a temporary file as HTML.
- // Get the filename of a temporary file.
- #ifdef XP_MAC
- _srcName = WH_TempName(xpFileToPost,"ns");
- #else
- _srcName = WH_TempName(xpTemporary,"ns");
- #endif
- if (!_srcName)
- goto CLEAN_UP;
-
- // Is this necessary for some Mac magic to work?
- srcName = WH_FilePlatformName(_srcName);
- if (!srcName)
- goto CLEAN_UP;
-
- srcURL = XP_PlatformFileToURL(srcName);
- if (!srcURL)
- goto CLEAN_UP;
-
- result = EDT_SaveFile(m_pBuffer->m_pContext,
- srcURL,srcURL,
- FALSE,FALSE,FALSE);
- if (result != ED_ERROR_NONE)
- goto CLEAN_UP;
- XP_TRACE(("Created %s",srcURL));
-
-
- // The converted plain text will go to "out.txt".
- destName = XP_STRDUP("out.txt");
- if (!destName)
- goto CLEAN_UP;
-
- destFile = XP_FileOpen(destName,xpFileToPost,XP_FILE_WRITE_BIN);
- if (!destFile)
- goto CLEAN_UP;
-
-
- //// Call XL_Translate text to convert src to dest, TextFETestDone will be called on
- // completion.
- srcURLS = NET_CreateURLStruct(srcURL,NET_DONT_RELOAD);
- if (!srcURLS) {
- XP_FileClose(destFile);
- goto CLEAN_UP;
- }
-
- XL_InitializeTextSetup(&setup);
- setup.url = srcURLS;
- setup.completion = TextFETestDone;
- setup.out = destFile;
-
- // Seems that passed in MWcontext is only used to copy some info when making the
- // temporary text context.
- XL_TranslateText(m_pBuffer->m_pContext,srcURLS,&setup);
- ret = TRUE;
-
-
- // Nasty, a goto.
- CLEAN_UP:
- if (_srcName)
- XP_FREE(_srcName);
- if (srcName)
- XP_FREE(srcName);
- if (srcURL)
- XP_FREE(srcURL);
- if (destName)
- XP_FREE(destName);
-
- return ret;
- }
-
- XP_Bool CEditTestManager::BoldTest(int32 rounds) {
- char* kTitle = "Bold Test\n";
- XP_TRACE(("%s", kTitle));
- EDT_SelectAll(m_pBuffer->m_pContext);
- EDT_DeleteChar(m_pBuffer->m_pContext);
- EDT_PasteText(m_pBuffer->m_pContext, kTitle);
- EDT_SelectAll(m_pBuffer->m_pContext);
- for( int32 i = 0; i < rounds; i++ ) {
- XP_TRACE(("Round %d", i));
- EDT_CharacterData* normal = EDT_GetCharacterData( m_pBuffer->m_pContext );
- EDT_CharacterData* bold = EDT_GetCharacterData( m_pBuffer->m_pContext );
- bold->mask = TF_BOLD;
- bold->values = TF_BOLD;
- EDT_SetCharacterData(m_pBuffer->m_pContext, bold);
- EDT_SetCharacterData(m_pBuffer->m_pContext, normal);
- EDT_FreeCharacterData(normal);
- EDT_FreeCharacterData(bold);
- }
- XP_TRACE(("End of %s.", kTitle));
- return TRUE;
- }
-
- XP_Bool CEditTestManager::EveryNavigationKeyEverywhereTest() {
- // Does navigation work from every position?
- XP_Bool result;
- result = NavigateChunkCrashTest() && UArrowTest(FALSE) && UArrowTest(TRUE)
- && DArrowTest(FALSE) && DArrowTest(TRUE);
- XP_TRACE(("Done.\n"));
- return result;
- }
-
- XP_Bool CEditTestManager::ArrowTest() {
- // Does the navigation move smoothly through the document?
- XP_Bool result;
- result = LArrowTest(FALSE) || LArrowTest(TRUE) || RArrowTest(FALSE)
- || RArrowTest(TRUE) || UArrowTest(TRUE) || DArrowTest(TRUE);
- #if 0
- // Too many false positives -- need to know about up/down at first/last line
- result |= UArrowTest(FALSE);
- result |= DArrowTest(FALSE);
- #endif
- XP_TRACE(("Done.\n"));
- return result;
- }
-
- void CEditTestManager::GetWholeDocumentSelection(CPersistentEditSelection& selection){
- CEditSelection wholeDocument;
- m_pBuffer->m_pRoot->GetAll(wholeDocument);
- selection = m_pBuffer->EphemeralToPersistent(wholeDocument);
- // Ignore the last 2 positions -- it's the EOF marker
- selection.m_end.m_index -= 2;
- }
-
- XP_Bool CEditTestManager::NavigateChunkCrashTest(){
- for ( int select = 0; select < 2; select++ ) {
- for ( int chunk = 0; chunk < EDT_NA_COUNT; chunk++ ) {
- for ( int direction = 0; direction < 2; direction++ ) {
- if ( !NavChunkCrashTest(select, chunk, direction) )
- return FALSE;
- }
- }
- }
- return TRUE;
- }
-
- XP_Bool CEditTestManager::NavChunkCrashTest(XP_Bool bSelect, int chunk, XP_Bool bDirection){
- XP_Bool bResult = TRUE;
- CPersistentEditSelection w;
- GetWholeDocumentSelection(w);
- CPersistentEditInsertPoint p;
- XP_TRACE(("NavChunkCrashTest bSelect = %d chunk = %d bDirection = %d\n", bSelect, chunk, bDirection));
-
- for ( p = w.m_start;
- p.m_index < w.m_end.m_index;
- p.m_index++ ) {
- m_pBuffer->SetInsertPoint(p);
- m_pBuffer->NavigateChunk(bSelect, chunk, bDirection);
- }
- return bResult;
- }
-
- XP_Bool CEditTestManager::RArrowTest(XP_Bool bSelect){
- XP_Bool result = TRUE;
- CPersistentEditSelection w;
- GetWholeDocumentSelection(w);
- CPersistentEditInsertPoint p;
- XP_TRACE(("Right Arrow%s\n", bSelect ? " with shift key" : ""));
-
- for ( p = w.m_start;
- p.m_index < w.m_end.m_index;
- p.m_index++ ) {
- m_pBuffer->SetInsertPoint(p);
- m_pBuffer->NavigateChunk(bSelect, LO_NA_CHARACTER, TRUE);
- CPersistentEditSelection s2;
- m_pBuffer->GetSelection(s2);
- if ( (bSelect == s2.IsInsertPoint()) ||
- s2.m_end.m_index != p.m_index + 1 ) {
- XP_TRACE(("%d should be %d was %d\n", p.m_index,
- p.m_index + 1, s2.m_end.m_index));
- result = FALSE;
- }
- }
- return result;
- }
-
- XP_Bool CEditTestManager::LArrowTest(XP_Bool bSelect){
- XP_Bool result = TRUE;
- CPersistentEditSelection w;
- GetWholeDocumentSelection(w);
- CPersistentEditInsertPoint p(0,TRUE);
- XP_TRACE(("Left Arrow Test%s\n", bSelect ? " with shift key" : ""));
-
- for ( p.m_index = w.m_end.m_index - 1;
- p.m_index > w.m_start.m_index;
- p.m_index-- ) {
-
- CEditSelection startSelection;
- CPersistentEditSelection s2;
-
- p.m_bStickyAfter = TRUE;
- m_pBuffer->SetInsertPoint(p);
-
- m_pBuffer->GetSelection(startSelection);
- if ( startSelection.m_start.GapWithBothSidesAllowed() && ! bSelect ) {
- // XP_TRACE(("%d - gap with both sides allowed.", p.m_index));
- // Test that SetInsertPoint did the right thing.
- m_pBuffer->GetSelection(s2);
- if ( ! s2.IsInsertPoint() || !s2.m_start.IsEqualUI(p) ) {
- XP_TRACE(("SetInsertPoint at %d should be %d.%d was %d.%d\n", p.m_index,
- p.m_index, p.m_bStickyAfter,
- s2.m_start.m_index, s2.m_start.m_bStickyAfter));
- result = FALSE;
- }
- // Test hump over soft break
- m_pBuffer->NavigateChunk(bSelect, LO_NA_CHARACTER, FALSE);
- m_pBuffer->GetSelection(s2);
- CPersistentEditInsertPoint expected = p;
- expected.m_bStickyAfter = FALSE;
- if ( ! s2.IsInsertPoint() || !s2.m_start.IsEqualUI(expected) ) {
- XP_TRACE(("gap at %d should be %d.%d was %d.%d\n", p.m_index,
- expected.m_index, expected.m_bStickyAfter,
- s2.m_start.m_index, s2.m_start.m_bStickyAfter));
- result = FALSE;
- }
- p.m_bStickyAfter = FALSE;
- m_pBuffer->SetInsertPoint(p);
- }
- m_pBuffer->NavigateChunk(bSelect, LO_NA_CHARACTER, FALSE);
- m_pBuffer->GetSelection(s2);
- if ( bSelect == s2.IsInsertPoint() ) {
- XP_TRACE(("%d Wrong type of selection. Expected %d.%d was %d.%d\n", p.m_index,
- p.m_index, p.m_bStickyAfter,
- s2.m_start.m_index, s2.m_start.m_bStickyAfter));
- result = FALSE;
- }
- else if ( s2.m_start.m_index != p.m_index - 1 ) {
- XP_TRACE(("%d wrong edge position. Should be %d.%d was %d.%d\n", p.m_index,
- p.m_index-1, p.m_bStickyAfter,
- s2.m_start.m_index, s2.m_start.m_bStickyAfter));
- result = FALSE;
- }
- }
- return result;
- }
-
- XP_Bool CEditTestManager::UArrowTest(XP_Bool bSelect){
- XP_Bool result = TRUE;
- CPersistentEditSelection w;
- GetWholeDocumentSelection(w);
- CPersistentEditInsertPoint p;
- XP_TRACE(("Up Arrow Test%s\n", bSelect ? " with shift key" : ""));
-
- for ( p = w.m_end.m_index - 1;
- p.m_index > w.m_start.m_index;
- p.m_index-- ) {
- m_pBuffer->SetInsertPoint(p);
- CPersistentEditSelection s;
- m_pBuffer->GetSelection(s);
- m_pBuffer->ClearMove();
- m_pBuffer->UpDown(bSelect, FALSE);
- CPersistentEditSelection s2;
- m_pBuffer->GetSelection(s2);
- if ( s2 == s ) {
- XP_TRACE(("%d didn't change selection\n", p.m_index));
- result = FALSE;
- }
- }
- return result;
- }
-
-
- XP_Bool CEditTestManager::DArrowTest(XP_Bool bSelect){
- XP_Bool result = TRUE;
- CPersistentEditSelection w;
- GetWholeDocumentSelection(w);
- CPersistentEditInsertPoint p;
- XP_TRACE(("Down Arrow Test%s\n", bSelect ? " with shift key" : ""));
-
- for ( p = w.m_start.m_index;
- p.m_index < w.m_end.m_index;
- p.m_index++ ) {
- m_pBuffer->SetInsertPoint(p);
- CPersistentEditSelection s;
- m_pBuffer->GetSelection(s);
- m_pBuffer->ClearMove();
- m_pBuffer->UpDown(bSelect, TRUE);
- CPersistentEditSelection s2;
- m_pBuffer->GetSelection(s2);
- if ( s2 == s ) {
- XP_TRACE(("%d didn't change selection\n", p.m_index));
- result = FALSE;
- }
- }
- return result;
- }
-
- XP_Bool CEditTestManager::BackspaceKeyTest(){
- XP_Bool result = TRUE;
- CPersistentEditSelection w;
- GetWholeDocumentSelection(w);
- CPersistentEditInsertPoint p;
- XP_TRACE(("DeleteKeyTest"));
- p = w.m_end;
- p.m_index--;
- m_pBuffer->SetInsertPoint(p);
- for ( p = w.m_start.m_index;
- p.m_index < w.m_end.m_index;
- p.m_index++ ) {
- m_pBuffer->DeletePreviousChar();
- }
- return result;
- }
-
- XP_Bool CEditTestManager::DeleteKeyTest(){
- XP_Bool result = TRUE;
- CPersistentEditSelection w;
- GetWholeDocumentSelection(w);
- CPersistentEditInsertPoint p;
- XP_TRACE(("DeleteKeyTest"));
-
- m_pBuffer->SetInsertPoint(w.m_start);
- for ( p = w.m_start.m_index;
- p.m_index < w.m_end.m_index;
- p.m_index++ ) {
- m_pBuffer->DeleteNextChar();
- }
- return result;
- }
-
- XP_Bool CEditTestManager::Backspace() {
- if ( ! m_bTesting ){
- m_iTriggerIndex--;
- if (m_iTriggerIndex < 0 ) m_iTriggerIndex = 0;
- }
- return m_bTesting;
- }
-
- XP_Bool CEditTestManager::ReturnKey() {
- if ( ! m_bTesting ){
- m_iTriggerIndex = 0;
- }
- return m_bTesting;
- }
-
- #ifdef EDITOR_JAVA
-
- void CEditTestManager::DumpPlugins(){
- XP_TRACE(("Dump Plugin database."));
- int32 numCategories = EDT_NumberOfPluginCategories();
- XP_TRACE(("EDT_NumberOfPluginCategories: %d", numCategories));
- for(int category = 0; category < numCategories; category++ ) {
- char* pcsCategoryName = EDT_GetPluginCategoryName(category);
- XP_TRACE(("EDT_GetPluginCategoryName(%d) = \"%s\"", category, pcsCategoryName));
- int plugins = EDT_NumberOfPlugins(category);
- XP_TRACE(("EDT_NumberOfPlugins(%d) = %d", category, plugins));
- for(int plugin = 0; plugin < plugins; plugin++){
- char* pcsPluginName = EDT_GetPluginName(category, plugin);
- XP_TRACE(("EDT_GetPluginName(%d, %d) = \"%s\"", category, plugin, pcsPluginName));
- char* pcsPluginMenuHelp = EDT_GetPluginMenuHelp(category, plugin);
- XP_TRACE(("EDT_GetPluginMenuHelp(%d, %d) = \"%s\"", category, plugin, pcsPluginMenuHelp));
- }
- }
- XP_TRACE(("Dump Image Encoder database."));
- int encoders = EDT_NumberOfEncoders();
- XP_TRACE(("EDT_NumberOfEncoders() = %d", encoders));
- for(int encoder = 0; encoder < encoders; encoder++){
- char* pcsEncoderName = EDT_GetEncoderName(encoder);
- XP_TRACE(("EDT_GetEncoderName(%d) = \"%s\"", encoder, pcsEncoderName));
-
- char* pcsEncoderFileExtension = EDT_GetEncoderFileExtension(encoder);
- XP_TRACE(("EDT_GetEncoderFileExtension(%d) = \"%s\"", encoder, pcsEncoderFileExtension));
-
- char* pcsEncoderFileType = EDT_GetEncoderFileType(encoder);
- XP_TRACE(("EDT_GetEncoderFileType(%d) = \"%s\"", encoder, pcsEncoderFileType));
-
- XP_TRACE(("EDT_GetEncoderNeedsQuantizedSource(%d) = \"%d\"", encoder, EDT_GetEncoderNeedsQuantizedSource(encoder)));
-
- char* pcsEncoderMenuHelp = EDT_GetEncoderMenuHelp(encoder);
- XP_TRACE(("EDT_GetEncoderMenuHelp(%d) = \"%s\"", encoder, pcsEncoderMenuHelp));
-
- }
- }
-
- #ifndef XP_OS2
- static
- #else
- extern "OPTLINK"
- #endif
- void edt_TestImageEncoderCallbackFn(EDT_ImageEncoderStatus status, void* hook) {
- XP_TRACE(("edt_TestImageEncoderCallbackFn Status: %d hook: %08x", status, hook));
- }
-
- void CEditTestManager::PerformFirstPlugin(){
- if ( EDT_NumberOfPluginCategories() <= 0 ) {
- XP_TRACE(("EDT_NumberOfPluginCategories: %d", EDT_NumberOfPluginCategories()));
- return;
- }
- if ( EDT_NumberOfPlugins(0) <= 0 ) {
- XP_TRACE(("EDT_NumberOfPlugins(0): %d", EDT_NumberOfPlugins(0)));
- return;
- }
- XP_Bool bItem = EDT_PerformPlugin(m_pBuffer->m_pContext, 0, 0, edt_TestImageEncoderCallbackFn, (void*) 0x1234);
- XP_TRACE(("EDT_PerformPlugin: returned %d\n", bItem));
- }
-
- void CEditTestManager::PerformPluginByName(){
- XP_TRACE(("Calling dummyPlugin.does.not.exist"));
- XP_Bool bResult = EDT_PerformPluginByClassName(m_pBuffer->m_pContext, "dummyPlugin.does.not.exist",
- edt_TestImageEncoderCallbackFn, (void*) 12);
- XP_TRACE(("EDT_PerformPluginByClassName returned %d\n", bResult));
- XP_TRACE(("Calling netscape.test.plugin.composer.EditRaw"));
- bResult = EDT_PerformPluginByClassName(m_pBuffer->m_pContext, "netscape.test.plugin.composer.EditRaw",
- edt_TestImageEncoderCallbackFn, (void*) 13);
- XP_TRACE(("EDT_PerformPluginByClassName returned %d\n", bResult));
- }
-
- void CEditTestManager::PerformFirstEncoder(){
- if ( EDT_NumberOfEncoders() <= 0 ) {
- XP_TRACE(("EDT_NumberOfEncoders: %d", EDT_NumberOfEncoders()));
- return;
- }
- char** ppPixels = (char**) XP_ALLOC(sizeof(char*));
- char* pPixels = (char*) XP_ALLOC(3);
- ppPixels[0] = pPixels;
- pPixels[0] = 1;
- pPixels[1] = 2;
- pPixels[2] = 3;
- XP_TRACE(("EDT_StartEncoder: starting\n"));
- XP_Bool bItem = EDT_StartEncoder(m_pBuffer->m_pContext, 0, 1, 1, ppPixels,
- "C:\\junk.txt", edt_TestImageEncoderCallbackFn, (void*) 0xfeedface);
- XP_TRACE(("EDT_StartEncoder: returned %d\n", bItem));
- XP_FREE(pPixels);
- XP_FREE(ppPixels);
- }
-
- #ifndef XP_OS2
- static
- #else
- extern "OPTLINK"
- #endif
- void edt_TestPreOpenCallbackFn(XP_Bool bUserCancled, char* pURL, void* hook) {
- XP_TRACE(("edt_TestPreOpenCallbackFn bUserCancled: %s url: %s hook: %08x", bUserCancled ? "TRUE" : "FALSE",
- pURL ? pURL : "null", hook));
- }
-
- void CEditTestManager::PerformPreOpen(){
- XP_TRACE(("Calling preOpen."));
- EDT_PreOpen(m_pBuffer->m_pContext,"http://PerformPreOpen",
- edt_TestPreOpenCallbackFn, (void*) 13);
- }
-
- #endif // EDITOR_JAVA
-
- void CEditTestManager::TestHTMLPaste(){
- EDT_PasteQuoteBegin(m_pBuffer->m_pContext, TRUE);
- EDT_PasteQuote(m_pBuffer->m_pContext, "<b>This is bold.</b>");
- EDT_PasteQuote(m_pBuffer->m_pContext, "<i>This is italic.</i>");
- EDT_PasteQuoteEnd(m_pBuffer->m_pContext);
- }
-
- void CEditTestManager::SaveToTempFile() {
- EDT_SaveToTempFile(m_pBuffer->m_pContext,(EDT_SaveToTempCallbackFn) SaveToTempFileCB,(void *)m_pBuffer->m_pContext);
- }
-
- void CEditTestManager::SaveToTempFileCB(char *pFileURL,void *hook) {
- XP_ASSERT(hook);
- MWContext *pContext = (MWContext *)hook;
- GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
-
- CEditTestManager *pManager = pEditBuffer->m_pTestManager;
- if (!pManager) {
- XP_ASSERT(0);
- return;
- }
- XP_FREEIF(pManager->m_pTempFileURL);
- if (pFileURL) {
- pManager->m_pTempFileURL = XP_STRDUP(pFileURL);
- XP_TRACE(("Wrote to temp file %s",pFileURL));
- }
- else
- {
- XP_TRACE(("Failed to write temp file."));
- }
- }
-
- void CEditTestManager::RemoveTempFile() {
- if (m_pTempFileURL) {
- XP_TRACE(("Removing file %s",m_pTempFileURL));
- EDT_RemoveTempFile(m_pBuffer->m_pContext,m_pTempFileURL);
- XP_FREEIF(m_pTempFileURL);
- }
- else {
- XP_TRACE(("No temp file has been saved"));
- }
- }
-
- void CEditTestManager::GetDocTempDir() {
- CEditCommandLog *pLog = CGlobalHistoryGroup::GetGlobalHistoryGroup()->GetLog(m_pBuffer);
- if (!pLog) {
- return;
- }
-
- char *pFile = pLog->GetDocTempDir();
- if (pFile) {
- XP_TRACE(("DocTempDir is %s",pFile));
- XP_FREE(pFile);
- }
- else {
- XP_TRACE(("No document temp dir was created."));
- }
- }
- #endif // DEBUG
-
- //-----------------------------------------------------------------------------
- // CParseState / CPrintState
- //-----------------------------------------------------------------------------
- #define PRE_BODY 0
- #define IN_BODY 1
- #define POST_BODY 2
-
- CParseState::CParseState()
- :m_bInTitle(FALSE),
- m_iDocPart(0),
- m_inJavaScript(0),
- m_baseFontSize(0),
- m_pNextText(0),
- m_pJavaScript(0),
- m_pPostBody(0){
- }
-
- XP_Bool CParseState::InBody(){
- return m_iDocPart == IN_BODY;
- }
-
- void CParseState::StartBody(){
- m_iDocPart = IN_BODY;
- }
-
- void CParseState::EndBody(){
- m_iDocPart = POST_BODY;
- }
-
- CStreamOutMemory* CParseState::GetStream(){
- if ( m_iDocPart < POST_BODY ) {
- // m_pJavaScript is mis-named. It's actually
- // a bag we hold all our unprocessed head tags in.
- if( m_pJavaScript == 0 ){
- m_pJavaScript = new CStreamOutMemory();
- }
- return m_pJavaScript;
- }
- else {
- if( m_pPostBody == 0 ){
- m_pPostBody = new CStreamOutMemory();
- }
- return m_pPostBody;
- }
- }
-
- CParseState::~CParseState() {
- Free(m_pJavaScript);
- Free(m_pPostBody);
- delete m_pNextText;
- }
-
- void CParseState::Free(CStreamOutMemory*& pStream){
- if ( pStream ) {
- // COutMemoryStreams don't delete their text.
- XP_HUGE_CHAR_PTR pData = pStream->GetText();
- if ( pData ) {
- XP_HUGE_FREE(pData);
- }
- delete pStream;
- pStream = NULL;
- }
- }
-
- void CParseState::Reset(){
- bLastWasSpace = TRUE; // at the beginning of the document
- // we should ignore leading spaces
- m_baseFontSize = 3;
- m_formatTypeStack.Reset();
- m_formatTextStack.Reset();
- m_iDocPart = 0;
- m_bInTitle = FALSE;
- m_inJavaScript = 0;
- m_pJavaScript = 0;
- delete m_pNextText;
- // force the compiler to use the non-stream constructor
- m_pNextText = new CEditTextElement((CEditElement*)0,0);
- }
-
- //-----------------------------------------------------------------------------
- // CPrintState
- //-----------------------------------------------------------------------------
- void CPrintState::Reset( IStreamOut* pOut, CEditBuffer *pBuffer ){
- m_pOut = pOut;
- m_iCharPos = 0;
- m_bTextLast = FALSE;
- m_iLevel = 0;
- m_pBuffer = pBuffer;
- m_bEncodeSelectionAsComment = FALSE;
- }
-
- void CPrintState::PrintSelectionComment(XP_Bool bEnd, XP_Bool bStickyAfter){
- if ( !bEnd ) {
- m_pBuffer->PasteHTMLHook(this);
- }
- m_pOut->Printf("<!-- %s%s -->", bEnd ? EDT_SELECTION_END_COMMENT : EDT_SELECTION_START_COMMENT,
- bStickyAfter ? "+" : "");
- }
-
- XP_Bool CPrintState::ShouldPrintSelectionComments(CEditLeafElement* pElement){
- return m_bEncodeSelectionAsComment && (
- ShouldPrintSelectionComment(pElement, FALSE)
- || ShouldPrintSelectionComment(pElement, TRUE));
- }
-
- XP_Bool CPrintState::ShouldPrintSelectionComment(CEditLeafElement* pElement, XP_Bool bEnd){
- return m_bEncodeSelectionAsComment && m_selection.GetEdge(bEnd)->m_pElement == pElement;
- }
-
- //-----------------------------------------------------------------------------
- // CEditLinkManager
- //-----------------------------------------------------------------------------
- EDT_HREFData* ED_Link::GetData(){
- EDT_HREFData* pData = EDT_NewHREFData();
- pData->pURL = XP_STRDUP( hrefStr );
- if( pExtra ){
- pData->pExtra = XP_STRDUP( pExtra );
- }
- else {
- pData->pExtra = 0;
- }
- return pData;
- }
-
- CEditLinkManager::CEditLinkManager(){
- }
-
- ED_Link* CEditLinkManager::MakeLink( char *pHREF, char *pExtra, intn iRefCount ){
-
- ED_Link *pNewLink = XP_NEW( ED_Link );
- pNewLink->iRefCount = iRefCount;
- pNewLink->pLinkManager = this;
- pNewLink->hrefStr = XP_STRDUP( pHREF );
- pNewLink->bAdjusted = FALSE;
- if( pExtra ){
- pNewLink->pExtra = XP_STRDUP( pExtra );
- }
- else {
- pNewLink->pExtra = 0;
- }
- return pNewLink;
- }
-
- void CEditLinkManager::AdjustAllLinks( char *pOldURL, char* pNewURL, ED_HREFList *badLinks ){
- int i;
- for (i = 0; i < m_links.Size(); i++ ){
- ED_Link *pLink;
- if( (pLink = m_links[i]) != 0 ){
- AdjustLink(&pLink->hrefStr,pOldURL,pNewURL,badLinks);
- }
- }
- }
-
- // Used for adjusting links, images, etc.
- // pNewBase can be NULL, the other args shouldn't be.
- //
- // Change *ppURL so that the URL will still point to the same location
- // after changing the base URL.
- // If there is no way to adjust ppURL, ppURL will not change and we add it to badLinks.
- // E.g. if ppURL relative to pOldBase points to a local file and
- // pNewBase is a remote site, we can't adjust the URL.
- void CEditLinkManager::AdjustLink(char **ppURL,char *pOldBase, char *pNewBase, ED_HREFList *badLinks){
-
- if (!ppURL || !*ppURL) {
- return;
- }
-
- if ((*ppURL)[0] == '#' || (*ppURL)[0] == '`') {
- // do nothing, but not an error.
- return;
- }
-
- // Will make url
- // absolute if the source and dest are on the same machine, just different
- // drives. If on the same drive, will make a relative URL.
- // If on different drives or different machine, leave URL alone, return FALSE.
-
- // Make absolute relative to source URL
- char *pAbsURL = NET_MakeAbsoluteURL( pOldBase, *ppURL );
- if (!pAbsURL) {
- // Add to list of bad links.
- AddHREFUnique(badLinks,*ppURL);
- return;
- }
- char *pNewURL = NULL;
-
- if( pNewBase ){
- // Try to make relative to dest URL.
- int result = NET_MakeRelativeURL( pNewBase, pAbsURL, &pNewURL );
-
- // If we can't make it relative.
- if (result != NET_URL_SAME_DIRECTORY &&
- result != NET_URL_SAME_DEVICE) {
-
- if (NET_URL_Type(pAbsURL) == FILE_TYPE_URL &&
- NET_URL_Type(pNewBase) != FILE_TYPE_URL) {
- // No point in adjusting URL or making relative, local file is not
- // visible to a remote machine. So don't change anything.
- XP_FREEIF(pAbsURL);
- XP_FREEIF(pNewURL);
-
- // Add to list of bad links.
- AddHREFUnique(badLinks,*ppURL);
- return;
- }
- // else pNewURL will be a copy of pAbsURL, so just continue.
- // I.e. we have made the URL absolute.
- }
- // result is same directory or same device.
- else if (result == NET_URL_SAME_DEVICE && (*ppURL)[0] == '/') {
- // Absolute pathing. Don't force it to be relative. It'll work in the
- // new location.
- XP_FREEIF(pAbsURL);
- XP_FREEIF(pNewURL);
- return;
- }
- // More aggressive absolute pathing. If the new relative url goes all the
- // way up to the root, just make it start from the root instead of having a
- // bunch of ../../../ Bug 50500.
- // E.g. pAbsURL = http://host/images/bob.gif,
- // pNewBase = http://host/dir1/dir2/dir3/doc.html
- // instead of setting pNewURL to
- // ../../../images/bob.gif, use
- // /images/bob.gif
- else if (result == NET_URL_SAME_DEVICE) {
- // Count sets of ../ at the beginning of pNewURL.
- int dotDotCount = 0;
- char *pSeek = pNewURL;
- while (pSeek && *pSeek && !XP_STRNCMP(pSeek,"../",3)) {
- dotDotCount++;
- pSeek +=3;
- }
-
- char *basePath = NET_ParseURL(pNewBase,GET_PATH_PART);
- if (!basePath) {
- XP_ASSERT(0);
- return;
- }
-
- /* Find location of drive separator */
- char *basePtr = (char*) XP_STRCHR(basePath, '|');
- if (!basePtr) {
- basePtr = basePath;
- // basePtr now points to first '/' in pNewBase before directories
-
- // Count number of subdirectories in pNewBase.
- int subDirCount = -1; // Don't count first slash.
- while (basePtr && *basePtr) {
- if (*basePtr == '/') {
- subDirCount++;
- }
- basePtr++;
- }
- XP_FREE(basePath);
-
- if (dotDotCount >= subDirCount && dotDotCount > 0) {
- if (dotDotCount > subDirCount) {
- // Error, Net_MakeRelativeURL added too many ../
- XP_ASSERT(0);
- }
-
- // pSeek is pointing to first char after all the ../
- char *pTemp = XP_STRDUP(pSeek - 1); // Move back to get the slash.
- XP_FREE(pNewURL);
- pNewURL = pTemp;
- }
- }
- else {
- // there is a drive separator, so this trick won't work.
- // use pNewURL as is.
- XP_FREE(basePath);
- }
- }
- } else {
- // No new base is supplied - so we just return absolute URL
- XP_FREEIF(*ppURL);
- *ppURL = pAbsURL;
- return;
- }
-
- // else pNewURL is a correct relative URL. Or an absolute URL if result == NET_URL_FAIL.
-
- XP_FREEIF( pAbsURL );
- XP_FREEIF(*ppURL);
- *ppURL = pNewURL;
- }
-
- ED_LinkId CEditLinkManager::Add( char *pHREF, char *pExtra ){
- int i = 0;
- int lastFree = -1;
- while( i < m_links.Size() ){
- ED_Link* pLink = m_links[i];
- if( pLink != 0 ){
- // need a more intelegent way of comparing HREFs
- if( XP_STRCMP( pLink->hrefStr, pHREF) == 0 ) {
- // Links the same. How about pExtra ?
- if ( (!!pExtra == !!pLink->pExtra)
- && ((pExtra &&
- XP_STRCMP( pExtra, pLink->pExtra ) == 0 )
- || pExtra == 0 ) ){
- pLink->iRefCount++;
- return pLink;
- }
- }
- }
- else {
- lastFree = i;
- }
- i++;
- }
-
- ED_Link *pNewLink = MakeLink( pHREF, pExtra );
-
- //
- // Store it.
- //
- if( lastFree != -1 ){
- m_links[lastFree] = pNewLink;
- }
- else {
- lastFree = m_links.Add( pNewLink );
- }
- pNewLink->linkOffset = lastFree;
- return pNewLink;
- }
-
- void CEditLinkManager::Free(ED_LinkId id){
- if( --id->iRefCount == 0 ){
- m_links[ id->linkOffset ] = 0;
- XP_FREEIF( id->pExtra );
- XP_FREEIF( id->hrefStr );
- XP_FREE( id );
- }
- }
-
- void CEditLinkManager::AddHREFUnique(ED_HREFList *badLinks,char *pURL) {
- for (int n = 0; n < badLinks->Size(); n++) {
- // Just comparing links for equality by string comparison.
- if (!XP_STRCMP((*badLinks)[n],pURL)) {
- // Already in list.
- return;
- }
- }
- badLinks->Add(XP_STRDUP(pURL));
- }
-
- XP_Bool EDT_SelectTableElement(MWContext *pMWContext, int32 x, int32 y,
- LO_Element *pLoElement,
- ED_HitType iHitType,
- XP_Bool bModifierKeyPressed,
- XP_Bool bExtendSelection)
- {
- GET_EDIT_BUF_OR_RETURN(pMWContext, pEditBuffer) 0;
- return pEditBuffer->SelectTableElement(x, y, pLoElement, iHitType,
- bModifierKeyPressed, bExtendSelection);
- }
-
- ED_HitType EDT_ExtendTableCellSelection(MWContext *pMWContext, int32 x, int32 y)
- {
- GET_EDIT_BUF_OR_RETURN(pMWContext, pEditBuffer) ED_HIT_NONE;
- return pEditBuffer->ExtendTableCellSelection(x, y);
- }
-
- // Dynamic Sizing Object
-
- CSizingObject::CSizingObject() :
- m_pBuffer(0),
- m_pLoElement(0),
- m_iStyle(0),
- m_iXOrigin(0),
- m_iYOrigin(0),
- m_iStartWidth(0),
- m_iStartHeight(0),
- m_iViewWidth(0),
- m_iViewHeight(0),
- m_bWidthPercent(0),
- m_bHeightPercent(0),
- m_bPercentOriginal(0),
- m_iAddCols(0),
- m_iAddRows(0)
- {
- }
-
- XP_Bool CSizingObject::Create(CEditBuffer *pBuffer,
- LO_Element *pLoElement,
- int iSizingStyle,
- int32 xVal, int32 yVal,
- XP_Bool /*bLockAspect*/, XP_Rect *pRect){
- XP_ASSERT(pBuffer);
- XP_ASSERT(pRect);
- XP_ASSERT(iSizingStyle);
- m_pBuffer = pBuffer;
- m_pLoElement = pLoElement;
- m_iStyle = iSizingStyle;
-
- if( !pLoElement )
- {
- #ifdef LAYERS
- pLoElement = LO_XYToElement(pBuffer->m_pContext, xVal, yVal, 0);
- #else
- pLoElement = LO_XYToElement(pBuffer->m_pContext, xVal, yVal);
- #endif
- }
- if( !pLoElement )
- {
- return FALSE;
- }
-
- // Get view window size for "100%" sizing
- FE_GetDocAndWindowPosition(pBuffer->m_pContext, &m_iXOrigin, &m_iYOrigin, &m_iViewWidth, &m_iViewHeight);
- if( !m_iViewWidth || !m_iViewHeight )
- {
- return FALSE;
- }
- // Get extra margin
- int32 iMarginWidth;
- int32 iMarginHeight;
- LO_GetDocumentMargins(pBuffer->m_pContext, &iMarginWidth, &iMarginHeight);
- m_iViewWidth -= 2 * iMarginWidth;
- m_iViewHeight -= 2 * iMarginHeight;
- LO_Any *pAny = &(pLoElement->lo_any);
- int32 iSelectX = pAny->x + pAny->x_offset;
- int32 iSelectY = pAny->y + pAny->y_offset;
-
- m_iParentWidth = 0;
- // Check for sizing of table cell or nested table
- if( pAny->type == LO_TABLE )
- {
- // Check for possible nested table by finding if it has a parent cell
- LO_CellStruct *pParentCell = lo_GetParentCell(m_pBuffer->m_pContext, pLoElement);
- if( pParentCell )
- {
- // Width = that of cell containing table
- m_iParentWidth = pParentCell->width;
- m_iWidthMsgID = XP_EDT_PERCENT_CELL;
- }
- iSelectX = pAny->x;
- iSelectY = pAny->y;
- }
- else if( pAny->type == LO_CELL )
- {
- //
- LO_TableStruct *pParentTable = lo_GetParentTable(m_pBuffer->m_pContext, pLoElement);
- if( pParentTable )
- {
- // Get the width usable for percent calculation (minus borders and cell spacing)
- m_iParentWidth = lo_CalcTableWidthForPercentMode(pLoElement);
- m_iWidthMsgID = XP_EDT_PERCENT_TABLE;
- }
- iSelectX = pAny->x;
- iSelectY = pAny->y;
- } else {
- // If not a table or cell,
- // select the item of interest to make it the current element
- // Select at its CENTER to avoid setting caret
- // if real X,Y is near the left or right edge
- iSelectX += pAny->width/2;
- iSelectY += pAny->height/2;
- }
-
- if( m_iParentWidth == 0 )
- {
- m_iParentWidth = m_iViewWidth;
- m_iWidthMsgID = XP_EDT_PERCENT_WINDOW;
- }
-
- //m_pBuffer->MoveAndHideCaretInTable(pLoElement);
-
- // Calculate the rect in View's coordinates;
- // ASSUMES PIXELS ONLY -- NO CONVERSION DONE
- m_Rect.left = pAny->x + pAny->x_offset - m_iXOrigin;
- m_Rect.top = pAny->y + pAny->y_offset - m_iYOrigin;
-
- // Recent default value of flag used
- // for image status string, e.g.: (% of original width)
- m_bPercentOriginal = FALSE;
-
- // Get percent-mode flag for edit element and adjust table/cell data
- switch ( m_pLoElement->type )
- {
- case LO_IMAGE:
- {
- // Get the edit element
- CEditElement * pElement = m_pLoElement->lo_any.edit_element;
- if( !pElement ) return FALSE;
-
- if( pElement->IsIcon() )
- {
- // All "unknown" tags are handled here
- pElement->GetWidth(&m_bWidthPercent, &m_iStartWidth);
- pElement->GetHeight(&m_bHeightPercent, &m_iStartHeight);
- } else if( pElement->IsImage() )
- {
- EDT_ImageData * pImageData = pElement->Image()->GetImageData();
- //pBuffer->GetImageData();
- if( pImageData )
- {
- m_bWidthPercent = pImageData->bWidthPercent;
- m_bHeightPercent = pImageData->bHeightPercent;
-
- // Save the original height and width of the image
- // if we have it
- if( pImageData->iOriginalWidth )
- {
- m_iStartWidth = pImageData->iOriginalWidth;
- m_iStartHeight = pImageData->iOriginalHeight;
- // Constrain relative to "original" dimensions
- m_bPercentOriginal = TRUE;
- }
- EDT_FreeImageData(pImageData);
- }
- // LO_ImageStruct includes border -- adjust
- m_Rect.left += ((LO_ImageStruct*)pAny)->border_width;
- m_Rect.top += ((LO_ImageStruct*)pAny)->border_width;
- }
- break;
- }
- case LO_HRULE:
- {
- // Get the edit element
- CEditElement * pElement = m_pLoElement->lo_any.edit_element;
- if( !pElement ) return FALSE;
-
- EDT_HorizRuleData * pHData = pElement->HorizRule()->GetData(); //pBuffer->GetHorizRuleData();
- if( pHData )
- {
- m_bWidthPercent = pHData->bWidthPercent;
- //Note: we will get width and "size" (height) in pixels below
- m_iStartHeight = pHData->size;
- EDT_FreeHorizRuleData(pHData);
- }
- break;
- }
- case LO_TABLE:
- {
- CEditTableElement *pTable =
- (CEditTableElement*)m_pBuffer->GetTableElementFromLO_Element( m_pLoElement, LO_TABLE );
- if( pTable )
- {
- EDT_TableData *pTableData = pTable->GetData();
- if( pTableData )
- {
- switch( iSizingStyle )
- {
- case ED_SIZE_RIGHT:
- // Use width determined by layout
- m_bWidthPercent = pTableData->bWidthPercent;
- if( m_bWidthPercent )
- {
- m_iStartWidth = (pAny->width * 100) / m_iParentWidth;
- } else {
- m_iStartWidth = pAny->width;
- }
- break;
- case ED_SIZE_BOTTOM:
- // Use Height determined by layout
- m_bHeightPercent = pTableData->bHeightPercent;
- if( m_bHeightPercent )
- {
- m_iStartHeight = (pAny->height * 100) / m_iViewHeight;
- } else {
- m_iStartHeight = pAny->height;
- }
- break;
- case ED_SIZE_ADD_COLS:
- // When adding columns, show selection only
- // around "new" columns, so rect.left = table->right
- m_Rect.left += pAny->width;
- m_Rect.right = m_Rect.left + 1;
- m_Rect.bottom = m_Rect.top + pAny->height;
- m_iStartHeight = pAny->height;
- break;
-
- case ED_SIZE_ADD_ROWS:
- // As with columns, rect is around "new" rows
- m_Rect.top += pAny->height;
- m_Rect.bottom = m_Rect.top + 1;
- m_Rect.right = m_Rect.left + pAny->width;
- m_iStartWidth = pAny->width;
- break;
- }
- EDT_FreeTableData(pTableData);
- }
- }
- break;
- }
- case LO_CELL:
- {
- CEditTableCellElement *pCell =
- (CEditTableCellElement*)m_pBuffer->GetTableElementFromLO_Element( m_pLoElement, LO_CELL );
- if( pCell )
- {
- EDT_TableCellData * pCellData = pCell->GetData(0);
- if( pCellData )
- {
- m_bWidthPercent = pCellData->bWidthPercent;
- m_bHeightPercent = pCellData->bHeightPercent;
- EDT_FreeTableCellData(pCellData);
-
- if( iSizingStyle == ED_SIZE_RIGHT )
- {
- if( m_bWidthPercent )
- {
- m_iStartWidth = (pAny->width * 100) / m_iParentWidth;
- } else {
- // Use width determined by layout
- m_iStartWidth = pAny->width; // pCellData->iWidth;
- }
- }
- else
- {
- if( m_bHeightPercent )
- {
- m_iStartHeight = (pAny->height * 100) / m_iViewHeight;
- } else {
- m_iStartHeight = pAny->height;
- }
- }
-
- // We will select the entire row or column, so get size of table
- LO_TableStruct * pLoTable = lo_GetParentTable(pBuffer->m_pContext, m_pLoElement);
- if( pLoTable )
- {
- int32 iAdjust = min(pLoTable->border_width, 4 - pLoTable->inter_cell_space);
- if( iSizingStyle == ED_SIZE_RIGHT )
- {
- // Prefered top and bottom is just inside table border
- m_Rect.top = pLoTable->y + pLoTable->y_offset - m_iYOrigin + pLoTable->border_width;
- m_Rect.bottom = m_Rect.top + pLoTable->height - 2*pLoTable->border_width;
-
- // Back off top and bottom if intercell space is too small
- if( pLoTable->inter_cell_space < 4 && iAdjust > 0 )
- {
- m_Rect.top -= iAdjust;
- m_Rect.bottom += iAdjust;
- }
- m_Rect.right = m_Rect.left + pAny->width;
- }
- else
- {
- // Prefered left and right is just inside table border
- m_Rect.left = pLoTable->x + pLoTable->x_offset - m_iXOrigin + pLoTable->border_width;
- m_Rect.right = m_Rect.left + pLoTable->width - 2*pLoTable->border_width;
-
- // Back off if intercell space is too small
- if( pLoTable->inter_cell_space < 4 && iAdjust > 0 )
- {
- m_Rect.left -= iAdjust;
- m_Rect.right += iAdjust;
- }
- m_Rect.bottom = m_Rect.top + pAny->height;
- }
- }
- }
- }
- break;
- }
- }
-
- XP_TRACE(("Start Sizing: m_iStartWidth = %d", m_iStartWidth));
-
- if( !m_bWidthPercent )
- {
- // We aren't doing percent, so set message ID for pixels
- m_iWidthMsgID = XP_EDT_PIXELS;
- }
-
- // Finish calculating object rect if not set for table sizing above
- if( iSizingStyle != ED_SIZE_ADD_COLS && iSizingStyle != ED_SIZE_ADD_ROWS &&
- m_pLoElement->type != LO_CELL )
- {
- m_Rect.right = m_Rect.left + pAny->width;
- m_Rect.bottom = m_Rect.top + pAny->height;
- }
- *pRect = m_Rect;
-
- // If we didn't set above, use current size or minimum of 1
- if( m_iStartWidth == 0 )
- {
- m_iStartWidth = max(1, pAny->width);
- }
- if( m_iStartHeight == 0 )
- {
- m_iStartHeight = max(1, pAny->height);
- }
- return TRUE;
- }
-
- #define EDT_NEW_ROW_HEIGHT 24
- #define EDT_NEW_COL_WIDTH 24
-
- PRIVATE
- void CalcAddRowRect(int32 iRows, XP_Rect *pTableRect, XP_Rect *pRect)
- {
- pRect->left = pTableRect->left + 6;
- pRect->right = pTableRect->right - 6;
- pRect->top = pTableRect->top + (iRows * EDT_NEW_ROW_HEIGHT) + 2;
- pRect->bottom = pRect->top;
- }
-
- PRIVATE
- void CalcAddColRect(int32 iCols, XP_Rect *pTableRect, XP_Rect *pRect)
- {
- pRect->top = pTableRect->top + 6;
- pRect->bottom = pTableRect->bottom - 6;
- pRect->left = pTableRect->left + (iCols * EDT_NEW_COL_WIDTH) + 2;
- pRect->right = pRect->left;
- }
-
- // Corner must be > any single side value
- #define EDT_IS_SIZING_CORNER(style) (style == ED_SIZE_TOP_LEFT || \
- style == ED_SIZE_TOP_RIGHT || \
- style == ED_SIZE_BOTTOM_LEFT || \
- style == ED_SIZE_BOTTOM_RIGHT )
-
- XP_Bool CSizingObject::GetSizingRect(int32 xVal, int32 yVal, XP_Bool bLockAspect, XP_Rect *pRect)
- {
- XP_ASSERT(pRect);
- int i;
- XP_Bool bLockAspectRatio = EDT_IS_SIZING_CORNER(m_iStyle) && bLockAspect;
-
- int32 iViewX = xVal - m_iXOrigin;
- int32 iViewY = yVal - m_iYOrigin;
-
- // Calculate the new rectangle
- // And don't allow dragging past opposite side:
- XP_Rect new_rect = m_Rect;
-
- if( m_bWidthPercent )
- {
- // In % mode, limit largest value to get 100% of width or height
- // Calc. the pixel value corresponding to just under 101% width or height,
- // so roundoff will always allow achieving 100%
- int32 iFullWidth = ((101 * m_iParentWidth) / 100) - 1;
- int32 iFullHeight = ((101 * m_iViewHeight) / 100) - 1;
-
- if( m_iStyle & ED_SIZE_TOP )
- {
- new_rect.top = min(m_Rect.bottom, max(iViewY,m_Rect.bottom-iFullHeight));
- }
- if( m_iStyle & ED_SIZE_BOTTOM )
- {
- new_rect.bottom = max(m_Rect.top, min(iViewY,m_Rect.top+iFullHeight));
- }
- if( m_iStyle & ED_SIZE_LEFT )
- {
- new_rect.left = min(m_Rect.right, max(iViewX,m_Rect.right-iFullWidth));
- }
- if( m_iStyle & ED_SIZE_RIGHT )
- {
- new_rect.right = max(m_Rect.left, iViewX); //(m_pLoElement->type == LO_CELL) ? iViewX : min(iViewX,m_Rect.left+iFullWidth));
- }
- } else {
- if( m_iStyle & ED_SIZE_TOP )
- {
- new_rect.top = min(m_Rect.bottom, iViewY);
- }
- if( m_iStyle & ED_SIZE_BOTTOM || m_iStyle == ED_SIZE_ADD_ROWS )
- {
- new_rect.bottom = max(m_Rect.top, iViewY);
- }
- if( m_iStyle & ED_SIZE_LEFT )
- {
- new_rect.left = min(m_Rect.right, iViewX);
- }
- if( m_iStyle & ED_SIZE_RIGHT || m_iStyle == ED_SIZE_ADD_COLS )
- {
- new_rect.right = max(m_Rect.left, iViewX);
- }
- }
- int iNewWidth = new_rect.right - new_rect.left;
- int iNewHeight = new_rect.bottom - new_rect.top;
-
- // When sizing both width and height,
- // fixup coordinates to lock aspect ratio
- //
- if(bLockAspectRatio)
- {
- int iLockedWidth = (iNewHeight * m_iStartWidth) / m_iStartHeight;
- int iLockedHeight = (iNewWidth * m_iStartHeight) / m_iStartWidth;
-
- if( iNewWidth < iLockedWidth )
- {
- // New width is too small to match new height - adjust
- if( m_iStyle & ED_SIZE_LEFT ){
- new_rect.left = new_rect.right - iLockedWidth;
- } else {
- new_rect.right = new_rect.left + iLockedWidth;
- }
- } else if( iNewHeight < iLockedHeight )
- {
- // New height is too small to match new width
- if( m_iStyle & ED_SIZE_TOP )
- {
- new_rect.top = new_rect.bottom - iLockedHeight;
- } else {
- new_rect.bottom = new_rect.top + iLockedHeight;
- }
- }
- }
-
- // Return new rect to caller
- *pRect = new_rect;
-
- // Check if rect is different from last rect requested
- if( new_rect.top != m_Rect.top ||
- new_rect.bottom != m_Rect.bottom ||
- new_rect.left != m_Rect.left ||
- new_rect.right != m_Rect.right )
- {
- m_Rect = new_rect;
-
- // Display status message with data for user:
- char pMsg[512] = "";
- char pPercentOfWhat[256] = "";
- int32 iWidth = m_Rect.right - m_Rect.left;
- int32 iHeight = m_Rect.bottom - m_Rect.top;
- int32 iPercent;
-
- XP_Bool bDoWidth = (m_iStyle & ED_SIZE_LEFT) || (m_iStyle & ED_SIZE_RIGHT);
- XP_Bool bDoHeight = (m_iStyle & ED_SIZE_TOP) || (m_iStyle & ED_SIZE_BOTTOM);
-
- // Show only dimension(s) for whats changing: (Width vs. Height vs both)
- // First part of status shows: "Width = xx[pixesl|%of window width]"
- // and/or similar string for Height.
- //
- if( bDoWidth )
- {
- if(m_bWidthPercent)
- {
- // Convert to % format
- iWidth = (iWidth * 100) / m_iParentWidth;
- }
- iPercent = (iWidth * 100 ) / m_iStartWidth;
-
- // "Width = x"
- PR_snprintf(pMsg, 128, XP_GetString(XP_EDT_WIDTH_EQUALS), iWidth);
- // "pixels" or "% of window"
-
- strcat(pMsg, XP_GetString(m_iWidthMsgID));
-
- // The % of original [width] and/or [height] string
- // Current logic assumes constaining aspect ratio when sizing corners,
- // so separate Width, Height percentages are not shown
- XP_STRCPY(pPercentOfWhat, XP_GetString(XP_EDT_WIDTH));
- }
- if( bDoHeight )
- {
- if(m_bHeightPercent)
- {
- iHeight = (iHeight * 100) / m_iViewHeight;
- }
- // Since corners are constrained to aspect ratio,
- // just use Width's calculation if already done
- if( !bDoWidth )
- {
- iPercent = (iHeight * 100 ) / m_iStartHeight;
- }
-
- // "Height = x"
- PR_snprintf(pMsg+XP_STRLEN(pMsg), 128,
- XP_GetString(XP_EDT_HEIGHT_EQUALS), iHeight);
- // "pixels" or "% of window"
- strcat(pMsg, XP_GetString(m_bHeightPercent ? (int)XP_EDT_PERCENT_WINDOW :
- (int)XP_EDT_PIXELS));
-
- if( bDoWidth )
- {
- strcat(pPercentOfWhat, XP_GetString(XP_EDT_AND));
- }
- strcat(pPercentOfWhat, XP_GetString(XP_EDT_HEIGHT));
- }
- if( bDoWidth || bDoHeight )
- {
- // Build string to report relative size change:
- // (% of [original|previous] [width | height | width and height])
- PR_snprintf(pMsg+XP_STRLEN(pMsg), 128,
- XP_GetString(m_bPercentOriginal ? (int)XP_EDT_PERCENT_ORIGINAL :
- (int)XP_EDT_PERCENT_PREVIOUS),
- iPercent, pPercentOfWhat);
- } else if( m_iStyle == ED_SIZE_ADD_COLS )
- {
- int iAddCols = iNewWidth / EDT_NEW_COL_WIDTH;
- PR_snprintf(pMsg, 128, XP_GetString(XP_EDT_ADD_COLUMNS), iAddCols);
- XP_Rect rect;
-
- // Erase all existing lines
- // NOTE: We can't draw/erase just the "new" line because
- // we may skip lines if mouse is moved fast, causing a mess
- for( i=1; i< m_iAddCols; i++ )
- {
- CalcAddColRect(i, &new_rect, &rect);
- FE_DisplayAddRowOrColBorder(m_pBuffer->m_pContext, &rect, TRUE);
- }
- // Draw all new lines based on new number of columns
- for( i=1; i< iAddCols; i++ )
- {
- CalcAddColRect(i, &new_rect, &rect);
- FE_DisplayAddRowOrColBorder(m_pBuffer->m_pContext, &rect, FALSE);
- }
- m_iAddCols = iAddCols;
- } else if( m_iStyle == ED_SIZE_ADD_ROWS )
- {
- int iAddRows = iNewHeight / EDT_NEW_ROW_HEIGHT;
- PR_snprintf(pMsg, 128, XP_GetString(XP_EDT_ADD_ROWS), iAddRows);
- XP_Rect rect;
-
- // Erase all existing lines
- for( i=1; i< m_iAddRows; i++ )
- {
- CalcAddRowRect(i, &new_rect, &rect);
- FE_DisplayAddRowOrColBorder(m_pBuffer->m_pContext, &rect, TRUE);
- }
- // Draw all new lines based on new number of columns
- for( i=1; i< iAddRows; i++ )
- {
- CalcAddRowRect(i, &new_rect, &rect);
- FE_DisplayAddRowOrColBorder(m_pBuffer->m_pContext, &rect, FALSE);
- }
- m_iAddRows = iAddRows;
- }
-
- FE_Progress(m_pBuffer->m_pContext, pMsg);
-
- // Indicate that rect changed
- return TRUE;
- }
- // Rect is same as last time
- return FALSE;
- }
-
- void CSizingObject::ResizeObject()
- {
- // Erase visual feedback when adding rows or columns
- EraseAddRowsOrCols();
- int32 iWidth, iWidthPixels, iHeight;
-
- // Get the element being sized (except table or cell - obtained below)
- CEditLeafElement *pElement = (CEditLeafElement*)(m_pLoElement->lo_any.edit_element);
-
- if( !(m_iStyle == ED_SIZE_ADD_ROWS || m_iStyle == ED_SIZE_ADD_COLS) )
- {
-
- iWidthPixels = m_Rect.right - m_Rect.left;
- iHeight = m_Rect.bottom - m_Rect.top;
-
- // Convert to percent if that's what we are using
- // Note that we do not change that mode when returning new size
- if( m_bWidthPercent )
- {
- iWidth = (iWidthPixels * 100) / m_iParentWidth;
- } else {
- iWidth = iWidthPixels;
- }
- if( m_bHeightPercent )
- {
- iHeight = (iHeight * 100) / m_iViewHeight;
- }
- }
-
- // Change the appropriate element's width and/or height
- switch ( m_pLoElement->type )
- {
- case LO_IMAGE:
- {
- if( pElement && pElement->IsIcon() )
- {
- // TODO: ALL "UNKNOWN" TAGS ARE HANDLED HERE
- // Only change dimension if we were sizing it
- if( !(m_iStyle & ED_SIZE_LEFT ||
- m_iStyle & ED_SIZE_RIGHT) )
- {
- iWidth = 0; // Signal to not change width...
- }
- if( !(m_iStyle & ED_SIZE_TOP ||
- m_iStyle & ED_SIZE_BOTTOM) )
- {
- iHeight = 0; // ...or height
- }
- if( iWidth > 0 || iHeight > 0 )
- {
- m_pBuffer->BeginBatchChanges(kSetUnknownTagDataCommandID);
- pElement->SetSize(m_bWidthPercent, iWidth, m_bHeightPercent, iHeight);
- m_pBuffer->EndBatchChanges();
- }
- m_pBuffer->Relayout(pElement, 0);
- } else if( pElement && pElement->IsImage() )
- {
- EDT_ImageData * pImageData = pElement->Image()->GetImageData();
- if( pImageData )
- {
-
- // Only change dimension if we were sizing it
- if( m_iStyle & ED_SIZE_TOP ||
- m_iStyle & ED_SIZE_BOTTOM )
- {
- pImageData->iHeight = iHeight;
- }
- if( m_iStyle & ED_SIZE_LEFT ||
- m_iStyle & ED_SIZE_RIGHT )
- {
- pImageData->iWidth = iWidth;
- }
- m_pBuffer->BeginBatchChanges(kSetImageDataCommandID);
- // We are not changing image URL, so third param
- // (keep-images-with-doc) shouldn't matter
- pElement->Image()->SetImageData(pImageData);
- edt_FreeImageData(pImageData);
- m_pBuffer->Relayout(pElement,0);
- m_pBuffer->EndBatchChanges();
- }
- }
- break;
- }
- case LO_HRULE:
- {
- if( pElement )
- {
- EDT_HorizRuleData * pHData = pElement->HorizRule()->GetData(); //m_pBuffer->GetHorizRuleData();
- if( pHData )
- {
- // Only change dimension if we were sizing it
- if( m_iStyle & ED_SIZE_TOP ||
- m_iStyle & ED_SIZE_BOTTOM )
- {
- pHData->size = iHeight;
- }
- if( m_iStyle & ED_SIZE_LEFT ||
- m_iStyle & ED_SIZE_RIGHT )
- {
- pHData->iWidth = iWidth;
- }
- m_pBuffer->BeginBatchChanges(kSetHorizRuleDataCommandID);
- pElement->HorizRule()->SetData(pHData);
- EDT_FreeHorizRuleData(pHData);
- m_pBuffer->Relayout(pElement,0);
- m_pBuffer->EndBatchChanges();
- }
- }
- break;
- }
- case LO_TABLE:
- {
- CEditTableElement *pTable =
- (CEditTableElement*)m_pBuffer->GetTableElementFromLO_Element( m_pLoElement, LO_TABLE );
- if( pTable )
- {
- if( m_iStyle == ED_SIZE_ADD_ROWS ||
- m_iStyle == ED_SIZE_ADD_COLS )
- {
- // Be sure caret is already in the table,
- // but don't show caret or scroll window
- m_pBuffer->MoveAndHideCaretInTable(m_pLoElement);
-
- // Move to last cell of table
- // (1ST param unused, 2nd = Forward, 3rd = NextRow index ptr
- while(m_pBuffer->NextTableCell(FALSE, TRUE, 0))
- ;
- // Note: These functions handles Begin/EndBatchChanges
- // TODO: CHANGE THIS???
- if( m_iStyle == ED_SIZE_ADD_ROWS )
- m_pBuffer->InsertTableRows(NULL, TRUE, m_iAddRows);
- else
- m_pBuffer->InsertTableColumns(NULL, TRUE, m_iAddCols);
-
- // InsertTable... will relayout
- //m_pBuffer->Relayout(pTable, 0);
- }
- else
- {
- // Sizing table width
- EDT_TableData * pTableData = pTable->GetData();
- if( pTableData && iWidth != m_iStartWidth )
- {
- pTableData->bWidthDefined = TRUE;
- pTableData->iWidth = iWidth;
- pTableData->iWidthPixels = iWidthPixels;
- m_pBuffer->BeginBatchChanges(kSetTableDataCommandID);
- pTable->SetData(pTableData);
- EDT_FreeTableData(pTableData);
- m_pBuffer->Relayout(pTable, 0);
- m_pBuffer->EndBatchChanges();
-
- XP_TRACE(("End Sizing: iWidth = %d", iWidth));
- }
- }
- }
- break;
- }
- case LO_CELL:
- {
- CEditTableCellElement *pCell =
- (CEditTableCellElement*)m_pBuffer->GetTableElementFromLO_Element( m_pLoElement, LO_CELL );
- if( pCell )
- {
- EDT_TableCellData * pCellData = pCell->GetData(0);
- if( pCellData && iWidth != m_iStartWidth )
- {
- pCellData->bWidthDefined = TRUE;
- pCellData->iWidth = iWidth;
- pCellData->iWidthPixels = iWidthPixels;
- m_pBuffer->BeginBatchChanges(kSetTableCellDataCommandID);
- pCell->SetData(pCellData);
- EDT_FreeTableCellData(pCellData);
-
- // Get change in pixels: + means we increased width
- int32 iDelta = iWidthPixels - m_pLoElement->lo_any.width;
- int32 iNewWidth;
-
- // Column sizing is complicated by the fact that first cell in column
- // may not be in the 1st row because of COLSPAN.
- // We must be sure 1st cell sharing RIGHT edge is resized as well,
- LO_TableStruct *pLoTable = lo_GetParentTable(NULL, m_pLoElement);
- LO_Element *pLoElement = (LO_Element*)pLoTable;
-
- // Stop when we reach the cell we were sizing
- while (pLoElement && pLoElement != m_pLoElement)
- {
- if( pLoElement->type == LO_CELL &&
- ((pLoElement->lo_cell.x + pLoElement->lo_cell.width) ==
- (m_pLoElement->lo_cell.x + m_pLoElement->lo_cell.width)) )
- {
- // We found a different cell in first row - get Edit element
- CEditTableCellElement *pFirstCell =
- (CEditTableCellElement*)m_pBuffer->GetTableElementFromLO_Element( pLoElement, LO_CELL );
- if( pFirstCell )
- {
- pCellData = pFirstCell->GetData(0);
- if( pCellData )
- {
- iNewWidth = pLoElement->lo_cell.width + iDelta;
- if( pCellData->bWidthPercent )
- {
- int32 iTableWidth = lo_CalcTableWidthForPercentMode(pLoElement);
- pCellData->iWidth = (iNewWidth * 100) / iTableWidth;
- } else {
- pCellData->iWidth = iNewWidth;
- }
- pCellData->iWidthPixels = iNewWidth;
-
- pCellData->bWidthDefined = TRUE;
- pFirstCell->SetData(pCellData);
- EDT_FreeTableCellData(pCellData);
- //Note: We don't need to change width in pLoElement
- // since we will relayout entire table, where new widths are determined
- }
- }
- break;
- }
- pLoElement = pLoElement->lo_any.next;
- }
-
- // Also adjust width of entire table by same amount,
- // else changing columns "fights" the user
- CEditTableElement *pTable = pCell->GetParentTable();
-
- if( pLoTable && pTable )
- {
- EDT_TableData * pTableData = pTable->GetData();
- if( pTableData )
- {
- pTableData->bWidthDefined = TRUE;
- iNewWidth = pLoTable->width + iDelta;
-
- if( pTableData->bWidthPercent )
- {
- // This may be > 100 %, but layout will redistibute sizes correctly
- // TODO: Should we warn the user and convert to "pixel" mode?
- // or just convert to pixel mode automatically?
- pTableData->iWidth = (iNewWidth * 100) / pLoTable->width;
-
- // Automatically convert to ABSOLUTE PIXELS if new % is > 100%
- if( pTableData->iWidth > 100 )
- {
- pTableData->iWidth = iNewWidth;
- pTableData->bWidthPercent = FALSE;
- }
- } else {
- pTableData->iWidth = iNewWidth;
- }
- pTableData->iWidthPixels = iNewWidth;
- pTable->SetData(pTableData);
- EDT_FreeTableData(pTableData);
- }
- }
-
- // Relayout the entire table
- m_pBuffer->Relayout(pTable, 0);
- m_pBuffer->EndBatchChanges();
- }
- }
- break;
- }
- }
- }
-
- void CSizingObject::EraseAddRowsOrCols()
- {
- int i;
- XP_Rect rect;
- if( m_iStyle == ED_SIZE_ADD_COLS )
- {
- // Erase all existing lines
- // NOTE: We can't draw/erase just the "new" line because
- // we may skip lines if mouse is moved fast, causing a mess
- for( i=1; i< m_iAddCols; i++ )
- {
- CalcAddColRect(i, &m_Rect, &rect);
- FE_DisplayAddRowOrColBorder(m_pBuffer->m_pContext, &rect, TRUE);
- }
- } else if( m_iStyle == ED_SIZE_ADD_ROWS )
- {
- // Erase all existing lines
- for( i=1; i< m_iAddRows; i++ )
- {
- CalcAddRowRect(i, &m_Rect, &rect);
- FE_DisplayAddRowOrColBorder(m_pBuffer->m_pContext, &rect, TRUE);
- }
- }
- }
-
- CSizingObject::~CSizingObject()
- {
- // Assure that next comparison to a new rect
- // will be different
- m_Rect.left = -1;
- FE_Progress(m_pBuffer->m_pContext, "");
-
- // Don't leave object in selected state
- m_pBuffer->ClearSelection(TRUE, FALSE);
- }
- ///////////////////////////////////////////////////
-
- // Relayout timer ... doesn't quite work perfectly.
-
- CRelayoutTimer::CRelayoutTimer(){
- m_pBuffer = NULL;
- }
-
- void CRelayoutTimer::SetEditBuffer(CEditBuffer* pBuffer){
- m_pBuffer = pBuffer;
- }
-
- void CRelayoutTimer::OnCallback() {
- m_pBuffer->Relayout(m_pStartElement, m_iOffset);
- }
-
- void CRelayoutTimer::Flush() {
- if (IsTimeoutEnabled() ) {
- Cancel();
- OnCallback();
- }
- }
-
- void CRelayoutTimer::Relayout( CEditElement *pStartElement, int iOffset)
- {
- const uint32 kRelayoutDelay = 50;
- XP_Bool bSetValues = TRUE;
- XP_Bool bInTable = pStartElement->GetTableIgnoreSubdoc() != NULL;
-
- if ( ! bInTable ) {
- Flush();
- m_pBuffer->Relayout(pStartElement, iOffset);
- return;
- }
- if ( IsTimeoutEnabled() ) {
- Cancel();
- if ( pStartElement != m_pStartElement ) {
- OnCallback(); // Do saved relayout now.
- }
- else {
- bSetValues = FALSE;
- }
- }
- if ( bSetValues) {
- m_pStartElement = pStartElement;
- m_iOffset = iOffset;
- }
-
- // Put the character into the LO_Element string so that the two data structures are consistent.
- if (pStartElement->IsText() ){
- CEditTextElement* pTextElement = pStartElement->Text();
- LO_TextStruct* pLoText = NULL;
- int iLoOffset = 0;
- if ( pTextElement->GetLOTextAndOffset(iOffset, FALSE, pLoText, iLoOffset) ) {
- if ( pLoText ) {
- int32 textLen = pLoText->text_len;
- char *pText;
- if (textLen <= 0 ){
- PA_FREE(pLoText->text);
- pLoText->text = (PA_Block) PA_ALLOC(2); // char plus zero terminated.
- }
- else {
- pLoText->text = (PA_Block) PA_REALLOC(pLoText->text, textLen + 2);
- }
- PA_LOCK(pText, char *, pLoText->text);
- int32 bytesToMove = textLen - iLoOffset;
- if ( bytesToMove > 0){
- XP_MEMMOVE(pText + iLoOffset +1, pText + iLoOffset, bytesToMove);
- }
- pText[iLoOffset] = pTextElement->GetText()[iOffset];
- pText[textLen+1] = '\0';
- // XP_TRACE(("pText=%08x %s %d\n", pText, pText, textLen));
- PA_UNLOCK(pLoText->text);
- textLen++;
- pLoText->text_len = (int16) textLen;
- }
- }
- }
- SetTimeout(kRelayoutDelay);
- }
-
- CAutoSaveTimer::CAutoSaveTimer() {
- m_pBuffer = NULL;
- m_iMinutes = 0;
- m_bSuspended = FALSE;
- m_bCalledWhileSuspended = FALSE;
- }
-
- void CAutoSaveTimer::SetEditBuffer(CEditBuffer* pBuffer){
- m_pBuffer = pBuffer;
- // Sanity check, is this an OK Buffer?
- XP_ASSERT(m_pBuffer->m_pRoot);
- }
-
- void CAutoSaveTimer::OnCallback() {
- if( m_bSuspended ){
- m_bCalledWhileSuspended = TRUE;
- } else {
- // Sanity check -- is this an OK Buffer?
- if ( ! m_pBuffer || ! m_pBuffer->m_pRoot ) {
- XP_ASSERT(FALSE);
- return;
- }
- // Skip autosave if currently suspended
- m_pBuffer->AutoSaveCallback();
- Restart();
- }
- }
-
- void CAutoSaveTimer::Restart() {
- #ifdef DEBUG_AUTO_SAVE
- const int32 kMillisecondsPerMinute = 6000L; //60000L; // * 1000 / 10;
- #else
- const int32 kMillisecondsPerMinute = 60000L;
- #endif
- if ( m_iMinutes > 0 ) {
- SetTimeout(m_iMinutes * kMillisecondsPerMinute);
- }
- }
-
- void CAutoSaveTimer::SetPeriod(int32 minutes){
- Cancel();
- m_iMinutes = minutes;
- Restart();
- }
-
- int32 CAutoSaveTimer::GetPeriod(){
- return m_iMinutes;
- }
-
- void CAutoSaveTimer::Suspend(){
- m_bSuspended = TRUE;
- }
-
- void CAutoSaveTimer::Resume(){
- m_bSuspended = FALSE;
- // We need to restart the timer ONLY
- // if we were called during a suspended period
- if( m_bCalledWhileSuspended ){
- m_bCalledWhileSuspended = FALSE;
- } else {
- Restart();
- }
- }
-
- CEditDocState::CEditDocState() {
- m_pBuffer = NULL;
- m_version = 0;
- }
-
- CEditDocState::~CEditDocState() {
- if (m_pBuffer) {
- XP_HUGE_FREE(m_pBuffer);
- }
- }
-
- #ifdef DEBUG
- void CEditDocState::Print(IStreamOut& stream) {
- if (!m_pBuffer) return;
-
- stream.Printf("%d bytes", XP_STRLEN(m_pBuffer));
- // have to dump one line at a time. XP_TRACE has a 512 char limit on Windows.
- char* b = m_pBuffer;
- while ( *b != '\0' ) {
- char* b2 = b;
- while ( *b2 != '\0' && *b2 != '\n'){
- b2++;
- }
- char old = *b2;
- *b2 = '\0';
- stream.Printf("%s\n", b);
- *b2 = old;
- b = b2 + 1;
- if ( old == '\0' ) break;
- }
- }
- #endif
-
-
-
- /* Take the document for current context and change appropriate
- * params to make it look like a "Untitled" new document
- * Allows loading any document as a "Template"
- */
- void EDT_ConvertCurrentDocToNewDoc(MWContext * pMWContext)
- {
- XP_ASSERT(pMWContext);
- if( !pMWContext ){
- return;
- }
- GET_WRITABLE_EDIT_BUF_OR_RETURN(pMWContext, pEditBuffer);
-
- char * pUntitled = XP_GetString(XP_EDIT_NEW_DOC_NAME);
-
- // Traverse all links and images and change URLs to absolute
- // since we will be destroying our current base doc URL
- EDT_ImageData *pImageData;
- char *pAbsolute = NULL;
- EDT_PageData *pPageData = pEditBuffer->GetPageData();
- if( !pPageData){
- return;
- }
-
- // Should be the same as pEntry->Address???
- char *pBaseURL = LO_GetBaseURL(pMWContext);
-
- // Call Java Plugin hook for pages to be closed,
- // BUT only if it really was an lockable source
- int iType = NET_URL_Type(pBaseURL);
- if( iType == FTP_TYPE_URL ||
- iType == HTTP_TYPE_URL ||
- iType == SECURE_HTTP_TYPE_URL ||
- iType == FILE_TYPE_URL ){
- EDT_PreClose(pMWContext, pBaseURL, NULL, NULL);
- }
-
- // Walk the tree and find all HREFs.
- CEditElement *pLeaf = pEditBuffer->m_pRoot->FindNextElement(
- &CEditElement::FindLeafAll,0 );
- // First sweep, mark all HREFs as not adjusted.
- while (pLeaf) {
- pEditBuffer->linkManager.SetAdjusted(pLeaf->Leaf()->GetHREF(),FALSE);
- pLeaf = pLeaf->FindNextElement(&CEditElement::FindLeafAll,0 );
- }
- // Second sweep, actually adjust the HREFs.
- pLeaf = pEditBuffer->m_pRoot->FindNextElement(
- &CEditElement::FindLeafAll,0 );
- while (pLeaf) {
- ED_LinkId linkId = pLeaf->Leaf()->GetHREF();
- if (linkId && !pEditBuffer->linkManager.GetAdjusted(linkId)) {
- pEditBuffer->linkManager.AdjustLink(linkId, pBaseURL, NULL, NULL);
- pEditBuffer->linkManager.SetAdjusted(linkId,TRUE);
- }
- pLeaf = pLeaf->FindNextElement(&CEditElement::FindLeafAll,0 );
- }
-
- // Regular images.
- CEditElement *pImage = pEditBuffer->m_pRoot->FindNextElement(
- &CEditElement::FindImage, 0 );
- while( pImage ){
- pImageData = pImage->Image()->GetImageData();
- if( pImageData ){
- if( pImageData->pSrc && *pImageData->pSrc ){
- char * pOld = XP_STRDUP(pImageData->pSrc);
- pAbsolute = NET_MakeAbsoluteURL( pBaseURL, pImageData->pSrc );
- if( pAbsolute ){
- XP_FREE(pImageData->pSrc);
- pImageData->pSrc = pAbsolute;
- }
- }
- if( pImageData->pLowSrc && *pImageData->pLowSrc){
- pAbsolute = NET_MakeAbsoluteURL( pBaseURL, pImageData->pLowSrc );
- if( pAbsolute ){
- XP_FREE(pImageData->pLowSrc);
- pImageData->pLowSrc = pAbsolute;
- }
- }
- pImage->Image()->SetImageData( pImageData );
- edt_FreeImageData( pImageData );
- }
- pImage = pImage->FindNextElement( &CEditElement::FindImage, 0 );
- }
-
- // If there is a background Image, make it absolute also
- if( pPageData->pBackgroundImage && *pPageData->pBackgroundImage){
- pAbsolute = NET_MakeAbsoluteURL( pBaseURL, pPageData->pBackgroundImage );
- if( pAbsolute ){
- XP_FREE(pPageData->pBackgroundImage);
- pPageData->pBackgroundImage = pAbsolute;
- }
- }
-
- // Change context's "title" string
- XP_FREEIF(pMWContext->title);
- pMWContext->title = NULL;
- pMWContext->is_new_document = TRUE;
-
- // Change the history entry data
- History_entry * pEntry = SHIST_GetCurrent(&(pMWContext->hist));
- if(pEntry ){
- XP_FREEIF(pEntry->address);
- pEntry->address = XP_STRDUP(pUntitled);
- XP_FREEIF(pEntry->title);
- }
- // Layout uses this as the base URL for all links and images
- LO_SetBaseURL( pMWContext, pUntitled );
-
- // Cleat the old title in page data
- XP_FREEIF(pPageData->pTitle);
-
- // This will set new background image,
- // call FE_SetDocTitle() with new "file://Untitled" string,
- // and refresh the layout of entire doc
- pEditBuffer->SetPageData(pPageData);
-
- pEditBuffer->FreePageData(pPageData);
- }
-
- char * EDT_GetFilename(char * pURL, XP_Bool bMustHaveExtension)
- {
- // No string or its empty
- if( !pURL || !*pURL ){
- return NULL;
- }
-
- // Isolate just the filename of source URL
- char * pFilename = XP_STRRCHR(pURL, '/');
-
- // Maybe its a local filename?
- if(!pFilename){
- pFilename = XP_STRRCHR(pURL, '\\');
- }
-
- // Or just after host or drive letter?
- if(!pFilename){
- pFilename = XP_STRCHR(pURL, ':');
- }
-
- if(pFilename){
- // Filename starts just after "/"
- pFilename++;
- } else {
- // Use what we have - maybe not a full URL spec?
- pFilename = pURL;
- }
- char * pResult = NULL;
-
- if( pFilename && *pFilename ){
- // Don't include any stuff after filename
- char * ques = XP_STRCHR(pFilename, '?');
- char * hash = XP_STRCHR(pFilename, '#');
- if(ques){
- *ques = '\0';
- }
- if(hash){
- *hash = '\0';
- }
-
- // Check if we must have a period to be considered a filename
- // This allow text without "." to be considered a subdirectory, not filename
- if( *pFilename ){
- if( !bMustHaveExtension ||
- (bMustHaveExtension && XP_STRCHR(pFilename, '.')) ){
- // Copy just the filename if we have one
- pResult = XP_STRDUP(pFilename);
- }
- }
-
- // set the values back
- if(ques){
- *ques = '?';
- }
- if(hash){
- *hash = '#';
- }
- }
- return pResult;
- }
-
- char * EDT_ReplaceFilename(char * pBaseURL, char * pURL, XP_Bool bMustHaveExtension)
- {
- char * pResult = NULL;
- if( !pBaseURL || !*pBaseURL ){
- return NULL;
- }
- // Find the start of filename in base -
- // copy to new string
- // **** We overload the meaning of bMustHaveExtension to
- // also cause any filename on the base to have an extension,
- // else any name without trailing slash, such as //chainsaw/mydir",
- // will be "corrected" by adding trailing slash
- if( bMustHaveExtension ){
- char * pBaseFilename = EDT_GetFilename(pBaseURL, bMustHaveExtension);
- int iLen = XP_STRLEN(pBaseURL);
- if( !pBaseFilename && pBaseURL[iLen-1] != '/' ){
- // No trailing slash found, copy string and append one
- pResult = (char*)XP_ALLOC(iLen+1);
- if( !pResult ){
- return NULL;
- }
- XP_STRCPY(pResult, pBaseURL);
- pResult[iLen] = '/';
- pResult[iLen+1] = '\0';
- }
- XP_FREEIF(pBaseFilename);
- }
- if( !pResult ){
- char * pBaseEnd = XP_STRRCHR(pBaseURL, '/');
-
- if( !pBaseEnd )
- pBaseEnd = XP_STRCHR(pBaseURL, ':');
- if( !pBaseEnd )
- return NULL;
-
- pBaseEnd++;
- char save_char = *pBaseEnd;
- *pBaseEnd = '\0';
-
- // Allocate result and copy the base part
- StrAllocCat(pResult, pBaseURL);
-
- // Restore character
- *pBaseEnd = save_char;
- }
- if( pResult && pURL ){
- // Get just the filename of source URL
- char * pFilename = EDT_GetFilename(pURL, bMustHaveExtension);
- if( pFilename ){
- // Append the filename to the base
- StrAllocCat(pResult, pFilename);
- XP_FREE(pFilename);
- }
- }
-
- //Note: If no pURL, pBaseURL is returned stripped of its filename
- return pResult;
- }
-
- char * EDT_GetDefaultPublishURL(MWContext * pMWContext, char **ppFilename, char **ppUserName, char **ppPassword)
- {
- XP_ASSERT(pMWContext);
- char * pURL = LO_GetBaseURL(pMWContext);
- if( !pURL ){
- return NULL;
- }
- XP_Bool bLastPublishFailed = EDT_IsSameURL(CEditSaveObject::m_pFailedPublishUrl, pURL, NULL, NULL);
-
- if( ppFilename ){
- if( EDT_IS_NEW_DOCUMENT(pMWContext) ){
- // New page: empty filename
- *ppFilename = NULL;
- } else {
- // Extract current filename part
- *ppFilename = EDT_GetFilename(pURL, TRUE);
-
- // On win16 force to lower case.
- #ifdef XP_WIN16
- char *pConvert = *ppFilename;
- while (pConvert && *pConvert) {
- *pConvert = XP_TO_LOWER(*pConvert);
- pConvert++;
- }
- #endif
- }
- }
- // Default: Clear password
- if( ppPassword ){
- *ppPassword = NULL;
- }
-
- if( !bLastPublishFailed && !EDT_IS_NEW_DOCUMENT(pMWContext) ){
- int iType = NET_URL_Type(pURL);
- if( iType == FTP_TYPE_URL ||
- iType == HTTP_TYPE_URL ||
- iType == SECURE_HTTP_TYPE_URL ) {
- // We are editing a remote page, so try to return it to that location
- // (We don't know the password)
- // Truncate current URL at the filename
- return EDT_ReplaceFilename(pURL, NULL, TRUE);
- }
- }
-
- char *pPrefURL = NULL;
- XP_Bool bUseDefault = FALSE;
-
- if( bLastPublishFailed ){
- // The publish destination should be saved to this at start of publishing (thus may not be "correct")
- // The destination should also be saved to the first history pref (editor.publish_history_0)
- // but only if publishing succeeded
- PREF_CopyCharPref("editor.publish_last_loc", &pPrefURL);
- } else {
- // Use the last successfully-used location saved in preferences
- PREF_CopyCharPref("editor.publish_history_0", &pPrefURL);
- }
- // Be sure to check for empty pref string
- if( !pPrefURL || !*pPrefURL ){
- XP_FREEIF(pPrefURL);
- // No last-used location -- use the default location
- PREF_CopyCharPref("editor.publish_location", &pPrefURL);
- bUseDefault = TRUE;
- }
-
- char * pLocation = 0;
- char * pUserName = ppUserName ? *ppUserName : 0;
-
- // Parse the preference string to extract Username
- // (password is separate for security munging)
- NET_ParseUploadURL( pPrefURL, &pLocation, &pUserName, NULL );
-
- if (ppUserName)
- *ppUserName = pUserName;
-
- if( ppPassword ){
- // Get the corrsponding password saved
- char * pPassword = NULL;
- if( bLastPublishFailed ){
- } else if( bUseDefault ){
- PREF_CopyCharPref("editor.publish_password", &pPassword);
- } else {
- PREF_CopyCharPref("editor.publish_password_0", &pPassword);
- }
-
- if( pPassword && *pPassword ){
- *ppPassword = SECNAV_UnMungeString(pPassword);
- XP_FREE(pPassword);
- }
- }
- XP_FREEIF(pPrefURL);
-
- return pLocation;
- }
-
- //
- // Keep this localized here. These two functions are the only ones
- // that need to know this value.
- // NOTE: CALLER MUST FREE THE RETURNED STRINGS
- #define MAX_PUBLISH_LOCATIONS 20
-
- XP_Bool
- EDT_GetPublishingHistory(unsigned n,
- char** location_r,
- char** username_r,
- char** password_r)
- {
- char prefname[32];
- char* prefvalue = NULL;
-
- if (n >= MAX_PUBLISH_LOCATIONS)
- return FALSE;
-
- XP_SPRINTF(prefname, "editor.publish_history_%d", n);
-
- if( PREF_CopyCharPref(prefname, &prefvalue) == -1 ||
- prefvalue == NULL || prefvalue[0] == '\0')
- return FALSE;
-
- if (location_r != NULL)
- *location_r = NULL; /* else NET_ParseUploadURL() will try to free! */
- if (username_r != NULL)
- *username_r = NULL;
-
- XP_Bool return_value;
- return_value = NET_ParseUploadURL(prefvalue, location_r, username_r, NULL);
- XP_FREE(prefvalue); // done with this now.
-
- if (!return_value)
- return FALSE;
-
- if (password_r != NULL) {
- XP_SPRINTF(prefname, "editor.publish_password_%d", n);
-
- if (PREF_CopyCharPref(prefname, &prefvalue) != -1 && prefvalue && *prefvalue) {
- *password_r = SECNAV_UnMungeString(prefvalue);
- } else {
- *password_r = NULL;
- }
- if (prefvalue != NULL)
- XP_FREE(prefvalue);
- }
- return TRUE;
- }
-
- void
- EDT_SyncPublishingHistory()
- {
- char prefname[32];
- char* prefvalue = NULL;
- char* pLastLoc = NULL;
- char* pLastPass = NULL;
- int i;
-
- /*
- * Last location should be set when you start a publish.
- * Now copy this to the top (first) of the history.
- * Abort if pref doesn't exist or is empty
- */
- if( PREF_CopyCharPref("editor.publish_last_loc", &pLastLoc) == -1 ||
- !pLastLoc || !*pLastLoc )
- return;
- PREF_CopyCharPref("editor.publish_last_pass", &pLastPass);
-
- /*
- * First scan the list to find pref that matches new item
- */
- for (i = 0; i < (MAX_PUBLISH_LOCATIONS - 1); i++) {
- XP_SPRINTF(prefname, "editor.publish_history_%d", i);
- if( PREF_CopyCharPref(prefname, &prefvalue) == -1 ||
- !prefvalue || !*prefvalue ||
- XP_STRCMP(prefvalue, pLastLoc) == 0) {
- //
- // No history or this history matches the last publish location.
- //
- break;
- }
- XP_FREEIF(prefvalue);
- }
- XP_FREEIF(prefvalue);
-
- /*
- * Now shift everything up a slot.
- */
- for (; i > 0; i--) {
- XP_SPRINTF(prefname, "editor.publish_history_%d", i-1);
- PREF_CopyCharPref(prefname, &prefvalue);
- XP_SPRINTF(prefname, "editor.publish_history_%d", i);
- PREF_SetCharPref(prefname, prefvalue);
- XP_FREEIF(prefvalue);
-
- XP_SPRINTF(prefname, "editor.publish_password_%d", i-1);
- PREF_CopyCharPref(prefname, &prefvalue);
- XP_SPRINTF(prefname, "editor.publish_password_%d", i);
- PREF_SetCharPref(prefname, prefvalue);
- XP_FREEIF(prefvalue);
- }
-
- /*
- * Now set the zero'th one.
- */
- PREF_SetCharPref("editor.publish_history_0", pLastLoc);
- PREF_SetCharPref("editor.publish_password_0", pLastPass);
-
- XP_FREEIF(pLastLoc);
- XP_FREEIF(pLastPass);
- }
-
- //
- // This was placed in EDT.H so front ends can use it as well
- // #define MAX_EDIT_HISTORY_LOCATIONS 10
-
- // Cache the Edit History data
- static char** ppEditHistoryURLs = NULL;
- static char** ppEditHistoryTitles = NULL;
-
- // NOTE: Caller must NOT free the returned strings - they are locally cached
- XP_Bool
- EDT_GetEditHistory(MWContext * pMWContext, unsigned n,
- char** ppUrl, char** ppTitle)
- {
- char prefname[32];
- unsigned i;
-
- // if context is NULL, bail!
- if( !pMWContext )
- return FALSE;
-
- // Initialize list if not done so already
- if( !ppEditHistoryURLs )
- EDT_SyncEditHistory(pMWContext);
-
- // Check if current URL is matches the requested or more recent items in the list
- if( pMWContext )
- {
- History_entry * pEntry = SHIST_GetCurrent(&(pMWContext->hist));
- if( pEntry && pEntry->address )
- {
- for( i = 0; i <= n; i++ ){
- XP_SPRINTF(prefname, "editor.url_history.URL_%d", i);
- if( ppEditHistoryURLs[i] &&
- EDT_IsSameURL(pEntry->address, ppEditHistoryURLs[i], 0, 0) )
- {
- // The current doc was found, so skip over it
- n++;
- break;
- }
- }
- }
- }
- // Default in case we don't set the location
- if( ppUrl )
- *ppUrl = NULL;
-
- if( n >= MAX_EDIT_HISTORY_LOCATIONS )
- return FALSE;
-
- if( !ppEditHistoryURLs[n] )
- return FALSE;
-
- // Return URL and Title to caller
- if( ppUrl )
- *ppUrl = ppEditHistoryURLs[n];
-
- if( ppTitle )
- *ppTitle = ppEditHistoryTitles[n];
-
- return TRUE;
- }
-
- static char pEmpty[] = "";
-
- void
- EDT_SyncEditHistory(MWContext * pMWContext)
- {
- char prefname[32];
- char* prefvalue = NULL;
- char* pTitle = pEmpty;
- int i;
-
- if(!pMWContext)
- return;
-
- // Initialize the local arrays from the current preference list
- if( !ppEditHistoryURLs )
- {
- ppEditHistoryURLs = (char**)XP_ALLOC( MAX_EDIT_HISTORY_LOCATIONS * sizeof(char*) );
- if( !ppEditHistoryURLs )
- return;
-
- ppEditHistoryTitles = (char**)XP_ALLOC( MAX_EDIT_HISTORY_LOCATIONS * sizeof(char*) );
- if( !ppEditHistoryTitles )
- {
- XP_FREEIF(ppEditHistoryURLs);
- return;
- }
-
- for( i = 0; i < MAX_EDIT_HISTORY_LOCATIONS; i++ )
- {
- XP_SPRINTF(prefname, "editor.url_history.URL_%d", i);
- if(PREF_CopyCharPref(prefname, &prefvalue) != -1 &&
- prefvalue && *prefvalue )
- {
- ppEditHistoryURLs[i] = prefvalue;
- prefvalue = NULL;
-
- } else {
- ppEditHistoryURLs[i] = NULL;
- XP_FREEIF(prefvalue);
- }
-
- XP_SPRINTF(prefname, "editor.url_history.TITLE_%d", i);
- if(PREF_CopyCharPref(prefname, &prefvalue) != -1 &&
- prefvalue && *prefvalue )
- {
- ppEditHistoryTitles[i] = prefvalue;
- prefvalue = NULL;
- } else {
- ppEditHistoryTitles[i] = NULL;
- XP_FREEIF(prefvalue);
- }
- }
- }
-
- History_entry * pEntry = SHIST_GetCurrent(&(pMWContext->hist));
- if(pEntry )
- {
- // Must have an address
- if( !pEntry->address || !*pEntry->address )
- return;
-
- // Test for new document URL: file://Untitled and ignore it
- if( !XP_STRCMP(XP_GetString(XP_EDIT_NEW_DOC_NAME), pEntry->address) ||
- !XP_STRCMP(XP_GetString(XP_EDIT_NEW_DOC_URL), pEntry->address))
- {
- return;
- }
-
- if( pEntry->title && *pEntry->title ){
- pTitle = pEntry->title;
- }
- }
-
- /*
- * First scan the list to find pref URL that matches current page
- */
- for (i = 0; i < (MAX_EDIT_HISTORY_LOCATIONS - 1); i++)
- {
- XP_SPRINTF(prefname, "editor.url_history.URL_%d", i);
- if( !ppEditHistoryURLs[i] ||
- EDT_IsSameURL(ppEditHistoryURLs[i], pEntry->address, 0, 0) ) {
- //
- // No history or this history matches the current last-edited URL
- //
- break;
- }
- }
- // Now i = the index to last-edited URL or last possible URL in the list
- if( i == (MAX_EDIT_HISTORY_LOCATIONS-1) )
- {
- // We will be replacing the last item, so delete it
- // so delete it
- XP_FREEIF(ppEditHistoryURLs[i]);
- XP_FREEIF(ppEditHistoryTitles[i]);
- }
-
- /*
- * Now shift everything one item.
- */
- for (; i > 0; i--)
- {
- XP_SPRINTF(prefname, "editor.url_history.URL_%d", i);
- // Not sure if this can handle null string, so lets not try!
- PREF_SetCharPref(prefname, ppEditHistoryURLs[i-1] ? ppEditHistoryURLs[i-1] : pEmpty);
-
- ppEditHistoryURLs[i] = ppEditHistoryURLs[i-1];
-
- XP_SPRINTF(prefname, "editor.url_history.TITLE_%d", i);
- PREF_SetCharPref(prefname, ppEditHistoryTitles[i-1] ? ppEditHistoryTitles[i-1] : pEmpty);
-
- ppEditHistoryTitles[i] = ppEditHistoryTitles[i-1];
- }
-
- /*
- * Now set the zero'th one -- the current URL
- */
- PREF_SetCharPref("editor.url_history.URL_0", pEntry->address);
- PREF_SetCharPref("editor.url_history.TITLE_0", pTitle);
-
- ppEditHistoryURLs[0] = XP_STRDUP(pEntry->address);
-
-
- if( pTitle && *pTitle )
- {
- ppEditHistoryTitles[0] = XP_STRDUP(pTitle);
- } else {
- ppEditHistoryTitles[0] = NULL;
- }
- }
-
- void edt_UpdateEditHistoryTitle(MWContext * pMWContext, char * pTitle)
- {
- if( pMWContext )
- {
- History_entry * pEntry = SHIST_GetCurrent(&(pMWContext->hist));
- if(pEntry && pEntry->address && !*pEntry->address)
- {
- for (int i = 0; i < MAX_EDIT_HISTORY_LOCATIONS; i++)
- {
- char prefname[32];
- XP_SPRINTF(prefname, "editor.url_history.URL_%d", i);
- if( ppEditHistoryURLs[i] &&
- EDT_IsSameURL(ppEditHistoryURLs[i], pEntry->address, 0, 0) )
- {
- XP_FREEIF(ppEditHistoryTitles[i]);
- if( pTitle )
- ppEditHistoryTitles[i] = pTitle;
-
- // Also update the preference value
- char prefname[32];
- XP_SPRINTF(prefname, "editor.url_history.TITLE_%d", i);
-
- // Not sure if this can handle null string, so lets not try!
- PREF_SetCharPref(prefname, pTitle ? pTitle : pEmpty);
- return;
- }
- }
- }
- }
- }
-
- char * EDT_GetPageTitleFromFilename(char * pFilename)
- {
- char * pTitle = NULL;
- if( pFilename ){
- // Get Full "filename" and we don't need an extension
- pTitle = EDT_GetFilename(pFilename, FALSE);
-
- if( pTitle ){
- // Don't include extension
- char * period = XP_STRCHR(pTitle, '.');
- if(period){
- // Truncate at the beginning of extension
- *period = '\0';
- }
- }
- }
- return pTitle;
- }
-
- // True if both urls are the same, ignores any username/password
- // information. Does caseless comparison for file:// URLs
- // on windows and mac.
- // url1 and url2 are relative to base1 and base2, respectively.
- // If url1 or url2 is already absolute, base1 or base2 can
- // be passed in as NULL.
- XP_Bool EDT_IsSameURL(char *url1,char *url2,char *base1,char *base2) {
- // Check for NULL or empty strings.
- if (!url1 || !url2 || !*url1 || !*url2) {
- return FALSE;
- }
-
- // Used passed in base URLs if provided.
- char *pAbs1 = NULL;
- char *pAbs2 = NULL;
- if (base1) {
- pAbs1 = NET_MakeAbsoluteURL(base1,url1);
- }
- if (base2) {
- pAbs2 = NET_MakeAbsoluteURL(base2,url2);
- }
- // Strip any username/password info from urls in making comparison if
- // they are http, https, or ftp.
- char *pUrl1 = edt_StripUsernamePassword(pAbs1 ? pAbs1 : url1);
- char *pUrl2 = edt_StripUsernamePassword(pAbs2 ? pAbs2 : url2);
- edt_StripAtHashOrQuestionMark(pUrl1);
- edt_StripAtHashOrQuestionMark(pUrl2);
-
- XP_Bool bRetVal = FALSE;
- if (pUrl1 && pUrl2) {
- char *pBaseUrl1 = NET_ParseURL(pUrl1, GET_PATH_PART);
- char *pBaseUrl2 = NET_ParseURL(pUrl2, GET_PATH_PART);
- #if defined(XP_WIN) || defined(XP_MAC) || defined(XP_OS2)
- // Strip off Target (named Anchors)
- // Local file URLs are equivalent if they differ only
- // by case.
- if (NET_URL_Type(pUrl1) == FILE_TYPE_URL) {
- bRetVal = (XP_STRCASECMP( pUrl1, pUrl2 ) == 0);
- }
- else {
- bRetVal = (XP_STRCMP( pUrl1, pUrl2 ) == 0 );
- }
- #else
- // Use regular strcmp.
- bRetVal = (XP_STRCMP( pUrl1, pUrl2 ) == 0 );
- #endif
- }
-
- XP_FREEIF(pUrl1);
- XP_FREEIF(pUrl2);
- XP_FREEIF(pAbs1);
- XP_FREEIF(pAbs2);
- return bRetVal;
- }
-
- // Replace the current selection with supplied text
- void EDT_ReplaceText(MWContext *pContext, char * pReplaceText, XP_Bool bReplaceAll,
- char *pTextToLookFor, XP_Bool bCaseless, XP_Bool bBackward, XP_Bool bDoWrap)
- {
- GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
- pEditBuffer->ReplaceLoop( pReplaceText, bReplaceAll,
- pTextToLookFor, bCaseless, bBackward, bDoWrap );
- }
-
- // Block of functions moved from EDITOR.CPP for Win16 Build
- // NOT USED???
- #ifdef FIND_REPLACE
-
- XP_Bool EDT_FindAndReplace(MWContext *pContext,
- EDT_FindAndReplaceData *pData ){
- GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) FALSE;
- return pEditBuffer->FindAndReplace( pData );
-
- }
- #endif // FIND_REPLACE
-
- // Table Sizing, Selection, Add Row/Col interface
- ED_HitType EDT_GetTableHitRegion(MWContext *pContext, int32 xVal, int32 yVal,
- LO_Element **ppElement, XP_Bool bModifierKeyPressed)
- {
- GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) ED_HIT_NONE;
- return pEditBuffer->GetTableHitRegion(xVal, yVal, ppElement, bModifierKeyPressed);
- }
-
- ED_HitType EDT_GetSelectedTableElement(MWContext *pContext, LO_Element **ppElement){
- return EDT_GetTableHitRegion(pContext, 0, 0, ppElement, FALSE);
- }
-
- // Object Sizer
- ED_SizeStyle EDT_CanSizeObject(MWContext *pContext, LO_Element *pElement,
- int32 xVal, int32 yVal){
- GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) 0;
- return pEditBuffer->CanSizeObject(pElement, xVal, yVal);
- }
-
- XP_Bool EDT_IsSizing(MWContext *pContext){
- GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) FALSE;
- return pEditBuffer->IsSizing();
- }
-
- ED_SizeStyle EDT_StartSizing(MWContext *pContext, LO_Element *pElement, int32 xVal, int32 yVal,
- XP_Bool bLockAspect, XP_Rect *pRect){
- GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) 0;
- return pEditBuffer->StartSizing(pElement, xVal, yVal, bLockAspect, pRect);
- }
-
- XP_Bool EDT_GetSizingRect(MWContext *pContext, int32 xVal, int32 yVal,
- XP_Bool bLockAspect, XP_Rect *pRect){
- GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) FALSE;
- return pEditBuffer->GetSizingRect(xVal, yVal, bLockAspect, pRect);
- }
-
- void EDT_EndSizing(MWContext *pContext){
- GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
- pEditBuffer->EndSizing();
- }
-
- void EDT_CancelSizing(MWContext *pContext){
- GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
- pEditBuffer->CancelSizing();
- }
-
- ED_BufferOffset EDT_GetInsertPointOffset( MWContext *pContext ){
- GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) 0;
- CPersistentEditInsertPoint p;
- pEditBuffer->GetInsertPoint( p );
- return (ED_BufferOffset) p.m_index;
- }
-
- void EDT_SetInsertPointToOffset( MWContext *pContext, ED_BufferOffset i,
- int32 iLen ){
- GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
- CPersistentEditInsertPoint p((ElementIndex)i);
-
- if( iLen != 0 ){
- CPersistentEditInsertPoint p1((ElementIndex)i+iLen);
- CPersistentEditSelection perSel;
- perSel = CPersistentEditSelection( p, p1 );
- CEditSelection sel = pEditBuffer->PersistentToEphemeral( perSel );
- pEditBuffer->SetSelection( sel );
- }
- else {
- pEditBuffer->SetInsertPoint( p );
- }
- }
-
- void EDT_OffsetToLayoutElement( MWContext *pContext, ED_BufferOffset i,
- LO_Element * *element, int32 *caretPos){
- GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
- CPersistentEditInsertPoint p((ElementIndex)i);
-
- CEditInsertPoint eP = pEditBuffer->PersistentToEphemeral(p);
- *element = eP.m_pElement->GetLayoutElement();
- *caretPos = eP.m_iPos;
- }
-
- ED_BufferOffset EDT_LayoutElementToOffset( MWContext *pContext,
- LO_Element *element, int32 caretPos){
- GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) -1;
-
- if (element->type != LO_TEXT)
- return -1;
-
- CEditInsertPoint insertPoint(element->lo_text.edit_element, caretPos);
-
- CPersistentEditInsertPoint p = pEditBuffer->EphemeralToPersistent(insertPoint);
-
- return p.m_index;
- }
-
- LO_TextBlock* EDT_GetTextBlock(MWContext *, LO_Element *le)
- {
- LO_TextBlock *block;
- CEditTextElement *pText;
-
- block = NULL;
-
- if( ( le->type == LO_TEXT ) && ( le->lo_any.edit_element != NULL )
- && le->lo_any.edit_element->IsA( P_TEXT ) ){
- pText = le->lo_any.edit_element->Text();
- block = pText->GetTextBlock();
- }
-
- return block;
- }
-
- void EDT_GetSelectionOffsets(MWContext *pContext, ED_BufferOffset* pStart, ED_BufferOffset* pEnd){
- if ( ! pStart || !pEnd ) {
- XP_ASSERT(FALSE);
- return;
- }
- GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
- CPersistentEditSelection s;
- pEditBuffer->GetSelection( s );
- *pStart = (ED_BufferOffset) s.m_start.m_index;
- *pEnd = (ED_BufferOffset) s.m_end.m_index;
- }
-
- XP_Bool EDT_SelectFirstMisspelledWord( MWContext *pContext ){
- GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) FALSE;
- return pEditBuffer->FindNextMisspelledWord( TRUE, TRUE, 0 );
- }
-
- XP_Bool EDT_SelectNextMisspelledWord( MWContext *pContext ){
- GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) FALSE;
- return pEditBuffer->FindNextMisspelledWord( FALSE, TRUE, 0 );
- }
-
- void EDT_ReplaceMisspelledWord( MWContext *pContext, char* pOldWord,
- char*pNewWord, XP_Bool bAll ){
- GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
- pEditBuffer->BeginBatchChanges(kPasteTextCommandID);
- pEditBuffer->IterateMisspelledWords( CEditBuffer::EMSW_REPLACE,
- pOldWord, pNewWord, bAll );
- pEditBuffer->EndBatchChanges();
- }
-
- void EDT_IgnoreMisspelledWord( MWContext *pContext, char* pOldWord,
- XP_Bool bAll ){
- GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
- pEditBuffer->IterateMisspelledWords( CEditBuffer::EMSW_IGNORE,
- pOldWord, 0, bAll );
- }
-
-
- XP_HUGE_CHAR_PTR EDT_GetPositionalText( MWContext* pContext ){
- GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) 0;
- return pEditBuffer->GetPositionalText();
- }
-
- void EDT_SetCharacterDataAtOffset( MWContext *pContext, EDT_CharacterData *pData,
- ED_BufferOffset iBufOffset, int32 iLen ){
- GET_WRITABLE_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
- pEditBuffer->SetCharacterDataAtOffset(pData, iBufOffset, iLen );
- }
-
- void EDT_SetRefresh( MWContext* pContext, XP_Bool bRefreshOn ){
- GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer);
- pEditBuffer->SetRefresh( bRefreshOn );
- }
-
-
- // Warning this deletes (and recreates) the CEditBuffer.
- XP_Bool EDT_SetEncoding(MWContext* pContext, int16 csid){
- GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) FALSE;
- XP_Bool bDoIt = TRUE;
- // if ( pEditBuffer->HasEncoding() ) {
- char* pMessage = XP_GetString(XP_EDT_I18N_HAS_CHARSET);
- if ( pMessage ) {
- bDoIt = FE_Confirm(pContext, pMessage);
- }
- else {
- XP_ASSERT(0);
- }
-
- if ( bDoIt ) {
- pEditBuffer->ChangeEncoding(csid);
- }
- return bDoIt;
- }
- // End of Block of functions moved from EDITOR.CPP for Win16 Build
-
- /*
- * Extract the Extra HTML string from the ED_Element pointer in an image struct
- * (ED_Element is a void* to external users)
- * Caller must XP_FREE result
- */
- char * EDT_GetExtraHTML_FromImage(LO_ImageStruct *pImage){
- if( pImage ){
- if( pImage->edit_element == 0 ){
- // We don't have an edit element - must be from Navigator,
- // so we have to pick out stuff that would end up in CEditImageElement's extra data
- // BUT the original PA_TAG data is no longer around.
- // The only item we will grab is the USEMAP data
- // TODO: Get other associated data such as JavaScript?
- // To do that, we need a new function to reconstruct a tag from LO_ImageStruct
-
- if ( pImage->image_attr && pImage->image_attr->usemap_name ){
- char * pRet = 0;
- pRet = PR_sprintf_append( pRet, "USEMAP=");
- pRet = PR_sprintf_append( pRet, pImage->image_attr->usemap_name);
- return pRet;
- }
- }else if( pImage->edit_element->IsImage() ){
- EDT_ImageData * pImageData = ((CEditImageElement*)pImage->edit_element)->GetImageData();
- if( pImageData->pExtra && *pImageData->pExtra ){
- return XP_STRDUP(pImageData->pExtra);
- }
- EDT_FreeImageData(pImageData);
- }
- }
- return NULL;
- }
-
- PRBool EDT_EncryptState( MWContext *pContext ){
- CEditBuffer *pEditBuffer = LO_GetEDBuffer( pContext );
-
- if (pEditBuffer == NULL) return PR_FALSE;
-
- return pEditBuffer->m_bEncrypt;
- }
-
- void EDT_EncryptToggle( MWContext *pContext ){
- CEditBuffer *pEditBuffer = LO_GetEDBuffer( pContext );
-
- if (pEditBuffer == NULL) return;
-
- pEditBuffer->m_bEncrypt = pEditBuffer->m_bEncrypt ? PR_FALSE : PR_TRUE;
- }
-
- void EDT_EncryptSet( MWContext *pContext ){
- CEditBuffer *pEditBuffer = LO_GetEDBuffer( pContext );
-
- if (pEditBuffer == NULL) return;
-
- pEditBuffer->m_bEncrypt = PR_TRUE;
- }
-
- void EDT_EncryptReset( MWContext *pContext ){
- CEditBuffer *pEditBuffer = LO_GetEDBuffer( pContext );
-
- if (pEditBuffer == NULL) return;
-
- pEditBuffer->m_bEncrypt = PR_FALSE;
- }
-
- #endif // EDITOR
-