1 /*
2 Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd.
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8
9 - Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11
12 - Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in
14 the documentation and/or other materials provided with the
15 distribution.
16
17 - Neither the name of The Numerical ALgorithms Group Ltd. nor the
18 names of its contributors may be used to endorse or promote products
19 derived from this software without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
22 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
25 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 /******************************************************************************
35 *
36 * keyin.c:
37 *
38 * Copyright The Numerical Algorithms Group Limited 1991, 1992, 1993.
39 *
40 ****************************************************************************/
41
42 #include "fricas_c_macros.h"
43 #include "debug.h"
44
45
46 #include "hyper.h"
47 #include "keyin.h"
48 #include "parse.h"
49
50 #include "all_hyper_proto.H1"
51 #include <X11/keysym.h>
52
53
54 #define min(x,y) ( (x<y)?(x):(y))
55
56 int in_cursor_height;
57 int in_cursor_width;
58 int out_cursor_height;
59 int out_cursor_width;
60 int in_cursor_y;
61 int out_cursor_y;
62 int start_x;
63 int start_y;
64 int simple_box_width;
65 int gInInsertMode = 0;
66
67 unsigned int ModifiersMask = ShiftMask | LockMask | ControlMask
68 | Mod1Mask | Mod2Mask | Mod3Mask
69 | Mod4Mask | Mod5Mask;
70
71 unsigned int UnsupportedModMask = LockMask | ControlMask
72 | Mod1Mask | Mod2Mask | Mod3Mask
73 | Mod4Mask | Mod5Mask;
74
75
76 /*
77 * Since the user can't tell me directly what name to use here, I am going to
78 * let it be a default property. This way the user can link to whatever page
79 * he/she wants. If it is a link right to the quit page, then I will just
80 * quit right away. Otherwise I will try to find the page, and display it.
81 */
82
83 static char *protected_quit;
84
85 HyperLink *quitLink; /** the global link to the quit page ***/
86
87 void
handle_key(XEvent * event)88 handle_key(XEvent *event)
89 {
90 char key_buffer[20];
91 int key_buffer_size = 20;
92 KeySym keysym;
93 XComposeStatus compstatus;
94 int charcount;
95 int display_again = 0;
96 char *name;
97 char *filename;
98 /*char *head = "echo htadd -l ";*/
99 /*char *blank1 = " ";*/
100 /*char *blank2 = " \n";*/
101 char buffer[180];
102 FILE *filehandle;
103
104 charcount = XLookupString((XKeyEvent *)event, key_buffer, key_buffer_size, &keysym ,&compstatus); /* 5 args */
105
106 key_buffer[charcount] = '\0';
107 switch (keysym) {
108 case XK_Prior:
109 case XK_F29:
110 scrollUpPage();
111 break;
112 case XK_Next:
113 case XK_F35:
114 scrollDownPage();
115 break;
116 case XK_F3:
117 case XK_F12:
118 quitHyperDoc();
119 break;
120 case XK_F5:
121 if (event->xkey.state & ShiftMask) {
122 name = gWindow->page->name;
123 filename = gWindow->page->filename;
124 sprintf(buffer, "htadd -l %s\n", filename);
125 system(buffer);
126 filehandle = (FILE *) hash_find(&gFileHashTable, filename);
127 fclose(filehandle);
128 hash_delete(&gFileHashTable, filename);
129 gWindow->fMacroHashTable =
130 (HashTable *) halloc(sizeof(HashTable), "macro hash");
131 hash_init(
132 gWindow->fMacroHashTable,
133 MacroHashSize,
134 (EqualFunction ) string_equal,
135 (HashcodeFunction) string_hash);
136 gWindow->fPatchHashTable = (HashTable *) halloc(sizeof(HashTable), "patch hash");
137 hash_init(
138 gWindow->fPatchHashTable,
139 PatchHashSize,
140 (EqualFunction ) string_equal,
141 (HashcodeFunction) string_hash);
142 gWindow->fPasteHashTable = (HashTable *) halloc(sizeof(HashTable), "paste hash");
143 hash_init(gWindow->fPasteHashTable,
144 PasteHashSize,
145 (EqualFunction ) string_equal,
146 (HashcodeFunction) string_hash);
147 gWindow->fCondHashTable = (HashTable *) halloc(sizeof(HashTable), "cond hash");
148 hash_init(
149 gWindow->fCondHashTable,
150 CondHashSize,
151 (EqualFunction ) string_equal,
152 (HashcodeFunction) string_hash);
153 gWindow->fPageHashTable = (HashTable *) halloc(sizeof(HashTable), "page hash");
154 hash_init(
155 gWindow->fPageHashTable,
156 PageHashSize,
157 (EqualFunction ) string_equal,
158 (HashcodeFunction) string_hash);
159 make_special_pages(gWindow->fPageHashTable);
160 read_ht_db(
161 gWindow->fPageHashTable,
162 gWindow->fMacroHashTable,
163 gWindow->fPatchHashTable);
164 gWindow->page = (HyperDocPage *) hash_find(gWindow->fPageHashTable, name);
165 if (gWindow->page == NULL) {
166 fprintf(stderr, "lose...gWindow->page for %s is null\n", name);
167 exit(-1);
168 }
169 display_again = 1;
170 }
171 break;
172 case XK_F9:
173 make_window_link(KeyDefsHelpPage);
174 break;
175 case XK_Tab:
176 if (event->xkey.state & ShiftMask)
177 prev_input_focus();
178 else if (event->xkey.state & ModifiersMask)
179 BeepAtTheUser();
180 else
181 next_input_focus();
182 break;
183 case XK_Return:
184 if (!(event->xkey.state & ShiftMask)) {
185 next_input_focus();
186 break;
187 }
188
189 /* next ones fall through to input area handling */
190
191 case XK_Escape:
192 if (!gWindow->page->current_item)
193 break;
194 case XK_F1:
195 if (!gWindow->page->current_item) {
196 gWindow->page->helppage = alloc_string(NoMoreHelpPage);
197 helpForHyperDoc();
198 break;
199 }
200 case XK_Home:
201 if (!gWindow->page->current_item) {
202 scrollToFirstPage();
203 break;
204 }
205 case XK_Up:
206 if (!gWindow->page->current_item) {
207 scrollUp();
208 break;
209 }
210 case XK_Down:
211 if (!gWindow->page->current_item) {
212 scrollDown();
213 break;
214 }
215
216 default:
217 display_again = 0;
218 dialog(event, keysym, key_buffer);
219 XFlush(gXDisplay);
220 break;
221 }
222
223 if (display_again) {
224 display_page(gWindow->page);
225 gWindow->fWindowHashTable = gWindow->page->fLinkHashTable;
226 }
227 }
228
229 /*
230 * This routine returns the modifier mask associated
231 * to a key symbol.
232 */
233
234 static unsigned int
get_modifier_mask(KeySym sym)235 get_modifier_mask(KeySym sym)
236 {
237 unsigned int i, mask;
238 XModifierKeymap *mod;
239 KeyCode kcode;
240 const int masks[8] = {
241 ShiftMask, LockMask, ControlMask,
242 Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
243 };
244
245 mod = XGetModifierMapping(gXDisplay);
246 kcode = XKeysymToKeycode(gXDisplay,sym);
247
248 if (mod) {
249 for (i = 0; i < (8 * mod->max_keypermod); i++){
250 if (!mod->modifiermap[i]) continue;
251 else if (kcode == mod->modifiermap[i]){
252 mask = masks[i / mod->max_keypermod];
253 XFreeModifiermap(mod);
254 return mask;
255 }
256 }
257 XFreeModifiermap(mod);
258 }
259 return 0;
260 }
261
262
263
264 /*
265 * This routine initializes some of the variables needed by the input
266 * strings, and boxes.
267 */
268
269 void
init_keyin(void)270 init_keyin(void)
271 {
272 char *prop;
273 unsigned int nlm;
274
275
276 nlm = get_modifier_mask(XK_Num_Lock);
277 UnsupportedModMask &= ~nlm;
278 ModifiersMask &= ~nlm;
279
280 /*
281 * First set all the values for when the active cursor is in the window
282 */
283
284 in_cursor_height = 2;
285 in_cursor_y = gInputFont->max_bounds.ascent +
286 gInputFont->max_bounds.descent;
287 in_cursor_width = gInputFont->max_bounds.width;
288
289 /*
290 * Now for when the cursor is empty
291 */
292
293 out_cursor_height = gInputFont->max_bounds.ascent +
294 gInputFont->max_bounds.descent;
295 out_cursor_y = 2;
296 out_cursor_width = in_cursor_width;
297
298 start_x = 5;
299
300 start_y = gInputFont->max_bounds.ascent;
301
302 /*
303 * Find out How big I should make the simple boxes
304 */
305
306 simple_box_width = XTextWidth(gInputFont, "X", 1) + 5;
307
308 prop = XGetDefault(gXDisplay, gArgv[0], "ProtectedQuit");
309
310 if (prop == NULL) {
311 protected_quit = (char *) halloc(strlen("ProtectedPage") + 1,
312 "protected_quit");
313 strcpy(protected_quit, "ProtectedPage");
314 }
315 else {
316 protected_quit = (char *) halloc(strlen(prop) + 1, "protected_quit");
317 strcpy(protected_quit, prop);
318 }
319
320
321 }
322