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