diff options
author | Eduardo Chappa <chappa@washington.edu> | 2014-03-10 00:17:48 -0600 |
---|---|---|
committer | Eduardo Chappa <chappa@washington.edu> | 2014-03-10 00:17:48 -0600 |
commit | 6a18937898292e97c15289e5ecd5d8f1c2205110 (patch) | |
tree | f1b5c155faa96d81e463d1879eb5f4f6185d4f6e /pico/osdep | |
parent | 228b2570e23919e9900b16037d2e407264f50637 (diff) | |
download | alpine-6a18937898292e97c15289e5ecd5d8f1c2205110.tar.xz |
* Bump version to 2.19.9.
* Fix windows strings to match version.
Diffstat (limited to 'pico/osdep')
-rw-r--r-- | pico/osdep/mswin_spell.c | 1094 |
1 files changed, 547 insertions, 547 deletions
diff --git a/pico/osdep/mswin_spell.c b/pico/osdep/mswin_spell.c index 1379beb6..e921cfcd 100644 --- a/pico/osdep/mswin_spell.c +++ b/pico/osdep/mswin_spell.c @@ -1,547 +1,547 @@ -/*
- * ========================================================================
- * MSWIN_SPELL.C
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * ========================================================================
- */
-
-#include "../headers.h"
-
-#include "mswin_aspell.h"
-#include "mswin_spell.h"
-
-#include <windowsx.h>
-
-typedef struct WORD_INFO
-{
- ASPELLINFO *aspellinfo; // Aspell information
-
- const char *utf8_err_message; // Error message, if any
-
- char *word_utf8; // utf-8
- LPTSTR word_lptstr;
-
- int word_doto; // UCS
- LINE *word_dotp; //
- int word_size; //
-} WORD_INFO;
-
-extern HINSTANCE ghInstance;
-extern HWND ghTTYWnd;
-
-/*
- * Function prototypes
- */
-static int get_next_bad_word(WORD_INFO *word_info);
-static void free_word_info_words(WORD_INFO *word_info);
-static INT_PTR CALLBACK spell_dlg_proc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
-
-/*
- * spell() - check for potentially missspelled words and offer them for
- * correction. Microsoft Windows specific version.
- */
-int
-spell(int f, int n)
-{
- int w_marko_bak;
- LINE *w_markp_bak;
- WORD_INFO word_info;
- ASPELLINFO *aspellinfo;
-
- emlwrite(_("Checking spelling..."), NULL); /* greetings! */
-
- memset(&word_info, 0, sizeof(WORD_INFO));
-
- aspellinfo = speller_init(NULL);
- if(!aspellinfo ||
- (word_info.utf8_err_message = speller_get_error_message(aspellinfo)))
- {
- if(word_info.utf8_err_message)
- emlwrite((char *)word_info.utf8_err_message, NULL); /* sad greetings! */
- else
- emlwrite(_("Spelling: initializing Aspell failed"), NULL);
-
- speller_close(aspellinfo);
- return -1;
- }
-
- // Back up current mark.
- w_marko_bak = curwp->w_marko;
- w_markp_bak = curwp->w_markp;
-
- setimark(0, 1);
- gotobob(0, 1);
-
- word_info.aspellinfo = aspellinfo;
-
- if(get_next_bad_word(&word_info))
- {
- DialogBoxParam(ghInstance, MAKEINTRESOURCE(DLG_SPELL), ghTTYWnd,
- spell_dlg_proc, (LPARAM)&word_info);
- }
-
- // Restore original mark if possible.
- if(curwp->w_markp)
- {
- // Clear any set marks.
- setmark(0, 1);
-
- if(w_markp_bak && llength(w_markp_bak))
- {
- // Make sure we don't set mark off the line.
- if(w_marko_bak >= llength(w_markp_bak))
- w_marko_bak = llength(w_markp_bak) - 1;
-
- curwp->w_marko = w_marko_bak;
- curwp->w_markp = w_markp_bak;
- }
- }
-
- if(word_info.utf8_err_message)
- emlwrite((char *)word_info.utf8_err_message, NULL);
- else
- emlwrite(_("Done checking spelling"), NULL);
-
- speller_close(aspellinfo);
- free_word_info_words(&word_info);
-
- swapimark(0, 1);
- curwp->w_flag |= WFHARD|WFMODE;
-
- update();
- return 1;
-}
-
-/*
- * handle_cb_editchange() - combobox contents have changed so enable/disable
- * the Change and Change All buttons accordingly.
- */
-static void
-handle_cb_editchange(HWND hDlg, HWND hwnd_combo)
-{
- int text_len = ComboBox_GetTextLength(hwnd_combo);
-
- Button_Enable(GetDlgItem(hDlg, ID_BUTTON_CHANGE), !!text_len);
- Button_Enable(GetDlgItem(hDlg, ID_BUTTON_CHANGEALL), !!text_len);
-}
-
-/*
- * spell_dlg_proc_set_word() - Set up the dialog to display spelling
- * information and suggestions for the current word.
- */
-static void
-spell_dlg_proc_set_word(HWND hDlg, WORD_INFO *word_info)
-{
- TCHAR dlg_title[256];
- HWND hwnd_combo = GetDlgItem(hDlg, ID_COMBO_SUGGESTIONS);
-
- // Clear the combobox.
- ComboBox_ResetContent(hwnd_combo);
-
- // Set the dialog box title
- _sntprintf(dlg_title, ARRAYSIZE(dlg_title), TEXT("Not in Dictionary: %s"),
- word_info->word_lptstr);
- dlg_title[ARRAYSIZE(dlg_title) - 1] = 0;
- SetWindowText(hDlg, dlg_title);
-
- // Populate the combobox with suggestions
- if(speller_suggestion_init(word_info->aspellinfo, word_info->word_utf8, -1))
- {
- const char *suggestion_utf8;
-
- while(suggestion_utf8 = speller_suggestion_getnext(word_info->aspellinfo))
- {
- LPTSTR suggestion_lptstr = utf8_to_lptstr((LPSTR)suggestion_utf8);
-
- if(suggestion_lptstr)
- {
- ComboBox_AddString(hwnd_combo, suggestion_lptstr);
- fs_give((void **)&suggestion_lptstr);
- }
- }
-
- // Select the first one.
- ComboBox_SetCurSel(hwnd_combo, 0);
-
- speller_suggestion_close(word_info->aspellinfo);
- }
-
- handle_cb_editchange(hDlg, hwnd_combo);
-}
-
-/*
- * spell_dlg_next_word() - Move to the next misspelled word and display
- * the information for it. If no more bad words, kill the dialog.
- */
-static void
-spell_dlg_next_word(HWND hDlg, WORD_INFO *word_info)
-{
- if(!get_next_bad_word(word_info))
- {
- EndDialog(hDlg, 0);
- return;
- }
-
- spell_dlg_proc_set_word(hDlg, word_info);
-}
-
-/*
- * chword_n() - change the given word_len pointed to by the curwp->w_dot
- * pointers to the word in cb
- */
-static void
-chword_n(int wb_len, UCS *cb)
-{
- ldelete(wb_len, NULL); /* not saved in kill buffer */
-
- while(*cb != '\0')
- linsert(1, *cb++);
-
- curwp->w_flag |= WFEDIT;
-}
-
-/*
- * replace_all() - replace all instances of oldword with newword from
- * the current '.' on. Mark is where curwp will get restored to.
- */
-static void
-replace_all(UCS *oldword, int oldword_len, UCS *newword)
-{
- int wrap;
-
- // Mark should be at "." right now - ie the start of the word we're
- // checking. We're going to use mark below to restore curwp since
- // chword_n can potentially realloc LINES and it knows about markp.
- assert(curwp->w_markp);
- assert(curwp->w_markp == curwp->w_dotp);
- assert(curwp->w_marko == curwp->w_doto);
-
- curwp->w_bufp->b_mode |= MDEXACT; /* case sensitive */
- while(forscan(&wrap, oldword, NULL, 0, 1))
- {
- if(wrap)
- break; /* wrap NOT allowed! */
-
- /*
- * We want to minimize the number of substrings that we report
- * as matching a misspelled word...
- */
- if(lgetc(curwp->w_dotp, 0).c != '>')
- {
- LINE *lp = curwp->w_dotp; /* for convenience */
- int off = curwp->w_doto;
-
- if(off == 0 || !ucs4_isalpha(lgetc(lp, off - 1).c))
- {
- off += oldword_len;
-
- if(off == llength(lp) || !ucs4_isalpha(lgetc(lp, off).c))
- {
- // Replace this word
- chword_n(oldword_len, newword);
- }
- }
- }
-
- forwchar(0, 1); /* move on... */
-
- }
- curwp->w_bufp->b_mode ^= MDEXACT; /* case insensitive */
-
- curwp->w_dotp = curwp->w_markp;
- curwp->w_doto = curwp->w_marko;
-}
-
-/*
- * handle_button_change() - Someone pressed the Change or Change All button.
- * So deal with it.
- */
-static void
-handle_button_change(HWND hDlg, WORD_INFO *word_info, int do_replace_all)
-{
- int str_lptstr_len;
- TCHAR str_lptstr[128];
-
- // Get the length of what they want to change to.
- str_lptstr_len = ComboBox_GetText(GetDlgItem(hDlg, ID_COMBO_SUGGESTIONS),
- str_lptstr, ARRAYSIZE(str_lptstr));
- if(str_lptstr_len)
- {
- UCS *str_ucs4;
- char *str_utf8;
-
- // Notify the speller so it'll suggest this word next time around.
- str_utf8 = lptstr_to_utf8(str_lptstr);
- if(str_utf8)
- {
- speller_replace_word(word_info->aspellinfo,
- word_info->word_utf8, -1, str_utf8, -1);
- fs_give((void **)&str_utf8);
- }
-
- str_ucs4 = lptstr_to_ucs4(str_lptstr);
- if(!str_ucs4)
- {
- // Uh oh - massive error.
- word_info->utf8_err_message = _("Spelling: lptstr_to_ucs4() failed");
- EndDialog(hDlg, -1);
- return;
- }
-
- // Move back to start of this word.
- curwp->w_doto = word_info->word_doto;
- curwp->w_dotp = word_info->word_dotp;
-
- if(do_replace_all)
- {
- int i;
- int word_size;
- UCS word[128];
-
- word_size = word_info->word_size;
- if(word_size >= ARRAYSIZE(word) - 1)
- word_size = ARRAYSIZE(word) - 1;
-
- for(i = 0; i < word_size; i++)
- word[i] = lgetc(curwp->w_dotp, curwp->w_doto + i).c;
-
- word[i] = 0;
-
- replace_all(word, word_size, str_ucs4);
-
- // Skip over the word we just inserted.
- forwchar(FALSE, (int)ucs4_strlen(str_ucs4));
- }
- else
- {
- // Swap it with the new improved version.
- chword_n(word_info->word_size, str_ucs4);
- }
- fs_give((void **)&str_ucs4);
- }
-
- update();
- spell_dlg_next_word(hDlg, word_info);
-}
-
-/*
- * center_dialog() - Center a dialog with respect to its parent.
- */
-static void
-center_dialog(HWND hDlg)
-{
- int dx;
- int dy;
- RECT rcDialog;
- RECT rcParent;
-
- GetWindowRect(GetParent(hDlg), &rcParent);
- GetWindowRect(hDlg, &rcDialog);
-
- dx = ((rcParent.right - rcParent.left) -
- (rcDialog.right - rcDialog.left)) / 2 + rcParent.left - rcDialog.left;
-
- dy = ((rcParent.bottom - rcParent.top) -
- (rcDialog.bottom - rcDialog.top)) / 2 + rcParent.top - rcDialog.top;
-
- OffsetRect(&rcDialog, dx, dy);
-
- SetWindowPos(hDlg, NULL, rcDialog.left, rcDialog.top, 0, 0,
- SWP_NOSIZE | SWP_NOZORDER);
-}
-
-/*
- * spell_dlg_on_command() - Handle the WM_COMMAND stuff for the spell dialog.
- */
-static void
-spell_dlg_on_command(HWND hDlg, int id, HWND hwndCtl, UINT codeNotify)
-{
- WORD_INFO *word_info =
- (WORD_INFO *)(LONG_PTR)GetWindowLongPtr(hDlg, GWLP_USERDATA);
-
- switch(id)
- {
- case ID_COMBO_SUGGESTIONS:
- if(codeNotify == CBN_EDITCHANGE)
- handle_cb_editchange(hDlg, hwndCtl);
- break;
-
- case ID_BUTTON_CHANGE:
- handle_button_change(hDlg, word_info, 0);
- break;
-
- case ID_BUTTON_CHANGEALL:
- handle_button_change(hDlg, word_info, 1);
- break;
-
- case ID_BUTTON_IGNOREONCE:
- spell_dlg_next_word(hDlg, word_info);
- break;
-
- case ID_BUTTON_IGNOREALL:
- speller_ignore_all(word_info->aspellinfo, word_info->word_utf8, -1);
- spell_dlg_next_word(hDlg, word_info);
- break;
-
- case ID_BUTTON_ADD_TO_DICT:
- speller_add_to_dictionary(word_info->aspellinfo, word_info->word_utf8, -1);
- spell_dlg_next_word(hDlg, word_info);
- break;
-
- case ID_BUTTON_CANCEL:
- EndDialog(hDlg, 0);
- break;
- }
-}
-
-/*
- * spell_dlg_proc() - Main spell dialog proc.
- */
-static INT_PTR CALLBACK
-spell_dlg_proc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
-{
- WORD_INFO *word_info;
-
- switch(message)
- {
- case WM_INITDIALOG:
- center_dialog(hDlg);
-
- // Limit how much junk they can type in.
- ComboBox_LimitText(GetDlgItem(hDlg, ID_COMBO_SUGGESTIONS), 128);
-
- word_info = (WORD_INFO *)lParam;
- SetWindowLongPtr(hDlg, GWLP_USERDATA, (LONG_PTR)word_info);
-
- spell_dlg_proc_set_word(hDlg, word_info);
- return TRUE;
-
- case WM_COMMAND:
- HANDLE_WM_COMMAND(hDlg, wParam, lParam, spell_dlg_on_command);
- return TRUE;
- }
-
- return FALSE;
-}
-
-/*
- * get_next_word() - Get the next word from dot. And skip words in
- * quoted lines.
- */
-static int
-get_next_word(WORD_INFO *word_info)
-{
- // Skip quoted lines
- while(lgetc(curwp->w_dotp, 0).c == '>')
- {
- if(curwp->w_dotp == curbp->b_linep)
- return 0;
-
- curwp->w_dotp = lforw(curwp->w_dotp);
- curwp->w_doto = 0;
- curwp->w_flag |= WFMOVE;
- }
-
- // Move to a word.
- while(inword() == FALSE)
- {
- if(forwchar(FALSE, 1) == FALSE)
- {
- // There is no next word.
- return 0;
- }
- }
-
- // If mark is currently set, clear it.
- if(curwp->w_markp)
- setmark(0, 1);
-
- // Set mark to beginning of this word.
- curwp->w_markp = curwp->w_dotp;
- curwp->w_marko = curwp->w_doto;
-
- // Get word length
- word_info->word_doto = curwp->w_doto;
- word_info->word_dotp = curwp->w_dotp;
- word_info->word_size = 0;
-
- while((inword() != FALSE) && (word_info->word_dotp == curwp->w_dotp))
- {
- word_info->word_size++;
-
- if(forwchar(FALSE, 1) == FALSE)
- break;
- }
-
- word_info->word_utf8 = ucs4_to_utf8_cpystr_n(
- (UCS *)&word_info->word_dotp->l_text[word_info->word_doto],
- word_info->word_size);
- return 1;
-}
-
-/*
- * get_next_word() - free the word_info members word_utf8 and word_lptstr.
- */
-static void
-free_word_info_words(WORD_INFO *word_info)
-{
- if(word_info->word_utf8)
- {
- fs_give((void **)&word_info->word_utf8);
- word_info->word_utf8 = NULL;
- }
-
- if(word_info->word_lptstr)
- {
- fs_give((void **)&word_info->word_lptstr);
- word_info->word_lptstr = NULL;
- }
-}
-
-/*
- * get_next_bad_word() - Search from '.' for the next word we think is
- * rotten. Mark it and highlight it.
- */
-static int
-get_next_bad_word(WORD_INFO *word_info)
-{
- free_word_info_words(word_info);
-
- while(get_next_word(word_info))
- {
- int ret;
-
- /* pass over words that contain @ */
- if(strchr(word_info->word_utf8, '@'))
- ret = 1;
- else
- ret = speller_check_word(word_info->aspellinfo, word_info->word_utf8, -1);
-
- if(ret == -1)
- {
- word_info->utf8_err_message =
- speller_get_error_message(word_info->aspellinfo);
- if(!word_info->utf8_err_message)
- word_info->utf8_err_message = _("Spelling: speller_check_word() failed");
- return 0;
- }
- else if(ret == 0)
- {
- // Highlight word.
- update();
-
- word_info->word_lptstr = utf8_to_lptstr(word_info->word_utf8);
- return 1;
- }
-
- free_word_info_words(word_info);
- }
-
- return 0;
-}
+/* + * ======================================================================== + * MSWIN_SPELL.C + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * ======================================================================== + */ + +#include "../headers.h" + +#include "mswin_aspell.h" +#include "mswin_spell.h" + +#include <windowsx.h> + +typedef struct WORD_INFO +{ + ASPELLINFO *aspellinfo; // Aspell information + + const char *utf8_err_message; // Error message, if any + + char *word_utf8; // utf-8 + LPTSTR word_lptstr; + + int word_doto; // UCS + LINE *word_dotp; // + int word_size; // +} WORD_INFO; + +extern HINSTANCE ghInstance; +extern HWND ghTTYWnd; + +/* + * Function prototypes + */ +static int get_next_bad_word(WORD_INFO *word_info); +static void free_word_info_words(WORD_INFO *word_info); +static INT_PTR CALLBACK spell_dlg_proc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); + +/* + * spell() - check for potentially missspelled words and offer them for + * correction. Microsoft Windows specific version. + */ +int +spell(int f, int n) +{ + int w_marko_bak; + LINE *w_markp_bak; + WORD_INFO word_info; + ASPELLINFO *aspellinfo; + + emlwrite(_("Checking spelling..."), NULL); /* greetings! */ + + memset(&word_info, 0, sizeof(WORD_INFO)); + + aspellinfo = speller_init(NULL); + if(!aspellinfo || + (word_info.utf8_err_message = speller_get_error_message(aspellinfo))) + { + if(word_info.utf8_err_message) + emlwrite((char *)word_info.utf8_err_message, NULL); /* sad greetings! */ + else + emlwrite(_("Spelling: initializing Aspell failed"), NULL); + + speller_close(aspellinfo); + return -1; + } + + // Back up current mark. + w_marko_bak = curwp->w_marko; + w_markp_bak = curwp->w_markp; + + setimark(0, 1); + gotobob(0, 1); + + word_info.aspellinfo = aspellinfo; + + if(get_next_bad_word(&word_info)) + { + DialogBoxParam(ghInstance, MAKEINTRESOURCE(DLG_SPELL), ghTTYWnd, + spell_dlg_proc, (LPARAM)&word_info); + } + + // Restore original mark if possible. + if(curwp->w_markp) + { + // Clear any set marks. + setmark(0, 1); + + if(w_markp_bak && llength(w_markp_bak)) + { + // Make sure we don't set mark off the line. + if(w_marko_bak >= llength(w_markp_bak)) + w_marko_bak = llength(w_markp_bak) - 1; + + curwp->w_marko = w_marko_bak; + curwp->w_markp = w_markp_bak; + } + } + + if(word_info.utf8_err_message) + emlwrite((char *)word_info.utf8_err_message, NULL); + else + emlwrite(_("Done checking spelling"), NULL); + + speller_close(aspellinfo); + free_word_info_words(&word_info); + + swapimark(0, 1); + curwp->w_flag |= WFHARD|WFMODE; + + update(); + return 1; +} + +/* + * handle_cb_editchange() - combobox contents have changed so enable/disable + * the Change and Change All buttons accordingly. + */ +static void +handle_cb_editchange(HWND hDlg, HWND hwnd_combo) +{ + int text_len = ComboBox_GetTextLength(hwnd_combo); + + Button_Enable(GetDlgItem(hDlg, ID_BUTTON_CHANGE), !!text_len); + Button_Enable(GetDlgItem(hDlg, ID_BUTTON_CHANGEALL), !!text_len); +} + +/* + * spell_dlg_proc_set_word() - Set up the dialog to display spelling + * information and suggestions for the current word. + */ +static void +spell_dlg_proc_set_word(HWND hDlg, WORD_INFO *word_info) +{ + TCHAR dlg_title[256]; + HWND hwnd_combo = GetDlgItem(hDlg, ID_COMBO_SUGGESTIONS); + + // Clear the combobox. + ComboBox_ResetContent(hwnd_combo); + + // Set the dialog box title + _sntprintf(dlg_title, ARRAYSIZE(dlg_title), TEXT("Not in Dictionary: %s"), + word_info->word_lptstr); + dlg_title[ARRAYSIZE(dlg_title) - 1] = 0; + SetWindowText(hDlg, dlg_title); + + // Populate the combobox with suggestions + if(speller_suggestion_init(word_info->aspellinfo, word_info->word_utf8, -1)) + { + const char *suggestion_utf8; + + while(suggestion_utf8 = speller_suggestion_getnext(word_info->aspellinfo)) + { + LPTSTR suggestion_lptstr = utf8_to_lptstr((LPSTR)suggestion_utf8); + + if(suggestion_lptstr) + { + ComboBox_AddString(hwnd_combo, suggestion_lptstr); + fs_give((void **)&suggestion_lptstr); + } + } + + // Select the first one. + ComboBox_SetCurSel(hwnd_combo, 0); + + speller_suggestion_close(word_info->aspellinfo); + } + + handle_cb_editchange(hDlg, hwnd_combo); +} + +/* + * spell_dlg_next_word() - Move to the next misspelled word and display + * the information for it. If no more bad words, kill the dialog. + */ +static void +spell_dlg_next_word(HWND hDlg, WORD_INFO *word_info) +{ + if(!get_next_bad_word(word_info)) + { + EndDialog(hDlg, 0); + return; + } + + spell_dlg_proc_set_word(hDlg, word_info); +} + +/* + * chword_n() - change the given word_len pointed to by the curwp->w_dot + * pointers to the word in cb + */ +static void +chword_n(int wb_len, UCS *cb) +{ + ldelete(wb_len, NULL); /* not saved in kill buffer */ + + while(*cb != '\0') + linsert(1, *cb++); + + curwp->w_flag |= WFEDIT; +} + +/* + * replace_all() - replace all instances of oldword with newword from + * the current '.' on. Mark is where curwp will get restored to. + */ +static void +replace_all(UCS *oldword, int oldword_len, UCS *newword) +{ + int wrap; + + // Mark should be at "." right now - ie the start of the word we're + // checking. We're going to use mark below to restore curwp since + // chword_n can potentially realloc LINES and it knows about markp. + assert(curwp->w_markp); + assert(curwp->w_markp == curwp->w_dotp); + assert(curwp->w_marko == curwp->w_doto); + + curwp->w_bufp->b_mode |= MDEXACT; /* case sensitive */ + while(forscan(&wrap, oldword, 0, NULL, 0, 1)) + { + if(wrap) + break; /* wrap NOT allowed! */ + + /* + * We want to minimize the number of substrings that we report + * as matching a misspelled word... + */ + if(lgetc(curwp->w_dotp, 0).c != '>') + { + LINE *lp = curwp->w_dotp; /* for convenience */ + int off = curwp->w_doto; + + if(off == 0 || !ucs4_isalpha(lgetc(lp, off - 1).c)) + { + off += oldword_len; + + if(off == llength(lp) || !ucs4_isalpha(lgetc(lp, off).c)) + { + // Replace this word + chword_n(oldword_len, newword); + } + } + } + + forwchar(0, 1); /* move on... */ + + } + curwp->w_bufp->b_mode ^= MDEXACT; /* case insensitive */ + + curwp->w_dotp = curwp->w_markp; + curwp->w_doto = curwp->w_marko; +} + +/* + * handle_button_change() - Someone pressed the Change or Change All button. + * So deal with it. + */ +static void +handle_button_change(HWND hDlg, WORD_INFO *word_info, int do_replace_all) +{ + int str_lptstr_len; + TCHAR str_lptstr[128]; + + // Get the length of what they want to change to. + str_lptstr_len = ComboBox_GetText(GetDlgItem(hDlg, ID_COMBO_SUGGESTIONS), + str_lptstr, ARRAYSIZE(str_lptstr)); + if(str_lptstr_len) + { + UCS *str_ucs4; + char *str_utf8; + + // Notify the speller so it'll suggest this word next time around. + str_utf8 = lptstr_to_utf8(str_lptstr); + if(str_utf8) + { + speller_replace_word(word_info->aspellinfo, + word_info->word_utf8, -1, str_utf8, -1); + fs_give((void **)&str_utf8); + } + + str_ucs4 = lptstr_to_ucs4(str_lptstr); + if(!str_ucs4) + { + // Uh oh - massive error. + word_info->utf8_err_message = _("Spelling: lptstr_to_ucs4() failed"); + EndDialog(hDlg, -1); + return; + } + + // Move back to start of this word. + curwp->w_doto = word_info->word_doto; + curwp->w_dotp = word_info->word_dotp; + + if(do_replace_all) + { + int i; + int word_size; + UCS word[128]; + + word_size = word_info->word_size; + if(word_size >= ARRAYSIZE(word) - 1) + word_size = ARRAYSIZE(word) - 1; + + for(i = 0; i < word_size; i++) + word[i] = lgetc(curwp->w_dotp, curwp->w_doto + i).c; + + word[i] = 0; + + replace_all(word, word_size, str_ucs4); + + // Skip over the word we just inserted. + forwchar(FALSE, (int)ucs4_strlen(str_ucs4)); + } + else + { + // Swap it with the new improved version. + chword_n(word_info->word_size, str_ucs4); + } + fs_give((void **)&str_ucs4); + } + + update(); + spell_dlg_next_word(hDlg, word_info); +} + +/* + * center_dialog() - Center a dialog with respect to its parent. + */ +static void +center_dialog(HWND hDlg) +{ + int dx; + int dy; + RECT rcDialog; + RECT rcParent; + + GetWindowRect(GetParent(hDlg), &rcParent); + GetWindowRect(hDlg, &rcDialog); + + dx = ((rcParent.right - rcParent.left) - + (rcDialog.right - rcDialog.left)) / 2 + rcParent.left - rcDialog.left; + + dy = ((rcParent.bottom - rcParent.top) - + (rcDialog.bottom - rcDialog.top)) / 2 + rcParent.top - rcDialog.top; + + OffsetRect(&rcDialog, dx, dy); + + SetWindowPos(hDlg, NULL, rcDialog.left, rcDialog.top, 0, 0, + SWP_NOSIZE | SWP_NOZORDER); +} + +/* + * spell_dlg_on_command() - Handle the WM_COMMAND stuff for the spell dialog. + */ +static void +spell_dlg_on_command(HWND hDlg, int id, HWND hwndCtl, UINT codeNotify) +{ + WORD_INFO *word_info = + (WORD_INFO *)(LONG_PTR)GetWindowLongPtr(hDlg, GWLP_USERDATA); + + switch(id) + { + case ID_COMBO_SUGGESTIONS: + if(codeNotify == CBN_EDITCHANGE) + handle_cb_editchange(hDlg, hwndCtl); + break; + + case ID_BUTTON_CHANGE: + handle_button_change(hDlg, word_info, 0); + break; + + case ID_BUTTON_CHANGEALL: + handle_button_change(hDlg, word_info, 1); + break; + + case ID_BUTTON_IGNOREONCE: + spell_dlg_next_word(hDlg, word_info); + break; + + case ID_BUTTON_IGNOREALL: + speller_ignore_all(word_info->aspellinfo, word_info->word_utf8, -1); + spell_dlg_next_word(hDlg, word_info); + break; + + case ID_BUTTON_ADD_TO_DICT: + speller_add_to_dictionary(word_info->aspellinfo, word_info->word_utf8, -1); + spell_dlg_next_word(hDlg, word_info); + break; + + case ID_BUTTON_CANCEL: + EndDialog(hDlg, 0); + break; + } +} + +/* + * spell_dlg_proc() - Main spell dialog proc. + */ +static INT_PTR CALLBACK +spell_dlg_proc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + WORD_INFO *word_info; + + switch(message) + { + case WM_INITDIALOG: + center_dialog(hDlg); + + // Limit how much junk they can type in. + ComboBox_LimitText(GetDlgItem(hDlg, ID_COMBO_SUGGESTIONS), 128); + + word_info = (WORD_INFO *)lParam; + SetWindowLongPtr(hDlg, GWLP_USERDATA, (LONG_PTR)word_info); + + spell_dlg_proc_set_word(hDlg, word_info); + return TRUE; + + case WM_COMMAND: + HANDLE_WM_COMMAND(hDlg, wParam, lParam, spell_dlg_on_command); + return TRUE; + } + + return FALSE; +} + +/* + * get_next_word() - Get the next word from dot. And skip words in + * quoted lines. + */ +static int +get_next_word(WORD_INFO *word_info) +{ + // Skip quoted lines + while(lgetc(curwp->w_dotp, 0).c == '>') + { + if(curwp->w_dotp == curbp->b_linep) + return 0; + + curwp->w_dotp = lforw(curwp->w_dotp); + curwp->w_doto = 0; + curwp->w_flag |= WFMOVE; + } + + // Move to a word. + while(inword() == FALSE) + { + if(forwchar(FALSE, 1) == FALSE) + { + // There is no next word. + return 0; + } + } + + // If mark is currently set, clear it. + if(curwp->w_markp) + setmark(0, 1); + + // Set mark to beginning of this word. + curwp->w_markp = curwp->w_dotp; + curwp->w_marko = curwp->w_doto; + + // Get word length + word_info->word_doto = curwp->w_doto; + word_info->word_dotp = curwp->w_dotp; + word_info->word_size = 0; + + while((inword() != FALSE) && (word_info->word_dotp == curwp->w_dotp)) + { + word_info->word_size++; + + if(forwchar(FALSE, 1) == FALSE) + break; + } + + word_info->word_utf8 = ucs4_to_utf8_cpystr_n( + (UCS *)&word_info->word_dotp->l_text[word_info->word_doto], + word_info->word_size); + return 1; +} + +/* + * get_next_word() - free the word_info members word_utf8 and word_lptstr. + */ +static void +free_word_info_words(WORD_INFO *word_info) +{ + if(word_info->word_utf8) + { + fs_give((void **)&word_info->word_utf8); + word_info->word_utf8 = NULL; + } + + if(word_info->word_lptstr) + { + fs_give((void **)&word_info->word_lptstr); + word_info->word_lptstr = NULL; + } +} + +/* + * get_next_bad_word() - Search from '.' for the next word we think is + * rotten. Mark it and highlight it. + */ +static int +get_next_bad_word(WORD_INFO *word_info) +{ + free_word_info_words(word_info); + + while(get_next_word(word_info)) + { + int ret; + + /* pass over words that contain @ */ + if(strchr(word_info->word_utf8, '@')) + ret = 1; + else + ret = speller_check_word(word_info->aspellinfo, word_info->word_utf8, -1); + + if(ret == -1) + { + word_info->utf8_err_message = + speller_get_error_message(word_info->aspellinfo); + if(!word_info->utf8_err_message) + word_info->utf8_err_message = _("Spelling: speller_check_word() failed"); + return 0; + } + else if(ret == 0) + { + // Highlight word. + update(); + + word_info->word_lptstr = utf8_to_lptstr(word_info->word_utf8); + return 1; + } + + free_word_info_words(word_info); + } + + return 0; +} |