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