gecko-dev/lib/layout/edtlist.cpp

666 строки
11 KiB
C++

/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#if defined(ENDER) && defined(MOZ_ENDER_MIME)
#ifdef DEBUG_kin
#define DEBUG_SAFE_LIST 1
#endif /* DEBUG_kin */
#ifdef DEBUG_SAFE_LIST
#include <stdio.h>
#endif /* DEBUG_SAFE_LIST */
#include "editor.h"
class LListElement
{
LListElement *m_pPrev;
LListElement *m_pNext;
protected:
void *m_pData;
public:
LListElement(void *data = 0)
: m_pPrev(0), m_pNext(0), m_pData(data) {}
virtual ~LListElement();
int32 insertBefore(LListElement *ele);
int32 insertAfter(LListElement *ele);
int32 unlink();
void *getData() { return m_pData; }
LListElement *getPrev() { return m_pPrev; }
LListElement *getNext() { return m_pNext; }
#ifdef DEBUG_SAFE_LIST
virtual void print();
#endif /* DEBUG_SAFE_LIST */
};
class LList
{
LListElement *m_pHead;
LListElement *m_pTail;
public:
LList() : m_pHead(0), m_pTail(0) {}
virtual ~LList();
LListElement *getHead() { return m_pHead; }
LListElement *getTail() { return m_pTail; }
int32 insertAtHead(LListElement *ele);
int32 insertAtTail(LListElement *ele);
int32 insertBefore(LListElement *ele1, LListElement *ele2);
int32 insertAfter(LListElement *ele1, LListElement*ele2);
XP_Bool isEmpty();
XP_Bool contains(LListElement *ele);
int32 remove(LListElement *ele);
#ifdef DEBUG_SAFE_LIST
virtual void print();
#endif /* DEBUG_SAFE_LIST */
};
class LListIterator
{
LList *m_pList;
LListElement *m_pNextElement;
public:
LListIterator(LList *list = 0) : m_pList(list), m_pNextElement(0) { init(); }
virtual int32 init()
{
if (!m_pList)
return 0;
m_pNextElement = m_pList->getHead();
return 0;
}
virtual LListElement *getNext()
{
LListElement *ele = m_pNextElement;
if (m_pNextElement)
m_pNextElement = m_pNextElement->getNext();
return ele;
}
};
class SortedLList : public LList
{
public:
virtual int32 insert(LListElement *ele);
virtual int32 compare(LListElement *ele1, LListElement *ele2);
};
LListElement::~LListElement()
{
// If we're destroying this element, make sure it's
// not on any list!
unlink();
}
//
// Insert ele before this
//
int32
LListElement::insertBefore(LListElement *ele)
{
if (!ele)
return -1;
ele->m_pNext = this;
ele->m_pPrev = m_pPrev;
m_pPrev = ele;
if (ele->m_pPrev)
ele->m_pPrev->m_pNext = ele;
return 0;
}
//
// Insert ele after this.
//
int32
LListElement::insertAfter(LListElement *ele)
{
if (!ele)
return -1;
ele->m_pPrev = this;
ele->m_pNext = m_pNext;
m_pNext = ele;
if (ele->m_pNext)
ele->m_pNext->m_pPrev = ele;
return 0;
}
//
// unlink this from it's list.
//
int32
LListElement::unlink()
{
if (m_pPrev)
m_pPrev->m_pNext = m_pNext;
if (m_pNext)
m_pNext->m_pPrev = m_pPrev;
m_pPrev = 0;
m_pNext = 0;
return 0;
}
#ifdef DEBUG_SAFE_LIST
void
LListElement::print()
{
fprintf(stdout, "this: 0x%.8x\n", this);
fprintf(stdout, " m_pData: 0x%.8x\n", m_pData);
fprintf(stdout, " m_pPrev: 0x%.8x\n", m_pPrev);
fprintf(stdout, " m_pNext: 0x%.8x\n", m_pNext);
}
#endif /* DEBUG_SAFE_LIST */
LList::~LList()
{
LListElement *ele;
while((ele = m_pHead))
{
remove(ele);
delete ele;
}
}
//
// Insert ele at the head of the list.
//
int32
LList::insertAtHead(LListElement *ele)
{
if (!ele)
return -1;
if (!m_pHead)
{
m_pHead = m_pTail = ele;
return 0;
}
m_pHead->insertBefore(ele);
m_pHead = ele;
return 0;
}
//
// Insert ele at the tail of the list.
//
int32
LList::insertAtTail(LListElement *ele)
{
if (!ele)
return -1;
if (!m_pHead)
{
m_pHead = m_pTail = ele;
return 0;
}
m_pTail->insertAfter(ele);
m_pTail = ele;
return 0;
}
//
// Insert ele2 before ele1 in the list.
//
int32
LList::insertBefore(LListElement *ele1, LListElement *ele2)
{
if (!ele1 || !ele2 || !contains(ele1))
return -1;
if (m_pHead == ele1)
{
insertAtHead(ele2);
return 0;
}
ele1->insertBefore(ele2);
return 0;
}
//
// Insert ele2 after ele1 in the list.
//
int32
LList::insertAfter(LListElement *ele1, LListElement *ele2)
{
if (!ele1 || !ele2 || !contains(ele1))
return -1;
if (m_pTail == ele1)
{
insertAtTail(ele2);
return 0;
}
ele1->insertAfter(ele2);
return 0;
}
//
// TRUE if the list contains no elements.
//
XP_Bool
LList::isEmpty()
{
return !m_pHead;
}
//
// TRUE if this contains ele.
//
XP_Bool
LList::contains(LListElement *ele)
{
LListElement *e = m_pHead;
if (!ele)
return FALSE;
while (e)
{
if (e == ele)
return TRUE;
e = e->getNext();
}
return FALSE;
}
//
// Remove ele from the list.
//
int32
LList::remove(LListElement *ele)
{
if (!ele || !contains(ele))
return -1;
if (!m_pHead)
return 0;
if (ele == m_pHead)
m_pHead = ele->getNext();
if (ele == m_pTail)
m_pTail = ele->getPrev();
ele->unlink();
return 0;
}
#ifdef DEBUG_SAFE_LIST
void
LList::print()
{
LListIterator li(this);
LListElement *ele;
fprintf(stdout, "-------------------------------\n");
fprintf(stdout, "HEAD: 0x%.8x\n", m_pHead);
fprintf(stdout, "TAIL: 0x%.8x\n", m_pTail);
while ((ele = li.getNext()))
{
ele->print();
fflush(stdout);
}
}
#endif /* DEBUG_SAFE_LIST */
int32
SortedLList::insert(LListElement *ele)
{
LListIterator li(this);
LListElement *le;
if (contains(ele))
return 0;
if (isEmpty())
{
LList::insertAtHead(ele);
return 0;
}
while ((le = li.getNext()))
{
if (compare(le, ele) >= 0)
return(LList::insertBefore(le, ele));
}
return(LList::insertAtTail(ele));
}
int32
SortedLList::compare(LListElement *ele1, LListElement *ele2)
{
if (ele1->getData() < ele2->getData())
return -1;
else if (ele1->getData() > ele2->getData())
return 1;
return 0;
}
class SafeListElement : public LListElement
{
public:
void *m_pID;
char *m_pTmpFilePath;
int32 m_iRefCount;
SafeListElement(void *id, const char *url_str, const char *path=0)
: LListElement(), m_pTmpFilePath(0)
{
if (url_str)
m_pData = (void *)XP_STRDUP(url_str);
if (path)
m_pTmpFilePath = XP_STRDUP(path);
m_pID = id;
m_iRefCount = 1;
}
virtual ~SafeListElement()
{
if (m_pTmpFilePath)
{
XP_FileRemove(m_pTmpFilePath, xpFileToPost);
XP_FREE(m_pTmpFilePath);
}
if (m_pData)
XP_FREE(m_pData);
m_pData = 0;
m_pID = 0;
m_pTmpFilePath = 0;
}
XP_Bool match(void *id, const char *url_str)
{
if (m_pID != id || (m_pData != (void *)url_str && (!url_str || !m_pData)))
return(FALSE);
return(!XP_STRCMP((char *)m_pData, url_str));
}
#ifdef DEBUG_SAFE_LIST
void print()
{
fprintf(stdout, "this: 0x%.8x\n", this);
fprintf(stdout, " id: 0x%.8x\n", m_pID);
fprintf(stdout, " url_str: %s\n", (char *)m_pData);
fprintf(stdout, " path: %s\n", m_pTmpFilePath ? m_pTmpFilePath : "0");
fprintf(stdout, " count: %d\n", m_iRefCount);
fprintf(stdout, " prev: 0x%.8x\n", getPrev());
fprintf(stdout, " next: 0x%.8x\n", getNext());
}
#endif /* DEBUG_SAFE_LIST */
};
class SafeList : public SortedLList
{
public:
virtual ~SafeList()
{
removeAll();
}
SafeListElement *find(void *id, const char *url_str)
{
LListIterator li(this);
SafeListElement *ele;
while ((ele = (SafeListElement *)li.getNext()))
{
if (ele->match(id, url_str))
return ele;
}
return 0;
}
int32 insert(void *id, const char *url_str, const char *path = 0)
{
SafeListElement *ele = find(id, url_str);
if (ele)
{
ele->m_iRefCount++;
return 0;
}
ele = new SafeListElement(id, url_str, path);
if (!ele)
return -1;
return SortedLList::insert((LListElement *)ele);
}
int32 remove(void *id, const char *url_str)
{
SafeListElement *ele = find(id, url_str);
if (!ele)
return 1;
ele->m_iRefCount--;
if (ele->m_iRefCount <= 0)
{
LList::remove((LListElement *)ele);
delete ele;
}
return 0;
}
int32 removeID(void *id)
{
LListIterator li(this);
SafeListElement *ele;
while ((ele = (SafeListElement *)li.getNext()))
{
if (ele->m_pID == id)
{
LList::remove((LListElement *)ele);
delete ele;
}
}
return 0;
}
int32 removeAll()
{
LListIterator li(this);
LListElement *ele;
while ((ele = li.getNext()))
{
LList::remove(ele);
delete ele;
}
return 0;
}
int32 compare(LListElement *ele1, LListElement *ele2)
{
SafeListElement *e1 = (SafeListElement *)ele1;
SafeListElement *e2 = (SafeListElement *)ele2;
char *d1 = (char *)e1->getData();
char *d2 = (char *)e2->getData();
if (e1->m_pID < e2->m_pID)
return -1;
else if (e1->m_pID > e2->m_pID)
return 1;
else if (!d1)
return -1;
else if (!d2)
return 1;
return XP_STRCMP(d1, d2);
}
};
static SafeList *app_safe_list = 0;
extern "C" XP_Bool
EDT_URLOnSafeList( void *id, const char *url_str )
{
return(app_safe_list &&
app_safe_list->find(id, url_str) != 0);
}
extern "C" int32
EDT_AddTmpFileURLToSafeList( void *id, const char *url_str, const char *path )
{
int32 status = 0;
if (!app_safe_list)
{
app_safe_list = new SafeList();
if (!app_safe_list)
return -1;
}
status = app_safe_list->insert(id, url_str, path);
#ifdef DEBUG_SAFE_LIST
app_safe_list->print();
#endif /* DEBUG_SAFE_LIST */
return status;
}
extern "C" int32
EDT_AddURLToSafeList( void *id, const char *url_str )
{
return EDT_AddTmpFileURLToSafeList(id, url_str, 0);
}
extern "C" int32
EDT_RemoveURLFromSafeList( void *id, const char *url_str )
{
int32 status = 0;
if (!app_safe_list)
return 0;
status = app_safe_list->remove(id, url_str);
#ifdef DEBUG_SAFE_LIST
app_safe_list->print();
#endif /* DEBUG_SAFE_LIST */
return status;
}
extern "C" int32
EDT_RemoveIDFromSafeList( void *id )
{
int32 status = 0;
if (!app_safe_list)
return 0;
status = app_safe_list->removeID(id);
#ifdef DEBUG_SAFE_LIST
app_safe_list->print();
#endif /* DEBUG_SAFE_LIST */
return status;
}
extern "C" int32
EDT_DestroySafeList()
{
if (!app_safe_list)
return 0;
delete app_safe_list;
app_safe_list = 0;
return 0;
}
extern "C" void *
EDT_GetIdFromContext(MWContext *pContext)
{
GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) 0;
return pEditBuffer->m_pEmbeddedData;
}
#endif /* ENDER && MOZ_ENDER_MIME */