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 /* Still a problem with close_client */
35 
36 /* Communication interface for external FriCAS buffers */
37 
38 #include "fricas_c_macros.h"
39 #include "debug.h"
40 
41 #include <signal.h>
42 
43 #include "hyper.h"
44 #include "parse.h"
45 #include "bsdsignal.h"
46 
47 #include "all_hyper_proto.H1"
48 #include "sockio-c.H1"
49 #include "bsdsignal.H1"
50 
51 static void start_user_buffer(HyperDocPage * page);
52 static void clear_execution_marks(HashTable * depend_hash);
53 static void issue_dependent_commands(HyperDocPage * page, TextNode * command,
54                                      int type);
55 static void send_pile(Sock * sock, char * str);
56 static void mark_as_executed(HyperDocPage * page, TextNode * command,
57                              int type);
58 static void accept_menu_server_connection(HyperDocPage * page);
59 static void switch_frames(void);
60 static void close_client(int pid);
61 
62 typedef struct sock_list {      /* linked list of Sock */
63     Sock Socket;
64     struct sock_list *next;
65 }   Sock_List;
66 
67 Sock_List *plSock = (Sock_List *) 0;
68 Sock *spad_socket = (Sock *) 0; /* to_server socket for SpadServer */
69 
70 char *p2sBuf = NULL;
71 int p2sBufSize = 0;
72 
73 /* issue a FriCAS command to the buffer associated with a page */
74 void
issue_spadcommand(HyperDocPage * page,TextNode * command,int immediate,int type)75 issue_spadcommand(HyperDocPage *page, TextNode *command, int immediate,
76                   int type)
77 {
78     char *buf;
79     int ret_val;
80 
81     ret_val = connect_spad();
82     if (ret_val == NotConnected || ret_val == SpadBusy)
83         return;
84 
85     if (page->sock == NULL)
86         start_user_buffer(page);
87     ret_val = send_int(page->sock, TestLine);
88     if (ret_val == -1) {
89         page->sock = NULL;
90         clear_execution_marks(page->depend_hash);
91         issue_spadcommand(page, command, immediate, type);
92         return;
93     }
94     issue_dependent_commands(page, command, type);
95     ret_val = send_int(page->sock, ReceiveInputLine);
96     buf = print_to_string(command);
97     if (immediate) {
98         int len = strlen(buf);
99         buf = p2sBuf = resizeBuffer(len + 2, p2sBuf, &p2sBufSize);
100         buf[len + 1] = '\0';
101         buf[len] = '\n';
102     }
103     if (type == Spadsrc)
104         send_pile(page->sock, buf);
105     else
106         send_string(page->sock, buf);
107     mark_as_executed(page, command, type);
108     gIsEndOfOutput = 0;
109 }
110 static void
send_pile(Sock * sock,char * str)111 send_pile(Sock *sock,char * str)
112 {
113     FILE *f;
114     char name[512], command[512];
115 
116     sprintf(name, "/tmp/hyper%s.input", getenv("SPADNUM"));
117     f = fopen(name, "w");
118     if (f == NULL) {
119         fprintf(stderr, "Can't open temporary input file %s\n", name);
120         return;
121     }
122     fprintf(f, "%s", str);
123     fclose(f);
124     sprintf(command, ")read %s\n", name);
125     send_string(sock, command);
126 }
127 static void
issue_dependent_commands(HyperDocPage * page,TextNode * command,int type)128 issue_dependent_commands(HyperDocPage *page, TextNode *command,int type)
129 {
130     TextNode *node, *depend_label;
131     SpadcomDepend *depend;
132     int end_type = (type == Spadcommand || type == Spadgraph) ?
133     (Endspadcommand) : (Endspadsrc);
134 
135     for (node = command->next; node->type != end_type;
136          node = node->next)
137         if (node->type == Free)
138             for (depend_label = node->data.node; depend_label != NULL;
139                  depend_label = depend_label->next)
140                 if (depend_label->type == Word) {
141                     depend = (SpadcomDepend *)
142                         hash_find(page->depend_hash, depend_label->data.text);
143                     if (depend == NULL) {
144                         fprintf(stderr, "Error: dependency on undefined label: %s\n",
145                                 depend_label->data.text);
146                         continue;
147                     }
148                     if (!depend->executed) {
149                         issue_spadcommand(page, depend->spadcom->next, 1,
150                                           depend->spadcom->type);
151                         while (!gIsEndOfOutput)
152                             pause();
153                         fricas_sleep(100);
154                     }
155                 }
156 }
157 static void
mark_as_executed(HyperDocPage * page,TextNode * command,int type)158 mark_as_executed(HyperDocPage *page, TextNode *command,int type)
159 {
160     TextNode *node, *depend_label;
161     SpadcomDepend *depend;
162     int end_type = (type == Spadcommand || type == Spadgraph)
163     ? (Endspadcommand) : (Endspadsrc);
164 
165     for (node = command; node->type != end_type; node = node->next)
166         if (node->type == Bound)
167             for (depend_label = node->data.node; depend_label != NULL;
168                  depend_label = depend_label->next)
169                 if (depend_label->type == Word) {
170                     depend = (SpadcomDepend *)
171                         hash_find(page->depend_hash, depend_label->data.text);
172                     if (depend == NULL) {
173                         fprintf(stderr, "No dependency entry for label: %s\n",
174                                 depend_label->data.text);
175                         continue;
176                     }
177                     depend->executed = 1;
178                 }
179 }
180 
181 /* start a spad buffer for the page associated with the give */
182 static void
start_user_buffer(HyperDocPage * page)183 start_user_buffer(HyperDocPage *page)
184 {
185     char buf[1024], *title;
186     char *SPAD;
187     char spadbuf[250];
188     char complfile[250];
189     int ret_val;
190 
191     SPAD = (char *) getenv("FRICAS");
192     if (SPAD == NULL) {
193         fprintf(stderr, "start_user_buffer: $FRICAS is empty\n");
194         exit(-1);
195     }
196     sprintf(spadbuf, "%s/lib/spadbuf", SPAD);
197     sprintf(complfile, "%s/lib/command.list", SPAD);
198     title = print_to_string(page->title);
199     if (access(complfile, R_OK) == 0)
200 
201         /*
202          * TTT says : why not invoke with "-name fricasclient" and set any
203          * defaults in the usual way
204          */
205         sprintf(buf,
206         "xterm -sb -sl 500 -name fricasclient -n '%s' -T '%s' -e  %s %s %s&",
207                 title, title, spadbuf, page->name, complfile);
208     else
209         sprintf(buf,
210          "xterm -sb -sl 500 -name fricasclient -n '%s' -T '%s' -e  %s '%s'&",
211                 title, title, spadbuf, page->name);
212     ret_val = system(buf);
213     if (ret_val == -1 || ret_val == 127) {
214 
215         /*
216          * perror("running the xterm spadbuf program"); exit(-1);
217          */
218     }
219     accept_menu_server_connection(page);
220     fricas_sleep(100);
221 }
222 
223 /* Clears the execution marks in a hash table when a buffer has been killed */
224 static void
clear_execution_marks(HashTable * depend_hash)225 clear_execution_marks(HashTable *depend_hash)
226 {
227     int i;
228     HashEntry *h;
229     SpadcomDepend *depend;
230 
231     if (depend_hash == 0)
232         return;
233     for (i = 0; i < depend_hash->size; i++)
234         for (h = depend_hash->table[i]; h != NULL; h = h->next) {
235             depend = (SpadcomDepend *) h->data;
236             depend->executed = 0;
237         }
238 }
239 
240 Sock *
accept_menu_connection(Sock * server_sock)241 accept_menu_connection(Sock *server_sock)
242 {
243     int sock_fd /*, session, ret_code*/;
244     Sock_List *pls;
245     /*Sock local_sock;*/
246 
247     /* Could only be InterpWindow */
248 
249     pls = (Sock_List *) halloc(sizeof(Sock_List),"SockList");
250     sock_fd = accept(server_sock->socket, 0, 0);
251     if (sock_fd == -1) {
252         perror("session : accepting connection");
253         return 0;
254     }
255     (pls->Socket).socket = sock_fd;
256     get_socket_type((Sock *) pls);
257 
258 #ifdef DEBUG
259     fprintf(stderr,
260             "session: accepted InterpWindow , fd = %d\n", sock_fd);
261 #endif
262 
263 
264     /* put new item at head of list */
265 
266     if (plSock == (Sock_List *) 0) {
267         plSock = pls;
268         plSock->next = (Sock_List *) 0;
269     }
270     else {
271         pls->next = plSock;
272         plSock = pls;
273     }
274 
275     /* need to maintain socket_mask since we roll our own accept */
276 
277     FD_SET(plSock->Socket.socket, &socket_mask);
278     return (Sock *) plSock;
279 }
280 
281 static void
accept_menu_server_connection(HyperDocPage * page)282 accept_menu_server_connection(HyperDocPage *page)
283 {
284 
285     /*
286      * TTT thinks this code should just provide a Sock to the page. The only
287      * client assumed is a spadbuf. Since spadbuf was invoked with the page
288      * name, it just passes it back here as a check (get_string line).
289      */
290     int ret_code/*, i*/;
291     fd_set rd;
292     Sock *sock;
293     char *buf_name;
294     HyperDocPage *npage;
295 
296     if (page->sock != NULL)
297         return;
298     while (1) {
299         rd = server_mask;
300         ret_code = sselect(FD_SETSIZE, &rd, 0, 0, NULL);
301         if (ret_code == -1) {
302             perror("Session manager select");
303             continue;
304         }
305 
306         if (server[1].socket > 0 && FD_ISSET(server[1].socket, &rd)) {
307             sock = accept_menu_connection(server + 1);
308             if (sock == 0)
309                 return;
310             if (sock->purpose == InterpWindow) {
311                 buf_name = get_string(sock);
312                 npage = (HyperDocPage *)
313                     hash_find(gWindow->fPageHashTable, buf_name);
314                 if (npage == NULL) {
315 
316                     /*
317                      * Lets just try using the current page TTT doesn't know
318                      * why this could be detrimental
319                      *
320                      * fprintf(stderr, "connecting spadbuf to unknown page:
321                      * %s\n", buf_name);
322                      */
323                     page->sock = sock;
324                     return;
325                 }
326                 else {
327 
328                     /*
329                      * For some reason npage and page may be different TTT
330                      * thinks this happens when a dynamic page has the same
331                      * name as an existing static page.
332                      */
333                     npage->sock = sock;
334                     page->sock = sock;
335                 }
336                 if (!strcmp(buf_name, page->name)) {
337                     return;
338                 }
339             }
340         }
341     }
342 }
343 
344 
345 /*
346  * This procedure takes a HyperDoc node, and expands it into string
347  */
348 
349 /*
350  * This routine takes a text node and creates a string out of it. This is for
351  * use with things such as spad commands. There are  a very limited set of
352  * node types it can handle, so be careful
353  */
354 
355 char *
print_to_string(TextNode * command)356 print_to_string(TextNode *command)
357 {
358     int len = 0;
359 
360     print_to_string1(command, &len);
361     p2sBuf = resizeBuffer(len, p2sBuf, &p2sBufSize);
362     return print_to_string1(command, NULL);
363 }
364 
365 /*
366 see the code in ht-util.boot
367         $funnyQuote := char 127
368         $funnyBacks := char 128
369 */
370 #define funnyEscape(c)  ((c) == '"' ? '\177' : ((c) == '\\' ? '\200' : c))
371 #define funnyUnescape(c) ((c) == '\177' ? '"' : ((c) == '\200' ? '\\' : c))
372 #define storeChar(ch) \
373   do { if (sizeBuf) { (*sizeBuf)++;} else {*c++ = (ch);} } while(0)
374 #define storeString(str) for (s=str;*s;s++) {storeChar(*s);}
375 
376 extern int include_bf;
377 
378 char *
print_to_string1(TextNode * command,int * sizeBuf)379 print_to_string1(TextNode *command,int * sizeBuf)
380 {
381     char *c = p2sBuf;
382     char *s;
383     InputItem *item;
384     LineStruct *curr_line;
385     int lcount;
386     InputBox *box;
387     int num_spaces;
388     int count;
389     TextNode *node;
390 
391     /*
392      * Init the stack of text nodes, things are pushed on here when I trace
393      * through a nodes data.node. This way we always know where the next is.
394      */
395 
396     for (node = command; node != NULL;) {
397         switch (node->type) {
398           case Newline:
399             storeChar('\n');
400             node = node->next;
401             break;
402           case Ifcond:
403             if (check_condition(node->data.ifnode->cond))
404                 node = node->data.ifnode->thennode;
405             else
406                 node = node->data.ifnode->elsenode;
407             break;
408           case Endarg:
409           case Endspadcommand:
410           case Endspadsrc:
411           case Endpix:
412             storeChar('\0');
413             return p2sBuf;
414           case Endverbatim:
415           case Endif:
416           case Fi:
417           case Endmacro:
418           case Endparameter:
419           case Rbrace:
420           case Endgroup:
421             node = node->next;
422             break;
423           case Punctuation:
424 
425             /*
426              * Simply copy the piece of text
427              */
428             if (node->space & FRONTSPACE) { storeChar(' '); }
429             for (s = node->data.text; *s; s++) { storeChar(*s); }
430             node = node->next;
431             break;
432           case WindowId:
433 
434             /*
435              * Simply copy the piece of text
436              */
437             if (node->space) { storeChar(' '); }
438             for (s = node->data.text; *s; s++) { storeChar(*s); }
439             storeChar(' ');
440             node = node->next;
441             break;
442           case Verbatim:
443           case Spadsrctxt:
444 
445             /*
446              * Simply copy the piece of text
447              */
448             if (node->space) { storeChar(' '); }
449             for (s = node->data.text; *s; s++) { storeChar(*s); }
450 
451             /*
452              * now add the eol
453              */
454 
455             /*
456              * if(node->next && node->next->type != Endspadsrc)
457              * storeChar('\n');
458              */
459             node = node->next;
460             break;
461           case Dash:
462           case Rsquarebrace:
463           case Lsquarebrace:
464           case Word:
465 
466             /*
467              * Simply copy the piece of text
468              */
469             if (node->space) { storeChar(' '); }
470             for (s = node->data.text; *s; s++) { storeChar(*s); }
471             node = node->next;
472             break;
473           case BoxValue:
474             box =
475              (InputBox *) hash_find(gWindow->page->box_hash, node->data.text);
476             if (box == NULL) {
477                 fprintf(stderr,
478                         "Print_to_string:Box %s Has no symbol table entry\n",
479                         node->data.text);
480                 exit(-1);
481             }
482             storeChar(' ');
483             if (box->picked) {
484                 storeChar('t');
485             }
486             else {
487                 storeChar('n');
488                 storeChar('i');
489                 storeChar('l');
490             }
491             node = node->next;
492             break;
493           case StringValue:
494             item = return_item(node->data.text);
495             if (item != NULL) {
496                 if (node->space)
497                     storeChar(' ');
498                 curr_line = item->lines;
499                 while (curr_line != NULL) {
500                     for (lcount = 0, s = curr_line->buffer; *s && lcount < item->size;
501                          s++, lcount++) {
502                         storeChar(funnyEscape(*s));
503                     }
504                     if (curr_line->len <= item->size && curr_line->next)
505                         storeChar('\n');
506                     curr_line = curr_line->next;
507                 }
508             }
509             else if ((box = (InputBox *) hash_find(gWindow->page->box_hash,
510                                                 node->data.text)) != NULL) {
511                 if (node->space) { storeChar(' '); }
512                 if (box->picked) {
513                     storeChar('t');
514                 }
515                 else {
516                     storeChar('n');
517                     storeChar('i');
518                     storeChar('l');
519                 }
520             }
521             else {
522                 fprintf(stderr, "Error, Symbol %s has no symbol table entry\n",
523                         node->data.text);
524                 exit(-1);
525             }
526             node = node->next;
527             break;
528           case Space:
529             num_spaces = (node->data.node != NULL ?
530                           atoi(node->data.node->data.text) : 1);
531             for (count = 0; count < num_spaces; count++)
532                 storeChar(' ');
533             node = node->next;
534             break;
535           case Titlenode:
536           case Endtitle:
537           case Center:
538           case Endcenter:
539           case BoldFace:
540           case Emphasize:
541           case Indentrel:
542             node = node->next;
543             break;
544           case Bound:
545             if (include_bf) {
546                 int len, i;
547                 TextNode *n2 = node->data.node;
548 
549                 storeChar('\\');
550                 storeChar('b');
551                 storeChar('o');
552                 storeChar('u');
553                 storeChar('n');
554                 storeChar('d');
555                 storeChar('{');
556                 for (; n2->type != Endarg; n2 = n2->next) {
557                     if (n2->type == Word) {
558                         len = strlen(n2->data.text);
559                         for (i = 0; i < len; i++)
560                             storeChar(n2->data.text[i]);
561                         storeChar(' ');
562                     }
563                 }
564                 storeChar('}');
565             }
566             node = node->next;
567             break;
568           case Free:
569             if (include_bf) {
570                 int len, i;
571                 TextNode *n2 = node->data.node;
572 
573                 storeChar('\\');
574                 storeChar('f');
575                 storeChar('r');
576                 storeChar('e');
577                 storeChar('e');
578                 storeChar('{');
579                 for (; n2->type != Endarg; n2 = n2->next) {
580                     if (n2->type == Word) {
581                         len = strlen(n2->data.text);
582                         for (i = 0; i < len; i++)
583                             storeChar(n2->data.text[i]);
584                         storeChar(' ');
585                     }
586                 }
587                 storeChar('}');
588             }
589             node = node->next;
590             break;
591           case Macro:
592             node = node->next;
593             break;
594           case Pound:
595             if (node->space) { storeChar(' '); }
596             node = node->next;
597             break;
598           case Group:
599             node = node->next;
600             break;
601           case Indent:
602             num_spaces = (node->data.node != NULL ?
603                           atoi(node->data.node->data.text) : 1);
604             for (count = 0; count < num_spaces; count++)
605                 storeChar(' ');
606             node = node->next;
607             break;
608           default:
609             fprintf(stderr,
610                     "Print_to_string: Unrecognized Keyword Type %d\n",
611                     node->type);
612             node=node->next;
613             break;
614         }
615     }
616     storeChar('\0');
617     return p2sBuf;
618 }
619 
620 /*
621  * Send a lisp or spad command to the FriCAS server for execution , if
622  * type is link, then we wait for a HyperDoc card to be returned
623  */
624 
625 HyperDocPage *
issue_server_command(HyperLink * link)626 issue_server_command(HyperLink *link)
627 {
628     TextNode *command = (TextNode *) link->reference.node;
629     int ret_val;
630     char *buf;
631     HyperDocPage *page;
632 
633     ret_val = connect_spad();
634     if (ret_val == NotConnected) {
635         page = (HyperDocPage *) hash_find(gWindow->fPageHashTable, "SpadNotConnectedPage");
636         if (page == NULL)
637             fprintf(stderr, "No SpadNotConnectedPage found\n");
638         return page;
639     }
640     if (ret_val == SpadBusy) {
641         page = (HyperDocPage *) hash_find(gWindow->fPageHashTable, "SpadBusyPage");
642         if (page == NULL)
643             fprintf(stderr, "No SpadBusyPage found\n");
644         return page;
645     }
646     switch_frames();
647     switch (link->type) {
648       case Qspadcall:
649       case Qspadcallquit:
650       case Spadlink:
651       case Spaddownlink:
652       case Spadmemolink:
653         send_int(spad_socket, QuietSpadCommand);
654         break;
655       case Spadcall:
656       case Spadcallquit:
657         send_int(spad_socket, SpadCommand);
658         break;
659       default:
660         send_int(spad_socket, LispCommand);
661         break;
662     }
663     buf = print_to_string(command);
664     send_string(spad_socket, buf);
665     if (link->type == Lispcommand || link->type == Spadcall
666         || link->type == Spadcallquit || link->type == Qspadcallquit
667         || link->type == Qspadcall || link->type == Lispcommandquit)
668         return NULL;
669     page = parse_page_from_socket();
670     return page;
671 }
672 
673 int
issue_serverpaste(TextNode * command)674 issue_serverpaste(TextNode *command)
675 {
676     char *buf;
677     int ret_val;
678 
679     ret_val = connect_spad();
680     if (ret_val == NotConnected || ret_val == SpadBusy)
681         return 1;
682     switch_frames();
683     send_int(spad_socket, LispCommand);
684     buf = print_to_string(command);
685     send_string(spad_socket, buf);
686     return 1;
687 }
688 
689 /*
690  * issue a unix command
691  */
692 void
issue_unixcommand(TextNode * node)693 issue_unixcommand(TextNode *node)
694 {
695     char *buf;
696     char *copy;
697 
698 
699     buf = print_to_string(node);
700     copy =(char *) halloc((strlen(buf)+2)*sizeof(char),"Unixcommand");
701     strcpy(copy,buf);
702     copy[strlen(buf) + 1] = '\0';
703     copy[strlen(buf)] = '&';
704     system(copy);
705     free(copy);
706     return;
707 }
708 
709 HyperDocPage *
issue_unixlink(TextNode * node)710 issue_unixlink(TextNode *node)
711 {
712     HyperDocPage *page;
713     char *buf;
714 
715     buf = print_to_string(node);
716     if ((unixfd = popen(buf, "r")) == NULL) {
717         fprintf(stderr, "Error popening %s\n", buf);
718         exit(-1);
719     }
720     bsdSignal(SIGUSR2,SIG_IGN,0);
721     page = parse_page_from_unixfd();
722     bsdSignal(SIGUSR2,sigusr2_handler,0);
723     return page;
724 }
725 
726 int
issue_unixpaste(TextNode * node)727 issue_unixpaste(TextNode *node)
728 {
729     char *buf;
730 
731     buf = print_to_string(node);
732     if ((unixfd = popen(buf, "r")) == NULL) {
733         fprintf(stderr, "Error popening %s\n", buf);
734         exit(-1);
735     }
736     return 1;
737 }
738 
739 
740 /*
741  * called when session_server selects
742  */
743 void
service_session_socket(void)744 service_session_socket(void)
745 {
746     int cmd, pid;
747 
748     cmd = get_int(session_server);
749     switch (cmd) {
750       case CloseClient:
751         pid = get_int(session_server);
752         if (pid != -1)
753             close_client(pid);
754         break;
755       default:
756         fprintf(stderr,
757                 "(HyperDoc) Unknown command from SessionServer %d\n", cmd);
758         break;
759     }
760 }
761 
762 
763 /*
764  * let spad know which frame to issue command via
765  */
766 static void
switch_frames(void)767 switch_frames(void)
768 {
769     if (session_server == NULL) {
770         fprintf(stderr, "(HyperDoc) No session manager connected!\n");
771         return;
772     }
773     if (gWindow->fricas_frame == -1) {
774         fprintf(stderr, "(HyperDoc) No FriCAS frame associated with top level window!\n");
775         return;
776     }
777     send_int(session_server, SwitchFrames);
778     send_int(session_server, gWindow->fricas_frame);
779 }
780 void
send_lisp_command(char * command)781 send_lisp_command(char *command)
782 {
783     int ret_val;
784 
785     ret_val = connect_spad();
786     if (ret_val == NotConnected || ret_val == SpadBusy) {
787         return;
788     }
789     send_int(spad_socket, LispCommand);
790     send_string(spad_socket, command);
791 }
792 void
escape_string(char * s)793 escape_string(char *s)
794 {
795     char *st;
796 
797     for (st = s; *st; st++)
798         *st = funnyEscape(*st);
799 }
800 void
unescape_string(char * s)801 unescape_string(char *s)
802 {
803     char *st;
804 
805     for (st = s; *st; st++)
806         *st = funnyUnescape(*st);
807 }
808 static void
close_client(int pid)809 close_client(int pid)
810 {
811     /*int i;*/
812     Sock_List *pSock, *locSock;
813 
814     /*
815      * just need to drop the list item
816      */
817 
818     if (plSock == (Sock_List *) 0)
819         return;
820 
821     /*
822      * first check head
823      */
824 
825     if ((plSock->Socket.pid == pid)) {
826         locSock = plSock;
827         if ((*plSock).next == (Sock_List *) 0) {
828             plSock = (Sock_List *) 0;
829         }
830         else {
831             plSock = plSock->next;
832         }
833         free(locSock);
834     }
835 
836     /*
837      * now check the rest
838      */
839 
840     else {
841         for (pSock = plSock; pSock->next != (Sock_List *) 0; pSock = pSock->next)
842             if (pSock->next->Socket.pid == pid) {
843                 locSock = pSock->next;
844                 if (pSock->next->next == (Sock_List *) 0) {
845                     pSock->next = (Sock_List *) 0;
846                 }
847                 else {
848                     pSock->next = pSock->next->next;
849                 }
850                 free(locSock);
851                 break;
852             }
853     }
854 }
855 
856 
857 
858 char *
print_source_to_string(TextNode * command)859 print_source_to_string(TextNode *command)
860 {
861     int len = 0;
862 
863     print_source_to_string1(command, &len);
864     p2sBuf = resizeBuffer(len, p2sBuf, &p2sBufSize);
865     return print_source_to_string1(command, NULL);
866 }
867 char *
print_source_to_string1(TextNode * command,int * sizeBuf)868 print_source_to_string1(TextNode *command,int * sizeBuf)
869 {
870     char *c = p2sBuf;
871     char *s;
872     InputItem *item;
873     LineStruct *curr_line;
874     int lcount;
875     InputBox *box;
876     int num_spaces;
877     int count;
878     TextNode *node;
879 
880     /*
881         print out HyperDoc source for what you see
882      */
883 
884     for (node = command; node != NULL;) {
885         switch (node->type) {
886           case Newline:
887             storeString("\\newline\n");
888             node = node->next;
889             break;
890           case Par:
891             storeString("\n\n");
892             node = node->next;
893             break;
894           case Indentrel:
895             storeString("\\indentrel{");
896             storeString(node->data.node->data.text);
897             storeChar('}');
898             node = node->next;
899             break;
900           case Tab:
901             storeString("\\tab{");
902             storeString(node->data.node->data.text);
903             storeChar('}');
904             node = node->next;
905             break;
906           case Ifcond:
907             if (check_condition(node->data.ifnode->cond))
908                 node = node->data.ifnode->thennode;
909             else
910                 node = node->data.ifnode->elsenode;
911             break;
912           case Endarg:
913           case Endspadsrc:
914           case Endpix:
915           case Endbutton:
916             storeChar('}');
917             node = node->next;
918             break;
919           case Endverbatim:
920           case Endif:
921           case Fi:
922           case Endmacro:
923           case Endparameter:
924           case Rbrace:
925             node = node->next;
926             break;
927           case Punctuation:
928 
929             /*
930              * Simply copy the piece of text
931              */
932             if (node->space & FRONTSPACE) { storeChar(' '); }
933             for (s = node->data.text; *s; s++) { storeChar(*s); }
934             node = node->next;
935             break;
936           case WindowId:
937             storeString("\\windowid ");
938             node = node->next;
939             break;
940           case Verbatim:
941           case Spadsrctxt:
942             if (node->space) { storeChar(' '); }
943             for (s = node->data.text; *s; s++) { storeChar(*s); }
944             node = node->next;
945             break;
946           case Dash:
947           case Rsquarebrace:
948           case Lsquarebrace:
949           case Word:
950             if (node->space) { storeChar(' '); }
951             for (s = node->data.text; *s; s++) { storeChar(*s); }
952             node = node->next;
953             break;
954           case BoxValue:
955             box = (InputBox *) hash_find(gWindow->page->box_hash, node->data.text);
956             if (box == NULL) {
957                 fprintf(stderr, "Print_to_string:Box %s Has no symbol table entry\n",
958                         node->data.text);
959                 exit(-1);
960             }
961             storeChar(' ');
962             if (box->picked) {
963                 storeChar('t');
964             }
965             else {
966                 storeChar('n');
967                 storeChar('i');
968                 storeChar('l');
969             }
970             node = node->next;
971             break;
972           case StringValue:
973             item = return_item(node->data.text);
974             if (item != NULL) {
975                 if (node->space) {  storeChar(' '); }
976                 curr_line = item->lines;
977                 while (curr_line != NULL) {
978                     for (lcount = 0, s = curr_line->buffer;
979                          *s && lcount < item->size;
980                          s++, lcount++) {
981                         storeChar(funnyUnescape(*s));
982                     }
983                     if (curr_line->len <= item->size && curr_line->next)
984                         storeChar('\n');
985                     curr_line = curr_line->next;
986                 }
987             }
988             else if ((box = (InputBox *) hash_find(gWindow->page->box_hash,
989                                                 node->data.text)) != NULL) {
990                 if (node->space) { storeChar(' '); }
991                 if (box->picked) {
992                     storeChar('t');
993                 }
994                 else {
995                     storeChar('n');
996                     storeChar('i');
997                     storeChar('l');
998                 }
999             }
1000             else {
1001                 fprintf(stderr, "Error, Symbol %s has no symbol table entry\n",
1002                         node->data.text);
1003                 exit(-1);
1004             }
1005             node = node->next;
1006             break;
1007           case Space:
1008             num_spaces = (node->data.node != NULL ?
1009                           atoi(node->data.node->data.text) : 1);
1010             for (count = 0; count < num_spaces; count++)
1011                 storeChar(' ');
1012             node = node->next;
1013             break;
1014           case Emphasize:
1015             storeString("\\em ");
1016             node = node->next;
1017             break;
1018           case BoldFace:
1019             storeString("\\bf ");
1020             node = node->next;
1021             break;
1022           case Sl:
1023             storeString("\\it ");
1024             node = node->next;
1025             break;
1026           case Rm:
1027             storeString("\\rm ");
1028             node = node->next;
1029             break;
1030           case It:
1031             storeString("\\it ");
1032             node = node->next;
1033             break;
1034           case Tt:
1035             storeString("\\tt ");
1036             node = node->next;
1037             break;
1038           case Group:
1039 /* skip {} */
1040             if (node->next->type==Endgroup){
1041                node=node->next->next;
1042                break;
1043                 }
1044             storeChar('{');
1045             node = node->next;
1046             break;
1047           case Endgroup:
1048             storeChar('}');
1049             node = node->next;
1050             break;
1051           case Box:
1052             storeString("\\box{");
1053             node = node->next;
1054             break;
1055           case Endbox:
1056             storeChar('}');
1057             node = node->next;
1058             break;
1059           case Center:
1060             storeString("\\center{");
1061             node = node->next;
1062             break;
1063           case Endcenter:
1064             storeString("}");
1065             storeChar('\n');
1066             node = node->next;
1067             break;
1068           case Titlenode:
1069           case Endtitle:
1070             node = node->next;
1071             break;
1072           case Bound:
1073             {
1074                 TextNode *n2 = node->data.node;
1075 
1076                 storeString("\\bound{");
1077                 for (; n2->type != Endarg; n2 = n2->next) {
1078                     if (n2->type == Word) {
1079                         storeString(n2->data.text);
1080                         storeChar(' ');
1081                         }
1082                     }
1083                 storeChar('}');
1084             }
1085             node = node->next;
1086             break;
1087           case Free:
1088             {
1089                 TextNode *n2 = node->data.node;
1090 
1091                 storeString("\\free{");
1092                 for (; n2->type != Endarg; n2 = n2->next) {
1093                     if (n2->type == Word) {
1094                         storeString(n2->data.text);
1095                         storeChar(' ');
1096                         }
1097                     }
1098                 storeChar('}');
1099                 }
1100             node = node->next;
1101             break;
1102           case Macro:
1103             storeChar(' ');
1104             node = node->next;
1105             break;
1106           case Pound:
1107             if (node->space) { storeChar(' '); }
1108             node = node->next;
1109             break;
1110           case Indent:
1111             num_spaces = (node->data.node != NULL ?
1112                           atoi(node->data.node->data.text) : 1);
1113             for (count = 0; count < num_spaces; count++)
1114                 storeChar(' ');
1115             node = node->next;
1116             break;
1117           case Inputbitmap:
1118             storeString("\\inputbitmap{");
1119             storeString(node->data.text);
1120             storeString("}\n");
1121             node = node->next;
1122             break;
1123           case Endscrolling:
1124             storeString("\\end{scroll}\n");
1125             node = node->next;
1126             break;
1127           case Scrollingnode:
1128             storeString("\\begin{scroll}\n");
1129             storeString("% This is the scrolling area\n");
1130             node = node->next;
1131             break;
1132           case Horizontalline:
1133             storeString("\\horizontalline\n");
1134             node = node->next;
1135             break;
1136           case Endtable:
1137             storeChar('}');
1138             node = node->next;
1139             break;
1140           case Table:
1141             storeString("\\table{");
1142             node = node->next;
1143             break;
1144           case Tableitem:
1145             storeChar('{');
1146             node = node->next;
1147             break;
1148           case Endtableitem:
1149             storeChar('}');
1150             node = node->next;
1151             break;
1152           case Beginitems:
1153             storeString("\\begin{items}");
1154             node = node->next;
1155             break;
1156           case Item:
1157             storeString("\n\\item");
1158             node = node->next;
1159             break;
1160           case Enditems:
1161             storeString("\n\\end{items}");
1162             node = node->next;
1163             break;
1164 /*** LINKS ***/
1165 /* all these guys are ended by Endbutton
1166 we close the brace then */
1167           case Spadlink:
1168             storeString("\\fauxspadlink{");
1169             node = node->next;
1170             break;
1171           case Unixlink:
1172             storeString("\\fauxunixlink{");
1173             node = node->next;
1174             break;
1175           case Lisplink:
1176             storeString("\\fauxlisplink{");
1177             node = node->next;
1178             break;
1179           case Link:
1180             storeString("\\fauxlink{");
1181             node = node->next;
1182             break;
1183           case LispDownLink:
1184             storeString("\\fauxlispdownlink{");
1185             node = node->next;
1186             break;
1187           case LispMemoLink:
1188             storeString("\\fauxlispmemolink{");
1189             node = node->next;
1190             break;
1191           case Memolink:
1192             storeString("\\fauxmemolink{");
1193             node = node->next;
1194             break;
1195           case Windowlink:
1196             storeString("\\fauxwindowlink{");
1197             node = node->next;
1198             break;
1199           case Downlink:
1200             storeString("\\fauxdownlink{");
1201             node = node->next;
1202             break;
1203 /** END OF LINKS **/
1204           case Unixcommand:
1205             storeString("\\unixcommand{");
1206             node = node->next;
1207             break;
1208           case Lispcommand:
1209             storeString("\\lispcommand{");
1210             node = node->next;
1211             break;
1212           case Spadgraph:
1213             storeString("\\spadgraph{");
1214             node = node->next;
1215             break;
1216           case Spadcommand:
1217             storeString("\\spadcommand{");
1218             node = node->next;
1219             break;
1220           case Endspadcommand:
1221             storeChar('}');
1222             node = node->next;
1223             break;
1224           case Footernode:
1225             storeString("% This is the footer\n");
1226             node = node->next;
1227             break;
1228           case Endfooter:
1229             storeString("% This is the end of the footer\n");
1230             node = node->next;
1231             break;
1232           case Endheader:
1233             storeString("% This is the end of the header\n");
1234             node = node->next;
1235             break;
1236           case Headernode:
1237             storeString("% This is the header\n");
1238             node = node->next;
1239             break;
1240           default:
1241             fprintf(stderr,
1242                     "Print_source_to_string: Unrecognized Keyword Type %d\n",
1243                     node->type);
1244             node=node->next;
1245             break;
1246         }
1247     }
1248     storeChar('\0');
1249     return p2sBuf;
1250 }
1251