[BeOS] Spelling dialog / support


Subject: [BeOS] Spelling dialog / support
From: Christopher Plymire (chrisjp@eudoramail.com)
Date: Tue Jul 25 2000 - 06:30:34 CDT


Finished spelling dialog resource.
Created code neccesary to operate the dialog correctly under BeOS.

spell.rsrc and should be inserted in /abi/src/wp/main/beos -- needs to
be marked as binary.
I've included diffs of the files neccesary to hook up these dialogs.

-Christopher

--- /windisk/abiword/abi/src/wp/ap/beos/ap_BeOSDialog_Spell.cpp Wed Jul 26 13:20:02 2000
+++ ap_BeOSDialog_Spell.cpp Tue Jul 25 11:26:26 2000
@@ -32,6 +32,40 @@
 
 #include "ut_Rehydrate.h"
 
+// We really shouldn't unlock the window lock, but the redraw when we focus on the next
+// misspelled word will deadlock if we don't..
+
+status_t WaitForDelete(sem_id blocker)
+{
+ status_t result;
+ thread_id this_tid = find_thread(NULL);
+ BLooper *pLoop;
+ BWindow *pWin = 0;
+
+ pLoop = BLooper::LooperForThread(this_tid);
+ if (pLoop)
+ pWin = dynamic_cast<BWindow*>(pLoop);
+
+ // block until semaphore is deleted (modal is finished)
+ if (pWin) {
+ do {
+ // update the window periodically
+ pWin->Unlock(); // Who will know?=)
+ snooze(100);
+ pWin->Lock();
+
+ pWin->UpdateIfNeeded();
+ result = acquire_sem_etc(blocker, 1, B_TIMEOUT, 1000);
+ } while (result != B_BAD_SEM_ID);
+ } else {
+ do {
+ // just wait for exit
+ result = acquire_sem(blocker);
+ } while (result != B_BAD_SEM_ID);
+ }
+ return result;
+}
+
 /*****************************************************************/
 
 class SpellWin:public BWindow {
@@ -42,57 +76,380 @@
                 virtual bool QuitRequested(void);
                 
         private:
- int spin;
                 AP_BeOSDialog_Spell *m_DlgSpell;
+
+ void _showMisspelledWord();
+ void _suggestChange();
+ void _toggleChangeButtons(UT_Bool shouldShow);
+ void _change();
+ void _tryAgain();
+ void _changeAll();
+
+ rgb_color normalText, badText;
+ sem_id modalSem;
 };
 
 SpellWin::SpellWin(BMessage *data)
