2
* Copyright (c) 1999 by The XFree86 Project, Inc.
4
* Permission is hereby granted, free of charge, to any person obtaining a
5
* copy of this software and associated documentation files (the "Software"),
6
* to deal in the Software without restriction, including without limitation
7
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
* and/or sell copies of the Software, and to permit persons to whom the
9
* Software is furnished to do so, subject to the following conditions:
11
* The above copyright notice and this permission notice shall be included in
12
* all copies or substantial portions of the Software.
14
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17
* THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
* Except as contained in this notice, the name of the XFree86 Project shall
23
* not be used in advertising or otherwise to promote the sale, use or other
24
* dealings in this Software without prior written authorization from the
27
* Author: Paulo C�sar Pereira de Andrade
30
/* $XFree86: xc/programs/xedit/ispell.c,v 1.19 2002/10/19 20:04:20 herrb Exp $ */
39
#include <sys/types.h>
41
#include <X11/Xaw/Toggle.h>
42
#include <X11/Xaw/MenuButton.h>
43
#include <X11/Xaw/SmeBSB.h>
44
#include <X11/Xaw/SimpleMenu.h>
60
typedef struct _ispell_undo {
63
XawTextPosition undo_pos;
64
Boolean repeat; /* two (misspelled?) words together */
66
int format; /* remember text formatting style */
67
struct _ispell_undo *next, *prev;
70
typedef struct _ispell_dict {
73
struct _ispell_dict *next;
78
struct _ispell_format {
84
static struct _ispell_format ispell_format[] = {
90
Widget shell, form, mispelled, repeated, word, replacement, text,
91
suggestions, viewport, list, commands, replace, status,
92
replaceAll, undo, ignore, ignoreAll, add, addUncap, suspend,
93
cancel, check, look, terse, options, dict, dictMenu,
98
int pid, ifd[2], ofd[2];
99
XawTextPosition left, right;
112
ispell_undo *undo_head, *undo_base;
119
Boolean terse_mode, undo_terse_mode;
120
char *guess_label, *miss_label, *root_label, *none_label, *eof_label,
121
*compound_label, *ok_label, *repeat_label, *working_label, *look_label;
127
ispell_dict *dict_info;
129
int format_mode; /* to undo correctly */
131
struct _ispell_format *format_info;
134
typedef struct _ReplaceList {
137
struct _ReplaceList *next;
140
typedef struct _IgnoreList {
143
struct _IgnoreList *next;
149
static void AddIspell(Widget, XtPointer, XtPointer);
150
static void ChangeDictionaryIspell(Widget, XtPointer, XtPointer);
151
static void ChangeFormatIspell(Widget, XtPointer, XtPointer);
152
static void CheckIspell(Widget, XtPointer, XtPointer);
153
static void IgnoreIspell(Widget, XtPointer, XtPointer);
154
static Bool InitIspell(void);
155
static void IspellCheckUndo(void);
156
static int IspellConvertHtmlAmp(char*);
157
static Bool IspellDoIgnoredWord(char*, int, int);
158
static Bool IspellIgnoredWord(char*, int, int);
159
static void IspellInputCallback(XtPointer, int*, XtInputId*);
160
static void IspellKillUndoBuffer(void);
161
static Bool IspellReceive(void);
162
static char *IspellReplacedWord(char*, char*);
163
static int IspellSend(void);
164
static void IspellSetSelection(XawTextPosition, XawTextPosition);
165
static void IspellSetRepeated(Bool);
166
static void IspellSetSensitive(Bool);
167
static void IspellSetStatus(char*);
168
static void IspellSetTerseMode(Bool);
169
static Bool IspellStartProcess(void);
170
static Bool IspellEndProcess(Bool, Bool);
171
static void LookIspell(Widget, XtPointer, XtPointer);
172
static void PopdownIspell(Widget, XtPointer, XtPointer);
173
static void ReplaceIspell(Widget, XtPointer, XtPointer);
174
static void RevertIspell(Widget, XtPointer, XtPointer);
175
static void SelectIspell(Widget, XtPointer, XtPointer);
176
static void ToggleTerseIspell(Widget, XtPointer, XtPointer);
177
#ifndef SIGNALRETURNSINT
178
static void timeout_signal(int);
179
static void (*old_timeout)(int);
181
static int timeout_signal(int);
182
static int (*old_timeout)(int);
184
static void UndoIspell(Widget, XtPointer, XtPointer);
186
Bool _XawTextSrcUndo(TextSrcObject, XawTextPosition*);
191
static struct _ispell ispell;
195
static ReplaceList *replace_list[RSTRTBLSZ];
196
static IgnoreList *ignore_list[ISTRTBLSZ];
199
#define XtCStatus "Status"
202
#define Offset(field) XtOffsetOf(struct _ispell, field)
203
static XtResource resources[] = {
204
{"wordChars", "Chars", XtRString, sizeof(char*),
205
Offset(wchars), XtRString, ""},
206
{"ispellCommand", "CommandLine", XtRString, sizeof(char*),
207
Offset(cmd), XtRString, "/usr/local/bin/ispell"},
208
{"terseMode", "Terse", XtRBoolean, sizeof(Boolean),
209
Offset(terse_mode), XtRImmediate, (XtPointer)False},
210
{"guessLabel", XtCStatus, XtRString, sizeof(String),
211
Offset(guess_label), XtRString, "Guess"},
212
{"missLabel", XtCStatus, XtRString, sizeof(String),
213
Offset(miss_label), XtRString, "Miss"},
214
{"rootLabel", XtCStatus, XtRString, sizeof(String),
215
Offset(root_label), XtRString, "Root:"},
216
{"noneLabel", XtCStatus, XtRString, sizeof(String),
217
Offset(none_label), XtRString, "None"},
218
{"compoundLabel", XtCStatus, XtRString, sizeof(String),
219
Offset(compound_label), XtRString, "Compound"},
220
{"okLabel", XtCStatus, XtRString, sizeof(String),
221
Offset(ok_label), XtRString, "Ok"},
222
{"eofLabel", XtCStatus, XtRString, sizeof(String),
223
Offset(eof_label), XtRString, "End Of File"},
224
{"repeatLabel", XtCStatus, XtRString, sizeof(String),
225
Offset(repeat_label), XtRString, "Repeat"},
226
{"workingLabel", XtCStatus, XtRString, sizeof(String),
227
Offset(working_label), XtRString, "..."},
228
{"lookLabel", XtCStatus, XtRString, sizeof(String),
229
Offset(look_label), XtRString, "Look"},
230
{"lookCommand", "CommandLine", XtRString, sizeof(char*),
231
Offset(look_cmd), XtRString, "/usr/bin/egrep -i"},
232
{"wordsFile", "Words", XtRString, sizeof(char*),
233
Offset(words_file), XtRString, "/usr/share/dict/words"},
234
{"dictionary", "Dictionary", XtRString, sizeof(char*),
235
Offset(dictionary), XtRString, "american"},
236
{"dictionaries", "Dictionary", XtRString, sizeof(char*),
237
Offset(dict_list), XtRString, "american americanmed+ english"},
238
{"formatting", "TextFormat", XtRString, sizeof(char*),
239
Offset(formatting), XtRString, "text"},
250
XmuNCopyISOLatin1Lowered(buf, buf, sizeof(buf));
261
XmuNCopyISOLatin1Uppered(buf, buf, sizeof(buf));
272
*upbuf = *lobuf = ch;
273
XmuNCopyISOLatin1Lowered(lobuf, lobuf, sizeof(lobuf));
274
XmuNCopyISOLatin1Uppered(upbuf, upbuf, sizeof(upbuf));
276
return (*lobuf != *upbuf && ch == *lobuf);
285
*upbuf = *lobuf = ch;
286
XmuNCopyISOLatin1Lowered(lobuf, lobuf, sizeof(lobuf));
287
XmuNCopyISOLatin1Uppered(upbuf, upbuf, sizeof(upbuf));
289
return (*lobuf != *upbuf && ch == *upbuf);
292
#define ToLower tolower
293
#define ToUpper toupper
294
#define IsLower islower
295
#define IsUpper isupper
302
# define WRITES(s) write(STDERR_FILENO, s, strlen(s))
304
# define WRITES(s) write(fileno(stderr), s, strlen(s))
308
#ifndef SIGNALRETURNSINT
310
timeout_signal(int unused)
312
int olderrno = errno;
314
WRITES("Warning: Timeout waiting ispell process to die.\n");
315
kill(ispell.pid, SIGTERM);
320
timeout_signal(int unused)
322
int olderrno = errno;
324
WRITES("Warning: Timeout waiting ispell process to die.\n");
325
kill(ispell.pid, SIGTERM);
333
IspellSetSelection(XawTextPosition left, XawTextPosition right)
335
/* Try to make sure the selected word is completely visible */
336
XawTextSetInsertionPoint(ispell.ascii, right);
337
XawTextSetInsertionPoint(ispell.ascii, left);
338
XawTextSetSelection(ispell.ascii, left, right);
342
IspellSetStatus(char *label)
346
XtSetArg(args[0], XtNlabel, label);
347
XtSetValues(ispell.status, args, 1);
351
IspellSetRepeated(Bool state)
353
static char *mispelled, *repeated;
356
if (mispelled == NULL) {
357
XtSetArg(args[0], XtNlabel, &mispelled);
358
XtGetValues(ispell.mispelled, args, 1);
359
mispelled = XtNewString(mispelled);
361
if (repeated == NULL) {
362
XtSetArg(args[0], XtNlabel, &repeated);
363
XtGetValues(ispell.repeated, args, 1);
364
repeated = XtNewString(repeated);
366
XtSetSensitive(ispell.replaceAll, !state);
367
XtSetSensitive(ispell.ignoreAll, !state);
368
XtSetSensitive(ispell.add, !state);
369
XtSetSensitive(ispell.addUncap, !state);
371
XtSetArg(args[0], XtNlabel, mispelled);
372
XtSetValues(ispell.mispelled, args, 1);
375
XtSetArg(args[0], XtNlabel, repeated);
376
XtSetValues(ispell.mispelled, args, 1);
381
IspellSetSensitive(Bool state)
383
XtSetSensitive(ispell.replace, state);
384
XtSetSensitive(ispell.replaceAll, state);
385
XtSetSensitive(ispell.ignore, state);
386
XtSetSensitive(ispell.ignoreAll, state);
387
XtSetSensitive(ispell.add, state);
388
XtSetSensitive(ispell.addUncap, state);
392
IspellSetTerseMode(Bool mode)
396
XtSetArg(args[0], XtNstate, ispell.terse_mode = mode);
397
XtSetValues(ispell.terse, args, 1);
398
write(ispell.ofd[1], mode ? "!\n" : "%\n", 2);
402
IspellCheckUndo(void)
404
ispell_undo *undo = XtNew(ispell_undo);
406
if (ispell.undo_for && strcmp(ispell.undo_for, ispell.dictionary)) {
407
XeditPrintf("Undo: Dictionary changed. Previous undo information lost.\n");
408
IspellKillUndoBuffer();
413
undo->repeat = False;
414
undo->terse = ispell.undo_terse_mode;
415
undo->format = ispell.format_mode;
416
if ((undo->prev = ispell.undo_head) != NULL)
417
undo->prev->next = undo;
421
if (!ispell.undo_base) {
422
ispell.undo_base = undo;
423
XtSetSensitive(ispell.undo, True);
425
else if (ispell.undo_depth > UNDO_DEPTH) {
428
if (ispell.undo_base->undo_str)
429
XtFree(ispell.undo_base->undo_str);
430
tmp = ispell.undo_base->next;
431
XtFree((char*)ispell.undo_base);
433
ispell.undo_base = tmp;
434
ispell.undo_depth = UNDO_DEPTH;
436
ispell.undo_head = undo;
440
IspellReplacedWord(char *word, char *replace)
447
ii = (ii << 1) ^ *pp++;
451
for (list = replace_list[ii]; list; list = list->next)
452
if (strcmp(list->word, word) == 0) {
454
XtFree(list->replace);
455
list->replace = XtNewString(replace);
457
return (list->replace);
463
list = XtNew(ReplaceList);
464
list->word = XtNewString(word);
465
list->replace = XtNewString(replace);
466
list->next = replace_list[ii];
467
replace_list[ii] = list;
469
return (list->replace);
473
IspellDoIgnoredWord(char *word, int cmd, int add)
475
IgnoreList *list, *prev;
480
ii = (ii << 1) ^ *pp++;
484
for (prev = list = ignore_list[ii]; list; prev = list, list = list->next)
485
if (strcmp(list->word, word) == 0) {
488
prev->next = list->next;
491
ignore_list[ii] = NULL;
494
return (cmd == CHECK);
500
list = XtNew(IgnoreList);
501
list->word = XtNewString(word);
503
list->next = ignore_list[ii];
504
ignore_list[ii] = list;
510
IspellIgnoredWord(char *word, int cmd, int add)
512
if (add != UNCAP && IspellDoIgnoredWord(word, cmd, add))
515
/* add/remove uncapped word to/of list,
516
* or cheks for correct capitalization */
517
if (add == UNCAP || cmd == CHECK) {
518
unsigned char *str = (unsigned char*)word;
519
unsigned char string[1024];
524
upper = IsUpper(*str);
525
*string = upper ? ToLower(*str) : *str;
530
for (i = 1; *str && i < sizeof(string) - 1; i++, str++) {
531
if (upper && IsLower(*str))
533
else if (!upper && IsUpper(*str))
535
string[i] = ToLower(*str);
539
if ((cmd != CHECK || status) &&
540
IspellDoIgnoredWord((char*)string, cmd, add))
553
char *str, *end, **list, **old_list;
554
char *tmp, word[1024];
557
if (ispell.lock || ispell.stat != RECEIVE)
560
while (1) { /* read the entire line */
561
if (ispell.buflen >= ispell.bufsiz - 1)
562
ispell.buf = XtRealloc(ispell.buf, ispell.bufsiz += BUFSIZ);
563
if ((len = read(ispell.ifd[0], &ispell.buf[ispell.buflen],
564
ispell.bufsiz - ispell.buflen - 1)) <= 0)
566
ispell.buflen += len;
568
if (ispell.buflen <= 0)
571
i = ispell.buflen - 1;
572
while (i >= 0 && ispell.buf[i] == '\n') {
576
if (len < 2 - ((ispell.terse_mode && i == -1) || ispell.buf[0] == '@'))
578
ispell.buf[ispell.buflen - len] = '\0';
581
if ((tmp = strchr(ispell.sendbuf, '\n')) != NULL)
584
switch (ispell.buf[0]) {
586
case '?': /* GUESS */
587
str = strchr(&ispell.buf[2], ' ');
588
if (!ispell.checkit) {
590
XtSetArg(args[0], XtNlabel, &ispell.buf[2]);
591
XtSetValues(ispell.word, args, 1);
595
str = strchr(str, ':') + 1;
597
end = strchr(str, ',');
598
if (end) *end = '\0';
600
list = (char**)XtRealloc((char*)list, (i + 16) * sizeof(char*));
602
for (j = 1; j < sizeof(word) && str[j]; j++) {
605
else if (str[j] == '-' && str[j+1] != '-' && str[j-1] != '-') {
606
char *p, string[256];
609
for (l = 0, k = j + 1; str[k] != '+' && str[k] != '-'
610
&& str[k] && l < sizeof(string) - 1; k++, l++)
614
if (l && (p = strstr(word, string)) != NULL) {
617
while ((p = strstr(p + l, string)) != NULL)
620
if (strcmp(p, string) == 0) {
634
list[i] = XtNewString(word);
636
if (end) str = end + 1;
641
XtSetArg(args[0], XtNlist, &old_list);
642
XtSetArg(args[1], XtNnumberStrings, &old_len);
643
XtGetValues(ispell.list, args, 2);
646
if ((str = IspellReplacedWord(&ispell.buf[2], NULL)) != NULL)
647
for (i = 0; i < len; i++) {
648
if (strcmp(list[i], str) == 0) {
649
ispell.item = list[i];
654
ispell.item = list[i = 0];
656
list = (char**)XtRealloc((char*)list, (len + 1) * sizeof(char*));
657
ispell.item = list[i] = XtNewString(str);
661
XtSetArg(args[0], XtNlist, list);
662
XtSetArg(args[1], XtNnumberStrings, len);
663
XtSetValues(ispell.list, args, 2);
665
XtSetSensitive(ispell.list, True);
667
XawListHighlight(ispell.list, i);
669
if (old_len > 1 || (XtName(ispell.list) != old_list[0])) {
670
while (--old_len > -1)
671
XtFree(old_list[old_len]);
672
XtFree((char*)old_list);
675
if (!ispell.checkit) {
676
XtSetArg(args[0], XtNstring, ispell.item);
677
XtSetValues(ispell.text, args, 1);
678
IspellSetSelection(ispell.left, ispell.right);
680
IspellSetRepeated(ispell.repeat = False);
683
IspellSetStatus(ispell.buf[0] == '?' ?
684
ispell.guess_label : ispell.miss_label);
685
ispell.undo_terse_mode = ispell.terse_mode;
686
ispell.format_mode = ispell.format_info->value;
690
case '-': /* COMPOUND */
693
str = &ispell.sendbuf[1];
694
if (!ispell.checkit) {
695
XtSetArg(args[0], XtNlabel, str);
696
XtSetValues(ispell.word, args, 1);
699
XtSetArg(args[0], XtNlist, &old_list);
700
XtSetArg(args[1], XtNnumberStrings, &old_len);
701
XtGetValues(ispell.list, args, 2);
704
list = (char**)XtMalloc(sizeof(char**));
705
if ((tmp = IspellReplacedWord(str, NULL)) != NULL)
707
if (tmp == NULL && ispell.buf[0] == '#')
708
list[0] = XtNewString("");
710
list[0] = XtNewString(str);
712
XtSetArg(args[0], XtNlist, list);
713
XtSetArg(args[1], XtNnumberStrings, 1);
714
XtSetValues(ispell.list, args, 2);
716
if (tmp == NULL && ispell.buf[0] == '#') {
717
XawListUnhighlight(ispell.list);
718
XtSetSensitive(ispell.list, False);
721
XtSetSensitive(ispell.list, True);
723
XawListHighlight(ispell.list, 0);
725
if (old_len > 1 || (XtName(ispell.list) != old_list[0])) {
726
while (--old_len > -1)
727
XtFree(old_list[old_len]);
728
XtFree((char*)old_list);
731
if (!ispell.checkit) {
732
XtSetArg(args[0], XtNstring, str);
733
XtSetValues(ispell.text, args, 1);
734
IspellSetSelection(ispell.left, ispell.right);
736
IspellSetRepeated(ispell.repeat = False);
739
ispell.undo_terse_mode = ispell.terse_mode;
740
ispell.format_mode = ispell.format_info->value;
742
if (ispell.buf[0] == '+') {
743
if ((tmp = strchr(&ispell.buf[2], '\n')) != NULL)
745
XmuSnprintf(word, sizeof(word), "%s %s",
746
ispell.root_label, &ispell.buf[2]);
747
IspellSetStatus(word);
750
IspellSetStatus(ispell.buf[0] == '#' ? ispell.none_label :
751
ispell.buf[0] == '-' ? ispell.compound_label :
755
case '\0': /* when running in terse mode */
757
(void)IspellIgnoredWord(&ispell.sendbuf[1], ADD, 0);
762
case '@': /* Ispell banner */
763
/* it only happens when the dictionary is changed */
764
if (!ispell.repeat) {
765
XawTextPosition left, right;
768
while (IspellSend() == 0)
770
/* word chars may have changed */
771
XawTextGetSelectionPos(ispell.ascii, &left, &right);
772
if (left != ispell.left || right != ispell.right) {
773
XtSetArg(args[0], XtNstring, &ispell.sendbuf[1]);
774
XtSetValues(ispell.text, args, 1);
775
IspellSetSelection(ispell.left, ispell.right);
777
ispell.checkit = True;
780
IspellSetStatus(ispell.repeat_label);
781
ispell.undo_terse_mode = ispell.terse_mode;
782
ispell.format_mode = ispell.format_info->value;
788
fprintf(stderr, "Unknown ispell command '%c'\n", ispell.buf[0]);
792
if (!ispell.lock && !ispell.checkit) {
794
while (IspellSend() == 0)
802
IspellConvertHtmlAmp(char *buf)
806
/* this function is static, so I can do it */
807
*strchr(++buf, ';') = '\0';
813
if (strcasecmp(&buf[1], "lt") == 0)
815
else if (strcasecmp(&buf[1], "gt") == 0)
817
else if (strcasecmp(&buf[1], "nbsp") == 0)
819
else if (strcasecmp(&buf[1], "amp") == 0)
821
else if (strcasecmp(&buf[1], "quot") == 0)
823
else if (*buf == '#') {
828
ch = strtol(&buf[1], &tmp, 10);
830
fprintf(stderr, "Warning: bad html interpreting '&#' mark.\n");
832
else if (strcmp(&buf[1], "acute") == 0) {
834
case 'a': ch = '�'; break;
835
case 'e': ch = '�'; break;
836
case 'i': ch = '�'; break;
837
case 'o': ch = '�'; break;
838
case 'u': ch = '�'; break;
839
case 'A': ch = '�'; break;
840
case 'E': ch = '�'; break;
841
case 'I': ch = '�'; break;
842
case 'O': ch = '�'; break;
843
case 'U': ch = '�'; break;
846
else if (strcmp(&buf[1], "grave") == 0) {
848
case 'a': ch = '�'; break;
849
case 'e': ch = '�'; break;
850
case 'i': ch = '�'; break;
851
case 'o': ch = '�'; break;
852
case 'u': ch = '�'; break;
853
case 'A': ch = '�'; break;
854
case 'E': ch = '�'; break;
855
case 'I': ch = '�'; break;
856
case 'O': ch = '�'; break;
857
case 'U': ch = '�'; break;
860
else if (strcmp(&buf[1], "tilde") == 0) {
862
case 'a': ch = '�'; break;
863
case 'o': ch = '�'; break;
864
case 'n': ch = '�'; break;
865
case 'A': ch = '�'; break;
866
case 'O': ch = '�'; break;
867
case 'N': ch = '�'; break;
870
else if (strcmp(&buf[1], "circ") == 0) {
872
case 'a': ch = '�'; break;
873
case 'e': ch = '�'; break;
874
case 'i': ch = '�'; break;
875
case 'o': ch = '�'; break;
876
case 'u': ch = '�'; break;
877
case 'A': ch = '�'; break;
878
case 'E': ch = '�'; break;
879
case 'I': ch = '�'; break;
880
case 'O': ch = '�'; break;
881
case 'U': ch = '�'; break;
884
else if (strcmp(&buf[1], "cedil") == 0) {
886
case 'c': ch = '�'; break;
887
case 'C': ch = '�'; break;
890
/* add more cases here */
900
XawTextPosition position, old_left, pos;
902
int i, len, spaces, nls;
903
Bool nl, html, inside_html;
907
if (ispell.lock || ispell.stat != SEND)
911
ispell.sendbuf[0] = '^'; /* don't evaluate following characters as commands */
915
html = ispell.format_info->value == HTML;
919
/* skip non word characters */
920
pos = position = ispell.right;
924
char mb[sizeof(wchar_t)];
927
position = XawTextSourceRead(ispell.source, position,
929
if (block.length == 0) { /* end of file */
932
XawTextSetInsertionPoint(ispell.ascii, ispell.right);
933
XawTextUnsetSelection(ispell.ascii);
934
IspellSetSensitive(False);
935
IspellSetStatus(ispell.eof_label);
938
for (i = 0; i < block.length; i++) {
940
wctomb(mb, ((wchar_t*)block.ptr)[i]);
944
if (amplen + 2 >= sizeof(ampbuf)) {
945
if (!ispell.terse_mode)
946
fprintf(stderr, "Warning: error interpreting '&' mark.\n");
949
goto retry_html_space;
951
else if ((ampbuf[amplen++] = *mb) == ';') {
954
ampbuf[amplen] = '\0';
955
ch = IspellConvertHtmlAmp(ampbuf);
958
(ch && strchr(ispell.wchars, ch))) {
959
/* interpret it again */
965
else if ((ch == '\n' || isspace(ch)) && spaces >= 0)
971
else if (html && *mb == '&') {
972
ampbuf[amplen++] = *mb;
973
pos = block.firstPos + i;
976
else if ((!html || !inside_html) && (isalpha(*mb) ||
977
(*mb && strchr(ispell.wchars, *mb)))) {
981
else if (!html && *mb == '\n') {
983
if (++nls > 1 && (!html || !inside_html))
985
else if (spaces >= 0)
990
if (*mb && strchr(ispell.skip, *mb)) {
991
position = ispell.right =
992
XawTextSourceScan(ispell.source, ispell.right + i,
993
XawstEOL, XawsdRight, 1, False);
997
else if (spaces >= 0 && isspace(*mb))
1002
else if (html && inside_html) {
1004
inside_html = False;
1006
else if (html && *mb == '<')
1008
else if (spaces >= 0 && (isspace(*mb) || (html && *mb == '\n')))
1019
old_left = ispell.left;
1022
position = ispell.left = ispell.right;
1025
char mb[sizeof(wchar_t)];
1028
position = XawTextSourceRead(ispell.source, position,
1030
if (block.length == 0 && len == 1) { /* end of file */
1033
XawTextSetInsertionPoint(ispell.ascii, ispell.right);
1034
XawTextUnsetSelection(ispell.ascii);
1035
IspellSetSensitive(False);
1036
IspellSetStatus(ispell.eof_label);
1039
for (i = 0; i < block.length; i++) {
1041
wctomb(mb, ((wchar_t*)block.ptr)[i]);
1045
if (amplen + 2 >= sizeof(ampbuf)) {
1046
if (!ispell.terse_mode)
1047
fprintf(stderr, "Warning: error interpreting '&' mark.\n");
1050
if (strchr(ispell.wchars, '&')) {
1051
if (len + 1 >= sizeof(ispell.sendbuf) - 1) {
1053
fprintf(stderr, "Warning: word is too large!\n");
1056
ispell.sendbuf[len++] = '&';
1057
goto retry_html_word;
1060
ispell.right = position;
1066
else if ((ampbuf[amplen++] = *mb) == ';') {
1069
ampbuf[amplen] = '\0';
1070
ch = IspellConvertHtmlAmp(ampbuf);
1073
(!ch || !strchr(ispell.wchars, ch))) {
1084
else if (html && *mb == '&') {
1085
ampbuf[amplen++] = *mb;
1086
pos = block.firstPos + i;
1089
else if (!isalpha(*mb) && (!*mb || !strchr(ispell.wchars, *mb))) {
1093
ispell.sendbuf[len] = *mb;
1094
if (++len >= sizeof(ispell.sendbuf) - 1) {
1096
fprintf(stderr, "Warning: word is too large!\n");
1101
if (done || block.length == 0)
1105
ispell.sendbuf[len] = '\0';
1107
if (spaces > 0 && spaces <= 32 && strcmp(ispell.sendbuf, ispell.sentbuf) == 0) {
1110
char **list, **old_list;
1111
char label[sizeof(ispell.sendbuf) + sizeof(ispell.sentbuf) + 32];
1113
strcpy(label, &ispell.sendbuf[1]);
1114
for (i = 0; i < spaces; i++)
1115
label[len + i - 1] = ' ';
1116
strcpy(&label[len + i - 1], &ispell.sendbuf[1]);
1117
XtSetArg(args[0], XtNlabel, label);
1118
XtSetValues(ispell.word, args, 1);
1120
XtSetArg(args[0], XtNstring, &ispell.sendbuf[1]);
1121
XtSetValues(ispell.text, args, 1);
1123
XtSetArg(args[0], XtNlist, &old_list);
1124
XtSetArg(args[1], XtNnumberStrings, &old_len);
1125
XtGetValues(ispell.list, args, 2);
1126
list = (char**)XtMalloc(sizeof(char**));
1127
list[0] = XtNewString(&ispell.sendbuf[1]);
1128
XtSetArg(args[0], XtNlist, list);
1129
XtSetArg(args[1], XtNnumberStrings, 1);
1130
XtSetValues(ispell.list, args, 2);
1131
XtSetSensitive(ispell.list, True);
1132
XawListHighlight(ispell.list, 0);
1133
if (old_len > 1 || (XtName(ispell.list) != old_list[0])) {
1134
while (--old_len > -1)
1135
XtFree(old_list[old_len]);
1136
XtFree((char*)old_list);
1139
IspellSetRepeated(True);
1140
IspellSetSelection(old_left, ispell.right);
1141
IspellSetStatus(ispell.repeat_label);
1142
ispell.repeat = ispell.lock = True;
1146
strcpy(ispell.sentbuf, ispell.sendbuf);
1148
if (len <= 2 || IspellIgnoredWord(&ispell.sendbuf[1], CHECK, 0))
1151
ispell.sendbuf[len++] = '\n';
1153
write(ispell.ofd[1], ispell.sendbuf, len);
1155
ispell.stat = RECEIVE;
1162
IspellInputCallback(XtPointer closure, int *source, XtInputId *id)
1164
if (ispell.right < 0) {
1168
ispell.right = XawTextGetInsertionPoint(ispell.ascii);
1169
ispell.right = XawTextSourceScan(ispell.source, ispell.right,
1170
XawstEOL, XawsdLeft, 1, True);
1171
len = read(ispell.ifd[0], buf, sizeof(buf));
1172
if (strncmp(buf, "@(#)", 4) == 0) {
1175
buf[len - 1] = '\0';
1176
XtSetArg(args[0], XtNtitle, &buf[5]);
1177
XtSetValues(ispell.shell, args, 1);
1180
fprintf(stderr, "Error: is ispell talking with me?\n");
1181
IspellSetTerseMode(ispell.terse_mode);
1182
while (IspellSend() == 0)
1185
else if (ispell.source)
1191
IspellCallback(Widget w, XtPointer client_data, XtPointer call_data)
1195
IspellAction(textwindow, NULL, NULL, &zero);
1200
IspellAction(Widget w, XEvent *event, String *params, Cardinal *num_params)
1204
char **strs, **list;
1206
Bool first_time = InitIspell();
1208
if (*num_params == 1 && (params[0][0] == 'e' || params[0][0] == 'E')) {
1209
PopdownIspell(w, (XtPointer)True, NULL);
1213
if (!XtIsSubclass(w, textWidgetClass) || ispell.source) {
1218
ispell.source = XawTextGetSource(ispell.ascii = w);
1221
/* let the user choose the better position for the ispell window */
1222
Dimension width, height, b_width;
1223
Position x, y, max_x, max_y;
1227
switch (event->type) {
1230
x = event->xbutton.x_root;
1231
y = event->xbutton.y_root;
1235
x = event->xkey.x_root;
1236
y = event->xkey.y_root;
1240
if (x < 0 || y < 0) {
1245
XQueryPointer(XtDisplay(ispell.shell), XtWindow(ispell.shell),
1246
&r, &c, &rx, &ry, &wx, &wy, &mask);
1252
XtSetArg(args[num_args], XtNwidth, &width); num_args++;
1253
XtSetArg(args[num_args], XtNheight, &height); num_args++;
1254
XtSetArg(args[num_args], XtNborderWidth, &b_width); num_args++;
1255
XtGetValues(ispell.shell, args, num_args);
1257
width += b_width << 1;
1258
height += b_width << 1;
1260
x -= (Position)(width >> 1);
1263
if (x > (max_x = (Position)(XtScreen(w)->width - width)))
1266
y -= (Position)(height >> 1);
1269
if (y > (max_y = (Position)(XtScreen(w)->height - height)))
1273
XtSetArg(args[num_args], XtNx, x); num_args++;
1274
XtSetArg(args[num_args], XtNy, y); num_args++;
1275
XtSetValues(ispell.shell, args, num_args);
1279
IspellSetRepeated(False);
1280
ispell.lock = ispell.repeat = ispell.checkit = False;
1283
IspellSetSensitive(True);
1284
XtSetSensitive(ispell.undo, False);
1286
XtSetArg(args[0], XtNlabel, "");
1287
XtSetValues(ispell.word, args, 1);
1289
XtSetArg(args[0], XtNstring, "");
1290
XtSetValues(ispell.text, args, 1);
1292
XtSetArg(args[0], XtNlist, &strs);
1293
XtSetArg(args[1], XtNnumberStrings, &n_strs);
1294
XtGetValues(ispell.list, args, 2);
1296
list = (char**)XtMalloc(sizeof(char**));
1297
list[0] = XtNewString("");
1298
XtSetArg(args[0], XtNlist, list);
1299
XtSetArg(args[1], XtNnumberStrings, 1);
1300
XtSetValues(ispell.list, args, 2);
1302
if (n_strs > 1 || (XtName(ispell.list) != strs[0])) {
1303
while (--n_strs > -1)
1304
XtFree(strs[n_strs]);
1305
XtFree((char*)strs);
1308
IspellSetStatus(ispell.working_label);
1311
(void)IspellStartProcess();
1313
ispell.right = XawTextGetInsertionPoint(ispell.ascii);
1314
ispell.right = XawTextSourceScan(ispell.source, ispell.right,
1315
XawstEOL, XawsdLeft, 1, True);
1316
while (IspellSend() == 0)
1320
XtPopup(ispell.shell, XtGrabExclusive);
1321
XtSetKeyboardFocus(ispell.shell, ispell.text);
1325
IspellStartProcess(void)
1331
ispell.source = XawTextGetSource(ispell.ascii);
1333
len = strlen(ispell.cmd) + strlen(ispell.dictionary) +
1334
strlen(ispell.wchars) + 16;
1335
command = XtMalloc(len);
1336
XmuSnprintf(command, len, "%s -a -d '%s' -w '%s'",
1337
ispell.cmd, ispell.dictionary, ispell.wchars);
1341
if ((ispell.pid = fork()) == 0) {
1344
dup2(ispell.ofd[0], 0);
1345
dup2(ispell.ifd[1], 1);
1346
close(ispell.ofd[0]);
1347
close(ispell.ofd[1]);
1348
close(ispell.ifd[0]);
1349
close(ispell.ifd[1]);
1350
execl("/bin/sh", "sh", "-c", command, (void *)NULL);
1353
else if (ispell.pid < 0) {
1354
fprintf(stderr, "Cannot fork\n");
1357
ispell.buf = XtMalloc(ispell.bufsiz = BUFSIZ);
1359
ispell.id = XtAppAddInput(XtWidgetToApplicationContext(ispell.shell),
1360
ispell.ifd[0], (XtPointer)XtInputReadMask,
1361
IspellInputCallback, NULL);
1362
fcntl(ispell.ifd[0], F_SETFL, O_NONBLOCK);
1372
PopdownIspell(Widget w, XtPointer client_data, XtPointer call_data)
1374
(void)IspellEndProcess((Bool)(long)client_data, True);
1375
XtPopdown(ispell.shell);
1376
*ispell.sentbuf = '\0';
1380
IspellEndProcess(Bool killit, Bool killundo)
1382
ispell.source = NULL;
1385
IgnoreList *il, *pil, *nil;
1388
/* insert added words in private dictionary */
1389
for (i = 0; i < ISTRTBLSZ; i++) {
1390
pil = il = ignore_list[i];
1395
ignore_list[i] = nil;
1398
if (il->add == UNCAP)
1399
write(ispell.ofd[1], "&", 1);
1401
write(ispell.ofd[1], "*", 1);
1402
write(ispell.ofd[1], il->word, strlen(il->word));
1403
write(ispell.ofd[1], "\n", 1);
1413
write(ispell.ofd[1], "#\n", 2); /* save dictionary */
1416
ReplaceList *rl, *prl;
1418
XtRemoveInput(ispell.id);
1420
close(ispell.ofd[0]);
1421
close(ispell.ofd[1]);
1422
close(ispell.ifd[0]);
1423
close(ispell.ifd[1]);
1425
/* if something goes wrong, we don't want to block here forever */
1426
old_timeout = signal(SIGALRM, timeout_signal);
1428
waitpid(ispell.pid, NULL, 0);
1430
signal(SIGALRM, old_timeout);
1437
for (i = 0; i < RSTRTBLSZ; i++) {
1438
prl = rl = replace_list[i];
1442
XtFree(prl->replace);
1446
replace_list[i] = NULL;
1448
for (i = 0; i < ISTRTBLSZ; i++) {
1449
pil = il = ignore_list[i];
1456
ignore_list[i] = NULL;
1461
IspellKillUndoBuffer();
1470
IspellKillUndoBuffer(void)
1472
ispell_undo *undo, *pundo;
1474
undo = pundo = ispell.undo_base;
1477
if (pundo->undo_str)
1478
XtFree(pundo->undo_str);
1479
XtFree((char*)pundo);
1482
ispell.undo_base = ispell.undo_head = NULL;
1483
ispell.undo_for = NULL;
1484
ispell.undo_depth = 0;
1485
XtSetSensitive(ispell.undo, False);
1490
RevertIspell(Widget w, XtPointer client_data, XtPointer call_data)
1493
char *string, *repstr = NULL;
1495
XtSetArg(args[0], XtNlabel, &string);
1496
XtGetValues(ispell.word, args, 1);
1497
if ((repstr = strchr(string, ' ')) != NULL) {
1498
string = repstr = XtNewString(string);
1499
*strchr(repstr, ' ') = '\0';
1501
XtSetArg(args[0], XtNstring, string);
1502
XtSetValues(ispell.text, args, 1);
1509
SelectIspell(Widget w, XtPointer client_data, XtPointer call_data)
1511
XawListReturnStruct *info = (XawListReturnStruct *)call_data;
1514
XtSetArg(args[0], XtNstring, ispell.item = info->string);
1515
XtSetValues(ispell.text, args, 1);
1520
ReplaceIspell(Widget w, XtPointer client_data, XtPointer call_data)
1522
XawTextPosition pos = XawTextGetInsertionPoint(ispell.ascii);
1523
XawTextBlock check, search, replace;
1530
XtSetArg(args[0], XtNlabel, &text);
1531
XtGetValues(ispell.word, args, 1);
1533
search.format = XawFmt8Bit;
1534
search.firstPos = 0;
1535
search.length = ispell.right - pos;
1537
XtSetArg(args[0], XtNstring, &text);
1538
XtGetValues(ispell.text, args, 1);
1540
replace.format = XawFmt8Bit;
1541
replace.firstPos = 0;
1542
replace.length = strlen(text);
1544
if (strcmp(search.ptr, replace.ptr) != 0 &&
1545
XawTextReplace(ispell.ascii, pos, pos + search.length,
1546
&replace) == XawEditDone) {
1547
ispell.right += replace.length - search.length;
1549
ispell.undo_head->undo_str = NULL;
1550
ispell.undo_head->undo_pos = pos;
1551
ispell.undo_head->undo_count = 1;
1553
if (ispell.repeat) {
1554
ispell.undo_head->repeat = 2; /* To recognize later it was replaced */
1555
ispell.undo_head->undo_count = ispell.right;
1556
ispell.undo_head->undo_str = XtNewString(search.ptr);
1558
if (client_data && !ispell.repeat) {
1559
XawTextDisableRedisplay(ispell.ascii);
1561
while ((pos = XawTextSourceSearch(ispell.source, pos, XawsdRight, &search))
1562
!= XawTextSearchError) {
1563
Bool do_replace = True;
1564
char mb[sizeof(wchar_t)];
1566
if (XawTextSourceRead(ispell.source, pos - 1, &check, 1) > 0) {
1568
wctomb(mb, *(wchar_t*)check.ptr);
1571
do_replace = !isalpha(*mb) && *mb && !strchr(ispell.wchars, *mb);
1574
XawTextSourceRead(ispell.source, pos + search.length, &check, 1) > 0) {
1576
wctomb(mb, *(wchar_t*)check.ptr);
1579
do_replace = !isalpha(*mb) && *mb && !strchr(ispell.wchars, *mb);
1582
XawTextReplace(ispell.ascii, pos, pos + search.length, &replace);
1583
++ispell.undo_head->undo_count;
1585
pos += search.length;
1587
XawTextEnableRedisplay(ispell.ascii);
1589
(void)IspellReplacedWord(search.ptr, replace.ptr);
1591
strncpy(&ispell.sentbuf[1], replace.ptr, sizeof(ispell.sentbuf) - 2);
1592
ispell.sentbuf[sizeof(ispell.sentbuf) - 1] = '\0';
1598
ispell.right = ispell.left = XawTextGetInsertionPoint(ispell.ascii);
1599
else if (!ispell.terse_mode || !ispell.item ||
1600
strcmp(ispell.item, replace.ptr))
1601
ispell.right = ispell.left; /* check it again! */
1603
ispell.lock = ispell.checkit = False;
1606
IspellSetStatus(ispell.working_label);
1607
while (IspellSend() == 0)
1613
IgnoreIspell(Widget w, XtPointer client_data, XtPointer call_data)
1621
XtSetArg(args[0], XtNlabel, &text);
1622
XtGetValues(ispell.word, args, 1);
1626
if ((ispell.undo_head->repeat = ispell.repeat) != False) {
1627
ispell.undo_head->undo_count = ispell.right;
1628
ispell.undo_head->undo_str = XtNewString(text);
1631
ispell.undo_head->undo_count = 0;
1633
ispell.undo_head->undo_pos = XawTextGetInsertionPoint(ispell.ascii);
1635
if (!ispell.repeat) {
1637
IspellIgnoredWord(text, ADD, 0);
1638
ispell.undo_head->undo_str = XtNewString(text);
1641
ispell.undo_head->undo_str = NULL;
1644
ispell.lock = ispell.checkit = False;
1647
IspellSetStatus(ispell.working_label);
1648
while (IspellSend() == 0)
1654
AddIspell(Widget w, XtPointer client_data, XtPointer call_data)
1658
int cmd = (long)client_data;
1660
if (!ispell.lock || ispell.repeat)
1663
XtSetArg(args[0], XtNlabel, &text);
1664
XtGetValues(ispell.word, args, 1);
1667
ispell.undo_head->undo_str = XtNewString(text);
1668
ispell.undo_head->undo_pos = XawTextGetInsertionPoint(ispell.ascii);
1669
ispell.undo_head->undo_count = -cmd;
1671
(void)IspellIgnoredWord(text, ADD, cmd);
1673
ispell.lock = ispell.checkit = False;
1675
IspellSetStatus(ispell.working_label);
1676
while (IspellSend() == 0)
1682
UndoIspell(Widget w, XtPointer client_data, XtPointer call_data)
1684
Bool enable_redisplay = False;
1685
ispell_undo *undo = ispell.undo_head;
1687
if ((!ispell.lock && ispell.stat) || !undo)
1690
if (ispell.undo_for && strcmp(ispell.undo_for, ispell.dictionary)) {
1691
XeditPrintf("Undo: Dictionary changed. Undo information was lost.\n");
1692
IspellKillUndoBuffer();
1697
if (undo->terse != ispell.terse_mode)
1698
IspellSetTerseMode(undo->terse);
1700
if (undo->format != ispell.format_info->value) {
1701
struct _ispell_format *fmt = &ispell_format[undo->format];
1702
ChangeFormatIspell(fmt->sme, (XtPointer)fmt, NULL);
1705
if (undo->undo_count > 0 && !undo->repeat) {
1706
XawTextPosition tmp;
1708
enable_redisplay = undo->undo_count > 1;
1709
if (enable_redisplay)
1710
XawTextDisableRedisplay(ispell.ascii);
1711
while (undo->undo_count--)
1712
if (!_XawTextSrcUndo((TextSrcObject)ispell.source, &tmp)) {
1717
else if (undo->undo_count < 0) {
1719
(void)IspellIgnoredWord(undo->undo_str, REMOVE, -undo->undo_count);
1721
else if (undo->undo_str) {
1723
IspellIgnoredWord(undo->undo_str, REMOVE, 0);
1726
XawTextSetInsertionPoint(ispell.ascii,
1727
ispell.right = ispell.left = undo->undo_pos);
1728
if (enable_redisplay)
1729
XawTextEnableRedisplay(ispell.ascii);
1731
/* need to do it because may be two misspelled words together */
1733
char **list, **old_list;
1737
if (undo->repeat > 1) {
1738
XawTextDisableRedisplay(ispell.ascii);
1739
if (!_XawTextSrcUndo((TextSrcObject)ispell.source, &ispell.right))
1741
XawTextEnableRedisplay(ispell.ascii);
1744
ispell.right = (XawTextPosition)undo->undo_count;
1745
IspellSetRepeated(ispell.repeat = True);
1746
XtSetArg(args[0], XtNlabel, undo->undo_str);
1747
XtSetValues(ispell.word, args, 1);
1748
XmuSnprintf(ispell.sentbuf, sizeof(ispell.sentbuf), "^%s",
1749
strrchr(undo->undo_str, ' ') + 1);
1750
strcpy(ispell.sendbuf, ispell.sentbuf);
1751
XtSetArg(args[0], XtNstring, &ispell.sentbuf[1]);
1752
XtSetValues(ispell.text, args, 1);
1754
XtSetArg(args[0], XtNlist, &old_list);
1755
XtSetArg(args[1], XtNnumberStrings, &old_len);
1756
XtGetValues(ispell.list, args, 2);
1758
list = (char **)XtMalloc(sizeof(char*));
1759
list[0] = XtNewString(&ispell.sentbuf[1]);
1760
XtSetArg(args[0], XtNlist, list);
1761
XtSetArg(args[1], XtNnumberStrings, 1);
1762
XtSetValues(ispell.list, args, 2);
1763
XtSetSensitive(ispell.list, True);
1764
XawListHighlight(ispell.list, 0);
1766
if (old_len > 1 || (XtName(ispell.list) != old_list[0])) {
1767
while (--old_len > -1)
1768
XtFree(old_list[old_len]);
1769
XtFree((char*)old_list);
1772
IspellSetSelection(ispell.left, ispell.right);
1773
IspellSetStatus(ispell.repeat_label);
1775
ispell.checkit = False;
1777
else if (ispell.repeat) {
1778
*ispell.sentbuf = '\0';
1779
IspellSetRepeated(ispell.repeat = False);
1783
undo->prev->next = NULL;
1784
ispell.undo_head = undo->prev;
1785
if (undo == ispell.undo_base) {
1786
ispell.undo_base = NULL;
1787
ispell.undo_for = NULL;
1788
XtSetSensitive(ispell.undo, False);
1791
XtFree(undo->undo_str);
1792
XtFree((char*)undo);
1793
--ispell.undo_depth;
1795
if (!ispell.stat || ispell.checkit)
1796
IspellSetSensitive(True);
1798
if (!ispell.repeat) {
1799
ispell.lock = ispell.checkit = False;
1801
IspellSetStatus(ispell.working_label);
1802
while (IspellSend() == 0)
1809
CheckIspell(Widget w, XtPointer client_data, XtPointer call_data)
1812
char *text, *str, string[1024];
1818
XtSetArg(args[0], XtNstring, &text);
1819
XtGetValues(ispell.text, args, 1);
1821
/* Check only a word at a time */
1825
if (isalpha(*str) || strchr(ispell.wchars, *str))
1832
if (isalpha(*str) || strchr(ispell.wchars, *str))
1833
string[i++] = *str++;
1839
if (strcmp(text, string)) {
1840
XawTextPosition pos = XawTextGetInsertionPoint(ispell.text) - len;
1842
XtSetArg(args[0], XtNstring, string);
1843
XtSetValues(ispell.text, args, 1);
1844
XawTextSetInsertionPoint(ispell.text, pos);
1853
len = XmuSnprintf(ispell.sendbuf, sizeof(ispell.sendbuf), "^%s\n", string);
1855
ispell.sendbuf[sizeof(ispell.sendbuf) - 1] = '\n';
1857
write(ispell.ofd[1], ispell.sendbuf, len);
1859
ispell.lock = False;
1860
ispell.checkit = True;
1861
ispell.stat = RECEIVE;
1866
LookIspell(Widget w, XtPointer client_data, XtPointer call_data)
1871
char *text, *str, **list, **old_list, command[1024], buffer[1024];
1872
Bool sensitive = True;
1877
XtSetArg(args[0], XtNstring, &text);
1878
XtGetValues(ispell.text, args, 1);
1885
if (strlen(ispell.look_cmd) + strlen(text) + strlen(ispell.words_file) + 8
1886
> sizeof(command) - 1) {
1887
fprintf(stderr, "Command line too large\n");
1891
XmuSnprintf(command, sizeof(command), "%s '^%s.*$' %s",
1892
ispell.look_cmd, text, ispell.words_file);
1894
if ((fd = popen(command, "r")) == NULL) {
1895
fprintf(stderr, "Cannot popen '%s'\n", ispell.look_cmd);
1902
#define MAX_LOOK_RESULTS 256
1903
while (fgets(buffer, sizeof(buffer), fd) != NULL) {
1904
if ((str = strchr(buffer, '\n')) == NULL) {
1905
fprintf(stderr, "String is too large\n");
1909
if ((len % 16) == 0)
1910
list = (char**)XtRealloc((char*)list, sizeof(char*) * (len + 16));
1911
list[len] = XtNewString(buffer);
1912
if (++len >= MAX_LOOK_RESULTS) {
1917
#undef MAX_LOOK_RESULTS
1919
XtSetArg(args[0], XtNlist, &old_list);
1920
XtSetArg(args[1], XtNnumberStrings, &old_len);
1921
XtGetValues(ispell.list, args, 2);
1924
list = (char**)XtMalloc(sizeof(char*));
1925
list[0] = XtNewString("");
1930
XtSetArg(args[0], XtNlist, list);
1931
XtSetArg(args[1], XtNnumberStrings, len);
1932
XtSetValues(ispell.list, args, 2);
1934
XtSetSensitive(ispell.list, sensitive);
1935
IspellSetStatus(sensitive ? ispell.look_label : ispell.none_label);
1937
if (old_len > 1 || (XtName(ispell.list) != old_list[0])) {
1938
while (--old_len > -1)
1939
XtFree(old_list[old_len]);
1940
XtFree((char*)old_list);
1948
ToggleTerseIspell(Widget w, XtPointer client_data, XtPointer call_data)
1953
ispell.terse_mode = !ispell.terse_mode;
1954
write(ispell.ofd[1], ispell.terse_mode ? "!\n" : "%\n", 2);
1959
ChangeDictionaryIspell(Widget w, XtPointer client_data, XtPointer call_data)
1961
ispell_dict *tmp, *dic = (ispell_dict*)client_data;
1962
XawTextPosition pos = XawTextGetInsertionPoint(ispell.ascii);
1963
XawTextPosition right = ispell.right;
1966
if (strcmp(XtName(dic->sme), ispell.dictionary) == 0)
1974
for (tmp = ispell.dict_info; tmp; tmp = tmp->next)
1975
if (strcmp(XtName(tmp->sme), ispell.dictionary) == 0) {
1976
XtSetArg(args[0], XtNleftBitmap, None);
1977
XtSetValues(tmp->sme, args, 1);
1980
if (ispell.undo_base && !ispell.undo_for)
1981
ispell.undo_for = ispell.dictionary;
1983
XtSetArg(args[0], XtNleftBitmap, flist.pixmap);
1984
XtSetValues(dic->sme, args, 1);
1985
ispell.dictionary = XtName(dic->sme);
1986
ispell.wchars = dic->wchars;
1987
XtSetArg(args[0], XtNlabel, XtName(dic->sme));
1988
XtSetValues(ispell.dict, args, 1);
1990
IspellSetStatus(ispell.working_label);
1992
(void)IspellEndProcess(True, False);
1993
ispell.lock = ispell.checkit = False;
1994
(void)IspellStartProcess();
1996
ispell.stat = RECEIVE;
1998
/* restart at the same selected word */
1999
if (ispell.repeat == False)
2000
ispell.left = ispell.right = pos;
2002
ispell.right = right;
2007
ChangeFormatIspell(Widget w, XtPointer client_data, XtPointer call_data)
2009
struct _ispell_format *fmt = (struct _ispell_format*)client_data;
2012
if (strcmp(fmt->name, ispell.formatting) == 0)
2020
XtSetArg(args[0], XtNleftBitmap, None);
2021
XtSetValues(ispell.format_info->sme, args, 1);
2023
XtSetArg(args[0], XtNleftBitmap, flist.pixmap);
2024
XtSetValues(fmt->sme, args, 1);
2025
ispell.formatting = fmt->name;
2026
ispell.format_info = fmt;
2027
XtSetArg(args[0], XtNlabel, fmt->name);
2028
XtSetValues(ispell.format, args, 1);
2036
XtResource dict_res;
2038
static XtResource text_res[] = {
2039
{"skipLines", "Skip", XtRString, sizeof(char*),
2040
XtOffsetOf(struct _ispell, skip), XtRString, "#"},
2046
ispell.shell = XtCreatePopupShell("ispell", transientShellWidgetClass,
2047
topwindow, NULL, 0);
2049
XtGetApplicationResources(ispell.shell, (XtPointer)&ispell, resources,
2050
XtNumber(resources), NULL, 0);
2052
ispell.form = XtCreateManagedWidget("form", formWidgetClass,
2053
ispell.shell, NULL, 0);
2054
ispell.mispelled = XtCreateManagedWidget("mispelled", labelWidgetClass,
2055
ispell.form, NULL, 0);
2056
ispell.repeated = XtCreateWidget("repeated", labelWidgetClass,
2057
ispell.form, NULL, 0);
2058
ispell.word = XtCreateManagedWidget("word", commandWidgetClass,
2059
ispell.form, NULL, 0);
2060
XtAddCallback(ispell.word, XtNcallback, RevertIspell, NULL);
2061
ispell.replacement = XtCreateManagedWidget("replacement", labelWidgetClass,
2062
ispell.form, NULL, 0);
2063
ispell.text = XtVaCreateManagedWidget("text", asciiTextWidgetClass,
2065
XtNeditType, XawtextEdit,
2067
ispell.suggestions = XtCreateManagedWidget("suggestions", labelWidgetClass,
2068
ispell.form, NULL, 0);
2069
ispell.viewport = XtCreateManagedWidget("viewport", viewportWidgetClass,
2070
ispell.form, NULL, 0);
2071
ispell.list = XtCreateManagedWidget("list", listWidgetClass,
2072
ispell.viewport, NULL, 0);
2073
XtAddCallback(ispell.list, XtNcallback, SelectIspell, NULL);
2074
ispell.commands = XtCreateManagedWidget("commands", formWidgetClass,
2075
ispell.form, NULL, 0);
2076
ispell.check = XtCreateManagedWidget("check", commandWidgetClass,
2077
ispell.commands, NULL, 0);
2078
XtAddCallback(ispell.check, XtNcallback, CheckIspell, NULL);
2079
ispell.look = XtCreateManagedWidget("look", commandWidgetClass,
2080
ispell.commands, NULL, 0);
2081
XtAddCallback(ispell.look, XtNcallback, LookIspell, NULL);
2082
ispell.undo = XtCreateManagedWidget("undo", commandWidgetClass,
2083
ispell.commands, NULL, 0);
2084
XtAddCallback(ispell.undo, XtNcallback, UndoIspell, NULL);
2085
ispell.replace = XtCreateManagedWidget("replace", commandWidgetClass,
2086
ispell.commands, NULL, 0);
2087
XtAddCallback(ispell.replace, XtNcallback, ReplaceIspell, (XtPointer)False);
2088
ispell.replaceAll = XtCreateManagedWidget("replaceAll", commandWidgetClass,
2089
ispell.commands, NULL, 0);
2090
XtAddCallback(ispell.replaceAll, XtNcallback, ReplaceIspell, (XtPointer)True);
2091
ispell.ignore = XtCreateManagedWidget("ignore", commandWidgetClass,
2092
ispell.commands, NULL, 0);
2093
XtAddCallback(ispell.ignore, XtNcallback, IgnoreIspell, (XtPointer)False);
2094
ispell.ignoreAll = XtCreateManagedWidget("ignoreAll", commandWidgetClass,
2095
ispell.commands, NULL, 0);
2096
XtAddCallback(ispell.ignoreAll, XtNcallback, IgnoreIspell, (XtPointer)True);
2097
ispell.add = XtCreateManagedWidget("add", commandWidgetClass,
2098
ispell.commands, NULL, 0);
2099
XtAddCallback(ispell.add, XtNcallback, AddIspell, (XtPointer)ASIS);
2100
ispell.addUncap = XtCreateManagedWidget("addUncap", commandWidgetClass,
2101
ispell.commands, NULL, 0);
2102
XtAddCallback(ispell.addUncap, XtNcallback, AddIspell, (XtPointer)UNCAP);
2103
ispell.suspend = XtCreateManagedWidget("suspend", commandWidgetClass,
2104
ispell.commands, NULL, 0);
2105
XtAddCallback(ispell.suspend, XtNcallback, PopdownIspell, (XtPointer)False);
2106
ispell.cancel = XtCreateManagedWidget("cancel", commandWidgetClass,
2107
ispell.commands, NULL, 0);
2108
XtAddCallback(ispell.cancel, XtNcallback, PopdownIspell, (XtPointer)True);
2109
ispell.terse = XtVaCreateManagedWidget("terse", toggleWidgetClass,
2111
XtNstate, ispell.terse_mode,
2113
XtAddCallback(ispell.terse, XtNcallback, ToggleTerseIspell, NULL);
2114
ispell.status = XtCreateManagedWidget("status", labelWidgetClass,
2115
ispell.form, NULL, 0);
2116
ispell.options = XtCreateManagedWidget("options", formWidgetClass,
2117
ispell.form, NULL, 0);
2118
ispell.dict = XtVaCreateManagedWidget("dict", menuButtonWidgetClass,
2120
XtNmenuName, "dictionaries",
2122
ispell.dictMenu = XtCreatePopupShell("dictionaries", simpleMenuWidgetClass,
2123
ispell.options, NULL, 0);
2124
XtRealizeWidget(ispell.dictMenu);
2126
ispell.format = XtVaCreateManagedWidget("format", menuButtonWidgetClass,
2128
XtNmenuName, "formats",
2130
ispell.formatMenu = XtCreatePopupShell("formats", simpleMenuWidgetClass,
2131
ispell.options, NULL, 0);
2132
XtRealizeWidget(ispell.formatMenu);
2134
XtRealizeWidget(ispell.shell);
2136
for (i = 0; i < sizeof(ispell_format) / sizeof(ispell_format[0]); i++) {
2137
struct _ispell_format *fmt = &ispell_format[i];
2139
fmt->sme = XtCreateManagedWidget(fmt->name, smeBSBObjectClass,
2140
ispell.formatMenu, NULL, 0);
2141
XtAddCallback(fmt->sme, XtNcallback, ChangeFormatIspell, (XtPointer)fmt);
2143
if (strcmp(fmt->name, ispell.formatting) == 0) {
2146
XtSetArg(args[0], XtNlabel, ispell.formatting);
2147
XtSetValues(ispell.format, args, 1);
2148
XtSetArg(args[0], XtNleftBitmap, flist.pixmap);
2149
XtSetValues(fmt->sme, args, 1);
2150
ispell.format_info = fmt;
2153
if (ispell.format_info == NULL) {
2157
ispell.format_info = &ispell_format[TEXT];
2159
XmuSnprintf(msg, sizeof(msg),
2160
"Unrecognized formatting type \"%s\", will use \"%s\"",
2161
ispell.formatting, ispell.format_info->name);
2162
XtAppWarning(XtWidgetToApplicationContext(ispell.shell), msg);
2163
ispell.formatting = ispell.format_info->name;
2165
XtSetArg(args[0], XtNlabel, ispell.format_info->name);
2166
XtSetValues(ispell.format, args, 1);
2167
XtSetArg(args[0], XtNleftBitmap, flist.pixmap);
2168
XtSetValues(ispell.format_info->sme, args, 1);
2170
XtGetApplicationResources(ispell_format[TEXT].sme, (XtPointer)&ispell,
2171
text_res, XtNumber(text_res), NULL, 0);
2173
dict_res.resource_name = "wordChars";
2174
dict_res.resource_class = "Chars";
2175
dict_res.resource_type = XtRString;
2176
dict_res.resource_size = sizeof(char*);
2177
dict_res.resource_offset = XtOffsetOf(ispell_dict, wchars);
2178
dict_res.default_type = XtRString;
2179
dict_res.default_addr = "";
2181
list = XtNewString(ispell.dict_list);
2182
for (str = strtok(list, " \t,"); str; str = strtok(NULL, " \t,")) {
2183
ispell_dict *dic = XtNew(ispell_dict);
2185
dic->sme = XtCreateManagedWidget(str, smeBSBObjectClass,
2186
ispell.dictMenu, NULL, 0);
2187
XtGetApplicationResources(dic->sme, (XtPointer)dic, &dict_res,
2189
XtAddCallback(dic->sme, XtNcallback, ChangeDictionaryIspell,
2192
if (!ispell.dict_info)
2193
ispell.dict_info = dic;
2195
ispell_dict *tmp = ispell.dict_info;
2197
for (; tmp->next; tmp = tmp->next)
2201
if (strcmp(str, ispell.dictionary) == 0) {
2204
XtSetArg(args[0], XtNleftBitmap, flist.pixmap);
2205
XtSetValues(dic->sme, args, 1);
2206
XtSetArg(args[0], XtNlabel, str);
2207
XtSetValues(ispell.dict, args, 1);
2208
ispell.wchars = dic->wchars;
2213
delete_window = XInternAtom(XtDisplay(ispell.shell), "WM_DELETE_WINDOW", False);
2214
XSetWMProtocols(XtDisplay(ispell.shell), XtWindow(ispell.shell), &delete_window, 1);