home *** CD-ROM | disk | FTP | other *** search
Text File | 1998-04-08 | 28.4 KB | 1,051 lines |
- /* -*- 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 "CSpellChecker.h"
-
- #include "CTextTable.h"
- #include "StBlockingDialogHandler.h"
- #include "URobustCreateWindow.h"
- #include "CSimpleTextView.h"
- #include "LGAEditField.h"
- #include "LGAPushButton.h"
- #include "LGAPopup.h"
- #include "CEditDictionary.h"
- #include "UMenuUtils.h"
-
- // need to include "structs.h" before "edt.h" because "edt.h" is missing
- // some of the includes it needs
- #include "structs.h"
- #include "edt.h"
- #include "proto.h" // LO_GetSelectionText
- #include "prefapi.h" // PREF_SetIntPref
- #include "uerrmgr.h" // ErrorManager
- #include "resgui.h" // error stringNums
- #include "macgui.h" // StPrepareForDialog
- #include "ufilemgr.h" // CFileMgr
-
- // shared library stuff from NSPR
- #include "prlink.h"
-
-
- /* The difference between calling the spell checker lib from a DLL or from
- a static linked lib depends on whether we're generating CFM code
- (and on whether the static lib was included in the application project) */
- #if GENERATINGCFM
- #define USE_DYNAMIC_SC_LIB
- #else
- #undef USE_DYNAMIC_SC_LIB
- #endif
-
- // local prototypes
- static void exit_spellchecker( PRLibrary *lib, ISpellChecker *pSpellChecker, CMacSpellChecker *macSpellChecker );
-
-
- // function typedefs
- typedef ISpellChecker*(*sc_create_func)();
- typedef void (*sc_destroy_func)(ISpellChecker *);
-
-
-
- CMacSpellChecker::CMacSpellChecker( MWContext *context, CEditView *editView, CSimpleTextView *textView )
- {
- mMWContext = context;
- mEditView = editView;
- mTextView = textView;
- mISpellChecker = NULL;
- }
-
-
- void CMacSpellChecker::ReplaceHilitedText( char *newText, Boolean doAll )
- {
- if ( mEditView )
- {
- char *oldWord = (char *)LO_GetSelectionText( GetMWContext() );
- if ( oldWord == NULL )
- return;
-
- EDT_ReplaceMisspelledWord( GetMWContext(), oldWord, newText, doAll );
- XP_FREE( oldWord );
- }
- else if ( mTextView )
- {
- GetISpellChecker()->ReplaceMisspelledWord( newText, doAll );
-
- /* assume the misspelled word is selected so that InsertPtr will replace it */
- mTextView->InsertPtr( newText, XP_STRLEN(newText), NULL, NULL, false, true );
- }
- }
-
-
- void CMacSpellChecker::IgnoreHilitedText( Boolean doAll )
- {
- if ( mEditView )
- {
- char *oldWord = (char *)LO_GetSelectionText( GetMWContext() );
- if ( oldWord == NULL )
- return;
-
- EDT_IgnoreMisspelledWord( GetMWContext(), oldWord, doAll );
- XP_FREE( oldWord );
- }
- else if ( mTextView && doAll )
- {
- SInt32 selStart = 0;
- SInt32 selEnd = 0;
- SInt32 selLen = 0;
-
- mTextView->GetSelection( &selStart, &selEnd );
-
- selLen = selEnd - selStart;
-
- if ( selLen > 0 )
- {
- Handle theText = mTextView->GetTextHandle();
- XP_ASSERT( theText != NULL );
-
- char *textP = (char *)XP_ALLOC( selLen + 1 );
- XP_ASSERT( textP );
- if ( textP )
- {
- ::BlockMoveData( ((char *)*theText) + selStart, textP, selLen );
- textP[ selLen ] = 0;
-
- GetISpellChecker()->IgnoreWord( textP );
- XP_FREE( textP );
- }
- }
- }
- // assume we don't need to do anything for ignoring just this occurrence in plain text
- }
-
-
- typedef struct dictionaryInfo
- {
- int langCode;
- int dialectCode;
- int menuItemNumber;
- } dictionaryInfo;
-
- static void AddDictionaryMenuItem( MenuHandle languagePopup, dictionaryInfo *dictInfoP )
- {
- // get string for lang code and dialectcode
- int stringIndex = 4;
- switch ( dictInfoP->langCode )
- {
- case L_ENGLISH:
- switch ( dictInfoP->dialectCode )
- {
- case D_US_ENGLISH: stringIndex = 5; break;
- case D_UK_ENGLISH: stringIndex = 6; break;
- case D_AUS_ENGLISH: stringIndex = 7; break;
- default: stringIndex = 8; break;
- }
- break;
-
- case L_CATALAN: stringIndex = 9; break;
- case L_HUNGARIAN: stringIndex = 10; break;
-
- case L_GERMAN:
- switch ( dictInfoP->dialectCode )
- {
- default: stringIndex = 11; break;
- case D_SCHARFES: stringIndex = 12; break;
- case D_DOPPEL: stringIndex = 13; break;
- }
- break;
-
- case L_SWEDISH: stringIndex = 14; break;
- case L_SPANISH: stringIndex = 15; break;
- case L_ITALIAN: stringIndex = 16; break;
- case L_DANISH: stringIndex = 17; break;
- case L_DUTCH: stringIndex = 18; break;
-
- case L_PORTUGUESE:
- switch ( dictInfoP->dialectCode )
- {
- default:
- case D_EUROPEAN: stringIndex = 20; break;
- case D_BRAZILIAN: stringIndex = 21; break;
- }
- break;
-
- case L_NORWEGIAN:
- switch ( dictInfoP->dialectCode )
- {
- default:
- case D_BOKMAL: stringIndex = 22; break;
- case D_NYNORSK: stringIndex = 23; break;
- }
- break;
-
- case L_FINNISH: stringIndex = 24; break;
- case L_GREEK: stringIndex = 25; break;
- case L_AFRIKAANS: stringIndex = 26; break;
- case L_POLISH: stringIndex = 27; break;
- case L_CZECH: stringIndex = 28; break;
- case L_FRENCH: stringIndex = 29; break;
- case L_RUSSIAN: stringIndex = 30; break;
- }
-
- Str255 str;
- ::GetIndString( str, SpellCheckerResource, stringIndex );
- if ( str[ 0 ] == 0 )
- dictInfoP->menuItemNumber = 0;
- else
- {
- UMenuUtils::AppendMenuItem( languagePopup, str, true );
- dictInfoP->menuItemNumber = ::CountMItems( languagePopup );
- }
- }
-
-
- static int FindDefaultMenuItem( int langcode, int dialectcode, dictionaryInfo *dictInfoP, int maxIndex )
- {
- int i;
- for (i = 0; i < maxIndex; i++ )
- {
- if ( langcode == dictInfoP[ i ].langCode && dialectcode == dictInfoP[ i ].dialectCode )
- return dictInfoP[ i ].menuItemNumber;
- }
-
- return 1;
- }
-
- static int FindDictionaryInfoIndexForMenu( LGAPopup *languagePopup, dictionaryInfo *dictInfoP, int maxIndex )
- {
- int menuSelection = languagePopup->GetValue();
- if ( menuSelection == 0 )
- return 0;
-
- int i;
- for (i = 0; i < maxIndex; i++ )
- {
- if ( menuSelection == dictInfoP[ i ].menuItemNumber )
- return i;
- }
-
- return 0;
- }
-
- void CMacSpellChecker::ShowDialog( char *textP )
- {
- Boolean continueChecking = StartProcessing( false );
- if ( continueChecking )
- continueChecking = GetNextMisspelledWord( true );
-
- Str255 s;
- LGAPushButton *btn;
- StPrepareForDialog prepare;
- StBlockingDialogHandler handler( res_ID, NULL );
- LDialogBox* dialog = (LDialogBox *)handler.GetDialog();
-
- CTextTable *listview = (CTextTable *)dialog->FindPaneByID( pane_SuggestionList );
- if ( listview == NULL )
- return;
-
- PenState penState;
- ::GetPenState( &penState );
- listview->AddAttachment( new LColorEraseAttachment( &penState, NULL, NULL, true ) );
-
- listview->FocusDraw();
- listview->AddListener( &handler );
- dialog->FocusDraw();
-
- LGAEditField *editField = (LGAEditField *)dialog->FindPaneByID( pane_NewWord );
- if ( editField == NULL )
- return;
-
- LGAPushButton *changeBtn = (LGAPushButton *)dialog->FindPaneByID( msg_Change );
- if ( changeBtn == NULL )
- return;
-
- LGAPopup *languagePopup = (LGAPopup *)dialog->FindPaneByID( msg_NewLanguage );
- if ( languagePopup == NULL )
- return;
- languagePopup->LoadPopupMenuH();
-
- int curDictionary, CurrLangCode, CurrDialectCode, menuLangCode, menuDialectCode;
- int numDictionaries = GetISpellChecker()->GetNumOfDictionaries();
-
- dictionaryInfo *dictInfoP = (dictionaryInfo *)XP_ALLOC( numDictionaries * sizeof( dictionaryInfo ) );
- if ( dictInfoP == NULL )
- return;
-
- for ( curDictionary = 0; curDictionary < numDictionaries; curDictionary++ )
- {
- if ( GetISpellChecker()->GetDictionaryLanguage( curDictionary, CurrLangCode, CurrDialectCode ) )
- break;
-
- dictInfoP[ curDictionary ].langCode = CurrLangCode;
- dictInfoP[ curDictionary ].dialectCode = CurrDialectCode;
- dictInfoP[ curDictionary ].menuItemNumber = curDictionary + 1;
- AddDictionaryMenuItem( languagePopup->GetMacMenuH(), &dictInfoP[ curDictionary ] );
- }
-
- GetISpellChecker()->GetCurrentLanguage( CurrLangCode, CurrDialectCode );
-
- // the following line resets the menu so its width gets adjusted and max value set
- languagePopup->SetMacMenuH( languagePopup->GetMacMenuH() );
- languagePopup->SetValue( FindDefaultMenuItem( CurrLangCode, CurrDialectCode, dictInfoP, numDictionaries ) );
-
- if ( continueChecking )
- SetNextMisspelledWord( textP, editField, listview, dialog );
-
- Boolean isEditFieldOriginal, doNextWord = false, doStartOver = false;
- MessageT message;
- do {
- LCommander *target = dialog->GetTarget();
-
- // if we're done checking we won't update buttons anymore
- if ( continueChecking )
- {
- editField->GetDescriptor( s );
- isEditFieldOriginal = ( XP_STRNCMP( (char *)s,
- (char *)mOrigMisspelledWord, mOrigMisspelledWord[0] + 1 ) == 0 );
- p2cstr( s );
- char *indexp = XP_STRCHR( (char *)s, ' ' );
- Boolean containsNoSpaces = indexp == NULL || indexp[0] == 0;
- // set state of buttons (enable/disable); disable when editField is target and matches origword
- btn = (LGAPushButton *)dialog->FindPaneByID( msg_Change_All );
- if ( target == editField && isEditFieldOriginal )
- {
- // string hasn't changed so disable "replace" and "replace all"
- changeBtn->Disable();
- if ( btn )
- btn->Disable();
- }
- else
- {
- changeBtn->Enable();
- if ( btn )
- btn->Enable();
- }
-
- // we shouldn't be able to "learn" something that is already in the dictionary (in sugg. list)
- btn = (LGAPushButton *)dialog->FindPaneByID( msg_Add_Button );
- if ( btn )
- {
- // can't learn if there's a space in the string!
- #ifdef LEARN_BUTTON_WORKS_AS_SPECD
- if ( target == editField && containsNoSpaces )
- #else
- if ( containsNoSpaces )
- #endif
- btn->Enable();
- else
- btn->Disable();
- }
-
- // we shouldn't be able to "check" unless the editfield is the target
- btn = (LGAPushButton *)dialog->FindPaneByID( msg_Check );
- if ( btn )
- {
- // can't check if multiple words (contains a space)
- if ( target == editField && containsNoSpaces )
- btn->Enable();
- else
- btn->Disable();
- }
-
- if ( changeBtn->GetValueMessage() != msg_Change )
- {
- changeBtn->SetValueMessage( msg_Change );
- ::GetIndString( s, SpellCheckerResource, ChangeStringIndex );
- changeBtn->SetDescriptor( s );
- }
-
- btn = (LGAPushButton *)dialog->FindPaneByID( msg_Ignore );
- if ( btn )
- btn->Enable();
- btn = (LGAPushButton *)dialog->FindPaneByID( msg_Ignore_All );
- if ( btn )
- btn->Enable();
- btn = (LGAPushButton *)dialog->FindPaneByID( msg_Stop );
- if ( btn )
- btn->Enable();
-
- editField->Enable();
- // listview->Enable();
- }
- else // done checking
- {
- doStartOver = false;
- dialog->FocusDraw();
-
- if ( changeBtn->GetValueMessage() != msg_Stop )
- {
- changeBtn->SetValueMessage( msg_Stop );
- ::GetIndString( s, SpellCheckerResource, DoneStringIndex );
- changeBtn->SetDescriptor( s );
- }
- changeBtn->Enable();
-
- // disable all of the other buttons
- btn = (LGAPushButton *)dialog->FindPaneByID( msg_Change_All );
- if ( btn )
- btn->Disable();
- btn = (LGAPushButton *)dialog->FindPaneByID( msg_Ignore );
- if ( btn )
- btn->Disable();
- btn = (LGAPushButton *)dialog->FindPaneByID( msg_Ignore_All );
- if ( btn )
- btn->Disable();
- btn = (LGAPushButton *)dialog->FindPaneByID( msg_Add_Button );
- if ( btn )
- btn->Disable();
- btn = (LGAPushButton *)dialog->FindPaneByID( msg_Check );
- if ( btn )
- btn->Disable();
-
- btn = (LGAPushButton *)dialog->FindPaneByID( msg_Stop );
- if ( btn )
- btn->Disable();
-
- editField->Disable(); // don't allow anymore typing
- listview->Disable();
- }
-
- if ( doNextWord )
- {
- doNextWord = false;
- dialog->FocusDraw();
-
- ClearReplacementWord( editField, listview );
- if ( continueChecking )
- continueChecking = GetNextMisspelledWord( doStartOver );
- if ( continueChecking )
- SetNextMisspelledWord( NULL, editField, listview, dialog );
- }
-
- message = handler.DoDialog();
- switch ( message )
- {
- case msg_Add_Button:
- editField->GetDescriptor( s );
- p2cstr( s );
- int statusError = GetISpellChecker()->AddWordToPersonalDictionary( (char *)s );
- if ( statusError )
- SysBeep(0);
- else
- ReplaceHilitedText( (char *)s, true );
- doNextWord = true;
- break;
-
- case msg_Ignore:
- case msg_Ignore_All:
- IgnoreHilitedText( message == msg_Ignore_All );
- doNextWord = true;
- break;
-
- case msg_Change:
- case msg_Change_All:
- if ( target && target == editField )
- editField->GetDescriptor( s );
- else if ( target && target == listview )
- {
- STableCell c(0, 1);
- c = listview->GetFirstSelectedCell();
- Uint32 len = sizeof( s );
- listview->GetCellData( c, s, len );
- }
- else
- s[ 0 ] = 0;
-
- if ( s[ 0 ] != 0 )
- {
- p2cstr( s );
- ReplaceHilitedText( (char *)s, message == msg_Change_All );
- }
-
- doNextWord = true;
- break;
-
- case msg_SelectionChanged:
- break;
-
- case msg_Check:
- GetAlternativesForWord( editField, listview, dialog );
- break;
-
- case msg_NewLanguage:
- // get current menu choice; convert to langcode/dialectcode
- int index = FindDictionaryInfoIndexForMenu( languagePopup, dictInfoP, numDictionaries );
- menuLangCode = dictInfoP[ index ].langCode;
- menuDialectCode = dictInfoP[ index ].dialectCode;
- if ( CurrLangCode != menuLangCode || menuDialectCode != CurrDialectCode ) // actually changed
- {
- CurrLangCode = menuLangCode;
- CurrDialectCode = menuDialectCode;
- PREF_SetIntPref( "SpellChecker.DefaultLanguage", menuLangCode );
- PREF_SetIntPref( "SpellChecker.DefaultDialect", menuDialectCode );
-
- if ( GetISpellChecker()->SetCurrentLanguage( menuLangCode, menuDialectCode ) == 0 )
- {
- doNextWord = true; // set flag to get next misspelled word and enable/disable
- doStartOver = true;
- continueChecking = StartProcessing( true ); // continue if any misspelled words
- }
- }
- break;
-
- case msg_EditDictionary:
- CEditDictionary *dictEditor = dynamic_cast<CEditDictionary *>
- (URobustCreateWindow::CreateWindow( CEditDictionary::res_ID, LCommander::GetTopCommander() ));
- if ( dictEditor )
- dictEditor->SetISpellChecker( GetISpellChecker() );
- break;
- }
- } while ( message != msg_Stop );
-
- if ( mEditView )
- // clear the TF_SPELL mask for any words that might still have it
- EDT_IgnoreMisspelledWord( mMWContext, NULL, true );
- }
-
-
- char *CMacSpellChecker::GetTextBuffer()
- {
- char *retVal;
-
- if ( mEditView )
- retVal = EDT_GetPositionalText( mMWContext );
- else if ( mTextView )
- {
- SInt32 theSize = mTextView->GetTextLength();
- if ( theSize == 0 )
- return NULL;
-
- retVal = (char *)XP_ALLOC( theSize + 1 );
- XP_ASSERT( retVal );
- if ( retVal )
- {
- Handle textH = mTextView->GetTextHandle();
- ::BlockMoveData( *textH, retVal, theSize );
- retVal[ theSize ] = 0;
- }
- }
-
- return retVal;
- }
-
-
- void CMacSpellChecker::GetSelection(int32 &selStart, int32 &selEnd)
- {
- if (mEditView)
- {
- char *pSelection = (char *)LO_GetSelectionText( GetMWContext() );
- if ( pSelection != NULL )
- {
- XP_FREE( pSelection );
- EDT_GetSelectionOffsets( GetMWContext(), &selStart, &selEnd );
- }
- }
- else
- mTextView->GetSelection( &selStart, &selEnd );
- }
-
-
- Boolean CMacSpellChecker::StartProcessing( Boolean startOver )
- {
- char *stringToCheck;
- char *misspelledWord = NULL;
-
- stringToCheck = GetTextBuffer();
- Boolean retVal = stringToCheck != NULL;
-
- if ( stringToCheck )
- {
- if ( mEditView )
- EDT_SetRefresh( mMWContext, false );
-
- if ( startOver )
- GetISpellChecker()->SetNewBuf( stringToCheck, true );
- else
- {
- // setting buffer the first time
- // let the spellchecker know the current selection
- int32 selStart = 0, selEnd = 0;
- GetSelection( selStart, selEnd );
- GetISpellChecker()->SetBuf( stringToCheck, selStart, selEnd );
- }
-
- XP_HUGE_FREE( stringToCheck );
-
- if ( mEditView )
- {
- // clear the TF_SPELL mask for any words that might still have it
- EDT_IgnoreMisspelledWord( mMWContext, NULL, true );
-
- // mark misspelled words
- EDT_CharacterData *pData = EDT_NewCharacterData();
- if ( pData )
- {
- pData->mask = TF_SPELL;
- pData->values = TF_SPELL;
-
- unsigned long StartPos = 0, len = 0;
- while ( GetISpellChecker()->GetNextMisspelledWord( StartPos, len ) == 0 )
- EDT_SetCharacterDataAtOffset( GetMWContext(), pData, StartPos, len );
-
- EDT_FreeCharacterData( pData );
- }
-
- // set cursor position at the beginning so that
- // EDT_SelectNextMisspelledWord will start at beginning
- EDT_BeginOfDocument( mMWContext, false );
- EDT_SetRefresh( mMWContext, true );
- }
- }
-
- return retVal;
- }
-
-
- Boolean CMacSpellChecker::GetNextMisspelledWord( Boolean startOver )
- {
- if ( isHTMLeditor() )
- {
- if ( startOver )
- return EDT_SelectFirstMisspelledWord( GetMWContext() );
- else
- return EDT_SelectNextMisspelledWord( GetMWContext() );
- }
- else
- {
- unsigned long StartPos = 0, Len = 0;
- if ( GetISpellChecker()->GetNextMisspelledWord( StartPos, Len ) == 0 )
- {
- mTextView->FocusDraw();
- mTextView->SetSelection( StartPos, StartPos + Len );
-
- return true;
- }
- else // no more misspelled words
- return false;
- }
-
- return false;
- }
-
-
- void CMacSpellChecker::SetNextMisspelledWord( char *textP, LEditField *typoField,
- CTextTable *table, LCommander *commander )
- {
- Boolean doFree = false;
-
- if ( textP == NULL )
- {
- if ( isHTMLeditor() )
- {
- textP = (char *)LO_GetSelectionText( GetMWContext() );
- doFree = ( textP != NULL );
- }
- else
- {
- SInt32 selStart = 0;
- SInt32 selEnd = 0;
- SInt32 selLen = 0;
-
- mTextView->FocusDraw();
- mTextView->GetSelection( &selStart, &selEnd );
- selLen = selEnd - selStart;
-
- if ( selLen > 0 )
- {
- textP = (char *)XP_ALLOC( selLen + 1 );
- XP_ASSERT( textP != NULL );
-
- doFree = ( textP != NULL );
-
- if ( textP )
- {
- Handle textH = mTextView->GetTextHandle();
- ::BlockMoveData( (*textH) + selStart, textP, selLen );
- textP[ selLen ] = 0;
- }
- }
- }
- }
-
- // convert c-string to pascal-string
- CStr255 str( textP );
- if ( typoField )
- {
- typoField->FocusDraw();
- typoField->SetDescriptor( str );
- typoField->SelectAll();
- // re-set misspelledword member
- typoField->GetDescriptor( mOrigMisspelledWord );
- }
-
- if ( table )
- {
- table->FocusDraw();
-
- STableCell cell(0, 1);
- int numRows = GetISpellChecker()->GetNumAlternatives( textP );
- if ( numRows > 0 )
- {
- table->Enable();
- table->InsertRows( numRows, 0, nil, 0, Refresh_Yes );
-
- int i, len;
- for ( i = 1; i <= numRows; i++ )
- {
- char liststr[256];
- if ( GetISpellChecker()->GetAlternative( i - 1, liststr, 255 ) == 0 )
- {
- len = XP_STRLEN( (char *)liststr );
- if ( len > 0 )
- {
- cell.row = i;
- CStr255 pascalstring( liststr );
- table->SetCellData( cell, pascalstring, len + 1 );
- }
- }
- }
-
- cell.row = 1;
- table->SelectCell( cell );
- if ( commander )
- commander->SwitchTarget( table );
- }
- else
- {
- table->InsertRows( 1, 0, nil, 0, Refresh_Yes );
-
- Str255 noneFoundString;
- noneFoundString[0] = 0;
- ::GetIndString( noneFoundString, SpellCheckerResource, 31 );
- cell.row = 1;
- table->SetCellData( cell, noneFoundString, noneFoundString[0] + 1 );
-
- table->Disable();
-
- if ( commander && typoField )
- commander->SwitchTarget( typoField );
- }
- }
-
- if ( doFree )
- XP_FREE( textP );
- }
-
-
- void CMacSpellChecker::ClearReplacementWord( LEditField *newWord, CTextTable *table )
- {
- if ( newWord )
- newWord->SetDescriptor( CStr255::sEmptyString );
-
- if ( table )
- {
- TableIndexT rows = 0, cols = 0;
- table->GetTableSize( rows, cols );
- if ( rows )
- {
- table->FocusDraw();
- table->RemoveRows( rows, 0, Refresh_Yes );
- }
- }
- }
-
-
- // this function is used only for "Check" button
- void CMacSpellChecker::GetAlternativesForWord( LEditField *newWord, CTextTable *table, LCommander *commander )
- {
- Str255 s;
- if ( newWord )
- newWord->GetDescriptor( s );
- p2cstr( s );
-
- if ( table )
- {
- table->FocusDraw();
-
- // clear previous choices (if any)
- TableIndexT rows = 0, cols = 0;
- table->GetTableSize( rows, cols );
- if ( rows )
- table->RemoveRows( rows, 0, Refresh_Yes );
-
- // add new list of choices (if any)
- STableCell cell(0, 1);
- if ( GetISpellChecker()->CheckWord( (char *)s ) )
- {
- // word spelled correctly; no need to get alternatives
- table->InsertRows( 1, 0, nil, 0, Refresh_Yes );
-
- Str255 spelledRightString;
- spelledRightString[0] = 0;
- ::GetIndString( spelledRightString, SpellCheckerResource, 32 );
- cell.row = 1;
- table->SetCellData( cell, spelledRightString, spelledRightString[0] + 1 );
- table->Disable();
-
- if ( commander && newWord )
- commander->SwitchTarget( newWord );
-
- return;
- }
-
- int numrows = GetISpellChecker()->GetNumAlternatives( (char *)s );
- if ( numrows > 0 )
- {
- table->Enable();
- table->InsertRows( numrows, 0, nil, 0, Refresh_Yes );
-
- char liststr[256];
- int i, len;
- for ( i = 1; i <= numrows; i++ )
- {
- if ( GetISpellChecker()->GetAlternative( i - 1, liststr, sizeof(s) ) == 0 )
- {
- len = XP_STRLEN( liststr );
- if ( len > 0 )
- {
- cell.row = i;
- CStr255 pascalstring( liststr );
- table->SetCellData( cell, pascalstring, len + 1 );
- }
- }
- }
-
- cell.row = 1;
- table->SelectCell( cell );
- if ( commander )
- commander->SwitchTarget( table );
- }
- else
- {
- table->InsertRows( 1, 0, nil, 0, Refresh_Yes );
-
- Str255 noneFoundString;
- noneFoundString[0] = 0;
- ::GetIndString( noneFoundString, SpellCheckerResource, 31 );
- cell.row = 1;
- table->SetCellData( cell, noneFoundString, noneFoundString[0] + 1 );
- table->Disable();
-
- if ( commander && newWord )
- commander->SwitchTarget( newWord );
- }
- }
- }
-
-
- #pragma mark -
-
- // returns success (true) or failure (false)
- static Boolean LocateDictionaries( FSSpec *mainDictionary, FSSpec *personalDictionary )
- {
- FSSpec appFolder, userPrefsFolder, goodFS;
- Str255 str;
- OSErr err;
-
- // assume main dictionary and netscape dictionary are next to each other
- // get that netscape dictionary FSSpec
- appFolder = CPrefs::GetFilePrototype( CPrefs::RequiredGutsFolder ); // CPrefs::NetscapeFolder
- // get netscape dictionary name
- ::GetIndString( str, SpellCheckerResource, NSDictionaryNameIndex );
- if ( str[ 0 ] == 0 )
- return false;
- if ( str[ 0 ] > MAX_MAC_FILENAME )
- str[ 0 ] = MAX_MAC_FILENAME;
-
- strncpy( (char *)&appFolder.name, (char *)str, str[0] + 1 );
- err = FSMakeFSSpec( appFolder.vRefNum, appFolder.parID, appFolder.name, &goodFS );
- if ( err == noErr )
- memcpy(mainDictionary, &goodFS, sizeof(FSSpec));
- else
- return false;
-
- // check for custom dictionary (may or may not be present)
- // assume in User Profile folder
- Boolean isValidPath = false;
- char *prefMacPath = NULL;
- PREF_CopyCharPref("SpellChecker.PersonalDictionary", &prefMacPath);
- if ( prefMacPath && *prefMacPath )
- {
- err = CFileMgr::FSSpecFromPathname( prefMacPath, &goodFS );
- if ( err == noErr )
- isValidPath = true;
- }
-
- XP_FREEIF( prefMacPath );
-
- if ( ! isValidPath )
- {
- userPrefsFolder = CPrefs::GetFilePrototype( CPrefs::MainFolder );
- // get user dictionary name
- ::GetIndString( str, SpellCheckerResource, UserDictionaryNameIndex );
- if ( str[ 0 ] == 0 )
- return false;
- if ( str[ 0 ] > MAX_MAC_FILENAME )
- str[ 0 ] = MAX_MAC_FILENAME;
-
- strncpy( (char *)&userPrefsFolder.name, (char *)str, str[0] + 1 );
- err = FSMakeFSSpec( userPrefsFolder.vRefNum, userPrefsFolder.parID, userPrefsFolder.name, &goodFS );
- }
-
- memcpy(personalDictionary, &goodFS, sizeof(FSSpec));
- if ( err == fnfErr )
- return true;
- if ( err != noErr )
- return false;
-
- return true;
- }
-
- #ifndef USE_DYNAMIC_SC_LIB
- /* The direct interface to PR_FindSymbol("SC_Create") and PR_FindSymbol("SC_Destroy"):
- These prototypes can't be found in any header file; they're defined in an unreleased source file.
- It's not _too_ unsafe to define them separately here, because the interface understood
- for these functions is the one which uses PR_FindSymbol, which naturally allows
- no prototypes anyway.
- */
- extern "C" ISpellChecker * SCAPI SC_Create();
- extern "C" void SCAPI SC_Destroy(ISpellChecker *pSpellChecker);
- #endif
-
- void do_spellcheck( MWContext *mwcontext, CEditView *editView, CSimpleTextView *textView )
- {
- if ( editView == NULL && textView == NULL )
- return;
-
- // editor requires a context
- if ( mwcontext == NULL && editView != NULL)
- return;
-
- // locate dictionaries
- FSSpec mainDictionary, personalDictionary;
- try {
- if ( ! LocateDictionaries( &mainDictionary, &personalDictionary ) )
- {
- // display message: unable to locate dictionary!
- ErrorManager::PlainAlert( NO_DICTIONARY_FOUND );
- return;
- }
- }
- catch(...)
- {
- // display message: unable to locate dictionary!
- ErrorManager::PlainAlert( NO_DICTIONARY_FOUND );
- return;
- }
-
- #ifdef USE_DYNAMIC_SC_LIB
- const char *libPath = PR_GetLibraryPath();
- PR_SetLibraryPath( "/usr/local/netscape/" );
-
- // load library
- char *libname = "NSSpellChecker"; // internal string within SHLB
- PRLibrary *spellCheckerLib = PR_LoadLibrary( libname );
-
- // set path back to original path (don't have ourselves in list)
- PR_SetLibraryPath( libPath );
-
- if ( spellCheckerLib == NULL )
- {
- // failed!
- ErrorManager::PlainAlert( NO_SPELL_SHLB_FOUND );
- return;
- }
- #else
- PRLibrary *spellCheckerLib = NULL;
- #endif
-
- ISpellChecker *pSpellChecker = NULL;
- CMacSpellChecker *macSpellChecker = NULL;
-
- try {
- #ifdef USE_DYNAMIC_SC_LIB
- sc_create_func sc_createProc;
- #ifndef NSPR20
- sc_createProc = (sc_create_func)PR_FindSymbol( "SC_Create", spellCheckerLib );
- #else
- sc_createProc = (sc_create_func)PR_FindSymbol( spellCheckerLib, "SC_Create" );
- #endif
- if ( sc_createProc == NULL )
- {
- ErrorManager::PlainAlert( NO_SPELL_SHLB_FOUND );
- exit_spellchecker( spellCheckerLib, pSpellChecker, macSpellChecker );
- return;
- }
-
- pSpellChecker = sc_createProc();
- #else
- pSpellChecker = SC_Create();
- #endif
- if ( pSpellChecker )
- {
- int err;
-
- macSpellChecker = new CMacSpellChecker( mwcontext, editView, textView );
-
- int32 Language = 0;
- int32 Dialect = 0;
- PREF_GetIntPref( "SpellChecker.DefaultLanguage", &Language );
- PREF_GetIntPref( "SpellChecker.DefaultDialect", &Dialect );
-
- err = pSpellChecker->Initialize( Language, Dialect,
- (char *)&mainDictionary,
- (char *)&personalDictionary );
- if ( err == noErr )
- {
- macSpellChecker->SetISpellChecker( pSpellChecker );
- macSpellChecker->ShowDialog( NULL );
- }
- }
- }
- catch(...)
- {
- exit_spellchecker( spellCheckerLib, pSpellChecker, macSpellChecker );
- throw;
- }
-
- exit_spellchecker( spellCheckerLib, pSpellChecker, macSpellChecker );
- }
-
-
- static void exit_spellchecker( PRLibrary *lib, ISpellChecker *pSpellChecker, CMacSpellChecker *macSpellChecker )
- {
- if ( pSpellChecker )
- {
- #ifdef USE_DYNAMIC_SC_LIB
- sc_destroy_func sc_destroyProc;
- #ifndef NSPR20
- sc_destroyProc = (sc_destroy_func)PR_FindSymbol( "SC_Destroy", lib );
- #else
- sc_destroyProc = (sc_destroy_func)PR_FindSymbol( lib, "SC_Destroy" );
- #endif
- if ( sc_destroyProc != NULL )
- sc_destroyProc( pSpellChecker );
- #else
- SC_Destroy( pSpellChecker );
- #endif
- }
-
- if ( macSpellChecker )
- delete macSpellChecker;
- macSpellChecker = NULL;
-
- // unload library
- if ( lib )
- int err = PR_UnloadLibrary( lib );
- }
-