1 /*
2 * Author: William Chia-Wei Cheng (bill.cheng@acm.org)
3 *
4 * Copyright (C) 2001-2009, William Chia-Wei Cheng.
5 *
6 * This file may be distributed under the terms of the Q Public License
7 * as defined by Trolltech AS of Norway and appearing in the file
8 * LICENSE.QPL included in the packaging of this file.
9 *
10 * THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING
11 * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
12 * PURPOSE. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
13 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
14 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
16 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 * @(#)$Header: /mm2/home/cvs/bc-src/tgif/wb.c,v 1.45 2011/05/16 16:22:00 william Exp $
19 */
20
21 #define _INCLUDE_FROM_WB_C_
22
23 #if (defined(PTHREAD) || defined(HAVE_LIBPTHREAD))
24 #include <pthread.h>
25 #endif /* (defined(PTHREAD) || defined(HAVE_LIBPTHREAD)) */
26
27 #include "tgifdefs.h"
28 #include "cmdids.h"
29
30 #ifdef _HAS_STREAMS_SUPPORT
31 #include <stropts.h>
32 #include <sys/types.h>
33 #endif /* _HAS_STREAMS_SUPPORT */
34 #include "rmcast/src/rmcast.h"
35
36 #include "auxtext.e"
37 #include "chat.e"
38 #include "choice.e"
39 #include "color.e"
40 #include "cmd.e"
41 #include "dialog.e"
42 #include "drawing.e"
43 #include "file.e"
44 #include "font.e"
45 #include "grid.e"
46 #include "http.e"
47 #include "import.e"
48 #include "mark.e"
49 #include "menu.e"
50 #include "msg.e"
51 #include "obj.e"
52 #include "page.e"
53 #include "raster.e"
54 #include "remote.e"
55 #include "rm_intrf.e"
56 #include "ruler.e"
57 #include "scroll.e"
58 #include "select.e"
59 #include "setup.e"
60 #include "stk.e"
61 #include "strtbl.e"
62 #include "tcp.e"
63 #include "util.e"
64 #include "version.e"
65 #include "wb.e"
66 #include "wb_buff.e"
67 #include "wb_seg.e"
68 #include "xpixmap.e"
69 #include "z_intrf.e"
70
71 struct WhiteBoardRec gstWBInfo;
72
73 int cmdLineNoWhiteBoard=FALSE;
74 int cmdLineWhiteBoardListenOnly=FALSE;
75
76 static int recordCmdLogicalClock=0;
77 static char recordCmdSenderProcID[MAXSTRING];
78
79 #ifdef _TGIF_DBG_WB2
80 static int wb2DebugLevel=0;
81 #endif /* _TGIF_DBG_WB2 */
82
83 /* =================== Remote Related Functions =================== */
84
85 static
CleanUpWBSockets()86 void CleanUpWBSockets()
87 {
88 if (gstWBInfo.listening) {
89 if (gstWBInfo.listen_socket != (-1)) {
90 close(gstWBInfo.listen_socket);
91 gstWBInfo.listen_socket = (-1);
92 }
93 if (gstWBInfo.listen_fp != NULL) {
94 fclose(gstWBInfo.listen_fp);
95 gstWBInfo.listen_fp = NULL;
96 }
97 if (gstWBInfo.gz_listen_fp != NULL) {
98 fclose(gstWBInfo.gz_listen_fp);
99 gstWBInfo.gz_listen_fp = NULL;
100 }
101 if (*gstWBInfo.gz_listen_fname != '\0') {
102 unlink(gstWBInfo.gz_listen_fname);
103 *gstWBInfo.gz_listen_fname = '\0';
104 }
105 if (*gstWBInfo.listen_fname != '\0') {
106 unlink(gstWBInfo.listen_fname);
107 *gstWBInfo.listen_fname = '\0';
108 }
109 gstWBInfo.listening = FALSE;
110 }
111 if (gstWBInfo.send_socket != (-1)) {
112 close(gstWBInfo.send_socket);
113 gstWBInfo.send_socket = (-1);
114 }
115 if (gstWBInfo.gz_send_fp != NULL) {
116 fclose(gstWBInfo.gz_send_fp);
117 gstWBInfo.gz_send_fp = NULL;
118 }
119 if (gstWBInfo.send_fp != NULL) {
120 fclose(gstWBInfo.send_fp);
121 gstWBInfo.send_fp = NULL;
122 }
123 if (*gstWBInfo.gz_send_fname != '\0') {
124 unlink(gstWBInfo.gz_send_fname);
125 *gstWBInfo.gz_send_fname = '\0';
126 }
127 if (*gstWBInfo.send_fname != '\0') {
128 unlink(gstWBInfo.send_fname);
129 *gstWBInfo.send_fname = '\0';
130 }
131 }
132
133 static
CleanUpWBShadowCmds()134 void CleanUpWBShadowCmds()
135 {
136 struct CmdRec *cmd_ptr=NULL;
137 int num_records=0;
138
139 for (cmd_ptr=gstWBInfo.last_shadow_cmd; cmd_ptr != NULL;
140 cmd_ptr=cmd_ptr->prev) {
141 num_records++;
142 }
143 if (num_records > 0) {
144 struct CmdRec *prev_cmd=NULL;
145 double inc=(100.0/((double)num_records)), percent_start=0.0;
146
147 ShowInterrupt(1);
148 SaveStatusStrings();
149 for (cmd_ptr=gstWBInfo.last_shadow_cmd; cmd_ptr != NULL; cmd_ptr=prev_cmd,
150 percent_start+=inc) {
151 prev_cmd = cmd_ptr->prev;
152 DeleteARedoRecord(cmd_ptr, percent_start,
153 min(((double)percent_start+inc),((double)100.0)));
154 }
155 RestoreStatusStrings();
156 HideInterrupt();
157 }
158 gstWBInfo.first_shadow_cmd = gstWBInfo.last_shadow_cmd = NULL;
159 }
160
161 static
CleanUpWBCmds()162 void CleanUpWBCmds()
163 {
164 struct CmdRec *cmd_ptr=NULL;
165 int num_records=0;
166
167 for (cmd_ptr=gstWBInfo.last_cmd; cmd_ptr != NULL; cmd_ptr=cmd_ptr->prev) {
168 num_records++;
169 }
170 if (num_records > 0) {
171 struct CmdRec *prev_cmd=NULL;
172 double inc=(100.0/((double)num_records)), percent_start=0.0;
173
174 ShowInterrupt(1);
175 SaveStatusStrings();
176 for (cmd_ptr=gstWBInfo.last_cmd; cmd_ptr != NULL; cmd_ptr=prev_cmd,
177 percent_start+=inc) {
178 prev_cmd = cmd_ptr->prev;
179 DeleteARedoRecord(cmd_ptr, percent_start,
180 min(((double)percent_start+inc),((double)100.0)));
181 }
182 RestoreStatusStrings();
183 HideInterrupt();
184 }
185 gstWBInfo.first_cmd = gstWBInfo.last_cmd = gstWBInfo.cur_cmd = NULL;
186
187 CleanUpWBShadowCmds();
188 }
189
190 static
CreateWBListenSocket()191 int CreateWBListenSocket()
192 {
193 gstWBInfo.listening = TRUE;
194
195 if (MkTempFile(gstWBInfo.listen_fname, sizeof(gstWBInfo.listen_fname),
196 tmpDir, TOOL_NAME) == NULL) {
197 fprintf(stderr, "Fail to create '%s' for deserialization.\n",
198 gstWBInfo.listen_fname);
199 return FALSE;
200 }
201 snprintf(gstWBInfo.gz_listen_fname, sizeof(gstWBInfo.gz_listen_fname),
202 "%s.z", gstWBInfo.listen_fname);
203 if ((gstWBInfo.listen_fp=fopen(gstWBInfo.listen_fname, "w+")) == NULL) {
204 fprintf(stderr, "Fail to create '%s' for deserialization.\n",
205 gstWBInfo.listen_fname);
206 return FALSE;
207 }
208 if ((gstWBInfo.gz_listen_fp=fopen(gstWBInfo.gz_listen_fname, "w+")) ==
209 NULL) {
210 fprintf(stderr, "Fail to create '%s' for deserialization.\n",
211 gstWBInfo.gz_listen_fname);
212 return FALSE;
213 }
214
215 return TRUE;
216 }
217
PrintFullIDsOfObjects(psz_prefix)218 void PrintFullIDsOfObjects(psz_prefix)
219 char *psz_prefix;
220 {
221 #ifdef _TGIF_DBG_WB2
222 if (wb2DebugLevel > 0) {
223 struct ObjRec *obj_ptr=NULL;
224 int stacking_order=0;
225
226 if (psz_prefix != NULL) {
227 if (strcmp(psz_prefix, "\t") == 0) {
228 fprintf(stderr, "\tin PrintFullIDsOfObjects():\n");
229 } else {
230 fprintf(stderr, "%s, in PrintFullIDsOfObjects():\n", psz_prefix);
231 }
232 } else {
233 fprintf(stderr, "In PrintFullIDsOfObjects():\n");
234 }
235 for (obj_ptr=topObj; obj_ptr != NULL; obj_ptr=obj_ptr->next,
236 stacking_order++) {
237 char buf[MAXSTRING], obj_type[MAXSTRING];
238
239 if (obj_ptr->creator_full_id == NULL) {
240 sprintf(buf, "(NULL)%1d/%s", obj_ptr->id, gszLocalPID);
241 } else {
242 strcpy(buf, obj_ptr->creator_full_id);
243 }
244 switch (obj_ptr->type) {
245 case OBJ_POLY: strcpy(obj_type, "p"); break;
246 case OBJ_BOX: strcpy(obj_type, "b"); break;
247 case OBJ_OVAL: strcpy(obj_type, "o"); break;
248 case OBJ_TEXT:
249 strcpy(obj_type, "t");
250 {
251 MiniLinesInfo *minilines=(&obj_ptr->detail.t->minilines);
252 char *psz=minilines->first->first_block->seg->dyn_str.s;
253 char buf1[MAXSTRING];
254 int len=strlen(psz);
255
256 if (len > 5) {
257 char saved_ch=psz[5];
258
259 sprintf(buf1, " - \"%s...\"", psz);
260 psz[5] = saved_ch;
261 } else {
262 sprintf(buf1, " - \"%s\"", psz);
263 }
264 strcat(buf, buf1);
265 }
266 break;
267 case OBJ_POLYGON: strcpy(obj_type, "g"); break;
268 case OBJ_ARC: strcpy(obj_type, "a"); break;
269 case OBJ_RCBOX: strcpy(obj_type, "rcb"); break;
270 case OBJ_XBM: strcpy(obj_type, "xbm"); break;
271 case OBJ_XPM: strcpy(obj_type, "xpm"); break;
272 case OBJ_GROUP:
273 case OBJ_ICON:
274 case OBJ_SYM:
275 case OBJ_PIN: strcpy(obj_type, "r"); break;
276 }
277 fprintf(stderr, "\t%d/%s:\t%s\n", stacking_order, obj_type, buf);
278 }
279 }
280 #endif /* _TGIF_DBG_WB2 */
281 }
282
283
RecvWBData(flag,ppsz_buf,pn_buf_sz)284 int RecvWBData(flag, ppsz_buf, pn_buf_sz)
285 int flag, *pn_buf_sz;
286 char **ppsz_buf;
287 {
288
289 int retval;
290
291 retval = buff_rem(gstWBInfo.bd_commands, (void**)ppsz_buf);
292
293 return retval;
294 }
295
296 static
ProcessWBInputData(buf)297 void ProcessWBInputData(buf)
298 char *buf;
299 /*
300 * Here the WB input data is in the HTTP data format.
301 * So we use HttpExtractText() to convert the data into
302 * something that can be handled by ProcessRemoteCmd().
303 * In the future, if the WB input data is binary, this is
304 * where the conversion takes place.
305 */
306 {
307 char *psz_content=NULL, *psz_content_type=NULL;
308 int content_sz=0;
309
310 psz_content = HttpExtractText(buf, &content_sz, NULL, &psz_content_type);
311 if (psz_content != NULL) {
312 ProcessRemoteCmd(psz_content_type, psz_content, content_sz);
313 FreeRemoteBuf(psz_content);
314 }
315 if (psz_content_type != NULL) UtilFree(psz_content_type);
316 }
317
WBHasReadData(pn_flag,pn_retry)318 int WBHasReadData(pn_flag, pn_retry)
319 int *pn_flag, *pn_retry;
320 {
321 /* leave *pn_retry alone */
322
323 if ((!(gstWBInfo.BlockRemoteCmdDepth <= 1)) && (buff_items(gstWBInfo.bd_commands) > 0) )
324 {
325 /* FIXME fprintf(stderr,"gstWBInfo.BlockRemoteCmdDepth > 1 e existem dados no buffer. (WBHasReadData)\n");
326 exit(1); */
327 }
328
329 return (gstWBInfo.BlockRemoteCmdDepth <= 1 &&
330 buff_items(gstWBInfo.bd_commands) > 0);
331 }
332
333
334
TryHandleWBInputData()335 void TryHandleWBInputData()
336 {
337 int flag=0, retry=TRUE;
338 char *buf;
339 int buf_sz;
340
341 while (retry && WBHasReadData(&flag, &retry)) {
342
343 buf=NULL;
344 buf_sz=0;
345
346 deserializingFile = TRUE;
347
348 if (RecvWBData(flag, &buf, &buf_sz)) {
349 ProcessWBInputData(buf);
350 FreeRemoteBuf(buf);
351 }
352 deserializingFile = FALSE;
353 }
354 }
355
SendWBData(pszWBData,logical_clock)356 int SendWBData(pszWBData, logical_clock)
357 char *pszWBData;
358 int logical_clock;
359 {
360 int nPackets1, i;
361 struct SegmentationPack *pack1;
362
363 #ifdef DEBUG
364 fprintf(stderr,"Mensagem enviada:\n%s\n", pszWBData);
365 #endif
366
367 pack1 = Segment( pszWBData, strlen(pszWBData), gszLocalPID, logical_clock, &nPackets1 );
368
369 for( i = 0; i < nPackets1; i++ )
370 {
371 RM_sendto(gstWBInfo.MCastSock, (char*)&pack1[i], sizeof(struct SegmentationPack));
372 }
373 free( pack1 );
374
375 #ifdef _TGIF_DBG_WB2
376 fprintf(stderr, "SendWBData(), pid = %ld\n", gstWBInfo.pid);
377 #endif /* _TGIF_DBG_WB2 */
378
379 return TRUE;
380 }
381
382 /* =================== Cmd Related Functions =================== */
383
384 static
SaveCmd(FP,CmdType,psi)385 int SaveCmd(FP, CmdType, psi)
386 FILE *FP;
387 int CmdType;
388 SerializationInfo *psi;
389 {
390 struct SelRec *sel_ptr=NULL;
391 int count=0;
392
393 /*
394 * This part should work now!
395 *
396 * if (recordCmdIncludeTgifObj) {
397 * sprintf(gszMsgBox, "%s.\n%s %s.\n\n%s %s.",
398 * "Warning: recordCmdIncludeTgifObj is TRUE in SaveCmd()",
399 * TOOL_NAME, "WhiteBoard may crash",
400 * "Please try to reproduce this error and send bug report to",
401 * authorEmailString);
402 * MsgBox(gszMsgBox, TOOL_NAME, STOP_MB);
403 * return FALSE;
404 * } else
405 */
406 if (CmdType == CMD_GOTO_PAGE) {
407 /*
408 * GotoPage() is disabled for _TGIF_WB2.
409 */
410 return FALSE;
411 }
412 if (fprintf(FP, "cmd(%1d,", CmdType) == EOF) {
413 writeFileFailed = TRUE;
414 }
415 if (CmdType == CMD_MOVE) {
416 if (fprintf(FP, "%1d,%1d,",
417 psi->subcmd->detail.move.dx, psi->subcmd->detail.move.dy) == EOF) {
418 writeFileFailed = TRUE;
419 }
420 } else if (CmdType == CMD_WB_CLEARALL) {
421 if (fprintf(FP, "%1d,%.3f,",
422 psi->subcmd->detail.clearall.page_style,
423 psi->subcmd->detail.clearall.print_mag) == EOF) {
424 writeFileFailed = TRUE;
425 }
426 } else if (CmdType == CMD_WB_SLIDESHOW) {
427 if (fprintf(FP, "%1d,",
428 psi->subcmd->detail.slideshow.into_slideshow) ==
429 EOF) {
430 writeFileFailed = TRUE;
431 }
432 } else if (CmdType == CMD_CHAT_A_LINE) {
433 if (fprintf(FP, "%1d,'", psi->subcmd->detail.chat.type) == EOF) {
434 writeFileFailed = TRUE;
435 }
436 SaveString(FP, psi->subcmd->detail.chat.nick_name);
437 if (fprintf(FP, "','%s',%1d,'%s',",
438 psi->subcmd->detail.chat.tfi.color_str,
439 psi->subcmd->detail.chat.tfi.font_style,
440 psi->subcmd->detail.chat.encoding) == EOF) {
441 writeFileFailed = TRUE;
442 }
443 if (fprintf(FP, "\"") == EOF) writeFileFailed = TRUE;
444 SaveString(FP, psi->subcmd->detail.chat.buf);
445 if (fprintf(FP, "\",") == EOF) writeFileFailed = TRUE;
446 }
447 if (fprintf(FP, "%1d,%1d,%1d,\"%s\").\n",
448 psi->include_tgif_obj, psi->new_colormap, psi->logical_clock,
449 psi->sender_process_id) == EOF) {
450 writeFileFailed = TRUE;
451 }
452 /* Lamport's Algorithm increments logical_clock */
453 gstWBInfo.logical_clock++;
454
455 if (psi->bot_before != NULL) {
456 if (fprintf(FP, "before_image(%1d,[\n", psi->count_before) == EOF) {
457 writeFileFailed = TRUE;
458 }
459 for (count=0, sel_ptr=psi->top_before; sel_ptr != NULL;
460 sel_ptr=sel_ptr->next, count++) {
461 struct ObjRec *obj_ptr=sel_ptr->obj;
462 char buf[MAXSTRING];
463
464 if (psi->pos_before_has_ids) {
465 sprintf(buf, "%s", ((char**)psi->pos_before)[count]);
466 } else {
467 if (obj_ptr->creator_full_id == NULL) {
468 sprintf(buf, "%1d/%s", obj_ptr->id, psi->sender_process_id);
469 } else {
470 strcpy(buf, obj_ptr->creator_full_id);
471 }
472 }
473 if (fprintf(FP, "\t\"") == EOF) writeFileFailed = TRUE;
474 SaveString(FP, buf);
475 if (sel_ptr->next == NULL) {
476 if (fprintf(FP, "\"\n") == EOF) writeFileFailed = TRUE;
477 } else {
478 if (fprintf(FP, "\",\n") == EOF) writeFileFailed = TRUE;
479 }
480 }
481 if (fprintf(FP, "]).\n") == EOF) writeFileFailed = TRUE;
482 }
483 if (psi->bot_sel != NULL) {
484 struct SelRec *sel_ptr;
485 int *stacking_pos=NULL, stacking_count=0;
486
487 sel_ptr = PrepareStackingInfo(psi->top_sel,
488 psi->bot_sel, psi->num_objs, FALSE,
489 &stacking_pos, &stacking_count, NULL);
490 if (sel_ptr == NULL && stacking_count == psi->num_objs) {
491 if (fprintf(FP, "after_positions(%1d,[\n",
492 psi->num_objs) == EOF) {
493 writeFileFailed = TRUE;
494 }
495 for (count=0, sel_ptr=psi->top_sel;
496 count < stacking_count && sel_ptr != NULL;
497 count++, sel_ptr=sel_ptr->next) {
498 char buf[MAXSTRING];
499
500 sprintf(buf, "%1d", stacking_pos[count]);
501 if (fprintf(FP, "\t") == EOF) writeFileFailed = TRUE;
502 SaveString(FP, buf);
503 if (sel_ptr->next == NULL) {
504 if (fprintf(FP, "\n") == EOF) writeFileFailed = TRUE;
505 } else {
506 if (fprintf(FP, ",\n") == EOF) writeFileFailed = TRUE;
507 }
508 }
509 if (fprintf(FP, "]).\n") == EOF) writeFileFailed = TRUE;
510
511 if (fprintf(FP, "after_image(%1d,[\n", psi->num_objs) ==
512 EOF) {
513 writeFileFailed = TRUE;
514 }
515 for (count=0, sel_ptr=psi->top_sel; sel_ptr != NULL;
516 sel_ptr=sel_ptr->next, count++) {
517 SaveObj(FP, sel_ptr->obj, 1);
518 if (sel_ptr->next == NULL) {
519 if (fprintf(FP, "\n") == EOF) writeFileFailed = TRUE;
520 } else {
521 if (fprintf(FP, ",\n") == EOF) writeFileFailed = TRUE;
522 }
523 }
524 if (fprintf(FP, "]).\n") == EOF) writeFileFailed = TRUE;
525 }
526 if (stacking_pos != NULL) free(stacking_pos);
527 }
528 return TRUE;
529 }
530
531 static
PrepareExtendedSerializationInfo(CmdPtr,psi)532 void PrepareExtendedSerializationInfo(CmdPtr, psi)
533 struct CmdRec *CmdPtr;
534 SerializationInfo *psi;
535 {
536 psi->subcmd = CmdPtr->subcmd;
537 psi->top_sel = NULL; /* not used */
538 psi->bot_sel = NULL; /* not used */
539 psi->num_objs = 0; /* not used */
540
541 psi->include_tgif_obj = CmdPtr->include_tgif_obj;
542 psi->new_colormap = CmdPtr->new_colormap;
543 psi->logical_clock = CmdPtr->logical_clock;
544 psi->sender_process_id = CmdPtr->sender_process_id;
545
546 psi->top_before = CmdPtr->top_before;
547 psi->bot_before = CmdPtr->bot_before;
548 psi->pos_before = CmdPtr->pos_before;
549 psi->count_before = CmdPtr->count_before;
550 psi->pos_before_has_ids = CmdPtr->pos_before_has_ids;
551 }
552
553 static
SaveExtendedCmd(FP,CmdPtr,psi)554 int SaveExtendedCmd(FP, CmdPtr, psi)
555 FILE *FP;
556 struct CmdRec *CmdPtr;
557 SerializationInfo *psi;
558 {
559 if (CmdPtr->type == CMD_GOTO_PAGE) {
560 /*
561 * GotoPage() is disabled for _TGIF_WB2.
562 */
563 return FALSE;
564 } else if (CmdPtr->type == CMD_CHAT_A_LINE) {
565 /*
566 * intentionally forget what has been chatted
567 */
568 return FALSE;
569 }
570 if (CmdPtr->serialization_buf == NULL) {
571 fprintf(stderr, "serialization_buf is NULL\n");
572 return FALSE;
573 }
574 #ifdef NOT_DEFINED
575 /* this is replaced by simply printing CmdPtr->serialization_buf */
576 if (fprintf(FP, "cmdx(%1d,%1d,", CmdPtr->type, CmdPtr->undone) == EOF) {
577 writeFileFailed = TRUE;
578 }
579 if (CmdPtr->type == CMD_MOVE) {
580 if (fprintf(FP, "%1d,%1d,",
581 CmdPtr->subcmd->detail.move.dx,
582 CmdPtr->subcmd->detail.move.dy) == EOF) {
583 writeFileFailed = TRUE;
584 }
585 } else if (CmdPtr->type == CMD_WB_CLEARALL) {
586 if (fprintf(FP, "%1d,%.3f,",
587 CmdPtr->subcmd->detail.clearall.page_style,
588 CmdPtr->subcmd->detail.clearall.print_mag) == EOF) {
589 writeFileFailed = TRUE;
590 }
591 } else if (CmdPtr->type == CMD_WB_SLIDESHOW) {
592 if (fprintf(FP, "%1d,",
593 CmdPtr->subcmd->detail.slideshow.into_slideshow) == EOF) {
594 writeFileFailed = TRUE;
595 }
596 } else if (CmdPtr->type == CMD_CHAT_A_LINE) {
597 /* intentionally forget what has been chatted */
598 return FALSE;
599 }
600 if (fprintf(FP, "%1d,%1d,%1d,\"%s\",%1d).\n",
601 CmdPtr->include_tgif_obj, CmdPtr->new_colormap, CmdPtr->logical_clock,
602 CmdPtr->sender_process_id, CmdPtr->undone) == EOF) {
603 writeFileFailed = TRUE;
604 }
605 #endif /* NOT_DEFINED */
606 if (fprintf(FP, "%s", CmdPtr->serialization_buf) == EOF) {
607 writeFileFailed = TRUE;
608 }
609 return TRUE;
610 }
611
612 static
SaveExtendedCmdInfo(FP,nNumCmds,nCurCmdPos)613 int SaveExtendedCmdInfo(FP, nNumCmds, nCurCmdPos)
614 FILE *FP;
615 int nNumCmds, nCurCmdPos;
616 {
617 if (fprintf(FP, "cmdxinfo(%1d,%1d).\n", nNumCmds, nCurCmdPos) == EOF) {
618 writeFileFailed = TRUE;
619 }
620 return TRUE;
621 }
622
623 #ifdef _TGIF_DBG_WB2
624 static
DebugDumpCmd(psz_prefix,cmd_type,logical_clock,psz_process_id)625 void DebugDumpCmd(psz_prefix, cmd_type, logical_clock, psz_process_id)
626 char *psz_prefix, *psz_process_id;
627 int cmd_type, logical_clock;
628 {
629 if (psz_prefix == NULL) {
630 fprintf(stderr, "cmd(%1d,%1d,\"%s\")\n", cmd_type, logical_clock,
631 psz_process_id);
632 } else {
633 fprintf(stderr, "%s, cmd(%1d,%1d,\"%s\")\n", psz_prefix, cmd_type,
634 logical_clock, psz_process_id);
635 }
636 }
637 #endif /* _TGIF_DBG_WB2 */
638
SerializeCmd(CmdType,psi,pnAssignedLogicalClock,ppszPlainWBData,pnPlainWBDataSz)639 char *SerializeCmd(CmdType, psi, pnAssignedLogicalClock, ppszPlainWBData,
640 pnPlainWBDataSz)
641 int CmdType, *pnAssignedLogicalClock, *pnPlainWBDataSz;
642 SerializationInfo *psi;
643 char **ppszPlainWBData;
644 {
645 char *buf=NULL, header[MAXSTRING<<1];
646 int content_sz=0, ok=TRUE, header_sz=0, do_deflate=TRUE;
647 long loc_sec=0L, loc_msec=0L;
648
649 if (HasZlibSupport()) {
650 #ifdef _TGIF_DBG_WB2
651 do_deflate = FALSE;
652 #endif /* _TGIF_DBG_WB2 */
653 } else {
654 do_deflate = FALSE;
655 }
656 if (gstWBInfo.send_fp == NULL || gstWBInfo.gz_send_fp == NULL) {
657 sprintf(gszMsgBox, "Cannot open '%s' or '%s'.\n\nSerialization aborted.",
658 gstWBInfo.send_fname, gstWBInfo.gz_send_fname);
659 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
660 return NULL;
661 }
662 *pnAssignedLogicalClock = gstWBInfo.logical_clock;
663
664 rewind(gstWBInfo.send_fp);
665 writeFileFailed = FALSE;
666
667 UtilGetMilliSecTime(&loc_sec, &loc_msec);
668 if (fprintf(gstWBInfo.send_fp, "%%TGWB begin - %ld.%ld\n",
669 loc_sec, loc_msec) == EOF) {
670 writeFileFailed = TRUE;
671 }
672 Save(gstWBInfo.send_fp, NULL, 0, 1);
673 ok = SaveCmd(gstWBInfo.send_fp, CmdType, psi);
674 /* gstWBInfo.logical_clock has been incremented in SaveCmd() */
675
676 if (fprintf(gstWBInfo.send_fp, "%%TGWB end - %ld.%ld\n",
677 loc_sec, loc_msec) == EOF) {
678 writeFileFailed = TRUE;
679 }
680 if (writeFileFailed) {
681 FailToWriteFileMessage(gstWBInfo.send_fname);
682 return NULL;
683 }
684 if (!ok) {
685 return NULL;
686 }
687 content_sz = (int)ftell(gstWBInfo.send_fp);
688 /*
689 * From: <PID>:<IP>\r\n
690 * Content-Type: application/x-tgif-cmd\r\n
691 * Content-Length: <LENGTH>\r\n
692 * \r\n
693 * <DATA of size LENGTH>
694 */
695 if (do_deflate && HasZlibSupport()) {
696 int rc=0;
697 char *new_buf=NULL;
698
699 rewind(gstWBInfo.send_fp);
700 new_buf = (char*)malloc((content_sz+1)*sizeof(char));
701 if (new_buf == NULL) FailAllocMessage();
702 if (fread(new_buf, sizeof(char), content_sz, gstWBInfo.send_fp) !=
703 content_sz) {
704 #ifdef _TGIF_DBG_WB2
705 fprintf(stderr, "Failed to read %1d bytes in SerializeCmd().\n",
706 content_sz);
707 fflush(stderr);
708 #endif /* _TGIF_DBG_WB2 */
709 do_deflate = FALSE;
710 } else {
711 new_buf[content_sz] = '\0';
712 *pnPlainWBDataSz = content_sz+1;
713 *ppszPlainWBData = new_buf;
714
715 if (!DoDeflate(gstWBInfo.send_fp, NULL, content_sz,
716 gstWBInfo.gz_send_fp, TRUE, TRUE, &rc)) {
717 ZlibError(rc, TRUE);
718 do_deflate = FALSE;
719 } else {
720 content_sz = (int)ftell(gstWBInfo.gz_send_fp);
721 }
722 }
723 }
724 if (do_deflate) {
725 sprintf(header, "%s%s\r\n%s%s\r\n%s%1d\r\n\r\n",
726 "From: ", gszLocalPID,
727 "Content-Type: ", "application/x-tgif-cmd-z",
728 "Content-Length: ", content_sz);
729 header_sz = strlen(header);
730 buf = (char*)malloc((header_sz+content_sz+1)*sizeof(char));
731 if (buf == NULL) FailAllocMessage();
732 strcpy(buf, header);
733 rewind(gstWBInfo.gz_send_fp);
734 if (fread(&buf[header_sz], sizeof(char), content_sz,
735 gstWBInfo.gz_send_fp) != content_sz) {
736 sprintf(gszMsgBox, "Error in reading '%s'.\n\nSerialization aborted.",
737 gstWBInfo.gz_send_fname);
738 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
739
740 UtilFree(buf);
741 return NULL;
742 }
743 } else {
744 sprintf(header, "%s%s\r\n%s%s\r\n%s%1d\r\n\r\n",
745 "From: ", gszLocalPID,
746 "Content-Type: ", "application/x-tgif-cmd",
747 "Content-Length: ", content_sz);
748 header_sz = strlen(header);
749 buf = (char*)malloc((header_sz+content_sz+1)*sizeof(char));
750 if (buf == NULL) FailAllocMessage();
751 strcpy(buf, header);
752 rewind(gstWBInfo.send_fp);
753 if (fread(&buf[header_sz], sizeof(char), content_sz, gstWBInfo.send_fp) !=
754 content_sz) {
755 sprintf(gszMsgBox, "Error in reading '%s'.\n\nSerialization aborted.",
756 gstWBInfo.send_fname);
757 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
758
759 UtilFree(buf);
760 return NULL;
761 }
762 }
763 buf[header_sz+content_sz] = '\0';
764 #ifdef _TGIF_DBG_WB2
765 if (wb2DebugLevel == 0) {
766 fprintf(stderr, "Sending %1d bytes, pid = %ld!\n", header_sz+content_sz+2,
767 gstWBInfo.pid);
768 } else {
769 fprintf(stderr, "===========================\n");
770 if (do_deflate) {
771 fprintf(stderr, "%s", header);
772 fprintf(stderr, "[content not displayed] ...\n");
773 } else {
774 fprintf(stderr, "%s", buf);
775 }
776 fprintf(stderr, "===========================\n");
777 fprintf(stderr, "Sending %1d bytes, pid = %ld!\n", header_sz+content_sz+2,
778 gstWBInfo.pid);
779 }
780 DebugDumpCmd(">>> In SerializeCmd()",
781 CmdType, *pnAssignedLogicalClock, gszLocalPID);
782 PrintFullIDsOfObjects("In SerializeCmd()");
783 #endif /* _TGIF_DBG_WB2 */
784
785 return buf;
786 }
787
SerializeFreeBuf(pszWBData)788 void SerializeFreeBuf(pszWBData)
789 char *pszWBData;
790 {
791 UtilFree(pszWBData);
792 }
793
794 static struct CmdRec gstDeserializeCmd;
795 static struct SubCmdRec *gpDeserializeSubCmd=NULL;
796
797 static char **gppszBeforeImage=NULL;
798 static int gnBeforeImageCount=0;
799
800 static int *gpnAfterPositions=NULL;
801 static int gnAfterPositionsCount=0;
802
803 static int seenCmdXInfo=FALSE;
804
805 static
CleanUpDeserializeCmd()806 void CleanUpDeserializeCmd()
807 {
808 if (gpDeserializeSubCmd != NULL) free(gpDeserializeSubCmd);
809 memset(&gstDeserializeCmd, 0, sizeof(struct CmdRec));
810 gpDeserializeSubCmd = NULL;
811 }
812
813 static
InitDeserializeCmd()814 int InitDeserializeCmd()
815 {
816 gpDeserializeSubCmd = (struct SubCmdRec *)malloc(sizeof(struct SubCmdRec));
817 if (gpDeserializeSubCmd == NULL) FailAllocMessage();
818 memset(gpDeserializeSubCmd, 0, sizeof(struct SubCmdRec));
819 memset(&gstDeserializeCmd, 0, sizeof(struct CmdRec));
820 gstDeserializeCmd.subcmd = gpDeserializeSubCmd;
821
822 return TRUE;
823 }
824
825 static
DoDeserializationCleanUp()826 void DoDeserializationCleanUp()
827 {
828 switch (gstDeserializeCmd.type) {
829 case CMD_WB_CLEARALL: break;
830 case CMD_CHAT_A_LINE:
831 UtilFree(gpDeserializeSubCmd->detail.chat.buf);
832 break;
833 case CMD_WB_SLIDESHOW: break;
834 default: break;
835 }
836 memset(gpDeserializeSubCmd, 0, sizeof(struct SubCmdRec));
837 memset(&gstDeserializeCmd, 0, sizeof(gstDeserializeCmd));
838 gstDeserializeCmd.subcmd = gpDeserializeSubCmd;
839 gstDeserializeCmd.type = INVALID;
840 }
841
842 static
CleanUpBeforeImage()843 void CleanUpBeforeImage()
844 {
845 if (gppszBeforeImage != NULL) {
846 int i;
847
848 for (i=0; i < gnBeforeImageCount; i++) {
849 if (gppszBeforeImage[i] != NULL) {
850 UtilFree(gppszBeforeImage[i]);
851 } else {
852 break;
853 }
854 }
855 free(gppszBeforeImage);
856 }
857 gppszBeforeImage = NULL;
858 gnBeforeImageCount = 0;
859 }
860
861 static
CleanUpAfterPositions()862 void CleanUpAfterPositions()
863 {
864 if (gpnAfterPositions != NULL) free(gpnAfterPositions);
865 gpnAfterPositions = NULL;
866 gnAfterPositionsCount = 0;
867 }
868
869 static
DeserializationCleanUp()870 void DeserializationCleanUp()
871 {
872 DoDeserializationCleanUp();
873 CleanUpBeforeImage();
874 CleanUpAfterPositions();
875 }
876
877 static
ResetDeserializeCmd()878 void ResetDeserializeCmd()
879 {
880 recordCmdIncludeTgifObj = FALSE;
881 recordCmdUsesNewColormap = FALSE;
882
883 memset(&gstDeserializeCmd, 0, sizeof(gstDeserializeCmd));
884 gstDeserializeCmd.subcmd = gpDeserializeSubCmd;
885 gstDeserializeCmd.type = INVALID;
886 gppszBeforeImage = NULL;
887 gpnAfterPositions = NULL;
888 gnBeforeImageCount = gnAfterPositionsCount = 0;
889 }
890
ReadExtendedCmd(FP,Inbuf)891 int ReadExtendedCmd(FP, Inbuf)
892 FILE *FP;
893 char *Inbuf;
894 {
895 char *c_ptr=NULL;
896
897 c_ptr = FindChar((int)'(', Inbuf);
898 InitScan(c_ptr, "\t\n, ()");
899 if (GETINT("cmdx", gstDeserializeCmd.type, "cmd_type") == INVALID ||
900 GETINT("cmdx", gstDeserializeCmd.undone, "undone") == INVALID) {
901 return FALSE;
902 }
903 if (gstDeserializeCmd.type == INVALID) {
904 return FALSE;
905 } else if (gstDeserializeCmd.type == CMD_GOTO_PAGE) {
906 return FALSE;
907 } else if (gstDeserializeCmd.type == CMD_WB_CLEARALL) {
908 int page_style=PORTRAIT;
909 float print_mag=(float)100.0;
910
911 if (GETINT("cmdx", page_style, "page_style") == INVALID ||
912 GETFLT("cmdx", print_mag, "print_mag") == INVALID) {
913 return FALSE;
914 }
915 gpDeserializeSubCmd->detail.clearall.page_style = page_style;
916 gpDeserializeSubCmd->detail.clearall.print_mag = print_mag;
917 } else if (gstDeserializeCmd.type == CMD_WB_SLIDESHOW) {
918 int into_slideshow=FALSE;
919
920 if (GETINT("cmdx", into_slideshow, "into_slideshow") == INVALID) {
921 return FALSE;
922 }
923 gpDeserializeSubCmd->detail.slideshow.into_slideshow = into_slideshow;
924 } else if (gstDeserializeCmd.type == CMD_CHAT_A_LINE) {
925 char nick_name[MAXSTRING], color_str[40], font_str[MAXSTRING];
926 char encoding[MAXSTRING];
927 int chat_type=FALSE, font_style=0, new_alloc=0;
928 struct DynStrRec dyn_str;
929
930 memset(&dyn_str, 0, sizeof(struct DynStrRec));
931 *nick_name = *color_str = *font_str = *encoding = '\0';
932
933 if (GETINT("cmdx", chat_type, "type") == INVALID ||
934 GETSTR("cmdx", nick_name, "nick_name") == INVALID ||
935 GETSTR("cmdx", color_str, "color_str") == INVALID ||
936 GETINT("cmdx", font_style, "font_style") == INVALID ||
937 GETSTR("cmdx", encoding, "encoding") == INVALID ||
938 GETDYN("cmdx", dyn_str, "buf") == INVALID) {
939 return FALSE;
940 }
941 UtilRemoveQuotes(nick_name);
942 UtilRemoveQuotes(color_str);
943 UtilRemoveQuotes(encoding);
944
945 gpDeserializeSubCmd->detail.chat.tfi.color_index =
946 QuickFindColorIndex(NULL, color_str, &new_alloc, TRUE);
947 UtilStrCpyN(gpDeserializeSubCmd->detail.chat.tfi.color_str,
948 sizeof(gpDeserializeSubCmd->detail.chat.tfi.color_str),
949 colorMenuItems[gpDeserializeSubCmd->detail.chat.tfi.color_index]);
950
951 gpDeserializeSubCmd->detail.chat.tfi.font_style = font_style;
952 gpDeserializeSubCmd->detail.chat.type = chat_type;
953 UtilStrCpyN(gpDeserializeSubCmd->detail.chat.nick_name,
954 sizeof(gpDeserializeSubCmd->detail.chat.nick_name), nick_name);
955 UtilStrCpyN(gpDeserializeSubCmd->detail.chat.encoding,
956 sizeof(gpDeserializeSubCmd->detail.chat.encoding), encoding);
957 gpDeserializeSubCmd->detail.chat.buf = dyn_str.s;
958 dyn_str.s = NULL;
959 } else if (gstDeserializeCmd.type == CMD_MOVE) {
960 int dx=0, dy=0;
961
962 if (GETINT("cmdx", dx, "dx") == INVALID ||
963 GETINT("cmdx", dy, "dy") == INVALID) {
964 return FALSE;
965 }
966 gpDeserializeSubCmd->detail.move.dx = dx;
967 gpDeserializeSubCmd->detail.move.dy = dy;
968 }
969 *recordCmdSenderProcID = '\0';
970 if (GETINT("cmdx", recordCmdIncludeTgifObj, "include_tgif_obj")==INVALID ||
971 GETINT("cmdx", recordCmdUsesNewColormap, "use_new_colormap")==INVALID ||
972 GETINT("cmdx", recordCmdLogicalClock, "logical_clock")==INVALID ||
973 GETSTR("cmdx", recordCmdSenderProcID, "sender_process_id")==INVALID ||
974 GETINT("cmdx", gstDeserializeCmd.undone, "undone")==INVALID) {
975 return FALSE;
976 }
977 UtilRemoveQuotes(recordCmdSenderProcID);
978
979 return TRUE;
980 }
981
ReadExtendedCmdInfo(FP,Inbuf)982 int ReadExtendedCmdInfo(FP, Inbuf)
983 FILE *FP;
984 char *Inbuf;
985 {
986 char *c_ptr=NULL;
987 int num_cmds=0, cur_cmd_pos=0;
988
989 c_ptr = FindChar((int)'(', Inbuf);
990 InitScan(c_ptr, "\t\n, ()");
991 if (GETINT("cmdxinfo", num_cmds, "num_cmds") == INVALID ||
992 GETINT("cmdxinfo", cur_cmd_pos, "cur_cmd_pos") == INVALID) {
993 return FALSE;
994 }
995 seenCmdXInfo = TRUE;
996
997 return TRUE;
998 }
999
ReadCmd(FP,Inbuf)1000 int ReadCmd(FP, Inbuf)
1001 FILE *FP;
1002 char *Inbuf;
1003 {
1004 char *c_ptr=NULL;
1005
1006 ResetDeserializeCmd();
1007
1008 c_ptr = FindChar((int)'(', Inbuf);
1009 InitScan(c_ptr, "\t\n, ()");
1010 if (GETINT("cmd", gstDeserializeCmd.type, "cmd_type") == INVALID) {
1011 return FALSE;
1012 }
1013 if (gstDeserializeCmd.type == INVALID) {
1014 return FALSE;
1015 } else if (gstDeserializeCmd.type == CMD_GOTO_PAGE) {
1016 return FALSE;
1017 } else if (gstDeserializeCmd.type == CMD_WB_CLEARALL) {
1018 int page_style=PORTRAIT;
1019 float print_mag=(float)100.0;
1020
1021 if (GETINT("cmd", page_style, "page_style") == INVALID ||
1022 GETFLT("cmd", print_mag, "print_mag") == INVALID) {
1023 return FALSE;
1024 }
1025 gpDeserializeSubCmd->detail.clearall.page_style = page_style;
1026 gpDeserializeSubCmd->detail.clearall.print_mag = print_mag;
1027 } else if (gstDeserializeCmd.type == CMD_WB_SLIDESHOW) {
1028 int into_slideshow=FALSE;
1029
1030 if (GETINT("cmd", into_slideshow, "into_slideshow") == INVALID) {
1031 return FALSE;
1032 }
1033 gpDeserializeSubCmd->detail.slideshow.into_slideshow = into_slideshow;
1034 } else if (gstDeserializeCmd.type == CMD_CHAT_A_LINE) {
1035 char nick_name[MAXSTRING], color_str[40], font_str[MAXSTRING];
1036 char encoding[MAXSTRING];
1037 int chat_type=FALSE, font_style=0, new_alloc=0;
1038 struct DynStrRec dyn_str;
1039
1040 memset(&dyn_str, 0, sizeof(struct DynStrRec));
1041 *nick_name = *color_str = *font_str = *encoding = '\0';
1042
1043 if (GETINT("cmd", chat_type, "type") == INVALID ||
1044 GETSTR("cmd", nick_name, "nick_name") == INVALID ||
1045 GETSTR("cmd", color_str, "color_str") == INVALID ||
1046 GETINT("cmd", font_style, "font_style") == INVALID ||
1047 GETSTR("cmd", encoding, "encoding") == INVALID ||
1048 GETDYN("cmd", dyn_str, "buf") == INVALID) {
1049 return FALSE;
1050 }
1051 UtilRemoveQuotes(nick_name);
1052 UtilRemoveQuotes(color_str);
1053 UtilRemoveQuotes(encoding);
1054
1055 gpDeserializeSubCmd->detail.chat.tfi.color_index =
1056 QuickFindColorIndex(NULL, color_str, &new_alloc, TRUE);
1057 UtilStrCpyN(gpDeserializeSubCmd->detail.chat.tfi.color_str,
1058 sizeof(gpDeserializeSubCmd->detail.chat.tfi.color_str),
1059 colorMenuItems[gpDeserializeSubCmd->detail.chat.tfi.color_index]);
1060
1061 gpDeserializeSubCmd->detail.chat.tfi.font_style = font_style;
1062 gpDeserializeSubCmd->detail.chat.type = chat_type;
1063 UtilStrCpyN(gpDeserializeSubCmd->detail.chat.nick_name,
1064 sizeof(gpDeserializeSubCmd->detail.chat.nick_name), nick_name);
1065 UtilStrCpyN(gpDeserializeSubCmd->detail.chat.encoding,
1066 sizeof(gpDeserializeSubCmd->detail.chat.encoding), encoding);
1067 gpDeserializeSubCmd->detail.chat.buf = dyn_str.s;
1068 dyn_str.s = NULL;
1069 } else if (gstDeserializeCmd.type == CMD_MOVE) {
1070 int dx=0, dy=0;
1071
1072 if (GETINT("cmd", dx, "dx") == INVALID ||
1073 GETINT("cmd", dy, "dy") == INVALID) {
1074 return FALSE;
1075 }
1076 gpDeserializeSubCmd->detail.move.dx = dx;
1077 gpDeserializeSubCmd->detail.move.dy = dy;
1078 }
1079 *recordCmdSenderProcID = '\0';
1080 if (GETINT("cmd", recordCmdIncludeTgifObj, "include_tgif_obj") == INVALID ||
1081 GETINT("cmd", recordCmdUsesNewColormap, "use_new_colormap") == INVALID ||
1082 GETINT("cmd", recordCmdLogicalClock, "logical_clock") == INVALID ||
1083 GETSTR("cmd", recordCmdSenderProcID, "sender_process_id") == INVALID) {
1084 return FALSE;
1085 }
1086 UtilRemoveQuotes(recordCmdSenderProcID);
1087 return TRUE;
1088 }
1089
ReadBeforeImage(FP,Inbuf)1090 int ReadBeforeImage(FP, Inbuf)
1091 FILE *FP;
1092 char *Inbuf;
1093 {
1094 char *c_ptr, *line;
1095 int index=0, ok=TRUE;
1096
1097 c_ptr = FindChar((int)'(', Inbuf);
1098 InitScan(c_ptr, "\t\n, ");
1099 if (GETINT("before_image", gnBeforeImageCount, "before_image_count") ==
1100 INVALID) {
1101 return FALSE;
1102 }
1103 if (gnBeforeImageCount > 0) {
1104 gppszBeforeImage = (char**)malloc(gnBeforeImageCount*sizeof(char*));
1105 if (gppszBeforeImage == NULL) FailAllocMessage();
1106 memset(gppszBeforeImage, 0, gnBeforeImageCount*sizeof(char*));
1107 }
1108 index = 0;
1109 while ((line=UtilGetALine(FP)) != NULL) {
1110 char full_id[MAXSTRING];
1111
1112 scanLineNum++;
1113 if (*line == ']') {
1114 free(line);
1115 break;
1116 }
1117 if (index >= gnBeforeImageCount) {
1118 fprintf(stderr, "Warning: too many lines in before_image.\n");
1119 free(line);
1120 break;
1121 }
1122 c_ptr = FindChar((int)'"', line);
1123 c_ptr = ParseStr(c_ptr, (int)'"', full_id, sizeof(full_id));
1124 if (c_ptr == NULL) {
1125 ok = FALSE;
1126 free(line);
1127 break;
1128 }
1129 gppszBeforeImage[index] = UtilStrDup(full_id);
1130 if (gppszBeforeImage[index] == NULL) FailAllocMessage();
1131 index++;
1132 free(line);
1133 }
1134 if (ok && index < gnBeforeImageCount) {
1135 fprintf(stderr, "Warning: too few lines in before_image.\n");
1136 ok = FALSE;
1137 }
1138 if (!ok) {
1139 CleanUpBeforeImage();
1140 }
1141 return ok;
1142 }
1143
ReadAfterPositions(FP,Inbuf)1144 int ReadAfterPositions(FP, Inbuf)
1145 FILE *FP;
1146 char *Inbuf;
1147 {
1148 char *c_ptr, *line;
1149 int index=0, ok=TRUE;
1150
1151 c_ptr = FindChar((int)'(', Inbuf);
1152 InitScan(c_ptr, "\t\n, ");
1153 if (GETINT("after_positions", gnAfterPositionsCount,
1154 "after_positions_count") == INVALID) {
1155 return FALSE;
1156 }
1157 if (gnAfterPositionsCount > 0) {
1158 gpnAfterPositions = (int*)malloc(gnAfterPositionsCount*sizeof(int));
1159 if (gpnAfterPositions == NULL) FailAllocMessage();
1160 memset(gpnAfterPositions, 0, gnAfterPositionsCount*sizeof(int));
1161 }
1162 index = 0;
1163 while ((line=UtilGetALine(FP)) != NULL) {
1164 int pos=(-1);
1165
1166 scanLineNum++;
1167 if (*line == ']') {
1168 free(line);
1169 break;
1170 }
1171 if (index >= gnAfterPositionsCount) {
1172 fprintf(stderr, "Warning: too many lines in before_image.\n");
1173 free(line);
1174 break;
1175 }
1176 InitScan(line, "\t\n, ");
1177 if (GETINT("after_positions", pos, "after_positions_pos") == INVALID) {
1178 ok = FALSE;
1179 free(line);
1180 break;
1181 }
1182 gpnAfterPositions[index++] = pos;
1183 free(line);
1184 }
1185 if (ok && index < gnAfterPositionsCount) {
1186 fprintf(stderr, "Warning: too few lines in after_positions.\n");
1187 ok = FALSE;
1188 }
1189 if (!ok) {
1190 CleanUpBeforeImage();
1191 }
1192 return ok;
1193 }
1194
ReadAfterImage(FP,Inbuf)1195 int ReadAfterImage(FP, Inbuf)
1196 FILE *FP;
1197 char *Inbuf;
1198 {
1199 struct ObjRec *obj_ptr=NULL;
1200 char *c_ptr;
1201 int ok=TRUE, count_expected=(-1), count=0;
1202
1203 c_ptr = FindChar((int)'(', Inbuf);
1204 InitScan(c_ptr, "\t\n, ");
1205 if (GETINT("after_image", count_expected, "after_image_count") == INVALID) {
1206 return FALSE;
1207 }
1208 count = 0;
1209 while (ReadObj(FP, &obj_ptr)) {
1210 if (obj_ptr == NULL) {
1211 ok = FALSE;
1212 break;
1213 }
1214 obj_ptr->next = NULL;
1215 obj_ptr->prev = botObj;
1216 if (botObj == NULL) {
1217 topObj = obj_ptr;
1218 } else {
1219 botObj->next = obj_ptr;
1220 }
1221 botObj = obj_ptr;
1222 obj_ptr = NULL;
1223 count++;
1224 }
1225 if (ok && count != count_expected) {
1226 fprintf(stderr, "Warning: object count mismatched in after_image.\n");
1227 ok = FALSE;
1228 }
1229 return ok;
1230 }
1231
1232 static
SelectObjects(top_obj,bot_obj)1233 void SelectObjects(top_obj, bot_obj)
1234 struct ObjRec *top_obj, *bot_obj;
1235 {
1236 struct ObjRec *obj_ptr;
1237
1238 for (obj_ptr=bot_obj; obj_ptr != NULL; obj_ptr=obj_ptr->prev) {
1239 obj_ptr->tmp_parent = NULL;
1240 AddObjIntoSel(obj_ptr, NULL, topSel, &topSel, &botSel);
1241 }
1242 UpdSelBBox();
1243 }
1244
1245 static
DeserializeCmd(psz_content_type,psz_buf,buf_sz,ppsz_plain_buf,pn_plain_buf_sz)1246 struct CmdRec *DeserializeCmd(psz_content_type, psz_buf, buf_sz, ppsz_plain_buf,
1247 pn_plain_buf_sz)
1248 char *psz_content_type, *psz_buf, **ppsz_plain_buf;
1249 int buf_sz, *pn_plain_buf_sz;
1250 {
1251 struct StkRec *stk_ptr=NULL;
1252 struct ObjRec *obj_ptr=NULL, *saved_top_obj=NULL, *saved_bot_obj=NULL;
1253 int read_status=TRUE, ok=TRUE, do_inflate=FALSE, need_to_free_buf=FALSE;
1254 struct CmdRec *cmd_ptr=NULL;
1255
1256 if (gstWBInfo.listen_fp == NULL) {
1257 sprintf(gszMsgBox, "Cannot open '%s'.\n\n%s pid=%ld.",
1258 gstWBInfo.listen_fname, "Deserialization aborted for",
1259 gstWBInfo.pid);
1260 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1261 return NULL;
1262 }
1263 #ifdef _TGIF_DBG_WB2
1264 fprintf(stderr, "Content-Type: %s\n",
1265 (psz_content_type!=NULL) ? psz_content_type : "(unknown)");
1266 fprintf(stderr, "Content-Length: %1d\n", buf_sz);
1267 #endif /* _TGIF_DBG_WB2 */
1268 if (psz_content_type != NULL &&
1269 strcmp(psz_content_type, "application/x-tgif-cmd-z") == 0) {
1270 if (!HasZlibSupport()) {
1271 sprintf(gszMsgBox, "%s %s.\n\nDeserialization aborted.",
1272 TOOL_NAME, "is not compiled with ZLIB and cannot inflate()");
1273 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1274 return NULL;
1275 } else {
1276 if (gstWBInfo.gz_listen_fp == NULL) {
1277 sprintf(gszMsgBox, "Cannot open '%s'.\n\n%s pid=%ld.",
1278 gstWBInfo.gz_listen_fname, "Deserialization aborted for",
1279 gstWBInfo.pid);
1280 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1281 return NULL;
1282 }
1283 do_inflate = TRUE;
1284 }
1285 }
1286
1287 if (do_inflate && HasZlibSupport()) {
1288 int rc=0;
1289
1290 if (!DoInflate(psz_buf, buf_sz, gstWBInfo.gz_listen_fp, TRUE, &rc)) {
1291 ZlibError(rc, FALSE);
1292 return NULL;
1293 }
1294 buf_sz = (int)ftell(gstWBInfo.gz_listen_fp);
1295 psz_buf = (char*)malloc(buf_sz+1);
1296 if (psz_buf == NULL) FailAllocMessage();
1297 rewind(gstWBInfo.gz_listen_fp);
1298 if (fread(psz_buf, sizeof(char), buf_sz, gstWBInfo.gz_listen_fp) !=
1299 buf_sz) {
1300 sprintf(gszMsgBox, "Cannot read %1d bytes from '%s'.\n\n%s.",
1301 buf_sz, gstWBInfo.gz_listen_fname, "Deserialization aborted");
1302 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1303 UtilFree(psz_buf);
1304 return NULL;
1305 }
1306 psz_buf[buf_sz] = '\0';
1307 if (ppsz_plain_buf != NULL) {
1308 *pn_plain_buf_sz = buf_sz;
1309 *ppsz_plain_buf = UtilStrDup(psz_buf);
1310 if (*ppsz_plain_buf == NULL) FailAllocMessage();
1311 }
1312 need_to_free_buf = TRUE;
1313 }
1314
1315 #ifdef _TGIF_DBG_WB2
1316 if (wb2DebugLevel == 0) {
1317 fprintf(stderr, "Received %1d bytes, pid = %ld, timestamp = (below)\n",
1318 buf_sz, gstWBInfo.pid);
1319 } else {
1320 fprintf(stderr, "<<<------------------------\n");
1321 fprintf(stderr, "%s\n", psz_buf);
1322 fprintf(stderr, "<<<------------------------\n");
1323 fprintf(stderr, "Received %1d bytes, pid = %ld, timestamp = (below)\n",
1324 buf_sz, gstWBInfo.pid);
1325 }
1326 PrintFullIDsOfObjects("In the beginning of DeserializeCmd()");
1327 #endif /* _TGIF_DBG_WB2 */
1328
1329 rewind(gstWBInfo.listen_fp);
1330 writeFileFailed = FALSE;
1331 if (fprintf(gstWBInfo.listen_fp, "%s", psz_buf) == EOF) {
1332 writeFileFailed = TRUE;
1333 }
1334 if (writeFileFailed) {
1335 FailToWriteFileMessage(gstWBInfo.listen_fname);
1336 return NULL;
1337 }
1338 stk_ptr = SaveFileInfo();
1339 ResetFileInfo();
1340 /* if (usePaperSizeStoredInFile) ResetOnePageSize(); */
1341
1342 ResetDeserializeCmd();
1343
1344 rewind(gstWBInfo.listen_fp);
1345 importingFile = TRUE;
1346
1347 strcpy(scanFileName, gstWBInfo.listen_fname);
1348 scanLineNum = 0;
1349 readingPageNum = loadedCurPageNum = 0;
1350 foundGoodStateObject = FALSE;
1351 while ((read_status=ReadObj(gstWBInfo.listen_fp, &obj_ptr)) == TRUE) {
1352 if (obj_ptr != NULL) {
1353 obj_ptr->tmp_parent = NULL;
1354 AdjForOldVersion(obj_ptr);
1355 AddObj(NULL, topObj, obj_ptr);
1356 }
1357 }
1358 importingFile = FALSE;
1359
1360 if (read_status == INVALID) {
1361 sprintf(gszMsgBox, "File version too large (=%1d). %s!",
1362 fileVersion, "Deserialization aborted");
1363 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1364 ok = FALSE;
1365 } else {
1366 #ifdef _TGIF_DBG_WB2
1367 fprintf(stderr, "%s, pid = %ld, timestamp = %1d/%s\n",
1368 "Command successfully parsed", gstWBInfo.pid, recordCmdLogicalClock,
1369 recordCmdSenderProcID);
1370 #endif /* _TGIF_DBG_WB2 */
1371 if (recordCmdLogicalClock+1 > gstWBInfo.logical_clock) {
1372 /* Lamport's Algorithm set logical_clock */
1373 gstWBInfo.logical_clock = recordCmdLogicalClock+1;
1374 #ifdef _TGIF_DBG_WB2
1375 fprintf(stderr, "Logical clock for pid = %ld set to %1d.\n",
1376 gstWBInfo.pid, gstWBInfo.logical_clock);
1377 #endif /* _TGIF_DBG_WB2 */
1378 }
1379 }
1380 if (!ok) {
1381 DelAllObj();
1382 } else {
1383 saved_top_obj = topObj;
1384 saved_bot_obj = botObj;
1385 topObj = botObj = NULL;
1386 }
1387 RestoreFileInfo(stk_ptr);
1388 ResetOnePageSize();
1389 free(stk_ptr);
1390 /*
1391 * This is new. Does it work?!
1392 */
1393 UpdPageStyle(pageStyle);
1394
1395 if (ok) {
1396 cmd_ptr = (struct CmdRec *)malloc(sizeof(struct CmdRec));
1397 if (cmd_ptr == NULL) FailAllocMessage();
1398 memset(cmd_ptr, 0, sizeof(struct CmdRec));
1399 cmd_ptr->serialized = TRUE; /* created from deserialization */
1400 cmd_ptr->top_before = cmd_ptr->bot_before = NULL;
1401 cmd_ptr->pos_before = (int*)gppszBeforeImage;
1402 cmd_ptr->count_before = gnBeforeImageCount;
1403 cmd_ptr->type = gstDeserializeCmd.type;
1404 cmd_ptr->undone = TRUE;
1405 cmd_ptr->include_tgif_obj = recordCmdIncludeTgifObj;
1406 cmd_ptr->new_colormap = recordCmdUsesNewColormap;
1407 cmd_ptr->logical_clock = recordCmdLogicalClock;
1408 if (*recordCmdSenderProcID != '\0') {
1409 cmd_ptr->sender_process_id = UtilStrDup(recordCmdSenderProcID);
1410 if (cmd_ptr->sender_process_id == NULL) FailAllocMessage();
1411 }
1412 cmd_ptr->first_redo_after_deserialize = TRUE;
1413 cmd_ptr->skipped = FALSE;
1414 #ifdef _TGIF_DBG_WB2
1415 DebugDumpCmd("<<< In DeserializeCmd()", cmd_ptr->type,
1416 cmd_ptr->logical_clock, cmd_ptr->sender_process_id);
1417 #endif /* _TGIF_DBG_WB2 */
1418 if (saved_top_obj != NULL) {
1419 SelectObjects(saved_top_obj, saved_bot_obj);
1420 CopySel(topSel, numObjSelected,
1421 &(cmd_ptr->top_after), &(cmd_ptr->bot_after));
1422 cmd_ptr->pos_after = gpnAfterPositions;
1423 cmd_ptr->count_after = gnAfterPositionsCount;
1424 RemoveAllSel();
1425 } else {
1426 cmd_ptr->top_after = cmd_ptr->bot_after = NULL;
1427 cmd_ptr->pos_after = NULL;
1428 cmd_ptr->count_after = 0;
1429 }
1430 gppszBeforeImage = NULL;
1431 gnBeforeImageCount = 0;
1432 gpnAfterPositions = NULL;
1433 gnAfterPositionsCount = 0;
1434 }
1435 /*
1436 * Move this to the end of ProcessRemoteCmd() because we may need
1437 * some information from gpDeserializeSubCmd.
1438 *
1439 * DeserializationCleanUp();
1440 */
1441
1442 #ifdef _TGIF_DBG_WB2
1443 PrintFullIDsOfObjects("At the end of DeserializeCmd()");
1444 #endif /* _TGIF_DBG_WB2 */
1445
1446 if (need_to_free_buf) UtilFree(psz_buf);
1447
1448 return cmd_ptr;
1449 }
1450
1451 static
TotalOrderForTwo(older_cmd,newer_cmd)1452 int TotalOrderForTwo(older_cmd, newer_cmd)
1453 struct CmdRec *older_cmd, *newer_cmd;
1454 /*
1455 * Note: If logical clocks and host names are the same, and if pid in
1456 * older_cmd is less than pid in newer_cmd, will return TRUE!
1457 */
1458 {
1459 int comparison=0;
1460
1461 if (older_cmd == NULL || newer_cmd == NULL) return TRUE;
1462
1463 if (older_cmd->logical_clock > newer_cmd->logical_clock) {
1464 return FALSE;
1465 } else if (older_cmd->logical_clock < newer_cmd->logical_clock) {
1466 return TRUE;
1467 }
1468 comparison = strcmp(older_cmd->sender_process_id,
1469 newer_cmd->sender_process_id);
1470 TgAssert(comparison != 0,
1471 "Identical logical clock detected in TotalOrderForTwo()", NULL);
1472 return (comparison < 0);
1473 }
1474
1475 #ifdef _TGIF_DBG_WB2
1476 static
DumpCmdStack(prefix_string)1477 void DumpCmdStack(prefix_string)
1478 char *prefix_string;
1479 /* Dump the command stack, last one first */
1480 {
1481 struct CmdRec *cmd_ptr=NULL;
1482
1483 if (prefix_string != NULL) fprintf(stderr, "%s\n", prefix_string);
1484 for (cmd_ptr=gstWBInfo.last_cmd; cmd_ptr != NULL; cmd_ptr=cmd_ptr->prev) {
1485 char buf[256];
1486
1487 if (cmd_ptr->skipped) {
1488 sprintf(buf, "\tcmd_ptr->next = 0x%08lx, (SKIPPED)",
1489 (long)cmd_ptr->next);
1490 } else {
1491 sprintf(buf, "\tcmd_ptr->next = 0x%08lx", (long)cmd_ptr->next);
1492 }
1493 DebugDumpCmd(buf, cmd_ptr->type, cmd_ptr->logical_clock,
1494 cmd_ptr->sender_process_id);
1495 }
1496 }
1497 #endif /* _TGIF_DBG_WB2 */
1498
FindCmdInsertionPoint(cmd_to_insert,pp_immed_right_cmd)1499 void FindCmdInsertionPoint(cmd_to_insert, pp_immed_right_cmd)
1500 struct CmdRec *cmd_to_insert, **pp_immed_right_cmd;
1501 /*
1502 * On return, cmd_to_insert is to be inserted immediately to the left
1503 * of *pp_immed_right_cmd.
1504 */
1505 {
1506 struct CmdRec *cmd_ptr=NULL;
1507
1508 for (cmd_ptr=gstWBInfo.last_cmd; cmd_ptr != NULL; cmd_ptr=cmd_ptr->prev) {
1509 if (TotalOrderForTwo(cmd_ptr, cmd_to_insert)) {
1510 *pp_immed_right_cmd = cmd_ptr->next;
1511 return;
1512 }
1513 }
1514 *pp_immed_right_cmd = gstWBInfo.first_cmd;
1515 }
1516
FindShadowCmdInsertionPoint(cmd_to_insert,pp_immed_right_cmd)1517 void FindShadowCmdInsertionPoint(cmd_to_insert, pp_immed_right_cmd)
1518 struct CmdRec *cmd_to_insert, **pp_immed_right_cmd;
1519 /*
1520 * On return, cmd_to_insert is to be inserted immediately to the left
1521 * of *pp_immed_right_cmd.
1522 */
1523 {
1524 struct CmdRec *cmd_ptr=NULL;
1525
1526 for (cmd_ptr=gstWBInfo.last_shadow_cmd; cmd_ptr != NULL;
1527 cmd_ptr=cmd_ptr->prev) {
1528 if (TotalOrderForTwo(cmd_ptr, cmd_to_insert)) {
1529 *pp_immed_right_cmd = cmd_ptr->next;
1530 return;
1531 }
1532 }
1533 *pp_immed_right_cmd = gstWBInfo.first_shadow_cmd;
1534 }
1535
1536 static
HighLightExistingObjects()1537 void HighLightExistingObjects()
1538 /*
1539 * If select object no longer exists, don't select and highlight it!
1540 */
1541 {
1542 int something_deleted=FALSE;
1543 struct SelRec *sel_ptr=NULL, *next_sel=NULL;
1544
1545 for (sel_ptr=topSel; sel_ptr != NULL; sel_ptr=next_sel) {
1546 next_sel = sel_ptr->next;
1547 if (!IsTopLevelObject(sel_ptr->obj)) {
1548 UnlinkSel(sel_ptr, &topSel, &botSel);
1549 free(sel_ptr);
1550 something_deleted = TRUE;
1551 }
1552 }
1553 if (something_deleted) UpdSelBBox();
1554 HighLightForward();
1555 }
1556
CleanUpObsoletedWBCmds(stopped_cmd_ptr)1557 void CleanUpObsoletedWBCmds(stopped_cmd_ptr)
1558 struct CmdRec *stopped_cmd_ptr;
1559 {
1560 struct CmdRec *cmd_ptr=NULL;
1561 int num_records=0;
1562
1563 for (cmd_ptr=stopped_cmd_ptr->prev; cmd_ptr != NULL; cmd_ptr=cmd_ptr->prev) {
1564 num_records++;
1565 }
1566 if (num_records > 0) {
1567 struct CmdRec *prev_cmd=NULL;
1568 double inc=(100.0/((double)num_records)), percent_start=0.0;
1569
1570 ShowInterrupt(1);
1571 SaveStatusStrings();
1572 for (cmd_ptr=stopped_cmd_ptr->prev; cmd_ptr != NULL; cmd_ptr=prev_cmd,
1573 percent_start+=inc) {
1574 prev_cmd = cmd_ptr->prev;
1575 DeleteARedoRecord(cmd_ptr, percent_start,
1576 min(((double)percent_start+inc),((double)100.0)));
1577 }
1578 RestoreStatusStrings();
1579 HideInterrupt();
1580 }
1581 gstWBInfo.first_cmd = stopped_cmd_ptr;
1582 gstWBInfo.first_cmd->prev = NULL;
1583
1584 CleanUpWBShadowCmds();
1585 }
1586
1587 static
HandleChatLine(cmd_ptr)1588 void HandleChatLine(cmd_ptr)
1589 struct CmdRec *cmd_ptr;
1590 {
1591 struct ChatSubCmdRec *pChatSubCmdInfo=(&gpDeserializeSubCmd->detail.chat);
1592
1593 switch (pChatSubCmdInfo->type) {
1594 case CHAT_STATE_NORMAL:
1595 ChatAppendChatLine(&pChatSubCmdInfo->tfi, pChatSubCmdInfo->nick_name,
1596 pChatSubCmdInfo->encoding, pChatSubCmdInfo->buf);
1597 break;
1598 case CHAT_STATE_HELLO:
1599 break;
1600 case CHAT_STATE_DISCONNECT:
1601 /* handle explicit user disconnect */
1602 break;
1603 }
1604 /*
1605 * Handle the chat line...
1606 */
1607 DeleteARedoRecord(cmd_ptr, 0, 0);
1608 gstWBInfo.cur_cmd = NULL;
1609 }
1610
ProcessRemoteCmd(psz_content_type,psz_buf,buf_sz)1611 void ProcessRemoteCmd(psz_content_type, psz_buf, buf_sz)
1612 char *psz_content_type, *psz_buf;
1613 int buf_sz;
1614 {
1615 struct SelRec *saved_top_sel=topSel, *saved_bot_sel=botSel;
1616 struct CmdRec *cmd_ptr=NULL;
1617 char *psz_plain_buf=NULL;
1618 int highlighted_before=FALSE, plain_buf_sz=0;
1619
1620 if (topSel != NULL) {
1621 highlighted_before = TRUE;
1622 HighLightReverse();
1623 topSel = botSel = NULL;
1624 }
1625 gstWBInfo.cur_cmd = DeserializeCmd(psz_content_type, psz_buf, buf_sz,
1626 &psz_plain_buf, &plain_buf_sz);
1627
1628 if (gstWBInfo.cur_cmd != NULL) {
1629 struct CmdRec *immed_right_cmd=NULL;
1630 int cur_cmd_is_wb_clearall=(gstWBInfo.cur_cmd->type == CMD_WB_CLEARALL);
1631
1632 if (gstWBInfo.cur_cmd->type == CMD_CHAT_A_LINE) {
1633 HandleChatLine(gstWBInfo.cur_cmd);
1634 /*
1635 * May be we need to allocate subcmd pointer here.
1636 */
1637 } else {
1638 if (gstWBInfo.cur_cmd->type == CMD_MOVE) {
1639 gstWBInfo.cur_cmd->subcmd =
1640 (struct SubCmdRec *)malloc(sizeof(struct SubCmdRec));
1641 if (gstWBInfo.cur_cmd->subcmd == NULL) FailAllocMessage();
1642 memset(gstWBInfo.cur_cmd->subcmd, 0, sizeof(struct SubCmdRec));
1643 gstWBInfo.cur_cmd->subcmd->detail.move.dx =
1644 gpDeserializeSubCmd->detail.move.dx;
1645 gstWBInfo.cur_cmd->subcmd->detail.move.dy =
1646 gpDeserializeSubCmd->detail.move.dy;
1647 } else if (gstWBInfo.cur_cmd->type == CMD_WB_SLIDESHOW) {
1648 gstWBInfo.cur_cmd->subcmd =
1649 (struct SubCmdRec *)malloc(sizeof(struct SubCmdRec));
1650 if (gstWBInfo.cur_cmd->subcmd == NULL) FailAllocMessage();
1651 memset(gstWBInfo.cur_cmd->subcmd, 0, sizeof(struct SubCmdRec));
1652 gstWBInfo.cur_cmd->subcmd->detail.slideshow.into_slideshow =
1653 gpDeserializeSubCmd->detail.slideshow.into_slideshow;
1654 }
1655 #ifdef _TGIF_DBG_WB2
1656 DumpCmdStack("Before FindCmdInsertionPoint()");
1657 #endif /* _TGIF_DBG_WB2 */
1658 /*
1659 * FindShadowCmdInsertionPoint() examine the logical clock of the new
1660 * command and decides where to insert it in the shadow cmd list.
1661 */
1662 FindShadowCmdInsertionPoint(gstWBInfo.cur_cmd, &immed_right_cmd);
1663
1664 if (immed_right_cmd == NULL) {
1665 /* append */
1666 CopyAndInsertCmd(TRUE,
1667 (psz_plain_buf==NULL ? psz_buf : psz_plain_buf),
1668 gstWBInfo.last_shadow_cmd, NULL, gstWBInfo.cur_cmd,
1669 &gstWBInfo.first_shadow_cmd, &gstWBInfo.last_shadow_cmd);
1670 } else {
1671 /* insert */
1672 CopyAndInsertCmd(TRUE,
1673 (psz_plain_buf==NULL ? psz_buf : psz_plain_buf),
1674 immed_right_cmd->prev, immed_right_cmd, gstWBInfo.cur_cmd,
1675 &gstWBInfo.first_shadow_cmd, &gstWBInfo.last_shadow_cmd);
1676 }
1677 immed_right_cmd = NULL;
1678 /*
1679 * FindCmdInsertionPoint() examine the logical clock of the new command
1680 * and decides where to insert it.
1681 */
1682 FindCmdInsertionPoint(gstWBInfo.cur_cmd, &immed_right_cmd);
1683
1684 if (immed_right_cmd == NULL) {
1685 /* append */
1686 InsertCmd(gstWBInfo.last_cmd, NULL, gstWBInfo.cur_cmd,
1687 &gstWBInfo.first_cmd, &gstWBInfo.last_cmd);
1688 } else {
1689 /* insert */
1690 InsertCmd(immed_right_cmd->prev, immed_right_cmd, gstWBInfo.cur_cmd,
1691 &gstWBInfo.first_cmd, &gstWBInfo.last_cmd);
1692 }
1693 #ifdef _TGIF_DBG_WB2
1694 DumpCmdStack("After FindCmdInsertionPoint()");
1695 #endif /* _TGIF_DBG_WB2 */
1696 if (immed_right_cmd != NULL) {
1697 /*
1698 * Undo all the commands to the right of gstWBInfo.cur_cmd.
1699 * Do not perform the undo if the command is skipped.
1700 */
1701 for (cmd_ptr=gstWBInfo.last_cmd; cmd_ptr != gstWBInfo.cur_cmd &&
1702 cmd_ptr->type != CMD_WB_CLEARALL; cmd_ptr=cmd_ptr->prev) {
1703 if (cmd_ptr->skipped) {
1704 #ifdef _TGIF_DBG_WB2
1705 strcpy(gszMsgBox, "*** No need to UndoACmd()");
1706 DebugDumpCmd(gszMsgBox, cmd_ptr->type, cmd_ptr->logical_clock,
1707 cmd_ptr->sender_process_id);
1708 #endif /* _TGIF_DBG_WB2 */
1709 cmd_ptr->skipped = FALSE;
1710 } else {
1711 #ifdef _TGIF_DBG_WB2
1712 strcpy(gszMsgBox, "*** Just before UndoACmd()");
1713 DebugDumpCmd(gszMsgBox, cmd_ptr->type, cmd_ptr->logical_clock,
1714 cmd_ptr->sender_process_id);
1715 PrintFullIDsOfObjects("\t");
1716 #endif /* _TGIF_DBG_WB2 */
1717 UndoACmd(cmd_ptr, FALSE, TRUE);
1718 #ifdef _TGIF_DBG_WB2
1719 DebugDumpCmd("*** After UndoACmd()",
1720 cmd_ptr->type, cmd_ptr->logical_clock,
1721 cmd_ptr->sender_process_id);
1722 PrintFullIDsOfObjects("\t");
1723 #endif /* _TGIF_DBG_WB2 */
1724 if (topSel != NULL) RemoveAllSel();
1725 }
1726 }
1727 if (cmd_ptr != gstWBInfo.cur_cmd) {
1728 gstWBInfo.cur_cmd = cmd_ptr;
1729 }
1730 }
1731 /*
1732 * Redo all the commands starting from gstWBInfo.cur_cmd.
1733 */
1734 if (gstWBInfo.cur_cmd->type == CMD_WB_CLEARALL) {
1735 CleanUpObsoletedWBCmds(gstWBInfo.cur_cmd);
1736 if (cur_cmd_is_wb_clearall) {
1737 struct ClearAllSubCmdRec *clearall=
1738 &gpDeserializeSubCmd->detail.clearall;
1739
1740 CleanUpDrawingWindow();
1741 ClearFileInfo(TRUE);
1742 SetFileModified(FALSE);
1743 ClearAndRedrawDrawWindow();
1744 CheckFileAttrsInLoad();
1745 Msg("WhiteBoard cleared by peer.");
1746 DelAllPages();
1747 lastPageNum = 1;
1748 InitPage();
1749 ShowPage();
1750 if (!(pageStyle == clearall->page_style &&
1751 fabs(printMag-clearall->print_mag) < INT_TOL)) {
1752 pageStyle = clearall->page_style;
1753 printMag = clearall->print_mag;
1754 UpdPageStyle(pageStyle);
1755
1756 UpdDrawWinWH();
1757 RedrawScrollBars();
1758 UpdDrawWinBBox();
1759
1760 SetDefaultDrawWinClipRecs();
1761
1762 DrawPaperBoundary(drawWindow);
1763 RedrawGridLines(drawWindow);
1764 RedrawPageLines(drawWindow);
1765 RedrawRulers();
1766 RedrawChoiceWindow();
1767
1768 RedrawTitleWindow();
1769 }
1770 }
1771 }
1772 for (cmd_ptr=gstWBInfo.cur_cmd; cmd_ptr != NULL;
1773 cmd_ptr=cmd_ptr->next) {
1774 #ifdef _TGIF_DBG_WB2
1775 DebugDumpCmd("--- Just before RedoACmd()",
1776 cmd_ptr->type, cmd_ptr->logical_clock,
1777 cmd_ptr->sender_process_id);
1778 PrintFullIDsOfObjects("\t");
1779 #endif /* _TGIF_DBG_WB2 */
1780 if (!RedoACmd(cmd_ptr, FALSE, TRUE)) {
1781 cmd_ptr->skipped = TRUE;
1782 #ifdef _TGIF_DBG_WB2
1783 DebugDumpCmd("=== Skip RedoACmd()",
1784 cmd_ptr->type, cmd_ptr->logical_clock,
1785 cmd_ptr->sender_process_id);
1786 PrintFullIDsOfObjects("\t");
1787 #endif /* _TGIF_DBG_WB2 */
1788 } else {
1789 #ifdef NOT_DEFINED
1790 /* insanity check! */
1791 fprintf(stderr, "Sanity check: %s\n",
1792 "need to comment this before distributing the code!");
1793 if (topSel != NULL) RemoveAllSel();
1794 UndoACmd(cmd_ptr, FALSE, TRUE);
1795 if (topSel != NULL) RemoveAllSel();
1796 if (!RedoACmd(cmd_ptr, FALSE, TRUE)) {
1797 fprintf(stderr, "\7\7\7Oh no!!! RedoACmd() failed!\n");
1798 }
1799 #endif /* NOT_DEFINED */
1800 #ifdef _TGIF_DBG_WB2
1801 DebugDumpCmd("--- Just after RedoACmd()",
1802 cmd_ptr->type, cmd_ptr->logical_clock,
1803 cmd_ptr->sender_process_id);
1804 PrintFullIDsOfObjects("\t");
1805 #endif /* _TGIF_DBG_WB2 */
1806 if (topSel != NULL) RemoveAllSel();
1807 }
1808 }
1809 #ifdef _TGIF_DBG_WB2
1810 PrintFullIDsOfObjects("At end of ProcessRemoteCmd()");
1811 fprintf(stderr, "%s%s\n",
1812 "========================================",
1813 "========================================");
1814 #endif /* _TGIF_DBG_WB2 */
1815 }
1816 }
1817 DeserializationCleanUp();
1818 ResetDeserializeCmd();
1819
1820 topSel = saved_top_sel;
1821 botSel = saved_bot_sel;
1822 UpdSelBBox();
1823 if (highlighted_before) {
1824 HighLightExistingObjects();
1825 }
1826 UtilFree(psz_plain_buf);
1827 }
1828
1829 /* =================== Pack and Unpack current state Functions ======= */
1830
1831 static
PackCurrentTGWBState(p_cur_state)1832 void PackCurrentTGWBState(p_cur_state)
1833 CurStatus *p_cur_state;
1834 {
1835 char tmp_fname[MAXPATHLENGTH], *buf=NULL, header[MAXSTRING<<1];
1836 char gz_tmp_fname[MAXPATHLENGTH];
1837 int content_sz=0, ok=TRUE, header_sz=0, num_cmds=0, cur_cmd_pos=0;
1838 int do_deflate=TRUE;
1839 struct CmdRec *cmd_ptr=NULL;
1840 long loc_sec=0L, loc_msec=0L;
1841 FILE *fp=NULL, *gz_fp=NULL;
1842
1843 if (HasZlibSupport()) {
1844 #ifdef _TGIF_DBG_WB2
1845 do_deflate = FALSE;
1846 #endif /* _TGIF_DBG_WB2 */
1847 } else {
1848 do_deflate = FALSE;
1849 }
1850 memset(p_cur_state, 0, sizeof(CurStatus));
1851 if (MkTempFile(tmp_fname, sizeof(tmp_fname), tmpDir, TOOL_NAME) == NULL) {
1852 fprintf(stderr, TgLoadString(STID_CANT_CREATE_NAMED_TMP_FILE), tmp_fname);
1853 fprintf(stderr, "\n");
1854 return;
1855 }
1856 snprintf(gz_tmp_fname, sizeof(gz_tmp_fname), "%s.z", tmp_fname);
1857
1858 if ((fp=fopen(tmp_fname, "w+")) == NULL) {
1859 FailToOpenMessage(tmp_fname, "w", NULL);
1860 return;
1861 }
1862 if ((gz_fp=fopen(gz_tmp_fname, "w+")) == NULL) {
1863 FailToOpenMessage(gz_tmp_fname, "w", NULL);
1864 fclose(fp);
1865 unlink(tmp_fname);
1866 return;
1867 }
1868 writeFileFailed = FALSE;
1869
1870 UtilGetMilliSecTime(&loc_sec, &loc_msec);
1871 if (fprintf(fp, "%%TGWB begin packing - %ld.%ld\n", loc_sec, loc_msec) ==
1872 EOF) {
1873 writeFileFailed = TRUE;
1874 }
1875 for (cmd_ptr=gstWBInfo.first_shadow_cmd; cmd_ptr != NULL;
1876 cmd_ptr=cmd_ptr->next) {
1877 SerializationInfo si;
1878
1879 memset(&si, 0, sizeof(SerializationInfo));
1880 PrepareExtendedSerializationInfo(cmd_ptr, &si);
1881 if (SaveExtendedCmd(fp, cmd_ptr, &si)) {
1882 if (cmd_ptr == gstWBInfo.cur_cmd) {
1883 cur_cmd_pos = num_cmds;
1884 }
1885 num_cmds++;
1886 }
1887 }
1888 ok = SaveExtendedCmdInfo(fp, num_cmds, cur_cmd_pos);
1889
1890 if (fprintf(fp, "%%TGWB end - %ld.%ld\n", loc_sec, loc_msec) == EOF) {
1891 writeFileFailed = TRUE;
1892 }
1893 if (writeFileFailed) {
1894 FailToWriteFileMessage(tmp_fname);
1895 fclose(fp);
1896 unlink(tmp_fname);
1897 fclose(gz_fp);
1898 unlink(gz_tmp_fname);
1899 return;
1900 }
1901 if (!ok) {
1902 fclose(fp);
1903 unlink(tmp_fname);
1904 fclose(gz_fp);
1905 unlink(gz_tmp_fname);
1906 return;
1907 }
1908 fflush(fp);
1909 content_sz = (int)ftell(fp);
1910 /*
1911 * From: <PID>:<IP>\r\n
1912 * Content-Type: application/x-tgif-cmd\r\n
1913 * Content-Length: <LENGTH>\r\n
1914 * \r\n
1915 * <DATA of size LENGTH>
1916 */
1917 if (do_deflate && HasZlibSupport()) {
1918 int rc=0;
1919
1920 if (!DoDeflate(fp, NULL, content_sz, gz_fp, TRUE, TRUE, &rc)) {
1921 ZlibError(rc, TRUE);
1922 do_deflate = FALSE;
1923 } else {
1924 content_sz = (int)ftell(gz_fp);
1925 }
1926 }
1927 if (do_deflate) {
1928 sprintf(header, "%s%s\r\n%s%s\r\n%s%1d\r\n\r\n",
1929 "From: ", gszLocalPID,
1930 "Content-Type: ", "application/x-tgif-cmd-z",
1931 "Content-Length: ", content_sz);
1932 header_sz = strlen(header);
1933 buf = (char*)malloc((header_sz+content_sz+1)*sizeof(char));
1934 if (buf == NULL) FailAllocMessage();
1935 strcpy(buf, header);
1936 rewind(gz_fp);
1937 if (fread(&buf[header_sz], sizeof(char), content_sz, gz_fp) !=
1938 content_sz) {
1939 sprintf(gszMsgBox,
1940 "Error in reading '%s'.\n\nPackCurrentTGWBState() aborted.",
1941 gz_tmp_fname);
1942 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1943
1944 UtilFree(buf);
1945 fclose(fp);
1946 unlink(tmp_fname);
1947 fclose(gz_fp);
1948 unlink(gz_tmp_fname);
1949 return;
1950 }
1951 } else {
1952 sprintf(header, "%s%s\r\n%s%s\r\n%s%1d\r\n\r\n",
1953 "From: ", gszLocalPID,
1954 "Content-Type: ", "application/x-tgif-cmd",
1955 "Content-Length: ", content_sz);
1956 header_sz = strlen(header);
1957 buf = (char*)malloc((header_sz+content_sz+1)*sizeof(char));
1958 if (buf == NULL) FailAllocMessage();
1959 strcpy(buf, header);
1960 rewind(fp);
1961 if (fread(&buf[header_sz], sizeof(char), content_sz, fp) !=
1962 content_sz) {
1963 sprintf(gszMsgBox,
1964 "Error in reading '%s'.\n\nPackCurrentTGWBState() aborted.",
1965 tmp_fname);
1966 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1967
1968 UtilFree(buf);
1969 fclose(fp);
1970 unlink(tmp_fname);
1971 fclose(gz_fp);
1972 unlink(gz_tmp_fname);
1973 return;
1974 }
1975 }
1976 buf[header_sz+content_sz] = '\0';
1977 #ifdef _TGIF_DBG_WB2
1978 if (wb2DebugLevel == 0) {
1979 fprintf(stderr, "Sending %1d bytes, pid = %ld!\n",
1980 header_sz+content_sz+2, gstWBInfo.pid);
1981 } else {
1982 fprintf(stderr, "---------------------------\n");
1983 if (do_deflate) {
1984 fprintf(stderr, "%s", header);
1985 fprintf(stderr, "[content not displayed] ...\n");
1986 } else {
1987 fprintf(stderr, "%s\n", buf);
1988 }
1989 fprintf(stderr, "---------------------------\n");
1990 fprintf(stderr, "Sent %1d bytes, pid = %ld!\n", header_sz+content_sz+2,
1991 gstWBInfo.pid);
1992 }
1993 DebugDumpCmd(">>> In PackCurrentTGWBState()",
1994 (-1), (-1), gszLocalPID);
1995 PrintFullIDsOfObjects("In PackCurrentTGWBState()");
1996 #endif /* _TGIF_DBG_WB2 */
1997 fclose(fp);
1998 unlink(tmp_fname);
1999 fclose(gz_fp);
2000 unlink(gz_tmp_fname);
2001
2002 /* It is important to include the terminating '\0' */
2003 p_cur_state->data = buf;
2004 p_cur_state->size = header_sz+content_sz+1;
2005 }
2006
2007 static
CheckUnpackState(read_status)2008 int CheckUnpackState(read_status)
2009 int read_status;
2010 {
2011 int ok=TRUE;
2012
2013 if (read_status == INVALID) {
2014 sprintf(gszMsgBox, "File version too large (=%1d). %s!",
2015 fileVersion, "UnpackCurrentTGWBState() aborted");
2016 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2017 ok = FALSE;
2018 } else {
2019 #ifdef _TGIF_DBG_WB2
2020 fprintf(stderr, "%s, pid = %ld, timestamp = %1d/%s\n",
2021 "Command successfully parsed", gstWBInfo.pid, recordCmdLogicalClock,
2022 recordCmdSenderProcID);
2023 #endif /* _TGIF_DBG_WB2 */
2024 if (recordCmdLogicalClock+1 > gstWBInfo.logical_clock) {
2025 /* Lamport's Algorithm set logical_clock */
2026 gstWBInfo.logical_clock = recordCmdLogicalClock+1;
2027 #ifdef _TGIF_DBG_WB2
2028 fprintf(stderr, "Logical clock for pid = %ld set to %1d.\n",
2029 gstWBInfo.pid, gstWBInfo.logical_clock);
2030 #endif /* _TGIF_DBG_WB2 */
2031 }
2032 }
2033 return ok;
2034 }
2035
2036 static
CreateCmdFromSerializedData(saved_top_obj,saved_bot_obj)2037 struct CmdRec *CreateCmdFromSerializedData(saved_top_obj, saved_bot_obj)
2038 struct ObjRec *saved_top_obj, *saved_bot_obj;
2039 {
2040 struct CmdRec *cmd_ptr=(struct CmdRec *)malloc(sizeof(struct CmdRec));
2041
2042 if (cmd_ptr == NULL) FailAllocMessage();
2043 memset(cmd_ptr, 0, sizeof(struct CmdRec));
2044 cmd_ptr->serialized = TRUE; /* created from deserialization */
2045 cmd_ptr->top_before = cmd_ptr->bot_before = NULL;
2046 cmd_ptr->pos_before = (int*)gppszBeforeImage;
2047 cmd_ptr->count_before = gnBeforeImageCount;
2048 cmd_ptr->type = gstDeserializeCmd.type;
2049 cmd_ptr->undone = TRUE;
2050 cmd_ptr->include_tgif_obj = recordCmdIncludeTgifObj;
2051 cmd_ptr->new_colormap = recordCmdUsesNewColormap;
2052 cmd_ptr->logical_clock = recordCmdLogicalClock;
2053 if (*recordCmdSenderProcID != '\0') {
2054 cmd_ptr->sender_process_id = UtilStrDup(recordCmdSenderProcID);
2055 if (cmd_ptr->sender_process_id == NULL) FailAllocMessage();
2056 } else {
2057 fprintf(stderr,
2058 "Missing sender_process_id in CreateCmdFromSerializedData().\n");
2059 }
2060 cmd_ptr->first_redo_after_deserialize = TRUE;
2061 cmd_ptr->skipped = FALSE;
2062 #ifdef _TGIF_DBG_WB2
2063 DebugDumpCmd("<<< In CreateCmdFromSerializedData()", cmd_ptr->type,
2064 cmd_ptr->logical_clock, cmd_ptr->sender_process_id);
2065 #endif /* _TGIF_DBG_WB2 */
2066 if (saved_top_obj != NULL) {
2067 SelectObjects(saved_top_obj, saved_bot_obj);
2068 CopySel(topSel, numObjSelected,
2069 &(cmd_ptr->top_after), &(cmd_ptr->bot_after));
2070 cmd_ptr->pos_after = gpnAfterPositions;
2071 cmd_ptr->count_after = gnAfterPositionsCount;
2072 RemoveAllSel();
2073 } else {
2074 cmd_ptr->top_after = cmd_ptr->bot_after = NULL;
2075 cmd_ptr->pos_after = NULL;
2076 cmd_ptr->count_after = 0;
2077 }
2078 gppszBeforeImage = NULL;
2079 gnBeforeImageCount = 0;
2080 gpnAfterPositions = NULL;
2081 gnAfterPositionsCount = 0;
2082
2083 return cmd_ptr;
2084 }
2085
2086 static
GetContentInfoFromBuf(buf,content_type_buf,content_type_buf_sz,pn_content_length,ppsz_buf_data_start)2087 int GetContentInfoFromBuf(buf, content_type_buf, content_type_buf_sz,
2088 pn_content_length, ppsz_buf_data_start)
2089 char *buf, *content_type_buf, **ppsz_buf_data_start;
2090 int content_type_buf_sz, *pn_content_length;
2091 {
2092 char *psz_start=buf, *psz=NULL;
2093 char *content_type_prefix="Content-Type: ";
2094 char *content_len_prefix="Content-Length: ";
2095 int content_type_prefix_len=strlen(content_type_prefix);
2096 int content_len_prefix_len=strlen(content_len_prefix);
2097 int found_content_type=FALSE, found_content_len=FALSE;
2098
2099 psz = strstr(psz_start, "\r\n");
2100 while (psz != NULL) {
2101 *psz = '\0';
2102 if (*psz_start == '\0') {
2103 *psz = '\r';
2104 psz_start = &psz[2];
2105 if (ppsz_buf_data_start != NULL) *ppsz_buf_data_start = psz_start;
2106 return (found_content_type && found_content_len);
2107 } else if (UtilStrNCaseCmp(psz_start, content_type_prefix,
2108 content_type_prefix_len) == 0) {
2109 UtilStrCpyN(content_type_buf, content_type_buf_sz,
2110 &psz_start[content_type_prefix_len]);
2111 UtilTrimBlanks(content_type_buf);
2112 found_content_type = TRUE;
2113 } else if (UtilStrNCaseCmp(psz_start, content_len_prefix,
2114 content_len_prefix_len) == 0) {
2115 char buf2[80];
2116 int ival=0;
2117
2118 UtilStrCpyN(buf2, sizeof(buf2),
2119 &psz_start[content_len_prefix_len]);
2120 UtilTrimBlanks(buf2);
2121 if (sscanf(buf2, "%d", &ival) == 1) {
2122 if (pn_content_length != NULL) *pn_content_length = ival;
2123 found_content_len = TRUE;
2124 }
2125 }
2126 *psz = '\r';
2127 psz_start = &psz[2];
2128 psz = strstr(psz_start, "\r\n");
2129 }
2130 return FALSE;
2131 }
2132
2133 static
ReadPastWrapper(fp,pn_file_pos)2134 int ReadPastWrapper(fp, pn_file_pos)
2135 FILE *fp;
2136 int *pn_file_pos;
2137 {
2138 char *buf=NULL;
2139 char *psz_looking_for="%TGWB begin packing - ";
2140 int len=strlen(psz_looking_for);
2141
2142 while ((buf=UtilGetALine(fp)) != NULL) {
2143 if (strncmp(buf, psz_looking_for, len) == 0) {
2144 if (pn_file_pos != NULL) *pn_file_pos = (int)ftell(fp);
2145 UtilFree(buf);
2146 return TRUE;
2147 }
2148 UtilFree(buf);
2149 }
2150 return FALSE;
2151 }
2152
2153 static
ReadPastHeader(fp,pn_file_pos)2154 int ReadPastHeader(fp, pn_file_pos)
2155 FILE *fp;
2156 int *pn_file_pos;
2157 /*
2158 * The From, Content-Type, Content-Length header is optional. So,
2159 * need to handle the case where there is a header and the case
2160 * where there is none.
2161 */
2162 {
2163 char *psz_looking_for="%TGWB begin - ";
2164 int len=strlen(psz_looking_for);
2165 int cur_pos=(int)ftell(fp);
2166 char *buf=NULL;
2167
2168 while ((buf=UtilGetALine(fp)) != NULL) {
2169 char obj_name[80];
2170
2171 *obj_name = '\0';
2172 UtilTrimBlanks(buf);
2173 if (*buf == '\0') {
2174 if (pn_file_pos != NULL) *pn_file_pos = (int)ftell(fp);
2175 UtilFree(buf);
2176 return TRUE;
2177 } else if (strncmp(buf, psz_looking_for, len) == 0) {
2178 if (pn_file_pos != NULL) *pn_file_pos = cur_pos;
2179 UtilFree(buf);
2180 return TRUE;
2181 } else if (*buf == ']' || *buf == '%') {
2182 fprintf(stderr,
2183 "Unexpected line (start with '%c' read in ReadPastHeader().\n",
2184 *buf);
2185 UtilFree(buf);
2186 return FALSE;
2187 } else if (ParseStr(buf, (int)'(', obj_name, sizeof(obj_name)) == NULL) {
2188 /* it's probably okay */
2189 } else if (strcmp(obj_name, "cmdxinfo") == 0) {
2190 int ok=ReadExtendedCmdInfo(fp, buf);
2191
2192 UtilFree(buf);
2193 return ok;
2194 }
2195 UtilFree(buf);
2196 cur_pos = (int)ftell(fp);
2197 }
2198 return FALSE;
2199 }
2200
2201 static
ReadAheadOverACmd(fp,pn_file_pos)2202 int ReadAheadOverACmd(fp, pn_file_pos)
2203 FILE *fp;
2204 int *pn_file_pos;
2205 {
2206 char *buf=NULL;
2207 char *psz_looking_for="%TGWB end - ";
2208 int len=strlen(psz_looking_for);
2209
2210 while ((buf=UtilGetALine(fp)) != NULL) {
2211 if (strncmp(buf, psz_looking_for, len) == 0) {
2212 if (pn_file_pos != NULL) *pn_file_pos = (int)ftell(fp);
2213 UtilFree(buf);
2214 return TRUE;
2215 }
2216 UtilFree(buf);
2217 }
2218 return FALSE;
2219 }
2220
2221 static
ReReadCmd(fp,start_file_pos,end_file_pos,pn_buf_len)2222 char *ReReadCmd(fp, start_file_pos, end_file_pos, pn_buf_len)
2223 FILE *fp;
2224 int start_file_pos, end_file_pos, *pn_buf_len;
2225 {
2226 char *buf=NULL;
2227 int ok=TRUE, buf_len=end_file_pos-start_file_pos;
2228
2229 if (end_file_pos > start_file_pos) {
2230 buf_len = end_file_pos-start_file_pos;
2231
2232 if (fseek(fp, start_file_pos, SEEK_SET) != 0) {
2233 fprintf(stderr,
2234 "Seek to %1d failed in UnpackCurrentTGWBState().\n",
2235 start_file_pos);
2236 ok = FALSE;
2237 } else {
2238 buf = (char*)malloc(buf_len+1);
2239 if (buf == NULL) FailAllocMessage();
2240 buf[buf_len] = '\0';
2241 if (buf_len != (int)fread(buf,
2242 sizeof(char), buf_len, fp)) {
2243 fprintf(stderr,
2244 "Reading %1d bytes failed in %s.\n",
2245 buf_len, "UnpackCurrentTGWBState()");
2246 ok = FALSE;
2247 }
2248 }
2249 if (ok && fseek(fp, start_file_pos, SEEK_SET) != 0) {
2250 fprintf(stderr,
2251 "Seek to %1d failed in UnpackCurrentTGWBState().\n",
2252 start_file_pos);
2253 ok = FALSE;
2254 }
2255 } else {
2256 fprintf(stderr,
2257 "Invalid (empty) cmd detected in UnpackCurrentTGWBState().\n");
2258 ok = FALSE;
2259 }
2260 if (!ok) {
2261 UtilFree(buf);
2262
2263 return NULL;
2264 }
2265 if (pn_buf_len != NULL) *pn_buf_len = buf_len;
2266
2267 return buf;
2268 }
2269
2270 static
UnpackCurrentTGWBState(p_cur_state)2271 void UnpackCurrentTGWBState(p_cur_state)
2272 CurStatus *p_cur_state;
2273 {
2274 struct StkRec *stk_ptr=NULL;
2275 struct ObjRec *obj_ptr=NULL, *saved_top_obj=NULL, *saved_bot_obj=NULL;
2276 int read_status=TRUE, ok=TRUE, start_file_pos=0, end_file_pos=0;
2277 int content_length=0, do_inflate=FALSE, need_to_free_buf=FALSE;
2278 char *buf=p_cur_state->data, tmp_fname[MAXPATHLENGTH], content_type[80];
2279 char *buf_data_start=NULL;
2280 FILE *fp=NULL;
2281 struct CmdRec *cmd_ptr=NULL;
2282
2283 *content_type = '\0';
2284 if (!GetContentInfoFromBuf(buf, content_type, sizeof(content_type),
2285 &content_length, &buf_data_start)) {
2286 sprintf(gszMsgBox, TgLoadString(STID_JOIN_WB_IN_FAILED_NO_CONTTYPE));
2287 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2288 return;
2289 }
2290 if (strcmp(content_type, "application/x-tgif-cmd-z") == 0) {
2291 if (!HasZlibSupport()) {
2292 sprintf(gszMsgBox, "%s %s.\n\nDeserialization aborted in %s.",
2293 TOOL_NAME, "is not compiled with ZLIB and cannot inflate()",
2294 "UnpackCurrentTGWBState()");
2295 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2296 return;
2297 } else {
2298 if (gstWBInfo.gz_listen_fp == NULL) {
2299 sprintf(gszMsgBox, "Cannot open '%s'.\n\n%s pid=%ld in %s.",
2300 gstWBInfo.gz_listen_fname, "Deserialization aborted for",
2301 gstWBInfo.pid, "UnpackCurrentTGWBState()");
2302 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2303 return;
2304 }
2305 do_inflate = TRUE;
2306 }
2307 }
2308 if (do_inflate && HasZlibSupport()) {
2309 int rc=0, buf_sz=0;
2310
2311 if (!DoInflate(buf_data_start, content_length, gstWBInfo.gz_listen_fp,
2312 TRUE, &rc)) {
2313 ZlibError(rc, FALSE);
2314 return;
2315 }
2316 buf_sz = (int)ftell(gstWBInfo.gz_listen_fp);
2317 buf = (char*)malloc(buf_sz+1);
2318 if (buf == NULL) FailAllocMessage();
2319 rewind(gstWBInfo.gz_listen_fp);
2320 if (fread(buf, sizeof(char), buf_sz, gstWBInfo.gz_listen_fp) !=
2321 buf_sz) {
2322 sprintf(gszMsgBox, "Cannot read %1d bytes from '%s'.\n\n%s for %s.",
2323 buf_sz, gstWBInfo.gz_listen_fname, "Deserialization aborted",
2324 "UnpackCurrentTGWBState()");
2325 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2326 UtilFree(buf);
2327 return;
2328 }
2329 need_to_free_buf = TRUE;
2330 }
2331 if (MkTempFile(tmp_fname, sizeof(tmp_fname), tmpDir, TOOL_NAME) == NULL) {
2332 fprintf(stderr, TgLoadString(STID_CANT_CREATE_NAMED_TMP_FILE), tmp_fname);
2333 fprintf(stderr, "\n");
2334 if (need_to_free_buf) UtilFree(buf);
2335 return;
2336 }
2337 if ((fp=fopen(tmp_fname, "w+")) == NULL) {
2338 FailToOpenMessage(tmp_fname, "w", NULL);
2339 if (need_to_free_buf) UtilFree(buf);
2340 return;
2341 }
2342 writeFileFailed = FALSE;
2343
2344 #ifdef _TGIF_DBG_WB2
2345 if (wb2DebugLevel == 0) {
2346 fprintf(stderr, "Received %1d bytes, pid = %ld\n", strlen(buf),
2347 gstWBInfo.pid);
2348 } else {
2349 fprintf(stderr, "<<<========================\n");
2350 fprintf(stderr, "%s\n", buf);
2351 fprintf(stderr, "<<<========================\n");
2352 fprintf(stderr, "Received %1d bytes, pid = %ld\n", strlen(buf),
2353 gstWBInfo.pid);
2354 }
2355 PrintFullIDsOfObjects("At the beginning of UnpackCurrentTGWBState()");
2356 #endif /* _TGIF_DBG_WB2 */
2357
2358 writeFileFailed = FALSE;
2359 if (fprintf(fp, "%s", buf) == EOF) {
2360 writeFileFailed = TRUE;
2361 }
2362 if (writeFileFailed) {
2363 FailToWriteFileMessage(gstWBInfo.listen_fname);
2364 fclose(fp);
2365 unlink(tmp_fname);
2366 if (need_to_free_buf) UtilFree(buf);
2367 return;
2368 }
2369 stk_ptr = SaveFileInfo();
2370 ResetFileInfo();
2371 /* if (usePaperSizeStoredInFile) ResetOnePageSize(); */
2372
2373 ResetDeserializeCmd();
2374
2375 rewind(fp);
2376 importingFile = TRUE;
2377
2378 strcpy(scanFileName, gstWBInfo.listen_fname);
2379 scanLineNum = 0;
2380 foundGoodStateObject = FALSE;
2381
2382 seenCmdXInfo = FALSE;
2383 *content_type = '\0';
2384 ok = ReadPastWrapper(fp, NULL);
2385 while (ok && !seenCmdXInfo) {
2386 char *serialization_buf=NULL;
2387 int serialization_buf_len=0;
2388
2389 DelAllPages();
2390 lastPageNum = 1;
2391 InitPage();
2392 readingPageNum = loadedCurPageNum = 0;
2393
2394 ok = ReadPastHeader(fp, &start_file_pos);
2395 if (ok) {
2396 if (seenCmdXInfo) {
2397 break;
2398 }
2399 ok = ReadAheadOverACmd(fp, &end_file_pos);
2400 if (ok) {
2401 serialization_buf = ReReadCmd(fp, start_file_pos, end_file_pos,
2402 &serialization_buf_len);
2403 if (serialization_buf == NULL) {
2404 ok = FALSE;
2405 #ifdef _TGIF_DBG_WB2
2406 } else {
2407 static int n=1;
2408
2409 fprintf(stderr, "******* cmd %1d begin *******\n", n);
2410 fprintf(stderr, "%s", serialization_buf);
2411 fprintf(stderr, "******* cmd %1d end *******\n", n++);
2412 #endif /* _TGIF_DBG_WB2 */
2413 }
2414 }
2415 }
2416 if (ok) {
2417 while ((read_status=ReadObj(fp, &obj_ptr)) == TRUE) {
2418 if (obj_ptr != NULL) {
2419 fprintf(stderr,
2420 "Unexpected objects read in UnpackCurrentTGWBState().\n");
2421 }
2422 }
2423 ok = CheckUnpackState(read_status);
2424 if (!ok) {
2425 DelAllObj();
2426 } else {
2427 saved_top_obj = topObj;
2428 saved_bot_obj = botObj;
2429 topObj = botObj = NULL;
2430 }
2431 DelAllPages();
2432 lastPageNum = 0;
2433 InitPage();
2434 }
2435 if (ok) {
2436 cmd_ptr = CreateCmdFromSerializedData(saved_top_obj, saved_bot_obj);
2437 if (cmd_ptr->type == CMD_MOVE) {
2438 cmd_ptr->subcmd =
2439 (struct SubCmdRec *)malloc(sizeof(struct SubCmdRec));
2440 if (cmd_ptr->subcmd == NULL) FailAllocMessage();
2441 memset(cmd_ptr->subcmd, 0, sizeof(struct SubCmdRec));
2442 cmd_ptr->subcmd->detail.move.dx =
2443 gpDeserializeSubCmd->detail.move.dx;
2444 cmd_ptr->subcmd->detail.move.dy =
2445 gpDeserializeSubCmd->detail.move.dy;
2446 } else if (cmd_ptr->type == CMD_WB_SLIDESHOW) {
2447 cmd_ptr->subcmd =
2448 (struct SubCmdRec *)malloc(sizeof(struct SubCmdRec));
2449 if (cmd_ptr->subcmd == NULL) FailAllocMessage();
2450 memset(cmd_ptr->subcmd, 0, sizeof(struct SubCmdRec));
2451 cmd_ptr->subcmd->detail.slideshow.into_slideshow =
2452 gpDeserializeSubCmd->detail.slideshow.into_slideshow;
2453 }
2454 if (cmd_ptr != NULL) {
2455 /* append */
2456 CopyAndInsertCmd(TRUE, serialization_buf, gstWBInfo.last_shadow_cmd,
2457 NULL, cmd_ptr, &gstWBInfo.first_shadow_cmd,
2458 &gstWBInfo.last_shadow_cmd);
2459 InsertCmd(gstWBInfo.last_cmd, NULL, cmd_ptr, &gstWBInfo.first_cmd,
2460 &gstWBInfo.last_cmd);
2461 }
2462 }
2463 #ifdef _TGIF_DBG_WB2
2464 PrintFullIDsOfObjects("In UnpackCurrentTGWBState()");
2465 #endif /* _TGIF_DBG_WB2 */
2466 DeserializationCleanUp();
2467 ResetDeserializeCmd();
2468 }
2469 importingFile = FALSE;
2470
2471 fclose(fp);
2472 unlink(tmp_fname);
2473
2474 RestoreFileInfo(stk_ptr);
2475 ResetOnePageSize();
2476 free(stk_ptr);
2477
2478 UpdPageStyle(pageStyle);
2479 /*
2480 * Now execute the commands!
2481 */
2482 if (ok) {
2483 gstWBInfo.cur_cmd = NULL;
2484 for (cmd_ptr=gstWBInfo.first_cmd; cmd_ptr != NULL;
2485 cmd_ptr=cmd_ptr->next) {
2486 #ifdef _TGIF_DBG_WB2
2487 DebugDumpCmd("--- Just before RedoACmd()",
2488 cmd_ptr->type, cmd_ptr->logical_clock,
2489 cmd_ptr->sender_process_id);
2490 PrintFullIDsOfObjects("\t");
2491 #endif /* _TGIF_DBG_WB2 */
2492 if (!RedoACmd(cmd_ptr, FALSE, TRUE)) {
2493 cmd_ptr->skipped = TRUE;
2494 #ifdef _TGIF_DBG_WB2
2495 DebugDumpCmd("=== Skip RedoACmd()",
2496 cmd_ptr->type, cmd_ptr->logical_clock,
2497 cmd_ptr->sender_process_id);
2498 PrintFullIDsOfObjects("\t");
2499 #endif /* _TGIF_DBG_WB2 */
2500 gstWBInfo.cur_cmd = cmd_ptr;
2501 break;
2502 } else {
2503 #ifdef _TGIF_DBG_WB2
2504 DebugDumpCmd("--- Just after RedoACmd()",
2505 cmd_ptr->type, cmd_ptr->logical_clock,
2506 cmd_ptr->sender_process_id);
2507 PrintFullIDsOfObjects("\t");
2508 #endif /* _TGIF_DBG_WB2 */
2509 if (topSel != NULL) RemoveAllSel();
2510 }
2511 }
2512 gstWBInfo.join_session_in_progress = TRUE;
2513 } else {
2514 CleanUpWBCmds();
2515 sprintf(gszMsgBox, TgLoadString(STID_JOIN_WB_IN_PROGRESS_FAILED));
2516 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2517 }
2518 if (need_to_free_buf) UtilFree(buf);
2519 }
2520
HandleNewUserRequest()2521 void HandleNewUserRequest()
2522 {
2523 char buf[80];
2524 int buf_sz=sizeof(buf);
2525
2526 /*
2527 * Get current tgwb state and establish
2528 * a TCP conection to send the data.
2529 */
2530 int index=0;
2531
2532 if (!gstWBInfo.do_whiteboard) {
2533 return;
2534 }
2535 for (index=0; index < buf_sz-1; index++) {
2536 if (read(talkToSelfFiledes[0], &buf[index], 1) != 1) {
2537 sprintf(gszMsgBox, TgLoadString(STID_READ_FROM_SELF_PIPE_FAIL), 1,
2538 TOOL_NAME),
2539 fprintf(stderr, "%s\n", gszMsgBox);
2540 index = (-1);
2541 break;
2542 } else if (buf[index] == '\0') {
2543 break;
2544 }
2545 }
2546 if (index == buf_sz-1) {
2547 sprintf(gszMsgBox, TgLoadString(STID_READ_FROM_SELF_PIPE_OVERFLOW),
2548 TOOL_NAME),
2549 fprintf(stderr, "%s\n", gszMsgBox);
2550 index = (-1);
2551 }
2552 if (index != (-1)) {
2553 int conn=0;
2554 CurStatus cur_state;
2555
2556 memset(&cur_state, 0, sizeof(CurStatus));
2557 sscanf(buf, "%d", &conn);
2558 serializingFile = TRUE;
2559 PackCurrentTGWBState(&cur_state);
2560 serializingFile = FALSE;
2561 if (cur_state.size != 0) {
2562 RM_sendCurStatus(conn, (char*)cur_state.data, cur_state.size);
2563 UtilFree(cur_state.data);
2564 }
2565 }
2566 }
2567
2568 /* =================== SIGPOLL Handler function =================== */
2569
2570 /* #define DEBUG0 */
2571
2572 #if (defined(PTHREAD) || defined(HAVE_LIBPTHREAD))
2573 static
ReceivePacket(void * arg)2574 void *ReceivePacket( void *arg )
2575 {
2576 while( 1 )
2577 {
2578 char *buf=NULL, *aux=NULL, id[300];
2579 int byread=0;
2580 struct SegmentationPack pack1;
2581
2582 if( (byread = RM_recv(gstWBInfo.MCastSock, (char*) &pack1, sizeof(struct SegmentationPack))) > 0 )
2583 {
2584 char *buffer1=NULL;
2585
2586 #ifdef DEBUG0
2587 fprintf(stdout, "__________# of received packet: %u of %u\n", ntohl(pack1.NumSeq), ntohl(pack1.NumPackets));
2588 #endif
2589 if( (buffer1 = DeSegment( pack1, &byread )) != NULL ){
2590 buf = (char *)malloc( byread + 1 );
2591 memcpy( buf, buffer1, byread );
2592 buf[byread]= '\0';
2593 free(buffer1);
2594 #ifdef DEBUG0
2595 fprintf(stdout, "******Desegmentation OK\n");
2596 #endif
2597 }
2598 else
2599 {
2600 continue;
2601 }
2602 } else if (byread == 0)
2603 {
2604 continue;
2605 }
2606 else {
2607 /* on error, break - no more messages to receive (shutting down) */
2608 break;
2609 }
2610
2611 /*
2612 * check if the message is from itself
2613 */
2614
2615
2616 if (strncmp(buf, "From: ", 6) != 0 || sscanf(&buf[6], "%s\r\n", id) != 1) {
2617 fprintf(stderr, "%s. %s, pid = %ld=tid=%s.\nbuf=%s.\n",
2618 "Fatal error", "Cannot find the sender id in IO_SignalHandler()",
2619 gstWBInfo.pid, id, buf);
2620 free(buf);
2621 continue;
2622 }
2623
2624 if(strcmp(id, gszLocalPID) == 0) {
2625 continue;
2626 }
2627
2628 #ifdef DEBUG0
2629 /* Verify if either the command may be processed right now, or if it should be stored */
2630 fprintf(stderr,"Process the comand now? ");
2631 #endif
2632
2633 if ((aux = (char *)malloc( byread + 1 )) == NULL)
2634 {
2635 fprintf(stderr,"Allocation error. (ReceivePacket)\n");
2636 exit(1);
2637 }
2638 strncpy(aux, buf, byread);
2639 aux[byread] = (char)0;
2640 buff_ins(gstWBInfo.bd_commands, aux);
2641 free(aux);
2642 free(buf);
2643
2644 /*
2645 * Don't think we need this any more!
2646 *
2647 * if(gstWBInfo.BlockRemoteCmdDepth > 0) {
2648
2649 #ifdef DEBUG
2650 * buff_show(gstWBInfo.bd_commands);
2651 #endif
2652 * continue;
2653 * }
2654 * else
2655 */
2656 {
2657 static char c='a';
2658
2659 if (write(talkToSelfFiledes[1], &c, 1) != 1) {
2660 sprintf(gszMsgBox, TgLoadString(STID_WRITE_TO_SELF_PIPE_FAIL),
2661 TOOL_NAME);
2662 fprintf(stderr, "%s\n", gszMsgBox);
2663 }
2664 }
2665 }
2666 return( NULL );
2667 }
2668 #endif /* (defined(PTHREAD) || defined(HAVE_LIBPTHREAD)) */
2669
2670 /* =================== Init and CleanUp Functions =================== */
2671
CleanUpWhiteBoard()2672 void CleanUpWhiteBoard()
2673 {
2674 int i=0;
2675
2676 if (!gstWBInfo.do_whiteboard) {
2677 return;
2678 }
2679 snprintf(gszMsgBox, sizeof(gszMsgBox), "****%s**** ",
2680 TgLoadString(STID_SHUTTING_DOWN_WHITEBOARD));
2681 Msg(gszMsgBox);
2682
2683 RM_leaveGroup( gstWBInfo.MCastSock, (char*)RM_USE_CURRENT_CONFIG );
2684 fprintf(stderr, "%s ", gszMsgBox);
2685 for (i=0; i < 10; i++) {
2686 fprintf(stderr, ".");
2687 MillisecondSleep(100);
2688 }
2689 fprintf(stderr, "\n");
2690 RMCastCleanUp();
2691 buff_destroy(gstWBInfo.bd_commands);
2692
2693 CleanUpWBSockets();
2694 CleanUpWBCmds();
2695 memset(&gstWBInfo, 0, sizeof(struct WhiteBoardRec));
2696
2697 CleanUpDeserializeCmd();
2698 buff_cleanup();
2699 }
2700
handler(int a)2701 void handler(int a)
2702 {
2703 fprintf(stderr,"alarm catched in wb.c\n");
2704 exit(1);
2705 }
2706
InitWhiteBoard()2707 int InitWhiteBoard()
2708 {
2709 InitLocalPID(); /* initializes gszLocalPID */
2710
2711 memset(&gstWBInfo, 0, sizeof(struct WhiteBoardRec));
2712
2713 gstWBInfo.BlockRemoteCmdDepth = 1; /* FIXME Should be zero? */
2714 gstWBInfo.pid = (long)getpid();
2715
2716 if (cmdLineWb2) {
2717 gstWBInfo.do_whiteboard = TRUE;
2718 }
2719 if (cmdLineNoWhiteBoard) gstWBInfo.do_whiteboard = FALSE;
2720
2721 *gstWBInfo.send_fname = *gstWBInfo.gz_send_fname = '\0';
2722 gstWBInfo.send_fp = gstWBInfo.gz_send_fp = NULL;
2723 gstWBInfo.send_socket = (-1);
2724
2725 gstWBInfo.listening = FALSE;
2726
2727 *gstWBInfo.listen_fname = *gstWBInfo.gz_listen_fname = '\0';
2728 gstWBInfo.listen_fp = gstWBInfo.gz_listen_fp = NULL;
2729 gstWBInfo.listen_socket = (-1);
2730
2731 #ifdef _TGIF_DBG_WB2
2732 {
2733 char *c_ptr=NULL;
2734
2735 wb2DebugLevel = 0;
2736 if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME, "DebugWB2")) != NULL) {
2737 wb2DebugLevel = atoi(c_ptr);
2738 }
2739 }
2740 #endif /* _TGIF_DBG_WB2 */
2741
2742 memset(&gRMCastIntrfInfo, 0, sizeof(RMCastIntrfInfo));
2743
2744 return TRUE;
2745 }
2746
InitWhiteBoard2()2747 int InitWhiteBoard2()
2748 {
2749 int want_new_member_support=0;
2750 #if (defined(PTHREAD) || defined(HAVE_LIBPTHREAD))
2751 pthread_t tid=(pthread_t)0;
2752 #endif /* (defined(PTHREAD) || defined(HAVE_LIBPTHREAD)) */
2753 char tgwb_config_file[255];
2754 char *homedir=NULL;
2755 int config_ok=0;
2756
2757 if (!gstWBInfo.do_whiteboard) return TRUE;
2758
2759 #if (!defined(PTHREAD) && !defined(HAVE_LIBPTHREAD))
2760 sprintf(gszMsgBox, TgLoadString(STID_NO_PTHREAD_CONTINUE), TOOL_NAME,
2761 TOOL_NAME, TOOL_NAME);
2762 MsgBox(gszMsgBox, TOOL_NAME, STOP_MB);
2763 gstWBInfo.do_whiteboard = FALSE;
2764 SendCommandToSelf(CMDID_QUIT, 0);
2765 return FALSE;
2766 #endif /* (!defined(PTHREAD) && !defined(HAVE_LIBPTHREAD)) */
2767
2768 if (!RMCastInit()) {
2769 gstWBInfo.do_whiteboard = FALSE;
2770 return FALSE;
2771 }
2772 InitDeserializeCmd();
2773
2774 if (!CreateWBListenSocket()) {
2775 CleanUpWBSockets();
2776 exit(-1);
2777 }
2778
2779 if (MkTempFile(gstWBInfo.send_fname, sizeof(gstWBInfo.send_fname),
2780 tmpDir, TOOL_NAME) == NULL) {
2781 fprintf(stderr, "Fail to create '%s' for serialization.\n",
2782 gstWBInfo.send_fname);
2783 exit(-1);
2784 }
2785 snprintf(gstWBInfo.gz_send_fname, sizeof(gstWBInfo.gz_send_fname),
2786 "%s.z", gstWBInfo.send_fname);
2787 if ((gstWBInfo.send_fp=fopen(gstWBInfo.send_fname, "w+")) == NULL) {
2788 fprintf(stderr, "Fail to create '%s' for serialization.\n",
2789 gstWBInfo.send_fname);
2790 exit(-1);
2791 }
2792 if ((gstWBInfo.gz_send_fp=fopen(gstWBInfo.gz_send_fname, "w+")) == NULL) {
2793 fprintf(stderr, "Fail to create '%s' for serialization.\n",
2794 gstWBInfo.gz_send_fname);
2795 exit(-1);
2796 }
2797
2798 if ( (homedir=getenv("HOME")) != NULL ){
2799 sprintf(tgwb_config_file,"%s/.tgwb/tgwb.conf",homedir);
2800 if (RM_readConfigFile(tgwb_config_file, 0))
2801 config_ok=2; /* It means that we read $HOME/.tgwb/tgwb.conf */
2802 }
2803 else{
2804 fprintf(stderr,"TGWB Warning: Can't get environment variable 'HOME', using default values.\n");
2805 }
2806 if (config_ok==0 && RM_readConfigFile("/etc/tgwb.conf", 0)){
2807 config_ok=1; /* It means that we read /etc/tgwb.conf */
2808 }
2809
2810 switch (config_ok){
2811 case 1:
2812 fprintf(stderr,"Using config file: '/etc/tgwb.conf'\n");
2813 break;
2814 case 2:
2815 fprintf(stderr,"Using config file: '%s'\n",tgwb_config_file);
2816 break;
2817 default:
2818 fprintf(stderr,"TGWB Warning:\n Config files:\n\t'%s/.tgwb/tgwb.conf'\n\t'/etc/tgwb.conf'\n not found.\nUsing default values.\n",homedir);
2819 }
2820
2821 /* setting defaults */
2822
2823 RM_setOption(PIPE, &talkToSelfFiledes);
2824 RM_setOption(SHUT_DOWN_ROUTINE, &CleanUpWBSockets);
2825
2826 RM_initialize((void *)RMcallback_terminate);
2827
2828 RM_getOption(NEW_MEMBER_SUPPORT, (void*)&want_new_member_support);
2829
2830 if (want_new_member_support)
2831 {
2832 CurStatus cur_state;
2833
2834 fprintf(stderr,"Getting the current status.\n");
2835
2836 RM_getCurStatus( (char*)RM_USE_CURRENT_CONFIG, RM_USE_CURRENT_CONFIG,
2837 &cur_state);
2838
2839 if (cur_state.size != -1)
2840 {
2841 int saved_disable_redraw=disableRedraw;
2842
2843 deserializingFile = TRUE;
2844 disableRedraw = TRUE;
2845 UnpackCurrentTGWBState(&cur_state);
2846 disableRedraw = saved_disable_redraw;
2847 if (!saved_disable_redraw) {
2848 ClearAndRedrawDrawWindow();
2849 }
2850 deserializingFile = FALSE;
2851 }
2852 }
2853 gstWBInfo.MCastSock = RM_joinGroup((char*)RM_USE_CURRENT_CONFIG, RM_USE_CURRENT_CONFIG );
2854
2855 gstWBInfo.bd_commands = buff_init (10, WB_PACK, UNSORTED, NULL );
2856
2857 /* debugging RMCAST
2858 fprintf(stderr,"buffer descriptor: %d\n", gstWBInfo.bd_commands);
2859 */
2860 #if (defined(PTHREAD) || defined(HAVE_LIBPTHREAD))
2861 if( pthread_create( &tid, NULL, ReceivePacket, NULL ) != 0 )
2862 {
2863 fprintf( stderr, "Could not create receive thread\n" );
2864 exit( -1 );
2865 }
2866 #endif /* (defined(PTHREAD) || defined(HAVE_LIBPTHREAD)) */
2867 return TRUE;
2868 }
2869
RMcallback_terminate(void)2870 void RMcallback_terminate( void )
2871 {
2872 /*
2873 * tgif must do its clean up here before exit
2874 *
2875 * exit(0);
2876 */
2877 }
2878
2879