Mercurial > pidgin
annotate src/gtkspell.c @ 2906:538c58b43eff
[gaim-migrate @ 2919]
save
save me from this
wandered around the town
all the thousand things
i might miss
and you
think we'll suffer much
think we'll close our eyes
just to see the light
pass us by
with tomorrow coming
hope that i don't let you
down again
said i'm so glad to be here
does it mean a thing
if only i could breathe what you breathe
if only i could see what you see
sit
we'll take our time
watching the flowers grow
all the friends we've known
say goodbye
and you
did you suffer much
did you close your eyes
just to see the night
rush on by
gathered all around you
hope that we don't let you
down again
i said i'm so glad to be here
does it mean a thing
if only i could breathe what you breathe
if only i could see what you see
i said i'm so glad to be here
does it mean a thing
if only i could breathe what you breathe
if only i could see what you see
if only i could just believe a thing
--Moist, "Breathe" (as transcribed by http://www.veddma.com/veddma/moist.htm)
Patches from:
Ari Pollak
Ben Miller
Mark Doliner
Sean Egan
Vincas Ciziunas
Thanks everyone.
Somewhere in the middle of all of this it started to get really tedious and annoying. I think it's getting close to the point where I quit.
committer: Tailor Script <tailor@pidgin.im>
author | Eric Warmenhoven <eric@warmenhoven.org> |
---|---|
date | Fri, 21 Dec 2001 10:23:04 +0000 |
parents | 4c6ad3d9db3f |
children | da324fe688b3 |
rev | line source |
---|---|
1117 | 1 /* gtkspell - a spell-checking addon for GtkText |
2 * Copyright (c) 2000 Evan Martin. | |
3 * vim: ts=4 sw=4 | |
4 * This library is free software; you can redistribute it and/or | |
5 * modify it under the terms of the GNU Lesser General Public | |
6 * License as published by the Free Software Foundation; either | |
7 * version 2 of the License, or (at your option) any later version. | |
8 * | |
9 * This library is distributed in the hope that it will be useful, | |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
12 * Lesser General Public License for more details. | |
13 * | |
14 * You should have received a copy of the GNU Lesser General Public | |
15 * License along with this library; if not, write to the Free Software | |
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
17 */ | |
18 | |
19 #include <gtk/gtk.h> | |
20 | |
21 #include <sys/types.h> | |
22 #include <sys/wait.h> | |
23 #include <sys/time.h> | |
24 #include <unistd.h> | |
25 #include <stdio.h> | |
26 #include <signal.h> | |
27 #include <ctype.h> | |
28 #include <string.h> | |
29 #include <stdlib.h> | |
30 #include <errno.h> | |
31 | |
32 /* TODO: | |
33 * handle dictionary changes | |
34 * asynchronous lookups | |
35 */ | |
36 | |
37 /* size of the text buffer used in various word-processing routines. */ | |
2454
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
38 /* #define BUFSIZE 1024 */ |
1117 | 39 /* number of suggestions to display on each menu. */ |
40 #define MENUCOUNT 10 | |
41 #define BUGEMAIL "gtkspell-devel@lists.sourceforge.net" | |
42 | |
43 /* because we keep only one copy of the spell program running, | |
44 * all ispell-related variables can be static. | |
45 */ | |
46 static pid_t spell_pid = -1; | |
1496
d33bf6548543
[gaim-migrate @ 1506]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1467
diff
changeset
|
47 static int fd_write[2] = {0}, fd_read[2] = {0}; |
1117 | 48 static int signal_set_up = 0; |
49 | |
50 /* FIXME? */ | |
51 static GdkColor highlight = { 0, 255*256, 0, 0 }; | |
52 | |
53 static void entry_insert_cb(GtkText *gtktext, | |
54 gchar *newtext, guint len, guint *ppos, gpointer d); | |
55 static void set_up_signal(); | |
56 | |
57 int gtkspell_running() { | |
58 return (spell_pid > 0); | |
59 } | |
60 | |
1794
60b3fd819cce
[gaim-migrate @ 1804]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1496
diff
changeset
|
61 /* |
1117 | 62 static void error_print(const char *fmt, ...) { |
63 va_list ap; | |
64 va_start(ap, fmt); | |
65 fprintf(stderr, "gtkspell: "); | |
66 vfprintf(stderr, fmt, ap); | |
67 va_end(ap); | |
68 } | |
1794
60b3fd819cce
[gaim-migrate @ 1804]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1496
diff
changeset
|
69 */ |
1815
f15d449b3167
[gaim-migrate @ 1825]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1794
diff
changeset
|
70 extern void debug_printf(char *, ...); |
1794
60b3fd819cce
[gaim-migrate @ 1804]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1496
diff
changeset
|
71 #define error_print debug_printf |
1117 | 72 |
73 /* functions to interface with pipe */ | |
74 static void writetext(char *text) { | |
75 write(fd_write[1], text, strlen(text)); | |
76 } | |
2454
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
77 |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
78 static char *readline() { |
2670
f6f2871d77c2
[gaim-migrate @ 2683]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2517
diff
changeset
|
79 static gchar *buf = NULL; |
f6f2871d77c2
[gaim-migrate @ 2683]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2517
diff
changeset
|
80 char *end; |
f6f2871d77c2
[gaim-migrate @ 2683]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2517
diff
changeset
|
81 char *ret; |
f6f2871d77c2
[gaim-migrate @ 2683]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2517
diff
changeset
|
82 char *tmp; |
f6f2871d77c2
[gaim-migrate @ 2683]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2517
diff
changeset
|
83 |
f6f2871d77c2
[gaim-migrate @ 2683]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2517
diff
changeset
|
84 /* read until we get a newline */ |
f6f2871d77c2
[gaim-migrate @ 2683]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2517
diff
changeset
|
85 while (!buf || (end = strchr(buf, '\n')) == NULL) { |
f6f2871d77c2
[gaim-migrate @ 2683]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2517
diff
changeset
|
86 char space[1024]; |
f6f2871d77c2
[gaim-migrate @ 2683]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2517
diff
changeset
|
87 int ret = read(fd_read[0], space, 1023); |
2727
4c6ad3d9db3f
[gaim-migrate @ 2740]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2725
diff
changeset
|
88 if (ret <= 0) { |
2454
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
89 error_print("read: %s\n", strerror(errno)); |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
90 return NULL; |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
91 } |
2670
f6f2871d77c2
[gaim-migrate @ 2683]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2517
diff
changeset
|
92 space[ret] = 0; |
f6f2871d77c2
[gaim-migrate @ 2683]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2517
diff
changeset
|
93 if (buf) { |
f6f2871d77c2
[gaim-migrate @ 2683]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2517
diff
changeset
|
94 tmp = buf; |
f6f2871d77c2
[gaim-migrate @ 2683]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2517
diff
changeset
|
95 buf = g_strconcat(tmp, space, NULL); |
f6f2871d77c2
[gaim-migrate @ 2683]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2517
diff
changeset
|
96 g_free(tmp); |
f6f2871d77c2
[gaim-migrate @ 2683]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2517
diff
changeset
|
97 } else |
f6f2871d77c2
[gaim-migrate @ 2683]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2517
diff
changeset
|
98 buf = g_strdup(space); |
f6f2871d77c2
[gaim-migrate @ 2683]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2517
diff
changeset
|
99 } |
f6f2871d77c2
[gaim-migrate @ 2683]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2517
diff
changeset
|
100 |
f6f2871d77c2
[gaim-migrate @ 2683]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2517
diff
changeset
|
101 /* we got a newline, and end points to it. |
f6f2871d77c2
[gaim-migrate @ 2683]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2517
diff
changeset
|
102 * copy out the data, reset buf, return */ |
2454
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
103 |
2670
f6f2871d77c2
[gaim-migrate @ 2683]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2517
diff
changeset
|
104 if (end[1] == 0) { |
f6f2871d77c2
[gaim-migrate @ 2683]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2517
diff
changeset
|
105 /* only one line is in the buffer */ |
f6f2871d77c2
[gaim-migrate @ 2683]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2517
diff
changeset
|
106 ret = buf; |
f6f2871d77c2
[gaim-migrate @ 2683]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2517
diff
changeset
|
107 buf = NULL; |
f6f2871d77c2
[gaim-migrate @ 2683]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2517
diff
changeset
|
108 return ret; |
f6f2871d77c2
[gaim-migrate @ 2683]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2517
diff
changeset
|
109 } |
f6f2871d77c2
[gaim-migrate @ 2683]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2517
diff
changeset
|
110 |
f6f2871d77c2
[gaim-migrate @ 2683]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2517
diff
changeset
|
111 ret = g_strndup(buf, end - buf + 1); |
f6f2871d77c2
[gaim-migrate @ 2683]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2517
diff
changeset
|
112 tmp = buf; |
f6f2871d77c2
[gaim-migrate @ 2683]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2517
diff
changeset
|
113 buf = g_strdup(end + 1); |
f6f2871d77c2
[gaim-migrate @ 2683]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2517
diff
changeset
|
114 g_free(tmp); |
f6f2871d77c2
[gaim-migrate @ 2683]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2517
diff
changeset
|
115 |
f6f2871d77c2
[gaim-migrate @ 2683]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2517
diff
changeset
|
116 return ret; |
2454
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
117 } |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
118 |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
119 static char *readresponse() { |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
120 char *r1, *r2, *result; |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
121 |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
122 r1 = readline(); |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
123 if (!r1) |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
124 return NULL; |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
125 if (*r1 == '\n') { |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
126 g_strchomp(r1); |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
127 return r1; |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
128 } |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
129 r2 = readline(); |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
130 if (!r2) { |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
131 g_free(r1); |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
132 return NULL; |
1117 | 133 } |
134 | |
2454
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
135 while (r2 && *r2 != '\n') { |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
136 char *tmp = r1; |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
137 r1 = g_strconcat(tmp, r2, NULL); |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
138 g_free(tmp); |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
139 g_free(r2); |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
140 r2 = readline(); |
1117 | 141 } |
142 | |
2454
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
143 if (!r2) { |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
144 g_free(r1); |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
145 return NULL; |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
146 } |
1117 | 147 |
2454
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
148 result = g_strconcat(r1, r2, NULL); |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
149 g_free(r1); |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
150 g_free(r2); |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
151 g_strchomp(result); |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
152 return result; |
1117 | 153 } |
154 | |
155 | |
156 void gtkspell_stop() { | |
157 if (gtkspell_running()) { | |
1415
3dfd2a83fb5e
[gaim-migrate @ 1425]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1127
diff
changeset
|
158 kill(spell_pid, SIGHUP); |
1496
d33bf6548543
[gaim-migrate @ 1506]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1467
diff
changeset
|
159 spell_pid = 0; |
d33bf6548543
[gaim-migrate @ 1506]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1467
diff
changeset
|
160 close(fd_read[0]); |
d33bf6548543
[gaim-migrate @ 1506]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1467
diff
changeset
|
161 close(fd_write[1]); |
1117 | 162 } |
163 } | |
164 | |
165 int gtkspell_start(char *path, char * args[]) { | |
166 int fd_error[2]; | |
167 | |
168 if (gtkspell_running()) { | |
169 error_print("gtkspell_start called while already running.\n"); | |
170 gtkspell_stop(); | |
171 } | |
172 | |
173 if (!signal_set_up) { | |
174 set_up_signal(); | |
175 signal_set_up = 1; | |
176 } | |
177 | |
178 pipe(fd_write); | |
179 pipe(fd_read); | |
180 pipe(fd_error); | |
181 | |
182 spell_pid = fork(); | |
183 if (spell_pid < 0) { | |
184 error_print("fork: %s\n", strerror(errno)); | |
185 return -1; | |
186 } else if (spell_pid == 0) { | |
187 dup2(fd_write[0], 0); | |
1496
d33bf6548543
[gaim-migrate @ 1506]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1467
diff
changeset
|
188 close(fd_write[0]); |
d33bf6548543
[gaim-migrate @ 1506]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1467
diff
changeset
|
189 close(fd_write[1]); |
d33bf6548543
[gaim-migrate @ 1506]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1467
diff
changeset
|
190 |
1117 | 191 dup2(fd_read[1], 1); |
192 close(fd_read[0]); | |
1496
d33bf6548543
[gaim-migrate @ 1506]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1467
diff
changeset
|
193 close(fd_read[1]); |
d33bf6548543
[gaim-migrate @ 1506]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1467
diff
changeset
|
194 |
d33bf6548543
[gaim-migrate @ 1506]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1467
diff
changeset
|
195 dup2(fd_error[1], 2); |
1117 | 196 close(fd_error[0]); |
1496
d33bf6548543
[gaim-migrate @ 1506]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1467
diff
changeset
|
197 close(fd_error[1]); |
1117 | 198 |
199 if (path == NULL) { | |
200 if (execvp(args[0], args) < 0) | |
201 error_print("execvp('%s'): %s\n", args[0], strerror(errno)); | |
202 } else { | |
203 if (execv(path, args) < 0) | |
204 error_print("execv('%s'): %s\n", path, strerror(errno)); | |
205 } | |
206 /* if we get here, we failed. | |
207 * send some text on the pipe to indicate status. | |
208 */ | |
1496
d33bf6548543
[gaim-migrate @ 1506]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1467
diff
changeset
|
209 write(0, "!", 1); /* stdout _is_ the pipe. */ |
1117 | 210 |
211 _exit(0); | |
212 } else { | |
213 /* there are at least two ways to fail: | |
214 * - the exec() can fail | |
215 * - the exec() can succeed, but the program can dump the help screen | |
216 * we must check for both. | |
217 */ | |
218 fd_set rfds; | |
219 struct timeval tv; | |
2454
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
220 char *buf; |
1117 | 221 |
1496
d33bf6548543
[gaim-migrate @ 1506]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1467
diff
changeset
|
222 close(fd_write[0]); |
d33bf6548543
[gaim-migrate @ 1506]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1467
diff
changeset
|
223 close(fd_read[1]); |
d33bf6548543
[gaim-migrate @ 1506]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1467
diff
changeset
|
224 |
1117 | 225 FD_ZERO(&rfds); |
226 FD_SET(fd_error[0], &rfds); | |
227 FD_SET(fd_read[0], &rfds); | |
228 tv.tv_sec = 2; | |
229 tv.tv_usec = 0; | |
1496
d33bf6548543
[gaim-migrate @ 1506]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1467
diff
changeset
|
230 |
1117 | 231 if (select(MAX(fd_error[0], fd_read[0])+1, |
232 &rfds, NULL, NULL, &tv) < 0) { | |
233 /* FIXME: is this needed? */ | |
234 error_print("Timed out waiting for spell command.\n"); | |
235 gtkspell_stop(); | |
236 return -1; | |
237 } | |
238 | |
239 if (FD_ISSET(fd_error[0], &rfds)) { /* stderr readable? */ | |
240 error_print("Spell command printed on stderr -- probably failed.\n"); | |
241 gtkspell_stop(); | |
242 return -1; | |
243 } | |
244 | |
1496
d33bf6548543
[gaim-migrate @ 1506]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1467
diff
changeset
|
245 /* we're done with stderr, now. */ |
d33bf6548543
[gaim-migrate @ 1506]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1467
diff
changeset
|
246 close(fd_error[0]); |
d33bf6548543
[gaim-migrate @ 1506]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1467
diff
changeset
|
247 close(fd_error[1]); |
d33bf6548543
[gaim-migrate @ 1506]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1467
diff
changeset
|
248 |
1117 | 249 /* otherwise, fd_read[0] is set. */ |
2454
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
250 buf = readline(); |
1117 | 251 |
252 /* ispell should print something like this: | |
253 * @(#) International Ispell Version 3.1.20 10/10/95 | |
254 * if it doesn't, it's an error. */ | |
2454
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
255 if (!buf || buf[0] != '@') { |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
256 if (buf) |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
257 g_free(buf); |
1117 | 258 gtkspell_stop(); |
259 return -1; | |
260 } | |
2454
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
261 g_free(buf); |
1117 | 262 } |
263 | |
264 /* put ispell into terse mode. | |
265 * this makes it not respond on correctly spelled words. */ | |
2454
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
266 writetext("!\n"); |
1117 | 267 return 0; |
268 } | |
269 | |
270 static GList* misspelled_suggest(char *word) { | |
2454
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
271 char *buf; |
1117 | 272 char *newword; |
273 GList *l = NULL; | |
274 int count; | |
275 | |
2461
0edec72bc72f
[gaim-migrate @ 2474]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2457
diff
changeset
|
276 if (!word) |
0edec72bc72f
[gaim-migrate @ 2474]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2457
diff
changeset
|
277 return NULL; |
0edec72bc72f
[gaim-migrate @ 2474]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2457
diff
changeset
|
278 |
2454
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
279 buf = g_strdup_printf("^%s\n", word); /* guard against ispell control chars */ |
1117 | 280 writetext(buf); |
2454
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
281 g_free(buf); |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
282 buf = readresponse(); |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
283 |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
284 if (!buf) |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
285 return NULL; |
1117 | 286 |
287 switch (buf[0]) { /* first char is ispell command. */ | |
288 case 0: /* no response: word is ok. */ | |
2454
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
289 g_free(buf); |
1117 | 290 return NULL; |
291 case '&': /* misspelled, with suggestions */ | |
292 /* & <orig> <count> <ofs>: <miss>, <miss>, <guess>, ... */ | |
293 strtok(buf, " "); /* & */ | |
294 newword = strtok(NULL, " "); /* orig */ | |
295 l = g_list_append(l, g_strdup(newword)); | |
296 newword = strtok(NULL, " "); /* count */ | |
297 count = atoi(newword); | |
298 strtok(NULL, " "); /* ofs: */ | |
299 | |
300 while ((newword = strtok(NULL, ",")) != NULL) { | |
301 int len = strlen(newword); | |
302 if (newword[len-1] == ' ' || newword[len-1] == '\n') | |
303 newword[len-1] = 0; | |
304 if (count == 0) { | |
305 g_list_append(l, NULL); /* signal the "suggestions" */ | |
306 } | |
307 /* add it to the list, skipping the initial space. */ | |
308 l = g_list_append(l, | |
309 g_strdup(newword[0] == ' ' ? newword+1 : newword)); | |
310 | |
311 count--; | |
312 } | |
2454
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
313 g_free(buf); |
1117 | 314 return l; |
315 | |
316 case '#': /* misspelled, no suggestions */ | |
1467
7f7857c5036e
[gaim-migrate @ 1477]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1415
diff
changeset
|
317 case '?': /* ispell is guessing. */ |
1117 | 318 /* # <orig> <ofs> */ |
319 strtok(buf, " "); /* & */ | |
320 newword = strtok(NULL, " "); /* orig */ | |
321 l = g_list_append(l, g_strdup(newword)); | |
2454
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
322 g_free(buf); |
1117 | 323 return l; |
324 default: | |
325 error_print("Unsupported spell command '%c'.\n" | |
326 "This is a bug; mail " BUGEMAIL " about it.\n", buf[0]); | |
1467
7f7857c5036e
[gaim-migrate @ 1477]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1415
diff
changeset
|
327 error_print("Input [%s]\nOutput [%s]\n", word, buf); |
7f7857c5036e
[gaim-migrate @ 1477]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1415
diff
changeset
|
328 |
1117 | 329 } |
2454
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
330 g_free(buf); |
1117 | 331 return NULL; |
332 } | |
333 | |
334 static int misspelled_test(char *word) { | |
2454
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
335 char *buf; |
2517
9cee43e4903d
[gaim-migrate @ 2530]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2461
diff
changeset
|
336 |
9cee43e4903d
[gaim-migrate @ 2530]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2461
diff
changeset
|
337 if (word == NULL) |
9cee43e4903d
[gaim-migrate @ 2530]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2461
diff
changeset
|
338 return 0; |
9cee43e4903d
[gaim-migrate @ 2530]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2461
diff
changeset
|
339 |
2454
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
340 buf = g_strdup_printf("^%s\n", word); /* guard against ispell control chars */ |
1117 | 341 writetext(buf); |
2454
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
342 g_free(buf); |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
343 buf = readresponse(); |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
344 |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
345 if (!buf) |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
346 return 0; |
1117 | 347 |
348 if (buf[0] == 0) { | |
2454
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
349 g_free(buf); |
1117 | 350 return 0; |
1467
7f7857c5036e
[gaim-migrate @ 1477]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1415
diff
changeset
|
351 } else if (buf[0] == '&' || buf[0] == '#' || buf[0] == '?') { |
2454
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
352 g_free(buf); |
1117 | 353 return 1; |
354 } | |
355 | |
356 error_print("Unsupported spell command '%c'.\n" | |
357 "This is a bug; mail " BUGEMAIL " about it.\n", buf[0]); | |
1467
7f7857c5036e
[gaim-migrate @ 1477]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1415
diff
changeset
|
358 error_print("Input [%s]\nOutput [%s]\n", word, buf); |
2454
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
359 g_free(buf); |
1117 | 360 return -1; |
361 } | |
362 | |
363 static gboolean iswordsep(char c) { | |
364 return !isalpha(c) && c != '\''; | |
365 } | |
366 | |
2454
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
367 static gboolean get_word_from_pos(GtkText* gtktext, int pos, char** buf, |
1117 | 368 int *pstart, int *pend) { |
369 gint start, end; | |
370 | |
371 if (iswordsep(GTK_TEXT_INDEX(gtktext, pos))) return FALSE; | |
372 | |
373 for (start = pos; start >= 0; --start) { | |
374 if (iswordsep(GTK_TEXT_INDEX(gtktext, start))) break; | |
375 } | |
376 start++; | |
377 | |
378 for (end = pos; end <= gtk_text_get_length(gtktext); end++) { | |
379 if (iswordsep(GTK_TEXT_INDEX(gtktext, end))) break; | |
380 } | |
381 | |
2457
e6b9246b33fd
[gaim-migrate @ 2470]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2456
diff
changeset
|
382 if (buf && (end - start + 1 > 0)) { |
e6b9246b33fd
[gaim-migrate @ 2470]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2456
diff
changeset
|
383 *buf = g_malloc(end - start + 1); |
1117 | 384 for (pos = start; pos < end; pos++) |
2457
e6b9246b33fd
[gaim-migrate @ 2470]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2456
diff
changeset
|
385 (*buf)[pos-start] = GTK_TEXT_INDEX(gtktext, pos); |
e6b9246b33fd
[gaim-migrate @ 2470]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2456
diff
changeset
|
386 (*buf)[pos-start] = 0; |
1117 | 387 } |
388 | |
389 if (pstart) *pstart = start; | |
390 if (pend) *pend = end; | |
391 | |
392 return TRUE; | |
393 } | |
394 | |
2454
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
395 static gboolean get_curword(GtkText* gtktext, char** buf, |
1117 | 396 int *pstart, int *pend) { |
397 int pos = gtk_editable_get_position(GTK_EDITABLE(gtktext)); | |
398 return get_word_from_pos(gtktext, pos, buf, pstart, pend); | |
399 } | |
400 | |
401 static void change_color(GtkText *gtktext, | |
402 int start, int end, GdkColor *color) { | |
403 char *newtext = gtk_editable_get_chars(GTK_EDITABLE(gtktext), start, end); | |
404 gtk_text_freeze(gtktext); | |
405 gtk_signal_handler_block_by_func(GTK_OBJECT(gtktext), | |
406 GTK_SIGNAL_FUNC(entry_insert_cb), NULL); | |
407 | |
408 gtk_text_set_point(gtktext, start); | |
409 gtk_text_forward_delete(gtktext, end-start); | |
410 | |
411 if (newtext && end-start > 0) | |
412 gtk_text_insert(gtktext, NULL, color, NULL, newtext, end-start); | |
413 | |
414 gtk_signal_handler_unblock_by_func(GTK_OBJECT(gtktext), | |
415 GTK_SIGNAL_FUNC(entry_insert_cb), NULL); | |
416 gtk_text_thaw(gtktext); | |
1415
3dfd2a83fb5e
[gaim-migrate @ 1425]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1127
diff
changeset
|
417 g_free(newtext); |
1117 | 418 } |
419 | |
420 static gboolean check_at(GtkText *gtktext, int from_pos) { | |
421 int start, end; | |
2454
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
422 char *buf = NULL; |
1117 | 423 |
2454
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
424 if (!get_word_from_pos(gtktext, from_pos, &buf, &start, &end)) { |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
425 if (buf) |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
426 g_free(buf); |
1117 | 427 return FALSE; |
428 } | |
429 | |
430 if (misspelled_test(buf)) { | |
431 if (highlight.pixel == 0) { | |
432 /* add an entry for the highlight in the color map. */ | |
433 GdkColormap *gc = gtk_widget_get_colormap(GTK_WIDGET(gtktext)); | |
2725
f3c094e78609
[gaim-migrate @ 2738]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2670
diff
changeset
|
434 gdk_colormap_alloc_color(gc, &highlight, FALSE, TRUE); |
1117 | 435 } |
436 change_color(gtktext, start, end, &highlight); | |
2454
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
437 if (buf) |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
438 g_free(buf); |
1117 | 439 return TRUE; |
440 } else { | |
441 change_color(gtktext, start, end, | |
442 &(GTK_WIDGET(gtktext)->style->fg[0])); | |
2454
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
443 if (buf) |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
444 g_free(buf); |
1117 | 445 return FALSE; |
446 } | |
447 } | |
448 | |
449 void gtkspell_check_all(GtkText *gtktext) { | |
450 guint origpos; | |
451 guint pos = 0; | |
452 guint len; | |
453 float adj_value; | |
454 | |
455 if (!gtkspell_running()) return; | |
456 | |
457 len = gtk_text_get_length(gtktext); | |
458 | |
459 adj_value = gtktext->vadj->value; | |
460 gtk_text_freeze(gtktext); | |
461 origpos = gtk_editable_get_position(GTK_EDITABLE(gtktext)); | |
462 while (pos < len) { | |
463 while (pos < len && iswordsep(GTK_TEXT_INDEX(gtktext, pos))) | |
464 pos++; | |
465 while (pos < len && !iswordsep(GTK_TEXT_INDEX(gtktext, pos))) | |
466 pos++; | |
467 if (pos > 0) | |
468 check_at(gtktext, pos-1); | |
469 } | |
470 gtk_text_thaw(gtktext); | |
471 gtk_editable_set_position(GTK_EDITABLE(gtktext), origpos); | |
472 } | |
473 | |
474 static void entry_insert_cb(GtkText *gtktext, | |
475 gchar *newtext, guint len, guint *ppos, gpointer d) { | |
476 int origpos; | |
477 | |
478 if (!gtkspell_running()) return; | |
479 | |
480 gtk_signal_handler_block_by_func(GTK_OBJECT(gtktext), | |
481 GTK_SIGNAL_FUNC(entry_insert_cb), | |
482 NULL); | |
483 gtk_text_insert(GTK_TEXT(gtktext), NULL, | |
484 &(GTK_WIDGET(gtktext)->style->fg[0]), NULL, newtext, len); | |
485 gtk_signal_handler_unblock_by_func(GTK_OBJECT(gtktext), | |
486 GTK_SIGNAL_FUNC(entry_insert_cb), | |
487 NULL); | |
488 gtk_signal_emit_stop_by_name(GTK_OBJECT(gtktext), "insert-text"); | |
489 *ppos += len; | |
490 | |
491 origpos = gtk_editable_get_position(GTK_EDITABLE(gtktext)); | |
492 | |
493 if (iswordsep(newtext[0])) { | |
494 /* did we just end a word? */ | |
495 if (*ppos >= 2) check_at(gtktext, *ppos-2); | |
496 | |
497 /* did we just split a word? */ | |
498 if (*ppos < gtk_text_get_length(gtktext)) | |
499 check_at(gtktext, *ppos+1); | |
500 } else { | |
501 /* check as they type, *except* if they're typing at the end (the most | |
502 * common case. | |
503 */ | |
504 if (*ppos < gtk_text_get_length(gtktext) && | |
505 !iswordsep(GTK_TEXT_INDEX(gtktext, *ppos))) | |
506 check_at(gtktext, *ppos-1); | |
507 } | |
508 | |
509 gtk_editable_set_position(GTK_EDITABLE(gtktext), origpos); | |
1496
d33bf6548543
[gaim-migrate @ 1506]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1467
diff
changeset
|
510 gtk_editable_select_region(GTK_EDITABLE(gtktext), origpos, origpos); |
1117 | 511 } |
512 | |
513 static void entry_delete_cb(GtkText *gtktext, | |
514 gint start, gint end, gpointer d) { | |
515 int origpos; | |
516 | |
517 if (!gtkspell_running()) return; | |
518 | |
519 origpos = gtk_editable_get_position(GTK_EDITABLE(gtktext)); | |
520 check_at(gtktext, start-1); | |
521 gtk_editable_set_position(GTK_EDITABLE(gtktext), origpos); | |
522 gtk_editable_select_region(GTK_EDITABLE(gtktext), origpos, origpos); | |
523 /* this is to *UNDO* the selection, in case they were holding shift | |
524 * while hitting backspace. */ | |
525 } | |
526 | |
527 static void replace_word(GtkWidget *w, gpointer d) { | |
528 int start, end; | |
529 char *newword; | |
530 | |
531 /* we don't save their position, | |
532 * because the cursor is moved by the click. */ | |
533 | |
534 gtk_text_freeze(GTK_TEXT(d)); | |
535 | |
536 gtk_label_get(GTK_LABEL(GTK_BIN(w)->child), &newword); | |
2454
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
537 get_curword(GTK_TEXT(d), NULL, &start, &end); |
1117 | 538 |
539 gtk_text_set_point(GTK_TEXT(d), end); | |
540 gtk_text_backward_delete(GTK_TEXT(d), end-start); | |
541 gtk_text_insert(GTK_TEXT(d), NULL, NULL, NULL, newword, strlen(newword)); | |
542 | |
543 gtk_text_thaw(GTK_TEXT(d)); | |
544 } | |
545 | |
546 static GtkMenu *make_menu(GList *l, GtkText *gtktext) { | |
547 GtkWidget *menu, *item; | |
548 char *caption; | |
549 menu = gtk_menu_new(); { | |
550 caption = g_strdup_printf("Not in dictionary: %s", (char*)l->data); | |
551 item = gtk_menu_item_new_with_label(caption); | |
2454
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
552 g_free(caption); |
1117 | 553 /* I'd like to make it so this item is never selectable, like |
554 * the menu titles in the GNOME panel... unfortunately, the GNOME | |
555 * panel creates their own custom widget to do this! */ | |
556 gtk_widget_show(item); | |
557 gtk_menu_append(GTK_MENU(menu), item); | |
558 | |
559 item = gtk_menu_item_new(); | |
560 gtk_widget_show(item); | |
561 gtk_menu_append(GTK_MENU(menu), item); | |
562 | |
563 l = l->next; | |
564 if (l == NULL) { | |
565 item = gtk_menu_item_new_with_label("(no suggestions)"); | |
566 gtk_widget_show(item); | |
567 gtk_menu_append(GTK_MENU(menu), item); | |
568 } else { | |
569 GtkWidget *curmenu = menu; | |
570 int count = 0; | |
571 do { | |
572 if (l->data == NULL && l->next != NULL) { | |
573 count = 0; | |
574 curmenu = gtk_menu_new(); | |
575 item = gtk_menu_item_new_with_label("Other Possibilities..."); | |
576 gtk_widget_show(item); | |
577 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), curmenu); | |
578 gtk_menu_append(GTK_MENU(curmenu), item); | |
579 l = l->next; | |
580 } else if (count > MENUCOUNT) { | |
581 count -= MENUCOUNT; | |
582 item = gtk_menu_item_new_with_label("More..."); | |
583 gtk_widget_show(item); | |
584 gtk_menu_append(GTK_MENU(curmenu), item); | |
585 curmenu = gtk_menu_new(); | |
586 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), curmenu); | |
587 } | |
588 item = gtk_menu_item_new_with_label((char*)l->data); | |
589 gtk_signal_connect(GTK_OBJECT(item), "activate", | |
590 GTK_SIGNAL_FUNC(replace_word), gtktext); | |
591 gtk_widget_show(item); | |
592 gtk_menu_append(GTK_MENU(curmenu), item); | |
593 count++; | |
594 } while ((l = l->next) != NULL); | |
595 } | |
596 } | |
597 return GTK_MENU(menu); | |
598 } | |
599 | |
600 static void popup_menu(GtkText *gtktext, GdkEventButton *eb) { | |
2454
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
601 char *buf = NULL; |
1117 | 602 GList *list, *l; |
603 | |
2454
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
604 get_curword(gtktext, &buf, NULL, NULL); |
1117 | 605 |
606 list = misspelled_suggest(buf); | |
2454
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
607 if (buf) |
64e20158271e
[gaim-migrate @ 2467]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1815
diff
changeset
|
608 g_free(buf); |
1117 | 609 if (list != NULL) { |
610 gtk_menu_popup(make_menu(list, gtktext), NULL, NULL, NULL, NULL, | |
611 eb->button, eb->time); | |
612 for (l = list; l != NULL; l = l->next) | |
613 g_free(l->data); | |
614 g_list_free(list); | |
615 } | |
616 } | |
617 | |
618 /* ok, this is pretty wacky: | |
619 * we need to let the right-mouse-click go through, so it moves the cursor, | |
620 * but we *can't* let it go through, because GtkText interprets rightclicks as | |
621 * weird selection modifiers. | |
622 * | |
623 * so what do we do? forge rightclicks as leftclicks, then popup the menu. | |
624 * HACK HACK HACK. | |
625 */ | |
626 static gint button_press_intercept_cb(GtkText *gtktext, GdkEvent *e, gpointer d) { | |
627 GdkEventButton *eb; | |
628 gboolean retval; | |
629 | |
630 if (!gtkspell_running()) return FALSE; | |
631 | |
632 if (e->type != GDK_BUTTON_PRESS) return FALSE; | |
633 eb = (GdkEventButton*) e; | |
634 | |
635 if (eb->button != 3) return FALSE; | |
636 | |
637 /* forge the leftclick */ | |
638 eb->button = 1; | |
639 | |
640 gtk_signal_handler_block_by_func(GTK_OBJECT(gtktext), | |
641 GTK_SIGNAL_FUNC(button_press_intercept_cb), d); | |
642 gtk_signal_emit_by_name(GTK_OBJECT(gtktext), "button-press-event", | |
643 e, &retval); | |
644 gtk_signal_handler_unblock_by_func(GTK_OBJECT(gtktext), | |
645 GTK_SIGNAL_FUNC(button_press_intercept_cb), d); | |
646 gtk_signal_emit_stop_by_name(GTK_OBJECT(gtktext), "button-press-event"); | |
647 | |
648 /* now do the menu wackiness */ | |
649 popup_menu(gtktext, eb); | |
650 return TRUE; | |
651 } | |
652 | |
653 void gtkspell_uncheck_all(GtkText *gtktext) { | |
654 int origpos; | |
655 char *text; | |
656 float adj_value; | |
657 | |
658 adj_value = gtktext->vadj->value; | |
659 gtk_text_freeze(gtktext); | |
660 origpos = gtk_editable_get_position(GTK_EDITABLE(gtktext)); | |
661 text = gtk_editable_get_chars(GTK_EDITABLE(gtktext), 0, -1); | |
662 gtk_text_set_point(gtktext, 0); | |
663 gtk_text_forward_delete(gtktext, gtk_text_get_length(gtktext)); | |
664 gtk_text_insert(gtktext, NULL, NULL, NULL, text, strlen(text)); | |
665 gtk_text_thaw(gtktext); | |
1794
60b3fd819cce
[gaim-migrate @ 1804]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
1496
diff
changeset
|
666 g_free(text); |
1117 | 667 |
668 gtk_editable_set_position(GTK_EDITABLE(gtktext), origpos); | |
669 gtk_adjustment_set_value(gtktext->vadj, adj_value); | |
670 } | |
671 | |
672 void gtkspell_attach(GtkText *gtktext) { | |
673 gtk_signal_connect(GTK_OBJECT(gtktext), "insert-text", | |
674 GTK_SIGNAL_FUNC(entry_insert_cb), NULL); | |
675 gtk_signal_connect_after(GTK_OBJECT(gtktext), "delete-text", | |
676 GTK_SIGNAL_FUNC(entry_delete_cb), NULL); | |
677 gtk_signal_connect(GTK_OBJECT(gtktext), "button-press-event", | |
678 GTK_SIGNAL_FUNC(button_press_intercept_cb), NULL); | |
679 } | |
680 | |
681 void gtkspell_detach(GtkText *gtktext) { | |
682 gtk_signal_disconnect_by_func(GTK_OBJECT(gtktext), | |
683 GTK_SIGNAL_FUNC(entry_insert_cb), NULL); | |
684 gtk_signal_disconnect_by_func(GTK_OBJECT(gtktext), | |
685 GTK_SIGNAL_FUNC(entry_delete_cb), NULL); | |
686 gtk_signal_disconnect_by_func(GTK_OBJECT(gtktext), | |
687 GTK_SIGNAL_FUNC(button_press_intercept_cb), NULL); | |
688 | |
689 gtkspell_uncheck_all(gtktext); | |
690 } | |
691 | |
692 static void sigchld(int param) { | |
693 if (gtkspell_running() && | |
694 (waitpid(spell_pid, NULL, WNOHANG) == spell_pid)) { | |
695 spell_pid = 0; | |
696 } else { | |
697 /* a default SIGCHLD handler. | |
698 * what else to do here? */ | |
699 waitpid(-1, NULL, WNOHANG); | |
700 } | |
701 } | |
702 | |
703 static void set_up_signal() { | |
704 struct sigaction sigact; | |
705 memset(&sigact, 0, sizeof(struct sigaction)); | |
706 | |
707 sigact.sa_handler = sigchld; | |
708 sigaction(SIGCHLD, &sigact, NULL); | |
709 } |