home *** CD-ROM | disk | FTP | other *** search
- /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * The contents of this file are subject to the Netscape Public License
- * Version 1.0 (the "NPL"); you may not use this file except in
- * compliance with the NPL. You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- *
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1998 Netscape Communications Corporation. All Rights
- * Reserved.
- */
-
- #include "CEditorWindow.h"
- #include "CBrowserContext.h"
- #include "resgui.h"
- #include "CFormattingToolBar.h"
- #include "CFontMenuAttachment.h"
- #include "CToolbarPopup.h"
- #include "CPatternButtonPopupText.h"
- #include "COpenRecentlyEditedPopup.h"
- #include "CColorPopup.h"
-
- #include "CEditDictionary.h"
-
- #include "CTextTable.h"
- #include "CTableKeySingleSelector.h"
-
- // macfe
- #include "mversion.h" // ID_STRINGS
- #include "URobustCreateWindow.h"
- #include "uprefd.h"
- #include "uerrmgr.h"
- #include "uapp.h"
- #include "meditdlg.h" // CTabbedDialog
- #include "meditor.h" // HandleModalDialog
- #include "CEditView.h"
-
- // Netscape
- #include "net.h" // NET_cinfo_find_type
- #include "proto.h" // XP_IsContextBusy
- #include "edt.h"
- #include "shist.h"
- #include "prefapi.h" // PREF_GetBoolPref
-
- #ifdef PROFILE
- #pragma profile on
- #endif
-
- // pane id constants - for ShowOneDragBar
- const PaneIDT Paragraph_Bar_PaneID = 'DBar';
- const PaneIDT Character_Bar_PaneID = 'NBar';
-
- const char* Pref_ShowParagraphBar = "editor.show_paragraph_toolbar";
- const char* Pref_ShowCharacterBar = "editor.show_character_toolbar";
-
- enum { eParagraphBar,
- eCharacterBar };
-
- CEditorWindow::CEditorWindow( LStream* inStream )
- :CBrowserWindow(inStream)
- {
- SetWindowType( WindowType_Editor );
- }
-
-
- static // PRIVATE
- CMediatedWindow* GetFrontWindowByType( OSType windowType )
- {
- CMediatedWindow* theWindow = NULL;
- CWindowIterator iter(windowType);
- iter.Next(theWindow);
- return theWindow;
- }
-
- // given an mwcontext (non-busy, with a history), select the matching editor window
- // or open an editor window based on that mwcontext
- // if all else fails (and memory is not low), create an empty editor window
- void CEditorWindow::MakeEditWindowFromBrowser( MWContext* mwcontext )
- {
- if ( Memory_MemoryIsLow() )
- return;
-
- History_entry* entry = NULL;
- if ( mwcontext && !XP_IsContextBusy( mwcontext ) )
- entry = SHIST_GetCurrent(&mwcontext->hist);
-
- if ( entry && entry->address)
- {
- // If there is already an editor window open for this url
- // just switch to it and keep this browser window open.
- CMediatedWindow * win;
- CWindowIterator iter(WindowType_Editor);
- while (iter.Next(win))
- {
- CNSContext* curContext = ((CBrowserWindow *)win)->GetWindowContext();
- MWContext* context;
-
- context = curContext ? curContext->operator MWContext*() : NULL;
- if (context && EDT_IS_EDITOR(context))
- {
- History_entry* newEntry = SHIST_GetCurrent(&context->hist);
- if (newEntry && newEntry->address && !strcmp(newEntry->address, entry->address))
- {
- win->Show();
- win->Select();
- return;
- }
- }
- }
-
- if (CEditorWindow::MakeEditWindow(mwcontext, NULL) == NULL) // new window based on history of this window
- return; // don't close this one on error.
- }
- else
- {
- CEditorWindow::MakeEditWindow(NULL, NULL); // make a completely new window
- }
- }
-
-
- // EDT_PreOpenCallbackFn
- static void createEditorWindowCallback( XP_Bool userCanceled, char* pURL, void* hook )
- {
- if ( !userCanceled )
- {
- EditorCreationStruct *edtCreatePtr = (EditorCreationStruct *)hook;
-
- if ( hook )
- {
- if ( edtCreatePtr->existingURLstruct && edtCreatePtr->existingURLstruct->address )
- {
- XP_FREE( edtCreatePtr->existingURLstruct->address );
- edtCreatePtr->existingURLstruct->address = XP_STRDUP( pURL );
- }
- }
-
- // substitute new URL
- CEditorWindow::CreateEditorWindowStage2( edtCreatePtr );
- }
- }
-
-
- CEditorWindow* CEditorWindow::MakeEditWindow( MWContext* old_context, URL_Struct* url )
- {
- Boolean urlCameInNULL = (url == NULL);
-
- // if we don't have an URL, try to get it from the old_context's window history
- if (url == NULL && old_context != NULL)
- {
- CBrowserContext *browserContext = (CBrowserContext *)old_context->fe.newContext;
- History_entry* entry = browserContext->GetCurrentHistoryEntry(); // Take the last instead of the first history entry.
- if ( entry )
- {
- url = SHIST_CreateURLStructFromHistoryEntry( old_context, entry );
- if ( url )
- url->force_reload = NET_NORMAL_RELOAD;
- }
- // if we don't have a history entry, we're kind of screwed-->just load a blank page
- }
-
- // we want to open a new blank edit window
- // or we are still having troubles... fall back to our old tried and true blank page
- if (url == NULL)
- url = NET_CreateURLStruct ("about:editfilenew", NET_NORMAL_RELOAD );
- // FIX THIS!!! the above line should use "XP_GetString(XP_EDIT_NEW_DOC_NAME)"
-
- // time of reckoning. We really, really need an URL and address at this point...
- // I don't know what an url without an address is anyway...
- if (url == NULL || url->address == NULL)
- return NULL;
-
- // now make sure that the url is a valid type to edit.
- NET_cinfo *cinfo = NET_cinfo_find_type (url->address);
-
- if (cinfo == NULL || cinfo->type == NULL ||
- (strcasecomp (cinfo->type, TEXT_HTML)
- && strcasecomp (cinfo->type, UNKNOWN_CONTENT_TYPE)
- && strcasecomp (cinfo->type, TEXT_PLAIN)))
- {
- ErrorManager::PlainAlert( NOT_HTML );
- return NULL;
- }
-
- EditorCreationStruct *edtCreatePtr = (EditorCreationStruct *)XP_ALLOC( sizeof( EditorCreationStruct ) );
- if ( edtCreatePtr )
- {
- edtCreatePtr->context = old_context;
- edtCreatePtr->existingURLstruct = url;
- edtCreatePtr->isEmptyPage = old_context == NULL && urlCameInNULL;
- }
-
- if ( urlCameInNULL && old_context == NULL )
- {
- return CreateEditorWindowStage2( edtCreatePtr );
- }
- else
- {
- EDT_PreOpen( old_context, url->address, createEditorWindowCallback, edtCreatePtr );
- return NULL;
- }
- }
-
-
- CEditorWindow *CEditorWindow::CreateEditorWindowStage2( EditorCreationStruct *edtCreatePtr )
- {
- // now we can create an editor window since we don't already have one for this url.
-
- /* instead of just calling LWindow::CreateWindow(), we do it ourselves by hand here
- * so that we can set the window bounds before we call FinishCreate().
- */
-
- if ( edtCreatePtr == NULL )
- return NULL;
-
- CEditorWindow* newWindow = NULL;
- SetDefaultCommander(CFrontApp::GetApplication());
- try {
- OSErr error;
- URobustCreateWindow::ReadObjects( 'PPob', CEditorWindow::res_ID, &newWindow, &error );
- Assert_(newWindow);
- FailOSErr_(error);
- if (newWindow == NULL)
- {
- XP_FREE( edtCreatePtr );
- return NULL;
- }
-
- newWindow->FinishCreate();
- if (newWindow->HasAttribute(windAttr_ShowNew))
- newWindow->Show();
-
- UReanimator::LinkListenerToControls( newWindow, newWindow, CEditorWindow::res_ID );
- }
- catch(...)
- {
- if ( newWindow )
- delete newWindow;
-
- XP_FREE( edtCreatePtr );
-
- return NULL;
- }
-
- Boolean hasURLstruct = edtCreatePtr->existingURLstruct && edtCreatePtr->existingURLstruct->address;
- CBrowserContext *nscontext = new CBrowserContext();
- newWindow->SetWindowContext( nscontext );
-
- CURLDispatcher::DispatchURL( edtCreatePtr->existingURLstruct, nscontext, false, false, CEditorWindow::res_ID );
-
- if ( edtCreatePtr->context )
- {
- nscontext->InitHistoryFromContext( (CBrowserContext *)edtCreatePtr->context->fe.newContext );
- }
- else
- {
- // the url will eventually be freed when the load is complete.
- }
-
- // set window title here (esp. for "open")
- if ( !edtCreatePtr->isEmptyPage
- && edtCreatePtr->existingURLstruct && edtCreatePtr->existingURLstruct->address )
- {
- char *pSlash = strrchr( edtCreatePtr->existingURLstruct->address, '/' );
- if ( pSlash )
- pSlash += 1; // move past '/'
- newWindow->NoteDocTitleChanged( pSlash );
- }
-
- XP_FREE( edtCreatePtr );
-
- return newWindow;
- }
-
-
- void CEditorWindow::SetWindowContext(CBrowserContext* inContext)
- {
- if ( inContext )
- {
- MWContext *context;
- context = inContext->operator MWContext*();
- if ( context )
- {
- context->is_editor = true;
- NET_CheckForTimeBomb( context );
- }
- }
-
- CBrowserWindow::SetWindowContext( inContext );
- }
-
-
- void CEditorWindow::NoteDocTitleChanged( const char* inNewTitle )
- {
- // there is one bogus set-title from layout that we want to skip...
- // We are hard coding "editfilenew" here because it is already hardcoded
- // a million other places...
- if ( inNewTitle && XP_STRCMP( inNewTitle, "editfilenew" ) == 0 )
- return;
-
- CNSContext *theContext = GetWindowContext();
-
- CStr255 title( inNewTitle );
- char *baseName = LO_GetBaseURL( theContext->operator MWContext*() ); // don't free this...
- // strip out username and password so user doesn't see them in window title
- char *location = NULL;
- if ( baseName )
- NET_ParseUploadURL( baseName, &location, NULL, NULL );
- CStr255 csBaseURL(location);
- // if this page has a local "file:" url, then just show the file name (skip the url and directory crap.)
-
- if ( location && NET_IsLocalFileURL(location) )
- {
- char *localName = NULL;
- XP_ConvertUrlToLocalFile( location, &localName );
-
- if (localName)
- {
- #if 0
- char *pSlash = strrchr(localName, '/');
- if (pSlash)
- { // is there is a slash, move everything AFTER the last slash to the front
- pSlash++;
- XP_STRCPY(localName, pSlash);
- }
- #endif
-
- csBaseURL = localName;
- XP_FREE(localName);
- }
- }
-
- CStr255 netscapeTitle;
- CStr255 subTitle;
-
- ::GetIndString( netscapeTitle, ID_STRINGS, APPNAME_STRING_INDEX );
- ::GetIndString( subTitle, WINDOW_TITLES_RESID, 3 );
-
- netscapeTitle += " ";
- netscapeTitle += subTitle;
- netscapeTitle += " - [";
- if ( inNewTitle && *inNewTitle )
- {
- netscapeTitle += title;
- if (csBaseURL.Length())
- netscapeTitle += " : ";
- }
- netscapeTitle += csBaseURL;
- netscapeTitle += "]";
-
- SetDescriptor( netscapeTitle );
-
- if ( location )
- XP_FREE( location );
- }
-
-
- void CEditorWindow::RegisterViewTypes()
- {
- // Registers all its view types
- RegisterClass_( CEditorWindow);
- RegisterClass_( CEditView);
- RegisterClass_( MultipleSelectionSingleColumn); // newer, better class?
- RegisterClass_( CTarget);
- RegisterClass_( CLineProp);
- RegisterClass_( CFormattingToolBar);
-
- RegisterClass_( CToolbarPopup); // newer, better class?
- RegisterClass_( CIconToolbarPopup); // newer, better class?
- RegisterClass_( CColorPopup);
- RegisterClass_( CFontMenuPopup );
-
- RegisterClass_( CChameleonCaption); // newer, better class?
- RegisterClass_( CChameleonView); // newer, better class?
- CTabbedDialog::RegisterViewTypes();
-
- RegisterClass_( CTextTable); // newer, better class?
- RegisterClass_( CTableKeySingleSelector); // newer, better class?
-
- RegisterClass_( CPatternButtonPopupText); // newer, better class?
- RegisterClass_( LOffscreenView);
- RegisterClass_( COpenRecentlyEditedPopup );
-
- RegisterClass_( CEditDictionary);
- RegisterClass_( CEditDictionaryTable);
- }
-
-
- void CEditorWindow::FinishCreateSelf()
- {
- CBrowserWindow::FinishCreateSelf();
-
- // Show/hide toolbars based on preference settings
- XP_Bool value;
- PREF_GetBoolPref(Pref_ShowParagraphBar, &value);
- mToolbarShown[eParagraphBar] = value;
- ShowOneDragBar(Paragraph_Bar_PaneID, value);
- PREF_GetBoolPref(Pref_ShowCharacterBar, &value);
- mToolbarShown[eCharacterBar] = value;
- ShowOneDragBar(Character_Bar_PaneID, value);
- }
-
-
- void CEditorWindow::ListenToMessage( MessageT inMessage, void* ioParam )
- {
- switch (inMessage)
- {
- case msg_NSCDocTitleChanged:
- NoteDocTitleChanged((const char*)ioParam);
- break;
-
- default:
- {
- if ( inMessage == 'Para' )
- {
- switch (*(long*)ioParam)
- {
- case 1: inMessage = cmd_Format_Paragraph_Normal; break;
- case 2: inMessage = cmd_Format_Paragraph_Head1; break;
- case 3: inMessage = cmd_Format_Paragraph_Head2; break;
- case 4: inMessage = cmd_Format_Paragraph_Head3; break;
- case 5: inMessage = cmd_Format_Paragraph_Head4; break;
- case 6: inMessage = cmd_Format_Paragraph_Head5; break;
- case 7: inMessage = cmd_Format_Paragraph_Head6; break;
- case 8: inMessage = cmd_Format_Paragraph_Address; break;
- case 9: inMessage = cmd_Format_Paragraph_Formatted; break;
- case 10: inMessage = cmd_Format_Paragraph_List_Item; break;
- case 11: inMessage = cmd_Format_Paragraph_Desc_Title; break;
- case 12: inMessage = cmd_Format_Paragraph_Desc_Text; break;
- }
- }
- else if ( inMessage == 'Size' )
- {
- switch (*(long*)ioParam)
- {
- case 1: inMessage = cmd_Format_Font_Size_N2; break;
- case 2: inMessage = cmd_Format_Font_Size_N1; break;
- case 3: inMessage = cmd_Format_Font_Size_0; break;
- case 4: inMessage = cmd_Format_Font_Size_P1; break;
- case 5: inMessage = cmd_Format_Font_Size_P2; break;
- case 6: inMessage = cmd_Format_Font_Size_P3; break;
- case 7: inMessage = cmd_Format_Font_Size_P4; break;
- }
- }
- else if ( inMessage == 'Algn' )
- {
- switch (*(long*)ioParam)
- {
- case 1: inMessage = cmd_JustifyLeft; break;
- case 2: inMessage = cmd_JustifyCenter; break;
- case 3: inMessage = cmd_JustifyRight; break;
- }
- }
-
- // GetHTMLView() guaranteed not to fail
- GetHTMLView()->ObeyCommand( inMessage, ioParam );
- break;
- }
- }
- }
-
-
- // EDT_PreCloseCallbackFn
- static void closeEditorWindowCallback( void* hook )
- {
- CEditorWindow *editorWindow = (CEditorWindow *)hook;
- if ( editorWindow )
- editorWindow->SetPluginDoneClosing();
- }
-
-
- Boolean CEditorWindow::ObeyCommand( CommandT inCommand, void *ioParam )
- {
- switch ( inCommand )
- {
- case cmd_NewWindowEditor:
- CEditorWindow::MakeEditWindow( NULL, NULL );
- break;
-
- case cmd_ViewSource:
- // Delegate this to the view.
- if ( ((CEditView *)GetHTMLView())->IsDoneLoading() )
- GetHTMLView()->ObeyCommand(inCommand, ioParam);
- break;
-
- case cmd_Toggle_Paragraph_Toolbar:
- ToggleDragBar(Paragraph_Bar_PaneID, eParagraphBar, Pref_ShowParagraphBar);
- break;
-
- case cmd_Toggle_Character_Toolbar:
- ToggleDragBar(Character_Bar_PaneID, eCharacterBar, Pref_ShowCharacterBar);
- break;
-
- case cmd_Close:
- case cmd_Quit: // we'll just intercept these and then send them on to the default case
- MWContext *mwcontext = GetWindowContext()->operator MWContext*();
- History_entry* newEntry = SHIST_GetCurrent(&mwcontext->hist);
- CStr255 fileName;
- if ( newEntry && newEntry->address )
- fileName = newEntry->address;
-
- if ( ((CEditView *)GetHTMLView())->IsDoneLoading() && EDT_DirtyFlag( *GetWindowContext() ) )
- {
- Select(); // This helps during a quit or "close all"
-
- MessageT itemHit = HandleModalDialog( EDITDLG_SAVE_BEFORE_QUIT, fileName, NULL );
- if (itemHit == cancel)
- return true;
-
- if (itemHit == ok)
- { // save
- if ( !((CEditView *)GetHTMLView())->SaveDocument() )
- return true;
- }
- EDT_SetDirtyFlag( mwcontext, false ); // we have to do this or else when we quit, we will be asked twice to save
- }
-
- // need to let this work asynchronously; make our own internal loop
- if ( ((CEditView *)GetHTMLView())->IsDoneLoading() && newEntry && newEntry->address )
- {
- mPluginDoneClosing = false;
- EDT_PreClose( mwcontext, newEntry->address, closeEditorWindowCallback, this );
-
- do
- {
- CFrontApp::GetApplication()->ProcessNextEvent();
- } while ( !mPluginDoneClosing );
- }
-
- // fall through
-
- default:
- {
- return CBrowserWindow::ObeyCommand (inCommand, ioParam);
- }
- }
- return TRUE;
- }
-
-
- void CEditorWindow::FindCommandStatus( CommandT inCommand,
- Boolean& outEnabled, Boolean& outUsesMark, Char16& outMark,
- Str255 outName )
- {
- short index;
- outUsesMark = FALSE;
- outEnabled = false;
-
- switch ( inCommand )
- {
- case cmd_ViewSource:
- // Delegate this to the view.
- if ( ((CEditView *)GetHTMLView())->IsDoneLoading() )
- GetHTMLView()->FindCommandStatus(inCommand, outEnabled, outUsesMark, outMark, outName);
- break;
-
- case cmd_Toggle_Character_Toolbar:
- outEnabled = ((CEditView *)GetHTMLView())->IsDoneLoading();
- index = mToolbarShown[eCharacterBar] ? CEditView::EDITOR_MENU_HIDE_COMP_TOOLBAR
- : CEditView::EDITOR_MENU_SHOW_COMP_TOOLBAR;
- ::GetIndString( outName, CEditView::STRPOUND_EDITOR_MENUS, index );
- break;
-
- case cmd_Toggle_Paragraph_Toolbar:
- outEnabled = ((CEditView *)GetHTMLView())->IsDoneLoading();
- index = mToolbarShown[eParagraphBar] ? CEditView::EDITOR_MENU_HIDE_FORMAT_TOOLBAR
- : CEditView::EDITOR_MENU_SHOW_FORMAT_TOOLBAR;
- ::GetIndString( outName, CEditView::STRPOUND_EDITOR_MENUS, index );
- break;
-
- default:
- CBrowserWindow::FindCommandStatus(inCommand, outEnabled, outUsesMark, outMark, outName );
- }
- }
-
-
- // Called when we are trying to quit the application
- Boolean CEditorWindow::AttemptQuitSelf( long inSaveOption )
- {
- MWContext *mwcontext = GetWindowContext()->operator MWContext*();
- if ( EDT_DirtyFlag( mwcontext ) )
- {
- History_entry* newEntry = SHIST_GetCurrent(&mwcontext->hist);
- CStr255 fileName;
- if ( newEntry && newEntry->address )
- fileName = newEntry->address;
-
- if ( kAEAsk == inSaveOption )
- {
- MessageT itemHit = HandleModalDialog( EDITDLG_SAVE_BEFORE_QUIT, fileName, NULL );
- if ( cancel == itemHit )
- return false;
- }
-
- // save
- if ( !((CEditView *)GetHTMLView())->SaveDocument() )
- return false;
- }
-
- return true;
- }
-
- #ifdef PROFILE
- #pragma profile off
- #endif
-