1 /*===========================================================================*/
2 /* */
3 /* This file is part of the SYMPHONY MILP Solver Framework. */
4 /* */
5 /* SYMPHONY was jointly developed by Ted Ralphs (ted@lehigh.edu) and */
6 /* Laci Ladanyi (ladanyi@us.ibm.com). */
7 /* */
8 /* The Interactive Graph Drawing application was developed by Marta Eso. */
9 /* */
10 /* (c) Copyright 2000-2019 Ted Ralphs. All Rights Reserved. */
11 /* */
12 /* This software is licensed under the Eclipse Public License. Please see */
13 /* accompanying file for terms. */
14 /* */
15 /*===========================================================================*/
16
17 #if defined(_MSC_VER) || defined (__MNO_CYGWIN)
18 #include <io.h>
19 #define execlp _execlp
20 #include <process.h>
21 #else
22 #include <unistd.h>
23 #endif
24 #include <memory.h>
25 #include <fcntl.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <stdarg.h>
30
31 #include "sym_constants.h"
32 #include "sym_macros.h"
33 #include "sym_proccomm.h"
34 #include "sym_messages.h"
35 #include "sym_dg.h"
36 #include "sym_dg_params.h"
37
38 /*===========================================================================*/
39
INTERMED_ERROR(char * window_name,int old_msgtag,int receiver,int msgtag)40 void INTERMED_ERROR(char *window_name, int old_msgtag,
41 int receiver, int msgtag)
42 {
43 int s_bufid;
44 s_bufid = init_send(DataInPlace);
45 send_char_array(window_name, MAX_NAME_LENGTH);
46 send_int_array(&old_msgtag, 1);
47 send_msg(receiver, msgtag);
48 freebuf(s_bufid);
49 }
50
51 /*===========================================================================*/
52
53 static int echo_commands;
spprint(FILE * write_to,const char * format,...)54 int spprint(FILE *write_to, const char *format, ...)
55 {
56 int i;
57 va_list ap;
58
59 va_start(ap, format);
60 if (echo_commands) vprintf(format, ap);
61 va_end(ap);
62 va_start(ap, format);
63 i = vfprintf(write_to, format, ap);
64 va_end(ap);
65 return(i);
66 }
67
68 /*===========================================================================*/
69
70 /*===========================================================================*\
71 * Exec the named cmd as a child process, returning two pipes to
72 * communicate with the process, and the child's process ID.
73 \*===========================================================================*/
74
start_child(char * cmd,FILE ** readpipe,FILE ** writepipe)75 int start_child(char *cmd, FILE **readpipe, FILE **writepipe)
76 {
77
78 /* FIXME: Doesn't seem to work for Windows */
79
80 #if !defined(_MSC_VER) && !defined (__MNO_CYGWIN)
81
82 int childpid, pipe1[2], pipe2[2];
83
84 #if !defined(_MSC_VER) && !defined (__MNO_CYGWIN)
85 if ((pipe(pipe1) < 0) || (pipe(pipe2) < 0)){
86 perror("pipe");
87 exit(-1);
88 }
89 #else
90 if ((_pipe(pipe1,256,O_BINARY) < 0) || (_pipe(pipe2,256,O_BINARY) < 0)){
91 perror("pipe");
92 exit(-1);
93 }
94 #endif
95
96 if ((childpid = vfork()) < 0){
97 perror("fork");
98 exit(-1);
99 }else if (childpid > 0){ /* parent */
100 close(pipe1[0]);
101 close(pipe2[1]);
102 /* write to child is pipe1[1], read from child is pipe2[0] */
103 *readpipe = fdopen(pipe2[0], "r");
104 /* this sets the pipe to be a Non-Blocking IO one, so fgets won't wait
105 * until it receives a line. */
106 fcntl(pipe2[0], F_SETFL, O_NONBLOCK);
107 *writepipe = fdopen(pipe1[1], "w");
108 setlinebuf(*writepipe);
109 return(childpid);
110 }else{ /* child */
111 close(pipe1[1]);
112 close(pipe2[0]);
113 /* read from parent is pipe1[0], write to parent is pipe2[1] */
114 dup2(pipe1[0], 0);
115 dup2(pipe2[1], 1);
116 close(pipe1[0]);
117 close(pipe2[1]);
118 if (execlp(cmd, cmd, NULL) < 0)
119 perror("execlp");
120
121 /* never returns */
122 }
123
124 #endif
125
126 return(0);
127 }
128
129 /*===========================================================================*/
130
main(void)131 int main(void)
132 {
133 dg_prob *dgp;
134 dg_params *par;
135 FILE *read_from, *write_to;
136 int childpid, sender;
137
138 char tcl_msg[MAX_LINE_LENGTH +1];
139 char name[MAX_NAME_LENGTH +1], name2[MAX_NAME_LENGTH +1];
140 char source[MAX_NAME_LENGTH +1], target[MAX_NAME_LENGTH +1];
141 char title[MAX_TITLE_LENGTH +1], title2[MAX_TITLE_LENGTH +1];
142 char fname[MAX_FILE_NAME_LENGTH +1];
143 char old_weight[MAX_WEIGHT_LENGTH +1], new_weight[MAX_WEIGHT_LENGTH +1];
144 char new_label[MAX_LABEL_LENGTH +1];
145 char new_dash[MAX_DASH_PATTERN_LENGTH +1];
146 char *str;
147 int msgtag, keyword, key, r_bufid, s_bufid, bufid, bytes, len;
148
149 int i, j, k, number, add_nodenum, change_nodenum, delete_nodenum;
150 int add_edgenum, change_edgenum, delete_edgenum;
151 int nodenum, new_nodenum, edgenum, new_edgenum, node_id, edge_id;
152 int new_radius, old_deleted_nodenum;
153 unsigned int id;
154 win_desc *desc;
155 dg_graph *g;
156 dg_node *nodes, *nod;
157 dg_edge *edges, *edg;
158 window *win, *new_win, *source_win, *target_win;
159
160 register_process();
161 dgp = (dg_prob *) calloc(1, sizeof(dg_prob));
162
163 /* receive parameters from the master */
164 r_bufid = receive_msg(ANYONE, DG_DATA);
165 bufinfo(r_bufid, &bytes, &msgtag, &dgp->master);
166 receive_char_array((char *)&dgp->par, sizeof(dg_params));
167 freebuf(r_bufid);
168 par = &(dgp->par);
169 echo_commands = par->echo_commands;
170
171 /* fork the wish shell */
172 childpid = start_child((char *)"wish", &read_from, &write_to);
173
174 /* Source the tcl scripts into wish and invoke startUp*/
175 spprint(write_to, "source %s/Init.tcl\n", par->source_path);
176 spprint(write_to, "source %s/Tools.tcl\n", par->source_path);
177 spprint(write_to, "source %s/NodeEdgeBasics.tcl\n", par->source_path);
178 spprint(write_to, "source %s/FileMenu.tcl\n", par->source_path);
179 spprint(write_to, "source %s/WindowMenu.tcl\n", par->source_path);
180 spprint(write_to, "source %s/NodeMenu.tcl\n", par->source_path);
181 spprint(write_to, "source %s/EdgeMenu.tcl\n", par->source_path);
182 spprint(write_to, "source %s/CAppl.tcl\n", par->source_path);
183
184 spprint(write_to, "Igd_StartUp\n");
185
186 /* set application defaults to those stored in par */
187 spprint(write_to,
188 "Igd_SetApplDefaults %i %i %i %i %i %i %i {%s} {%s} %i %i %i %f {%s} {%s} {%s}\n",
189 par->canvas_width, par->canvas_height, par->viewable_width,
190 par->viewable_height, par->disp_nodelabels,
191 par->disp_nodeweights, par->disp_edgeweights, par->node_dash,
192 par->edge_dash, par->node_radius, par->interactive_mode,
193 par->mouse_tracking, par->scale_factor, par->nodelabel_font,
194 par->nodeweight_font, par->edgeweight_font);
195
196 /* invoke user initialization */
197 #ifdef USE_SYM_APPLICATION
198 CALL_USER_FUNCTION( user_initialize_dg(&dgp->user) );
199 #endif
200
201 while(TRUE){
202
203 msgtag = 0;
204
205 if (dgp->waiting_to_die){
206 for ( i = 0; i < dgp->window_num; ){
207 if ( ! dgp->windows[i]->wait_for_click ){
208 spprint(write_to, "Igd_QuitWindow %u\n",dgp->windows[i]->id);
209 free_window(&dgp->window_num, dgp->windows, i);
210 }else{
211 i++;
212 }
213 }
214 if ( ! dgp->window_num )
215 wait_for_you_can_die(dgp, write_to);
216 }
217
218 /* Interpret message coming from the tcl application. */
219 if (fgets(tcl_msg, 80, read_from) != NULL) {
220 sscanf(tcl_msg, "%i", &msgtag);
221
222 switch(msgtag){
223
224 case IGDTOI_CLICK_HAPPENED:
225 /* if wait_for_click is 2, send a message to the owner */
226 fgets(name2, MAX_NAME_LENGTH +1, read_from);
227 sscanf(name2, "%u", &id);
228 for (i = dgp->window_num - 1; i >= 0; i-- )
229 if ( dgp->windows[i]->id == id )
230 break;
231 if ( i < 0 ) {
232 /* this should never happen */
233 printf("Window of id %u is not found\n", id);
234 break;
235 }
236 if ( dgp->windows[i]->wait_for_click == 2 ) {
237 s_bufid = init_send(DataInPlace);
238 send_str(name);
239 send_msg(dgp->windows[i]->owner_tid, ITOC_CLICK_HAPPENED);
240 freebuf(s_bufid);
241 }
242 dgp->windows[i]->wait_for_click = 0;
243 break;
244
245 case IGDTOI_QUIT_WINDOW:
246 /* delete data structure corresponding to this window */
247 fgets(name2, MAX_NAME_LENGTH +1, read_from);
248 sscanf(name2, "%u", &id);
249 for (i = dgp->window_num - 1; i >= 0; i-- )
250 if ( dgp->windows[i]->id == id )
251 break;
252 if ( i < 0 ) {
253 /* this should never happen */
254 printf("Window of id %u is not found\n", id);
255 break;
256 }
257 spprint(write_to, "Igd_QuitWindow %u\n", id);
258 free_window(&dgp->window_num, dgp->windows, i);
259 break;
260
261 case IGDTOI_QUIT_APPLICATION:
262 /* delete all windows */
263 for ( i = 0; i < dgp->window_num; ){
264 if ( ! dgp->windows[i]->wait_for_click ){
265 spprint(write_to, "Igd_QuitWindow %u\n",dgp->windows[i]->id);
266 free_window(&dgp->window_num, dgp->windows, i);
267 }else{
268 i++;
269 }
270 }
271 dgp->waiting_to_die = TRUE;
272 break;
273
274 case IGDTOI_TEXT_ENTERED:
275 fgets(name2, MAX_NAME_LENGTH +1, read_from);
276 sscanf(name2, "%u", &id);
277 for (i = dgp->window_num - 1; i >= 0; i-- )
278 if ( dgp->windows[i]->id == id )
279 break;
280 win = dgp->windows[i];
281 if ( i < 0 ) {
282 /* this should never happen */
283 printf("Window of id %u is not found\n", id);
284 break;
285 }
286 fgets(tcl_msg, MAX_LINE_LENGTH +1, read_from);
287 sscanf(tcl_msg, "%i", &win->text_length);
288 win->text = (char *) malloc( (win->text_length + 1) * CSIZE);
289 fread(win->text, CSIZE, win->text_length, read_from);
290 win->text[win->text_length] = 0;
291
292 /* invoke function that interprets the message */
293 #ifdef USE_SYM_APPLICATION
294 CALL_USER_FUNCTION( user_interpret_text(dgp->user,
295 win->text_length,
296 win->text,
297 win->owner_tid) );
298 #endif
299 break;
300
301 case IGDTOI_REQUEST_GRAPH:
302 fgets(name2, MAX_NAME_LENGTH +1, read_from);
303 sscanf(name2, "%u", &id);
304 for (i = dgp->window_num - 1; i >= 0; i-- )
305 if ( dgp->windows[i]->id == id )
306 break;
307 if ( i < 0 ) {
308 /* this should never happen */
309 printf("Window of id %u is not found\n", id);
310 break;
311 }
312 display_graph_on_canvas(dgp->windows[i], write_to);
313 break;
314
315 default:
316 printf("Unknown message type from IGD to I (%i)\n", msgtag);
317 break;
318
319 } /* end switch */
320 } /* end if */
321
322 if (dgp->waiting_to_die)
323 continue;
324
325
326 /* Interpret the message coming from the C application.
327
328 All the messages except INITIALIZE_WINDOW and COPY_GRAPH
329 and QUIT will be put on the pipe corresponding to the appropriate
330 window (messages are processed in FIFO order
331
332 In case of INITIALIZE_WINDOW the data structure associated
333 with a winow is created (including the pipes.
334
335 In case of COPY_GRAPH a message must be placed on both the
336 source and the target window's pipe.
337
338 In case of QUIT all data structures are disassembled and then
339 the tcl application is killed. */
340
341 r_bufid = nreceive_msg(ANYONE, ANYTHING);
342 if (r_bufid > 0){
343 bufinfo(r_bufid, &bytes, &msgtag, &sender);
344 switch (msgtag){
345
346 case CTOI_INITIALIZE_WINDOW:
347
348 /* get the name of the new window */
349 receive_str(name);
350 receive_str(title);
351
352 /* if a window with this name already exists: error */
353 i = find_window(dgp->window_num, dgp->windows, name);
354 if ( i >= 0 ) {
355 INTERMED_ERROR(name, msgtag, sender,ITOC_WINDOW_ALREADY_EXISTS);
356 freebuf(r_bufid);
357 break;
358 }
359 /* allocate space for the new window */
360 win = init_dgwin(dgp, sender, name, title);
361
362 /* set up the window description */
363 receive_int_array(&number, 1);
364 copy_win_desc_from_par(win, &dgp->par);
365 for ( ; number > 0; number-- ) {
366 /* read out the key - value pairs */
367 receive_int_array(&key, 1);
368 set_window_desc_pvm(key, win);
369 }
370
371 freebuf(r_bufid);
372 break;
373
374
375 case CTOI_COPY_GRAPH:
376 /* Copy source's graph into target's window.
377 Here a message is placed onto both target's and source's
378 pipe so that they can wait for each other before the
379 actual copying happens (shake hands) */
380
381 receive_str(target);
382 receive_str(source);
383
384 i = find_window(dgp->window_num, dgp->windows, target);
385 if (i < 0) { /* target doesn't exist, send error message */
386 INTERMED_ERROR(target, msgtag, sender,ITOC_WINDOW_DOESNT_EXIST);
387 freebuf(r_bufid);
388 break;
389 }
390 j = find_window(dgp->window_num, dgp->windows, source);
391 if (j < 0) { /* source doesn't exist, send error message */
392 INTERMED_ERROR(source, msgtag, sender,ITOC_WINDOW_DOESNT_EXIST);
393 freebuf(r_bufid);
394 break;
395 }
396 bufid = init_send(DataInPlace);
397 msgtag = WAITING_TO_GET_A_COPY;
398 send_int_array(&msgtag, 1);
399 send_str(source);
400 add_msg(dgp->windows[i], bufid);
401 setsbuf(0);
402
403 bufid = init_send(DataInPlace);
404 msgtag = WAITING_TO_BE_COPIED;
405 send_int_array(&msgtag, 1);
406 send_str(target);
407 add_msg(dgp->windows[j], bufid);
408 setsbuf(0);
409
410 freebuf(r_bufid);
411 break;
412
413
414 case CTOI_QUIT:
415 /* quit from all windows, disassemble data structures.
416 * (actually, this will happen on the top of the while loop...) */
417 if (! dgp->waiting_to_die)
418 dgp->waiting_to_die = TRUE;
419 freebuf(r_bufid);
420 break;
421
422 case CTOI_YOU_CAN_DIE:
423 /* quit from all windows, disassemble data structures.
424 * (actually, this will happen on the top of the while loop...)
425 * and die */
426 dgp->waiting_to_die = 2 * TRUE;
427 freebuf(r_bufid);
428 break;
429
430
431 default:
432 /* Check if window with name exists. If not, send back error
433 message. If yes, copy the message over to window's pipe. */
434 receive_str(name);
435 len = strlen(name);
436 i = find_window(dgp->window_num, dgp->windows, name);
437 if (i < 0){
438 /* there is no window of that name: send error message */
439 INTERMED_ERROR(name, msgtag, sender,ITOC_WINDOW_DOESNT_EXIST);
440 freebuf(r_bufid);
441 break;
442 }
443
444 add_msg(dgp->windows[i], r_bufid);
445 setrbuf(0);
446 break;
447 } /* end switch */
448 } /* endif r_bufid > 0 */
449
450
451 if (dgp->waiting_to_die)
452 continue;
453
454 /* Process one message from each window's pipe. */
455
456 for ( i = 0; i < dgp->window_num; i++ ) {
457
458 win = dgp->windows[i];
459
460 /* if wait_for_click is set, skip */
461 if ( win->wait_for_click )
462 continue;
463
464 /* if window is waiting to be copied or waiting to get a copy, skip */
465 if ( win->copy_status )
466 continue;
467
468 /* if no message in the pipe, skip */
469 if (win->buf.bufread == -1)
470 continue;
471
472 /* else: process the message .... */
473 msgtag = 0;
474 r_bufid = get_next_msg(win);
475 setrbuf(r_bufid);
476 bufinfo(r_bufid, &bytes, &msgtag, &sender);
477
478 if (msgtag == 0){
479 /* This means that the message was locally 'hand-packed' */
480 receive_int_array(&msgtag, 1);
481 }
482
483 switch ( msgtag ) {
484
485 case CTOI_USER_MESSAGE:
486 #ifdef USE_SYM_APPLICATION
487 user_dg_process_message(win->user, win, write_to);
488 #endif
489 break;
490
491 case CTOI_QUIT_WINDOW:
492 /* delete this window */
493 spprint(write_to, "Igd_QuitWindow %u\n", win->id);
494 free_window(&dgp->window_num, dgp->windows, i);
495 i--;
496 break;
497
498
499 case CTOI_CHANGE_WINDOW_DESC:
500 /* change window descriptions */
501 receive_int_array(&number, 1);
502 for ( ; number > 0; number-- ) {
503 /* read out the key - value pairs */
504 receive_int_array(&key, 1);
505 set_window_desc_pvm(key, win);
506 }
507 desc = &(win->desc);
508 if ( win->window_displayed ) {
509 spprint(write_to, "Igd_SetAndExecuteWindowDesc %u %i %i %i %i %i %i %i {%s} {%s} %i %i %i %f {%s} {%s} {%s}\n",
510 win->id, desc->canvas_width, desc->canvas_height,
511 desc->viewable_width, desc->viewable_height,
512 desc->disp_nodelabels, desc->disp_nodeweights,
513 desc->disp_edgeweights, desc->node_dash,
514 desc->edge_dash, desc->node_radius,
515 desc->interactive_mode, desc->mouse_tracking,
516 desc->scale_factor, desc->nodelabel_font,
517 desc->nodeweight_font, desc->edgeweight_font);
518 }
519 break;
520
521
522 case CTOI_SET_GRAPH:
523 case CTOI_SET_AND_DRAW_GRAPH:
524 /* define the graph corresponding to this window */
525 g = &(win->g);
526 FREE(g->nodes);
527 FREE(g->edges);
528
529 receive_int_array(&g->nodenum, 1);
530 if ( g->nodenum ) {
531 nodes = g->nodes =
532 (dg_node *) malloc(g->nodenum * sizeof(dg_node));
533 for ( j = 0; j < g->nodenum; j++ ) {
534 read_node_desc_from_pvm(nodes+j, win);
535 }
536 }
537
538 receive_int_array(&g->edgenum, 1);
539 if ( g->edgenum ) {
540 edges = g->edges =
541 (dg_edge *) malloc(g->edgenum * sizeof(dg_edge));
542 for ( j = 0; j < g->edgenum; j++ ) {
543 read_edge_desc_from_pvm(edges+j, win);
544 }
545 }
546
547 if ( msgtag == CTOI_SET_AND_DRAW_GRAPH || win->window_displayed )
548 display_graph_on_canvas(win, write_to);
549
550 break;
551
552
553 case CTOI_DRAW_GRAPH:
554 /* first erase/create the window itself, then display all the nodes
555 and edges */
556 display_graph_on_canvas(win, write_to);
557 break;
558
559
560 case CTOI_DELETE_GRAPH:
561 /* delete the data structure of the graph and erase its window
562 if open */
563 FREE(win->g.nodes);
564 FREE(win->g.edges);
565 win->g.nodenum = win->g.deleted_nodenum = 0;
566 win->g.edgenum = win->g.deleted_edgenum = 0;
567 if ( win->window_displayed ){
568 spprint(write_to, "Igd_EraseWindow %u\n", win->id);
569 }
570 break;
571
572
573 case CTOI_WAIT_FOR_CLICK_NO_REPORT:
574 /* window will not get any messages until the Continue button
575 is pressed. the window has to be open to have an effect */
576 if ( win->window_displayed ) {
577 win->wait_for_click = 1;
578 spprint(write_to, "Igd_CApplWaitForClick %u\n", win->id);
579 } else {
580 INTERMED_ERROR(win->name, msgtag, win->owner_tid,
581 ITOC_WINDOW_ISNT_DISPLAYED);
582 }
583 break;
584
585
586 case CTOI_WAIT_FOR_CLICK_AND_REPORT:
587 /* window will not get any messages until the Continue button
588 is pressed. the window has to be open to have an effect.
589 the owner gets a message */
590 if ( win->window_displayed ) {
591 win->wait_for_click = 2;
592 spprint(write_to, "Igd_CApplWaitForClick %u\n", win->id);
593 } else {
594 INTERMED_ERROR(win->name, msgtag, win->owner_tid,
595 ITOC_WINDOW_ISNT_DISPLAYED);
596 }
597 break;
598
599
600 case CTOI_SAVE_GRAPH_TO_FILE:
601 /* save the graph into a file (only if it is displayed!) */
602 receive_str(fname);
603 if ( win->window_displayed ) {
604 spprint(write_to, "Igd_SaveGraph %u {%s}\n", win->id, fname);
605 } else {
606 INTERMED_ERROR(win->name, msgtag, win->owner_tid,
607 ITOC_WINDOW_ISNT_DISPLAYED);
608 }
609 break;
610
611
612 case CTOI_SAVE_GRAPH_PS_TO_FILE:
613 /* save postscript of the picture displayed. works only if
614 window is displayed. */
615 receive_str(fname);
616 if ( win->window_displayed ) {
617 spprint(write_to, "Igd_SavePs %u {%s}\n", win->id, fname);
618 } else {
619 INTERMED_ERROR(win->name, msgtag, win->owner_tid,
620 ITOC_WINDOW_ISNT_DISPLAYED);
621 }
622 break;
623
624
625 case CTOI_CLONE_WINDOW:
626 /* clone this window. if window is not displayed, only the
627 graph data structure will be copied over. */
628 /* wait_for_click, copy_status and text will not be copied over. */
629 receive_str(name2);
630 receive_str(title2);
631
632 if ( find_window(dgp->window_num, dgp->windows, name2) >= 0 ) {
633 INTERMED_ERROR(win->name, msgtag, sender,
634 ITOC_WINDOW_ALREADY_EXISTS);
635 break;
636 }
637
638 new_win = init_dgwin(dgp, sender, name2, title2);
639 copy_window_structure(new_win, win);
640
641 if ( win->window_displayed ) {
642 spprint(write_to,
643 "Igd_CopyWindowDesc %u %u\n", new_win->id, win->id);
644 spprint(write_to,
645 "Igd_InitWindow %u {%s}\n", new_win->id, title2);
646 spprint(write_to, "Igd_DisplayWindow %u\n", new_win->id);
647 spprint(write_to, "Igd_EnableCAppl %u\n", new_win->id);
648 spprint(write_to, "Igd_CopyGraph %u %u\n", new_win->id,win->id);
649 new_win->window_displayed = 1;
650 }
651 break;
652
653
654 case CTOI_RENAME_WINDOW:
655 /* change the title of the window */
656 receive_str(win->title);
657 if ( win->window_displayed ){
658 spprint(write_to,
659 "Igd_RenameWindow %u {%s}\n", win->id, win->title);
660 }
661 break;
662
663
664 case CTOI_RESIZE_VIEWABLE_WINDOW:
665 /* change the sizes of canvas */
666 receive_int_array(&win->desc.viewable_width, 1);
667 receive_int_array(&win->desc.viewable_height, 1);
668 if ( win->window_displayed ){
669 spprint(write_to, "Igd_ResizeViewableWindow %u %i %i\n",
670 win->id, win->desc.viewable_width,
671 win->desc.viewable_height);
672 }
673 break;
674
675
676 case CTOI_RESIZE_CANVAS:
677 /* change the size of the canvas */
678 receive_int_array(&win->desc.canvas_width, 1);
679 receive_int_array(&win->desc.canvas_height, 1);
680 if ( win->window_displayed ){
681 spprint(write_to, "Igd_ResizeCanvas %u %i %i\n", win->id,
682 win->desc.canvas_width, win->desc.canvas_height);
683 }
684 break;
685
686
687 case WAITING_TO_GET_A_COPY:
688 /* Read out the name of the source-graph from the pipe.
689 If the source-graph is waiting to be copied, source and
690 target have found each other */
691 receive_str(win->source) ;
692 win->copy_status = 2;
693
694 j = find_window(dgp->window_num, dgp->windows, win->source);
695 if ( j >= 0 && dgp->windows[j]->copy_status == 1 ) {
696 /* source graph exists and it is waiting to be copied */
697 source_win = dgp->windows[j];
698
699 /* copy the data structure */
700 copy_window_structure(win, source_win);
701
702 /* if the window is displayed, change picture */
703 if ( win->window_displayed ) {
704 display_graph_on_canvas(win, write_to);
705 }
706
707 /* zero out the copy stati */
708 win->copy_status = 0;
709 win->source[0] = 0;
710 source_win->copy_status = 0;
711 source_win->target[0] = 0;
712 }
713 break;
714
715
716 case WAITING_TO_BE_COPIED:
717 /* Read out the name of the target graph from the pipe.
718 If the target-graph is waiting to get a copy, source and
719 target have found each other. */
720 receive_str(win->target);
721 win->copy_status = 1;
722
723 j = find_window(dgp->window_num, dgp->windows, win->target);
724 if ( j >= 0 && dgp->windows[j]->copy_status == 2 ) {
725 /* target exists and waiting for a copy */
726 target_win = dgp->windows[j];
727
728 /* copy the data structure */
729 copy_window_structure(target_win, win);
730
731 /* if the target window is displayed, update the picture */
732 if ( target_win->window_displayed ) {
733 display_graph_on_canvas(target_win, write_to);
734 }
735
736 /* zero out the copy stati */
737 win->copy_status = 0;
738 win->target[0] = 0;
739 target_win->copy_status = 0;
740 target_win->source[0] = 0;
741 }
742 break;
743
744
745 case CTOI_MODIFY_GRAPH:
746 /* Make changes in the graph. The data structure is updated,
747 and if the window is displayed, the picture gets updated, too */
748
749 /* The message is in keyword - description pairs, with the
750 END_OF_MESSAGE keyword at the end. We switch on the keyword */
751
752 do {
753 receive_int_array(&keyword, 1);
754
755 switch ( keyword ) {
756
757 case MODIFY_ADD_NODES:
758 /* same format as in SET_GRAPH */
759 receive_int_array(&add_nodenum, 1);
760 if ( add_nodenum ) {
761 g = &(win->g);
762 nodenum = g->nodenum;
763 nodes = g->nodes = (dg_node *)
764 realloc(g->nodes,
765 (nodenum + add_nodenum) * sizeof(dg_node));
766 for (j = 0, new_nodenum = nodenum; j < add_nodenum; j++) {
767 read_node_desc_from_pvm(nodes+new_nodenum, win);
768 if (find_node(nodes[new_nodenum].node_id, g) < 0)
769 new_nodenum++;
770 }
771 g->nodenum = new_nodenum;
772
773 if ( win->window_displayed ) {
774 for ( j = nodenum; j < new_nodenum; j++ ) {
775 nod = nodes + j;
776 spprint(write_to,
777 "Igd_MakeNode %u %i %i %i {%s} {%s} %i\n",
778 win->id, nod->node_id, nod->posx,
779 nod->posy, nod->label, nod->dash,
780 nod->radius);
781 if ( *nod->weight != 0 ){
782 spprint(write_to,
783 "Igd_MakeNodeWeight %u %i {%s}\n",
784 win->id, nod->node_id, nod->weight);
785 }
786 }
787 }
788 }
789
790 break;
791
792
793 case MODIFY_CHANGE_WEIGHTS_OF_NODES:
794 /* change weights of nodes. nodes not in the graph or nodes
795 already deleted are skipped, no error message is given. */
796 g = &(win->g);
797 receive_int_array(&change_nodenum, 1);
798 for ( j = 0; j < change_nodenum; j++ ) {
799 receive_int_array(&node_id, 1);
800 receive_str(new_weight);
801 if ( (k = find_node(node_id, g)) >= 0 ) {
802 strcpy(g->nodes[k].weight, new_weight);
803 if ( win->window_displayed ) {
804 strcpy(old_weight, g->nodes[k].weight);
805 if ( *old_weight != 0 ) {
806 if ( *new_weight != 0 ) {
807 spprint(write_to,
808 "Igd_ChangeOneNodeWeight %u %i {%s}\n"
809 , win->id, node_id, new_weight);
810 } else {
811 /* new weight == 0 */
812 spprint(write_to,
813 "Igd_DeleteNodeWeight %u %i\n",
814 win->id, node_id);
815 }
816 } else {
817 /* no weight before */
818 if ( *new_weight != 0 ) {
819 spprint(write_to,
820 "Igd_MakeNodeWeight %u %i {%s}\n",
821 win->id, node_id, new_weight);
822 }
823 }
824 }
825 }
826 }
827 break;
828
829
830 case MODIFY_CHANGE_LABELS_OF_NODES:
831 /* change labels of nodes. nodes not in the graph or nodes
832 already deleted are skipped, no error message is given */
833 g = &(win->g);
834 receive_int_array(&change_nodenum, 1);
835 for ( j = 0; j < change_nodenum; j++ ) {
836 receive_int_array(&node_id, 1);
837 receive_str(new_label);
838 if ( (k = find_node(node_id, g)) >= 0 ) {
839 strcpy(g->nodes[k].label, new_label);
840 if ( win->window_displayed ) {
841 spprint(write_to,
842 "Igd_ChangeOneNodeLabel %u %i {%s}\n",
843 win->id, node_id, new_label);
844 }
845 }
846 }
847 break;
848
849
850 case MODIFY_CHANGE_DASH_OF_NODES:
851 /* change dash pattern of individual nodes. nodes not in the
852 graph will not cause error messages */
853 g = &(win->g);
854 receive_int_array(&change_nodenum, 1);
855 for ( j = 0; j < change_nodenum; j++ ) {
856 receive_int_array(&node_id, 1);
857 receive_str(new_dash);
858 if ( (k = find_node(node_id, g)) >= 0 ) {
859 strcpy(g->nodes[k].dash, new_dash);
860 if ( win->window_displayed ){
861 spprint(write_to,
862 "Igd_ChangeOneNodeDash %u %i {%s}\n",
863 win->id, node_id, new_dash);
864 }
865 }
866 }
867 break;
868
869
870 case MODIFY_CHANGE_RADII_OF_NODES:
871 /* change radii of individual nodes. nodes not in the
872 graph will not cause error messages */
873 g = &(win->g);
874 receive_int_array(&change_nodenum, 1);
875 for ( j = 0; j < change_nodenum; j++ ) {
876 receive_int_array(&node_id, 1);
877 receive_int_array(&new_radius, 1);
878 if ( (k = find_node(node_id, g)) >= 0 ) {
879 g->nodes[k].radius = new_radius;
880 if ( win->window_displayed ){
881 spprint(write_to,
882 "Igd_ChangeOneNodeRadius %u %i %i\n",
883 win->id, node_id, new_radius);
884 }
885 }
886 }
887 break;
888
889
890 case MODIFY_DELETE_NODES:
891 /* nodes not in the graph will not cause error messages */
892 receive_int_array(&delete_nodenum, 1);
893 if ( delete_nodenum ) {
894 g = &(win->g);
895 old_deleted_nodenum = g->deleted_nodenum;
896 for ( j = 0; j < delete_nodenum; j++ ) {
897 receive_int_array(&node_id, 1);
898 if ( (k = find_node(node_id, g)) >= 0 ) {
899 g->nodes[k].deleted = 1;
900 g->deleted_nodenum++;
901 if ( win->window_displayed ){
902 spprint(write_to,
903 "Igd_DeleteNode %u %i\n", win->id,
904 node_id);
905 }
906 }
907 }
908 if ( g->deleted_nodenum > old_deleted_nodenum ) {
909 /* mark edges that have at least one deleted endpoint
910 to be deleted. Igd_DeleteNode already took care of
911 deleting these edges from the picture */
912 for (k=g->edgenum-1, edg=g->edges; k >= 0; k--, edg++)
913 if ( ! edg->deleted &&
914 ((find_node(edg->tail, g) < 0) ||
915 (find_node(edg->head, g) < 0))){
916 edg->deleted = 1;
917 g->deleted_edgenum++;
918 }
919 }
920 /* if too many nodes and/or edges have been deleted,
921 compress the graph */
922 if ( g->deleted_nodenum > 0.1 * g->nodenum ||
923 g->deleted_edgenum > 0.1 * g->edgenum )
924 compress_graph(g);
925 }
926
927 break;
928
929
930 case MODIFY_ADD_EDGES:
931 /* same format as in SET_GRAPH. Nonvalid edges (one or
932 both endpoints is not in the graph will not cause an error
933 message. */
934 receive_int_array(&add_edgenum, 1);
935 if ( add_edgenum ) {
936 g = &(win->g);
937 edgenum = g->edgenum;
938 edges = g->edges = (dg_edge *)
939 realloc(g->edges,
940 (edgenum+add_edgenum)*sizeof(dg_edge));
941 for (j = 0, new_edgenum = edgenum; j < add_edgenum; j++) {
942 edg = edges + new_edgenum;
943 read_edge_desc_from_pvm(edg, win);
944 if ((find_edge(edg->edge_id, g) < 0) &&
945 (find_node(edg->tail, g) >= 0) &&
946 (find_node(edg->head, g) >= 0))
947 new_edgenum++;
948 }
949 g->edgenum = new_edgenum;
950
951 if ( win->window_displayed ) {
952 for ( j = edgenum; j < new_edgenum; j++ ) {
953 edg = edges + j;
954 spprint(write_to, "Igd_MakeEdge %u %i %i %i {%s}\n",
955 win->id, edg->edge_id, edg->tail,
956 edg->head, edg->dash);
957 if ( *edg->weight != 0 ){
958 spprint(write_to,
959 "Igd_MakeEdgeWeight %u %i {%s}\n",
960 win->id, edg->edge_id, edg->weight);
961 }
962 }
963 }
964 }
965
966 break;
967
968
969 case MODIFY_CHANGE_WEIGHTS_OF_EDGES:
970 /* change weights of edges. edges not in the graph or edges
971 already deleted are skipped, no error message is given. */
972 g = &(win->g);
973 receive_int_array(&change_edgenum, 1);
974 for ( j = 0; j < change_edgenum; j++ ) {
975 receive_int_array(&edge_id, 1);
976 receive_str(new_weight);
977 if ( (k = find_edge(edge_id, g)) >= 0 ) {
978 strcpy(g->edges[k].weight, new_weight);
979 if ( win->window_displayed ) {
980 strcpy(old_weight, g->edges[k].weight);
981 if ( *old_weight != 0 ) {
982 if ( *new_weight != 0 ) {
983 spprint(write_to,
984 "Igd_ChangeOneEdgeWeight %u %i {%s}\n"
985 , win->id, edge_id, new_weight);
986 } else {
987 /* new weight : 0 */
988 spprint(write_to,
989 "Igd_DeleteEdgeWeight %u %i\n",
990 win->id, edge_id);
991 }
992 } else {
993 /* no weight before */
994 if ( *new_weight != 0 ) {
995 spprint(write_to,
996 "Igd_MakeEdgeWeight %u %i {%s}\n",
997 win->id, edge_id, new_weight);
998 }
999 }
1000 }
1001 }
1002 }
1003
1004 break;
1005
1006
1007 case MODIFY_CHANGE_DASH_OF_EDGES:
1008 /* change dash pattern of individual edges. edges not in the
1009 graph will not cause error messages */
1010 g = &(win->g);
1011 receive_int_array(&change_edgenum, 1);
1012 for ( j = 0; j < change_edgenum; j++ ) {
1013 receive_int_array(&edge_id, 1);
1014 receive_str(new_dash);
1015 if ( (k = find_edge(edge_id, g)) >= 0 ) {
1016 strcpy(g->edges[k].dash, new_dash);
1017 if ( win->window_displayed ){
1018 spprint(write_to,
1019 "Igd_ChangeOneEdgeDash %u %i {%s}\n",
1020 win->id, edge_id, new_dash);
1021 }
1022 }
1023 }
1024
1025 break;
1026
1027
1028 case MODIFY_DELETE_EDGES:
1029 /* edges not in the graph will not cause error messages */
1030 g = &(win->g);
1031 receive_int_array(&delete_edgenum, 1);
1032 for ( j = 0; j < delete_edgenum; j++ ) {
1033 receive_int_array(&edge_id, 1);
1034 if ( (k = find_edge(edge_id, g)) >= 0 ) {
1035 g->edges[k].deleted = 1;
1036 g->deleted_edgenum++;
1037 if ( win->window_displayed ) {
1038 spprint(write_to, "Igd_DeleteEdge %u %i\n",
1039 win->id, edge_id);
1040 }
1041 }
1042 }
1043 /* if too many edges have been deleted, compress the
1044 graph */
1045 if ( g->deleted_edgenum > 0.1 * g->edgenum )
1046 compress_graph(g);
1047
1048 break;
1049
1050
1051 case MODIFY_DELETE_ALL_EDGES:
1052 /* will delete all edges from the graph */
1053 g = &(win->g);
1054 if ( win->window_displayed ) {
1055 for ( j = 0; j < g->edgenum; j++ )
1056 if ( ! g->edges[j].deleted ){
1057 spprint(write_to, "Igd_DeleteEdge %u %i\n",
1058 win->id, g->edges[j].edge_id);
1059 }
1060 }
1061 FREE(g->edges);
1062 g->edgenum = 0;
1063
1064 break;
1065
1066 case MODIFY_END_OF_MESSAGE:
1067 break;
1068
1069
1070 default:
1071 printf("Unrecognized keyword %i\n", keyword);
1072 break;
1073
1074
1075 } /* end switch (keyword) */
1076
1077 } while ( keyword != MODIFY_END_OF_MESSAGE );
1078
1079 break;
1080
1081
1082 case CTOI_CLEAR_MESSAGE:
1083 if ( win->window_displayed ) {
1084 spprint(write_to, "Igd_CApplClearCmsg %u\n", win->id);
1085 }
1086 break;
1087
1088 case CTOI_PRINT_MESSAGE:
1089 if ( win->window_displayed ) {
1090 str = malloc(bytes);
1091 receive_str(str);
1092 spprint(write_to, "Igd_CApplSetCmsg %u {%s}\n", win->id, str);
1093 FREE(str);
1094 }
1095 break;
1096
1097 case CTOI_APPEND_MESSAGE:
1098 if ( win->window_displayed ) {
1099 str = malloc(bytes);
1100 receive_str(str);
1101 spprint(write_to, "Igd_CApplAppendCmsg %u {%s}\n", win->id,str);
1102 FREE(str);
1103 }
1104 break;
1105
1106 default:
1107 printf("Unknown message tag: %i\n", msgtag);
1108 break;
1109
1110 } /* end switch (msgtag) */
1111
1112 freebuf(r_bufid);
1113 } /* end for */
1114
1115 } /* end while */
1116 return(0);
1117 }
1118
1119
1120 /*===========================================================================*/
1121
1122 /*===========================================================================*\
1123 * Find the window with the given name in windows.
1124 \*===========================================================================*/
1125
find_window(int window_num,window ** windows,char * name)1126 int find_window(int window_num, window **windows, char *name)
1127 {
1128 int i;
1129
1130 for ( i = window_num - 1; i >= 0; i-- )
1131 if ( strcmp(windows[i]->name, name) == 0 )
1132 break;
1133
1134 return(i);
1135 }
1136
1137 /*===========================================================================*/
1138
1139 /*===========================================================================*\
1140 * Read out the description of a node from pvm buffer
1141 \*===========================================================================*/
1142
read_node_desc_from_pvm(dg_node * nod,window * win)1143 void read_node_desc_from_pvm(dg_node *nod, window *win)
1144 {
1145 int key;
1146
1147 receive_int_array(&nod->node_id, 1);
1148 receive_int_array(&nod->posx, 1);
1149 receive_int_array(&nod->posy, 1);
1150 receive_int_array(&key, 1);
1151
1152 if ( key & 0x08 ){
1153 receive_str(nod->weight);
1154 }else{
1155 *nod->weight = 0;
1156 }
1157 if ( key & 0x04 ) {
1158 receive_str(nod->label);
1159 } else {
1160 sprintf(nod->label, "%i", nod->node_id);
1161 }
1162 if ( key & 0x02 ) {
1163 receive_str(nod->dash);
1164 } else {
1165 strcpy(nod->dash, win->desc.node_dash);
1166 }
1167 if ( key & 0x01 ) {
1168 receive_int_array(&nod->radius, 1);
1169 } else {
1170 nod->radius = win->desc.node_radius;
1171 }
1172 nod->deleted = FALSE;
1173 }
1174
1175 /*===========================================================================*/
1176
1177 /*===========================================================================*\
1178 * Read out the description of an edge from pvm buffer
1179 \*===========================================================================*/
1180
read_edge_desc_from_pvm(dg_edge * edg,window * win)1181 void read_edge_desc_from_pvm(dg_edge *edg, window *win)
1182 {
1183 int key;
1184
1185 receive_int_array(&edg->edge_id, 1);
1186 receive_int_array(&edg->tail, 1);
1187 receive_int_array(&edg->head, 1);
1188 receive_int_array(&key, 1);
1189 if ( key & 0x08 ){
1190 receive_str(edg->weight);
1191 }else{
1192 *edg->weight = 0;
1193 }
1194 if ( key & 0x02 ) {
1195 receive_str(edg->dash);
1196 } else {
1197 strcpy(edg->dash, win->desc.edge_dash);
1198 }
1199 edg->deleted = FALSE;
1200 }
1201
1202 /*===========================================================================*/
1203
1204 /*===========================================================================*\
1205 * Find the index of node with node_id in the graph.
1206 \*===========================================================================*/
1207
find_node(int node_id,dg_graph * g)1208 int find_node(int node_id, dg_graph *g)
1209 {
1210 int i;
1211
1212 for ( i = g->nodenum-1; i >= 0; i-- )
1213 if ( g->nodes[i].node_id == node_id )
1214 break;
1215
1216 if ( i >= 0 && ! g->nodes[i].deleted ) {
1217 return(i);
1218 } else {
1219 return(-1);
1220 }
1221
1222 return(-1);
1223 }
1224
1225 /*===========================================================================*/
1226
1227 /*===========================================================================*\
1228 * Find the index of edge with edge_id in the graph.
1229 \*===========================================================================*/
1230
find_edge(int edge_id,dg_graph * g)1231 int find_edge(int edge_id, dg_graph *g)
1232 {
1233 int i;
1234
1235 for ( i = g->edgenum-1; i >= 0; i-- )
1236 if ( g->edges[i].edge_id == edge_id )
1237 break;
1238
1239 if ( i >= 0 && ! g->edges[i].deleted ) {
1240 return(i);
1241 } else {
1242 return(-1);
1243 }
1244
1245 return(-1);
1246 }
1247
1248 /*===========================================================================*/
1249
1250 /*===========================================================================*\
1251 * Compess the graph: delete nodes and edges that have been marked.
1252 \*===========================================================================*/
1253
compress_graph(dg_graph * g)1254 void compress_graph(dg_graph *g)
1255 {
1256 dg_node *nodes = g->nodes;
1257 dg_edge *edges = g->edges;
1258 int new_nodenum, new_edgenum;
1259 int i;
1260
1261 if ( g->deleted_nodenum ) {
1262 /* find the first deleted node */
1263 for ( i = 0; i < g->nodenum; i++ ) {
1264 if ( nodes[i].deleted )
1265 break;
1266 }
1267
1268 for ( new_nodenum = i; i < g->nodenum; i++ ) {
1269 if ( ! nodes[i].deleted )
1270 nodes[new_nodenum++] = nodes[i];
1271
1272 }
1273
1274 g->nodes = (dg_node *) realloc(nodes, new_nodenum * sizeof(dg_node));
1275 g->nodenum = new_nodenum;
1276 g->deleted_nodenum = 0;
1277 }
1278
1279 if ( g->deleted_edgenum ) {
1280 /* find the first deleted edge */
1281 for ( i = 0; i < g->edgenum; i++ ) {
1282 if ( edges[i].deleted )
1283 break;
1284 }
1285
1286 for ( new_edgenum = i; i < g->edgenum; i++ ) {
1287 if ( ! edges[i].deleted )
1288 edges[new_edgenum++] = edges[i];
1289
1290 }
1291
1292 g->edges = (dg_edge *) realloc(edges, new_edgenum * sizeof(dg_edge));
1293 g->edgenum = new_edgenum;
1294 g->deleted_edgenum = 0;
1295 }
1296
1297 }
1298
1299 /*===========================================================================*/
1300
1301 /*===========================================================================*\
1302 * Copy the source window into target window's structure.
1303 * The following will be copied over: desc and g.
1304 * It is assumed that space is already allocated for the target_window.
1305 \*===========================================================================*/
1306
copy_window_structure(window * target_win,window * source_win)1307 void copy_window_structure(window *target_win, window *source_win)
1308 {
1309 int nodenum = source_win->g.nodenum;
1310 int edgenum = source_win->g.edgenum;
1311
1312 target_win->desc = source_win->desc;
1313
1314 FREE(target_win->g.nodes);
1315 FREE(target_win->g.edges);
1316
1317 if ( (target_win->g.nodenum = nodenum) ) {
1318 target_win->g.nodes = (dg_node *) malloc(nodenum * sizeof(dg_node));
1319 memcpy(target_win->g.nodes, source_win->g.nodes,
1320 nodenum * sizeof(dg_node));
1321 }
1322
1323 if ( (target_win->g.edgenum = edgenum) ) {
1324 target_win->g.edges = (dg_edge *) malloc(edgenum * sizeof(dg_edge));
1325 memcpy(target_win->g.edges, source_win->g.edges,
1326 edgenum * sizeof(dg_edge));
1327 }
1328 }
1329
1330 /*===========================================================================*/
1331
1332 /*===========================================================================*\
1333 * Display the graph in window's data structure on the canvas.
1334 * write_to is teh handle to wish.
1335 \*===========================================================================*/
1336
display_graph_on_canvas(window * win,FILE * write_to)1337 void display_graph_on_canvas(window *win, FILE *write_to)
1338 {
1339 win_desc *desc = &(win->desc);
1340 dg_graph *g = &(win->g);
1341 int j;
1342 dg_node *nod;
1343 dg_edge *edg;
1344
1345 if ( win->window_displayed ) {
1346
1347 /* need to erase the window then reset the window descriptions */
1348 spprint(write_to, "Igd_EraseWindow %u\n", win->id);
1349 spprint(write_to, "Igd_SetAndExecuteWindowDesc %u %i %i %i %i %i %i %i {%s} {%s} %i %i %i %f %s %s %s\n",
1350 win->id, desc->canvas_width, desc->canvas_height,
1351 desc->viewable_width, desc->viewable_height,
1352 desc->disp_nodelabels, desc->disp_nodeweights,
1353 desc->disp_edgeweights, desc->node_dash, desc->edge_dash,
1354 desc->node_radius, desc->interactive_mode,
1355 desc->mouse_tracking, desc->scale_factor, desc->nodelabel_font,
1356 desc->nodeweight_font, desc->edgeweight_font);
1357
1358 } else {
1359
1360 /* create window and set window description */
1361 spprint(write_to, "Igd_SetWindowDesc %u %i %i %i %i %i %i %i {%s} {%s} %i %i %i %f %s %s %s\n",
1362 win->id, desc->canvas_width, desc->canvas_height,
1363 desc->viewable_width, desc->viewable_height,
1364 desc->disp_nodelabels, desc->disp_nodeweights,
1365 desc->disp_edgeweights, desc->node_dash, desc->edge_dash,
1366 desc->node_radius, desc->interactive_mode,
1367 desc->mouse_tracking, desc->scale_factor, desc->nodelabel_font,
1368 desc->nodeweight_font, desc->edgeweight_font);
1369 spprint(write_to, "Igd_InitWindow %u {%s}\n", win->id, win->title);
1370 spprint(write_to, "Igd_DisplayWindow %u\n", win->id);
1371 spprint(write_to, "Igd_EnableCAppl %u\n", win->id);
1372 win->window_displayed = 1;
1373 }
1374
1375 /* now display the nodes and edges */
1376
1377 if ( g->nodenum ) {
1378 for ( j = 0; j < g->nodenum; j++ ) {
1379 nod = g->nodes + j;
1380 if ( !nod->deleted ) {
1381 spprint(write_to, "Igd_MakeNode %u %i %i %i %s {%s} %i\n",
1382 win->id, nod->node_id, nod->posx, nod->posy,
1383 nod->label, nod->dash, nod->radius);
1384 if ( *nod->weight != 0 ){
1385 spprint(write_to, "Igd_MakeNodeWeight %u %i %s\n",
1386 win->id, nod->node_id, nod->weight);
1387 }
1388 }
1389 } /* endfor j */
1390 }
1391 if ( g->edgenum ) {
1392 for ( j = 0; j < g->edgenum; j++ ) {
1393 edg = g->edges + j;
1394 if ( !edg->deleted ) {
1395 spprint(write_to, "Igd_MakeEdge %u %i %i %i {%s}\n",
1396 win->id, edg->edge_id, edg->tail, edg->head,
1397 edg->dash);
1398 if ( *edg->weight != 0 ){
1399 spprint(write_to, "Igd_MakeEdgeWeight %u %i {%s}\n",
1400 win->id, edg->edge_id, edg->weight);
1401 }
1402 }
1403 } /* endfor j */
1404 }
1405 }
1406
1407 /*===========================================================================*/
1408
1409 /*===========================================================================*\
1410 * Disassemble data structure windows[i].
1411 \*===========================================================================*/
1412
free_window(int * pwindow_num,window ** windows,int i)1413 void free_window(int *pwindow_num, window **windows, int i)
1414 {
1415 window *w = windows[i];
1416
1417 FREE(w->g.nodes);
1418 FREE(w->g.edges);
1419 /* free the bufid fifo */
1420 FREE(w->buf.bufid);
1421 if (w->user){
1422 #ifdef USE_SYM_APPLICATION
1423 user_dg_free_window(&w->user, w);
1424 #else
1425 FREE(w->user);
1426 #endif
1427 }
1428 FREE(w);
1429
1430 /* delete pointer from windows */
1431 if ( i < *pwindow_num - 1 )
1432 windows[i] = windows[*pwindow_num-1];
1433 (*pwindow_num)--;
1434 }
1435
1436 /*===========================================================================*/
1437
copy_win_desc_from_par(window * win,dg_params * par)1438 void copy_win_desc_from_par(window *win, dg_params *par)
1439 {
1440 win->desc.canvas_width = par->canvas_width;
1441 win->desc.canvas_height = par->canvas_height;
1442 win->desc.viewable_width = par->viewable_width;
1443 win->desc.viewable_height = par->viewable_height;
1444
1445 win->desc.disp_nodelabels = par->disp_nodelabels;
1446 win->desc.disp_nodeweights = par->disp_nodeweights;
1447 win->desc.disp_edgeweights = par->disp_edgeweights;
1448
1449 strcpy(win->desc.node_dash, par->node_dash);
1450 strcpy(win->desc.edge_dash, par->edge_dash);
1451
1452 win->desc.node_radius = par->node_radius;
1453 win->desc.interactive_mode = par->interactive_mode;
1454 win->desc.mouse_tracking = par->mouse_tracking;
1455 win->desc.scale_factor = par->scale_factor;
1456
1457 strcpy(win->desc.nodelabel_font, par->nodelabel_font);
1458 strcpy(win->desc.nodeweight_font, par->nodeweight_font);
1459 strcpy(win->desc.edgeweight_font, par->edgeweight_font);
1460 }
1461
1462 /*===========================================================================*/
1463
set_window_desc_pvm(int key,window * win)1464 void set_window_desc_pvm(int key, window *win)
1465 {
1466 win_desc *desc = &win->desc;
1467
1468 switch ( key ) {
1469 case CANVAS_WIDTH:
1470 receive_int_array(&desc->canvas_width, 1);
1471 break;
1472 case CANVAS_HEIGHT:
1473 receive_int_array(&desc->canvas_height, 1);
1474 break;
1475 case VIEWABLE_WIDTH:
1476 receive_int_array(&desc->viewable_width, 1);
1477 break;
1478 case VIEWABLE_HEIGHT:
1479 receive_int_array(&desc->viewable_height, 1);
1480 break;
1481 case DISP_NODELABELS:
1482 receive_int_array(&desc->disp_nodelabels, 1);
1483 break;
1484 case DISP_NODEWEIGHTS:
1485 receive_int_array(&desc->disp_nodeweights, 1);
1486 break;
1487 case DISP_EDGEWEIGHTS:
1488 receive_int_array(&desc->disp_edgeweights, 1);
1489 break;
1490 case NODE_DASH:
1491 receive_str(desc->node_dash);
1492 break;
1493 case EDGE_DASH:
1494 receive_str(desc->edge_dash);
1495 break;
1496 case NODE_RADIUS:
1497 receive_int_array(&desc->node_radius, 1);
1498 break;
1499 case INTERACTIVE_MODE:
1500 receive_int_array(&desc->interactive_mode, 1);
1501 break;
1502 case MOUSE_TRACKING:
1503 receive_int_array(&desc->mouse_tracking, 1);
1504 break;
1505 case SCALE_FACTOR:
1506 receive_dbl_array(&desc->scale_factor, 1);
1507 break;
1508 case NODELABEL_FONT:
1509 receive_str(desc->nodelabel_font);
1510 break;
1511 case NODEWEIGHT_FONT:
1512 receive_str(desc->nodeweight_font);
1513 break;
1514 case EDGEWEIGHT_FONT:
1515 receive_str(desc->edgeweight_font);
1516 break;
1517 }
1518 }
1519
1520 /*===========================================================================*/
1521
wait_for_you_can_die(dg_prob * dgp,FILE * write_to)1522 void wait_for_you_can_die(dg_prob *dgp, FILE *write_to)
1523 {
1524 int bufid, s_bufid, bytes, msgtag, sender;
1525
1526 FREE(dgp->windows);
1527 /* invoke the Igd_QuitAll function */
1528 spprint(write_to, "Igd_QuitAll\n");
1529
1530 if (dgp->waiting_to_die == 2 * TRUE)
1531 exit(0);
1532
1533 while (TRUE){
1534 receive_msg(ANYONE, ANYTHING);
1535 bufinfo(bufid, &bytes, &msgtag, &sender);
1536 if (msgtag != CTOI_YOU_CAN_DIE){
1537 s_bufid = init_send(DataInPlace);
1538 send_msg(sender, ITOC_APPLICATION_KILLED);
1539 freebuf(s_bufid);
1540 }else{
1541 exit(0);
1542 }
1543 }
1544 }
1545
1546 /*===========================================================================*/
1547
init_dgwin(dg_prob * dgp,int sender,char * name,char * title)1548 window *init_dgwin(dg_prob *dgp, int sender, char *name, char *title)
1549 {
1550 window *win = (window *) calloc(1, sizeof(window));
1551
1552 win->owner_tid = sender;
1553 strcpy(win->name, name);
1554 strcpy(win->title, title);
1555 win->id = dgp->next_id++;
1556 /* initialize buf_fifo */
1557 win->buf.bufid = (int *) malloc(127 * ISIZE);
1558 win->buf.bufspace = 127;
1559 win->buf.bufread = -1;
1560 win->buf.bufwrite = 0;
1561
1562 dgp->window_num++;
1563 if (dgp->window_num == 1)
1564 dgp->windows = (window **) malloc( sizeof(window *) );
1565 else
1566 dgp->windows = (window **)
1567 realloc(dgp->windows, dgp->window_num * sizeof(window *));
1568 dgp->windows[dgp->window_num-1] = win;
1569 #ifdef USE_SYM_APPLICATION
1570 CALL_USER_FUNCTION( user_dg_init_window(&win->user, win) );
1571 #else
1572 win->user = NULL;
1573 #endif
1574 return(win);
1575 }
1576
1577 /*===========================================================================*/
1578
add_msg(window * win,int bufid)1579 void add_msg(window *win, int bufid)
1580 {
1581 register buf_fifo *buf = &win->buf;
1582
1583 if (buf->bufread == -1){
1584 /* then bufwrite must be 0 */
1585 buf->bufid[0] = bufid;
1586 buf->bufread = 0;
1587 buf->bufwrite = 1;
1588 return;
1589 }
1590 if (buf->bufread == buf->bufwrite){
1591 /* the list of bufid's is full */
1592 int *newbufid = (int *) malloc((buf->bufspace + 128) * ISIZE);
1593 memcpy(newbufid, buf->bufid + buf->bufread,
1594 (buf->bufspace - buf->bufread) * ISIZE);
1595 memcpy(newbufid + (buf->bufspace - buf->bufread), buf->bufid,
1596 buf->bufread * ISIZE);
1597 FREE(buf->bufid);
1598 buf->bufid = newbufid;
1599 buf->bufread = 0;
1600 buf->bufwrite = buf->bufspace;
1601 buf->bufspace += 128;
1602 }
1603 buf->bufid[buf->bufwrite] = bufid;
1604 if (++buf->bufwrite == buf->bufspace)
1605 buf->bufwrite = 0;
1606 }
1607
1608 /*===========================================================================*/
1609
get_next_msg(window * win)1610 int get_next_msg(window *win)
1611 {
1612 register buf_fifo *buf = &win->buf;
1613 int bufid = buf->bufid[buf->bufread];
1614
1615 if (++buf->bufread == buf->bufspace)
1616 buf->bufread = 0;
1617 if (buf->bufread == buf->bufwrite){
1618 buf->bufread = -1;
1619 buf->bufwrite = 0;
1620 }
1621 return( bufid );
1622 }
1623
1624
1625