Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

open-axiom repository from github

24005 views
1
/*
2
Copyright (C) 1991-2002, The Numerical Algorithms Group Ltd.
3
All rights reserved.
4
Copyright (C) 2007-2010, Gabriel Dos Reis.
5
All rights reserved.
6
7
Redistribution and use in source and binary forms, with or without
8
modification, are permitted provided that the following conditions are
9
met:
10
11
- Redistributions of source code must retain the above copyright
12
notice, this list of conditions and the following disclaimer.
13
14
- Redistributions in binary form must reproduce the above copyright
15
notice, this list of conditions and the following disclaimer in
16
the documentation and/or other materials provided with the
17
distribution.
18
19
- Neither the name of The Numerical Algorithms Group Ltd. nor the
20
names of its contributors may be used to endorse or promote products
21
derived from this software without specific prior written permission.
22
23
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
24
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
26
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
27
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
*/
35
36
#define _EVENT_C
37
38
#include "openaxiom-c-macros.h"
39
40
#include <X11/X.h>
41
#include <X11/Xatom.h>
42
#include <X11/cursorfont.h>
43
#include <sys/types.h>
44
#include <sys/signal.h>
45
#include <setjmp.h>
46
#include <sys/time.h>
47
48
#include "debug.h"
49
#include "sockio.h"
50
#include "hyper.h"
51
#include "event.h"
52
#include "keyin.h"
53
#include "hyper.h"
54
#include "display.h"
55
#include "parse.h"
56
#include "parse-paste.h"
57
#include "initx.h"
58
#include "scrollbar.h"
59
#include "group.h"
60
#include "lex.h"
61
#include "sockio.h"
62
63
jmp_buf env;
64
Window gActiveWindow;
65
int motion = 0;
66
int gNeedIconName = 0;
67
unsigned long bigmask= 0xffffffff;
68
static HyperLink *gSavedInputAreaLink = NULL;
69
70
71
static int
72
HyperDocErrorHandler(Display *display, XErrorEvent *xe)
73
{
74
if (xe->request_code != 15) {
75
char buf[1024];
76
77
XGetErrorText(display, xe->error_code, buf, sizeof(buf));
78
79
fprintf(stderr, "error code = %d\n", xe->error_code);
80
fprintf(stderr, "major op code = %d\n", xe->request_code);
81
fprintf(stderr, "minor op code = %d\n", xe->minor_code);
82
fprintf(stderr, "XID = %ld\n", xe->resourceid);
83
fprintf(stderr, "%s\n", buf);
84
85
if (xe->request_code != 15)
86
exit(-1);
87
}
88
return(0);
89
}
90
91
static void
92
set_error_handlers()
93
{
94
XSetErrorHandler(HyperDocErrorHandler);
95
}
96
97
static int
98
set_window(Window window)
99
{
100
Window root, parent, *children, grandparent,myarg;
101
HDWindow *htw;
102
unsigned int nchildren;
103
int st;
104
105
myarg=window;
106
nchildren = 0;
107
htw = (HDWindow *) hash_find(&gSessionHashTable, (char *)&myarg);
108
if (htw != NULL) {
109
gWindow = htw;
110
return 1;
111
}
112
st = XQueryTree(gXDisplay, myarg, &root, &parent, &children, &nchildren);
113
if (st==0) goto ERROR;
114
if (nchildren > 0)
115
XFree(children);
116
htw = (HDWindow *) hash_find(&gSessionHashTable, (char *)&parent);
117
if (htw != NULL) {
118
gWindow = htw;
119
return 1;
120
121
}
122
else {
123
/* check for a grandparent */
124
st = XQueryTree(gXDisplay, parent, &root, &grandparent, &children, &nchildren);
125
if (st==0) goto ERROR;
126
if (nchildren > 0)
127
XFree(children);
128
htw = (HDWindow *) hash_find(&gSessionHashTable, (char *)&grandparent);
129
if (htw != NULL) {
130
gWindow = htw;
131
return 1;
132
}
133
}
134
135
/*
136
* fprintf(stderr, "window(%d) and it's parent(%d) aren't in
137
* gSessionHashTable\n", window, parent);
138
139
we never found that window. this happens if (not iff) we exit from
140
an unfocused non-main window under certain wm's and click-to-type. the program returns here with
141
the window handle that was just destroyed. So let's set the global gWindow
142
to the main window.
143
*/
144
145
ERROR:
146
gWindow=gParentWindow;
147
return 0;
148
}
149
150
151
static HyperLink *
152
findButtonInList(HDWindow * window, int x, int y)
153
{
154
ButtonList *bl;
155
156
if (!window || window->page->type == UnloadedPageType)
157
return NULL;
158
for (bl = window->page->s_button_list; bl != NULL; bl = bl->next)
159
if (x >= bl->x0 && x <= bl->x1 && y >= bl->y0 && y <= bl->y1)
160
return bl->link;
161
for (bl = window->page->button_list; bl != NULL; bl = bl->next)
162
if (x >= bl->x0 && x <= bl->x1 && y >= bl->y0 && y <= bl->y1)
163
return bl->link;
164
return NULL;
165
}
166
167
static void
168
set_cursor(HDWindow *window,Cursor state)
169
{
170
if (state == gBusyCursor)
171
XDefineCursor(gXDisplay, window->fMainWindow, gBusyCursor);
172
else if (state == gActiveCursor)
173
XDefineCursor(gXDisplay, window->fMainWindow, gActiveCursor);
174
else
175
XDefineCursor(gXDisplay, window->fMainWindow, gNormalCursor);
176
XFlush(gXDisplay);
177
}
178
179
static void
180
change_cursor(Cursor state, HDWindow *window)
181
{
182
if (window->fDisplayedCursor == state)
183
return;
184
window->fDisplayedCursor = state;
185
set_cursor(window, state);
186
}
187
188
189
static void
190
make_busy_cursor(HDWindow *window)
191
{
192
change_cursor(gBusyCursor, window);
193
}
194
195
static void
196
make_busy_cursors()
197
{
198
hash_map(&gSessionHashTable, (MappableFunction)make_busy_cursor);
199
}
200
201
static void
202
handle_motion_event(XMotionEvent *event)
203
{
204
if (!gWindow)
205
return;
206
if (findButtonInList(gWindow, event->x, event->y) != NULL)
207
change_cursor(gActiveCursor, gWindow);
208
else
209
change_cursor(gNormalCursor, gWindow);
210
}
211
212
213
/*
214
* This procedure whips thru the stack and clears all expose events for the
215
* given routine
216
*/
217
static void
218
clear_exposures(Window w)
219
{
220
XEvent report;
221
222
XFlush(gXDisplay);
223
while (XCheckTypedWindowEvent(gXDisplay, w, Expose, &report));
224
}
225
226
static HyperLink *
227
get_hyper_link(XButtonEvent * event)
228
{
229
HyperLink *l1, *l2;
230
231
l1 = (HyperLink *) hash_find(gWindow->fWindowHashTable, (char *)&(event->window));
232
if (l1)
233
return l1;
234
l2 = findButtonInList(gWindow, event->x, event->y);
235
return l2;
236
}
237
238
239
static HyperDocPage *
240
paste_button(PasteNode * paste)
241
{
242
HyperDocPage *page = NULL;
243
auto pastewhere = paste->where;
244
245
246
if ( paste->end_node ==NULL || paste->begin_node==NULL || paste->arg_node==NULL ){
247
BeepAtTheUser();
248
return NULL;
249
}
250
251
page=parse_patch(paste);
252
/* paste has changed after this call so use pastewhere*/
253
254
if (pastewhere != SourceInputKind{ } && page ) {
255
if (0 == strcmp(page->name, "ErrorPage"))
256
page = NULL;
257
}
258
else
259
BeepAtTheUser();
260
261
return page;
262
}
263
264
static void
265
killAxiomPage(HyperDocPage * page)
266
{
267
char command[512];
268
269
sprintf(command, "(|htpDestroyPage| '%s)", page->name);
270
send_lisp_command(command);
271
}
272
273
static void
274
kill_page(HyperDocPage * page)
275
{
276
page->scroll_off = 0;
277
if (page->type == SpadGen) {
278
hash_delete(gWindow->fPageHashTable, page->name);
279
killAxiomPage(page);
280
free_page(page);
281
}
282
}
283
284
/* pops the memo stack */
285
286
static HyperDocPage *
287
returnlink()
288
{
289
int i;
290
291
if (gWindow->fMemoStackIndex == 0) {
292
BeepAtTheUser();
293
return NULL;
294
}
295
else {
296
kill_page(gWindow->page);
297
for (i = gWindow->fDownLinkStackIndex - 1;
298
i >= gWindow->fDownLinkStackTop[gWindow->fMemoStackIndex - 1];
299
i--)
300
{
301
kill_page(gWindow->fDownLinkStack[i]);
302
}
303
gWindow->fDownLinkStackIndex =
304
gWindow->fDownLinkStackTop[--gWindow->fMemoStackIndex];
305
return (gWindow->fMemoStack[gWindow->fMemoStackIndex]);
306
}
307
}
308
309
/* pops a page if it can from the downlink stack */
310
311
static HyperDocPage *
312
uplink()
313
{
314
if (gWindow->fDownLinkStackIndex == 0)
315
return returnlink();
316
else {
317
kill_page(gWindow->page);
318
return (gWindow->fDownLinkStack[--gWindow->fDownLinkStackIndex]);
319
}
320
}
321
322
/*
323
* find_page takes as an argument the HyperDoc for a page name and returns
324
* the associated page
325
*/
326
327
static HyperDocPage *
328
find_page(TextNode * node)
329
{
330
char *page_name;
331
HyperDocPage *page;
332
333
/* try and find the page name */
334
page_name = print_to_string(node);
335
page = (HyperDocPage *) hash_find(gWindow->fPageHashTable, page_name);
336
337
if (page == NULL) {
338
/* try to find the unknown page */
339
page = (HyperDocPage *) hash_find(gWindow->fPageHashTable, "UnknownPage");
340
if (page == NULL) {
341
/* Yikes, Even that could not be found */
342
fprintf(stderr, "Unknown page name %s\n", page_name);
343
}
344
else {
345
if (page->type == UnloadedPageType)
346
page->type = UlUnknownPage;
347
else
348
page->type = UnknownPage;
349
}
350
}
351
return page;
352
}
353
354
/* pushes a page onto the down link stack */
355
356
static void
357
downlink()
358
{
359
if (gWindow->fDownLinkStackIndex == MaxDownlinkDepth)
360
fprintf(stderr, "exceeded maximum link nesting level\n");
361
else
362
gWindow->fDownLinkStack[gWindow->fDownLinkStackIndex++] = gWindow->page;
363
}
364
365
static void
366
memolink()
367
{
368
if (gWindow->fMemoStackIndex == MaxMemoDepth)
369
fprintf(stderr, "exceeded maximum link nesting level\n");
370
else {
371
gWindow->fMemoStack[gWindow->fMemoStackIndex] = gWindow->page;
372
gWindow->fDownLinkStackTop[gWindow->fMemoStackIndex++] = gWindow->fDownLinkStackIndex;
373
}
374
}
375
376
static void
377
windowlink_handler(TextNode * node)
378
{
379
char *page_name;
380
381
/* first try and find the page */
382
page_name = print_to_string(node);
383
384
if (init_top_window(page_name) == -1) {
385
return;
386
}
387
/* gWindow->fWindowHashTable = gWindow->page->fLinkHashTable;*/
388
}
389
390
static void
391
lispwindowlink_handler(HyperLink * link)
392
{
393
394
/*
395
* Since we are popping up a new window, then we had better change all
396
* the cursors right away. We won't get another chance at it.
397
*/
398
399
if (init_top_window(NULL) != -1) {
400
HyperDocPage *page = NULL;
401
int frame = gWindow->fAxiomFrame;
402
403
page = issue_server_command(link);
404
gWindow->fAxiomFrame = frame;
405
gWindow->page = page;
406
/* gWindow->fWindowHashTable = gWindow->page->fLinkHashTable;*/
407
}
408
}
409
410
static void
411
create_window()
412
{
413
XWindowAttributes wa;
414
415
XGetWindowAttributes(gXDisplay, gWindow->fMainWindow, &wa);
416
417
gWindow->width = wa.width;
418
gWindow->height = wa.height;
419
display_page(gWindow->page);
420
gWindow->fWindowHashTable = gWindow->page->fLinkHashTable;
421
422
/* then select for the events I normally would like to catch */
423
XSelectInput(gXDisplay, gWindow->fMainWindow, ButtonPress | KeyPressMask |
424
PointerMotionMask |
425
ExposureMask /* | EnterWindowMask | LeaveWindowMask */ );
426
XSelectInput(gXDisplay, gWindow->fScrollWindow, ExposureMask);
427
428
}
429
430
/*
431
* These are macros for taking care of the downlink stack, and the memolink
432
* stack.
433
*/
434
435
#define NotSpecial(t) \
436
((t == openaxiom_Quitbutton_token || t == openaxiom_Returnbutton_token \
437
|| t == openaxiom_Upbutton_token || t == UnknownPage \
438
|| t == UlUnknownPage || t == ErrorPage) \
439
?(0):(1))
440
441
/*
442
* Handle a button pressed event. window is the subwindow in which the event
443
* occured, and button is the button which was pressed
444
*/
445
446
static void
447
handle_button(int button, XButtonEvent * event)
448
{
449
HyperLink *link;
450
HyperDocPage *page = NULL;
451
char *page_name;
452
453
/* find page name from sub-window handle */
454
455
link = get_hyper_link(event);
456
457
if (link == NULL) { /* user clicked on an inactive area */
458
/* BeepAtTheUser(); */ /* I always thought this was annoying. RSS */
459
return;
460
}
461
462
switch (link->type) {
463
case openaxiom_Pastebutton_token:
464
page = paste_button(link->reference.paste);
465
break;
466
case openaxiom_Link_token:
467
page_name = print_to_string(link->reference.node);
468
page = (HyperDocPage *) hash_find(gWindow->fPageHashTable, page_name);
469
break;
470
case openaxiom_Helpbutton_token:
471
helpForHyperDoc();
472
page = NULL;
473
break;
474
case openaxiom_Scrollbar_token:
475
scrollScroller(event);
476
break;
477
case Scrollupbutton:
478
scrollUp();
479
break;
480
case Scrolldownbutton:
481
scrollDown();
482
break;
483
484
case openaxiom_Inputstring_token:
485
/* We must be changing input focus or getting a selection */
486
487
change_input_focus(link);
488
if ( button == Button2 ) {
489
XConvertSelection(gXDisplay, XA_PRIMARY, XA_STRING,
490
XInternAtom(gXDisplay, "PASTE_SELECTION", False),
491
gWindow->fMainWindow, CurrentTime);
492
gSavedInputAreaLink = link;
493
}
494
break;
495
496
case openaxiom_SimpleBox_token:
497
page = NULL;
498
toggle_input_box(link);
499
break;
500
case openaxiom_Radiobox_token:
501
page = NULL;
502
toggle_radio_box(link);
503
break;
504
case openaxiom_Quitbutton_token:
505
quitHyperDoc();
506
break;
507
case openaxiom_Returnbutton_token: /* pop memo information */
508
page = returnlink();
509
break;
510
case openaxiom_Upbutton_token: /* pop downlink information */
511
page = uplink();
512
break;
513
case openaxiom_Downlink_token:
514
page = find_page(link->reference.node);
515
if (page && NotSpecial(page->type))
516
downlink();
517
break;
518
case openaxiom_Memolink_token:
519
page = find_page(link->reference.node);
520
if (page && NotSpecial(page->type))
521
memolink();
522
break;
523
case openaxiom_Windowlink_token:
524
page = find_page(link->reference.node);
525
if (page && NotSpecial(page->type)) {
526
windowlink_handler(link->reference.node);
527
gNeedIconName = 1;
528
page = NULL;
529
}
530
break;
531
case openaxiom_Lispwindowlink_token:
532
lispwindowlink_handler(link);
533
gNeedIconName = 1;
534
page = NULL;
535
break;
536
case openaxiom_LispMemoLink_token:
537
case openaxiom_Spadmemolink_token:
538
page = issue_server_command(link);
539
if (page && NotSpecial(page->type))
540
memolink();
541
break;
542
case openaxiom_LispDownLink_token:
543
case openaxiom_Spaddownlink_token:
544
page = issue_server_command(link);
545
if (page && NotSpecial(page->type))
546
downlink();
547
break;
548
case openaxiom_Spadlink_token:
549
case openaxiom_Lisplink_token:
550
page = issue_server_command(link);
551
break;
552
case openaxiom_Lispcommand_token:
553
case openaxiom_Qspadcall_token:
554
case openaxiom_Spadcall_token:
555
page = issue_server_command(link);
556
break;
557
case openaxiom_Lispcommandquit_token:
558
case openaxiom_Spadcallquit_token:
559
case openaxiom_Qspadcallquit_token:
560
page = issue_server_command(link);
561
exitHyperDoc();
562
break;
563
case openaxiom_Spadcommand_token:
564
case openaxiom_Spadgraph_token:
565
case openaxiom_Spadsrc_token:
566
issue_spadcommand(gWindow->page, link->reference.node,
567
button == Button1, link->type);
568
break;
569
case openaxiom_Unixlink_token:
570
page = issue_unixlink(link->reference.node);
571
if (page && NotSpecial(page->type)) {
572
downlink();
573
}
574
break;
575
case openaxiom_Unixcommand_token:
576
issue_unixcommand(link->reference.node);
577
break;
578
default:
579
break;
580
}
581
582
if (page) {
583
switch (page->type) { /* check for special button types */
584
case openaxiom_Quitbutton_token:
585
exitHyperDoc();
586
return;
587
case openaxiom_Returnbutton_token:
588
gWindow->page = returnlink();
589
break;
590
case openaxiom_Upbutton_token:
591
gWindow->page = uplink();
592
break;
593
case ErrorPage:
594
case UnknownPage:
595
case UlUnknownPage:
596
if (page->type == UlUnknownPage)
597
page->type = UnloadedPageType;
598
downlink();
599
gWindow->page = page;
600
break;
601
default: /* a normal link */
602
gWindow->page = page;
603
break;
604
}
605
if (link->type != openaxiom_Pastebutton_token)
606
display_page(gWindow->page);
607
gWindow->fWindowHashTable = gWindow->page->fLinkHashTable; /* reset the window hash */
608
}
609
}
610
611
612
static void
613
handle_event(XEvent * event)
614
{
615
XWindowAttributes wa;
616
/* fprintf(stderr,"event:handle_event entered\n");*/
617
set_window(event->xany.window);
618
if (event->type == MotionNotify) {
619
/* fprintf(stderr,"event:handle_event type=MotionNotify\n");*/
620
handle_motion_event((XMotionEvent *)event);
621
motion = 1;
622
return;
623
}
624
make_busy_cursors();
625
switch (event->type) {
626
case DestroyNotify:
627
/* fprintf(stderr,"event:handle_event type=DestroyNotify\n");*/
628
break;
629
case Expose:
630
/* fprintf(stderr,"event:handle_event type=Expose\n");*/
631
XGetWindowAttributes(gXDisplay, gWindow->fMainWindow, &wa);
632
if ((gWindow->width == 0 && gWindow->height == 0) ||
633
(wa.width != gWindow->width || wa.height != gWindow->height)) {
634
gWindow->width = wa.width;
635
gWindow->height = wa.height;
636
display_page(gWindow->page);
637
gWindow->fWindowHashTable = gWindow->page->fLinkHashTable;
638
}
639
else /** just redraw the thing **/
640
expose_page(gWindow->page);
641
XFlush(gXDisplay);
642
clear_exposures(gWindow->fMainWindow);
643
clear_exposures(gWindow->fScrollWindow);
644
break;
645
case ButtonPress:
646
/* fprintf(stderr,"event:handle_event type=ButtonPress\n");*/
647
handle_button(event->xbutton.button, (XButtonEvent *)event);
648
XFlush(gXDisplay);
649
if (gWindow) {
650
while (XCheckTypedWindowEvent(gXDisplay, gWindow->fMainWindow,
651
Expose, event));
652
while (XCheckTypedWindowEvent(gXDisplay, gWindow->fScrollWindow,
653
Expose, event));
654
}
655
break;
656
case KeyPress:
657
/* fprintf(stderr,"event:handle_event type=KeyPress\n");*/
658
handle_key(event);
659
if (gWindow) {
660
while (XCheckTypedWindowEvent(gXDisplay, gWindow->fMainWindow,
661
Expose, event));
662
while (XCheckTypedWindowEvent(gXDisplay, gWindow->fScrollWindow,
663
Expose, event));
664
}
665
break;
666
case MapNotify:
667
/* fprintf(stderr,"event:handle_event type=MapNotify\n");*/
668
create_window();
669
break;
670
671
case SelectionNotify:
672
/* fprintf(stderr,"event:handle_event type=SelectionNotify\n");*/
673
/* this is in response to a previous request in an input area */
674
if ( gSavedInputAreaLink ) {
675
XSelectionEvent *pSelEvent;
676
Atom dataProperty;
677
pSelEvent = (XSelectionEvent *) event;
678
dataProperty = XInternAtom(gXDisplay, "PASTE_SELECTION", False);
679
/* change the input focus */
680
681
/* change_input_focus(gSavedInputAreaLink); */
682
683
/* try to get the selection as a window property */
684
685
if ( pSelEvent->requestor == gWindow->fMainWindow &&
686
pSelEvent->selection == XA_PRIMARY &&
687
/* pSelEvent->time == CurrentTime && */
688
pSelEvent->target == XA_STRING &&
689
pSelEvent->property == dataProperty )
690
{
691
Atom actual_type;
692
int actual_format;
693
unsigned long nitems, leftover;
694
char *pSelection = NULL;
695
696
if (Success == XGetWindowProperty(gXDisplay,
697
gWindow->fMainWindow,
698
pSelEvent->property, 0L, 100000000L, True,
699
AnyPropertyType, &actual_type, &actual_format,
700
&nitems, &leftover, (unsigned char **) &pSelection) )
701
{
702
char *pBuffer;
703
InputItem *item = gSavedInputAreaLink->reference.string;
704
705
for (pBuffer = pSelection; *pBuffer; ++pBuffer)
706
add_buffer_to_sym(pBuffer, item);
707
708
XFree(pSelection);
709
}
710
}
711
712
/* clear the link info */
713
714
gSavedInputAreaLink = NULL;
715
}
716
break;
717
718
default:
719
/* fprintf(stderr,"event:handle_event type=default\n");*/
720
break;
721
}
722
723
}
724
725
/*
726
* This routine is called when the quitbutton is hit. For the moment I am
727
* just going to leave it all behind
728
*/
729
730
void
731
quitHyperDoc()
732
{
733
HyperDocPage *page;
734
735
if (gSessionHashTable.num_entries == 1 || gParentWindow == gWindow) {
736
if (!strcmp(gWindow->page->name, "ProtectedQuitPage")){
737
exitHyperDoc();
738
}
739
page = (HyperDocPage *) hash_find(gWindow->fPageHashTable, "ProtectedQuitPage");
740
if (page == NULL) {
741
fprintf(stderr, "Unknown page name %s\n", "ProtectedQuitPage");
742
exitHyperDoc();
743
return;
744
}
745
if (gWindow->fDownLinkStackIndex == MaxDownlinkDepth)
746
fprintf(stderr, "exceeded maximum link nesting level\n");
747
else
748
gWindow->fDownLinkStack[gWindow->fDownLinkStackIndex++] = gWindow->page;
749
gWindow->page = page;
750
display_page(gWindow->page);
751
gWindow->fWindowHashTable = gWindow->page->fLinkHashTable;
752
}
753
else
754
exitHyperDoc();
755
}
756
757
758
759
void
760
make_window_link(char *name)
761
{
762
if (init_top_window(name) != -1)
763
{}/* gWindow->fWindowHashTable = gWindow->page->fLinkHashTable; */
764
}
765
766
767
void
768
helpForHyperDoc()
769
{
770
HyperDocPage *page = NULL;
771
772
/* do not do anything if we are already at the "no more help" page */
773
774
if (0 == strcmp(gWindow->page->name, NoMoreHelpPage))
775
return;
776
777
/* if no help page recorded, use the standard "no more help" page */
778
779
if (!gWindow->page->helppage)
780
gWindow->page->helppage = alloc_string(NoMoreHelpPage);
781
782
/* if we are on the main help page, use "no more help" page */
783
784
if (0 == strcmp(gWindow->page->name, TopLevelHelpPage))
785
gWindow->page->helppage = alloc_string(NoMoreHelpPage);
786
787
page = (HyperDocPage *) hash_find(gWindow->fPageHashTable, gWindow->page->helppage);
788
789
if (page)
790
make_window_link(gWindow->page->helppage);
791
else
792
BeepAtTheUser();
793
}
794
795
796
void
797
exitHyperDoc()
798
{
799
XEvent event;
800
801
802
if (gSessionHashTable.num_entries == 1 || gParentWindow == gWindow) {
803
free_hd_window(gWindow);
804
exit(0);
805
}
806
hash_delete(&gSessionHashTable, (char *)&gWindow->fMainWindow);
807
808
/*
809
* Now we quickly want to flush all the events associated with this
810
* window from existence
811
*/
812
813
XFlush(gXDisplay);
814
while (XCheckWindowEvent(gXDisplay, gWindow->fMainWindow, bigmask, &event)) {
815
}
816
while (XCheckWindowEvent(gXDisplay, gWindow->fScrollWindow,bigmask, &event)) {
817
}
818
while (XCheckWindowEvent(gXDisplay, gWindow->fDisplayedWindow, bigmask, &event)) {
819
}
820
while (XCheckWindowEvent(gXDisplay, gWindow->fScrollUpWindow, bigmask, &event)) {
821
}
822
while (XCheckWindowEvent(gXDisplay, gWindow->fScrollDownWindow, bigmask, &event)) {
823
}
824
while (XCheckWindowEvent(gXDisplay, gWindow->scrollbar, bigmask, &event)) {
825
}
826
while (XCheckWindowEvent(gXDisplay, gWindow->scroller, bigmask, &event)) {
827
}
828
829
XDestroyWindow(gXDisplay, gWindow->fMainWindow);
830
free_hd_window(gWindow);
831
gWindow = NULL;
832
gActiveWindow = -1;
833
XFlush(gXDisplay);
834
}
835
836
void
837
get_new_window()
838
{
839
840
int val;
841
char buf[128];
842
int frame;
843
Window wid;
844
HDWindow *htw;
845
HyperDocPage *hpage;
846
847
848
/*
849
* If I am going to try and start a new window, then I should make sure I
850
* have a coonection to listen on
851
*
852
* BUT This code is entered when a socket selects
853
*
854
* if (spad_socket == NULL) { spad_socket =
855
* connect_to_local_server(SpadServer, MenuServer, 10); if (spad_socket
856
* == NULL) { fprintf(stderr, "Get_new_window: Couldn't Connect to
857
* SpadServer\n"); return -1; } }
858
*
859
*/
860
861
862
frame = get_int(spad_socket);
863
val = get_int(spad_socket);
864
switch (val) {
865
case StartPage:
866
init_top_window(NULL);
867
val = get_int(spad_socket);
868
init_scanner();
869
input_type = SourceInputKind::SpadSocket;
870
input_string = "";
871
gWindow->page = parse_page_from_socket();
872
gWindow->fAxiomFrame = frame;
873
XFlush(gXDisplay);
874
break;
875
case LinkToPage:
876
get_string_buf(spad_socket, buf, 128);
877
if (init_top_window(buf) == -1) {
878
fprintf(stderr, "get_new_window: Did not find page %s\n", buf);
879
/* return -1; */
880
}
881
gWindow->fAxiomFrame = frame;
882
break;
883
case PopUpPage:
884
val = get_int(spad_socket);
885
init_form_window(NULL, val);
886
send_int(spad_socket, gWindow->fMainWindow);
887
init_scanner();
888
input_type = SourceInputKind::SpadSocket;
889
input_string = "";
890
gWindow->page = parse_page_from_socket();
891
compute_form_page(gWindow->page);
892
893
XMapWindow(gXDisplay, gWindow->fMainWindow);
894
895
gWindow->fWindowHashTable = gWindow->page->fLinkHashTable;
896
gWindow->fAxiomFrame = frame;
897
XFlush(gXDisplay);
898
break;
899
case PopUpNamedPage:
900
val = get_int(spad_socket);
901
get_string_buf(spad_socket, buf, 128);
902
903
if (init_form_window(buf, val) == -1) {
904
send_int(spad_socket, -1);
905
break;
906
}
907
load_page(gWindow->page);
908
compute_form_page(gWindow->page);
909
910
XMapWindow(gXDisplay, gWindow->fMainWindow);
911
912
gWindow->fWindowHashTable = gWindow->page->fLinkHashTable;
913
gWindow->fAxiomFrame = frame;
914
XFlush(gXDisplay);
915
send_int(spad_socket, gWindow->fMainWindow);
916
/* fprintf(stderr, "Window Id was %d\n", gWindow->fMainWindow); */
917
break;
918
case ReplaceNamedPage:
919
wid = (Window) get_int(spad_socket);
920
get_string_buf(spad_socket, buf, 128);
921
922
htw = (HDWindow *) hash_find(&gSessionHashTable,(char *)&wid);
923
if (htw == NULL) break;
924
hpage = (HyperDocPage *) hash_find(gWindow->fPageHashTable, buf);
925
if (hpage == NULL) break;
926
gWindow = htw;
927
gWindow->page = hpage;
928
display_page(gWindow->page);
929
gWindow->fWindowHashTable = gWindow->page->fLinkHashTable;
930
clear_exposures(gWindow->fMainWindow);
931
clear_exposures(gWindow->fScrollWindow);
932
XFlush(gXDisplay);
933
break;
934
case ReplacePage:
935
wid = (Window) get_int(spad_socket);
936
set_window(wid);
937
init_scanner();
938
input_type = SourceInputKind::SpadSocket;
939
input_string = "";
940
gWindow->page = parse_page_from_socket();
941
display_page(gWindow->page);
942
gWindow->fWindowHashTable = gWindow->page->fLinkHashTable;
943
clear_exposures(gWindow->fMainWindow);
944
clear_exposures(gWindow->fScrollWindow);
945
XFlush(gXDisplay);
946
break;
947
case KillPage:
948
/* Here the user wishes to kill the page */
949
wid = (Window) get_int(spad_socket);
950
htw = (HDWindow *) hash_find(&gSessionHashTable,(char *)&wid);
951
if (htw !=NULL) {
952
gWindow = htw;
953
exitHyperDoc();
954
break;
955
}
956
break;
957
}
958
}
959
960
static void
961
init_cursor_state(HDWindow *window)
962
{
963
if (window) {
964
int x, y, rx, ry, but;
965
Window r, c;
966
967
XQueryPointer(gXDisplay, window->fMainWindow,
968
&r, &c, &rx, &ry, &x, &y,(unsigned int *) &but);
969
if (findButtonInList(window, x, y) != NULL)
970
change_cursor(gActiveCursor, window);
971
else
972
change_cursor(gNormalCursor, window);
973
}
974
}
975
976
static void
977
init_cursor_states()
978
{
979
hash_map(&gSessionHashTable,(MappableFunction) init_cursor_state);
980
}
981
982
983
/*
984
* This is the main X loop. It keeps grabbing events. Since the only way the
985
* window can die is through an event, it never actually end. One of the
986
* subroutines it calls is responsible for killing everything
987
*/
988
989
void
990
mainEventLoop()
991
{
992
XEvent event;
993
int Xcon;
994
fd_set rd, dum1, dum2;
995
motion = 0;
996
gActiveWindow = -1;
997
set_error_handlers();
998
Xcon = ConnectionNumber(gXDisplay);
999
1000
while (1) {
1001
/* fprintf(stderr,"event:mainEventLoop: loop top\n");*/
1002
while (gSessionHashTable.num_entries == 0)
1003
pause();
1004
1005
/* XFlush(gXDisplay); */
1006
1007
if (!motion)
1008
init_cursor_states();
1009
motion = 0;
1010
1011
if (!spad_socket == 0) {
1012
FD_ZERO(&rd);
1013
FD_ZERO(&dum1);
1014
FD_ZERO(&dum2);
1015
FD_CLR(0, &dum1);
1016
FD_CLR(0, &dum2);
1017
FD_CLR(0, &rd);
1018
FD_SET(spad_socket->socket, &rd);
1019
FD_SET(Xcon, &rd);
1020
if (!session_server == 0) {
1021
FD_SET(session_server->socket, &rd);
1022
}
1023
if (XEventsQueued(gXDisplay, QueuedAlready)) {
1024
XNextEvent(gXDisplay, &event);
1025
handle_event(&event);
1026
}
1027
else {
1028
select(FD_SETSIZE, &rd, &dum1, &dum2, NULL);
1029
if (FD_ISSET(Xcon, &rd) ||
1030
XEventsQueued(gXDisplay, QueuedAfterFlush)) {
1031
XNextEvent(gXDisplay, &event);
1032
handle_event(&event);
1033
}
1034
else if (FD_ISSET(spad_socket->socket, &rd))
1035
/*
1036
* Axiom Socket do what handle_event does The 100 is
1037
* $SpadStuff in hypertex.boot
1038
*/
1039
{
1040
if (100 == get_int(spad_socket)) {
1041
set_window(gParentWindow->fMainWindow);
1042
make_busy_cursors();
1043
get_new_window();
1044
}
1045
}
1046
/*
1047
* Session Socket Telling us about the death of a spadbuf
1048
* (plus maybe more later) service_session_socket in
1049
* spadint.c
1050
*/
1051
else
1052
if (session_server && FD_ISSET(session_server->socket, &rd)) {
1053
service_session_socket();
1054
}
1055
}
1056
}
1057
else {
1058
XNextEvent(gXDisplay, &event);
1059
handle_event(&event);
1060
}
1061
}
1062
}
1063
1064