/* AbiWord * Copyright (C) 1998,1999 AbiSource, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #include #include #include "ut_string.h" #include "ut_assert.h" #include "ut_debugmsg.h" #include "xap_App.h" #include "xap_QNXApp.h" #include "xap_QNXFrameImpl.h" #include "xap_Frame.h" #include "ap_Strings.h" #include "ap_Dialog_Id.h" #include "ap_Dialog_Spell.h" #include "ap_QNXDialog_Spell.h" #include "ut_qnxHelper.h" XAP_Dialog * AP_QNXDialog_Spell::static_constructor(XAP_DialogFactory * pFactory, XAP_Dialog_Id id) { AP_QNXDialog_Spell * p = new AP_QNXDialog_Spell(pFactory,id); return p; } AP_QNXDialog_Spell::AP_QNXDialog_Spell(XAP_DialogFactory * pDlgFactory, XAP_Dialog_Id id) : AP_Dialog_Spell(pDlgFactory,id) { } AP_QNXDialog_Spell::~AP_QNXDialog_Spell(void) { } /************************************************************/ void AP_QNXDialog_Spell::runModal(XAP_Frame * pFrame) { // class the base class method to initialize some basic xp stuff AP_Dialog_Spell::runModal(pFrame); m_bCancelled = false; bool bRes = nextMisspelledWord(); // To center the dialog, we need the frame of its parent. XAP_QNXFrameImpl * pQNXFrameImpl = (XAP_QNXFrameImpl*)pFrame->getFrameImpl(); PtWidget_t *parentWindow = pQNXFrameImpl->getTopLevelWindow(); UT_ASSERT(parentWindow); PtSetParentWidget(parentWindow); if (bRes) { // we need to prepare the dialog PtWidget_t * mainWindow = _constructWindow(); UT_ASSERT(mainWindow); // Populate the window's data items _populateWindowData(); UT_QNXCenterWindow(parentWindow, mainWindow); UT_QNXBlockWidget(parentWindow, 1); PtRealizeWidget(mainWindow); // now loop while there are still misspelled words while (bRes) { // show word in main window makeWordVisible(); // update dialog with new misspelled word info/suggestions _showMisspelledWord(); int count; count = PtModalStart(); done = 0; while(!done) { PtProcessEvent(); } PtModalEnd(MODAL_END_ARG(count)); _purgeSuggestions(); if (m_bCancelled) { break; } // get the next unknown word bRes = nextMisspelledWord(); } _storeWindowData(); UT_QNXBlockWidget(parentWindow, 0); PtDestroyWidget(mainWindow); } } /**********************************************************/ static int s_change_clicked(PtWidget_t *widget, void *data, PtCallbackInfo_t *info) { AP_QNXDialog_Spell *dlg = (AP_QNXDialog_Spell *)data; UT_ASSERT(widget && dlg); dlg->event_Change(); return Pt_CONTINUE; } static int s_change_all_clicked(PtWidget_t *widget, void *data, PtCallbackInfo_t *info) { AP_QNXDialog_Spell *dlg = (AP_QNXDialog_Spell *)data; UT_ASSERT(widget && dlg); dlg->event_ChangeAll(); return Pt_CONTINUE; } static int s_ignore_clicked(PtWidget_t *widget, void *data, PtCallbackInfo_t *info) { AP_QNXDialog_Spell *dlg = (AP_QNXDialog_Spell *)data; UT_ASSERT(widget && dlg); dlg->event_Ignore(); return Pt_CONTINUE; } static int s_ignore_all_clicked(PtWidget_t *widget, void *data, PtCallbackInfo_t *info) { AP_QNXDialog_Spell *dlg = (AP_QNXDialog_Spell *)data; UT_ASSERT(widget && dlg); dlg->event_IgnoreAll(); return Pt_CONTINUE; } static int s_add_to_dict_clicked(PtWidget_t *widget, void *data, PtCallbackInfo_t *info) { AP_QNXDialog_Spell *dlg = (AP_QNXDialog_Spell *)data; UT_ASSERT(widget && dlg); dlg->event_AddToDict(); return Pt_CONTINUE; } static int s_cancel_clicked(PtWidget_t *widget, void *data, PtCallbackInfo_t *info) { AP_QNXDialog_Spell *dlg = (AP_QNXDialog_Spell *)data; UT_ASSERT(widget && dlg); dlg->event_Cancel(); return Pt_CONTINUE; } static int s_suggestion_selected(PtWidget_t *widget, void *data, PtCallbackInfo_t *info) { AP_QNXDialog_Spell *dlg = (AP_QNXDialog_Spell *)data; UT_ASSERT(widget && dlg); PtListCallback_t *list = (PtListCallback_t *)info->cbdata; dlg->event_SuggestionSelected(list->item_pos, list->item); return Pt_CONTINUE; } static int s_replacement_changed(PtWidget_t *widget, void *data, PtCallbackInfo_t *info) { AP_QNXDialog_Spell *dlg = (AP_QNXDialog_Spell *)data; UT_ASSERT(widget && dlg); dlg->event_ReplacementChanged(); return Pt_CONTINUE; } static int s_delete_clicked(PtWidget_t *widget, void *data, PtCallbackInfo_t *info) { AP_QNXDialog_Spell *dlg = (AP_QNXDialog_Spell *)data; UT_ASSERT(dlg); dlg->event_Cancel(); return Pt_CONTINUE; } /********************************************************************/ PtWidget_t * AP_QNXDialog_Spell::_constructWindow(void) { PtWidget_t *windowSpell; PtWidget_t *label1; PtWidget_t *textWord; PtWidget_t *label2; PtWidget_t *entryChange; PtWidget_t *clistSuggestions; PtWidget_t *buttonChange; PtWidget_t *buttonChangeAll; PtWidget_t *buttonIgnore; PtWidget_t *buttonIgnoreAll; PtWidget_t *buttonAddToDict; PtWidget_t *buttonCancel; const XAP_StringSet * pSS = m_pApp->getStringSet(); XML_Char * unixstr = NULL; // used for conversions windowSpell = abiCreatePhabDialog("ap_QNXDialog_Spell",pSS,AP_STRING_ID_DLG_Spell_SpellTitle); SetupContextHelp(windowSpell,this); PtAddHotkeyHandler(windowSpell,Pk_F1,0,Pt_HOTKEY_SYM,this,OpenHelp); PtAddCallback(windowSpell, Pt_CB_WINDOW_CLOSING, s_delete_clicked, this); localizeLabel(abiPhabLocateWidget(windowSpell,"lblNotDictionary"), pSS, AP_STRING_ID_DLG_Spell_UnknownWord); textWord = abiPhabLocateWidget(windowSpell,"multiError"); buttonIgnore = abiPhabLocateWidget(windowSpell,"btnIgnore"); localizeLabel(buttonIgnore, pSS, AP_STRING_ID_DLG_Spell_Ignore); PtAddCallback(buttonIgnore, Pt_CB_ACTIVATE, s_ignore_clicked, this); buttonIgnoreAll = abiPhabLocateWidget(windowSpell,"btnIgnoreAll"); localizeLabel(buttonIgnoreAll, pSS, AP_STRING_ID_DLG_Spell_IgnoreAll); PtAddCallback(buttonIgnoreAll, Pt_CB_ACTIVATE, s_ignore_all_clicked, this); buttonAddToDict = abiPhabLocateWidget(windowSpell,"btnAdd"); localizeLabel(buttonAddToDict, pSS, AP_STRING_ID_DLG_Spell_AddToDict); PtAddCallback(buttonAddToDict, Pt_CB_ACTIVATE, s_add_to_dict_clicked, this); localizeLabel(abiPhabLocateWidget(windowSpell,"lblChange"), pSS, AP_STRING_ID_DLG_Spell_ChangeTo); entryChange = abiPhabLocateWidget(windowSpell,"textChange"); PtAddCallback(entryChange, Pt_CB_TEXT_CHANGED, s_replacement_changed, this); clistSuggestions = abiPhabLocateWidget(windowSpell,"listSuggestions"); PtAddCallback(clistSuggestions, Pt_CB_SELECTION, s_suggestion_selected, this); buttonChange = abiPhabLocateWidget(windowSpell,"btnChange"); localizeLabel(buttonChange, pSS, AP_STRING_ID_DLG_Spell_Change); PtAddCallback(buttonChange, Pt_CB_ACTIVATE, s_change_clicked, this); buttonChangeAll = abiPhabLocateWidget(windowSpell,"btnChangeAll"); localizeLabel(buttonChangeAll, pSS, AP_STRING_ID_DLG_Spell_ChangeAll); PtAddCallback(buttonChangeAll, Pt_CB_ACTIVATE, s_change_all_clicked, this); buttonCancel = abiPhabLocateWidget(windowSpell,"btnCancel"); localizeLabel(buttonCancel, pSS, XAP_STRING_ID_DLG_Cancel); PtAddCallback(buttonCancel, Pt_CB_ACTIVATE, s_cancel_clicked, this); // update member variables with the important widgets // that we'll interact with later m_buttonChange = buttonChange; m_buttonChangeAll = buttonChangeAll; m_buttonIgnore = buttonIgnore; m_buttonIgnoreAll = buttonIgnoreAll; m_buttonAddToDict = buttonAddToDict; m_buttonCancel = buttonCancel; m_textWord = textWord; m_entryChange = entryChange; m_clistSuggestions = clistSuggestions; m_windowMain = windowSpell; return windowSpell; } static char *get_text_string(PtWidget_t *w) { char *text; PtGetResource(w, Pt_ARG_TEXT_STRING, &text, 0); return text; } static void set_text_string(PtWidget_t *w, char *str) { PtSetResource(w, Pt_ARG_TEXT_STRING, str, 0); } void AP_QNXDialog_Spell::_showMisspelledWord(void) { PtArg_t args[10]; unsigned int n; n = 0; PtSetArg(&args[n++], Pt_ARG_TEXT_STRING, 0, 0); PtSetResources(m_textWord, n, args); const UT_UCSChar *p; char *str; int len; // insert start of sentence UT_sint32 iLength; PtMultiTextAttributes_t attrs; p = m_pWordIterator->getPreWord(iLength); if (0 < iLength) { str = _convertToMB(p); len = mbstrlen(str, 0, NULL); PtMultiTextAttributes_t attrs; memset(&attrs, 0, sizeof(attrs)); attrs.text_color = Pg_BLACK; PtMultiTextModifyText(m_textWord, /* Widget */ 0, 0, /* start, end positions */ -1, /* insert position (end of buffer) */ str, /* text to insert */ len, /* length of text */ &attrs, /* Attributes (use default) */ Pt_MT_TEXT_COLOR); /* Flags on which attrs to use */ FREEP(str); } // insert misspelled word (in highlight color) p = m_pWordIterator->getCurrentWord(iLength); if (0 < iLength) { str = _convertToMB(p); len = mbstrlen(str, 0, NULL); attrs.text_color = Pg_RED; PtMultiTextModifyText(m_textWord, /* Widget */ 0, 0, /* start, end positions */ -1, /* insert position (end of buffer) */ str, /* text to insert */ len, /* length of text */ &attrs, /* Attributes */ Pt_MT_TEXT_COLOR); /* Flags on which attrs to use */ FREEP(str); } // insert end of sentence p = m_pWordIterator->getPostWord(iLength); if (0 < iLength) { str = _convertToMB(p); len = mbstrlen(str, 0, NULL); attrs.text_color = Pg_BLACK; PtMultiTextModifyText(m_textWord, /* Widget */ 0, 0, /* start, end positions */ -1, /* insert position (end of buffer) */ str, /* text to insert */ len, /* length of text */ &attrs, /* Attributes */ Pt_MT_TEXT_COLOR); /* Flags on which attrs to use */ FREEP(str); } // TODO: set scroll position so misspelled word is centered char *suggest[2] = {NULL, NULL}; PtListDeleteAllItems(m_clistSuggestions); for (unsigned int i = 0; i < m_Suggestions->getItemCount(); i++) { suggest[0] = _convertToMB((UT_UCSChar *)m_Suggestions->getNthItem(i)); PtListAddItems(m_clistSuggestions, (const char **)suggest, 1, 0); if (i==0) { set_text_string(m_entryChange, suggest[0]); } FREEP(suggest[0]); } if (!m_Suggestions->getItemCount()) { const XAP_StringSet * pSS = m_pApp->getStringSet(); UT_UTF8String s; pSS->getValueUTF8(AP_STRING_ID_DLG_Spell_NoSuggestions,s); UT_XML_cloneNoAmpersands(suggest[0], s.utf8_str()); PtListAddItems(m_clistSuggestions, (const char **)&suggest[0], 1, 0); FREEP(suggest[0]); n = 0; PtSetArg(&args[n++], Pt_ARG_FLAGS, Pt_BLOCKED, Pt_BLOCKED); PtSetResources(m_clistSuggestions, n, args); n = 0; PtSetArg(&args[n++], Pt_ARG_TEXT_STRING, NULL, 0); PtSetResources(m_entryChange, n, args); } else { // select first on the list; signal handler should update our entry box PtListSelectPos(m_clistSuggestions, 1); } m_iSelectedRow = -1; } void AP_QNXDialog_Spell::_populateWindowData(void) { // TODO: initialize list of user dictionaries } void AP_QNXDialog_Spell::_storeWindowData(void) { // TODO: anything to store? } /*************************************************************/ void AP_QNXDialog_Spell::event_Change() { UT_UCSChar * replace = NULL; if (m_iSelectedRow != -1) { replace = (UT_UCSChar*) m_Suggestions->getNthItem(m_iSelectedRow); changeWordWith(replace); } else { char *text = get_text_string(m_entryChange); replace = _convertFromMB(text); if (!UT_UCS4_strlen(replace)) { FREEP(replace); return; } changeWordWith(replace); FREEP(replace); } done = 1; } void AP_QNXDialog_Spell::event_ChangeAll() { UT_UCSChar * replace = NULL; if (m_iSelectedRow != -1) { replace = (UT_UCSChar*) m_Suggestions->getNthItem(m_iSelectedRow); addChangeAll(replace); changeWordWith(replace); } else { char *text = get_text_string(m_entryChange); replace = _convertFromMB(text); if (!UT_UCS4_strlen(replace)) { FREEP(replace); return; } addChangeAll(replace); changeWordWith(replace); FREEP(replace); } done = 1; } void AP_QNXDialog_Spell::event_Ignore() { ignoreWord(); done = 1; } void AP_QNXDialog_Spell::event_IgnoreAll() { addIgnoreAll(); ignoreWord(); done = 1; } void AP_QNXDialog_Spell::event_AddToDict() { addToDict(); ignoreWord(); done = 1; } void AP_QNXDialog_Spell::event_Cancel() { if (!done++) { m_bCancelled = true; } } //This is called when the user clicks an item in the list ... void AP_QNXDialog_Spell::event_SuggestionSelected(int index, char *newreplacement) { if (!newreplacement) return; m_iSelectedRow = index - 1; set_text_string(m_entryChange, newreplacement); //Set the suggestion text .... UT_ASSERT(newreplacement); } void AP_QNXDialog_Spell::event_ReplacementChanged() { printf("Replacement changed \n"); char * modtext = get_text_string(m_entryChange); UT_ASSERT(modtext); int index = PtListItemPos(m_clistSuggestions, modtext); if (index != 0) { m_iSelectedRow = index -1; PtListSelectPos(m_clistSuggestions, index); //PtListGotoPos(m_clistSuggestions, index); } else { if (m_iSelectedRow > 0) { PtListUnselectPos(m_clistSuggestions, m_iSelectedRow + 1); } //PtListGotoPos(m_clistSuggestions, 0); m_iSelectedRow = -1; } } // Photon uses multibyte strings for i18n // these functions convert from wide (UCS) to MB and back // TODO: these are probably generally useful functions, // TODO: but I don't know about xp support for them. // make a multibyte encoded version of a string char * AP_QNXDialog_Spell::_convertToMB(const UT_UCS4Char *wword) { UT_UCS4String ucs4(wword); return UT_strdup(ucs4.utf8_str()); } // make a multibyte encoded version of a string char * AP_QNXDialog_Spell::_convertToMB(const UT_UCS4Char *wword, UT_sint32 iLength) { UT_UCS4String ucs4(wword, iLength); return UT_strdup(ucs4.utf8_str()); } // make a wide string from a multibyte string UT_UCSChar * AP_QNXDialog_Spell::_convertFromMB(const char *word) { UT_UCS4Char * str = 0; UT_UCS4String ucs4(word); UT_UCS4_cloneString(&str, ucs4.ucs4_str()); return str; }