- :BWindow(data) {
- spin = 1;
+ :BWindow(data)
+{
+
 }
 
-void SpellWin::SetDlg(AP_BeOSDialog_Spell *dlg) {
+void SpellWin::SetDlg(AP_BeOSDialog_Spell *dlg)
+{
         m_DlgSpell = dlg;
 
+ // As nice as using InterfaceElements is, the app doesn't properly set up
+ // the textRect for our BTextView..
+ BTextView* sentenceView = (BTextView *)FindView("sentencedisplay");
+ BRect frameRect = sentenceView->Bounds();
+ frameRect.InsetBy(5,5);
+
+ sentenceView->SetTextRect(frameRect);
+
+ normalText.red = normalText.blue = normalText.green = 0;
+ normalText.alpha = 255;
+
+ badText.red = 255;
+ badText.blue = badText.green = 0;
+ badText.alpha = 255;
+
+ UT_Bool bRes = m_DlgSpell->nextMisspelledWord();
+ if(!bRes)
+ return;
+
+ // set initial state
+ m_DlgSpell->makeWordVisible();
+
+ _showMisspelledWord();
+
+ // This semaphore ties up the window until after it deletes..
+ modalSem = create_sem(0,"SpellModalSem");
+
         Show();
- while (spin) { snooze(1); }
- Hide();
 
-#if 0
- UT_Bool bRes = nextMisspelledWord();
- while (bRes) {
- // show word in main window
- makeWordVisible();
+ WaitForDelete(modalSem);
+}
+
+void SpellWin::_suggestChange()
+{
+ BListView* suggestList = (BListView *)FindView("suggestlist");
+ BTextControl* changeText = (BTextControl *)FindView("changetxt");
+
+ m_DlgSpell->m_iSelectedRow = suggestList->CurrentSelection();
+
+ if (!m_DlgSpell->m_Suggestions.count)
+ {
+ // no change to suggest, ignore it
+ if (m_DlgSpell->m_iSelectedRow != -1)
+ suggestList->Select(-1);
+ }
+ else
+ {
+ // copy suggestion to edit field
+ UT_ASSERT((m_DlgSpell->m_iSelectedRow > -1));
+
+ BStringItem* selectedItem = (BStringItem *)suggestList->ItemAt(m_DlgSpell->m_iSelectedRow);
+ changeText->SetText(selectedItem->Text());
+ }
+
+}
+
+void SpellWin::_change(void)
+{
+ UT_UCSChar * replace = NULL;
+ BTextControl* changeText = (BTextControl *)FindView("changetxt");
+
+ if (m_DlgSpell->m_iSelectedRow != -1)
+ {
+ replace = m_DlgSpell->m_Suggestions.word[m_DlgSpell->m_iSelectedRow];
+ m_DlgSpell->changeWordWith(replace);
+ }
+ else
+ {
+ UT_UCS_cloneString_char(&replace, changeText->Text());
+ if (!UT_UCS_strlen(replace))
+ {
+ return;
+ }
+ m_DlgSpell->changeWordWith(replace);
+ }
+
+ _tryAgain();
+}
+
+
+void SpellWin::_tryAgain(void)
+{
+ BListView* suggestList = (BListView *)FindView("suggestlist");
+
+ // clear prior suggestions
+ m_DlgSpell->_purgeSuggestions();
+
+ int32 numItems = suggestList->CountItems();
+
+ // Clear out the dialog
+ for ( int32 i = 0; i < numItems; i++ )
+ {
+ BListItem* pItem = suggestList->RemoveItem((long int)0);
+ delete pItem;
+ }
+
+ // what's next
+ UT_Bool bRes = m_DlgSpell->nextMisspelledWord();
 
- // update dialog with new misspelled word info/suggestions
- //_showMisspelledWord();
+ if (bRes)
+ {
+ // show word in main window
+ m_DlgSpell->makeWordVisible();
 
- // run into the GTK event loop for this window
- //gtk_main();
+ // update dialog with new misspelled word info/suggestions
+ _showMisspelledWord();
+ }
+ else
+ {
+ PostMessage(B_QUIT_REQUESTED);
+ }
+}
 
- //_purgeSuggestions();
+void SpellWin::_changeAll(void)
+{
+ BTextControl* changeText = (BTextControl *)FindView("changetxt");
+ UT_UCSChar * replace = NULL;
+
+ if (m_DlgSpell->m_iSelectedRow != -1)
+ {
+ replace = (UT_UCSChar*) m_DlgSpell->m_Suggestions.word[m_DlgSpell->m_iSelectedRow];
+ m_DlgSpell->addChangeAll(replace);
+ m_DlgSpell->changeWordWith(replace);
+ }
+ else
+ {
+ UT_UCS_cloneString_char(&replace,changeText->Text());
+ if (!UT_UCS_strlen(replace))
+ {
+ return;
+ }
+
+ m_DlgSpell->addChangeAll(replace);
+ m_DlgSpell->changeWordWith(replace);
+ }
+
+ _tryAgain();
+}
 
- if (m_bCancelled) break;
+void SpellWin::_showMisspelledWord(void)
+{
+ UT_UCSChar *p;
+ UT_uint32 len;
+ char * buf;
+ UT_uint32 sum = 0;
+
+ BTextView* sentenceView = (BTextView *)FindView("sentencedisplay");
+ BListView* suggestList = (BListView *)FindView("suggestlist");
+
+ sentenceView->SetText("");
+ sentenceView->MakeEditable(true);
+
+ // Run array is 3 long because begin sentence black, misspelled word red, end sentence black..
+ // Note: We need to delete this when we are done..
+ text_run_array* array = (text_run_array *)malloc(sizeof(text_run_array) + sizeof(text_run) * 3);
+ array->count = 3;
+
+ array->runs[0].offset = 0;
+ array->runs[0].font = be_plain_font;
+ array->runs[0].color = normalText;
+
+ array->runs[1].font = be_bold_font;
+ array->runs[1].color = badText;
+
+ array->runs[2].font = be_plain_font;
+ array->runs[2].color = normalText;
+
+ // insert start of sentence
+
+ p = m_DlgSpell->_getPreWord();
+ len = UT_UCS_strlen(p);
+ if (len)
+ {
+ buf = new char [len + 1];
+ UT_UCS_strcpy_to_char(buf, p);
+ sentenceView->Insert(buf, (long int)len);
+ DELETEP(buf);
+ }
+ FREEP(p);
+ sum += len;
+
+ array->runs[1].offset = sum;
+
+ p = m_DlgSpell->_getCurrentWord();
+ len = UT_UCS_strlen(p);
+ if (len)
+ {
+ buf = new char [len + 1];
+ UT_UCS_strcpy_to_char(buf, p);
+ sentenceView->Insert(sum, buf, (long int)len);
+ DELETEP(buf);
+ }
+ FREEP(p);
+ sum += len;
+
+ array->runs[2].offset = sum;
+
+ p = m_DlgSpell->_getPostWord();
+ len = UT_UCS_strlen(p);
+ if (len)
+ {
+ buf = new char [len + 1];
+ UT_UCS_strcpy_to_char(buf, p);
+ sentenceView->Insert(sum, buf, (long int)len);
+ DELETEP(buf);
+ }
+ FREEP(p);
+
+ sentenceView->SetRunArray(0, (long int)sum + len , array);
+ sentenceView->MakeEditable(false);
+
+ // insert suggestions
+ if (!m_DlgSpell->m_Suggestions.count)
+ {
+ const XAP_StringSet * pSS = m_DlgSpell->m_pApp->getStringSet();
+ BStringItem* emptyItem = new BStringItem(pSS->getValue(AP_STRING_ID_DLG_Spell_NoSuggestions));
+ suggestList->AddItem(emptyItem);
+ m_DlgSpell->m_iSelectedRow = -1;
+ _toggleChangeButtons(UT_FALSE);
+ }
+ else
+ {
+ for (int i = 0; i < m_DlgSpell->m_Suggestions.count; i++)
+ {
+ p = (UT_UCSChar *) m_DlgSpell->m_Suggestions.word[i];
+ len = UT_UCS_strlen(p);
+ if (len)
+ {
+ buf = new char [len + 1];
+ UT_UCS_strcpy_to_char(buf, p);
+ BStringItem* pItem = new BStringItem(buf);
+ suggestList->AddItem(pItem);
+ DELETEP(buf);
+ }
+ }
+
+ m_DlgSpell->m_iSelectedRow = 0;
+ _toggleChangeButtons(UT_TRUE);
+ }
 
- // get the next unknown word
- bRes = nextMisspelledWord();
- }
-#endif
+ suggestList->Select(0);
+ _suggestChange();
 }
 
-void SpellWin::DispatchMessage(BMessage *msg, BHandler *handler) {
- switch(msg->what) {
+void SpellWin::DispatchMessage(BMessage *msg, BHandler *handler)
+{
+ BTextControl* editSuggest;
+ BListView* suggestList;
+ int32 selIndex;
+ BStringItem* pCurSelItem;
+
+ switch(msg->what)
+ {
+ case 'ibut': // ignore button
+ m_DlgSpell->ignoreWord();
+ _tryAgain();
+ break;
+
+ case 'iabu': // ignore all button.
+ m_DlgSpell->addIgnoreAll();
+ m_DlgSpell->ignoreWord();
+ _tryAgain();
+ break;
+
+ case 'abut': // add button
+ m_DlgSpell->addToDict();
+ m_DlgSpell->ignoreWord();
+ _tryAgain();
+ break;
+
+ case 'cbut':
+ _change();
+ break;
+
+ case 'cabu':
+ _changeAll();
+ break;
+
+ case 'selc':
+ // Update the current selection in the add box..
+ suggestList = (BListView *)FindView("suggestlist");
+ editSuggest = (BTextControl *)FindView("changetxt");
+
+ m_DlgSpell->m_iSelectedRow = suggestList->CurrentSelection();
+ selIndex = m_DlgSpell->m_iSelectedRow;
+
+ pCurSelItem = (BStringItem *)suggestList->ItemAt(m_DlgSpell->m_iSelectedRow);
+
+ if(pCurSelItem)
+ editSuggest->TextView()->SetText(pCurSelItem->Text());
+
+ break;
+
+ case 'invs': // Called when the user double-clicks a suggested word in the spell dialog.
+ suggestList = (BListView *)FindView("suggestlist");
+ if( msg->FindInt32("index" , &selIndex) == B_OK)
+ {
+ m_DlgSpell->m_iSelectedRow = selIndex;
+ _change();
+ }
+ break;
+
+ case 'spmo': // Whenever the user edits the text control.
+
+ // Determine if the user clicked an item in the suggest box.
+
+ suggestList = (BListView *)FindView("suggestlist");
+ editSuggest = (BTextControl *)FindView("changetxt");
+
+ for(int i = 0; i < suggestList->CountItems(); i ++)
+ {
+ pCurSelItem = (BStringItem *)suggestList->ItemAt(i);
+
+ if(strcmp(pCurSelItem->Text() , editSuggest->Text()) == 0)
+ {
+ return;;
+ }
+ }
+
+ // The user is editing it so, enable the change button.
+ _toggleChangeButtons(UT_TRUE);
+
+ suggestList->DeselectAll();
+ m_DlgSpell->m_iSelectedRow = -1;
+
+ break;
+
         default:
                 BWindow::DispatchMessage(msg, handler);
         }
+
 }
 
 //Behave like a good citizen
-bool SpellWin::QuitRequested() {
- spin = 0;
+bool SpellWin::QuitRequested()
+{
+ delete_sem(modalSem);
         return(true);
 }
 
+void SpellWin::_toggleChangeButtons(UT_Bool shouldShow)
+{
+ BButton *change, *changeall;
+ change = (BButton *)FindView("change");
+ changeall = (BButton *)FindView("changeall");
+
+ if(change)
+ change->SetEnabled(shouldShow);
+ if(changeall)
+ changeall->SetEnabled(shouldShow);
+}
 
 /*****************************************************************/
 
@@ -125,7 +482,7 @@
                 newwin = new SpellWin(&msg);
                 newwin->SetDlg(this);
                 //Take the information here ...
- newwin->Close();
+ // newwin->Close(); QuitRequested kills this dialog..
         }
 }
 


--- /windisk/abiword/abi/src/wp/ap/beos/ap_BeOSDialog_Spell.h Wed Jul 26 13:20:10 2000
+++ ap_BeOSDialog_Spell.h Mon Jul 24 15:39:39 2000
@@ -28,6 +28,8 @@
 
 class AP_BeOSDialog_Spell: public AP_Dialog_Spell
 {
+ friend class SpellWin;
+
  public:
    AP_BeOSDialog_Spell(XAP_DialogFactory * pDlgFactory, XAP_Dialog_Id id);
    virtual ~AP_BeOSDialog_Spell(void);






This archive was generated by hypermail 2b25 : Tue Jul 25 2000 - 10:33:32 CDT