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
/* $XdotOrg: app/xedit/ispell.c,v 1.7 2005/04/04 10:17:07 eich Exp $ */
31
/* $XFree86: xc/programs/xedit/ispell.c,v 1.19 2002/10/19 20:04:20 herrb Exp $ */
40
#include <sys/types.h>
42
#include <X11/Xaw/Toggle.h>
43
#include <X11/Xaw/MenuButton.h>
44
#include <X11/Xaw/SmeBSB.h>
45
#include <X11/Xaw/SimpleMenu.h>
62
typedef struct _ispell_undo {
65
XawTextPosition undo_pos;
66
Boolean repeat; /* two (misspelled?) words together */
68
int format; /* remember text formatting style */
69
struct _ispell_undo *next, *prev;
72
typedef struct _ispell_dict {
75
struct _ispell_dict *next;
80
struct _ispell_format {
86
static struct _ispell_format ispell_format[] = {
92
Widget shell, form, mispelled, repeated, word, replacement, text,
93
suggestions, viewport, list, commands, replace, status,
94
replaceAll, undo, ignore, ignoreAll, add, addUncap, suspend,
95
cancel, check, look, terse, options, dict, dictMenu,
100
int pid, ifd[2], ofd[2];
101
XawTextPosition left, right;
114
ispell_undo *undo_head, *undo_base;
121
Boolean terse_mode, undo_terse_mode;
122
char *guess_label, *miss_label, *root_label, *none_label, *eof_label,
123
*compound_label, *ok_label, *repeat_label, *working_label, *look_label;
129
ispell_dict *dict_info;
131
int format_mode; /* to undo correctly */
133
struct _ispell_format *format_info;
136
typedef struct _ReplaceList {
139
struct _ReplaceList *next;
142
typedef struct _IgnoreList {
145
struct _IgnoreList *next;
151
static void AddIspell(Widget, XtPointer, XtPointer);
152
static void ChangeDictionaryIspell(Widget, XtPointer, XtPointer);
153
static void ChangeFormatIspell(Widget, XtPointer, XtPointer);
154
static void CheckIspell(Widget, XtPointer, XtPointer);
155
static void IgnoreIspell(Widget, XtPointer, XtPointer);
156
static Bool InitIspell(void);
157
static void IspellCheckUndo(void);
158
static int IspellConvertHtmlAmp(char*);
159
static Bool IspellDoIgnoredWord(char*, int, int);
160
static Bool IspellIgnoredWord(char*, int, int);
161
static void IspellInputCallback(XtPointer, int*, XtInputId*);
162
static void IspellKillUndoBuffer(void);
163
static Bool IspellReceive(void);
164
static char *IspellReplacedWord(char*, char*);
165
static int IspellSend(void);
166
static void IspellSetSelection(XawTextPosition, XawTextPosition);
167
static void IspellSetRepeated(Bool);
168
static void IspellSetSensitive(Bool);
169
static void IspellSetStatus(char*);
170
static void IspellSetTerseMode(Bool);
171
static Bool IspellStartProcess(void);
172
static Bool IspellEndProcess(Bool, Bool);
173
static void LookIspell(Widget, XtPointer, XtPointer);
174
static void PopdownIspell(Widget, XtPointer, XtPointer);
175
static void ReplaceIspell(Widget, XtPointer, XtPointer);
176
static void RevertIspell(Widget, XtPointer, XtPointer);
177
static void SelectIspell(Widget, XtPointer, XtPointer);
178
static void ToggleTerseIspell(Widget, XtPointer, XtPointer);
179
#ifndef SIGNALRETURNSINT
180
static void timeout_signal(int);
181
static void (*old_timeout)(int);
183
static int timeout_signal(int);
184
static int (*old_timeout)(int);
186
static void UndoIspell(Widget, XtPointer, XtPointer);
188
Bool _XawTextSrcUndo(TextSrcObject, XawTextPosition*);
193
static struct _ispell ispell;
197
static ReplaceList *replace_list[RSTRTBLSZ];
198
static IgnoreList *ignore_list[ISTRTBLSZ];
201
#define XtCStatus "Status"
204
#define Offset(field) XtOffsetOf(struct _ispell, field)
205
static XtResource resources[] = {
206
{"wordChars", "Chars", XtRString, sizeof(char*),
207
Offset(wchars), XtRString, ""},
208
{"ispellCommand", "CommandLine", XtRString, sizeof(char*),
209
Offset(cmd), XtRString, "/usr/local/bin/ispell"},
210
{"terseMode", "Terse", XtRBoolean, sizeof(Boolean),
211
Offset(terse_mode), XtRImmediate, (XtPointer)False},
212
{"guessLabel", XtCStatus, XtRString, sizeof(String),
213
Offset(guess_label), XtRString, "Guess"},
214
{"missLabel", XtCStatus, XtRString, sizeof(String),
215
Offset(miss_label), XtRString, "Miss"},
216
{"rootLabel", XtCStatus, XtRString, sizeof(String),
217
Offset(root_label), XtRString, "Root:"},
218
{"noneLabel", XtCStatus, XtRString, sizeof(String),
219
Offset(none_label), XtRString, "None"},
220
{"compoundLabel", XtCStatus, XtRString, sizeof(String),
221
Offset(compound_label), XtRString, "Compound"},
222
{"okLabel", XtCStatus, XtRString, sizeof(String),
223
Offset(ok_label), XtRString, "Ok"},
224
{"eofLabel", XtCStatus, XtRString, sizeof(String),
225
Offset(eof_label), XtRString, "End Of File"},
226
{"repeatLabel", XtCStatus, XtRString, sizeof(String),
227
Offset(repeat_label), XtRString, "Repeat"},
228
{"workingLabel", XtCStatus, XtRString, sizeof(String),
229
Offset(working_label), XtRString, "..."},
230
{"lookLabel", XtCStatus, XtRString, sizeof(String),
231
Offset(look_label), XtRString, "Look"},
232
{"lookCommand", "CommandLine", XtRString, sizeof(char*),
233
Offset(look_cmd), XtRString, "/usr/bin/egrep -i"},
234
{"wordsFile", "Words", XtRString, sizeof(char*),
235
Offset(words_file), XtRString, "/usr/share/dict/words"},
236
{"dictionary", "Dictionary", XtRString, sizeof(char*),
237
Offset(dictionary), XtRString, "american"},
238
{"dictionaries", "Dictionary", XtRString, sizeof(char*),
239
Offset(dict_list), XtRString, "american americanmed+ english"},
240
{"formatting", "TextFormat", XtRString, sizeof(char*),
241
Offset(formatting), XtRString, "text"},
252
XmuNCopyISOLatin1Lowered(buf, buf, sizeof(buf));
263
XmuNCopyISOLatin1Uppered(buf, buf, sizeof(buf));
274
*upbuf = *lobuf = ch;
275
XmuNCopyISOLatin1Lowered(lobuf, lobuf, sizeof(lobuf));
276
XmuNCopyISOLatin1Uppered(upbuf, upbuf, sizeof(upbuf));
278
return (*lobuf != *upbuf && ch == *lobuf);
287
*upbuf = *lobuf = ch;
288
XmuNCopyISOLatin1Lowered(lobuf, lobuf, sizeof(lobuf));
289
XmuNCopyISOLatin1Uppered(upbuf, upbuf, sizeof(upbuf));
291
return (*lobuf != *upbuf && ch == *upbuf);
294
#define ToLower tolower
295
#define ToUpper toupper
296
#define IsLower islower
297
#define IsUpper isupper
304
# define WRITES(s) write(STDERR_FILENO, s, strlen(s))
306
# define WRITES(s) write(fileno(stderr), s, strlen(s))
310
#ifndef SIGNALRETURNSINT
312
timeout_signal(int unused)
314
int olderrno = errno;
316
WRITES("Warning: Timeout waiting ispell process to die.\n");
317
kill(ispell.pid, SIGTERM);
322
timeout_signal(int unused)
324
int olderrno = errno;
326
WRITES("Warning: Timeout waiting ispell process to die.\n");
327
kill(ispell.pid, SIGTERM);
335
IspellSetSelection(XawTextPosition left, XawTextPosition right)
337
/* Try to make sure the selected word is completely visible */
338
XawTextSetInsertionPoint(ispell.ascii, right);
339
XawTextSetInsertionPoint(ispell.ascii, left);
340
XawTextSetSelection(ispell.ascii, left, right);
344
IspellSetStatus(char *label)
348
XtSetArg(args[0], XtNlabel, label);
349
XtSetValues(ispell.status, args, 1);
353
IspellSetRepeated(Bool state)
355
static char *mispelled, *repeated;
358
if (mispelled == NULL) {
359
XtSetArg(args[0], XtNlabel, &mispelled);
360
XtGetValues(ispell.mispelled, args, 1);
361
mispelled = XtNewString(mispelled);
363
if (repeated == NULL) {
364
XtSetArg(args[0], XtNlabel, &repeated);
365
XtGetValues(ispell.repeated, args, 1);
366
repeated = XtNewString(repeated);
368
XtSetSensitive(ispell.replaceAll, !state);
369
XtSetSensitive(ispell.ignoreAll, !state);
370
XtSetSensitive(ispell.add, !state);
371
XtSetSensitive(ispell.addUncap, !state);
373
XtSetArg(args[0], XtNlabel, mispelled);
374
XtSetValues(ispell.mispelled, args, 1);
377
XtSetArg(args[0], XtNlabel, repeated);
378
XtSetValues(ispell.mispelled, args, 1);
383
IspellSetSensitive(Bool state)
385
XtSetSensitive(ispell.replace, state);
386
XtSetSensitive(ispell.replaceAll, state);
387
XtSetSensitive(ispell.ignore, state);
388
XtSetSensitive(ispell.ignoreAll, state);
389
XtSetSensitive(ispell.add, state);
390
XtSetSensitive(ispell.addUncap, state);
394
IspellSetTerseMode(Bool mode)
398
XtSetArg(args[0], XtNstate, ispell.terse_mode = mode);
399
XtSetValues(ispell.terse, args, 1);
400
write(ispell.ofd[1], mode ? "!\n" : "%\n", 2);
404
IspellCheckUndo(void)
406
ispell_undo *undo = XtNew(ispell_undo);
408
if (ispell.undo_for && strcmp(ispell.undo_for, ispell.dictionary)) {
409
XeditPrintf("Undo: Dictionary changed. Previous undo information lost.\n");
410
IspellKillUndoBuffer();
415
undo->repeat = False;
416
undo->terse = ispell.undo_terse_mode;
417
undo->format = ispell.format_mode;
418
if ((undo->prev = ispell.undo_head) != NULL)
419
undo->prev->next = undo;
423
if (!ispell.undo_base) {
424
ispell.undo_base = undo;
425
XtSetSensitive(ispell.undo, True);
427
else if (ispell.undo_depth > UNDO_DEPTH) {
430
if (ispell.undo_base->undo_str)
431
XtFree(ispell.undo_base->undo_str);
432
tmp = ispell.undo_base->next;
433
XtFree((char*)ispell.undo_base);
435
ispell.undo_base = tmp;
436
ispell.undo_depth = UNDO_DEPTH;
438
ispell.undo_head = undo;
442
IspellReplacedWord(char *word, char *replace)
449
ii = (ii << 1) ^ *pp++;
453
for (list = replace_list[ii]; list; list = list->next)
454
if (strcmp(list->word, word) == 0) {
456
XtFree(list->replace);
457
list->replace = XtNewString(replace);
459
return (list->replace);
465
list = XtNew(ReplaceList);
466
list->word = XtNewString(word);
467
list->replace = XtNewString(replace);
468
list->next = replace_list[ii];
469
replace_list[ii] = list;
471
return (list->replace);
475
IspellDoIgnoredWord(char *word, int cmd, int add)
477
IgnoreList *list, *prev;
482
ii = (ii << 1) ^ *pp++;
486
for (prev = list = ignore_list[ii]; list; prev = list, list = list->next)
487
if (strcmp(list->word, word) == 0) {
490
prev->next = list->next;
493
ignore_list[ii] = NULL;
496
return (cmd == CHECK);
502
list = XtNew(IgnoreList);
503
list->word = XtNewString(word);
505
list->next = ignore_list[ii];
506
ignore_list[ii] = list;
512
IspellIgnoredWord(char *word, int cmd, int add)
514
if (add != UNCAP && IspellDoIgnoredWord(word, cmd, add))
517
/* add/remove uncapped word to/of list,
518
* or cheks for correct capitalization */
519
if (add == UNCAP || cmd == CHECK) {
520
unsigned char *str = (unsigned char*)word;
521
unsigned char string[1024];
526
upper = IsUpper(*str);
527
*string = upper ? ToLower(*str) : *str;
532
for (i = 1; *str && i < sizeof(string) - 1; i++, str++) {
533
if (upper && IsLower(*str))
535
else if (!upper && IsUpper(*str))
537
string[i] = ToLower(*str);
541
if ((cmd != CHECK || status) &&
542
IspellDoIgnoredWord((char*)string, cmd, add))
555
char *str, *end, **list, **old_list;
556
char *tmp, word[1024];
559
if (ispell.lock || ispell.stat != RECEIVE)
562
while (1) { /* read the entire line */
563
if (ispell.buflen >= ispell.bufsiz - 1)
564
ispell.buf = XtRealloc(ispell.buf, ispell.bufsiz += BUFSIZ);
565
if ((len = read(ispell.ifd[0], &ispell.buf[ispell.buflen],
566
ispell.bufsiz - ispell.buflen - 1)) <= 0)
568
ispell.buflen += len;
570
if (ispell.buflen <= 0)
573
i = ispell.buflen - 1;
574
while (i >= 0 && ispell.buf[i] == '\n') {
578
if (len < 2 - ((ispell.terse_mode && i == -1) || ispell.buf[0] == '@'))
580
ispell.buf[ispell.buflen - len] = '\0';
583
if ((tmp = strchr(ispell.sendbuf, '\n')) != NULL)
586
switch (ispell.buf[0]) {
588
case '?': /* GUESS */
589
str = strchr(&ispell.buf[2], ' ');
590
if (!ispell.checkit) {
592
XtSetArg(args[0], XtNlabel, &ispell.buf[2]);
593
XtSetValues(ispell.word, args, 1);
597
str = strchr(str, ':') + 1;
599
end = strchr(str, ',');
600
if (end) *end = '\0';
602
list = (char**)XtRealloc((char*)list, (i + 16) * sizeof(char*));
604
for (j = 1; j < sizeof(word) && str[j]; j++) {
607
else if (str[j] == '-' && str[j+1] != '-' && str[j-1] != '-') {
608
char *p, string[256];
611
for (l = 0, k = j + 1; str[k] != '+' && str[k] != '-'
612
&& str[k] && l < sizeof(string) - 1; k++, l++)
616
if (l && (p = strstr(word, string)) != NULL) {
619
while ((p = strstr(p + l, string)) != NULL)
622
if (strcmp(p, string) == 0) {
636
list[i] = XtNewString(word);
638
if (end) str = end + 1;
643
XtSetArg(args[0], XtNlist, &old_list);
644
XtSetArg(args[1], XtNnumberStrings, &old_len);
645
XtGetValues(ispell.list, args, 2);
648
if ((str = IspellReplacedWord(&ispell.buf[2], NULL)) != NULL)
649
for (i = 0; i < len; i++) {
650
if (strcmp(list[i], str) == 0) {
651
ispell.item = list[i];
656
ispell.item = list[i = 0];
658
list = (char**)XtRealloc((char*)list, (len + 1) * sizeof(char*));
659
ispell.item = list[i] = XtNewString(str);
663
XtSetArg(args[0], XtNlist, list);
664
XtSetArg(args[1], XtNnumberStrings, len);
665
XtSetValues(ispell.list, args, 2);
667
XtSetSensitive(ispell.list, True);
669
XawListHighlight(ispell.list, i);
671
if (old_len > 1 || (XtName(ispell.list) != old_list[0])) {
672
while (--old_len > -1)
673
XtFree(old_list[old_len]);
674
XtFree((char*)old_list);
677
if (!ispell.checkit) {
678
XtSetArg(args[0], XtNstring, ispell.item);
679
XtSetValues(ispell.text, args, 1);
680
IspellSetSelection(ispell.left, ispell.right);
682
IspellSetRepeated(ispell.repeat = False);
685
IspellSetStatus(ispell.buf[0] == '?' ?
686
ispell.guess_label : ispell.miss_label);
687
ispell.undo_terse_mode = ispell.terse_mode;
688
ispell.format_mode = ispell.format_info->value;
692
case '-': /* COMPOUND */
695
str = &ispell.sendbuf[1];
696
if (!ispell.checkit) {
697
XtSetArg(args[0], XtNlabel, str);
698
XtSetValues(ispell.word, args, 1);
701
XtSetArg(args[0], XtNlist, &old_list);
702
XtSetArg(args[1], XtNnumberStrings, &old_len);
703
XtGetValues(ispell.list, args, 2);
706
list = (char**)XtMalloc(sizeof(char**));
707
if ((tmp = IspellReplacedWord(str, NULL)) != NULL)
709
if (tmp == NULL && ispell.buf[0] == '#')
710
list[0] = XtNewString("");
712
list[0] = XtNewString(str);
714
XtSetArg(args[0], XtNlist, list);
715
XtSetArg(args[1], XtNnumberStrings, 1);
716
XtSetValues(ispell.list, args, 2);
718
if (tmp == NULL && ispell.buf[0] == '#') {
719
XawListUnhighlight(ispell.list);
720
XtSetSensitive(ispell.list, False);
723
XtSetSensitive(ispell.list, True);
725
XawListHighlight(ispell.list, 0);
727
if (old_len > 1 || (XtName(ispell.list) != old_list[0])) {
728
while (--old_len > -1)
729
XtFree(old_list[old_len]);
730
XtFree((char*)old_list);
733
if (!ispell.checkit) {
734
XtSetArg(args[0], XtNstring, str);
735
XtSetValues(ispell.text, args, 1);
736
IspellSetSelection(ispell.left, ispell.right);
738
IspellSetRepeated(ispell.repeat = False);
741
ispell.undo_terse_mode = ispell.terse_mode;
742
ispell.format_mode = ispell.format_info->value;
744
if (ispell.buf[0] == '+') {
745
if ((tmp = strchr(&ispell.buf[2], '\n')) != NULL)
747
XmuSnprintf(word, sizeof(word), "%s %s",
748
ispell.root_label, &ispell.buf[2]);
749
IspellSetStatus(word);
752
IspellSetStatus(ispell.buf[0] == '#' ? ispell.none_label :
753
ispell.buf[0] == '-' ? ispell.compound_label :
757
case '\0': /* when running in terse mode */
759
(void)IspellIgnoredWord(&ispell.sendbuf[1], ADD, 0);
764
case '@': /* Ispell banner */
765
/* it only happens when the dictionary is changed */
766
if (!ispell.repeat) {
767
XawTextPosition left, right;
770
while (IspellSend() == 0)
772
/* word chars may have changed */
773
XawTextGetSelectionPos(ispell.ascii, &left, &right);
774
if (left != ispell.left || right != ispell.right) {
775
XtSetArg(args[0], XtNstring, &ispell.sendbuf[1]);
776
XtSetValues(ispell.text, args, 1);
777
IspellSetSelection(ispell.left, ispell.right);
779
ispell.checkit = True;
782
IspellSetStatus(ispell.repeat_label);
783
ispell.undo_terse_mode = ispell.terse_mode;
784
ispell.format_mode = ispell.format_info->value;
790
fprintf(stderr, "Unknown ispell command '%c'\n", ispell.buf[0]);
794
if (!ispell.lock && !ispell.checkit) {
796
while (IspellSend() == 0)
804
IspellConvertHtmlAmp(char *buf)
808
/* this function is static, so I can do it */
809
*strchr(++buf, ';') = '\0';
815
if (strcasecmp(&buf[1], "lt") == 0)
817
else if (strcasecmp(&buf[1], "gt") == 0)
819
else if (strcasecmp(&buf[1], "nbsp") == 0)
821
else if (strcasecmp(&buf[1], "amp") == 0)
823
else if (strcasecmp(&buf[1], "quot") == 0)
825
else if (*buf == '#') {
830
ch = strtol(&buf[1], &tmp, 10);
832
fprintf(stderr, "Warning: bad html interpreting '&#' mark.\n");
834
else if (strcmp(&buf[1], "acute") == 0) {
836
case 'a': ch = 0xe1; break;
837
case 'e': ch = 0xe9; break;
838
case 'i': ch = 0xed; break;
839
case 'o': ch = 0xf3; break;
840
case 'u': ch = 0xfa; break;
841
case 'A': ch = 0xc1; break;
842
case 'E': ch = 0xc9; break;
843
case 'I': ch = 0xcd; break;
844
case 'O': ch = 0xd3; break;
845
case 'U': ch = 0xda; break;
848
else if (strcmp(&buf[1], "grave") == 0) {
850
case 'a': ch = 0xe0; break;
851
case 'e': ch = 0xe8; break;
852
case 'i': ch = 0xec; break;
853
case 'o': ch = 0xf2; break;
854
case 'u': ch = 0xf9; break;
855
case 'A': ch = 0xc0; break;
856
case 'E': ch = 0xc8; break;
857
case 'I': ch = 0xcc; break;
858
case 'O': ch = 0xd2; break;
859
case 'U': ch = 0xd9; break;
862
else if (strcmp(&buf[1], "tilde") == 0) {
864
case 'a': ch = 0xe3; break;
865
case 'o': ch = 0xf5; break;
866
case 'n': ch = 0xf1; break;
867
case 'A': ch = 0xe3; break;
868
case 'O': ch = 0xd5; break;
869
case 'N': ch = 0xd1; break;
872
else if (strcmp(&buf[1], "circ") == 0) {
874
case 'a': ch = 0xe2; break;
875
case 'e': ch = 0xea; break;
876
case 'i': ch = 0xee; break;
877
case 'o': ch = 0xf4; break;
878
case 'u': ch = 0xfb; break;
879
case 'A': ch = 0xc2; break;
880
case 'E': ch = 0xca; break;
881
case 'I': ch = 0xce; break;
882
case 'O': ch = 0xd4; break;
883
case 'U': ch = 0xdb; break;
886
else if (strcmp(&buf[1], "cedil") == 0) {
888
case 'c': ch = 0xe7; break;
889
case 'C': ch = 0xc7; break;
892
/* add more cases here */
902
XawTextPosition position, old_left, pos;
904
int i, len, spaces, nls;
905
Bool nl, html, inside_html;
909
if (ispell.lock || ispell.stat != SEND)
913
ispell.sendbuf[0] = '^'; /* don't evaluate following characters as commands */
917
html = ispell.format_info->value == HTML;
921
/* skip non word characters */
922
pos = position = ispell.right;
926
char mb[sizeof(wchar_t)];
929
position = XawTextSourceRead(ispell.source, position,
931
if (block.length == 0) { /* end of file */
934
XawTextSetInsertionPoint(ispell.ascii, ispell.right);
935
XawTextUnsetSelection(ispell.ascii);
936
IspellSetSensitive(False);
937
IspellSetStatus(ispell.eof_label);
940
for (i = 0; i < block.length; i++) {
941
wctomb(mb, ((wchar_t*)block.ptr)[i]);
943
if (amplen + 2 >= sizeof(ampbuf)) {
944
if (!ispell.terse_mode)
945
fprintf(stderr, "Warning: error interpreting '&' mark.\n");
948
goto retry_html_space;
950
else if ((ampbuf[amplen++] = *mb) == ';') {
953
ampbuf[amplen] = '\0';
954
ch = IspellConvertHtmlAmp(ampbuf);
957
(ch && strchr(ispell.wchars, ch))) {
958
/* interpret it again */
964
else if ((ch == '\n' || isspace(ch)) && spaces >= 0)
970
else if (html && *mb == '&') {
971
ampbuf[amplen++] = *mb;
972
pos = block.firstPos + i;
975
else if ((!html || !inside_html) && (isalpha(*mb) ||
976
(*mb && strchr(ispell.wchars, *mb)))) {
980
else if (!html && *mb == '\n') {
982
if (++nls > 1 && (!html || !inside_html))
984
else if (spaces >= 0)
989
if (*mb && strchr(ispell.skip, *mb)) {
990
position = ispell.right =
991
XawTextSourceScan(ispell.source, ispell.right + i,
992
XawstEOL, XawsdRight, 1, False);
996
else if (spaces >= 0 && isspace(*mb))
1001
else if (html && inside_html) {
1003
inside_html = False;
1005
else if (html && *mb == '<')
1007
else if (spaces >= 0 && (isspace(*mb) || (html && *mb == '\n')))
1018
old_left = ispell.left;
1021
position = ispell.left = ispell.right;
1024
char mb[sizeof(wchar_t)];
1027
position = XawTextSourceRead(ispell.source, position,
1029
if (block.length == 0 && len == 1) { /* end of file */
1032
XawTextSetInsertionPoint(ispell.ascii, ispell.right);
1033
XawTextUnsetSelection(ispell.ascii);
1034
IspellSetSensitive(False);
1035
IspellSetStatus(ispell.eof_label);
1038
for (i = 0; i < block.length; i++) {
1039
wctomb(mb, ((wchar_t*)block.ptr)[i]);
1041
if (amplen + 2 >= sizeof(ampbuf)) {
1042
if (!ispell.terse_mode)
1043
fprintf(stderr, "Warning: error interpreting '&' mark.\n");
1046
if (strchr(ispell.wchars, '&')) {
1047
if (len + 1 >= sizeof(ispell.sendbuf) - 1) {
1049
fprintf(stderr, "Warning: word is too large!\n");
1052
ispell.sendbuf[len++] = '&';
1053
goto retry_html_word;
1056
ispell.right = position;
1062
else if ((ampbuf[amplen++] = *mb) == ';') {
1065
ampbuf[amplen] = '\0';
1066
ch = IspellConvertHtmlAmp(ampbuf);
1069
(!ch || !strchr(ispell.wchars, ch))) {
1080
else if (html && *mb == '&') {
1081
ampbuf[amplen++] = *mb;
1082
pos = block.firstPos + i;
1085
else if (!isalpha(*mb) && (!*mb || !strchr(ispell.wchars, *mb))) {
1089
ispell.sendbuf[len] = *mb;
1090
if (++len >= sizeof(ispell.sendbuf) - 1) {
1092
fprintf(stderr, "Warning: word is too large!\n");
1097
if (done || block.length == 0)
1101
ispell.sendbuf[len] = '\0';
1103
if (spaces > 0 && spaces <= 32 && strcmp(ispell.sendbuf, ispell.sentbuf) == 0) {
1106
char **list, **old_list;
1107
char label[sizeof(ispell.sendbuf) + sizeof(ispell.sentbuf) + 32];
1109
strcpy(label, &ispell.sendbuf[1]);
1110
for (i = 0; i < spaces; i++)
1111
label[len + i - 1] = ' ';
1112
strcpy(&label[len + i - 1], &ispell.sendbuf[1]);
1113
XtSetArg(args[0], XtNlabel, label);
1114
XtSetValues(ispell.word, args, 1);
1116
XtSetArg(args[0], XtNstring, &ispell.sendbuf[1]);
1117
XtSetValues(ispell.text, args, 1);
1119
XtSetArg(args[0], XtNlist, &old_list);
1120
XtSetArg(args[1], XtNnumberStrings, &old_len);
1121
XtGetValues(ispell.list, args, 2);
1122
list = (char**)XtMalloc(sizeof(char**));
1123
list[0] = XtNewString(&ispell.sendbuf[1]);
1124
XtSetArg(args[0], XtNlist, list);
1125
XtSetArg(args[1], XtNnumberStrings, 1);
1126
XtSetValues(ispell.list, args, 2);
1127
XtSetSensitive(ispell.list, True);
1128
XawListHighlight(ispell.list, 0);
1129
if (old_len > 1 || (XtName(ispell.list) != old_list[0])) {
1130
while (--old_len > -1)
1131
XtFree(old_list[old_len]);
1132
XtFree((char*)old_list);
1135
IspellSetRepeated(True);
1136
IspellSetSelection(old_left, ispell.right);
1137
IspellSetStatus(ispell.repeat_label);
1138
ispell.repeat = ispell.lock = True;
1142
strcpy(ispell.sentbuf, ispell.sendbuf);
1144
if (len <= 2 || IspellIgnoredWord(&ispell.sendbuf[1], CHECK, 0))
1147
ispell.sendbuf[len++] = '\n';
1149
write(ispell.ofd[1], ispell.sendbuf, len);
1151
ispell.stat = RECEIVE;
1158
IspellInputCallback(XtPointer closure, int *source, XtInputId *id)
1160
if (ispell.right < 0) {
1164
ispell.right = XawTextGetInsertionPoint(ispell.ascii);
1165
ispell.right = XawTextSourceScan(ispell.source, ispell.right,
1166
XawstEOL, XawsdLeft, 1, True);
1167
len = read(ispell.ifd[0], buf, sizeof(buf));
1168
if (strncmp(buf, "@(#)", 4) == 0) {
1171
buf[len - 1] = '\0';
1172
XtSetArg(args[0], XtNtitle, &buf[5]);
1173
XtSetValues(ispell.shell, args, 1);
1176
fprintf(stderr, "Error: is ispell talking with me?\n");
1177
IspellSetTerseMode(ispell.terse_mode);
1178
while (IspellSend() == 0)
1181
else if (ispell.source)
1187
IspellCallback(Widget w, XtPointer client_data, XtPointer call_data)
1191
IspellAction(textwindow, NULL, NULL, &zero);
1196
IspellAction(Widget w, XEvent *event, String *params, Cardinal *num_params)
1200
char **strs, **list;
1202
Bool first_time = InitIspell();
1204
if (*num_params == 1 && (params[0][0] == 'e' || params[0][0] == 'E')) {
1205
PopdownIspell(w, (XtPointer)True, NULL);
1209
if (!XtIsSubclass(w, textWidgetClass) || ispell.source) {
1214
ispell.source = XawTextGetSource(ispell.ascii = w);
1217
/* let the user choose the better position for the ispell window */
1218
Dimension width, height, b_width;
1219
Position x, y, max_x, max_y;
1223
switch (event->type) {
1226
x = event->xbutton.x_root;
1227
y = event->xbutton.y_root;
1231
x = event->xkey.x_root;
1232
y = event->xkey.y_root;
1236
if (x < 0 || y < 0) {
1241
XQueryPointer(XtDisplay(ispell.shell), XtWindow(ispell.shell),
1242
&r, &c, &rx, &ry, &wx, &wy, &mask);
1248
XtSetArg(args[num_args], XtNwidth, &width); num_args++;
1249
XtSetArg(args[num_args], XtNheight, &height); num_args++;
1250
XtSetArg(args[num_args], XtNborderWidth, &b_width); num_args++;
1251
XtGetValues(ispell.shell, args, num_args);
1253
width += b_width << 1;
1254
height += b_width << 1;
1256
x -= (Position)(width >> 1);
1259
if (x > (max_x = (Position)(XtScreen(w)->width - width)))
1262
y -= (Position)(height >> 1);
1265
if (y > (max_y = (Position)(XtScreen(w)->height - height)))
1269
XtSetArg(args[num_args], XtNx, x); num_args++;
1270
XtSetArg(args[num_args], XtNy, y); num_args++;
1271
XtSetValues(ispell.shell, args, num_args);
1275
IspellSetRepeated(False);
1276
ispell.lock = ispell.repeat = ispell.checkit = False;
1279
IspellSetSensitive(True);
1280
XtSetSensitive(ispell.undo, False);
1282
XtSetArg(args[0], XtNlabel, "");
1283
XtSetValues(ispell.word, args, 1);
1285
XtSetArg(args[0], XtNstring, "");
1286
XtSetValues(ispell.text, args, 1);
1288
XtSetArg(args[0], XtNlist, &strs);
1289
XtSetArg(args[1], XtNnumberStrings, &n_strs);
1290
XtGetValues(ispell.list, args, 2);
1292
list = (char**)XtMalloc(sizeof(char**));
1293
list[0] = XtNewString("");
1294
XtSetArg(args[0], XtNlist, list);
1295
XtSetArg(args[1], XtNnumberStrings, 1);
1296
XtSetValues(ispell.list, args, 2);
1298
if (n_strs > 1 || (XtName(ispell.list) != strs[0])) {
1299
while (--n_strs > -1)
1300
XtFree(strs[n_strs]);
1301
XtFree((char*)strs);
1304
IspellSetStatus(ispell.working_label);
1307
(void)IspellStartProcess();
1309
ispell.right = XawTextGetInsertionPoint(ispell.ascii);
1310
ispell.right = XawTextSourceScan(ispell.source, ispell.right,
1311
XawstEOL, XawsdLeft, 1, True);
1312
while (IspellSend() == 0)
1316
XtPopup(ispell.shell, XtGrabExclusive);
1317
XtSetKeyboardFocus(ispell.shell, ispell.text);
1321
IspellStartProcess(void)
1327
ispell.source = XawTextGetSource(ispell.ascii);
1329
len = strlen(ispell.cmd) + strlen(ispell.dictionary) +
1330
strlen(ispell.wchars) + 16;
1331
command = XtMalloc(len);
1332
XmuSnprintf(command, len, "%s -a -d '%s' -w '%s'",
1333
ispell.cmd, ispell.dictionary, ispell.wchars);
1337
if ((ispell.pid = fork()) == 0) {
1340
dup2(ispell.ofd[0], 0);
1341
dup2(ispell.ifd[1], 1);
1342
close(ispell.ofd[0]);
1343
close(ispell.ofd[1]);
1344
close(ispell.ifd[0]);
1345
close(ispell.ifd[1]);
1346
execl("/bin/sh", "sh", "-c", command, (void *)NULL);
1349
else if (ispell.pid < 0) {
1350
fprintf(stderr, "Cannot fork\n");
1353
ispell.buf = XtMalloc(ispell.bufsiz = BUFSIZ);
1355
ispell.id = XtAppAddInput(XtWidgetToApplicationContext(ispell.shell),
1356
ispell.ifd[0], (XtPointer)XtInputReadMask,
1357
IspellInputCallback, NULL);
1358
fcntl(ispell.ifd[0], F_SETFL, O_NONBLOCK);
1368
PopdownIspell(Widget w, XtPointer client_data, XtPointer call_data)
1370
(void)IspellEndProcess((Bool)(long)client_data, True);
1371
XtPopdown(ispell.shell);
1372
*ispell.sentbuf = '\0';
1376
IspellEndProcess(Bool killit, Bool killundo)
1378
ispell.source = NULL;
1381
IgnoreList *il, *pil, *nil;
1384
/* insert added words in private dictionary */
1385
for (i = 0; i < ISTRTBLSZ; i++) {
1386
pil = il = ignore_list[i];
1391
ignore_list[i] = nil;
1394
if (il->add == UNCAP)
1395
write(ispell.ofd[1], "&", 1);
1397
write(ispell.ofd[1], "*", 1);
1398
write(ispell.ofd[1], il->word, strlen(il->word));
1399
write(ispell.ofd[1], "\n", 1);
1409
write(ispell.ofd[1], "#\n", 2); /* save dictionary */
1412
ReplaceList *rl, *prl;
1414
XtRemoveInput(ispell.id);
1416
close(ispell.ofd[0]);
1417
close(ispell.ofd[1]);
1418
close(ispell.ifd[0]);
1419
close(ispell.ifd[1]);
1421
/* if something goes wrong, we don't want to block here forever */
1422
old_timeout = signal(SIGALRM, timeout_signal);
1424
waitpid(ispell.pid, NULL, 0);
1426
signal(SIGALRM, old_timeout);
1433
for (i = 0; i < RSTRTBLSZ; i++) {
1434
prl = rl = replace_list[i];
1438
XtFree(prl->replace);
1442
replace_list[i] = NULL;
1444
for (i = 0; i < ISTRTBLSZ; i++) {
1445
pil = il = ignore_list[i];
1452
ignore_list[i] = NULL;
1457
IspellKillUndoBuffer();
1466
IspellKillUndoBuffer(void)
1468
ispell_undo *undo, *pundo;
1470
undo = pundo = ispell.undo_base;
1473
if (pundo->undo_str)
1474
XtFree(pundo->undo_str);
1475
XtFree((char*)pundo);
1478
ispell.undo_base = ispell.undo_head = NULL;
1479
ispell.undo_for = NULL;
1480
ispell.undo_depth = 0;
1481
XtSetSensitive(ispell.undo, False);
1486
RevertIspell(Widget w, XtPointer client_data, XtPointer call_data)
1489
char *string, *repstr = NULL;
1491
XtSetArg(args[0], XtNlabel, &string);
1492
XtGetValues(ispell.word, args, 1);
1493
if ((repstr = strchr(string, ' ')) != NULL) {
1494
string = repstr = XtNewString(string);
1495
*strchr(repstr, ' ') = '\0';
1497
XtSetArg(args[0], XtNstring, string);
1498
XtSetValues(ispell.text, args, 1);
1505
SelectIspell(Widget w, XtPointer client_data, XtPointer call_data)
1507
XawListReturnStruct *info = (XawListReturnStruct *)call_data;
1510
XtSetArg(args[0], XtNstring, ispell.item = info->string);
1511
XtSetValues(ispell.text, args, 1);
1516
ReplaceIspell(Widget w, XtPointer client_data, XtPointer call_data)
1518
XawTextPosition pos = XawTextGetInsertionPoint(ispell.ascii);
1519
XawTextBlock check, search, replace;
1526
XtSetArg(args[0], XtNlabel, &text);
1527
XtGetValues(ispell.word, args, 1);
1529
search.format = XawFmt8Bit;
1530
search.firstPos = 0;
1531
search.length = ispell.right - pos;
1533
XtSetArg(args[0], XtNstring, &text);
1534
XtGetValues(ispell.text, args, 1);
1536
replace.format = XawFmt8Bit;
1537
replace.firstPos = 0;
1538
replace.length = strlen(text);
1540
if (strcmp(search.ptr, replace.ptr) != 0 &&
1541
XawTextReplace(ispell.ascii, pos, pos + search.length,
1542
&replace) == XawEditDone) {
1543
ispell.right += replace.length - search.length;
1545
ispell.undo_head->undo_str = NULL;
1546
ispell.undo_head->undo_pos = pos;
1547
ispell.undo_head->undo_count = 1;
1549
if (ispell.repeat) {
1550
ispell.undo_head->repeat = 2; /* To recognize later it was replaced */
1551
ispell.undo_head->undo_count = ispell.right;
1552
ispell.undo_head->undo_str = XtNewString(search.ptr);
1554
if (client_data && !ispell.repeat) {
1555
XawTextDisableRedisplay(ispell.ascii);
1557
while ((pos = XawTextSourceSearch(ispell.source, pos, XawsdRight, &search))
1558
!= XawTextSearchError) {
1559
Bool do_replace = True;
1560
char mb[sizeof(wchar_t)];
1562
if (XawTextSourceRead(ispell.source, pos - 1, &check, 1) > 0) {
1563
wctomb(mb, *(wchar_t*)check.ptr);
1564
do_replace = !isalpha(*mb) && *mb && !strchr(ispell.wchars, *mb);
1567
XawTextSourceRead(ispell.source, pos + search.length, &check, 1) > 0) {
1568
wctomb(mb, *(wchar_t*)check.ptr);
1569
do_replace = !isalpha(*mb) && *mb && !strchr(ispell.wchars, *mb);
1572
XawTextReplace(ispell.ascii, pos, pos + search.length, &replace);
1573
++ispell.undo_head->undo_count;
1575
pos += search.length;
1577
XawTextEnableRedisplay(ispell.ascii);
1579
(void)IspellReplacedWord(search.ptr, replace.ptr);
1581
strncpy(&ispell.sentbuf[1], replace.ptr, sizeof(ispell.sentbuf) - 2);
1582
ispell.sentbuf[sizeof(ispell.sentbuf) - 1] = '\0';
1588
ispell.right = ispell.left = XawTextGetInsertionPoint(ispell.ascii);
1589
else if (!ispell.terse_mode || !ispell.item ||
1590
strcmp(ispell.item, replace.ptr))
1591
ispell.right = ispell.left; /* check it again! */
1593
ispell.lock = ispell.checkit = False;
1596
IspellSetStatus(ispell.working_label);
1597
while (IspellSend() == 0)
1603
IgnoreIspell(Widget w, XtPointer client_data, XtPointer call_data)
1611
XtSetArg(args[0], XtNlabel, &text);
1612
XtGetValues(ispell.word, args, 1);
1616
if ((ispell.undo_head->repeat = ispell.repeat) != False) {
1617
ispell.undo_head->undo_count = ispell.right;
1618
ispell.undo_head->undo_str = XtNewString(text);
1621
ispell.undo_head->undo_count = 0;
1623
ispell.undo_head->undo_pos = XawTextGetInsertionPoint(ispell.ascii);
1625
if (!ispell.repeat) {
1627
IspellIgnoredWord(text, ADD, 0);
1628
ispell.undo_head->undo_str = XtNewString(text);
1631
ispell.undo_head->undo_str = NULL;
1634
ispell.lock = ispell.checkit = False;
1637
IspellSetStatus(ispell.working_label);
1638
while (IspellSend() == 0)
1644
AddIspell(Widget w, XtPointer client_data, XtPointer call_data)
1648
int cmd = (long)client_data;
1650
if (!ispell.lock || ispell.repeat)
1653
XtSetArg(args[0], XtNlabel, &text);
1654
XtGetValues(ispell.word, args, 1);
1657
ispell.undo_head->undo_str = XtNewString(text);
1658
ispell.undo_head->undo_pos = XawTextGetInsertionPoint(ispell.ascii);
1659
ispell.undo_head->undo_count = -cmd;
1661
(void)IspellIgnoredWord(text, ADD, cmd);
1663
ispell.lock = ispell.checkit = False;
1665
IspellSetStatus(ispell.working_label);
1666
while (IspellSend() == 0)
1672
UndoIspell(Widget w, XtPointer client_data, XtPointer call_data)
1674
Bool enable_redisplay = False;
1675
ispell_undo *undo = ispell.undo_head;
1677
if ((!ispell.lock && ispell.stat) || !undo)
1680
if (ispell.undo_for && strcmp(ispell.undo_for, ispell.dictionary)) {
1681
XeditPrintf("Undo: Dictionary changed. Undo information was lost.\n");
1682
IspellKillUndoBuffer();
1687
if (undo->terse != ispell.terse_mode)
1688
IspellSetTerseMode(undo->terse);
1690
if (undo->format != ispell.format_info->value) {
1691
struct _ispell_format *fmt = &ispell_format[undo->format];
1692
ChangeFormatIspell(fmt->sme, (XtPointer)fmt, NULL);
1695
if (undo->undo_count > 0 && !undo->repeat) {
1696
XawTextPosition tmp;
1698
enable_redisplay = undo->undo_count > 1;
1699
if (enable_redisplay)
1700
XawTextDisableRedisplay(ispell.ascii);
1701
while (undo->undo_count--)
1702
if (!_XawTextSrcUndo((TextSrcObject)ispell.source, &tmp)) {
1707
else if (undo->undo_count < 0) {
1709
(void)IspellIgnoredWord(undo->undo_str, REMOVE, -undo->undo_count);
1711
else if (undo->undo_str) {
1713
IspellIgnoredWord(undo->undo_str, REMOVE, 0);
1716
XawTextSetInsertionPoint(ispell.ascii,
1717
ispell.right = ispell.left = undo->undo_pos);
1718
if (enable_redisplay)
1719
XawTextEnableRedisplay(ispell.ascii);
1721
/* need to do it because may be two misspelled words together */
1723
char **list, **old_list;
1727
if (undo->repeat > 1) {
1728
XawTextDisableRedisplay(ispell.ascii);
1729
if (!_XawTextSrcUndo((TextSrcObject)ispell.source, &ispell.right))
1731
XawTextEnableRedisplay(ispell.ascii);
1734
ispell.right = (XawTextPosition)undo->undo_count;
1735
IspellSetRepeated(ispell.repeat = True);
1736
XtSetArg(args[0], XtNlabel, undo->undo_str);
1737
XtSetValues(ispell.word, args, 1);
1738
XmuSnprintf(ispell.sentbuf, sizeof(ispell.sentbuf), "^%s",
1739
strrchr(undo->undo_str, ' ') + 1);
1740
strcpy(ispell.sendbuf, ispell.sentbuf);
1741
XtSetArg(args[0], XtNstring, &ispell.sentbuf[1]);
1742
XtSetValues(ispell.text, args, 1);
1744
XtSetArg(args[0], XtNlist, &old_list);
1745
XtSetArg(args[1], XtNnumberStrings, &old_len);
1746
XtGetValues(ispell.list, args, 2);
1748
list = (char **)XtMalloc(sizeof(char*));
1749
list[0] = XtNewString(&ispell.sentbuf[1]);
1750
XtSetArg(args[0], XtNlist, list);
1751
XtSetArg(args[1], XtNnumberStrings, 1);
1752
XtSetValues(ispell.list, args, 2);
1753
XtSetSensitive(ispell.list, True);
1754
XawListHighlight(ispell.list, 0);
1756
if (old_len > 1 || (XtName(ispell.list) != old_list[0])) {
1757
while (--old_len > -1)
1758
XtFree(old_list[old_len]);
1759
XtFree((char*)old_list);
1762
IspellSetSelection(ispell.left, ispell.right);
1763
IspellSetStatus(ispell.repeat_label);
1765
ispell.checkit = False;
1767
else if (ispell.repeat) {
1768
*ispell.sentbuf = '\0';
1769
IspellSetRepeated(ispell.repeat = False);
1773
undo->prev->next = NULL;
1774
ispell.undo_head = undo->prev;
1775
if (undo == ispell.undo_base) {
1776
ispell.undo_base = NULL;
1777
ispell.undo_for = NULL;
1778
XtSetSensitive(ispell.undo, False);
1781
XtFree(undo->undo_str);
1782
XtFree((char*)undo);
1783
--ispell.undo_depth;
1785
if (!ispell.stat || ispell.checkit)
1786
IspellSetSensitive(True);
1788
if (!ispell.repeat) {
1789
ispell.lock = ispell.checkit = False;
1791
IspellSetStatus(ispell.working_label);
1792
while (IspellSend() == 0)
1799
CheckIspell(Widget w, XtPointer client_data, XtPointer call_data)
1802
char *text, *str, string[1024];
1808
XtSetArg(args[0], XtNstring, &text);
1809
XtGetValues(ispell.text, args, 1);
1811
/* Check only a word at a time */
1815
if (isalpha(*str) || strchr(ispell.wchars, *str))
1822
if (isalpha(*str) || strchr(ispell.wchars, *str))
1823
string[i++] = *str++;
1829
if (strcmp(text, string)) {
1830
XawTextPosition pos = XawTextGetInsertionPoint(ispell.text) - len;
1832
XtSetArg(args[0], XtNstring, string);
1833
XtSetValues(ispell.text, args, 1);
1834
XawTextSetInsertionPoint(ispell.text, pos);
1843
len = XmuSnprintf(ispell.sendbuf, sizeof(ispell.sendbuf), "^%s\n", string);
1845
ispell.sendbuf[sizeof(ispell.sendbuf) - 1] = '\n';
1847
write(ispell.ofd[1], ispell.sendbuf, len);
1849
ispell.lock = False;
1850
ispell.checkit = True;
1851
ispell.stat = RECEIVE;
1856
LookIspell(Widget w, XtPointer client_data, XtPointer call_data)
1861
char *text, *str, **list, **old_list, command[1024], buffer[1024];
1862
Bool sensitive = True;
1867
XtSetArg(args[0], XtNstring, &text);
1868
XtGetValues(ispell.text, args, 1);
1875
if (strlen(ispell.look_cmd) + strlen(text) + strlen(ispell.words_file) + 8
1876
> sizeof(command) - 1) {
1877
fprintf(stderr, "Command line too large\n");
1881
XmuSnprintf(command, sizeof(command), "%s '^%s.*$' %s",
1882
ispell.look_cmd, text, ispell.words_file);
1884
if ((fd = popen(command, "r")) == NULL) {
1885
fprintf(stderr, "Cannot popen '%s'\n", ispell.look_cmd);
1892
#define MAX_LOOK_RESULTS 256
1893
while (fgets(buffer, sizeof(buffer), fd) != NULL) {
1894
if ((str = strchr(buffer, '\n')) == NULL) {
1895
fprintf(stderr, "String is too large\n");
1899
if ((len % 16) == 0)
1900
list = (char**)XtRealloc((char*)list, sizeof(char*) * (len + 16));
1901
list[len] = XtNewString(buffer);
1902
if (++len >= MAX_LOOK_RESULTS) {
1907
#undef MAX_LOOK_RESULTS
1909
XtSetArg(args[0], XtNlist, &old_list);
1910
XtSetArg(args[1], XtNnumberStrings, &old_len);
1911
XtGetValues(ispell.list, args, 2);
1914
list = (char**)XtMalloc(sizeof(char*));
1915
list[0] = XtNewString("");
1920
XtSetArg(args[0], XtNlist, list);
1921
XtSetArg(args[1], XtNnumberStrings, len);
1922
XtSetValues(ispell.list, args, 2);
1924
XtSetSensitive(ispell.list, sensitive);
1925
IspellSetStatus(sensitive ? ispell.look_label : ispell.none_label);
1927
if (old_len > 1 || (XtName(ispell.list) != old_list[0])) {
1928
while (--old_len > -1)
1929
XtFree(old_list[old_len]);
1930
XtFree((char*)old_list);
1938
ToggleTerseIspell(Widget w, XtPointer client_data, XtPointer call_data)
1943
ispell.terse_mode = !ispell.terse_mode;
1944
write(ispell.ofd[1], ispell.terse_mode ? "!\n" : "%\n", 2);
1949
ChangeDictionaryIspell(Widget w, XtPointer client_data, XtPointer call_data)
1951
ispell_dict *tmp, *dic = (ispell_dict*)client_data;
1952
XawTextPosition pos = XawTextGetInsertionPoint(ispell.ascii);
1953
XawTextPosition right = ispell.right;
1956
if (strcmp(XtName(dic->sme), ispell.dictionary) == 0)
1964
for (tmp = ispell.dict_info; tmp; tmp = tmp->next)
1965
if (strcmp(XtName(tmp->sme), ispell.dictionary) == 0) {
1966
XtSetArg(args[0], XtNleftBitmap, None);
1967
XtSetValues(tmp->sme, args, 1);
1970
if (ispell.undo_base && !ispell.undo_for)
1971
ispell.undo_for = ispell.dictionary;
1973
XtSetArg(args[0], XtNleftBitmap, flist.pixmap);
1974
XtSetValues(dic->sme, args, 1);
1975
ispell.dictionary = XtName(dic->sme);
1976
ispell.wchars = dic->wchars;
1977
XtSetArg(args[0], XtNlabel, XtName(dic->sme));
1978
XtSetValues(ispell.dict, args, 1);
1980
IspellSetStatus(ispell.working_label);
1982
(void)IspellEndProcess(True, False);
1983
ispell.lock = ispell.checkit = False;
1984
(void)IspellStartProcess();
1986
ispell.stat = RECEIVE;
1988
/* restart at the same selected word */
1989
if (ispell.repeat == False)
1990
ispell.left = ispell.right = pos;
1992
ispell.right = right;
1997
ChangeFormatIspell(Widget w, XtPointer client_data, XtPointer call_data)
1999
struct _ispell_format *fmt = (struct _ispell_format*)client_data;
2002
if (strcmp(fmt->name, ispell.formatting) == 0)
2010
XtSetArg(args[0], XtNleftBitmap, None);
2011
XtSetValues(ispell.format_info->sme, args, 1);
2013
XtSetArg(args[0], XtNleftBitmap, flist.pixmap);
2014
XtSetValues(fmt->sme, args, 1);
2015
ispell.formatting = fmt->name;
2016
ispell.format_info = fmt;
2017
XtSetArg(args[0], XtNlabel, fmt->name);
2018
XtSetValues(ispell.format, args, 1);
2026
XtResource dict_res;
2028
static XtResource text_res[] = {
2029
{"skipLines", "Skip", XtRString, sizeof(char*),
2030
XtOffsetOf(struct _ispell, skip), XtRString, "#"},
2036
ispell.shell = XtCreatePopupShell("ispell", transientShellWidgetClass,
2037
topwindow, NULL, 0);
2039
XtGetApplicationResources(ispell.shell, (XtPointer)&ispell, resources,
2040
XtNumber(resources), NULL, 0);
2042
ispell.form = XtCreateManagedWidget("form", formWidgetClass,
2043
ispell.shell, NULL, 0);
2044
ispell.mispelled = XtCreateManagedWidget("mispelled", labelWidgetClass,
2045
ispell.form, NULL, 0);
2046
ispell.repeated = XtCreateWidget("repeated", labelWidgetClass,
2047
ispell.form, NULL, 0);
2048
ispell.word = XtCreateManagedWidget("word", commandWidgetClass,
2049
ispell.form, NULL, 0);
2050
XtAddCallback(ispell.word, XtNcallback, RevertIspell, NULL);
2051
ispell.replacement = XtCreateManagedWidget("replacement", labelWidgetClass,
2052
ispell.form, NULL, 0);
2053
ispell.text = XtVaCreateManagedWidget("text", asciiTextWidgetClass,
2055
XtNeditType, XawtextEdit,
2057
ispell.suggestions = XtCreateManagedWidget("suggestions", labelWidgetClass,
2058
ispell.form, NULL, 0);
2059
ispell.viewport = XtCreateManagedWidget("viewport", viewportWidgetClass,
2060
ispell.form, NULL, 0);
2061
ispell.list = XtCreateManagedWidget("list", listWidgetClass,
2062
ispell.viewport, NULL, 0);
2063
XtAddCallback(ispell.list, XtNcallback, SelectIspell, NULL);
2064
ispell.commands = XtCreateManagedWidget("commands", formWidgetClass,
2065
ispell.form, NULL, 0);
2066
ispell.check = XtCreateManagedWidget("check", commandWidgetClass,
2067
ispell.commands, NULL, 0);
2068
XtAddCallback(ispell.check, XtNcallback, CheckIspell, NULL);
2069
ispell.look = XtCreateManagedWidget("look", commandWidgetClass,
2070
ispell.commands, NULL, 0);
2071
XtAddCallback(ispell.look, XtNcallback, LookIspell, NULL);
2072
ispell.undo = XtCreateManagedWidget("undo", commandWidgetClass,
2073
ispell.commands, NULL, 0);
2074
XtAddCallback(ispell.undo, XtNcallback, UndoIspell, NULL);
2075
ispell.replace = XtCreateManagedWidget("replace", commandWidgetClass,
2076
ispell.commands, NULL, 0);
2077
XtAddCallback(ispell.replace, XtNcallback, ReplaceIspell, (XtPointer)False);
2078
ispell.replaceAll = XtCreateManagedWidget("replaceAll", commandWidgetClass,
2079
ispell.commands, NULL, 0);
2080
XtAddCallback(ispell.replaceAll, XtNcallback, ReplaceIspell, (XtPointer)True);
2081
ispell.ignore = XtCreateManagedWidget("ignore", commandWidgetClass,
2082
ispell.commands, NULL, 0);
2083
XtAddCallback(ispell.ignore, XtNcallback, IgnoreIspell, (XtPointer)False);
2084
ispell.ignoreAll = XtCreateManagedWidget("ignoreAll", commandWidgetClass,
2085
ispell.commands, NULL, 0);
2086
XtAddCallback(ispell.ignoreAll, XtNcallback, IgnoreIspell, (XtPointer)True);
2087
ispell.add = XtCreateManagedWidget("add", commandWidgetClass,
2088
ispell.commands, NULL, 0);
2089
XtAddCallback(ispell.add, XtNcallback, AddIspell, (XtPointer)ASIS);
2090
ispell.addUncap = XtCreateManagedWidget("addUncap", commandWidgetClass,
2091
ispell.commands, NULL, 0);
2092
XtAddCallback(ispell.addUncap, XtNcallback, AddIspell, (XtPointer)UNCAP);
2093
ispell.suspend = XtCreateManagedWidget("suspend", commandWidgetClass,
2094
ispell.commands, NULL, 0);
2095
XtAddCallback(ispell.suspend, XtNcallback, PopdownIspell, (XtPointer)False);
2096
ispell.cancel = XtCreateManagedWidget("cancel", commandWidgetClass,
2097
ispell.commands, NULL, 0);
2098
XtAddCallback(ispell.cancel, XtNcallback, PopdownIspell, (XtPointer)True);
2099
ispell.terse = XtVaCreateManagedWidget("terse", toggleWidgetClass,
2101
XtNstate, ispell.terse_mode,
2103
XtAddCallback(ispell.terse, XtNcallback, ToggleTerseIspell, NULL);
2104
ispell.status = XtCreateManagedWidget("status", labelWidgetClass,
2105
ispell.form, NULL, 0);
2106
ispell.options = XtCreateManagedWidget("options", formWidgetClass,
2107
ispell.form, NULL, 0);
2108
ispell.dict = XtVaCreateManagedWidget("dict", menuButtonWidgetClass,
2110
XtNmenuName, "dictionaries",
2112
ispell.dictMenu = XtCreatePopupShell("dictionaries", simpleMenuWidgetClass,
2113
ispell.options, NULL, 0);
2114
XtRealizeWidget(ispell.dictMenu);
2116
ispell.format = XtVaCreateManagedWidget("format", menuButtonWidgetClass,
2118
XtNmenuName, "formats",
2120
ispell.formatMenu = XtCreatePopupShell("formats", simpleMenuWidgetClass,
2121
ispell.options, NULL, 0);
2122
XtRealizeWidget(ispell.formatMenu);
2124
XtRealizeWidget(ispell.shell);
2126
for (i = 0; i < sizeof(ispell_format) / sizeof(ispell_format[0]); i++) {
2127
struct _ispell_format *fmt = &ispell_format[i];
2129
fmt->sme = XtCreateManagedWidget(fmt->name, smeBSBObjectClass,
2130
ispell.formatMenu, NULL, 0);
2131
XtAddCallback(fmt->sme, XtNcallback, ChangeFormatIspell, (XtPointer)fmt);
2133
if (strcmp(fmt->name, ispell.formatting) == 0) {
2136
XtSetArg(args[0], XtNlabel, ispell.formatting);
2137
XtSetValues(ispell.format, args, 1);
2138
XtSetArg(args[0], XtNleftBitmap, flist.pixmap);
2139
XtSetValues(fmt->sme, args, 1);
2140
ispell.format_info = fmt;
2143
if (ispell.format_info == NULL) {
2147
ispell.format_info = &ispell_format[TEXT];
2149
XmuSnprintf(msg, sizeof(msg),
2150
"Unrecognized formatting type \"%s\", will use \"%s\"",
2151
ispell.formatting, ispell.format_info->name);
2152
XtAppWarning(XtWidgetToApplicationContext(ispell.shell), msg);
2153
ispell.formatting = ispell.format_info->name;
2155
XtSetArg(args[0], XtNlabel, ispell.format_info->name);
2156
XtSetValues(ispell.format, args, 1);
2157
XtSetArg(args[0], XtNleftBitmap, flist.pixmap);
2158
XtSetValues(ispell.format_info->sme, args, 1);
2160
XtGetApplicationResources(ispell_format[TEXT].sme, (XtPointer)&ispell,
2161
text_res, XtNumber(text_res), NULL, 0);
2163
dict_res.resource_name = "wordChars";
2164
dict_res.resource_class = "Chars";
2165
dict_res.resource_type = XtRString;
2166
dict_res.resource_size = sizeof(char*);
2167
dict_res.resource_offset = XtOffsetOf(ispell_dict, wchars);
2168
dict_res.default_type = XtRString;
2169
dict_res.default_addr = "";
2171
list = XtNewString(ispell.dict_list);
2172
for (str = strtok(list, " \t,"); str; str = strtok(NULL, " \t,")) {
2173
ispell_dict *dic = XtNew(ispell_dict);
2175
dic->sme = XtCreateManagedWidget(str, smeBSBObjectClass,
2176
ispell.dictMenu, NULL, 0);
2177
XtGetApplicationResources(dic->sme, (XtPointer)dic, &dict_res,
2179
XtAddCallback(dic->sme, XtNcallback, ChangeDictionaryIspell,
2182
if (!ispell.dict_info)
2183
ispell.dict_info = dic;
2185
ispell_dict *tmp = ispell.dict_info;
2187
for (; tmp->next; tmp = tmp->next)
2191
if (strcmp(str, ispell.dictionary) == 0) {
2194
XtSetArg(args[0], XtNleftBitmap, flist.pixmap);
2195
XtSetValues(dic->sme, args, 1);
2196
XtSetArg(args[0], XtNlabel, str);
2197
XtSetValues(ispell.dict, args, 1);
2198
ispell.wchars = dic->wchars;
2203
delete_window = XInternAtom(XtDisplay(ispell.shell), "WM_DELETE_WINDOW", False);
2204
XSetWMProtocols(XtDisplay(ispell.shell), XtWindow(ispell.shell), &delete_window, 1);