зеркало из https://github.com/mozilla/pjs.git
Generic message dialog, fix insert element-related bugs, initial personal dictionary dialog, other editor bugs
This commit is contained in:
Родитель
3f4c237872
Коммит
8f1b0f0e2f
|
@ -56,6 +56,14 @@ NS_IMETHODIMP InsertTextTxn::Init(nsIDOMCharacterData *aElement,
|
|||
const nsString &aStringToInsert,
|
||||
nsIPresShell *aPresShell)
|
||||
{
|
||||
#if 0 //def DEBUG_cmanske
|
||||
nsString text;
|
||||
aElement->GetData(text);
|
||||
printf("InsertTextTxn: Offset to insert at = %d. Text of the node to insert into:\n", aOffset);
|
||||
wprintf(text.GetUnicode());
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
mElement = do_QueryInterface(aElement);
|
||||
mOffset = aOffset;
|
||||
mStringToInsert = aStringToInsert;
|
||||
|
|
|
@ -1754,7 +1754,7 @@ nsEditor::InsertText(const nsString& aStringToInsert)
|
|||
if (NS_SUCCEEDED(result) && NS_SUCCEEDED(selection->GetAnchorOffset(&offset)) && selectedNode)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> newNode;
|
||||
result = CreateNode(GetTextNodeTag(), selectedNode, offset+1,
|
||||
result = CreateNode(GetTextNodeTag(), selectedNode, offset, // offset+1, why the +1???
|
||||
getter_AddRefs(newNode));
|
||||
if (NS_SUCCEEDED(result) && newNode)
|
||||
{
|
||||
|
@ -1795,6 +1795,23 @@ NS_IMETHODIMP nsEditor::CreateTxnForInsertText(const nsString & aStringToInsert,
|
|||
result = mPresShell->GetSelection(getter_AddRefs(selection));
|
||||
if ((NS_SUCCEEDED(result)) && selection)
|
||||
{
|
||||
#if 0
|
||||
// Trap the simple case where the collapsed selection
|
||||
// is pointing to the beginning of a text node.
|
||||
// That's where we should insert new text
|
||||
// *** If we don't do this, we will return NS_ERROR_EDITOR_NO_TEXTNODE
|
||||
// from the iterator block below.
|
||||
// This may be OK, now that I fixed InsertText so it inserts
|
||||
// at the offset of the selection anchor (i.e., the caret offset)
|
||||
// instead of at offset+1
|
||||
PRBool collapsed
|
||||
result = selection->GetIsCollapsed(&collapsed);
|
||||
if (NS_SUCCEEDED(result) && collapsed)
|
||||
{
|
||||
// Check if the node at selection offset is a textNode
|
||||
// and use that with offset = 0.
|
||||
}
|
||||
#endif
|
||||
result = NS_ERROR_UNEXPECTED;
|
||||
nsCOMPtr<nsIEnumerator> enumerator;
|
||||
enumerator = do_QueryInterface(selection);
|
||||
|
@ -2007,6 +2024,14 @@ NS_IMETHODIMP nsEditor::DeleteSelectionAndPrepareToCreateNode(nsCOMPtr<nsIDOMNod
|
|||
PRUint32 selectedNodeContentCount=0;
|
||||
nsCOMPtr<nsIDOMCharacterData>selectedParentNodeAsText;
|
||||
selectedParentNodeAsText = do_QueryInterface(parentSelectedNode);
|
||||
#ifdef DEBUG_cmanske
|
||||
// What is the parent node for the selection?
|
||||
nsAutoString tag;
|
||||
parentSelectedNode->GetNodeName(tag);
|
||||
printf("Parent of selected node's NodeName = ");
|
||||
wprintf(tag.GetUnicode());
|
||||
printf("\n");
|
||||
#endif
|
||||
/* if the selection is a text node, split the text node if necesary
|
||||
and compute where to put the new node
|
||||
*/
|
||||
|
@ -2050,15 +2075,38 @@ NS_IMETHODIMP nsEditor::DeleteSelectionAndPrepareToCreateNode(nsCOMPtr<nsIDOMNod
|
|||
result = parentChildList->Item(offsetOfSelectedNode, getter_AddRefs(selectedNode));
|
||||
if ((NS_SUCCEEDED(result)) && selectedNode)
|
||||
{
|
||||
#if 0 //def DEBUG_cmanske
|
||||
// What is the item at the selected offset?
|
||||
nsAutoString tag;
|
||||
selectedNode->GetNodeName(tag);
|
||||
printf("Selected Node's name = ");
|
||||
wprintf(tag.GetUnicode());
|
||||
printf("\n");
|
||||
#endif
|
||||
nsCOMPtr<nsIDOMCharacterData>selectedNodeAsText;
|
||||
selectedNodeAsText = do_QueryInterface(selectedNode);
|
||||
nsCOMPtr<nsIDOMNodeList>childList;
|
||||
selectedNode->GetChildNodes(getter_AddRefs(childList));
|
||||
if ((NS_SUCCEEDED(result)) && childList) {
|
||||
childList->GetLength(&selectedNodeContentCount);
|
||||
//CM: I added "result ="
|
||||
result = selectedNode->GetChildNodes(getter_AddRefs(childList));
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
if (childList)
|
||||
{
|
||||
childList->GetLength(&selectedNodeContentCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is the case where the collapsed selection offset
|
||||
// points to an inline node with no children
|
||||
// This must also be where the new node should be inserted
|
||||
// and there is no splitting necessary
|
||||
offsetOfNewNode = offsetOfSelectedNode;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
else
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if ((offsetOfSelectedNode!=0) && (((PRUint32)offsetOfSelectedNode)!=selectedNodeContentCount))
|
||||
{
|
||||
|
|
|
@ -973,9 +973,8 @@ nsEditorShell::CloseWindow()
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
mWebShellWin->Close();
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
|
|
@ -247,6 +247,8 @@ class nsEditorShell : public nsIEditorShell,
|
|||
nsStringArray mSuggestedWordList;
|
||||
PRInt32 mSuggestedWordIndex;
|
||||
NS_IMETHOD DeleteSuggestedWordList();
|
||||
nsStringArray mDictionaryList;
|
||||
PRInt32 mDictionaryIndex;
|
||||
|
||||
typedef enum {
|
||||
ePlainTextEditorType = 1,
|
||||
|
|
|
@ -43,7 +43,6 @@
|
|||
#include "nsFileSpec.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIFileWidget.h" // for GetLocalFileURL stuff
|
||||
#include "nsWidgetsCID.h"
|
||||
#include "nsIDocumentEncoder.h"
|
||||
#include "nsIPref.h"
|
||||
|
@ -51,6 +50,8 @@
|
|||
#include "nsIPresShell.h"
|
||||
#include "prprf.h"
|
||||
|
||||
const unsigned char nbsp = 160;
|
||||
|
||||
#ifdef ENABLE_JS_EDITOR_LOG
|
||||
#include "nsJSEditorLog.h"
|
||||
#endif // ENABLE_JS_EDITOR_LOG
|
||||
|
@ -165,28 +166,22 @@ NS_IMETHODIMP nsHTMLEditor::InsertText(const nsString& aStringToInsert)
|
|||
|
||||
NS_IMETHODIMP nsHTMLEditor::SetBackgroundColor(const nsString& aColor)
|
||||
{
|
||||
#ifdef ENABLE_JS_EDITOR_LOG
|
||||
// nsresult result;
|
||||
NS_ASSERTION(mDoc, "Missing Editor DOM Document");
|
||||
|
||||
// TODO: Check selection for Cell, Row, Column or table and do color on appropriate level
|
||||
// For initial testing, just set the background on the BODY tag (the document's background)
|
||||
|
||||
// Do this only if setting a table or cell background
|
||||
// It will be called in nsTextEditor::SetBackgroundColor for the page background
|
||||
#if 0 //def ENABLE_JS_EDITOR_LOG
|
||||
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
||||
|
||||
if (mJSEditorLog)
|
||||
mJSEditorLog->SetBackgroundColor(aColor);
|
||||
#endif // ENABLE_JS_EDITOR_LOG
|
||||
|
||||
nsresult res;
|
||||
NS_ASSERTION(mDoc, "Missing Editor DOM Document");
|
||||
|
||||
// TODO: Check selection for Cell, Row, Column or table and do color on appropriate level
|
||||
// For initial testing, just set the background on the BODY tag (the document's background)
|
||||
|
||||
// Set the background color attribute on the body tag
|
||||
nsCOMPtr<nsIDOMElement> bodyElement;
|
||||
res = nsEditor::GetBodyElement(getter_AddRefs(bodyElement));
|
||||
if (NS_SUCCEEDED(res) && bodyElement)
|
||||
{
|
||||
nsAutoEditBatch beginBatching(this);
|
||||
bodyElement->SetAttribute("bgcolor", aColor);
|
||||
}
|
||||
return res;
|
||||
return nsTextEditor::SetBackgroundColor(aColor);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsHTMLEditor::SetBodyAttribute(const nsString& aAttribute, const nsString& aValue)
|
||||
|
@ -2058,12 +2053,7 @@ nsHTMLEditor::CreateElementWithDefaults(const nsString& aTagName, nsIDOMElement*
|
|||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Set default values for new elements
|
||||
// TODO: These should probably be in XUL or prefs?
|
||||
if (isAnchor)
|
||||
{
|
||||
// TODO: Get the text of the selection and build a suggested Name
|
||||
// Replace spaces with "_"
|
||||
} else if (TagName.Equals("hr"))
|
||||
if (TagName.Equals("hr"))
|
||||
{
|
||||
// Hard coded defaults in case there's no prefs
|
||||
nsAutoString align("center");
|
||||
|
@ -2126,49 +2116,31 @@ nsHTMLEditor::CreateElementWithDefaults(const nsString& aTagName, nsIDOMElement*
|
|||
{
|
||||
newElement->SetAttribute("cellpadding","2");
|
||||
newElement->SetAttribute("cellspacing","2");
|
||||
newElement->SetAttribute("width","50%");
|
||||
newElement->SetAttribute("border","1");
|
||||
} else if (TagName.Equals("tr"))
|
||||
{
|
||||
newElement->SetAttribute("valign","top");
|
||||
} else if (TagName.Equals("td"))
|
||||
{
|
||||
newElement->SetAttribute("width","40px");
|
||||
newElement->SetAttribute("height","40px");
|
||||
newElement->SetAttribute("valign","top");
|
||||
|
||||
// Insert the default space in a cell so border displays
|
||||
nsCOMPtr<nsIDOMNode> newCellNode = do_QueryInterface(newElement);
|
||||
if (newCellNode)
|
||||
{
|
||||
|
||||
// First create a parent paragraph node
|
||||
// THIS SHOULD BE A RULE METHOD -- SOMETHING LIKE CreateParagraphNode
|
||||
nsCOMPtr<nsIDOMElement> mozDivElement;
|
||||
nsresult result = mDoc->CreateElement("div", getter_AddRefs(mozDivElement));
|
||||
|
||||
if (NS_SUCCEEDED(result) && mozDivElement)
|
||||
// TODO: This should probably be in the RULES code or
|
||||
// preference based for "should we add the nbsp"
|
||||
nsCOMPtr<nsIDOMText>newTextNode;
|
||||
nsString space;
|
||||
// Set contents to the   character by concatanating the char code
|
||||
space += nbsp;
|
||||
// If we fail here, we return NS_OK anyway, since we have an OK cell node
|
||||
nsresult result = mDoc->CreateTextNode(space, getter_AddRefs(newTextNode));
|
||||
if (NS_SUCCEEDED(result) && newTextNode)
|
||||
{
|
||||
// Set the 'class' attribute needed so Composer 4.x doesn't eat the div
|
||||
mozDivElement->SetAttribute("class", "moz-p");
|
||||
|
||||
nsCOMPtr<nsIDOMNode>resultNode;
|
||||
nsCOMPtr<nsIDOMNode> mozDivNode = do_QueryInterface(mozDivElement);
|
||||
result = newCellNode->AppendChild(mozDivNode, getter_AddRefs(resultNode));
|
||||
|
||||
if (NS_SUCCEEDED(result) && resultNode)
|
||||
{
|
||||
// Append a text node
|
||||
nsCOMPtr<nsIDOMText>newTextNode;
|
||||
nsString space;
|
||||
// Set contents to the   character by concatanating the char code
|
||||
space += 160;
|
||||
result = mDoc->CreateTextNode(space, getter_AddRefs(newTextNode));
|
||||
if (NS_SUCCEEDED(result) && newTextNode)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode>resultNode2;
|
||||
result = mozDivNode->AppendChild(newTextNode, getter_AddRefs(resultNode2));
|
||||
}
|
||||
}
|
||||
result = newCellNode->AppendChild(newTextNode, getter_AddRefs(resultNode));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2204,9 +2176,11 @@ nsHTMLEditor::InsertElement(nsIDOMElement* aElement, PRBool aDeleteSelection)
|
|||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsAutoEditBatch beginBatching(this);
|
||||
// For most elements, set caret after inserting
|
||||
PRBool setCaretAfterElement = PR_TRUE;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> parentSelectedNode;
|
||||
PRInt32 offsetOfNewNode;
|
||||
PRInt32 splitPointOffset;
|
||||
|
||||
nsCOMPtr<nsIDOMSelection>selection;
|
||||
res = nsEditor::GetSelection(getter_AddRefs(selection));
|
||||
|
@ -2257,32 +2231,102 @@ nsHTMLEditor::InsertElement(nsIDOMElement* aElement, PRBool aDeleteSelection)
|
|||
}
|
||||
}
|
||||
|
||||
res = DeleteSelectionAndPrepareToCreateNode(parentSelectedNode, offsetOfNewNode);
|
||||
res = DeleteSelectionAndPrepareToCreateNode(parentSelectedNode, splitPointOffset);
|
||||
if (NS_SUCCEEDED(res))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> newNode = do_QueryInterface(aElement);
|
||||
PRBool isInline;
|
||||
res = IsNodeInline(newNode, isInline);
|
||||
if( NS_SUCCEEDED(res) /*&& isInline*/)
|
||||
if( NS_SUCCEEDED(res) && isInline)
|
||||
{
|
||||
// The simple case of an inline node
|
||||
res = InsertNode(aElement, parentSelectedNode, offsetOfNewNode);
|
||||
// This will split any inline nodes at the caret
|
||||
// and insert between them
|
||||
res = InsertNode(aElement, parentSelectedNode, splitPointOffset);
|
||||
} else {
|
||||
// Inserting a BLOCK element:
|
||||
// TODO: Start with parentSelectedNode and check if its a block that can accept the
|
||||
// block node we want to insert as its child. For initial testing, assume its OK
|
||||
//
|
||||
// Get the parent of the paragraph/container
|
||||
nsCOMPtr<nsIDOMNode> parentNode;
|
||||
parentSelectedNode->GetParentNode(getter_AddRefs(parentNode));
|
||||
res = SplitNodeDeep(parentSelectedNode, parentSelectedNode, offsetOfNewNode);
|
||||
if (NS_SUCCEEDED(res))
|
||||
// Inserting a BLOCK element
|
||||
// Get the first block parent of the paragraph/container
|
||||
// which we can split to create insert location
|
||||
// (Current parent may already be a suitable block to split)
|
||||
nsCOMPtr<nsIDOMNode> parentNodeOfInsert = parentSelectedNode;
|
||||
nsCOMPtr<nsIDOMNode> topNodeToSplit = parentSelectedNode;
|
||||
nsCOMPtr<nsIDOMElement> bodyElement;
|
||||
// We need to find the offset at each level we will split
|
||||
// to use when we insert the new element
|
||||
PRInt32 offsetToInsertAt = splitPointOffset;
|
||||
|
||||
res = nsEditor::GetBodyElement(getter_AddRefs(bodyElement));
|
||||
|
||||
if (NS_SUCCEEDED(res) && bodyElement &&
|
||||
// If text node is direct child of body, we can't insert a block node
|
||||
(parentSelectedNode != bodyElement))
|
||||
{
|
||||
res = InsertNode(aElement, parentSelectedNode, offsetOfNewNode);
|
||||
nsCOMPtr<nsIDOMNode> bodyNode = do_QueryInterface(bodyElement);
|
||||
PRBool isInline = PR_TRUE;
|
||||
while (isInline)
|
||||
{
|
||||
// Get parent of the top node to split
|
||||
res = topNodeToSplit->GetParentNode(getter_AddRefs(parentNodeOfInsert));
|
||||
// If Inline, we loop around to get the next parent level
|
||||
if (NS_SUCCEEDED(res) && parentNodeOfInsert &&
|
||||
NS_SUCCEEDED(IsNodeInline(topNodeToSplit, isInline)) &&
|
||||
NS_SUCCEEDED(GetChildOffset(topNodeToSplit, parentNodeOfInsert, offsetToInsertAt)))
|
||||
{
|
||||
#ifdef DEBUG_cmanske
|
||||
nsAutoString nodeName;
|
||||
topNodeToSplit->GetNodeName(nodeName);
|
||||
printf("Top Node to split: ");
|
||||
wprintf(nodeName.GetUnicode());
|
||||
|
||||
parentNodeOfInsert->GetNodeName(nodeName);
|
||||
printf(" Parent of this node: ");
|
||||
wprintf(nodeName.GetUnicode());
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
// The new offset to insert at is just after the topmost node we will split
|
||||
offsetToInsertAt++;
|
||||
} else {
|
||||
// Major failure if we get here
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
if (bodyNode != topNodeToSplit)
|
||||
{
|
||||
// We have the node to split and its parent.
|
||||
// TODO: Implement "CanContainElement" to be sure
|
||||
// we are allowed to insert aElement under parentNodeOfInsert
|
||||
// If we can't we should call special methods for various combintations
|
||||
// if (!CanContain(aElement, parentNodeOfInsert)
|
||||
// return NS_ERROR_FAILURE;
|
||||
|
||||
// Split nodes from the selection parent ("bottom node") and all intervening parents
|
||||
// up to the topmost node, which may be = to bottom node)
|
||||
// (This redistribute children as each level is split.)
|
||||
res = SplitNodeDeep(topNodeToSplit, parentSelectedNode, splitPointOffset);
|
||||
if (NS_SUCCEEDED(res))
|
||||
{
|
||||
//Insert the block element between the 2 "topmost" containers
|
||||
res = InsertNode(aElement, parentNodeOfInsert, offsetToInsertAt);
|
||||
|
||||
// Check for special case of inserting a table
|
||||
PRBool caretIsSet;
|
||||
res = SetCaretInTableCell(aElement, &caretIsSet);
|
||||
if (NS_SUCCEEDED(res) && caretIsSet)
|
||||
setCaretAfterElement = PR_FALSE;
|
||||
}
|
||||
} else {
|
||||
// If here, we must have an inline node directly under the body
|
||||
// so we can't insert a block tag
|
||||
// TODO: Take each inline node resulting from DeleteSelectionAndPrepareToCreateNode
|
||||
// and insert them each into a default paragraph.
|
||||
// Then insert new block node between them.
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (NS_SUCCEEDED(res))
|
||||
if (setCaretAfterElement && NS_SUCCEEDED(res))
|
||||
SetCaretAfterElement(aElement);
|
||||
return res;
|
||||
}
|
||||
|
@ -2452,6 +2496,77 @@ nsHTMLEditor::SelectElement(nsIDOMElement* aElement)
|
|||
return res;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::SetCaretInTableCell(nsIDOMElement* aElement, PRBool* caretIsSet)
|
||||
{
|
||||
nsresult res = NS_ERROR_NULL_POINTER;
|
||||
if (caretIsSet)
|
||||
*caretIsSet = PR_FALSE;
|
||||
if (aElement && IsElementInBody(aElement))
|
||||
{
|
||||
res = NS_OK;
|
||||
nsAutoString tagName;
|
||||
aElement->GetNodeName(tagName);
|
||||
tagName.ToLowerCase();
|
||||
if (tagName == "td" || tagName == "tr" ||
|
||||
tagName == "th" || tagName == "td" ||
|
||||
tagName == "caption")
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aElement);
|
||||
nsCOMPtr<nsIDOMNode> parent;
|
||||
// This MUST succeed if IsElementInBody was TRUE
|
||||
node->GetParentNode(getter_AddRefs(parent));
|
||||
nsCOMPtr<nsIDOMNode>firstChild;
|
||||
// Find deepest child
|
||||
PRBool hasChild;
|
||||
while (NS_SUCCEEDED(node->HasChildNodes(&hasChild)) && hasChild)
|
||||
{
|
||||
if (NS_SUCCEEDED(node->GetFirstChild(getter_AddRefs(firstChild))))
|
||||
{
|
||||
parent = node;
|
||||
node = firstChild;
|
||||
}
|
||||
}
|
||||
PRInt32 offset = 0;
|
||||
nsCOMPtr<nsIDOMNode>lastChild;
|
||||
res = parent->GetLastChild(getter_AddRefs(lastChild));
|
||||
if (NS_SUCCEEDED(res) && lastChild && node != lastChild)
|
||||
{
|
||||
if (node == lastChild)
|
||||
{
|
||||
// Check if node is text and has more than just a  
|
||||
nsCOMPtr<nsIDOMCharacterData>textNode = do_QueryInterface(node);
|
||||
nsString text;
|
||||
char nbspStr[2] = {nbsp, 0};
|
||||
if (textNode && textNode->GetData(text))
|
||||
{
|
||||
// Set selection relative to the text node
|
||||
parent = node;
|
||||
PRInt32 len = text.Length();
|
||||
if (len > 1 || text != nbspStr)
|
||||
{
|
||||
offset = len;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// We have > 1 node, so set to end of content
|
||||
}
|
||||
}
|
||||
// Set selection at beginning of deepest node
|
||||
// Should we set
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
res = nsEditor::GetSelection(getter_AddRefs(selection));
|
||||
if (NS_SUCCEEDED(res) && selection)
|
||||
{
|
||||
res = selection->Collapse(parent, offset);
|
||||
if (NS_SUCCEEDED(res) && caretIsSet)
|
||||
*caretIsSet = PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::SetCaretAfterElement(nsIDOMElement* aElement)
|
||||
{
|
||||
|
@ -2464,8 +2579,8 @@ nsHTMLEditor::SetCaretAfterElement(nsIDOMElement* aElement)
|
|||
|
||||
nsresult res = NS_ERROR_NULL_POINTER;
|
||||
|
||||
// Must be sure that element is contained in the document body
|
||||
if (IsElementInBody(aElement))
|
||||
// Be sure the element is contained in the document body
|
||||
if (aElement && IsElementInBody(aElement))
|
||||
{
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
res = nsEditor::GetSelection(getter_AddRefs(selection));
|
||||
|
@ -2477,11 +2592,12 @@ nsHTMLEditor::SetCaretAfterElement(nsIDOMElement* aElement)
|
|||
{
|
||||
PRInt32 offsetInParent;
|
||||
res = GetChildOffset(aElement, parent, offsetInParent);
|
||||
|
||||
// New collapsed selection will be just after the new element
|
||||
offsetInParent++;
|
||||
if (NS_SUCCEEDED(res))
|
||||
{
|
||||
// Collapse selection to just after desired element,
|
||||
selection->Collapse(parent, offsetInParent+1);
|
||||
// Collapse selection to just after desired element,
|
||||
selection->Collapse(parent, offsetInParent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -124,6 +124,9 @@ public:
|
|||
// End of methods implemented in nsEditor
|
||||
//=============================================================
|
||||
// HTML Editing methods
|
||||
|
||||
// This sets background on the appropriate container element (table, cell,)
|
||||
// or calls into nsTextEditor to set the page background
|
||||
NS_IMETHOD SetBackgroundColor(const nsString& aColor);
|
||||
NS_IMETHOD SetBodyAttribute(const nsString& aAttr, const nsString& aValue);
|
||||
NS_IMETHOD GetParagraphStyle(nsStringArray *aTagList);
|
||||
|
@ -154,6 +157,7 @@ public:
|
|||
NS_IMETHOD InsertLinkAroundSelection(nsIDOMElement* aAnchorElement);
|
||||
PRBool IsElementInBody(nsIDOMElement* aElement);
|
||||
NS_IMETHOD SelectElement(nsIDOMElement* aElement);
|
||||
NS_IMETHOD SetCaretInTableCell(nsIDOMElement* aElement, PRBool* caretIsSet);
|
||||
NS_IMETHOD SetCaretAfterElement(nsIDOMElement* aElement);
|
||||
|
||||
// Table Editing (implemented in EditTable.cpp)
|
||||
|
|
|
@ -2907,6 +2907,30 @@ nsTextEditor::SetTypeInStateForProperty(TypeInState &aTypeInState,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsTextEditor::SetBackgroundColor(const nsString& aColor)
|
||||
{
|
||||
// This is done in nsHTMLEditor::SetBackgroundColor should we do it here?
|
||||
#ifdef ENABLE_JS_EDITOR_LOG
|
||||
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
||||
|
||||
if (mJSEditorLog)
|
||||
mJSEditorLog->SetBackgroundColor(aColor);
|
||||
#endif // ENABLE_JS_EDITOR_LOG
|
||||
|
||||
nsresult res;
|
||||
NS_ASSERTION(mDoc, "Missing Editor DOM Document");
|
||||
|
||||
// Set the background color attribute on the body tag
|
||||
nsCOMPtr<nsIDOMElement> bodyElement;
|
||||
res = nsEditor::GetBodyElement(getter_AddRefs(bodyElement));
|
||||
if (NS_SUCCEEDED(res) && bodyElement)
|
||||
{
|
||||
nsAutoEditBatch beginBatching(this);
|
||||
bodyElement->SetAttribute("bgcolor", aColor);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// This file should be rearranged to put all methods that simply call nsEditor together
|
||||
NS_IMETHODIMP
|
||||
nsTextEditor::CopyAttributes(nsIDOMNode *aDestNode, nsIDOMNode *aSourceNode)
|
||||
|
|
|
@ -74,6 +74,8 @@ public:
|
|||
NS_IMETHOD SetMaxTextLength(PRInt32 aMaxTextLength);
|
||||
NS_IMETHOD InsertBreak();
|
||||
NS_IMETHOD CopyAttributes(nsIDOMNode *aDestNode, nsIDOMNode *aSourceNode);
|
||||
// This method sets background of the page (the body tag)
|
||||
NS_IMETHOD SetBackgroundColor(const nsString& aColor);
|
||||
|
||||
// Transaction control
|
||||
NS_IMETHOD EnableUndo(PRBool aEnable);
|
||||
|
|
|
@ -973,9 +973,8 @@ nsEditorShell::CloseWindow()
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
mWebShellWin->Close();
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
|
|
@ -247,6 +247,8 @@ class nsEditorShell : public nsIEditorShell,
|
|||
nsStringArray mSuggestedWordList;
|
||||
PRInt32 mSuggestedWordIndex;
|
||||
NS_IMETHOD DeleteSuggestedWordList();
|
||||
nsStringArray mDictionaryList;
|
||||
PRInt32 mDictionaryIndex;
|
||||
|
||||
typedef enum {
|
||||
ePlainTextEditorType = 1,
|
||||
|
|
|
@ -56,6 +56,14 @@ NS_IMETHODIMP InsertTextTxn::Init(nsIDOMCharacterData *aElement,
|
|||
const nsString &aStringToInsert,
|
||||
nsIPresShell *aPresShell)
|
||||
{
|
||||
#if 0 //def DEBUG_cmanske
|
||||
nsString text;
|
||||
aElement->GetData(text);
|
||||
printf("InsertTextTxn: Offset to insert at = %d. Text of the node to insert into:\n", aOffset);
|
||||
wprintf(text.GetUnicode());
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
mElement = do_QueryInterface(aElement);
|
||||
mOffset = aOffset;
|
||||
mStringToInsert = aStringToInsert;
|
||||
|
|
|
@ -1754,7 +1754,7 @@ nsEditor::InsertText(const nsString& aStringToInsert)
|
|||
if (NS_SUCCEEDED(result) && NS_SUCCEEDED(selection->GetAnchorOffset(&offset)) && selectedNode)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> newNode;
|
||||
result = CreateNode(GetTextNodeTag(), selectedNode, offset+1,
|
||||
result = CreateNode(GetTextNodeTag(), selectedNode, offset, // offset+1, why the +1???
|
||||
getter_AddRefs(newNode));
|
||||
if (NS_SUCCEEDED(result) && newNode)
|
||||
{
|
||||
|
@ -1795,6 +1795,23 @@ NS_IMETHODIMP nsEditor::CreateTxnForInsertText(const nsString & aStringToInsert,
|
|||
result = mPresShell->GetSelection(getter_AddRefs(selection));
|
||||
if ((NS_SUCCEEDED(result)) && selection)
|
||||
{
|
||||
#if 0
|
||||
// Trap the simple case where the collapsed selection
|
||||
// is pointing to the beginning of a text node.
|
||||
// That's where we should insert new text
|
||||
// *** If we don't do this, we will return NS_ERROR_EDITOR_NO_TEXTNODE
|
||||
// from the iterator block below.
|
||||
// This may be OK, now that I fixed InsertText so it inserts
|
||||
// at the offset of the selection anchor (i.e., the caret offset)
|
||||
// instead of at offset+1
|
||||
PRBool collapsed
|
||||
result = selection->GetIsCollapsed(&collapsed);
|
||||
if (NS_SUCCEEDED(result) && collapsed)
|
||||
{
|
||||
// Check if the node at selection offset is a textNode
|
||||
// and use that with offset = 0.
|
||||
}
|
||||
#endif
|
||||
result = NS_ERROR_UNEXPECTED;
|
||||
nsCOMPtr<nsIEnumerator> enumerator;
|
||||
enumerator = do_QueryInterface(selection);
|
||||
|
@ -2007,6 +2024,14 @@ NS_IMETHODIMP nsEditor::DeleteSelectionAndPrepareToCreateNode(nsCOMPtr<nsIDOMNod
|
|||
PRUint32 selectedNodeContentCount=0;
|
||||
nsCOMPtr<nsIDOMCharacterData>selectedParentNodeAsText;
|
||||
selectedParentNodeAsText = do_QueryInterface(parentSelectedNode);
|
||||
#ifdef DEBUG_cmanske
|
||||
// What is the parent node for the selection?
|
||||
nsAutoString tag;
|
||||
parentSelectedNode->GetNodeName(tag);
|
||||
printf("Parent of selected node's NodeName = ");
|
||||
wprintf(tag.GetUnicode());
|
||||
printf("\n");
|
||||
#endif
|
||||
/* if the selection is a text node, split the text node if necesary
|
||||
and compute where to put the new node
|
||||
*/
|
||||
|
@ -2050,15 +2075,38 @@ NS_IMETHODIMP nsEditor::DeleteSelectionAndPrepareToCreateNode(nsCOMPtr<nsIDOMNod
|
|||
result = parentChildList->Item(offsetOfSelectedNode, getter_AddRefs(selectedNode));
|
||||
if ((NS_SUCCEEDED(result)) && selectedNode)
|
||||
{
|
||||
#if 0 //def DEBUG_cmanske
|
||||
// What is the item at the selected offset?
|
||||
nsAutoString tag;
|
||||
selectedNode->GetNodeName(tag);
|
||||
printf("Selected Node's name = ");
|
||||
wprintf(tag.GetUnicode());
|
||||
printf("\n");
|
||||
#endif
|
||||
nsCOMPtr<nsIDOMCharacterData>selectedNodeAsText;
|
||||
selectedNodeAsText = do_QueryInterface(selectedNode);
|
||||
nsCOMPtr<nsIDOMNodeList>childList;
|
||||
selectedNode->GetChildNodes(getter_AddRefs(childList));
|
||||
if ((NS_SUCCEEDED(result)) && childList) {
|
||||
childList->GetLength(&selectedNodeContentCount);
|
||||
//CM: I added "result ="
|
||||
result = selectedNode->GetChildNodes(getter_AddRefs(childList));
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
if (childList)
|
||||
{
|
||||
childList->GetLength(&selectedNodeContentCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is the case where the collapsed selection offset
|
||||
// points to an inline node with no children
|
||||
// This must also be where the new node should be inserted
|
||||
// and there is no splitting necessary
|
||||
offsetOfNewNode = offsetOfSelectedNode;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
else
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if ((offsetOfSelectedNode!=0) && (((PRUint32)offsetOfSelectedNode)!=selectedNodeContentCount))
|
||||
{
|
||||
|
|
|
@ -43,7 +43,6 @@
|
|||
#include "nsFileSpec.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIFileWidget.h" // for GetLocalFileURL stuff
|
||||
#include "nsWidgetsCID.h"
|
||||
#include "nsIDocumentEncoder.h"
|
||||
#include "nsIPref.h"
|
||||
|
@ -51,6 +50,8 @@
|
|||
#include "nsIPresShell.h"
|
||||
#include "prprf.h"
|
||||
|
||||
const unsigned char nbsp = 160;
|
||||
|
||||
#ifdef ENABLE_JS_EDITOR_LOG
|
||||
#include "nsJSEditorLog.h"
|
||||
#endif // ENABLE_JS_EDITOR_LOG
|
||||
|
@ -165,28 +166,22 @@ NS_IMETHODIMP nsHTMLEditor::InsertText(const nsString& aStringToInsert)
|
|||
|
||||
NS_IMETHODIMP nsHTMLEditor::SetBackgroundColor(const nsString& aColor)
|
||||
{
|
||||
#ifdef ENABLE_JS_EDITOR_LOG
|
||||
// nsresult result;
|
||||
NS_ASSERTION(mDoc, "Missing Editor DOM Document");
|
||||
|
||||
// TODO: Check selection for Cell, Row, Column or table and do color on appropriate level
|
||||
// For initial testing, just set the background on the BODY tag (the document's background)
|
||||
|
||||
// Do this only if setting a table or cell background
|
||||
// It will be called in nsTextEditor::SetBackgroundColor for the page background
|
||||
#if 0 //def ENABLE_JS_EDITOR_LOG
|
||||
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
||||
|
||||
if (mJSEditorLog)
|
||||
mJSEditorLog->SetBackgroundColor(aColor);
|
||||
#endif // ENABLE_JS_EDITOR_LOG
|
||||
|
||||
nsresult res;
|
||||
NS_ASSERTION(mDoc, "Missing Editor DOM Document");
|
||||
|
||||
// TODO: Check selection for Cell, Row, Column or table and do color on appropriate level
|
||||
// For initial testing, just set the background on the BODY tag (the document's background)
|
||||
|
||||
// Set the background color attribute on the body tag
|
||||
nsCOMPtr<nsIDOMElement> bodyElement;
|
||||
res = nsEditor::GetBodyElement(getter_AddRefs(bodyElement));
|
||||
if (NS_SUCCEEDED(res) && bodyElement)
|
||||
{
|
||||
nsAutoEditBatch beginBatching(this);
|
||||
bodyElement->SetAttribute("bgcolor", aColor);
|
||||
}
|
||||
return res;
|
||||
return nsTextEditor::SetBackgroundColor(aColor);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsHTMLEditor::SetBodyAttribute(const nsString& aAttribute, const nsString& aValue)
|
||||
|
@ -2058,12 +2053,7 @@ nsHTMLEditor::CreateElementWithDefaults(const nsString& aTagName, nsIDOMElement*
|
|||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Set default values for new elements
|
||||
// TODO: These should probably be in XUL or prefs?
|
||||
if (isAnchor)
|
||||
{
|
||||
// TODO: Get the text of the selection and build a suggested Name
|
||||
// Replace spaces with "_"
|
||||
} else if (TagName.Equals("hr"))
|
||||
if (TagName.Equals("hr"))
|
||||
{
|
||||
// Hard coded defaults in case there's no prefs
|
||||
nsAutoString align("center");
|
||||
|
@ -2126,49 +2116,31 @@ nsHTMLEditor::CreateElementWithDefaults(const nsString& aTagName, nsIDOMElement*
|
|||
{
|
||||
newElement->SetAttribute("cellpadding","2");
|
||||
newElement->SetAttribute("cellspacing","2");
|
||||
newElement->SetAttribute("width","50%");
|
||||
newElement->SetAttribute("border","1");
|
||||
} else if (TagName.Equals("tr"))
|
||||
{
|
||||
newElement->SetAttribute("valign","top");
|
||||
} else if (TagName.Equals("td"))
|
||||
{
|
||||
newElement->SetAttribute("width","40px");
|
||||
newElement->SetAttribute("height","40px");
|
||||
newElement->SetAttribute("valign","top");
|
||||
|
||||
// Insert the default space in a cell so border displays
|
||||
nsCOMPtr<nsIDOMNode> newCellNode = do_QueryInterface(newElement);
|
||||
if (newCellNode)
|
||||
{
|
||||
|
||||
// First create a parent paragraph node
|
||||
// THIS SHOULD BE A RULE METHOD -- SOMETHING LIKE CreateParagraphNode
|
||||
nsCOMPtr<nsIDOMElement> mozDivElement;
|
||||
nsresult result = mDoc->CreateElement("div", getter_AddRefs(mozDivElement));
|
||||
|
||||
if (NS_SUCCEEDED(result) && mozDivElement)
|
||||
// TODO: This should probably be in the RULES code or
|
||||
// preference based for "should we add the nbsp"
|
||||
nsCOMPtr<nsIDOMText>newTextNode;
|
||||
nsString space;
|
||||
// Set contents to the   character by concatanating the char code
|
||||
space += nbsp;
|
||||
// If we fail here, we return NS_OK anyway, since we have an OK cell node
|
||||
nsresult result = mDoc->CreateTextNode(space, getter_AddRefs(newTextNode));
|
||||
if (NS_SUCCEEDED(result) && newTextNode)
|
||||
{
|
||||
// Set the 'class' attribute needed so Composer 4.x doesn't eat the div
|
||||
mozDivElement->SetAttribute("class", "moz-p");
|
||||
|
||||
nsCOMPtr<nsIDOMNode>resultNode;
|
||||
nsCOMPtr<nsIDOMNode> mozDivNode = do_QueryInterface(mozDivElement);
|
||||
result = newCellNode->AppendChild(mozDivNode, getter_AddRefs(resultNode));
|
||||
|
||||
if (NS_SUCCEEDED(result) && resultNode)
|
||||
{
|
||||
// Append a text node
|
||||
nsCOMPtr<nsIDOMText>newTextNode;
|
||||
nsString space;
|
||||
// Set contents to the   character by concatanating the char code
|
||||
space += 160;
|
||||
result = mDoc->CreateTextNode(space, getter_AddRefs(newTextNode));
|
||||
if (NS_SUCCEEDED(result) && newTextNode)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode>resultNode2;
|
||||
result = mozDivNode->AppendChild(newTextNode, getter_AddRefs(resultNode2));
|
||||
}
|
||||
}
|
||||
result = newCellNode->AppendChild(newTextNode, getter_AddRefs(resultNode));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2204,9 +2176,11 @@ nsHTMLEditor::InsertElement(nsIDOMElement* aElement, PRBool aDeleteSelection)
|
|||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsAutoEditBatch beginBatching(this);
|
||||
// For most elements, set caret after inserting
|
||||
PRBool setCaretAfterElement = PR_TRUE;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> parentSelectedNode;
|
||||
PRInt32 offsetOfNewNode;
|
||||
PRInt32 splitPointOffset;
|
||||
|
||||
nsCOMPtr<nsIDOMSelection>selection;
|
||||
res = nsEditor::GetSelection(getter_AddRefs(selection));
|
||||
|
@ -2257,32 +2231,102 @@ nsHTMLEditor::InsertElement(nsIDOMElement* aElement, PRBool aDeleteSelection)
|
|||
}
|
||||
}
|
||||
|
||||
res = DeleteSelectionAndPrepareToCreateNode(parentSelectedNode, offsetOfNewNode);
|
||||
res = DeleteSelectionAndPrepareToCreateNode(parentSelectedNode, splitPointOffset);
|
||||
if (NS_SUCCEEDED(res))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> newNode = do_QueryInterface(aElement);
|
||||
PRBool isInline;
|
||||
res = IsNodeInline(newNode, isInline);
|
||||
if( NS_SUCCEEDED(res) /*&& isInline*/)
|
||||
if( NS_SUCCEEDED(res) && isInline)
|
||||
{
|
||||
// The simple case of an inline node
|
||||
res = InsertNode(aElement, parentSelectedNode, offsetOfNewNode);
|
||||
// This will split any inline nodes at the caret
|
||||
// and insert between them
|
||||
res = InsertNode(aElement, parentSelectedNode, splitPointOffset);
|
||||
} else {
|
||||
// Inserting a BLOCK element:
|
||||
// TODO: Start with parentSelectedNode and check if its a block that can accept the
|
||||
// block node we want to insert as its child. For initial testing, assume its OK
|
||||
//
|
||||
// Get the parent of the paragraph/container
|
||||
nsCOMPtr<nsIDOMNode> parentNode;
|
||||
parentSelectedNode->GetParentNode(getter_AddRefs(parentNode));
|
||||
res = SplitNodeDeep(parentSelectedNode, parentSelectedNode, offsetOfNewNode);
|
||||
if (NS_SUCCEEDED(res))
|
||||
// Inserting a BLOCK element
|
||||
// Get the first block parent of the paragraph/container
|
||||
// which we can split to create insert location
|
||||
// (Current parent may already be a suitable block to split)
|
||||
nsCOMPtr<nsIDOMNode> parentNodeOfInsert = parentSelectedNode;
|
||||
nsCOMPtr<nsIDOMNode> topNodeToSplit = parentSelectedNode;
|
||||
nsCOMPtr<nsIDOMElement> bodyElement;
|
||||
// We need to find the offset at each level we will split
|
||||
// to use when we insert the new element
|
||||
PRInt32 offsetToInsertAt = splitPointOffset;
|
||||
|
||||
res = nsEditor::GetBodyElement(getter_AddRefs(bodyElement));
|
||||
|
||||
if (NS_SUCCEEDED(res) && bodyElement &&
|
||||
// If text node is direct child of body, we can't insert a block node
|
||||
(parentSelectedNode != bodyElement))
|
||||
{
|
||||
res = InsertNode(aElement, parentSelectedNode, offsetOfNewNode);
|
||||
nsCOMPtr<nsIDOMNode> bodyNode = do_QueryInterface(bodyElement);
|
||||
PRBool isInline = PR_TRUE;
|
||||
while (isInline)
|
||||
{
|
||||
// Get parent of the top node to split
|
||||
res = topNodeToSplit->GetParentNode(getter_AddRefs(parentNodeOfInsert));
|
||||
// If Inline, we loop around to get the next parent level
|
||||
if (NS_SUCCEEDED(res) && parentNodeOfInsert &&
|
||||
NS_SUCCEEDED(IsNodeInline(topNodeToSplit, isInline)) &&
|
||||
NS_SUCCEEDED(GetChildOffset(topNodeToSplit, parentNodeOfInsert, offsetToInsertAt)))
|
||||
{
|
||||
#ifdef DEBUG_cmanske
|
||||
nsAutoString nodeName;
|
||||
topNodeToSplit->GetNodeName(nodeName);
|
||||
printf("Top Node to split: ");
|
||||
wprintf(nodeName.GetUnicode());
|
||||
|
||||
parentNodeOfInsert->GetNodeName(nodeName);
|
||||
printf(" Parent of this node: ");
|
||||
wprintf(nodeName.GetUnicode());
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
// The new offset to insert at is just after the topmost node we will split
|
||||
offsetToInsertAt++;
|
||||
} else {
|
||||
// Major failure if we get here
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
if (bodyNode != topNodeToSplit)
|
||||
{
|
||||
// We have the node to split and its parent.
|
||||
// TODO: Implement "CanContainElement" to be sure
|
||||
// we are allowed to insert aElement under parentNodeOfInsert
|
||||
// If we can't we should call special methods for various combintations
|
||||
// if (!CanContain(aElement, parentNodeOfInsert)
|
||||
// return NS_ERROR_FAILURE;
|
||||
|
||||
// Split nodes from the selection parent ("bottom node") and all intervening parents
|
||||
// up to the topmost node, which may be = to bottom node)
|
||||
// (This redistribute children as each level is split.)
|
||||
res = SplitNodeDeep(topNodeToSplit, parentSelectedNode, splitPointOffset);
|
||||
if (NS_SUCCEEDED(res))
|
||||
{
|
||||
//Insert the block element between the 2 "topmost" containers
|
||||
res = InsertNode(aElement, parentNodeOfInsert, offsetToInsertAt);
|
||||
|
||||
// Check for special case of inserting a table
|
||||
PRBool caretIsSet;
|
||||
res = SetCaretInTableCell(aElement, &caretIsSet);
|
||||
if (NS_SUCCEEDED(res) && caretIsSet)
|
||||
setCaretAfterElement = PR_FALSE;
|
||||
}
|
||||
} else {
|
||||
// If here, we must have an inline node directly under the body
|
||||
// so we can't insert a block tag
|
||||
// TODO: Take each inline node resulting from DeleteSelectionAndPrepareToCreateNode
|
||||
// and insert them each into a default paragraph.
|
||||
// Then insert new block node between them.
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (NS_SUCCEEDED(res))
|
||||
if (setCaretAfterElement && NS_SUCCEEDED(res))
|
||||
SetCaretAfterElement(aElement);
|
||||
return res;
|
||||
}
|
||||
|
@ -2452,6 +2496,77 @@ nsHTMLEditor::SelectElement(nsIDOMElement* aElement)
|
|||
return res;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::SetCaretInTableCell(nsIDOMElement* aElement, PRBool* caretIsSet)
|
||||
{
|
||||
nsresult res = NS_ERROR_NULL_POINTER;
|
||||
if (caretIsSet)
|
||||
*caretIsSet = PR_FALSE;
|
||||
if (aElement && IsElementInBody(aElement))
|
||||
{
|
||||
res = NS_OK;
|
||||
nsAutoString tagName;
|
||||
aElement->GetNodeName(tagName);
|
||||
tagName.ToLowerCase();
|
||||
if (tagName == "td" || tagName == "tr" ||
|
||||
tagName == "th" || tagName == "td" ||
|
||||
tagName == "caption")
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aElement);
|
||||
nsCOMPtr<nsIDOMNode> parent;
|
||||
// This MUST succeed if IsElementInBody was TRUE
|
||||
node->GetParentNode(getter_AddRefs(parent));
|
||||
nsCOMPtr<nsIDOMNode>firstChild;
|
||||
// Find deepest child
|
||||
PRBool hasChild;
|
||||
while (NS_SUCCEEDED(node->HasChildNodes(&hasChild)) && hasChild)
|
||||
{
|
||||
if (NS_SUCCEEDED(node->GetFirstChild(getter_AddRefs(firstChild))))
|
||||
{
|
||||
parent = node;
|
||||
node = firstChild;
|
||||
}
|
||||
}
|
||||
PRInt32 offset = 0;
|
||||
nsCOMPtr<nsIDOMNode>lastChild;
|
||||
res = parent->GetLastChild(getter_AddRefs(lastChild));
|
||||
if (NS_SUCCEEDED(res) && lastChild && node != lastChild)
|
||||
{
|
||||
if (node == lastChild)
|
||||
{
|
||||
// Check if node is text and has more than just a  
|
||||
nsCOMPtr<nsIDOMCharacterData>textNode = do_QueryInterface(node);
|
||||
nsString text;
|
||||
char nbspStr[2] = {nbsp, 0};
|
||||
if (textNode && textNode->GetData(text))
|
||||
{
|
||||
// Set selection relative to the text node
|
||||
parent = node;
|
||||
PRInt32 len = text.Length();
|
||||
if (len > 1 || text != nbspStr)
|
||||
{
|
||||
offset = len;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// We have > 1 node, so set to end of content
|
||||
}
|
||||
}
|
||||
// Set selection at beginning of deepest node
|
||||
// Should we set
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
res = nsEditor::GetSelection(getter_AddRefs(selection));
|
||||
if (NS_SUCCEEDED(res) && selection)
|
||||
{
|
||||
res = selection->Collapse(parent, offset);
|
||||
if (NS_SUCCEEDED(res) && caretIsSet)
|
||||
*caretIsSet = PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::SetCaretAfterElement(nsIDOMElement* aElement)
|
||||
{
|
||||
|
@ -2464,8 +2579,8 @@ nsHTMLEditor::SetCaretAfterElement(nsIDOMElement* aElement)
|
|||
|
||||
nsresult res = NS_ERROR_NULL_POINTER;
|
||||
|
||||
// Must be sure that element is contained in the document body
|
||||
if (IsElementInBody(aElement))
|
||||
// Be sure the element is contained in the document body
|
||||
if (aElement && IsElementInBody(aElement))
|
||||
{
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
res = nsEditor::GetSelection(getter_AddRefs(selection));
|
||||
|
@ -2477,11 +2592,12 @@ nsHTMLEditor::SetCaretAfterElement(nsIDOMElement* aElement)
|
|||
{
|
||||
PRInt32 offsetInParent;
|
||||
res = GetChildOffset(aElement, parent, offsetInParent);
|
||||
|
||||
// New collapsed selection will be just after the new element
|
||||
offsetInParent++;
|
||||
if (NS_SUCCEEDED(res))
|
||||
{
|
||||
// Collapse selection to just after desired element,
|
||||
selection->Collapse(parent, offsetInParent+1);
|
||||
// Collapse selection to just after desired element,
|
||||
selection->Collapse(parent, offsetInParent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -124,6 +124,9 @@ public:
|
|||
// End of methods implemented in nsEditor
|
||||
//=============================================================
|
||||
// HTML Editing methods
|
||||
|
||||
// This sets background on the appropriate container element (table, cell,)
|
||||
// or calls into nsTextEditor to set the page background
|
||||
NS_IMETHOD SetBackgroundColor(const nsString& aColor);
|
||||
NS_IMETHOD SetBodyAttribute(const nsString& aAttr, const nsString& aValue);
|
||||
NS_IMETHOD GetParagraphStyle(nsStringArray *aTagList);
|
||||
|
@ -154,6 +157,7 @@ public:
|
|||
NS_IMETHOD InsertLinkAroundSelection(nsIDOMElement* aAnchorElement);
|
||||
PRBool IsElementInBody(nsIDOMElement* aElement);
|
||||
NS_IMETHOD SelectElement(nsIDOMElement* aElement);
|
||||
NS_IMETHOD SetCaretInTableCell(nsIDOMElement* aElement, PRBool* caretIsSet);
|
||||
NS_IMETHOD SetCaretAfterElement(nsIDOMElement* aElement);
|
||||
|
||||
// Table Editing (implemented in EditTable.cpp)
|
||||
|
|
|
@ -123,6 +123,11 @@ public:
|
|||
*/
|
||||
NS_IMETHOD RemoveTextProperty(nsIAtom *aProperty, const nsString *aAttribute)=0;
|
||||
|
||||
/**
|
||||
* Set the background color of the the document background
|
||||
*/
|
||||
NS_IMETHOD SetBackgroundColor(const nsString& aColor)=0;
|
||||
|
||||
/**
|
||||
* DeleteSelection removes all nodes in the current selection.
|
||||
* @param aDir if eLTR, delete to the right (for example, the DEL key)
|
||||
|
|
|
@ -267,7 +267,6 @@
|
|||
<menu name="&fileMenu.label;">
|
||||
<menuitem name="&newCmd.label;" onclick="EditorNew()"/>
|
||||
<menuitem name="&openCmd.label;" onclick="EditorOpen()"/>
|
||||
<menuitem name="&closeCmd.label;" onclick="EditorClose()"/>
|
||||
<separator />
|
||||
<menuitem name="&saveCmd.label;" onclick="EditorSave()"/>
|
||||
<menuitem name="&saveAsCmd.label;" onclick="EditorSaveAs()"/>
|
||||
|
@ -276,6 +275,7 @@
|
|||
<menuitem name="&printPreviewCmd.label;" onclick="EditorPrintPreview()"/>
|
||||
<menuitem name="&printCmd.label;" onclick="EditorPrint()"/>
|
||||
<separator />
|
||||
<menuitem name="&closeCmd.label;" onclick="EditorClose()"/>
|
||||
<menuitem name="&quitCmd.label;" onclick="EditorExit()"/>
|
||||
</menu>
|
||||
|
||||
|
|
|
@ -25,13 +25,16 @@ function EditorStartup(editorType)
|
|||
dump("Doing Startup...\n");
|
||||
contentWindow = window.content;
|
||||
|
||||
dump("Trying to make an editor appcore through the component manager...\n");
|
||||
dump("Trying to make an Editor Shell through the component manager...\n");
|
||||
|
||||
var editorShell = Components.classes["component://netscape/editor/editorshell"].createInstance();
|
||||
editorShell = editorShell.QueryInterface(Components.interfaces.nsIEditorShell);
|
||||
editorShell = Components.classes["component://netscape/editor/editorshell"].createInstance();
|
||||
if (editorShell)
|
||||
editorShell = editorShell.QueryInterface(Components.interfaces.nsIEditorShell);
|
||||
|
||||
if (!editorShell)
|
||||
{
|
||||
dump("Failed to create editor shell\n");
|
||||
// 7/12/99 THIS DOESN'T WORK YET!
|
||||
window.close();
|
||||
return;
|
||||
}
|
||||
|
@ -39,16 +42,16 @@ function EditorStartup(editorType)
|
|||
// store the editor shell in the window, so that child windows can get to it.
|
||||
window.editorShell = editorShell;
|
||||
|
||||
window.editorShell.Init();
|
||||
window.editorShell.SetWebShellWindow(window);
|
||||
window.editorShell.SetToolbarWindow(window)
|
||||
window.editorShell.SetEditorType(editorType);
|
||||
window.editorShell.SetContentWindow(contentWindow);
|
||||
editorShell.Init();
|
||||
editorShell.SetWebShellWindow(window);
|
||||
editorShell.SetToolbarWindow(window)
|
||||
editorShell.SetEditorType(editorType);
|
||||
editorShell.SetContentWindow(contentWindow);
|
||||
|
||||
// Get url for editor content and load it.
|
||||
// the editor gets instantiated by the editor shell when the URL has finished loading.
|
||||
var url = document.getElementById("args").getAttribute("value");
|
||||
window.editorShell.LoadUrl(url);
|
||||
editorShell.LoadUrl(url);
|
||||
|
||||
dump("EditorAppCore windows have been set.\n");
|
||||
SetupToolbarElements();
|
||||
|
@ -83,13 +86,13 @@ function EditorShutdown()
|
|||
function EditorNew()
|
||||
{
|
||||
dump("In EditorNew..\n");
|
||||
window.editorShell.NewWindow();
|
||||
editorShell.NewWindow();
|
||||
}
|
||||
|
||||
function EditorOpen()
|
||||
{
|
||||
dump("In EditorOpen..\n");
|
||||
window.editorShell.Open();
|
||||
editorShell.Open();
|
||||
}
|
||||
|
||||
function EditorNewPlaintext()
|
||||
|
@ -131,14 +134,14 @@ function EditorNewBrowser()
|
|||
function EditorSave()
|
||||
{
|
||||
dump("In EditorSave...\n");
|
||||
window.editorShell.Save();
|
||||
editorShell.Save();
|
||||
contentWindow.focus();
|
||||
}
|
||||
|
||||
function EditorSaveAs()
|
||||
{
|
||||
dump("In EditorSave...\n");
|
||||
window.editorShell.SaveAs();
|
||||
editorShell.SaveAs();
|
||||
contentWindow.focus();
|
||||
}
|
||||
|
||||
|
@ -146,14 +149,17 @@ function EditorSaveAs()
|
|||
function EditorPrint()
|
||||
{
|
||||
dump("In EditorPrint..\n");
|
||||
window.editorShell.Print();
|
||||
editorShell.Print();
|
||||
contentWindow.focus();
|
||||
}
|
||||
|
||||
function EditorClose()
|
||||
{
|
||||
dump("In EditorClose...\n");
|
||||
window.editorShell.CloseWindow();
|
||||
editorShell.CloseWindow();
|
||||
// This doesn't work, but we can close
|
||||
// the window in the EditorAppShell, so we don't need it
|
||||
//window.close();
|
||||
}
|
||||
|
||||
// --------------------------- Edit menu ---------------------------
|
||||
|
@ -161,62 +167,62 @@ function EditorClose()
|
|||
function EditorUndo()
|
||||
{
|
||||
dump("Undoing\n");
|
||||
window.editorShell.Undo();
|
||||
editorShell.Undo();
|
||||
contentWindow.focus();
|
||||
}
|
||||
|
||||
function EditorRedo()
|
||||
{
|
||||
dump("Redoing\n");
|
||||
window.editorShell.Redo();
|
||||
editorShell.Redo();
|
||||
contentWindow.focus();
|
||||
}
|
||||
|
||||
function EditorCut()
|
||||
{
|
||||
window.editorShell.Cut();
|
||||
editorShell.Cut();
|
||||
contentWindow.focus();
|
||||
}
|
||||
|
||||
function EditorCopy()
|
||||
{
|
||||
window.editorShell.Copy();
|
||||
editorShell.Copy();
|
||||
contentWindow.focus();
|
||||
}
|
||||
|
||||
function EditorPaste()
|
||||
{
|
||||
window.editorShell.Paste();
|
||||
editorShell.Paste();
|
||||
contentWindow.focus();
|
||||
}
|
||||
|
||||
function EditorPasteAsQuotation()
|
||||
{
|
||||
window.editorShell.PasteAsQuotation();
|
||||
editorShell.PasteAsQuotation();
|
||||
contentWindow.focus();
|
||||
}
|
||||
|
||||
function EditorPasteAsQuotationCited(citeString)
|
||||
{
|
||||
window.editorShell.PasteAsCitedQuotation(CiteString);
|
||||
editorShell.PasteAsCitedQuotation(CiteString);
|
||||
contentWindow.focus();
|
||||
}
|
||||
|
||||
function EditorSelectAll()
|
||||
{
|
||||
window.editorShell.SelectAll();
|
||||
editorShell.SelectAll();
|
||||
contentWindow.focus();
|
||||
}
|
||||
|
||||
function EditorFind()
|
||||
{
|
||||
window.editorShell.Find();
|
||||
editorShell.Find();
|
||||
contentWindow.focus();
|
||||
}
|
||||
|
||||
function EditorFindNext()
|
||||
{
|
||||
window.editorShell.FindNext();
|
||||
editorShell.FindNext();
|
||||
}
|
||||
|
||||
function EditorShowClipboard()
|
||||
|
@ -229,7 +235,7 @@ function EditorShowClipboard()
|
|||
function EditorSetDocumentCharacterSet(aCharset)
|
||||
{
|
||||
dump(aCharset);
|
||||
dump(" NOT IMPLEMENTED YET\n");
|
||||
editorShell.editorDocument.SetDocumentCharacterSet(aCharset);
|
||||
}
|
||||
|
||||
|
||||
|
@ -237,14 +243,14 @@ function EditorSetDocumentCharacterSet(aCharset)
|
|||
|
||||
function EditorSetTextProperty(property, attribute, value)
|
||||
{
|
||||
window.editorShell.SetTextProperty(property, attribute, value);
|
||||
editorShell.SetTextProperty(property, attribute, value);
|
||||
dump("Set text property -- calling focus()\n");
|
||||
contentWindow.focus();
|
||||
}
|
||||
|
||||
function EditorSetParagraphFormat(paraFormat)
|
||||
{
|
||||
window.editorShell.paragraphFormat = paraFormat;
|
||||
editorShell.paragraphFormat = paraFormat;
|
||||
contentWindow.focus();
|
||||
}
|
||||
|
||||
|
@ -253,11 +259,11 @@ function EditorSetFontSize(size)
|
|||
if( size == "0" || size == "normal" ||
|
||||
size == "+0" )
|
||||
{
|
||||
window.editorShell.RemoveTextProperty("font", size);
|
||||
editorShell.RemoveTextProperty("font", size);
|
||||
dump("Removing font size\n");
|
||||
} else {
|
||||
dump("Setting font size\n");
|
||||
window.editorShell.SetTextProperty("font", "size", size);
|
||||
editorShell.SetTextProperty("font", "size", size);
|
||||
}
|
||||
contentWindow.focus();
|
||||
}
|
||||
|
@ -265,40 +271,40 @@ function EditorSetFontSize(size)
|
|||
function EditorSetFontFace(fontFace)
|
||||
{
|
||||
if( fontFace == "" || fontFace == "normal") {
|
||||
window.editorShell.RemoveTextProperty("font", "face");
|
||||
editorShell.RemoveTextProperty("font", "face");
|
||||
} else if( fontFace == "tt") {
|
||||
// The old "teletype" attribute
|
||||
window.editorShell.SetTextProperty("tt", "", "");
|
||||
editorShell.SetTextProperty("tt", "", "");
|
||||
// Clear existing font face
|
||||
window.editorShell.RemoveTextProperty("font", "face");
|
||||
editorShell.RemoveTextProperty("font", "face");
|
||||
} else {
|
||||
window.editorShell.SetTextProperty("font", "face", fontFace);
|
||||
editorShell.SetTextProperty("font", "face", fontFace);
|
||||
}
|
||||
contentWindow.focus();
|
||||
}
|
||||
|
||||
function EditorSetFontColor(color)
|
||||
{
|
||||
window.editorShell.SetTextProperty("font", "color", color);
|
||||
editorShell.SetTextProperty("font", "color", color);
|
||||
contentWindow.focus();
|
||||
}
|
||||
|
||||
function EditorSetBackgroundColor(color)
|
||||
{
|
||||
window.editorShell.SetBackgroundColor(color);
|
||||
editorShell.SetBackgroundColor(color);
|
||||
contentWindow.focus();
|
||||
}
|
||||
|
||||
function EditorApplyStyle(styleName)
|
||||
{
|
||||
dump("applying style\n");
|
||||
window.editorShell.SetTextProperty(styleName, "", "");
|
||||
editorShell.SetTextProperty(styleName, "", "");
|
||||
contentWindow.focus();
|
||||
}
|
||||
|
||||
function EditorRemoveStyle(styleName)
|
||||
{
|
||||
window.editorShell.RemoveTextProperty(styleName, "");
|
||||
editorShell.RemoveTextProperty(styleName, "");
|
||||
contentWindow.focus();
|
||||
}
|
||||
|
||||
|
@ -310,7 +316,7 @@ function EditorRemoveLinks()
|
|||
|
||||
function EditorApplyStyleSheet(styleSheetURL)
|
||||
{
|
||||
window.editorShell.ApplyStyleSheet(styleSheetURL);
|
||||
editorShell.ApplyStyleSheet(styleSheetURL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -318,72 +324,61 @@ function EditorApplyStyleSheet(styleSheetURL)
|
|||
|
||||
function EditorGetText()
|
||||
{
|
||||
if (window.editorShell) {
|
||||
if (editorShell) {
|
||||
dump("Getting text\n");
|
||||
var outputText = window.editorShell.contentsAsText;
|
||||
var outputText = editorShell.contentsAsText;
|
||||
dump(outputText + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
function EditorGetHTML()
|
||||
{
|
||||
if (window.editorShell) {
|
||||
if (editorShell) {
|
||||
dump("Getting HTML\n");
|
||||
var outputText = window.editorShell.contentsAsHTML;
|
||||
var outputText = editorShell.contentsAsHTML;
|
||||
dump(outputText + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
function EditorInsertText(textToInsert)
|
||||
{
|
||||
if (window.editorShell) {
|
||||
window.editorShell.InsertText(textToInsert);
|
||||
}
|
||||
editorShell.InsertText(textToInsert);
|
||||
}
|
||||
|
||||
function EditorInsertHTML()
|
||||
{
|
||||
if (window.editorShell) {
|
||||
window.openDialog("chrome://editordlgs/content/EdInsSrc.xul",
|
||||
"InsSrcDlg", "chrome", "");
|
||||
}
|
||||
window.openDialog("chrome://editordlgs/content/EdInsSrc.xul",
|
||||
"InsSrcDlg", "chrome", "");
|
||||
}
|
||||
|
||||
function EditorInsertLink()
|
||||
{
|
||||
if (window.editorShell) {
|
||||
window.openDialog("chrome://editordlgs/content/EdLinkProps.xul", "LinkDlg", "chrome", "");
|
||||
}
|
||||
window.openDialog("chrome://editordlgs/content/EdLinkProps.xul", "LinkDlg", "chrome", "");
|
||||
contentWindow.focus();
|
||||
}
|
||||
|
||||
function EditorInsertImage()
|
||||
{
|
||||
if (window.editorShell) {
|
||||
window.openDialog("chrome://editordlgs/content/EdImageProps.xul", "dlg", "chrome", "");
|
||||
}
|
||||
window.openDialog("chrome://editordlgs/content/EdImageProps.xul", "dlg", "chrome", "");
|
||||
contentWindow.focus();
|
||||
}
|
||||
|
||||
function EditorInsertHLine()
|
||||
{
|
||||
if (window.editorShell) {
|
||||
// Inserting an HLine is different in that we don't use properties dialog
|
||||
// unless we are editing an existing line's attributes
|
||||
// We get the last-used attributes from the prefs and insert immediately
|
||||
|
||||
// Inserting an HLine is different in that we don't use properties dialog
|
||||
// unless we are editing an existing line's attributes
|
||||
// We get the last-used attributes from the prefs and insert immediately
|
||||
|
||||
tagName = "hr";
|
||||
hLine = window.editorShell.GetSelectedElement(tagName);
|
||||
tagName = "hr";
|
||||
hLine = editorShell.GetSelectedElement(tagName);
|
||||
|
||||
if (hLine) {
|
||||
// We only open the dialog for an existing HRule
|
||||
window.openDialog("chrome://editordlgs/content/EdHLineProps.xul", "dlg", "chrome", "");
|
||||
} else {
|
||||
hLine = editorShell.CreateElementWithDefaults(tagName);
|
||||
if (hLine) {
|
||||
// We only open the dialog for an existing HRule
|
||||
window.openDialog("chrome://editordlgs/content/EdHLineProps.xul", "dlg", "chrome", "");
|
||||
} else {
|
||||
hLine = window.editorShell.CreateElementWithDefaults(tagName);
|
||||
if (hLine) {
|
||||
window.editorShell.InsertElement(hLine, false);
|
||||
}
|
||||
editorShell.InsertElement(hLine, false);
|
||||
}
|
||||
}
|
||||
contentWindow.focus();
|
||||
|
@ -398,14 +393,14 @@ function EditorInsertNamedAnchor()
|
|||
function EditorIndent(indent)
|
||||
{
|
||||
dump("indenting\n");
|
||||
window.editorShell.Indent(indent);
|
||||
editorShell.Indent(indent);
|
||||
contentWindow.focus();
|
||||
}
|
||||
|
||||
function EditorInsertList(listType)
|
||||
{
|
||||
dump("Inserting list\n");
|
||||
window.editorShell.InsertList(listType);
|
||||
editorShell.InsertList(listType);
|
||||
contentWindow.focus();
|
||||
}
|
||||
|
||||
|
@ -426,7 +421,7 @@ function EditorInsertTable()
|
|||
function EditorAlign(align)
|
||||
{
|
||||
dump("aligning\n");
|
||||
window.editorShell.Align(align);
|
||||
editorShell.Align(align);
|
||||
contentWindow.focus();
|
||||
}
|
||||
|
||||
|
@ -438,7 +433,7 @@ function EditorPrintPreview()
|
|||
|
||||
function CheckSpelling()
|
||||
{
|
||||
var spellChecker = window.editorShell.QueryInterface(Components.interfaces.nsIEditorSpellCheck);
|
||||
var spellChecker = editorShell.QueryInterface(Components.interfaces.nsIEditorSpellCheck);
|
||||
if (spellChecker)
|
||||
{
|
||||
dump("Check Spelling starting...\n");
|
||||
|
@ -449,9 +444,11 @@ function CheckSpelling()
|
|||
{
|
||||
dump("THERE IS NO MISSPELLED WORD!\n");
|
||||
// TODO: PUT UP A MESSAGE BOX TO TELL THE USER
|
||||
window.editorShell.CloseSpellChecking();
|
||||
spellChecker.CloseSpellChecking();
|
||||
} else {
|
||||
dump("We found a MISSPELLED WORD\n");
|
||||
// Set spellChecker variable on window
|
||||
window.spellChecker = spellChecker;
|
||||
window.openDialog("chrome://editordlgs/content/EdSpellCheck.xul", "SpellDlg", "chrome", "", firstMisspelledWord);
|
||||
}
|
||||
}
|
||||
|
@ -467,9 +464,9 @@ function OnCreateAlignmentPopup()
|
|||
|
||||
function EditorApplyStyleSheet(url)
|
||||
{
|
||||
if (window.editorShell)
|
||||
if (editorShell)
|
||||
{
|
||||
window.editorShell.ApplyStyleSheet(url);
|
||||
editorShell.ApplyStyleSheet(url);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -524,21 +521,15 @@ function EditorStartLog()
|
|||
{
|
||||
var fs;
|
||||
|
||||
if (window.editorShell)
|
||||
{
|
||||
fs = EditorGetScriptFileSpec();
|
||||
window.editorShell.StartLogging(fs);
|
||||
fs = EditorGetScriptFileSpec();
|
||||
editorShell.StartLogging(fs);
|
||||
|
||||
fs = null;
|
||||
}
|
||||
fs = null;
|
||||
}
|
||||
|
||||
function EditorStopLog()
|
||||
{
|
||||
if (window.editorShell)
|
||||
{
|
||||
window.editorShell.StopLogging();
|
||||
}
|
||||
editorShell.StopLogging();
|
||||
}
|
||||
|
||||
function EditorRunLog()
|
||||
|
@ -553,7 +544,7 @@ function EditorGetNodeFromOffsets(offsets)
|
|||
var node = null;
|
||||
var i;
|
||||
|
||||
node = window.editorShell.editorDocument;
|
||||
node = editorShell.editorDocument;
|
||||
|
||||
for (i = 0; i < offsets.length; i++)
|
||||
{
|
||||
|
@ -566,7 +557,7 @@ function EditorGetNodeFromOffsets(offsets)
|
|||
function EditorSetSelectionFromOffsets(selRanges)
|
||||
{
|
||||
var rangeArr, start, end, i, node, offset;
|
||||
var selection = window.editorShell.editorSelection;
|
||||
var selection = editorShell.editorSelection;
|
||||
|
||||
selection.clearSelection();
|
||||
|
||||
|
@ -576,7 +567,7 @@ function EditorSetSelectionFromOffsets(selRanges)
|
|||
start = rangeArr[0];
|
||||
end = rangeArr[1];
|
||||
|
||||
var range = window.editorShell.editorDocument.createRange();
|
||||
var range = editorShell.editorDocument.createRange();
|
||||
|
||||
node = EditorGetNodeFromOffsets(start[0]);
|
||||
offset = start[1];
|
||||
|
@ -594,61 +585,51 @@ function EditorSetSelectionFromOffsets(selRanges)
|
|||
|
||||
function EditorTestSelection()
|
||||
{
|
||||
if (window.editorShell)
|
||||
dump("Testing selection\n");
|
||||
var selection = editorShell.editorSelection;
|
||||
if (selection)
|
||||
{
|
||||
dump("Testing selection\n");
|
||||
var selection = window.editorShell.editorSelection;
|
||||
if (selection)
|
||||
dump("Got selection\n");
|
||||
var firstRange = selection.getRangeAt(0);
|
||||
if (firstRange)
|
||||
{
|
||||
dump("Got selection\n");
|
||||
var firstRange = selection.getRangeAt(0);
|
||||
if (firstRange)
|
||||
{
|
||||
dump("Range contains \"");
|
||||
dump(firstRange.toString() + "\"\n");
|
||||
}
|
||||
dump("Range contains \"");
|
||||
dump(firstRange.toString() + "\"\n");
|
||||
}
|
||||
}
|
||||
|
||||
dump("Selection as text\n");
|
||||
dump(window.editorShell.selectionAsText + "\n\n");
|
||||
dump(editorShell.selectionAsText + "\n\n");
|
||||
|
||||
dump("Selection as HTML\n");
|
||||
dump(window.editorShell.selectionAsHTML + "\n\n");
|
||||
dump(editorShell.selectionAsHTML + "\n\n");
|
||||
}
|
||||
|
||||
function EditorUnitTests()
|
||||
{
|
||||
if (window.editorShell) {
|
||||
dump("Running Unit Tests\n");
|
||||
window.editorShell.RunUnitTests();
|
||||
}
|
||||
dump("Running Unit Tests\n");
|
||||
editorShell.RunUnitTests();
|
||||
}
|
||||
|
||||
function EditorExit()
|
||||
{
|
||||
if (window.editorShell) {
|
||||
dump("Exiting\n");
|
||||
window.editorShell.Exit();
|
||||
}
|
||||
dump("Exiting\n");
|
||||
editorShell.Exit();
|
||||
}
|
||||
|
||||
function EditorTestDocument()
|
||||
{
|
||||
if (window.editorShell)
|
||||
dump("Getting document\n");
|
||||
var theDoc = editorShell.editorDocument;
|
||||
if (theDoc)
|
||||
{
|
||||
dump("Getting document\n");
|
||||
var theDoc = window.editorShell.editorDocument;
|
||||
if (theDoc)
|
||||
{
|
||||
dump("Got the doc\n");
|
||||
dump("Document name:" + theDoc.nodeName + "\n");
|
||||
dump("Document type:" + theDoc.doctype + "\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
dump("Failed to get the doc\n");
|
||||
}
|
||||
dump("Got the doc\n");
|
||||
dump("Document name:" + theDoc.nodeName + "\n");
|
||||
dump("Document type:" + theDoc.doctype + "\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
dump("Failed to get the doc\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,25 @@
|
|||
// Each editor window must include this file
|
||||
// Variables shared by all dialogs:
|
||||
var editorShell;
|
||||
|
||||
function InitEditorShell()
|
||||
{
|
||||
// get the editor shell from the parent window
|
||||
editorShell = window.opener.editorShell;
|
||||
if (editorShell) {
|
||||
editorShell = editorShell.QueryInterface(Components.interfaces.nsIEditorShell);
|
||||
}
|
||||
if (!editorShell) {
|
||||
dump("EditorShell not found!!!\n");
|
||||
window.close();
|
||||
return false;
|
||||
}
|
||||
// Save as a property of the window so it can be used by child dialogs
|
||||
window.editorShell = editorShell;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function ClearList(list)
|
||||
{
|
||||
for( i = (list.length-1); i >= 0; i-- ) {
|
||||
|
@ -33,8 +55,18 @@ function ValidateNumberString(value, minValue, maxValue)
|
|||
return number + "";
|
||||
}
|
||||
}
|
||||
message = "The number you entered ("+number+") is outside of allowed range.\nPlease enter a number between "+minValue+" and "+maxValue;
|
||||
|
||||
// Initialize where we place result from generic EdMessage dialog
|
||||
window.msgResult = 0;
|
||||
// This is NOT MODAL!
|
||||
window.openDialog("chrome://editordlgs/content/EdMessage.xul", "MsgDlg", "chrome", "", message, "Input Error", "OK");
|
||||
// We could do something like this if we could call
|
||||
// a method that pumps the message system
|
||||
//while (window.msgResult == 0);
|
||||
|
||||
dump("Message button pressed: "+window.msgResult+"\n");
|
||||
// Return an empty string to indicate error
|
||||
//TODO: Popup a message box telling the user about the error
|
||||
return "";
|
||||
}
|
||||
|
||||
|
@ -203,6 +235,29 @@ function SetLabelEnabledByID( labelID, doEnable )
|
|||
}
|
||||
}
|
||||
|
||||
// Next two methods assume caller has a "percentChar" variable
|
||||
// to hold an empty string (no % used) or "%" (percent is used)
|
||||
function InitPixelOrPercentPopupButton(element, attribute, buttonID)
|
||||
{
|
||||
size = element.getAttribute(attribute);
|
||||
btn = document.getElementById(buttonID);
|
||||
|
||||
// Search for a "%" character
|
||||
percentIndex = size.search(/%/);
|
||||
if (percentIndex > 0) {
|
||||
percentChar = "%";
|
||||
// Strip out the %
|
||||
size = size.substr(0, percentIndex);
|
||||
// TODO: USE ENTITIES FOR TEXT VALUES
|
||||
if (btn)
|
||||
btn.setAttribute("value","percent");
|
||||
} else {
|
||||
if (btn)
|
||||
btn.setAttribute("value","pixels");
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
// Input string is "" for pixel, or "%" for percent
|
||||
function SetPixelOrPercentByID(elementID, percentString)
|
||||
{
|
||||
|
@ -223,9 +278,11 @@ function SetPixelOrPercentByID(elementID, percentString)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// All dialogs share this simple method
|
||||
function onCancel()
|
||||
{
|
||||
dump("Cancel button clicked: closing window\n");
|
||||
window.close();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,20 +1,13 @@
|
|||
//Cancel() is in EdDialogCommon.js
|
||||
var editorShell;
|
||||
var insertNew = true;
|
||||
var tagname = "TAG NAME"
|
||||
|
||||
// dialog initialization code
|
||||
function Startup()
|
||||
{
|
||||
// get the editor shell from the parent window
|
||||
editorShell = window.opener.editorShell;
|
||||
editorShell = editorShell.QueryInterface(Components.interfaces.nsIEditorShell);
|
||||
if(!editorShell) {
|
||||
dump("EditoreditorShell not found!!!\n");
|
||||
window.close();
|
||||
if (!InitEditorShell())
|
||||
return;
|
||||
}
|
||||
dump("EditoreditorShell found for NamedAnchor Properties dialog\n");
|
||||
dump("EditoreditorShell found for dialog\n");
|
||||
|
||||
// Create dialog object to store controls for easy access
|
||||
dialog = new Object;
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
xmlns:xul ="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns="http://www.w3.org/TR/REC-html40"
|
||||
onload = "Startup()"
|
||||
align="vertical" flex="100%">
|
||||
align="vertical">
|
||||
|
||||
<!-- Methods common to all editor dialogs -->
|
||||
<script language="JavaScript" src="chrome://editordlgs/content/EdDialogCommon.js">
|
||||
|
@ -17,17 +17,11 @@
|
|||
</script>
|
||||
|
||||
<xul:broadcaster id="args" value=""/>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<!-- THIS SHOULD BE A XUL FRAGMENT -->
|
||||
<td align = "right">
|
||||
<button class="spaced" id="OK" onclick="onOK()">OK</button>
|
||||
<button class="spaced" id="Cancel" onclick="onCancel()">Cancel</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr width="100%"/>
|
||||
<xul:box>
|
||||
<xul:titledbutton class="spaced" id="Advanced" onclick="onAdvanced()" value="More Attributes..."/>
|
||||
<xul:spring flex="100%"/>
|
||||
<xul:titledbutton class="spaced" id="OK" onclick="onOK()" value="OK"/>
|
||||
<xul:titledbutton class="spaced" id="Cancel" onclick="onCancel()" value="Cancel"/>
|
||||
</xul:box>
|
||||
</xul:window>
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
var spellChecker;
|
||||
|
||||
function Startup()
|
||||
{
|
||||
if (!InitEditorShell())
|
||||
return;
|
||||
dump("EditoreditorShell found for dialog\n");
|
||||
|
||||
// Get the spellChecker shell
|
||||
spellChecker = editorShell.QueryInterface(Components.interfaces.nsIEditorSpellCheck);
|
||||
if (!spellChecker) {
|
||||
dump("SpellChecker not found!!!\n");
|
||||
window.close();
|
||||
}
|
||||
|
||||
// Create dialog object to store controls for easy access
|
||||
dialog = new Object;
|
||||
// GET EACH CONTROL -- E.G.:
|
||||
//dialog.editBox = document.getElementById("editBox");
|
||||
|
||||
// SET FOCUS TO FIRST CONTROL
|
||||
//dialog.editBox.focus();
|
||||
}
|
||||
|
||||
function SelectWord()
|
||||
{
|
||||
dump("SelectWord\n");
|
||||
}
|
||||
|
||||
function AddWord()
|
||||
{
|
||||
dump("AddWord\n");
|
||||
}
|
||||
|
||||
function ReplaceWord()
|
||||
{
|
||||
dump("ReplaceWord\n");
|
||||
}
|
||||
|
||||
function RemoveWord()
|
||||
{
|
||||
dump("RemoveWord\n");
|
||||
}
|
||||
|
||||
|
||||
function onOK()
|
||||
{
|
||||
window.close();
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin/xul.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://editordlgs/skin/EditorDialog.css" type="text/css"?>
|
||||
<!DOCTYPE window>
|
||||
<!-- dialog containing a control requiring initial setup -->
|
||||
<!-- WE SHOULD NOT USE ABSOLUTE WITH AND HEIGHT - USE BOXES INSTEAD? -->
|
||||
<xul:window class="dialog" title="Personal Dictionary"
|
||||
xmlns:xul ="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns="http://www.w3.org/TR/REC-html40"
|
||||
onload = "Startup()"
|
||||
align="vertical">
|
||||
|
||||
<!-- Methods common to all editor dialogs -->
|
||||
<script language="JavaScript" src="chrome://editordlgs/content/EdDialogCommon.js">
|
||||
</script>
|
||||
<script language="JavaScript" src="chrome://editordlgs/content/EdDictionary.js">
|
||||
</script>
|
||||
|
||||
<xul:broadcaster id="args" value=""/>
|
||||
<table>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
NewWord<br/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<input type="text" class="SpellCheckWord" id="Word" size="10"/>
|
||||
</td>
|
||||
<td>
|
||||
<xul:titledbutton class="SizeToCell" id="AddWord" onclick="AddWord()" value="Add"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
Words:
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<select class="SpellCheckList" id="SuggestedList" size="6" onchange="SelectWord()">
|
||||
<option>Sample contents 1</option>
|
||||
<option>Sample contents 2</option>
|
||||
<option>Sample contents 3</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<xul:titledbutton class="SizeToCell" id="ReplaceWord" onclick="ReplaceWord()" value="Replace"/>
|
||||
<br/>
|
||||
<xul:titledbutton class="SizeToCell" id="RemoveWord" onclick="RemoveWord()" value="Remove"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<xul:box>
|
||||
<xul:spring flex="100%"/>
|
||||
<xul:titledbutton class="spaced" id="OK" onclick="onOK()" value="OK"/>
|
||||
<xul:titledbutton class="spaced" id="Cancel" onclick="onCancel()" value="Cancel"/>
|
||||
<xul:spring flex="100%"/>
|
||||
</xul:box>
|
||||
|
||||
</xul:window>
|
|
@ -1,4 +1,3 @@
|
|||
var editorShell;
|
||||
var toolkitCore;
|
||||
var tagName = "hr";
|
||||
var hLineElement;
|
||||
|
@ -10,17 +9,11 @@ var shading = true;
|
|||
// dialog initialization code
|
||||
function Startup()
|
||||
{
|
||||
// get the editor shell from the parent window
|
||||
editorShell = window.opener.editorShell;
|
||||
editorShell = editorShell.QueryInterface(Components.interfaces.nsIEditorShell);
|
||||
if(!editorShell) {
|
||||
dump("editorShell not found!!!\n");
|
||||
window.close();
|
||||
if (!InitEditorShell())
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the selected horizontal line
|
||||
hLineElement = window.editorShell.GetSelectedElement(tagName);
|
||||
hLineElement = editorShell.GetSelectedElement(tagName);
|
||||
|
||||
if (!hLineElement) {
|
||||
// We should never be here if not editing an existing HLine
|
||||
|
@ -29,7 +22,7 @@ function Startup()
|
|||
return;
|
||||
}
|
||||
// Create a temporary element to use with Save Settings as default
|
||||
tempLineElement = window.editorShell.editorDocument.createElement("HR");
|
||||
tempLineElement = editorShell.editorDocument.createElement("HR");
|
||||
if (!hLineElement) {
|
||||
dump("Temporary HLine element was not created!\n");
|
||||
window.close();
|
||||
|
@ -44,27 +37,17 @@ function Startup()
|
|||
dialog.centerAlign = document.getElementById("centerAlign");
|
||||
dialog.rightAlign = document.getElementById("rightAlign");
|
||||
dialog.shading = document.getElementById("3dShading");
|
||||
dialog.pixelOrPercentButton = document.getElementById("pixelOrPercentButton");
|
||||
|
||||
|
||||
// Initialize control values based on existing attributes
|
||||
|
||||
// Just to be confusing, "size" is used instead of height
|
||||
// We will use "height" here and in UI
|
||||
dialog.heightInput.value = hLineElement.getAttribute("size");
|
||||
width = hLineElement.getAttribute("width");
|
||||
|
||||
// This assumes initial button text is "percent"
|
||||
// Search for a "%" character
|
||||
percentIndex = width.search(/%/);
|
||||
if (percentIndex > 0) {
|
||||
percentChar = "%";
|
||||
// Strip out the %
|
||||
width = width.substr(0, percentIndex);
|
||||
} else {
|
||||
dialog.pixelOrPercentButton.setAttribute("value","pixels");
|
||||
}
|
||||
|
||||
dialog.widthInput.value = width;
|
||||
// Get the width attribute of the element, stripping out "%"
|
||||
// This sets contents of button text and "percentChar" variable
|
||||
dialog.widthInput.value = InitPixelOrPercentPopupButton(hLineElement, "width", "pixelOrPercentButton");
|
||||
|
||||
align = hLineElement.getAttribute("align");
|
||||
if (align == "center") {
|
||||
|
@ -81,22 +64,6 @@ function Startup()
|
|||
dialog.heightInput.focus();
|
||||
}
|
||||
|
||||
// Input string is "" for pixel, or "%" for percent
|
||||
function SetPixelOrPercent(percentString)
|
||||
{
|
||||
percentChar = percentString;
|
||||
dump("SetPixelOrPercent. PercentChar="+percentChar+"\n");
|
||||
|
||||
if (percentChar == "%") {
|
||||
dialog.pixelOrPercentButton.setAttribute("value","percent");
|
||||
dump("TODO: Set button text to PERCENT\n");
|
||||
} else {
|
||||
dialog.pixelOrPercentButton.setAttribute("value","pixels");
|
||||
dump("TODO: Set button text to PIXELS\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function onSaveDefault()
|
||||
{
|
||||
// "false" means set attributes on the tempLineElement,
|
||||
|
@ -118,6 +85,7 @@ function ValidateData(setAttributes)
|
|||
height = ValidateNumberString(dialog.heightInput.value, 1, maxPixels);
|
||||
if (height == "") {
|
||||
// Set focus to the offending control
|
||||
dump("Height is empty\n");
|
||||
dialog.heightInput.focus();
|
||||
return false;
|
||||
}
|
||||
|
@ -139,6 +107,7 @@ function ValidateData(setAttributes)
|
|||
|
||||
width = ValidateNumberString(dialog.widthInput.value, 1, maxLimit);
|
||||
if (width == "") {
|
||||
dump("Width is empty\n");
|
||||
dialog.widthInput.focus();
|
||||
return false;
|
||||
}
|
||||
|
@ -181,11 +150,11 @@ function ValidateData(setAttributes)
|
|||
|
||||
function onOK()
|
||||
{
|
||||
dump("************* onOK for HLine props\n");
|
||||
// Since we only edit existing HLines,
|
||||
// ValidateData will set the new attributes
|
||||
// so there's nothing else to do
|
||||
if (ValidateData(true)) {
|
||||
window.close();
|
||||
dump("CLOSING EdHLineProps\n");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,8 +71,8 @@
|
|||
|
||||
<xul:popup id="PixelOrPercentMenu">
|
||||
<xul:menu>
|
||||
<xul:menuitem name="pixels" onclick="SetPixelOrPercent('')"/>
|
||||
<xul:menuitem name="percent" onclick="SetPixelOrPercent('%')"/>
|
||||
<xul:menuitem name="pixels" onclick="SetPixelOrPercentByID('pixelOrPercentButton', '')"/>
|
||||
<xul:menuitem name="percent" onclick="SetPixelOrPercentByID('pixelOrPercentButton', '%')"/>
|
||||
</xul:menu>
|
||||
</xul:popup>
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
var editorShell;
|
||||
var insertNew = true;
|
||||
var imageElement;
|
||||
var tagName = "img"
|
||||
|
@ -9,16 +8,8 @@ var hasAnyChanged = false;
|
|||
// dialog initialization code
|
||||
function Startup()
|
||||
{
|
||||
dump("Doing Startup...\n");
|
||||
|
||||
// get the editor shell from the parent window
|
||||
editorShell = window.opener.editorShell;
|
||||
editorShell = editorShell.QueryInterface(Components.interfaces.nsIEditorShell);
|
||||
if(!editorShell) {
|
||||
dump("EditoreditorShell not found!!!\n");
|
||||
window.close();
|
||||
if (!InitEditorShell())
|
||||
return;
|
||||
}
|
||||
dump("EditoreditorShell found for Image Properties dialog\n");
|
||||
|
||||
// Create dialog object to store controls for easy access
|
||||
|
@ -263,6 +254,10 @@ function doOverallEnabling()
|
|||
// SetLabelEnabledByID( "bordertypeLabel", canEnableAll );
|
||||
}
|
||||
|
||||
function SetImageAlignment()
|
||||
{
|
||||
}
|
||||
|
||||
function onOK()
|
||||
{
|
||||
imageElement.setAttribute("src",dialog.srcInput.value);
|
||||
|
@ -316,7 +311,8 @@ function onOK()
|
|||
// handle insertion of new image
|
||||
if (insertNew) {
|
||||
dump("src="+imageElement.getAttribute("src")+" alt="+imageElement.getAttribute("alt")+"\n");
|
||||
editorShell.InsertElement(imageElement, false);
|
||||
// 'true' means delete the selection before inserting
|
||||
editorShell.InsertElement(imageElement, true);
|
||||
}
|
||||
|
||||
// dismiss dialog
|
||||
|
|
|
@ -18,21 +18,13 @@
|
|||
|
||||
/* Insert Source HTML dialog */
|
||||
|
||||
var editorShell;
|
||||
var dialog;
|
||||
|
||||
// dialog initialization code
|
||||
function Startup()
|
||||
{
|
||||
// get the editor shell from the parent window
|
||||
editorShell = window.opener.editorShell;
|
||||
editorShell = editorShell.QueryInterface(Components.interfaces.nsIEditorShell);
|
||||
|
||||
if (!editorShell) {
|
||||
dump("editorShell not found!!!\n");
|
||||
window.close();
|
||||
return;
|
||||
}
|
||||
if (!InitEditorShell())
|
||||
return;
|
||||
|
||||
// Create dialog object to store controls for easy access
|
||||
dialog = new Object;
|
||||
|
|
|
@ -1,42 +1,44 @@
|
|||
//Cancel() is in EdDialogCommon.js
|
||||
var editorShell;
|
||||
var tagName = "table"
|
||||
var tableElement = null;
|
||||
var rowElement = null;
|
||||
var cellElement = null;
|
||||
var maxRows = 10000;
|
||||
var maxColumns = 10000;
|
||||
var percentChar = "";
|
||||
var maxPixels = 10000;
|
||||
|
||||
// dialog initialization code
|
||||
function Startup()
|
||||
{
|
||||
// get the editor shell from the parent window
|
||||
editorShell = window.opener.editorShell;
|
||||
editorShell = editorShell.QueryInterface(Components.interfaces.nsIEditorShell);
|
||||
if(!editorShell) {
|
||||
dump("EditoreditorShell not found!!!\n");
|
||||
window.close();
|
||||
if (!InitEditorShell())
|
||||
return;
|
||||
}
|
||||
dump("EditoreditorShell found for Insert Table dialog\n");
|
||||
|
||||
// Create dialog object to store controls for easy access
|
||||
dialog = new Object;
|
||||
dialog.rowsInput = document.getElementById("rows");
|
||||
dialog.columnsInput = document.getElementById("columns");
|
||||
|
||||
// Set default number to 1 row, 2 columns:
|
||||
dialog.rowsInput.value = 1;
|
||||
dialog.columnsInput.value = 2;
|
||||
|
||||
tableElement = editorShell.CreateElementWithDefaults(tagName);
|
||||
|
||||
if(!tableElement)
|
||||
{
|
||||
dump("Failed to create a new table!\n");
|
||||
window.close();
|
||||
}
|
||||
|
||||
|
||||
// Create dialog object to store controls for easy access
|
||||
dialog = new Object;
|
||||
dialog.rowsInput = document.getElementById("rows");
|
||||
dialog.columnsInput = document.getElementById("columns");
|
||||
dialog.widthInput = document.getElementById("width");
|
||||
dialog.borderInput = document.getElementById("border");
|
||||
|
||||
// Get default attributes set on the created table:
|
||||
// Get the width attribute of the element, stripping out "%"
|
||||
// This sets contents of button text and "percentChar" variable
|
||||
dialog.widthInput.value = InitPixelOrPercentPopupButton(tableElement, "width", "pixelOrPercentButton");
|
||||
dialog.borderInput.value = tableElement.getAttribute("border");
|
||||
|
||||
// Set default number to 1 row, 2 columns:
|
||||
dialog.rowsInput.value = 1;
|
||||
dialog.columnsInput.value = 2;
|
||||
|
||||
dialog.rowsInput.focus();
|
||||
}
|
||||
|
||||
|
@ -72,8 +74,6 @@ function onOK()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: VALIDATE ROWS, COLS and BUILD TABLE
|
||||
// Don't delete selected text when inserting
|
||||
editorShell.InsertElement(tableElement, false);
|
||||
window.close();
|
||||
|
|
|
@ -16,22 +16,46 @@
|
|||
|
||||
<xul:broadcaster id="args" value=""/>
|
||||
<table>
|
||||
<tr>
|
||||
<tr class="vcenter">
|
||||
<td align="right">
|
||||
<span>Number of rows:</span>
|
||||
</td>
|
||||
<td>
|
||||
<td cellspan="2">
|
||||
<input type="text" id="rows" size="4"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr class="vcenter">
|
||||
<td align="right">
|
||||
<span>Number of columns:</span>
|
||||
</td>
|
||||
<td>
|
||||
<td cellspan="2">
|
||||
<input type="text" id="columns" size="4"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="vcenter">
|
||||
<td align="right" valign="middle">
|
||||
<span>Width:</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="width" size="4" maxlength="4"/>
|
||||
</td>
|
||||
<td>
|
||||
<xul:titledbutton class="popup PixelOrPercent" id="pixelOrPercentButton" value="percent" align="left" popup="PixelOrPercentMenu" popupanchor="bottomleft"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="vcenter">
|
||||
<td align="right">
|
||||
<span>Border:</span>
|
||||
</td>
|
||||
<td>
|
||||
<!-- THIS IS DUMB Can't figure out how to put "pixels" after the
|
||||
input box and make them center vertically. Used another TD instead -->
|
||||
<input type="text" id="border" size="4"/>
|
||||
</td>
|
||||
<td>
|
||||
<span>pixels</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr width="100%"/>
|
||||
<xul:box>
|
||||
|
@ -40,4 +64,12 @@
|
|||
<xul:titledbutton class="spaced" id="OK" onclick="onOK()" value="OK"/>
|
||||
<xul:titledbutton class="spaced" id="Cancel" onclick="onCancel()" value="Cancel"/>
|
||||
</xul:box>
|
||||
|
||||
<xul:popup id="PixelOrPercentMenu">
|
||||
<xul:menu>
|
||||
<xul:menuitem name="pixels" onclick="SetPixelOrPercentByID('pixelOrPercentButton', '')"/>
|
||||
<xul:menuitem name="percent" onclick="SetPixelOrPercentByID('pixelOrPercentButton', '%')"/>
|
||||
</xul:menu>
|
||||
</xul:popup>
|
||||
|
||||
</xul:window>
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
var editorShell;
|
||||
var anchorElement = null;
|
||||
var imageElement = null;
|
||||
var insertNew = true;
|
||||
|
@ -14,17 +13,8 @@ var dialog;
|
|||
// dialog initialization code
|
||||
function Startup()
|
||||
{
|
||||
dump("Doing Startup...\n");
|
||||
|
||||
// get the editor shell from the parent window
|
||||
editorShell = window.opener.editorShell;
|
||||
editorShell = editorShell.QueryInterface(Components.interfaces.nsIEditorShell);
|
||||
|
||||
if(!editorShell) {
|
||||
dump("editorShell not found!!!\n");
|
||||
window.close();
|
||||
return;
|
||||
}
|
||||
if (!InitEditorShell())
|
||||
return;
|
||||
|
||||
// Create dialog object to store controls for easy access
|
||||
dialog = new Object;
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
// dialog initialization code
|
||||
|
||||
function Startup()
|
||||
{
|
||||
if (!InitEditorShell())
|
||||
return;
|
||||
dump("EditorShell found for Message dialog\n");
|
||||
|
||||
window.opener.msgResult = 0;
|
||||
|
||||
// Message is wrapped in a <div>
|
||||
// We will add child text node(s)
|
||||
messageParent = (document.getElementById("message"));
|
||||
messageText = window.arguments[1];
|
||||
if (messageText && messageText.length > 0)
|
||||
{
|
||||
// Let the caller use "\n" to cause breaks
|
||||
// Translate these into <br> tags
|
||||
done = false;
|
||||
while (!done) {
|
||||
breakIndex = messageText.search(/\n/);
|
||||
if (breakIndex == 0) {
|
||||
// Ignore break at the first character
|
||||
messageText = messageText.slice(1);
|
||||
dump("Found break at begining\n");
|
||||
messageFragment = "";
|
||||
} else if (breakIndex > 0) {
|
||||
// The fragment up to the break
|
||||
messageFragment = messageText.slice(0, breakIndex);
|
||||
|
||||
// Chop off fragment we just found from remaining string
|
||||
messageText = messageText.slice(breakIndex+1);
|
||||
} else {
|
||||
// "\n" not found. We're done
|
||||
done = true;
|
||||
messageFragment = messageText;
|
||||
}
|
||||
messageNode = document.createTextNode(messageFragment);
|
||||
if (messageNode)
|
||||
messageParent.appendChild(messageNode);
|
||||
|
||||
// This is needed when the default namespace of the document is XUL
|
||||
breakNode = document.createElementWithNameSpace("BR", "http://www.w3.org/TR/REC-html40");
|
||||
if (breakNode)
|
||||
messageParent.appendChild(breakNode);
|
||||
}
|
||||
} else {
|
||||
// We must have a message
|
||||
window.close();
|
||||
}
|
||||
title = window.arguments[2];
|
||||
if (title.length > 0) {
|
||||
// BUG 9722: Not implemented yet.
|
||||
//document.title = title;
|
||||
}
|
||||
|
||||
button1 = document.getElementById("button1");
|
||||
button2 = document.getElementById("button2");
|
||||
button3 = document.getElementById("button3");
|
||||
// All buttons must have the same parent
|
||||
buttonParent = button1.parentNode;
|
||||
|
||||
button1Text = window.arguments[3];
|
||||
if (button1Text && button1Text.length > 0)
|
||||
{
|
||||
dump(button1Text+"\n");
|
||||
button1.setAttribute("value", button1Text);
|
||||
} else {
|
||||
// We must have at least one button!
|
||||
window.close();
|
||||
}
|
||||
|
||||
button2Text = window.arguments[4];
|
||||
if (button2Text && button2Text.length > 0)
|
||||
{
|
||||
dump(button2Text+"\n");
|
||||
button2.setAttribute("value", button2Text);
|
||||
} else {
|
||||
buttonParent.removeChild(button2);
|
||||
}
|
||||
|
||||
button3Text = window.arguments[5];
|
||||
if (button3Text && button3Text.length > 0)
|
||||
{
|
||||
dump(button3Text+"\n");
|
||||
button3.setAttribute("value", button3Text);
|
||||
} else {
|
||||
buttonParent.removeChild(button3);
|
||||
}
|
||||
}
|
||||
|
||||
function onButton1()
|
||||
{
|
||||
window.opener.msgResult = 1;
|
||||
window.close();
|
||||
}
|
||||
|
||||
function onButton2()
|
||||
{
|
||||
window.opener.msgResult = 2;
|
||||
window.close();
|
||||
}
|
||||
|
||||
function onButton3()
|
||||
{
|
||||
window.opener.msgResult = 3;
|
||||
window.close();
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin/xul.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://editordlgs/skin/EditorDialog.css" type="text/css"?>
|
||||
<!DOCTYPE window>
|
||||
<!-- dialog containing a control requiring initial setup -->
|
||||
<window title="Netscape" class="dialog"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:html="http://www.w3.org/TR/REC-html40"
|
||||
onload = "Startup()"
|
||||
align="vertical">
|
||||
|
||||
<!-- Methods common to all editor dialogs -->
|
||||
<html:script language="JavaScript" src="chrome://editordlgs/content/EdDialogCommon.js">
|
||||
</html:script>
|
||||
<html:script language="JavaScript" src="chrome://editordlgs/content/EdMessage.js">
|
||||
</html:script>
|
||||
|
||||
<broadcaster id="args" value=""/>
|
||||
<!-- text node(s) with message text will be appended as children to this -->
|
||||
<html:div id="message" flex="100%" style="width: 20em;"/>
|
||||
<spring style="height: 15px"/>
|
||||
<box align="horizontal" style="margin: 10px">
|
||||
<spring flex="100%"/>
|
||||
<titledbutton class="MsgButton" id="button1" onclick="onButton1()"/>
|
||||
<titledbutton class="MsgButton" id="button2" onclick="onButton2()"/>
|
||||
<titledbutton class="MsgButton" id="button3" onclick="onButton3()"/>
|
||||
<spring flex="100%"/>
|
||||
</box>
|
||||
</window>
|
|
@ -1,5 +1,3 @@
|
|||
//Cancel() is in EdDialogCommon.js
|
||||
var editorShell;
|
||||
var insertNew = true;
|
||||
var tagName = "anchor"
|
||||
var anchorElement = null;
|
||||
|
@ -7,14 +5,8 @@ var anchorElement = null;
|
|||
// dialog initialization code
|
||||
function Startup()
|
||||
{
|
||||
// get the editor shell from the parent window
|
||||
editorShell = window.opener.editorShell;
|
||||
editorShell = editorShell.QueryInterface(Components.interfaces.nsIEditorShell);
|
||||
if(!editorShell) {
|
||||
dump("EditoreditorShell not found!!!\n");
|
||||
window.close();
|
||||
if (!InitEditorShell())
|
||||
return;
|
||||
}
|
||||
dump("EditoreditorShell found for NamedAnchor Properties dialog\n");
|
||||
|
||||
// Create dialog object to store controls for easy access
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
</tr>
|
||||
</table>
|
||||
<!-- A classic case of box layout fighting what I want to do!
|
||||
<xul:box flex="100%">
|
||||
<xul:box>
|
||||
<div class="spacedtext">
|
||||
Enter a name for this target:
|
||||
</div>
|
||||
|
|
|
@ -1,19 +1,21 @@
|
|||
var editorShell;
|
||||
var misspelledWord;
|
||||
var spellChecker;
|
||||
|
||||
// dialog initialization code
|
||||
function Startup()
|
||||
{
|
||||
dump("Doing Startup...\n");
|
||||
if (!InitEditorShell())
|
||||
return;
|
||||
dump("EditorShell found for Spell Checker dialog\n");
|
||||
|
||||
// get the editor shell from the parent window
|
||||
editorShell = window.opener.editorShell;
|
||||
editorShell = editorShell.QueryInterface(Components.interfaces.nsIEditorSpellCheck);
|
||||
if(!editorShell) {
|
||||
dump("EditoreditorShell not found!!!\n");
|
||||
// Get the spellChecker shell
|
||||
spellChecker = editorShell.QueryInterface(Components.interfaces.nsIEditorSpellCheck);
|
||||
if (!spellChecker) {
|
||||
dump("SpellChecker not found!!!\n");
|
||||
window.close();
|
||||
}
|
||||
dump("EditoreditorShell found for Spell Checker dialog\n");
|
||||
// Save as a property of the window so it can be used by child dialogs
|
||||
window.spellChecker = spellChecker;
|
||||
|
||||
// Create dialog object to store controls for easy access
|
||||
dialog = new Object;
|
||||
|
@ -52,7 +54,7 @@ function Startup()
|
|||
|
||||
function NextWord()
|
||||
{
|
||||
misspelledWord = editorShell.GetNextMisspelledWord();
|
||||
misspelledWord = spellChecker.GetNextMisspelledWord();
|
||||
dialog.wordInput.value = misspelledWord;
|
||||
if (misspelledWord == "") {
|
||||
dump("FINISHED SPELL CHECKING\n");
|
||||
|
@ -68,7 +70,7 @@ function CheckWord()
|
|||
word = dialog.wordInput.value;
|
||||
if (word != "") {
|
||||
dump("CheckWord: Word in edit field="+word+"\n");
|
||||
isMisspelled = editorShell.CheckCurrentWord(word);
|
||||
isMisspelled = spellChecker.CheckCurrentWord(word);
|
||||
if (isMisspelled) {
|
||||
dump("CheckWord says word was misspelled\n");
|
||||
misspelledWord = word;
|
||||
|
@ -96,7 +98,7 @@ function IgnoreAll()
|
|||
{
|
||||
dump("SpellCheck: IgnoreAll\n");
|
||||
if (misspelledWord != "") {
|
||||
editorShell.IgnoreWordAllOccurrences(misspelledWord);
|
||||
spellChecker.IgnoreWordAllOccurrences(misspelledWord);
|
||||
}
|
||||
NextWord();
|
||||
}
|
||||
|
@ -106,7 +108,7 @@ function Replace()
|
|||
dump("SpellCheck: Replace\n");
|
||||
newWord = dialog.wordInput.value;
|
||||
if (misspelledWord != "" && misspelledWord != newWord) {
|
||||
isMisspelled = editorShell.ReplaceWord(misspelledWord, newWord, false);
|
||||
isMisspelled = spellChecker.ReplaceWord(misspelledWord, newWord, false);
|
||||
}
|
||||
NextWord();
|
||||
}
|
||||
|
@ -116,7 +118,7 @@ function ReplaceAll()
|
|||
dump("SpellCheck: ReplaceAll\n");
|
||||
newWord = dialog.wordInput.value;
|
||||
if (misspelledWord != "" && misspelledWord != newWord) {
|
||||
isMisspelled = editorShell.ReplaceWord(misspelledWord, newWord, true);
|
||||
isMisspelled = spellChecker.ReplaceWord(misspelledWord, newWord, true);
|
||||
}
|
||||
NextWord();
|
||||
}
|
||||
|
@ -125,15 +127,13 @@ function AddToDictionary()
|
|||
{
|
||||
dump("SpellCheck: AddToDictionary\n");
|
||||
if (misspelledWord != "") {
|
||||
editorShell.AddWordToDictionary(misspelledWord);
|
||||
spellChecker.AddWordToDictionary(misspelledWord);
|
||||
}
|
||||
}
|
||||
|
||||
function EditDictionary()
|
||||
{
|
||||
dump("SpellCheck: EditDictionary TODO: IMPLEMENT DIALOG\n");
|
||||
window.width = 700;
|
||||
window.height = 700;
|
||||
window.openDialog("chrome://editordlgs/content/EdDictionary.xul", "Dictionary", "chrome", "", misspelledWord);
|
||||
}
|
||||
|
||||
function SelectLanguage()
|
||||
|
@ -144,9 +144,9 @@ function SelectLanguage()
|
|||
|
||||
function Close()
|
||||
{
|
||||
dump("SpellCheck: Spell Checker Closed\n");
|
||||
dump("SpellCheck: Spell Checker is closing...\n");
|
||||
// Shutdown the spell check and close the dialog
|
||||
editorShell.CloseSpellChecking();
|
||||
spellChecker.CloseSpellChecking();
|
||||
window.close();
|
||||
}
|
||||
|
||||
|
@ -165,7 +165,7 @@ function FillSuggestedList(firstWord)
|
|||
|
||||
// Get suggested words until an empty string is returned
|
||||
do {
|
||||
word = editorShell.GetSuggestedWord();
|
||||
word = spellChecker.GetSuggestedWord();
|
||||
dump("Suggested Word = "+word+"\n");
|
||||
if (word != "") {
|
||||
AppendStringToList(list, word);
|
||||
|
|
|
@ -6,13 +6,17 @@ EdHLineProps.xul
|
|||
EdHLineProps.js
|
||||
EdImageProps.xul
|
||||
EdImageProps.js
|
||||
EdLinkProps.js
|
||||
EdLinkProps.xul
|
||||
EdSpellCheck.js
|
||||
EdLinkProps.js
|
||||
EdSpellCheck.xul
|
||||
EdSpellCheck.js
|
||||
EdDictionary.xul
|
||||
EdDictionary.js
|
||||
EdNamedAnchorProps.xul
|
||||
EdNamedAnchorProps.js
|
||||
EdInsertTable.xul
|
||||
EdInsertTable.js
|
||||
EdInsSrc.xul
|
||||
EdInsSrc.js
|
||||
EdMessage.xul
|
||||
EdMessage.js
|
||||
|
|
|
@ -38,10 +38,14 @@ EXPORT_RESOURCE_CONTENT = \
|
|||
$(srcdir)/EdHLineProps.js \
|
||||
$(srcdir)/EdSpellCheck.xul \
|
||||
$(srcdir)/EdSpellCheck.js \
|
||||
$(srcdir)/EdDictionary.xul \
|
||||
$(srcdir)/EdDictionary.js \
|
||||
$(srcdir)/EdNamedAnchorProps.xul \
|
||||
$(srcdir)/EdNamedAnchorProps.js \
|
||||
$(srcdir)/EdInsertTable.xul \
|
||||
$(srcdir)/EdInsertTable.js \
|
||||
$(srcdir)/EdMessage.xul \
|
||||
$(srcdir)/EdMessage.js \
|
||||
$(NULL)
|
||||
|
||||
install::
|
||||
|
|
|
@ -29,12 +29,16 @@ install::
|
|||
$(MAKE_INSTALL) EdHLineProps.js $(DIST)\bin\chrome\editor\dialogs\content\default
|
||||
$(MAKE_INSTALL) EdSpellCheck.xul $(DIST)\bin\chrome\editor\dialogs\content\default
|
||||
$(MAKE_INSTALL) EdSpellCheck.js $(DIST)\bin\chrome\editor\dialogs\content\default
|
||||
$(MAKE_INSTALL) EdDictionary.xul $(DIST)\bin\chrome\editor\dialogs\content\default
|
||||
$(MAKE_INSTALL) EdDictionary.js $(DIST)\bin\chrome\editor\dialogs\content\default
|
||||
$(MAKE_INSTALL) EdNamedAnchorProps.xul $(DIST)\bin\chrome\editor\dialogs\content\default
|
||||
$(MAKE_INSTALL) EdNamedAnchorProps.js $(DIST)\bin\chrome\editor\dialogs\content\default
|
||||
$(MAKE_INSTALL) EdInsertTable.xul $(DIST)\bin\chrome\editor\dialogs\content\default
|
||||
$(MAKE_INSTALL) EdInsertTable.js $(DIST)\bin\chrome\editor\dialogs\content\default
|
||||
$(MAKE_INSTALL) EdInsSrc.xul $(DIST)\bin\chrome\editor\dialogs\content\default
|
||||
$(MAKE_INSTALL) EdInsSrc.js $(DIST)\bin\chrome\editor\dialogs\content\default
|
||||
$(MAKE_INSTALL) EdMessage.xul $(DIST)\bin\chrome\editor\dialogs\content\default
|
||||
$(MAKE_INSTALL) EdMessage.js $(DIST)\bin\chrome\editor\dialogs\content\default
|
||||
|
||||
clobber::
|
||||
rm -f $(DIST)\bin\chrome\editor\dialogs\content\default\EdDialogCommon.js
|
||||
|
@ -46,9 +50,13 @@ clobber::
|
|||
rm -f $(DIST)\bin\chrome\editor\dialogs\content\default\EdHLineProps.js
|
||||
rm -f $(DIST)\bin\chrome\editor\dialogs\content\default\EdSpellCheck.xul
|
||||
rm -f $(DIST)\bin\chrome\editor\dialogs\content\default\EdSpellCheck.js
|
||||
rm -f $(DIST)\bin\chrome\editor\dialogs\content\default\EdDictionary.xul
|
||||
rm -f $(DIST)\bin\chrome\editor\dialogs\content\default\EdDictionary.js
|
||||
rm -f $(DIST)\bin\chrome\editor\dialogs\content\default\EdNamedAnchorProps.xul
|
||||
rm -f $(DIST)\bin\chrome\editor\dialogs\content\default\EdNamedAnchorProps.js
|
||||
rm -f $(DIST)\bin\chrome\editor\dialogs\content\default\EdInsertTable.xul
|
||||
rm -f $(DIST)\bin\chrome\editor\dialogs\content\default\EdInsertTable.js
|
||||
rm -f $(DIST)\bin\chrome\editor\dialogs\content\default\EdInsSrc.xul
|
||||
rm -f $(DIST)\bin\chrome\editor\dialogs\content\default\EdInsSrc.js
|
||||
rm -f $(DIST)\bin\chrome\editor\dialogs\content\default\EdMessage.xul
|
||||
rm -f $(DIST)\bin\chrome\editor\dialogs\content\default\EdMessage.js
|
||||
|
|
|
@ -49,20 +49,20 @@ tree {
|
|||
}
|
||||
|
||||
/* HTML ELEMENTS */
|
||||
table { cell-spacing: 5px; }
|
||||
td, table { border: 0px;}
|
||||
|
||||
/* Force all rows to line up cell contents at the top */
|
||||
tr { vertical-align: top }
|
||||
|
||||
/* Use this to override the default vertical centering */
|
||||
.vcenter { vertical-align: middle }
|
||||
|
||||
tr[show=0] { display: none }
|
||||
tr[show=1] { display: table-row }
|
||||
|
||||
|
||||
/* FOR DEBUG PURPOSE -- use border-width: 1px */
|
||||
/* BORDER STYLE NOT WORKING 5/12/99 */
|
||||
td, table { border: 0px;}
|
||||
|
||||
p, br, td {
|
||||
font-family: Sans-Serif;
|
||||
font-size: 8pt;
|
||||
p, br {
|
||||
margin-top: 4px;
|
||||
margin-bottom: 4px
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ label[class="disabled"] {
|
|||
|
||||
.InsetBorder { border: 1px inset; padding: 5px }
|
||||
|
||||
button.spaced {
|
||||
.spaced {
|
||||
/* BUG - Setting size doesn't work?
|
||||
width: 80px;
|
||||
height: 20px;
|
||||
|
@ -139,19 +139,29 @@ button.ChooseFile {
|
|||
}
|
||||
|
||||
input[type="file"] {
|
||||
background-color: #CCCCCC; /* not working on Macintosh */
|
||||
font-family: Sans-Serif;
|
||||
font-size: 8pt;
|
||||
}
|
||||
|
||||
titledbutton.PixelOrPercent {
|
||||
min-width: 7em;
|
||||
margin-left: 0px;
|
||||
/* THIS SHOULD BE CHANGED TO MATCH THE LONGER
|
||||
STRING WHEN LOCALIZED: "Percent" or "Pixels"
|
||||
This takes some experimentation,
|
||||
since number of chars. over estimates required width*/
|
||||
width: 6em;
|
||||
}
|
||||
|
||||
titledbutton.SizeToCell {
|
||||
/* BUG: Setting this to 100% chops off right border of button */
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
titledbutton.MsgButton {
|
||||
min-width: 6em;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
hr {
|
||||
height: 2px;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче