Revising nsIChannel to allow for overlapped i/o. This consists of three parts: 1. Factoring nsIChannel into a protocol specific part, the nsIChannel, and a socket specific, the nsITransport. 2. Derive the nsIChannel from a nsIRequest. 2. Changes the notification system from necko and the URILoader to pass the nsIRequest interface instead of nsIChannel interface. This goal stems from wanting to be able to have active AsyncRead and AsyncWrite operations on nsSocketTransport. This is desired because it would greatly simplify the task of maintaining persistent/reusable socket connections for FTP, HTTP, and Imap (and potentially other protocols). The problem with the existing nsIChannel interface is that it does not allow one to selectively suspend just one of the read or write operations while keeping the other active. r=darin@netscape.com sr=rpotts@netscape.com git-svn-id: svn://10.0.0.236/trunk@87587 18797224-902f-48f8-a5cc-f745e15eee43
1102 lines
31 KiB
C++
1102 lines
31 KiB
C++
/*
|
|
* The contents of this file are subject to the Mozilla Public
|
|
* License Version 1.1 (the "MPL"); you may not use this file
|
|
* except in compliance with the MPL. You may obtain a copy of
|
|
* the MPL at http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the MPL is distributed on an "AS
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
* implied. See the MPL for the specific language governing
|
|
* rights and limitations under the MPL.
|
|
*
|
|
* The Original Code is XMLterm.
|
|
*
|
|
* The Initial Developer of the Original Code is Ramalingam Saravanan.
|
|
* Portions created by Ramalingam Saravanan <svn@xmlterm.org> are
|
|
* Copyright (C) 1999 Ramalingam Saravanan. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
* Pierre Phaneuf <pp@ludusdesign.com>
|
|
*/
|
|
|
|
// mozXMLTerminal.cpp: implementation of mozIXMLTerminal interface
|
|
// to manage all XMLTerm operations.
|
|
// Creates a new mozXMLTermSession object to manage session input/output.
|
|
// Creates a mozLineTermAux object to access LineTerm operations.
|
|
// Creates key/text/mouse/drag listener objects to handle user events.
|
|
|
|
#include "nscore.h"
|
|
#include "nspr.h"
|
|
|
|
#include "nsCOMPtr.h"
|
|
#include "nsString.h"
|
|
|
|
#include "nsIDocument.h"
|
|
#include "nsIDOMHTMLDocument.h"
|
|
#include "nsIDocumentViewer.h"
|
|
#include "nsIDocumentLoaderObserver.h"
|
|
#include "nsIObserver.h"
|
|
|
|
#include "nsIPresContext.h"
|
|
#include "nsICaret.h"
|
|
|
|
#include "nsIDOMEventReceiver.h"
|
|
#include "nsIDOMEventListener.h"
|
|
|
|
#include "nsIServiceManager.h"
|
|
#include "nsISupportsPrimitives.h"
|
|
|
|
#include "nsWidgetsCID.h"
|
|
#include "nsIClipboard.h"
|
|
#include "nsITransferable.h"
|
|
|
|
#include "nsFont.h"
|
|
#include "nsIFontMetrics.h"
|
|
#include "nsILookAndFeel.h"
|
|
|
|
#include "mozXMLT.h"
|
|
#include "mozXMLTermUtils.h"
|
|
#include "mozXMLTerminal.h"
|
|
#include "mozIXMLTermSuspend.h"
|
|
|
|
#include "nsIWebNavigation.h"
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
|
|
|
static NS_DEFINE_IID(kIXMLTerminalIID, MOZIXMLTERMINAL_IID);
|
|
static NS_DEFINE_IID(kXMLTerminalCID, MOZXMLTERMINAL_CID);
|
|
|
|
static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID);
|
|
static NS_DEFINE_CID(kCTransferableCID, NS_TRANSFERABLE_CID);
|
|
static NS_DEFINE_CID(kLookAndFeelCID, NS_LOOKANDFEEL_CID);
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
// mozXMLTerminal factory
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
nsresult
|
|
NS_NewXMLTerminal(mozIXMLTerminal** aXMLTerminal)
|
|
{
|
|
NS_PRECONDITION(aXMLTerminal != nsnull, "null ptr");
|
|
if (!aXMLTerminal)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
*aXMLTerminal = new mozXMLTerminal();
|
|
if (! *aXMLTerminal)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
NS_ADDREF(*aXMLTerminal);
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
// mozXMLTerminal implementation
|
|
/////////////////////////////////////////////////////////////////////////
|
|
mozXMLTerminal::mozXMLTerminal() :
|
|
mInitialized(PR_FALSE),
|
|
|
|
mCookie(nsAutoString()),
|
|
|
|
mCommand(nsAutoString()),
|
|
mPromptExpr(nsAutoString()),
|
|
|
|
mInitInput(nsAutoString()),
|
|
|
|
mXMLTermShell(nsnull),
|
|
mDocShell(nsnull),
|
|
mPresShell(nsnull),
|
|
mDOMDocument(nsnull),
|
|
|
|
mXMLTermSession(nsnull),
|
|
|
|
mLineTermAux(nsnull),
|
|
mNeedsResizing(PR_FALSE),
|
|
|
|
mKeyListener(nsnull),
|
|
mTextListener(nsnull),
|
|
mMouseListener(nsnull),
|
|
mDragListener(nsnull)
|
|
{
|
|
NS_INIT_REFCNT();
|
|
}
|
|
|
|
|
|
mozXMLTerminal::~mozXMLTerminal()
|
|
{
|
|
Finalize();
|
|
}
|
|
|
|
|
|
// Implement AddRef and Release
|
|
NS_IMPL_ADDREF(mozXMLTerminal)
|
|
NS_IMPL_RELEASE(mozXMLTerminal)
|
|
|
|
|
|
NS_INTERFACE_MAP_BEGIN(mozXMLTerminal)
|
|
/*
|
|
I maintained the order from the original, however,
|
|
the original called |XMLT_LOG| and in the interface-map form
|
|
it no longer does. Is this an issue?
|
|
*/
|
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, mozIXMLTerminal)
|
|
NS_INTERFACE_MAP_ENTRY(mozIXMLTerminal)
|
|
NS_INTERFACE_MAP_ENTRY(nsIDocumentLoaderObserver)
|
|
NS_INTERFACE_MAP_ENTRY(nsIObserver)
|
|
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
|
NS_INTERFACE_MAP_END
|
|
|
|
|
|
NS_IMETHODIMP mozXMLTerminal::GetCurrentEntryNumber(PRInt32 *aNumber)
|
|
{
|
|
if (!mXMLTermSession)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
return mXMLTermSession->GetCurrentEntryNumber(aNumber);
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP mozXMLTerminal::GetHistory(PRInt32 *aHistory)
|
|
{
|
|
if (!mXMLTermSession)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
return mXMLTermSession->GetHistory(aHistory);
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP mozXMLTerminal::SetHistory(PRInt32 aHistory)
|
|
{
|
|
if (!mXMLTermSession)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
return mXMLTermSession->SetHistory(aHistory);
|
|
}
|
|
|
|
NS_IMETHODIMP mozXMLTerminal::GetPrompt(PRUnichar **aPrompt)
|
|
{
|
|
if (!mXMLTermSession)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
return mXMLTermSession->GetPrompt(aPrompt);
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP mozXMLTerminal::SetPrompt(const PRUnichar* aPrompt)
|
|
{
|
|
if (!mXMLTermSession)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
return mXMLTermSession->SetPrompt(aPrompt);
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP mozXMLTerminal::GetKeyIgnore(PRBool* aIgnore)
|
|
{
|
|
if (!mKeyListener)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
nsCOMPtr<mozIXMLTermSuspend> suspend= do_QueryInterface(mKeyListener);
|
|
if (!suspend)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
return suspend->GetSuspend(aIgnore);
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP mozXMLTerminal::SetKeyIgnore(const PRBool aIgnore)
|
|
{
|
|
if (!mKeyListener)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
nsCOMPtr<mozIXMLTermSuspend> suspend= do_QueryInterface(mKeyListener);
|
|
if (!suspend)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
return suspend->SetSuspend(aIgnore);
|
|
}
|
|
|
|
|
|
// Initialize by starting load of Init page for XMLTerm
|
|
NS_IMETHODIMP mozXMLTerminal::Init(nsIDocShell* aDocShell,
|
|
mozIXMLTermShell* aXMLTermShell,
|
|
const PRUnichar* aURL,
|
|
const PRUnichar* args)
|
|
{
|
|
XMLT_LOG(mozXMLTerminal::Init,20,("\n"));
|
|
|
|
if (!aDocShell)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
if (mInitialized)
|
|
return NS_ERROR_ALREADY_INITIALIZED;
|
|
|
|
// Initialization flag
|
|
mInitialized = PR_TRUE;
|
|
|
|
// Containing docshell
|
|
mDocShell = getter_AddRefs(NS_GetWeakReference(aDocShell)); // weak ref
|
|
|
|
mXMLTermShell = aXMLTermShell; // containing xmlterm shell; no addref
|
|
|
|
nsresult result = NS_OK;
|
|
|
|
// NOTE: Need to parse args string!!!
|
|
mCommand.SetLength(0);
|
|
mPromptExpr.SetLength(0);
|
|
mInitInput = args;
|
|
|
|
if ((aURL != nsnull) && (*aURL != 0)) {
|
|
// Load URL and activate XMLTerm after loading
|
|
XMLT_LOG(mozXMLTerminal::Init,22,("setting DocLoaderObs\n"));
|
|
|
|
// About to create owning reference to this
|
|
result = aDocShell->SetDocLoaderObserver((nsIDocumentLoaderObserver*)this);
|
|
if (NS_FAILED(result))
|
|
return NS_ERROR_FAILURE;
|
|
|
|
XMLT_LOG(mozXMLTerminal::Init,22,("done setting DocLoaderObs\n"));
|
|
|
|
// Load initial XMLterm background document
|
|
nsCAutoString urlCString;
|
|
urlCString.AssignWithConversion(aURL);
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
result = uri->SetSpec(urlCString.GetBuffer());
|
|
if (NS_FAILED(result))
|
|
return NS_ERROR_FAILURE;
|
|
|
|
result = aDocShell->LoadURI(uri, nsnull, nsIWebNavigation::LOAD_FLAGS_NONE);
|
|
if (NS_FAILED(result))
|
|
return NS_ERROR_FAILURE;
|
|
|
|
} else {
|
|
// Document already loaded; activate XMLTerm
|
|
result = Activate();
|
|
if (NS_FAILED(result))
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
XMLT_LOG(mozXMLTerminal::Init,21,("exiting\n"));
|
|
return result;
|
|
}
|
|
|
|
|
|
// De-initialize XMLTerminal
|
|
NS_IMETHODIMP mozXMLTerminal::Finalize(void)
|
|
{
|
|
if (!mInitialized)
|
|
return NS_OK;
|
|
|
|
XMLT_LOG(mozXMLTerminal::Finalize,20,("\n"));
|
|
|
|
mInitialized = PR_FALSE;
|
|
|
|
if (mXMLTermSession) {
|
|
// Finalize XMLTermSession object and delete it (it is not ref. counted)
|
|
mXMLTermSession->Finalize();
|
|
delete mXMLTermSession;
|
|
mXMLTermSession = nsnull;
|
|
}
|
|
|
|
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryReferent(mDOMDocument);
|
|
|
|
if (domDoc) {
|
|
// Release any event listeners for the document
|
|
nsCOMPtr<nsIDOMEventReceiver> eventReceiver;
|
|
nsresult result = domDoc->QueryInterface(NS_GET_IID(nsIDOMEventReceiver), getter_AddRefs(eventReceiver));
|
|
|
|
if (NS_SUCCEEDED(result) && eventReceiver) {
|
|
if (mKeyListener) {
|
|
eventReceiver->RemoveEventListenerByIID(mKeyListener,
|
|
NS_GET_IID(nsIDOMKeyListener));
|
|
mKeyListener = nsnull;
|
|
}
|
|
|
|
if (mTextListener) {
|
|
eventReceiver->RemoveEventListenerByIID(mTextListener,
|
|
NS_GET_IID(nsIDOMTextListener));
|
|
mTextListener = nsnull;
|
|
}
|
|
|
|
if (mMouseListener) {
|
|
eventReceiver->RemoveEventListenerByIID(mMouseListener,
|
|
NS_GET_IID(nsIDOMMouseListener));
|
|
mMouseListener = nsnull;
|
|
}
|
|
|
|
if (mDragListener) {
|
|
eventReceiver->RemoveEventListenerByIID(mDragListener,
|
|
NS_GET_IID(nsIDOMDragListener));
|
|
mDragListener = nsnull;
|
|
}
|
|
}
|
|
}
|
|
|
|
mDOMDocument = nsnull;
|
|
|
|
if (mLineTermAux) {
|
|
// Finalize and release reference to LineTerm object owned by us
|
|
mLineTermAux->CloseAux();
|
|
mLineTermAux = nsnull;
|
|
}
|
|
|
|
nsCOMPtr<nsIDocShell> docShell = do_QueryReferent(mDocShell);
|
|
if (docShell) {
|
|
// Stop observing document loading
|
|
docShell->SetDocLoaderObserver((nsIDocumentLoaderObserver *)nsnull);
|
|
}
|
|
mDocShell = nsnull;
|
|
|
|
mPresShell = nsnull;
|
|
mXMLTermShell = nsnull;
|
|
|
|
XMLT_LOG(mozXMLTerminal::Finalize,22,("END\n"));
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
/** Activates XMLterm and instantiates LineTerm;
|
|
* called at the the end of Init page loading.
|
|
*/
|
|
NS_IMETHODIMP mozXMLTerminal::Activate(void)
|
|
{
|
|
nsresult result = NS_OK;
|
|
|
|
#if 0
|
|
// TEMPORARY: Testing mozIXMLTermStream
|
|
nsAutoString streamData( "<HTML><HEAD><TITLE>Stream Title</TITLE>"
|
|
"<SCRIPT language='JavaScript'>"
|
|
"function clik(){ dump('click\\n');return(false);}"
|
|
"</SCRIPT></HEAD>"
|
|
"<BODY><B>Stream Body "
|
|
"<SPAN STYLE='color: blue' onClick='return clik();'>Clik</SPAN></B><BR>"
|
|
"<TABLE WIDTH=720><TR><TD WIDTH=700 BGCOLOR=maroon> </TABLE>"
|
|
"<BR>ABCD<BR>EFGH<BR>JKLM<BR>"
|
|
"</BODY></HTML>" );
|
|
|
|
nsCOMPtr<mozIXMLTermStream> stream;
|
|
result = NS_NewXMLTermStream(getter_AddRefs(stream));
|
|
if (NS_FAILED(result)) {
|
|
fprintf(stderr, "mozXMLTerminal::Activate: Failed to create stream\n");
|
|
return result;
|
|
}
|
|
|
|
nsCOMPtr<nsIDocShell> docShell = do_QueryReferent(mDocShell);
|
|
if (!docShell)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
nsCOMPtr<nsIDOMWindowInternal> outerDOMWindow;
|
|
result = mozXMLTermUtils::ConvertDocShellToDOMWindow(docShell,
|
|
getter_AddRefs(outerDOMWindow));
|
|
|
|
if (NS_FAILED(result) || !outerDOMWindow) {
|
|
fprintf(stderr, "mozXMLTerminal::Activate: Failed to convert docshell\n");
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
result = stream->Open(outerDOMWindow, "iframet", "chrome://dummy",
|
|
"text/html", 800);
|
|
if (NS_FAILED(result)) {
|
|
fprintf(stderr, "mozXMLTerminal::Activate: Failed to open stream\n");
|
|
return result;
|
|
}
|
|
|
|
result = stream->Write(streamData.GetUnicode());
|
|
if (NS_FAILED(result)) {
|
|
fprintf(stderr, "mozXMLTerminal::Activate: Failed to write to stream\n");
|
|
return result;
|
|
}
|
|
|
|
result = stream->Close();
|
|
if (NS_FAILED(result)) {
|
|
fprintf(stderr, "mozXMLTerminal::Activate: Failed to close stream\n");
|
|
return result;
|
|
}
|
|
|
|
#endif
|
|
|
|
XMLT_LOG(mozXMLTerminal::Activate,20,("\n"));
|
|
|
|
if (!mInitialized)
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
PR_ASSERT(mDocShell != nsnull);
|
|
|
|
if ((mDOMDocument != nsnull) || (mPresShell != nsnull))
|
|
return NS_ERROR_FAILURE;
|
|
|
|
nsCOMPtr<nsIDocShell> docShell = do_QueryReferent(mDocShell);
|
|
if (!docShell)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
// Get reference to presentation shell
|
|
nsCOMPtr<nsIPresContext> presContext;
|
|
result = docShell->GetPresContext(getter_AddRefs(presContext));
|
|
if (NS_FAILED(result) || !presContext)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
nsCOMPtr<nsIPresShell> presShell;
|
|
result = docShell->GetPresShell(getter_AddRefs(presShell));
|
|
if (NS_FAILED(result) || !presShell)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
// Get reference to DOMDocument
|
|
nsCOMPtr<nsIDocument> document;
|
|
result = presShell->GetDocument(getter_AddRefs(document));
|
|
|
|
if (NS_FAILED(result) || !document)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(document);
|
|
if (!domDoc)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
// Save weak references to presentation shell and DOMDocument
|
|
mPresShell = getter_AddRefs(NS_GetWeakReference(presShell)); // weak ref
|
|
mDOMDocument = getter_AddRefs(NS_GetWeakReference(domDoc)); // weak ref
|
|
|
|
// Show caret
|
|
ShowCaret();
|
|
|
|
// Determine current screen dimensions
|
|
PRInt32 nRows, nCols, xPixels, yPixels;
|
|
result = ScreenSize(nRows, nCols, xPixels, yPixels);
|
|
if (NS_FAILED(result))
|
|
return result;
|
|
|
|
// The above call does not return the correct screen dimensions.
|
|
// (because rendering is still in progress?)
|
|
// As a workaround, explicitly set screen dimensions
|
|
nRows = 24;
|
|
nCols = 80;
|
|
xPixels = 0;
|
|
yPixels = 0;
|
|
|
|
// Instantiate and initialize XMLTermSession object
|
|
mXMLTermSession = new mozXMLTermSession();
|
|
|
|
if (!mXMLTermSession) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
result = mXMLTermSession->Init(this, presShell, domDoc, nRows, nCols);
|
|
if (NS_FAILED(result)) {
|
|
XMLT_WARNING("mozXMLTerminal::Activate: Warning - Failed to initialize XMLTermSession\n");
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
// Instantiate LineTerm
|
|
XMLT_LOG(mozXMLTerminal::Activate,22,
|
|
("instantiating lineterm, nRows=%d, nCols=%d\n", nRows, nCols));
|
|
result = NS_NewLineTermAux(getter_AddRefs(mLineTermAux));
|
|
if (NS_FAILED(result)) {
|
|
XMLT_WARNING("mozXMLTerminal::Activate: Warning - Failed to instantiate LineTermAux\n");
|
|
return result;
|
|
}
|
|
|
|
// Open LineTerm to execute command
|
|
// Non-owning reference to this; delete LineTerm before deleting self
|
|
PRInt32 options = 0;
|
|
|
|
XMLT_LOG(mozXMLTerminal::Activate,22,("Opening LineTerm\n"));
|
|
nsCOMPtr<nsIObserver> anObserver = this;
|
|
#ifdef NO_CALLBACK
|
|
anObserver = nsnull;
|
|
#endif
|
|
nsAutoString cookie;
|
|
result = mLineTermAux->OpenAux(mCommand.GetUnicode(),
|
|
mInitInput.GetUnicode(),
|
|
mPromptExpr.GetUnicode(),
|
|
options, LTERM_DETERMINE_PROCESS,
|
|
nRows, nCols, xPixels, yPixels,
|
|
domDoc, anObserver, cookie);
|
|
|
|
if (NS_FAILED(result)) {
|
|
XMLT_WARNING("mozXMLTerminal::Activate: Warning - Failed to open LineTermAux\n");
|
|
return result;
|
|
}
|
|
XMLT_LOG(mozXMLTerminal::Activate,22,("Opened LineTerm\n"));
|
|
|
|
// Save cookie
|
|
mCookie = cookie;
|
|
|
|
// Get the DOM event receiver for document
|
|
nsCOMPtr<nsIDOMEventReceiver> eventReceiver;
|
|
result = domDoc->QueryInterface(NS_GET_IID(nsIDOMEventReceiver),
|
|
getter_AddRefs(eventReceiver));
|
|
if (NS_FAILED(result)) {
|
|
XMLT_WARNING("mozXMLTerminal::Activate: Warning - Failed to get DOM receiver\n");
|
|
return result;
|
|
}
|
|
|
|
// Create a key listener
|
|
result = NS_NewXMLTermKeyListener(getter_AddRefs(mKeyListener), this);
|
|
if (NS_OK != result) {
|
|
XMLT_WARNING("mozXMLTerminal::Activate: Warning - Failed to get key listener\n");
|
|
return result;
|
|
}
|
|
|
|
// Register the key listener with the DOM event receiver
|
|
result = eventReceiver->AddEventListenerByIID(mKeyListener,
|
|
NS_GET_IID(nsIDOMKeyListener));
|
|
|
|
if (NS_FAILED(result)) {
|
|
XMLT_WARNING("mozXMLTerminal::Activate: Warning - Failed to register key listener\n");
|
|
return result;
|
|
}
|
|
|
|
// Create a text listener
|
|
result = NS_NewXMLTermTextListener(getter_AddRefs(mTextListener), this);
|
|
if (NS_OK != result) {
|
|
XMLT_WARNING("mozXMLTerminal::Activate: Warning - Failed to get text listener\n");
|
|
return result;
|
|
}
|
|
|
|
// Register the text listener with the DOM event receiver
|
|
result = eventReceiver->AddEventListenerByIID(mTextListener,
|
|
NS_GET_IID(nsIDOMTextListener));
|
|
if (NS_FAILED(result)) {
|
|
XMLT_WARNING("mozXMLTerminal::Activate: Warning - Failed to register text listener\n");
|
|
return result;
|
|
}
|
|
|
|
// Create a mouse listener
|
|
result = NS_NewXMLTermMouseListener(getter_AddRefs(mMouseListener), this);
|
|
if (NS_OK != result) {
|
|
XMLT_WARNING("mozXMLTerminal::Activate: Warning - Failed to get mouse listener\n");
|
|
return result;
|
|
}
|
|
|
|
// Register the mouse listener with the DOM event receiver
|
|
result = eventReceiver->AddEventListenerByIID(mMouseListener,
|
|
NS_GET_IID(nsIDOMMouseListener));
|
|
if (NS_FAILED(result)) {
|
|
XMLT_WARNING("mozXMLTerminal::Activate: Warning - Failed to register mouse listener\n");
|
|
return result;
|
|
}
|
|
|
|
// Create a drag listener
|
|
result = NS_NewXMLTermDragListener(getter_AddRefs(mDragListener), this);
|
|
if (NS_OK != result) {
|
|
XMLT_WARNING("mozXMLTerminal::Activate: Warning - Failed to get drag listener\n");
|
|
return result;
|
|
}
|
|
|
|
// Register the drag listener with the DOM event receiver
|
|
result = eventReceiver->AddEventListenerByIID(mDragListener,
|
|
NS_GET_IID(nsIDOMDragListener));
|
|
if (NS_FAILED(result)) {
|
|
XMLT_WARNING("mozXMLTerminal::Activate: Warning - Failed to register drag listener\n");
|
|
return result;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
/** Returns current screen size in rows/cols and in pixels
|
|
* @param (output) rows
|
|
* @param (output) cols
|
|
* @param (output) xPixels
|
|
* @param (output) yPixels
|
|
*/
|
|
NS_IMETHODIMP mozXMLTerminal::ScreenSize(PRInt32& rows, PRInt32& cols,
|
|
PRInt32& xPixels, PRInt32& yPixels)
|
|
{
|
|
nsresult result;
|
|
|
|
XMLT_LOG(mozXMLTerminal::ScreenSize,70,("\n"));
|
|
|
|
nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mPresShell);
|
|
if (!presShell)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
// Get presentation context
|
|
nsCOMPtr<nsIPresContext> presContext;
|
|
result = presShell->GetPresContext( getter_AddRefs(presContext) );
|
|
if (NS_FAILED(result))
|
|
return result;
|
|
|
|
// Get the default fixed pitch font
|
|
nsFont defaultFixedFont("dummyfont", NS_FONT_STYLE_NORMAL,
|
|
NS_FONT_VARIANT_NORMAL,
|
|
NS_FONT_WEIGHT_NORMAL,
|
|
NS_FONT_DECORATION_NONE, 16);
|
|
|
|
result = presContext->GetDefaultFixedFont(defaultFixedFont);
|
|
if (NS_FAILED(result))
|
|
return result;
|
|
|
|
// Get metrics for fixed font
|
|
nsCOMPtr<nsIFontMetrics> fontMetrics;
|
|
result = presContext->GetMetricsFor(defaultFixedFont,
|
|
getter_AddRefs(fontMetrics));
|
|
if (NS_FAILED(result) || !fontMetrics)
|
|
return result;
|
|
|
|
// Get font height (includes leading?)
|
|
nscoord fontHeight, fontWidth;
|
|
result = fontMetrics->GetHeight(fontHeight);
|
|
result = fontMetrics->GetMaxAdvance(fontWidth);
|
|
|
|
// Determine docshell size in twips
|
|
nsRect shellArea;
|
|
result = presContext->GetVisibleArea(shellArea);
|
|
if (NS_FAILED(result))
|
|
return result;
|
|
|
|
// Determine twips to pixels conversion factor
|
|
float pixelScale;
|
|
presContext->GetTwipsToPixels(&pixelScale);
|
|
|
|
// Convert dimensions to pixels
|
|
float xdel, ydel;
|
|
xdel = pixelScale * fontWidth;
|
|
ydel = pixelScale * fontHeight + 2;
|
|
|
|
xPixels = (int) (pixelScale * shellArea.width);
|
|
yPixels = (int) (pixelScale * shellArea.height);
|
|
|
|
// Determine number of rows/columns
|
|
rows = (int) ((yPixels-16) / ydel);
|
|
cols = (int) ((xPixels-20) / xdel);
|
|
|
|
if (rows < 1) rows = 1;
|
|
if (cols < 1) cols = 1;
|
|
|
|
XMLT_LOG(mozXMLTerminal::ScreenSize,72,
|
|
("rows=%d, cols=%d, xPixels=%d, yPixels=%d\n",
|
|
rows, cols, xPixels, yPixels));
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
// Transmit string to LineTerm (use saved cookie)
|
|
NS_IMETHODIMP mozXMLTerminal::SendTextAux(const nsString& aString)
|
|
{
|
|
return SendText(aString, mCookie.GetUnicode());
|
|
}
|
|
|
|
|
|
// Transmit string to LineTerm
|
|
NS_IMETHODIMP mozXMLTerminal::SendText(const nsString& aString,
|
|
const PRUnichar* aCookie)
|
|
{
|
|
nsresult result;
|
|
|
|
if (!mLineTermAux)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
nsAutoString sendStr(aString);
|
|
|
|
// Preprocess string and check if it is to be consumed
|
|
PRBool consumed, checkSize;
|
|
result = mXMLTermSession->Preprocess(sendStr, consumed, checkSize);
|
|
|
|
PRBool screenMode;
|
|
GetScreenMode(&screenMode);
|
|
|
|
if (!screenMode && (checkSize || mNeedsResizing)) {
|
|
// Resize terminal, if need be
|
|
mXMLTermSession->Resize(mLineTermAux);
|
|
mNeedsResizing = PR_FALSE;
|
|
}
|
|
|
|
if (!consumed) {
|
|
result = mLineTermAux->Write(sendStr.GetUnicode(), aCookie);
|
|
if (NS_FAILED(result)) {
|
|
// Abort XMLterm session
|
|
nsAutoString abortCode;
|
|
abortCode.AssignWithConversion("SendText");
|
|
mXMLTermSession->Abort(mLineTermAux, abortCode);
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
/** Shows the caret and make it editable.
|
|
*/
|
|
NS_IMETHODIMP mozXMLTerminal::ShowCaret(void)
|
|
{
|
|
// In principle, this method needs to be called only once;
|
|
// in practice, certain operations seem to hide the caret
|
|
// especially when one starts mucking around with the display:
|
|
// style property.
|
|
// Under those circumstances, call this method to re-display the caret.
|
|
|
|
XMLT_LOG(mozXMLTerminal::ShowCaret,70,("\n"));
|
|
|
|
if (!mPresShell)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mPresShell);
|
|
if (!presShell)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
nsCOMPtr<nsISelectionController> selCon = do_QueryInterface(presShell);
|
|
|
|
if (!selCon) {
|
|
XMLT_WARNING("mozXMLTerminal::ShowCaret: Warning - Failed to get SelectionController\n");
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
PRInt32 pixelWidth;
|
|
nsresult result;
|
|
|
|
NS_WITH_SERVICE(nsILookAndFeel, look, kLookAndFeelCID, &result);
|
|
|
|
if (NS_SUCCEEDED(result) && look) {
|
|
look->GetMetric(nsILookAndFeel::eMetric_SingleLineCaretWidth, pixelWidth);
|
|
|
|
selCon->SetCaretWidth(pixelWidth);
|
|
}
|
|
|
|
selCon->SetCaretEnabled(PR_TRUE);
|
|
selCon->SetCaretReadOnly(PR_FALSE);
|
|
|
|
nsCOMPtr<nsICaret> caret;
|
|
if (NS_SUCCEEDED(presShell->GetCaret(getter_AddRefs(caret))) && caret) {
|
|
|
|
caret->SetCaretVisible(PR_TRUE);
|
|
caret->SetCaretReadOnly(PR_FALSE);
|
|
|
|
nsCOMPtr<nsISelection> sel;
|
|
|
|
if (NS_SUCCEEDED(selCon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(sel))) && sel) {
|
|
caret->SetCaretDOMSelection(sel);
|
|
}
|
|
} else {
|
|
XMLT_WARNING("mozXMLTerminal::ShowCaret: Warning - Failed to get caret\n");
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
// Paste data from clipboard to terminal
|
|
NS_IMETHODIMP mozXMLTerminal::Paste()
|
|
{
|
|
nsresult result;
|
|
nsAutoString pasteString;
|
|
|
|
XMLT_LOG(mozXMLTerminal::Paste,20,("\n"));
|
|
|
|
// Get Clipboard service
|
|
NS_WITH_SERVICE (nsIClipboard, clipboard, kCClipboardCID, &result);
|
|
if ( NS_FAILED(result) )
|
|
return result;
|
|
|
|
// Generic transferable for getting clipboard data
|
|
nsCOMPtr<nsITransferable> trans;
|
|
result = nsComponentManager::CreateInstance(kCTransferableCID, nsnull,
|
|
NS_GET_IID(nsITransferable),
|
|
(void**) getter_AddRefs(trans));
|
|
|
|
if (NS_FAILED(result) || !trans)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
// DataFlavors to get out of transferable
|
|
trans->AddDataFlavor(kHTMLMime);
|
|
trans->AddDataFlavor(kUnicodeMime);
|
|
|
|
// Get data from clipboard
|
|
result = clipboard->GetData(trans, nsIClipboard::kSelectionClipboard);
|
|
if (NS_FAILED(result))
|
|
return result;
|
|
|
|
char* bestFlavor = nsnull;
|
|
nsCOMPtr<nsISupports> genericDataObj;
|
|
PRUint32 objLen = 0;
|
|
result = trans->GetAnyTransferData(&bestFlavor,
|
|
getter_AddRefs(genericDataObj), &objLen);
|
|
if (NS_FAILED(result))
|
|
return result;
|
|
|
|
nsAutoString flavor;
|
|
flavor.AssignWithConversion(bestFlavor);
|
|
|
|
char* temCStr = flavor.ToNewCString();
|
|
XMLT_LOG(mozXMLTerminal::Paste,20,("flavour=%s\n", temCStr));
|
|
nsMemory::Free(temCStr);
|
|
|
|
if (flavor.EqualsWithConversion(kHTMLMime) || flavor.EqualsWithConversion(kUnicodeMime)) {
|
|
nsCOMPtr<nsISupportsWString> textDataObj ( do_QueryInterface(genericDataObj) );
|
|
if (textDataObj && objLen > 0) {
|
|
PRUnichar* text = nsnull;
|
|
textDataObj->ToString ( &text );
|
|
pasteString.Assign( text, objLen / 2 );
|
|
result = SendTextAux(pasteString);
|
|
}
|
|
}
|
|
nsMemory::Free(bestFlavor);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
// Poll for readable data from LineTerm
|
|
NS_IMETHODIMP mozXMLTerminal::Poll(void)
|
|
{
|
|
if (!mLineTermAux)
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
XMLT_LOG(mozXMLTerminal::Poll,20,("\n"));
|
|
|
|
nsresult result;
|
|
PRBool processedData;
|
|
|
|
result = mXMLTermSession->ReadAll(mLineTermAux, processedData);
|
|
if (NS_FAILED(result)) {
|
|
XMLT_WARNING("mozXMLTerminal::Poll: Warning - Error return 0x%x from ReadAll\n", result);
|
|
return result;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
// Handle callback from LineTerm when new input/output needs to be displayed
|
|
NS_IMETHODIMP mozXMLTerminal::Observe(nsISupports *aSubject,
|
|
const PRUnichar *aTopic,
|
|
const PRUnichar *someData)
|
|
{
|
|
nsCOMPtr<mozILineTermAux> lineTermAux = do_QueryInterface(aSubject);
|
|
PR_ASSERT(lineTermAux != nsnull);
|
|
|
|
PR_ASSERT(lineTermAux.get() == mLineTermAux.get());
|
|
|
|
return Poll();
|
|
}
|
|
|
|
|
|
// Returns document associated with XMLTerminal
|
|
NS_IMETHODIMP mozXMLTerminal::GetDocument(nsIDOMDocument** aDoc)
|
|
{
|
|
if (!aDoc)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
*aDoc = nsnull;
|
|
|
|
NS_PRECONDITION(mDOMDocument, "bad state, null mDOMDocument");
|
|
if (!mDOMDocument)
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryReferent(mDOMDocument);
|
|
if (!domDoc)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
return domDoc->QueryInterface(NS_GET_IID(nsIDOMDocument),
|
|
(void **)aDoc);
|
|
}
|
|
|
|
|
|
// Returns doc shell associated with XMLTerm
|
|
NS_IMETHODIMP mozXMLTerminal::GetDocShell(nsIDocShell** aDocShell)
|
|
{
|
|
if (!aDocShell)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
*aDocShell = nsnull;
|
|
|
|
NS_PRECONDITION(mDocShell, "bad state, null mDocShell");
|
|
if (!mDocShell)
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
nsCOMPtr<nsIDocShell> docShell = do_QueryReferent(mDocShell);
|
|
if (!docShell) {
|
|
XMLT_ERROR("mozXMLTerminal::GetDocShell: Error - Invalid weak reference\n");
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
return docShell->QueryInterface(NS_GET_IID(nsIDocShell),
|
|
(void **)aDocShell);
|
|
}
|
|
|
|
|
|
// Returns presentation shell associated with XMLTerm
|
|
NS_IMETHODIMP mozXMLTerminal::GetPresShell(nsIPresShell** aPresShell)
|
|
{
|
|
if (!aPresShell)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
*aPresShell = nsnull;
|
|
|
|
NS_PRECONDITION(mPresShell, "bad state, null mPresShell");
|
|
if (!mPresShell)
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mPresShell);
|
|
if (!presShell) {
|
|
XMLT_ERROR("mozXMLTerminal::GetPresShell: Error - Invalid weak reference\n");
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
return presShell->QueryInterface(NS_GET_IID(nsIPresShell),
|
|
(void **)aPresShell);
|
|
}
|
|
|
|
|
|
// Returns DOMDocument associated with XMLTerm
|
|
NS_IMETHODIMP mozXMLTerminal::GetDOMDocument(nsIDOMDocument** aDOMDocument)
|
|
{
|
|
if (!aDOMDocument)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
*aDOMDocument = nsnull;
|
|
|
|
NS_PRECONDITION(mDOMDocument, "bad state, null mDOMDocument");
|
|
if (!mDOMDocument)
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryReferent(mDOMDocument);
|
|
if (!domDoc) {
|
|
XMLT_ERROR("mozXMLTerminal::GetDOMDocument: Error - Invalid weak reference\n");
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
return domDoc->QueryInterface(NS_GET_IID(nsIDOMDocument),
|
|
(void **)aDOMDocument);
|
|
}
|
|
|
|
|
|
// Returns SelectionController associated with XMLTerm
|
|
NS_IMETHODIMP mozXMLTerminal::GetSelectionController(nsISelectionController** aSelectionController)
|
|
{
|
|
if (!aSelectionController)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
*aSelectionController = nsnull;
|
|
|
|
NS_PRECONDITION(mPresShell, "bad state, null mPresShell");
|
|
if (!mPresShell)
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mPresShell);
|
|
if (!presShell) {
|
|
XMLT_ERROR("mozXMLTerminal::GetSelectionControlle: Error - Invalid weak reference\n");
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
return presShell->QueryInterface(NS_GET_IID(nsISelectionController),
|
|
(void **)aSelectionController);
|
|
}
|
|
|
|
|
|
/** Gets flag denoting whether terminal is in full screen mode
|
|
* @param aFlag (output) screen mode flag
|
|
*/
|
|
NS_IMETHODIMP mozXMLTerminal::GetScreenMode(PRBool* aFlag)
|
|
{
|
|
return mXMLTermSession->GetScreenMode(aFlag);
|
|
}
|
|
|
|
|
|
/** Checks if supplied cookie is valid for XMLTerm
|
|
* @param aCookie supplied cookie string
|
|
* @param _retval PR_TRUE if supplied cookie matches XMLTerm cookie
|
|
*/
|
|
NS_IMETHODIMP mozXMLTerminal::MatchesCookie(const PRUnichar* aCookie,
|
|
PRBool *_retval)
|
|
{
|
|
XMLT_LOG(mozXMLTerminal::MatchesCookie,20,("\n"));
|
|
|
|
if (!_retval)
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
// Check if supplied cookie matches XMLTerm cookie
|
|
*_retval = mCookie.EqualsWithConversion(aCookie);
|
|
|
|
if (!(*_retval)) {
|
|
XMLT_ERROR("mozXMLTerminal::MatchesCookie: Error - Cookie mismatch\n");
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
/** Resizes XMLterm to match a resized window.
|
|
*/
|
|
NS_IMETHODIMP mozXMLTerminal::Resize(void)
|
|
{
|
|
nsresult result;
|
|
|
|
XMLT_LOG(mozXMLTerminal::Resize,20,("\n"));
|
|
|
|
if (!mXMLTermSession)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
PRBool screenMode;
|
|
GetScreenMode(&screenMode);
|
|
|
|
if (screenMode) {
|
|
// Delay resizing until next input processing
|
|
mNeedsResizing = PR_TRUE;
|
|
} else {
|
|
// Resize session
|
|
result = mXMLTermSession->Resize(mLineTermAux);
|
|
if (NS_FAILED(result))
|
|
return result;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
// nsIDocumentLoaderObserver methods
|
|
NS_IMETHODIMP
|
|
mozXMLTerminal::OnStartDocumentLoad(nsIDocumentLoader* loader, nsIURI* aURL,
|
|
const char* aCommand)
|
|
{
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
mozXMLTerminal::OnEndDocumentLoad(nsIDocumentLoader* loader, nsIRequest* request,
|
|
nsresult aStatus)
|
|
{
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
mozXMLTerminal::OnStartURLLoad(nsIDocumentLoader* loader,
|
|
nsIRequest* request)
|
|
{
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
mozXMLTerminal::OnProgressURLLoad(nsIDocumentLoader* loader,
|
|
nsIRequest* request, PRUint32 aProgress,
|
|
PRUint32 aProgressMax)
|
|
{
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
mozXMLTerminal::OnStatusURLLoad(nsIDocumentLoader* loader,
|
|
nsIRequest* request, nsString& aMsg)
|
|
{
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
mozXMLTerminal::OnEndURLLoad(nsIDocumentLoader* loader,
|
|
nsIRequest* request, nsresult aStatus)
|
|
{
|
|
XMLT_LOG(mozXMLTerminal::OnEndURLLoad,20,("\n"));
|
|
|
|
// Activate XMLTerm
|
|
Activate();
|
|
return NS_OK;
|
|
}
|