mgpm/ 40775 423 0 0 6646655173 10344 5ustar luigiwheelmgpm/Makefile100644 423 0 1014 6646653373 12073 0ustar luigiwheel# New ports collection makefile for: rlc # Version required: none # Date created: Thu Nov 5 16:24:09 GMT 1998 # Whom: luigi@iet.unipi.it # # $Id: Makefile,v 1.1$ # DISTNAME= mgp-snap-981221 PKGNAME= mgpm-0.02 CATEGORIES= mbone MASTER_SITES= ftp://ftp.mew.org/ MAINTAINER= luigi@iet.unipi.it USE_IMAKE= yes GNU_CONFIGURE= yes WRKSRC= ${WRKDIR}/kit post-extract: do-install: echo "Prefix is ${PREFIX}" @${INSTALL_PROGRAM} ${WRKSRC}/mgp ${PREFIX}/bin/mgpm .include mgpm/files/ 40755 423 0 0 6637752665 11450 5ustar luigiwheelmgpm/files/md5100644 423 0 100 6637752665 12124 0ustar luigiwheelMD5 (mgp-snap-981221.tar.gz) = 0533926a0cb7934e37ee181bb8481daf mgpm/patches/ 40755 423 0 0 6637272045 11762 5ustar luigiwheelmgpm/patches/patch-ba100664 0 0 523 6637210675 13245 0ustar rootwheel--- scanner.l.orig Sat Nov 14 18:16:06 1998 +++ scanner.l Sun Dec 20 15:39:32 1998 @@ -121,6 +121,7 @@ (IMAGE|image) return KW_IMAGE; (NEWIMAGE|newimage) return KW_NEWIMAGE; (BIMAGE|bimage) return KW_BIMAGE; +(IMPORT|import) return KW_IMPORT; (PAGE|page) return KW_PAGE; (HGAP|hgap) return KW_HGAP; (VGAP|vgap) return KW_VGAP; mgpm/patches/patch-aa100644 423 0 3770 6637272334 13470 0ustar luigiwheel--- Imakefile.in.orig Sat Nov 14 18:44:38 1998 +++ Imakefile.in Sun Dec 20 23:06:06 1998 @@ -5,9 +5,10 @@ VPATH= @srcdir@ SRCS= mgp.c draw.c parse.c plist.c print.c globals.c x11.c x11dummy.c \ font.c background.c scanner.c grammar.c postscript.c tfont.c \ - embed.c + embed.c net.c fileio.c cmdio.c TPOBJS= mgp.o draw.o parse.o plist.o globals.o x11.o font.o background.o \ - scanner.o grammar.o postscript.o tfont.o embed.o + scanner.o grammar.o postscript.o tfont.o embed.o \ + net.o fileio.o cmdio.o PROBJS= print.o parse.o globals.o x11dummy.o scanner.o grammar.o postscript.o \ embed.o LIBOBJS= @LIBOBJS@ @@ -19,7 +20,8 @@ LEX= @LEX@ # NOTE: we must not define CC here, since imake may assume other CC to be used. -OPTFLAGS= @OPTFLAGS@ +CCOPTIONS= -Wall +OPTFLAGS= @OPTFLAGS@ -Wall DEFS= @DEFS@ -DMGPLIBDIR=\"$(LIBDIR)/mgp\" #DEFS+= -DGLYPHEDGE @@ -76,13 +78,16 @@ NamedMakeSubdirs($(srcdir)/image/libimage.a, image) MakeSubdirs(sample contrib) -mgp.o: $(srcdir)/mgp.c ctlwords.h -draw.o: $(srcdir)/draw.c ctlwords.h -globals.o: $(srcdir)/globals.c ctlwords.h -grammar.o: $(srcdir)/grammar.c ctlwords.h -parse.o: $(srcdir)/parse.c ctlwords.h -plist.o: $(srcdir)/plist.c ctlwords.h -print.o: $(srcdir)/print.c ctlwords.h +mgp.o: $(srcdir)/mgp.c ctlwords.h mgp.h +draw.o: $(srcdir)/draw.c ctlwords.h mgp.h +globals.o: $(srcdir)/globals.c ctlwords.h mgp.h +grammar.o: $(srcdir)/grammar.c ctlwords.h mgp.h +parse.o: $(srcdir)/parse.c ctlwords.h mgp.h +plist.o: $(srcdir)/plist.c ctlwords.h mgp.h +print.o: $(srcdir)/print.c ctlwords.h mgp.h +net.o: $(srcdir)/net.c ctlwords.h mgp.h +fileio.o: $(srcdir)/fileio.c ctlwords.h mgp.h +fileio.o: $(srcdir)/fileio.c ctlwords.h mgp.h ctlwords.h: $(srcdir)/ctlwords.c $(srcdir)/ctlwords.pl $(srcdir)/globals.c if test -x $(PERL); then \ @@ -94,7 +99,7 @@ scanner.c: $(srcdir)/scanner.l $(LEX) -t $(srcdir)/scanner.l > scanner.c -scanner.o: scanner.c tokdefs.h +scanner.o: scanner.c tokdefs.h mgp.h grammar.c: $(srcdir)/grammar.y $(YACC) -d $(srcdir)/grammar.y mgpm/patches/patch-ab100644 423 0 31716 6646634526 13517 0ustar luigiwheel--- draw.c.orig Thu Dec 17 05:32:33 1998 +++ draw.c Tue Jan 12 12:56:38 1999 @@ -72,7 +72,7 @@ static int obj_new_xfont __P((struct render_state *, int, int, int, u_int, char *)); static int obj_new_image __P((struct render_state *, int, int, Image *, int, int)); -static int obj_new_icon __P((struct render_state *, int, int, u_int, u_int, u_long, u_int, XPoint *)); +static int obj_new_icon __P((struct render_state *, int, int, u_int, u_int, u_int, u_long, u_int, XPoint *)); static Pixel obj_image_color __P((Image *, Image *, Pixel)); static Image *obj_image_trans __P((Image *, u_int, u_int)); static void obj_draw_image __P((Drawable, u_int, u_int, struct render_object *)); @@ -125,6 +125,10 @@ /* * state management. + * Also, send commands etc if doing multicast. + * XXX lr I think this could be a bit more complete, e.g. + * initialize state->cp. This is not done just because the other + * routines (state_next, state_init, draw_*) are tolerant. */ void state_goto(state, page, repaint) @@ -132,6 +136,12 @@ u_int page; int repaint; { + int old_page = state->page ; + + DEB(if (old_page == page) + fprintf(stderr, "?? useless goto %d -> %d%s\n", + old_page, page, repaint ? ", repaint":"");) + if (!repaint) purgechild(state->page); @@ -140,7 +150,35 @@ state->page = page; state->line = 0; state->cp = NULL; + state->cp_sp = 0; /* XXX lr stack */ state->phase = P_NONE; + tx_cmd(RC_GOTO_PAGE, page, 0); +} + +/* + * this function handles CALL/RETURN intructions. The mechanism is used + * for expanding tabs and sequences of control items. + * a RETURN is state->cp == NULL. + * a CALL is state->cp == CTL_CALL. + */ +void +state_call_ret(struct render_state *state) +{ +again: + while (!state->cp && state->cp_sp >0) { /* XXX return */ + fprintf(stderr, "-- RETURN depth %d\n", state->cp_sp); + state->cp_sp-- ; + state->cp = state->cp_stack[state->cp_sp] ; + } + if (state->cp && state->cp->ct_op == CTL_CALL) { + state->cp_stack[state->cp_sp++] = state->cp->ct_next; + state->cp = state->cp->cti_value ; + fprintf(stderr, "-- CALL depth %d\n", state->cp_sp); + /* + * be prepared to handle empty routines + */ + goto again ; + } } void @@ -151,17 +189,10 @@ case P_NONE: fprintf(stderr, "internal error\n"); break; - case P_DEFAULT: - if (state->cp) - state->cp = state->cp->ct_next; - if (!state->cp) { - state->cp = page_control[state->page][state->line]; - state->phase = P_PAGE; - } - break; case P_PAGE: if (state->cp) state->cp = state->cp->ct_next; + state_call_ret(state); if (!state->cp) { state->line++; state->cp = NULL; @@ -184,11 +215,15 @@ state->line = 0; state_newpage(state); state_init(state); + tx_cmd(RC_GOTO_PAGE, state->page, 0); } else state->phase = P_END; } } +/* + * set pointer to the first command for the line. + */ void state_init(state) struct render_state *state; @@ -196,19 +231,15 @@ assert(state); if (state->phase == P_NONE || !state->cp) { -#if 0 - if (!(page_attribute[state->page].pg_flag & PGFLAG_NODEF)) { - state->cp = default_control[state->line]; - state->phase = P_DEFAULT; - } else -#endif - { state->cp = page_control[state->page][state->line]; + state_call_ret(state); state->phase = P_PAGE; } } -} +/* + * reset yposition and mark status for the page + */ void state_newpage(state) struct render_state *state; @@ -219,7 +250,14 @@ /* * page management. + * draw_page() draws a full page, ignoring pauses except at the end + * of page. lastcp is the last command to process. The special value + * &stop_on_pause is used to stop at the first pause. + * Used to generate html files. + * draw_one() executes one directive and then polls events. */ +struct ctrl stop_on_pause ; /* used as a stopgap */ + void draw_page(state, lastcp) struct render_state *state; @@ -227,7 +265,6 @@ { u_int end_line; int pause; - assert(state); /* initialize the state, if required. */ @@ -243,7 +280,6 @@ case P_NONE: fprintf(stderr, "internal error\n"); cleanup(-1); - case P_DEFAULT: case P_PAGE: pause = 0; if (state->cp) @@ -251,6 +287,8 @@ if (lastcp && state->cp == lastcp) goto done; if (pause) { + if (lastcp == &stop_on_pause) + goto done ; if (state->cp && state->cp->ct_op == CTL_PAUSE && state->cp->cti_value) { @@ -270,10 +308,12 @@ XFlush(display); } + Bool -draw_one(state, e) +draw_one(state, e, got_command) struct render_state *state; XEvent *e; + int *got_command; { u_int end_line; int pause; @@ -286,7 +326,9 @@ char c; extern volatile int ttykey_enable; #endif + int max_fd; + *got_command=0; assert(state); /* initialize the state, if required. */ @@ -298,7 +340,6 @@ end_line = page_attribute[state->page].pg_linenum; switch (state->phase) { - case P_DEFAULT: case P_PAGE: pause = 0; if (state->cp) @@ -332,6 +373,13 @@ state_next(state); return True; } + + if (rx_poll() && (pause || state->phase == P_END ) ) { + *got_command=1; + XFlush(display); + return True; + } + #ifdef TTY_KEYINPUT if (ttykey_enable) { FD_ZERO(&fds); @@ -366,10 +414,32 @@ if (ttykey_enable) FD_SET(0, &fds); #endif +/* + * XXX Hooks for replay can be put here. + * + */ /* wait for something */ tout.tv_sec = 2; tout.tv_usec = 0; - (void)select(xfd + 1, &fds, NULL, NULL, &tout); + if (tx_addr) { + int base = time(NULL); + if (resend_time > 0) + tout.tv_sec = min(tout.tv_sec, resend_time - base); + if (tout.tv_sec < 0) + fprintf(stderr, " ** warning, timeout %d\n", + tout.tv_sec); + } + max_fd=xfd; + if (rx_addr) { + FD_SET(rx_socket, &fds); + max_fd = max(max_fd, rx_socket); + } + select(max_fd+ 1, &fds, NULL, NULL, &tout); + if (tx_addr) { + int t = time(NULL); + if ( t >= resend_time && resend_time>0 ) + mcast_resend(); + } #ifdef TTY_KEYINPUT if (!(mgp_flag & FL_NOSTDIN) && !ttykey_enable) try_enable_ttykey(); @@ -384,7 +454,7 @@ int *seenpause; { struct ctrl *cp; - +again: if (seenpause) *seenpause = 0; cp = state->cp; @@ -395,6 +465,12 @@ } switch(cp->ct_op) { + case CTL_CALL: + fprintf(stderr, "-- CTL_CALL in process_direc\n"); + state_call_ret(state); + goto again ; + break ; + case CTL_SIZE: char_size = state->height * cp->ctf_value / 100; #ifdef FREETYPE @@ -623,6 +699,9 @@ process_icon(state, cp); break; + case CTL_DRAW: + process_draw(state, cp); + break; #ifdef VFLIB case CTL_VFCAP: vfcap_name = cp->ctc_value; @@ -639,6 +718,7 @@ break; #endif + case CTL_IMPORT: /* XXX lr */ case CTL_NOOP: case CTL_NODEF: break; @@ -851,7 +931,7 @@ /* * render characters. */ -static void +void draw_string(state, data) struct render_state *state; char *data; @@ -1330,10 +1410,10 @@ } static int -obj_new_icon(state, x, y, itype, isize, color, npoint, xpoint) +obj_new_icon(state, x, y, itype, iwidth, iheight, color, npoint, xpoint) struct render_state *state; int x, y; - u_int itype, isize; + u_int itype, iwidth, iheight; u_long color; u_int npoint; XPoint *xpoint; @@ -1349,7 +1429,7 @@ obj->fore = color; obj->type = O_ICON; obj->data.icon.itype = itype; - obj->data.icon.isize = isize; + obj->data.icon.isize = iwidth; obj->data.icon.npoint = npoint; if (npoint) { obj->data.icon.xpoint = malloc(sizeof(XPoint) * npoint); @@ -1362,7 +1442,7 @@ } else obj->data.icon.xpoint = NULL; obj->ascent = 0; /*XXX*/ - obj->descent = isize; /*XXX*/ + obj->descent = iheight; /*XXX*/ obj->vertloc = VL_CENTER; return 1; } @@ -1596,7 +1676,6 @@ u_int code; char *registry; XChar2b kch[2]; - char ch[2]; u_int isize; int i; #ifdef RASTERLIB @@ -1829,10 +1908,18 @@ break; case 3: case 4: case 5: case 6: case 7: + case 8: /* rect */ + case 9: /* frame */ for (i = 0; i < obj->data.icon.npoint; i++) { obj->data.icon.xpoint[i].x += x; obj->data.icon.xpoint[i].y += y; } + if (obj->data.icon.itype==9) + XDrawLines(display, target, gcfore, + obj->data.icon.xpoint, + obj->data.icon.npoint, + CoordModeOrigin); + else XFillPolygon(display, target, gcfore, obj->data.icon.xpoint, obj->data.icon.npoint, @@ -2750,12 +2837,78 @@ } static void +process_draw(state, cp) + struct render_state *state; + struct ctrl *cp; +{ + XPoint xpoint[5]; + + int sz = (int) char_size ; + char *s= "?" ; + drawcmds cmd = cp->ct_val.ctrl_drawcmd.cmd ; + int icon_x = state->linewidth ; + int points = 0 ; + int icon_type = 9 ; /* 8 = filled, 9 = not filled */ + + switch (cmd) { + case DC_LINE: + s = "line"; + xpoint[0].x = icon_x + cp->ct_val.ctrl_drawcmd.x0*sz/100 ; + xpoint[0].y = -(cp->ct_val.ctrl_drawcmd.y0*sz/100); + xpoint[1].x = icon_x + cp->ct_val.ctrl_drawcmd.x1*sz/100 ; + xpoint[1].y = -(cp->ct_val.ctrl_drawcmd.y1*sz/100); + points = 2 ; + break ; + + case DC_RECT : + case DC_FRAME : + if (cmd == DC_RECT) { + s = "rect"; + icon_type = 8 ; + points = 4 ; + } else { + s = "frame"; + points = 5 ; + } + xpoint[0].x = icon_x + cp->ct_val.ctrl_drawcmd.x0*sz/100 ; + xpoint[0].y = -(cp->ct_val.ctrl_drawcmd.y0*sz/100); + xpoint[4].x = xpoint[0].x ; + xpoint[4].y = xpoint[0].y ; + xpoint[2].x = icon_x + cp->ct_val.ctrl_drawcmd.x1*sz/100 ; + xpoint[2].y = -(cp->ct_val.ctrl_drawcmd.y1*sz/100); + xpoint[1].x = xpoint[2].x ; + xpoint[1].y = xpoint[0].y ; + xpoint[3].x = xpoint[0].x ; + xpoint[3].y = xpoint[2].y ; + points = 5 ; + break ; + + break ; + } + obj_new_icon(state, 0, 0, icon_type, + 0 /* width */ , + 0 /* icon_height */, + cp->ct_val.ctrl_drawcmd.color, + points, xpoint); + state->objlast->vertloc = VL_BASE; +} + +/* + * icon have a default width of one char, placed centered + */ + +static void process_icon(state, cp) struct render_state *state; struct ctrl *cp; { u_int i, icon_type, icon_size, icon_x, icon_y, index; + u_int icon_height; u_long tmp_color; + /* + * if you define new icons, remember to also add + * the case to the switch in obj_draw() + */ static struct ctl_words icon_words[] = { { 1, 'x', "box", 3 }, { 2, 'x', "arc", 3 }, @@ -2764,17 +2917,23 @@ { 5, 'x', "delta3", 6 }, { 6, 'x', "delta4", 6 }, { 7, 'x', "dia", 3 }, + { 8, 'x', "rect", 4 }, + { 9, 'x', "frame", 5 }, { 0, 'x', NULL, 0 } }; - XPoint xpoint[4]; + XPoint xpoint[5]; static struct icon_point { int point_num; - XPoint xpoint[4]; - } icon_point[] = {{ 3, {{1, 0}, {0, 2}, {2, 2}, {0, 0}}}, - { 3, {{0, 0}, {2, 0}, {1, 2}, {0, 0}}}, - { 3, {{0, 0}, {0, 2}, {2, 1}, {0, 0}}}, - { 3, {{2, 0}, {2, 2}, {0, 1}, {0, 0}}}, - { 4, {{1, 0}, {0, 1}, {1, 2}, {2, 1}}}}; + XPoint xpoint[5]; + } icon_point[] = { + { 3, {{1, 0}, {0, 2}, {2, 2}, {0, 0}, {0,0}}}, + { 3, {{0, 0}, {2, 0}, {1, 2}, {0, 0}, {0,0}}}, + { 3, {{0, 0}, {0, 2}, {2, 1}, {0, 0}, {0,0}}}, + { 3, {{2, 0}, {2, 2}, {0, 1}, {0, 0}, {0,0}}}, + { 4, {{1, 0}, {0, 1}, {1, 2}, {2, 1}, {0,0}}}, + { 4, {{0, 0}, {0, 2}, {2, 2}, {2, 0}, {0,0}}}, + { 5, {{0, 0}, {0, 2}, {2, 2}, {2, 0}, {0,0}}}, + }; for (i = 0; icon_words[i].ctl_strlen != 0; i++) { if (!strncasecmp(cp->ctic_value, icon_words[i].ctl_string, @@ -2785,6 +2944,15 @@ icon_type = icon_words[i].ctl_type; /* may be 0 */ icon_size = char_size * cp->ctic_size / 100; + icon_height = icon_size ; + /* + * this hack lets us define geometry as WWWHHH + * for non-square icons. + */ + if (cp->ctic_size > 1000) { + icon_size = char_size * cp->ctic_size / 100000 ; + icon_height = char_size * (cp->ctic_size % 1000) / 100 ; + } switch(icon_type){ case 0: @@ -2803,7 +2971,8 @@ /* this is box */ obj_new_icon(state, state->linewidth + char_size/2 - icon_size/2, - POSY(icon_size), icon_type, icon_size, + POSY(icon_height), icon_type, icon_size, + icon_height, cp->ctic_color, 0, NULL); state->linewidth += char_size; break; @@ -2813,6 +2982,7 @@ obj_new_icon(state, state->linewidth + char_size/2 - icon_size/2, POSY(icon_size), icon_type, icon_size, + icon_height, cp->ctic_color, 0, NULL); state->linewidth += char_size; break; @@ -2822,10 +2992,16 @@ case 5: case 6: case 7: + case 8: + case 9: index = icon_type - 3; + /* non-square icons are left-aligned */ + if (icon_size != icon_height) + icon_x = state->linewidth ; + else icon_x = state->linewidth + (char_size - icon_size) / 2; #if 0 - icon_y = POSY(icon_size); + icon_y = POSY(icon_height); #else icon_y = 0; #endif @@ -2833,11 +3009,13 @@ xpoint[i].x = icon_x + icon_point[index].xpoint[i].x * icon_size / 2; xpoint[i].y = icon_y + - icon_point[index].xpoint[i].y * icon_size / 2; + icon_point[index].xpoint[i].y * icon_height / 2; } obj_new_icon(state, 0, 0, icon_type, icon_size, + icon_height, cp->ctic_color, icon_point[index].point_num, xpoint); - state->linewidth += char_size; + state->linewidth += + (char_size > icon_size) ? char_size : icon_size; break; default: mgpm/patches/patch-ac100644 423 0 27747 6637274412 13523 0ustar luigiwheel--- net.c.orig Sun Dec 20 23:06:38 1998 +++ net.c Sun Dec 20 23:18:29 1998 @@ -0,0 +1,503 @@ +/* net.c + + by Davide Devoti (davided@luna.it) and Luigi Rizzo (luigi@iet.unipi.it) + + The socket I/O functions are derived from the net.cc module from vic, with + the following (original) copyright: + + * Copyright (c) 1993-1994 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and the Network Research Group at + * Lawrence Berkeley Laboratory. + * 4. Neither the name of the University nor of the Laboratory may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include +#include +#include "mgp.h" + +static char *mcast_sender_file=NULL; +static int mcast_sender_pid; + +/*--------------- start of loss simulation routine ------------------*/ +/* Functions related to UDP losses + out of order simulation*/ + +//#define UDP_LOSSES + +#ifdef UDP_LOSSES + +int udp_loss_socket=0; + +int +lib_start() +{ + int s2; + u_short port; + int pid; + char buffer[MAX_SYNC_PKT_SIZE]; + int l; + + port=1111; + port=htons(port); + + udp_loss_socket=openssock(inet_addr("127.0.0.1\0"), port, 2, 0); + if (udp_loss_socket<0) { + printf("Error in library init\n"); + return(-1); + } + + pid=fork(); + if (pid==0) { + fd_set fset; + int a; + struct timeval tval; + int r; + int i; + int s1; + +#define MAX_PACKETS 100 +#define MAX_HOPS 11 + + struct packet_info { + int dest_socket; + char data[MAX_SYNC_PKT_SIZE]; + int len; + int hops; + }; + + struct packet_info packets[MAX_PACKETS]; + int packets_count=0; + + close(s1); + + srand(13); + + s2=openrsock(inet_addr("127.0.0.1\0"), &port); + if (s2<0) { + printf("Error int library init\n"); + exit(-1); + } + + while (1) { + FD_ZERO(&fset); + FD_SET(s2, &fset); + tval.tv_sec=0; + tval.tv_usec=500000; + r=select(s2+1, &fset, NULL, NULL, &tval); + if (r==1) { + recvfrom(s2, &s1, 4, 0, NULL, NULL); + FD_ZERO(&fset); + FD_SET(s2, &fset); + select(s2+1, &fset, NULL, NULL, NULL); + l=recvfrom(s2, buffer, MAX_SYNC_PKT_SIZE, 0, NULL, NULL); + if (packets_count=0) { + packets[packets_count].dest_socket=s1; + packets[packets_count].hops=a; + packets[packets_count].len=l; + memcpy(packets[packets_count].data, buffer, l); + packets_count++; + } + } + } else { + r=0; + while (r0) { + int arg ; + s1=rindex(q, '/'); + arg = atoi(s1+1); + switch (count) { + case 3: + if (arg <= 0) + return -1 ; + *rate = arg ; + break ; + + case 2: + *ttl=atoi(s1+1); + if (arg <= 0 || arg > 255) + return -1 ; + *ttl = arg ; + break ; + + case 1: + *p = arg ; + break ; + } + *s1 = '\0' ; + count-- ; + } + return 0; +} + + +extern char *internalfilename; + +int mcast_ttl = 10 ; /* local... */ +int mcast_rate = 8 ; /* Kbit/s */ + +static void +mcast_start_sender() +{ + int i; + char d[64]; + static char *s_args[13]; + + i = 0 ; + s_args[i++] = "sen-sample" ; + s_args[i++] = "-s" ; + sprintf(d, "%d", sender_version); + s_args[i++] = strdup(d); /* XXX leak */ + s_args[i++] = "-f" ; + s_args[i++] = strdup(mcast_sender_file); /* XXX leak */ + s_args[i++] = "-I"; + s_args[i++] = "-r"; + sprintf(d, "%d", mcast_rate); + s_args[i++] = strdup(d); /* XXX leak */ + s_args[i++] = "-t"; + sprintf(d, "%d", mcast_ttl); + s_args[i++] = strdup(d) ; /* XXX leak */ + s_args[i++] = "-d"; + s_args[i++] = strdup(rmdp_addr); /* XXX leak */ + s_args[i++] = NULL; + + fprintf(stderr, "%s %s %s %s %s %s %s %s\n", + s_args[0], s_args[1], s_args[2], s_args[3], + s_args[4], s_args[5], s_args[6], s_args[7]); + mcast_sender_pid=fork(); + if (mcast_sender_pid==0) { + execvp(s_args[0], s_args); + exit(1); + } +} + +void +mcast_restart_sender() +{ + kill(mcast_sender_pid, SIGKILL); + sender_version++; + save_binary_file(mcast_sender_file, sender_version); + mcast_start_sender(); +} + +void +sender_init() +{ + char tmpaddr[256]; + u_int16_t port1; + + if (internalfilename) + mcast_sender_file=internalfilename; + else { + mcast_sender_file=malloc(200); + + sprintf(mcast_sender_file, + "%s/mgp_mcast_sender.int", tmp_dir); + save_binary_file(mcast_sender_file, sender_version); + } + if (parse_addr(rmdp_addr, tmpaddr, sizeof(tmpaddr), + &port1, &mcast_ttl, &mcast_rate)<0) { + printf("Error parsing multicast files address\n"); + cleanup(0); + } + mcast_start_sender(); /* XXX */ +} + +/*----------------- Socket I/O functions ---------------*/ + +static int +nonblock(int fd) +{ +#ifdef WIN32 + u_long flag = 1; + + if (ioctlsocket(fd, FIONBIO, &flag) == -1) { + return -1; + } +#else + int flags = fcntl(fd, F_GETFL, 0); +#if defined(hpux) || defined(__hpux) + flags |= O_NONBLOCK; +#else + flags |= O_NONBLOCK|O_NDELAY; +#endif + if (fcntl(fd, F_SETFL, flags) == -1) { + return -1; + } +#endif + return 0; +} + +int +openssock(u_int32_t addr, u_int16_t port, int ttl, int unbound) +{ + int fd; + struct sockaddr_in sin; + + + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) + return -1; + if (nonblock(fd) < 0) + return -1; + + if (IN_CLASSD(ntohl(addr))) { +#ifdef IP_ADD_MEMBERSHIP +#ifdef WIN32 + u_int t; +#else + u_char t; +#endif + + /*** set the multicast TTL ***/ + t = (ttl > 255) ? 255 : (ttl < 0) ? 0 : ttl; + if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, + (char*)&t, sizeof(t)) < 0) { + return -1; + } +#else + return -1; +#endif + } + + if (unbound) + return fd; + +#ifdef WIN32 + memset((char *)&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_port = 0; + sin.sin_addr.s_addr = INADDR_ANY; + if (bind(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) { + return -1; + } +#endif + memset((char *)&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_port = port; + sin.sin_addr.s_addr = addr; + if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) { + return -1; + } + + return fd ; +} + +int +join_group(int fd, u_int32_t addr) +{ + struct ip_mreq mr; + /* if not m-cast addr. do nothing */ + if (!IN_CLASSD(ntohl(addr))) + return(0); + + /*** XXX now we shuold check whether fd is a valif socket */ + + mr.imr_multiaddr.s_addr = addr; + mr.imr_interface.s_addr = INADDR_ANY; + if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, + (char *)&mr, sizeof(mr)) < 0) { + return -1; + } + return (0); +} + +int +leave_group(int fd, u_int32_t addr) +{ + struct ip_mreq mr; + /* if not m-cast addr. do nothing */ + if (!IN_CLASSD(ntohl(addr))) + return(0); + + /*** XXX now we shuold check whether fd is a valif socket */ + + mr.imr_multiaddr.s_addr = addr; + mr.imr_interface.s_addr = INADDR_ANY; + if (setsockopt(fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, + (char *)&mr, sizeof(mr)) < 0) { + return -1; + } + return (0); +} + +int +openrsock(u_int32_t addr, u_int16_t *port) +{ + int fd; + struct sockaddr_in sin; + int on = 1; + + + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + return -1; + } + if (nonblock(fd) < 0) + return -1; + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,(char *)&on, sizeof(on)) < 0) { + return -1; + } +#ifdef SO_REUSEPORT + on = 1; + if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (char *)&on, sizeof(on)) < 0) { + return -1; + } +#endif + memset((char *)&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_port = *port; +#ifdef IP_ADD_MEMBERSHIP + if (IN_CLASSD(ntohl(addr))) { + + /* + * Try to bind the multicast address as the socket + * dest address. On many systems this won't work + * so fall back to a destination of INADDR_ANY if + * the first bind fails. + */ + sin.sin_addr.s_addr = addr; + if (bind(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) { + sin.sin_addr.s_addr = INADDR_ANY; + if (bind(fd, (struct sockaddr*)&sin, sizeof(sin)) < 0) { + return -1; + } + } + if (join_group(fd, addr)!=0) + return (fd); + } else +#endif + { + /* + * bind the local port to this socket. If that + * fails, another app probably has the addresses bound so + * just exit. + */ + sin.sin_addr.s_addr = addr ; + if (bind(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) { + return -1; + } + } + + if (*port == 0) { + memset((char *)&sin, 0, sizeof(sin)); + on = sizeof(sin); + getsockname(fd, (struct sockaddr *)&sin, &on) ; + *port = sin.sin_port ; + } + + return fd ; +} + +unsigned long +localaddr(int ssock_) +{ + struct sockaddr_in ad; + struct sockaddr_in *p = &ad; + int len = sizeof(*p); + memset((char *)p, 0, sizeof(*p)); + p->sin_family = AF_INET; + if (getsockname(ssock_, (struct sockaddr *)p, &len) < 0) { + /* perror("getsockname"); */ + memset((char *)p, 0, sizeof(*p)); + } + if (p->sin_addr.s_addr == 0) { + char hostname[80]; + struct hostent *hp; + + if (gethostname(hostname, sizeof(hostname)) >= 0) { + if ((hp = gethostbyname(hostname)) >= 0) { + p->sin_addr.s_addr = ((struct in_addr *)hp->h_addr)->s_addr; + } + } + } + + if (p->sin_addr.s_addr != 0) + return (p->sin_addr.s_addr); + else + return -1; +} mgpm/patches/patch-ae100644 423 0 24121 6637753040 13503 0ustar luigiwheel--- mgp.h.orig Thu Dec 10 18:14:23 1998 +++ mgp.h Mon Dec 21 00:23:55 1998 @@ -29,6 +29,9 @@ * $Id: mgp.h,v 1.100 1998/11/24 10:25:49 itojun Exp $ */ +#define DEB(x) +#define DDB(x) x + #include #include #include @@ -63,6 +66,22 @@ #include #include "image/xloadimage.h" +/* to support multicast Socket I/O functions */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "compat.h" + +/* end of Socket I/O functions support */ + #ifndef __P # define __P(x) x #endif @@ -117,9 +136,12 @@ #define RCFILE ".mgprc" #define EMBEDDIR "EMBEDDIR/" -#define UUDECODE "/usr/bin/uudecode" +#define UUDECODE "/usr/bin/uudecode -s" #define GUNZIP "/usr/contrib/bin/gunzip" +/* + * remember, a few arrays have size MAXPAGE*MAXLINE so do not exceed! + */ #define MAXPAGE 200 #define MAXLINE 100 #define MAXVALLEN 512 @@ -169,11 +191,165 @@ (KeyPressMask|KeyReleaseMask|ButtonPressMask|StructureNotifyMask|\ ExposureMask) #define EVENT_RAKUGAKI \ - (EVENT_DEFAULT|ButtonReleaseMask|Button1MotionMask) + (EVENT_DEFAULT|ButtonReleaseMask|Button1MotionMask|Button3MotionMask) + +#define max(a,b) (a>b)?a:b +#define min(a,b) (a>b)?b:a + +/* a new mod function useful for negative numbers*/ +#define my_mod(a,b) ((a%b)>=0)?(a%b):(b+(a%b)) + +/* Multicast support */ + +/* These are the possible commands included in a multicast packet. + * Names are prefix by RC (Remote Command) + */ + +#define RC_NONE 0 /* no pending command */ +#define RC_GOTO_PAGE 10 +#define RC_UNPAUSE 11 +#define RC_DRAW 12 +#define RC_REPAINT 13 +#define RC_TEXT 14 /* user-typed text */ +#define RC_RESIZE 15 + +/* Max number of rx streams (that is command sources) */ +/* At the moment this value is unused */ + +#define MAX_SYNC_SOURCES 1000 + +/* This is the max size of a sync packet */ + +#define MAX_SYNC_PKT_SIZE 300 + +/* This is the max number of points in a freehand draw */ + +#define MAX_DRAW_POINTS ( (MAX_SYNC_PKT_SIZE - 60) / 4 ) + +#define MAX_TEXT_CHARS 20 + +#define TEXT_TIMER 1 /* seconds after which txt is updated */ + + +/* This is the inter-sync packet time */ + +#define RESEND_INTERVAL 5 + +/* This is the exit status from the receiver when it finds that there's a new transmission */ + +#define NEW_TRANSMISSION_ACTIVE 67 + + +/* RTP header structure */ +/* + * a pkt in the control stream is made of one rtphdr followed by + * a sync_pkt_hdr and payload data. One additional byte is used as + * terminator (it does not have a sequence number) + */ + +struct rtphdr { +#if defined(_BIG_ENDIAN) + u_int v:2; + u_int p:1; + u_int x:1; + u_int cc:4; + u_int m:1; + u_int pt:7; /* msb is the marker... */ + u_int seq:16; +#else + u_int cc:4; + u_int x:1; + u_int p:1; + u_int v:2; + u_int pt:7; /* lsb is the marker... */ + u_int m:1; + u_int seq:16; +#endif + + u_int32_t timestamp; + u_int32_t ssrc; +}; + +typedef struct rtphdr rtphdr; + +struct sync_pkt_hdr { + u_int16_t vers; + u_int16_t page; + u_int16_t width; + u_int16_t height; + u_int32_t seq; /* sequence # of first byte */ +}; + +typedef struct sync_pkt_hdr ctrl_hdr ; + +#define PAYLOAD_OFS ( sizeof(rtphdr) + sizeof(ctrl_hdr) ) +#define PAYLOAD_LEN (MAX_SYNC_PKT_SIZE - PAYLOAD_OFS) + +struct net_pkt { + rtphdr r ; + ctrl_hdr s ; + u_char data[PAYLOAD_LEN] ; +} ; + +/* + * info on the receive stream + */ +struct rx_segment { + struct rx_segment *next ; + int len; + ctrl_hdr s; /* all the state is here, incl seq. (host order) */ + u_char *data ; +} ; + + +struct rx_stream { + u_int32_t s_id; /* id of the source associated with the stream */ + struct rx_segment *first, *last ; + ctrl_hdr s_curr; /* state associated to parse_start */ + int parse_start; /* first byte to parse */ + int last_goto; /* last goto known (or right after it) */ +}; + +struct stream_list { + struct rx_stream *str; + struct stream_list *next; +}; + +/* + * data to send are stored in a buffer of limited size. This is sent + * split into pkts of bounded size. Only the commands related to + * the last page are sent, previous ones are lost (unimportant). + * Each pkt sent is associated to a global state (ctrl_hdr). + * This data structure contains two such state variables, one for + * the most recent pkt, one for the background task which scans + * all pkts. + */ + +#define MAX_TX_BUFFER_SIZE 64000 +#define MAX_TX_PACKETS 50 /* XXX */ + + +/* RTP stuff */ + +#define RTP_VERSION 2 +#define RTP_PAD 0 +#define RTP_EXTENSION 0 +#define RTP_CSRC 0 +#define RTP_MARKER 0 +#define RTP_PAYLOAD_TYPE 0 + + +/* These are the tokens we use in an internal-data file */ +#define NUMBER_OF_PAGES 127 +#define NEW_PAGE 128 +#define NEW_LINE 129 +#define NEW_DIRECTIVE 130 +#define END_OF_LINE 131 + #include "ctlwords.h" -struct ctrl_double { +struct ctrl_double { /* XXX lr never used */ double ct_value; }; @@ -237,6 +413,18 @@ struct g_color **colors; }; +typedef enum drawcmds { + DC_NONE, DC_MOVETO, DC_LINETO, DC_LINE, DC_RECT, DC_FRAME +} drawcmds; + +struct ctrl_drawcmd { + drawcmds cmd; + u_long color ; + u_short width ; + u_short fill ; + short x0, y0, x1, y1 ; +} ; + struct ctrl_bar { u_long ct_color; u_int ct_width; @@ -252,8 +440,7 @@ struct ctrl { u_char ct_op; - u_char ct_flag; - u_int ct_page; + u_char ct_page; /* XXX lr never used. MAXPAGE is 200 */ struct ctrl *ct_next; union { struct ctrl_double ctrl_double; @@ -266,6 +453,7 @@ struct ctrl_bar ctrl_bar; struct ctrl_args ctrl_args; struct ctrl_icon ctrl_icon; + struct ctrl_drawcmd ctrl_drawcmd; } ct_val; }; @@ -321,8 +509,6 @@ struct page_attribute { u_int pg_flag; u_int pg_linenum; - u_int pg_b_numcolor; /* background gradation number of colors */ - u_int pg_b_dir; /* background gradation deg */ }; extern struct page_attribute page_attribute[MAXPAGE]; @@ -331,10 +517,16 @@ u_int page; u_int line; struct ctrl *cp; - enum { P_NONE, P_DEFAULT, P_PAGE, P_END } phase; + /* next two implement a small stack for TAB directives. + * in fact only one can be called right now... + */ + struct ctrl *cp_stack[10]; + u_int cp_sp; + + enum { P_NONE, P_PAGE, P_END } phase; /* * NONE - nothing - * DEFAULT - doing default_control + * DEFAULT - doing default_control (never!) * PAGE - doing page_control */ u_char *curprefix; @@ -346,13 +538,13 @@ /* * state of the renderer * we don't have xpos here since that will be - * dynaimcally determined at CTL_LINEEND. + * dynamically determined at CTL_LINEEND. */ Drawable target; u_int height; u_int width; u_int ypos; - int have_mark; + int have_mark; /* flag used with %again and mark_ypos */ u_int mark_ypos; u_int repaint; int maxascent; @@ -382,7 +574,8 @@ #endif /* FREETYPE */ O_XFONT, O_IMAGE, - O_ICON + O_ICON, + O_DRAW } type; u_long fore; union { @@ -408,6 +601,11 @@ u_int npoint; XPoint *xpoint; } icon; + struct { + drawcmds cmd ; + u_short x0, y0, x1, y1 ; + } draw ; + } data; }; @@ -501,6 +695,7 @@ extern u_long fore_color; extern u_long back_color; extern u_long ctrl_color; +extern u_long draw_linewidth; extern u_int b_quality; extern u_int quality_flag; @@ -509,6 +704,45 @@ #define VERT_STEP(s) ((s) + VERT_GAP(s)) #define HORIZ_STEP(s, x) ((x) + HORIZ_GAP(s)) + +/* The following variables are defined in net.c. + * Their implicit or explicit purpose is to allow multicast data + * transfer support. + */ + +extern u_int16_t sender_version; +extern u_int16_t current_sender_version; +extern time_t resend_time; +extern char *tmp_dir; +extern int mcast_client; /* set if we receive mgp files via multicast + from multicast_address */ +extern int mcast_sender; /* set if we send mgp files via multicast + to multicast_address */ + +extern int mgp_cmd_rx; /* set if we receive mgp commands via multicast + from rx_socket */ +extern int mgp_cmd_tx; /* set if we semd mgp commands via multicast + to tx_socket */ + +extern char *mcast_client_file; +extern char *mcast_sender_file; + +extern char *rmdp_addr; /* address used to transfer files */ + +extern char *rx_addr; /* address to receive mgp commands */ +extern char *tx_addr; /* address to send mgp commands */ + +/* the socket to send/receive presentation commands */ + +extern int mcast_sender_pid; +extern int tx_socket; + +extern int rx_socket; +#if 0 +extern char rx_pkt[MAX_SYNC_PKT_SIZE]; +extern int rx_pkt_sz; +#endif + /* * The following variable are defined in x11.c. Therefore, these are * accessible only in "mgp" binary, not in "mgp2ps". @@ -579,7 +813,8 @@ extern void state_newpage __P((struct render_state *)); extern void state_next __P((struct render_state *)); extern void draw_page __P((struct render_state *, struct ctrl *)); -extern Bool draw_one __P((struct render_state *, XEvent *)); +extern struct ctrl stop_on_pause ; +extern Bool draw_one __P((struct render_state *, XEvent *, int *)); extern void timebar __P((struct render_state *)); extern void draw_reinit __P((struct render_state *)); @@ -645,6 +880,27 @@ extern char *embed_fname __P((char *)); extern void embed_file __P((FILE *, struct ctrl *, int *)); extern void cleandir __P((void)); + +/* net.c */ +extern void save_binary_file __P((char *filename, char version)); +extern int load_binary_file __P((char *filename, char *version)); +extern void clean_internal_dir __P(()); +extern int parse_addr __P((char *s, char *a, int addrlen, short *p, + int *ttl, int *rate)); +extern void mcast_resend __P(()); +extern void mcast_new_page __P((u_int new_page)); +extern int got_pkt __P((struct stream_list **str_list, + struct rx_stream **src_str)); +extern char *inet_ntoa(); + +/* Socket I/O functions */ + +extern int openssock __P((u_int32_t addr, u_int16_t port, int ttl, int unbound)); +extern int openrsock __P((u_int32_t addr, u_int16_t *port)); +extern int join_group __P((int fd, u_int32_t addr)); +extern int leave_group __P((int fd, u_int32_t addr)); +extern unsigned long localaddr __P((int ssock_)); + /* missing/ *.c */ #ifndef HAVE_STRDUP mgpm/patches/patch-af100644 423 0 51154 6646634565 13524 0ustar luigiwheel--- mgp.c.orig Thu Dec 17 05:32:37 1998 +++ mgp.c Tue Jan 12 12:37:34 1999 @@ -54,19 +54,15 @@ u_int tbar_mode; static int rakugaki = 0; -static int rakugaki_x = -1; -static int rakugaki_y = -1; static int rakugaki_color = 0; static XColor rakugaki_fore; -static XColor rakugaki_back; -static char *rakugaki_forecolors[] = { - "red", "green", "blue", "yellow", "black", "white", -}; -static char *rakugaki_backcolors[] = { - "black", "black", "black", "black", "gray", "gray", -}; static int demointerval = 0; /* XXX define option for this */ +static int mcast_client=0; /* 1 if use rmdp to receive file */ +static int mcast_sender=0; /* 1 if use rmdp to send file */ +static char *mcast_client_file=NULL; +char *rmdp_addr = NULL; /* address used to transfer files */ + u_long depth_mask; char *back_clname = DEFAULT_BACK; @@ -98,11 +94,16 @@ static void mgp_usage __P((char *)); static void mgp_show_version __P((char *)); static void beep __P((void)); +static void rakugaki_toggle __P((void)); static void main_loop __P((u_int)); static void rakugaki_update __P((struct render_state *, XEvent *)); -static void rakugaki_updatecolor __P((Cursor)); +void rakugaki_updatecolor __P((Cursor, int)); +static void raku_next_color __P((void)); static RETSIGTYPE waitkids __P((int)); static int wantreload __P((void)); +void load_client_startup_file __P((void)); +void tx_init (int start_page); +void rx_init (void); /*image*/ extern char *expandPath __P((char *)); @@ -166,6 +167,7 @@ sigset_t mask; cleandir(); /* clean up embedded files and its dir */ + clean_internal_dir(); /* clean up internal data files and its dir */ #ifdef TTY_KEYINPUT if (ttykey_enable) tcsetattr(0, TCSANOW, &saveattr); @@ -184,6 +186,16 @@ exit(-sig); } +/* added to allow internal data saving */ +char *internalfilename = NULL ; + +static void +load_the_file(char *f) +{ + if (load_binary_file(f, NULL) == 0 ) + load_file(f); +} + int main(argc, argv) int argc; @@ -206,19 +218,66 @@ #endif progname = argv[0]; + /* we must create a place for temp files ! */ + tmp_dir=(char *)malloc(200); + sprintf(tmp_dir, "/tmp/mgp_int.%d", getpid()); + /* we use the same method shown in embed.c */ + if (mkdir(tmp_dir, 0700)==-1 && errno!=EEXIST) { + perror("Error creating temp dir "); + exit(0); + } if ((p = getenv("MGPWDIR")) != NULL) { mgpwdir = p; } -#define ACCEPTOPTS "BdvVob:c:eg:f:hlGp:qt:Q:PST:D:CORw:X:x:n" +/* + * the following options are related to multicast: + + -i filename: save internal data to file (for later http + distribution) + -M multicast addr/port/ttl/rate on base layer - multicast sender mode + (send slides data to given address) + this implies a "-s" option on addr-1 (to ease life) + + -s multicast addr/port/ttl - send mgp commands to given address + -r multicast addr/port - receive mgp commands from given address + this is implicit if an 'rmdp' url is specified. In this + case addr-1 is used. + + */ + +#define ACCEPTOPTS "Bd:vVob:c:g:f:hlGp:qt:Q:PST:D:CORw:X:x:ni:M:r:s:" while ((opt = getopt(argc, argv, ACCEPTOPTS)) != -1) { #undef ACCEPTOPTS switch (opt) { + case 's': + tx_addr = optarg; + break; + case 'r': + rx_addr = optarg; + break; + + case 'M': + if (mgp_flag & FL_DEMO) { + fprintf(stderr, "-M and demo mode incompatible\n"); + cleanup(0); + } + mcast_sender=1; + rmdp_addr = optarg; + if (tx_addr == NULL) + tx_addr = rmdp_addr ; + break ; + + case 'i': + internalfilename=optarg; + break; + case 'B': mgp_flag |= FL_BIMAGE; break; case 'd': + demointerval=atoi(optarg); mgp_flag |= FL_DEMO; break; @@ -352,28 +411,66 @@ signal(SIGQUIT, cleanup); signal(SIGTERM, cleanup); + init_win1(xgeometry); + if (argc != 1) { mgp_usage(progname); /*NOTREACHED*/ } mgp_fname = argv[0]; - { + + if (!strncmp(mgp_fname,"rmdp://", 7) ) { + char *loc; + mcast_client=1; + rmdp_addr = strdup( mgp_fname + 7); + if ((loc=index(rmdp_addr, '/'))!=NULL) + *loc='\0'; /* remove trailing slash */ + if ((loc=index(rmdp_addr, ':'))!=NULL) + *loc='/'; /* replace port separator */ + if (rx_addr == NULL) { /* add an implicit '-r' option */ + rx_addr = rmdp_addr ; + fprintf(stderr, "add -r %s\n", rx_addr ); + } + } else if (!strncmp(mgp_fname,"file://", 7) ) { + mgp_fname = mgp_fname + 7 ; /* skip URL part */ + } else if (!strncmp(mgp_fname,"http://", 7) ) { + char *tmp, cmd[1024]; + + internalfilename = malloc(strlen(tmp_dir) + + strlen(mgp_fname) + 1 ) ; + tmp = rindex(mgp_fname, '/'); + sprintf(internalfilename,"%s%s", tmp_dir, tmp); + sprintf(cmd, "(cd %s ; fetch %s)", + tmp_dir, mgp_fname); + fprintf(stderr, "++ wait.. loading %s -> %s\n", + mgp_fname, internalfilename); + mgp_fname = internalfilename; + system(cmd); + } + + if (!mcast_client) { struct stat sb; srctimestamp = (time_t) 0; if (0 <= stat(mgp_fname, &sb)) srctimestamp = sb.st_ctime; - } - - init_win1(xgeometry); strncpy(buf, mgp_fname, sizeof(buf)); if ((p = rindex(buf, '/'))) { *p = '\0'; Paths[NumPaths++]= expandPath(buf); } loadPathsAndExts(); - load_file(mgp_fname); + load_the_file(mgp_fname); if (parse_error) exit(-1); + if (internalfilename) + save_binary_file(internalfilename, 0); + } else { + loadPathsAndExts(); + load_client_startup_file(); + if (parse_error) + exit(-1); + } + init_win2(); #ifdef VFLIB vfc_setfont(vfont_name); @@ -615,6 +712,11 @@ fprintf(stderr, "\t-R: Do not perform automatic reload\n"); fprintf(stderr, "\t-X : ghostscript device to use\n"); fprintf(stderr, "\t-n: Disables control key input from tty\n"); + fprintf(stderr, + "\t-i : Save internal data to file\n" + "\t-M : Send slides data to given address\n" + "\t-s
: send commands to given address\n" + "\t-r : receive mgp commands from given address\n"); exit(0); } @@ -625,6 +727,142 @@ XBell(display, 0); } +void +mcast_receiver(struct render_state *state) +{ + int receiver_exit_status; + int mcast_client_pid; + XEvent my_event; + fd_set fset; + int xfd; + int res; + int i ; + struct timeval tout; + char *s_args[6]; + + signal(SIGCHLD, SIG_IGN); + + sprintf(mcast_client_file, "%s/mgp_mcast.int", tmp_dir); + + i = 0 ; + s_args[i++] = "rec-sample"; + s_args[i++] = "-f" ; + s_args[i++] = strdup(mcast_client_file); + s_args[i++] = "-d"; + s_args[i++] = strdup(rmdp_addr); /* XXX leak */ + s_args[i++] = NULL ; + + fprintf(stderr, "%s %s %s %s %s\n", + s_args[0], s_args[1], s_args[2], s_args[3], + s_args[4]); + mcast_client_pid=fork(); + if (mcast_client_pid==0) { /* child */ + execvp(s_args[0], s_args); + fprintf(stderr, "-- receiver done\n"); + exit(0); + } + + xfd=ConnectionNumber(display); + + for (;;) { + FD_ZERO(&fset); + FD_SET(xfd, &fset); + + tout.tv_sec=2; + tout.tv_usec=0; + + res=select(xfd+1, &fset, NULL, NULL, &tout); + + if (res==1) { + XNextEvent(display, &my_event); + if (my_event.type==KeyPress) { + receiver_exit_status=-1; + kill(mcast_client_pid, SIGKILL); + break ; + } + + if (my_event.type==ConfigureNotify) { + if (my_event.xconfigure.window != window) + continue; + if (window_width != my_event.xconfigure.width + || window_height != my_event.xconfigure.height) { + struct ctrl *lastcp; + + state->width = window_width = my_event.xconfigure.width; + state->height = window_height = my_event.xconfigure.height; + draw_reinit(state); /*notify*/ + lastcp = state->cp; + state_goto(state, state->page, 1); + draw_page(state, lastcp); + } + } + } + if (waitpid(mcast_client_pid, &receiver_exit_status, WNOHANG)) { + receiver_exit_status=WEXITSTATUS(receiver_exit_status); + break ; + } + } + + signal(SIGCHLD, waitkids); + + if (receiver_exit_status!=0) { + state_goto(state, 2, 0); + draw_page(state, &stop_on_pause); + sleep(2); + cleanup(0); + } + + draw_reinit(state); + cleanup_file(); + + i = load_binary_file(mcast_client_file, ¤t_sender_version); + if (i == 0) { + fprintf(stderr, "-- sorry. Load file failed\n"); + cleanup(0); + /*NOTREACHED*/ + } + sender_version=current_sender_version; + + if (internalfilename) + save_binary_file(internalfilename, sender_version); +} + +static void +client_init() +{ + static struct render_state state; + + memset(&state, 0, sizeof(struct render_state)); + state.target = window; /*XXX*/ + state.width = window_width; + state.height = window_height; + + state_goto(&state, 1, 0); + draw_page(&state, &stop_on_pause); + + mcast_client_file=malloc(200); + + mcast_receiver(&state); +} + +Cursor pen_curs; + +#if 0 +void +check_page(struct render_state *state, ctrl_hdr *s) +{ + if ((s->page!=state->page)) { + state_goto(state, s->page, 0); + draw_page(state, &stop_on_pause); + } +} +#endif + +/* + * need_redraw is set when the receiver changes page autonomously + */ +int need_redraw = 0 ; + static void main_loop(start_page) u_int start_page; @@ -636,8 +874,12 @@ u_int shift = 0; u_int control = 0; static struct render_state state; - static Cursor pen_curs; u_int prevpage; + Time last_button_press ; + + int got_command; + + static struct stream_list *str_list=NULL; memset(&state, 0, sizeof(struct render_state)); state.target = window; /*XXX*/ @@ -645,8 +887,19 @@ state.height = window_height; if (!pen_curs) { pen_curs = XCreateFontCursor(display, XC_pencil); - rakugaki_updatecolor(pen_curs); + rakugaki_updatecolor(pen_curs, 0); } + if (mcast_client) + client_init(); + else if (mcast_sender) + sender_init(); + + if (rx_addr) + rx_init(); + + if (tx_addr) + tx_init(start_page); + state_goto(&state, start_page, 0); #if 0 /* be conservative about first page... */ @@ -668,6 +921,9 @@ #endif while (1) { + struct render_state tstate; /* temporary state */ + int unpause=0; /* temporary flag for multicast tx */ + if (!t_start && 1 < state.page) t_start = time(NULL); if (rakugaki) @@ -676,7 +932,7 @@ XUndefineCursor(display, window); do { ; /*nothing*/ - } while (draw_one(&state, &e) == False); + } while (draw_one(&state, &e, &got_command) == False); if (t_fin) timebar(&state); @@ -702,13 +958,20 @@ if (wantreload()) { draw_reinit(&state); cleanup_file(); - load_file(mgp_fname); + load_the_file(mgp_fname); if (maxpage < state.page) state.page = 1; state_goto(&state, state.page, 1); /*repaint*/ + if (mcast_sender) + mcast_restart_sender(); } } + if (rx_addr && got_command) { + handle_pkt(&state, &str_list); + continue; + } + prevpage = state.page; switch (e.type) { case EnterNotify: @@ -734,71 +997,68 @@ break; case ButtonPress: - if (rakugaki && e.xany.window == window) { - rakugaki_update(&state, &e); - break; - } - + last_button_press = e.xbutton.time; + if (e.xany.window != window) { for (i = 1; i <= maxpage; i++) { if (e.xany.window == plwin[i]) { + need_redraw = 1 ; state_goto(&state, i, 0); pl_off(&state); break; } } - if (e.xany.window == window) { - if (e.xbutton.button == 1) { - struct render_state tstate; - tstate = state; - - if (!shift && state.cp - && state.cp->ct_op == CTL_PAUSE) { - state_next(&tstate); - } else if (state.page + 1 < maxpage) { - state_goto(&tstate, - state.page + 1, 0); - } else { - beep(); - break; - } - - if (memcmp(&state, &tstate, - sizeof(state)) != 0) { - state = tstate; + } else { /* main window */ + if (rakugaki) { + if (e.xbutton.button == 1 || + e.xbutton.button == 3 ) + rakugaki_update(&state, &e); } else { - /* cannot make a progress */ - beep(); - } + if (e.xbutton.button == 1) { + number = 1 ; + goto slide_forward ; } else if (e.xbutton.button == 3) { - if (state.page > 1) { - state_goto(&state, - state.page - 1, 0); - } else - beep(); + number = 1 ; + goto slide_backward ; + } } } break; - case ButtonRelease: + case ButtonRelease: /* XXX swap ? */ + last_button_press = e.xbutton.time - last_button_press ; + switch (e.xbutton.button) { + case 1 : /* pen */ + case 3 : /* eraser */ if (rakugaki && e.xany.window == window) rakugaki_update(&state, &e); - if (e.xbutton.button == 2) - goto rakugaki_toggle; break; - case MotionNotify: - if (!rakugaki) + case 2 : + if (rakugaki && last_button_press < 500) + raku_next_color(); + else + rakugaki_toggle(); + break; /* case 2 */ + + } /* end button switch */ break; - if (e.xany.window == window) + + case MotionNotify: + if (rakugaki && e.xany.window == window) rakugaki_update(&state, &e); break; case KeyPress: key = XLookupKeysym((XKeyEvent *)&e, 0); + if (!control && rakugaki && e.xany.window == window) { + rakugaki_update(&state, &e); + break; + } switch (key) { case XK_q: case XK_Escape: + free_stream_list(str_list); return; /*NOTREACHED*/ @@ -808,33 +1068,32 @@ case XK_Down: case XK_Next: case XK_space: - { - struct render_state tstate; +slide_forward: + /* this is forward, similar to left click */ + need_redraw = 1 ; tstate = state; if (number == 0) number = 1; - if (state.cp && state.cp->ct_op == CTL_PAUSE) - state_next(&tstate); - else if (state.page + number - <= maxpage) { - state_goto(&tstate, - state.page + number, 0); + if (state.cp && state.cp->ct_op == CTL_PAUSE) { + state_next(&state); + unpause= (tstate.page==state.page); + } else if (state.page + number <= maxpage) { + state_goto(&state, state.page + number, 0); } else { beep(); break; } - if (memcmp(&state, &tstate, - sizeof(state)) != 0) { - state = tstate; + if (memcmp(&state, &tstate, sizeof(state)) != 0) { + if (tx_addr && unpause) + tx_cmd(RC_UNPAUSE, 0, 0); } else { /* cannot make a progress */ beep(); } number = 0; break; - } case XK_b: case XK_k: @@ -843,37 +1102,22 @@ case XK_Prior: case XK_BackSpace: case XK_Delete: - if (number == 0) number = 1; - if (state.page - number >= 1) { - state_goto(&state, - state.page - number, 0); - } else +slide_backward: + need_redraw = 1 ; + if (number == 0) + number = 1; + if (state.page - number >= 1) + state_goto(&state, state.page - number, 0); + else beep(); number = 0; break; case XK_x: - if (shift) { - rakugaki_color++; - rakugaki_updatecolor(pen_curs); - XUndefineCursor(display, window); - XDefineCursor(display, window, - pen_curs); - XFlush(display); - } else { -rakugaki_toggle: - rakugaki = 1 - rakugaki; - rakugaki_x = rakugaki_y = -1; - - if (rakugaki) { - XDefineCursor(display, window, - pen_curs); - } else { - XUndefineCursor(display, - window); - } - XFlush(display); - } + if (shift) /* switch color */ + raku_next_color(); + else + rakugaki_toggle(); break; case XK_t: @@ -904,10 +1148,12 @@ pl_off(&state); draw_reinit(&state); cleanup_file(); - load_file(mgp_fname); + load_the_file(mgp_fname); if (maxpage < state.page) state.page = 1; state_goto(&state, state.page, 1); + if (mcast_sender) + mcast_restart_sender(); goto repaint; } break; @@ -915,8 +1161,7 @@ case XK_l: /* used to be control-L */ repaint:; { - struct ctrl *lastcp; - lastcp = state.cp; + struct ctrl *lastcp = state.cp; /* stop here */ state.repaint = 1; state_goto(&state, state.page, 1); draw_page(&state, lastcp); @@ -985,6 +1230,8 @@ if (state.repaint) break; + if (rx_addr) + break; /* XXX ??? */ /* compress expose event */ while (XEventsQueued(display, QueuedAfterReading) > 0) { XPeekEvent(display, &ahead); @@ -1018,6 +1265,7 @@ state.height = e.xconfigure.height; draw_reinit(&state); /*notify*/ lastcp = state.cp; + tx_cmd(RC_RESIZE, window_width, window_height); state_goto(&state, state.page, 1); draw_page(&state, lastcp); } @@ -1046,53 +1294,167 @@ } } + +static int rakugaki_x = -1; +static int rakugaki_y = -1; +static XColor rakugaki_back; +static char *rakugaki_forecolors[] = { + "red", "green", "blue", "yellow", "black", "white", +}; +static char *rakugaki_backcolors[] = { + "black", "black", "black", "black", "gray", "gray", +}; + +void +rakugaki_toggle() +{ + rakugaki = 1 - rakugaki; + rakugaki_x = rakugaki_y = -1; + + if (rakugaki) + XDefineCursor(display, window, pen_curs); + else + XUndefineCursor(display, window); + XFlush(display); +} + +/* + * set the pen (or eraser) color. Used by the sender and the remote rcvr. + */ + +void +raku_set_color(int pen, int new_color) +{ + int i ; + if (pen) { + /* Foreground color update */ + if (new_color >= 0) + rakugaki_updatecolor(pen_curs, new_color); + XSetForeground(display, gcpen, rakugaki_fore.pixel); /* XXX needed?*/ + if (window_height < 400) + i = 1 ; + else + i = 2 ; + } else { /* eraser */ + i = 1 + window_height/10 ; + XSetForeground(display, gcpen, back_color); + } + XSetLineAttributes(display, gcpen, + i, LineSolid, CapRound, JoinRound); +} + +/* + * This handles user input in drawing mode. + */ + static void rakugaki_update(state, e) struct render_state *state; XEvent *e; { - int x, y; + XMotionEvent *em = (XMotionEvent *)e; + static int x = -1, y = -1; + char buf[16]; + int len ; + KeySym key ; + static int fn = 0 ; /* nothing pressed */ - if (e->type == MotionNotify) { - XMotionEvent *em; - em = (XMotionEvent *)e; - x = em->x; y = em->y; - } else if (e->type == ButtonPress) { - XButtonPressedEvent *eb; - eb = (XButtonPressedEvent *)e; - x = eb->x; y = eb->y; - } else { - rakugaki_x = rakugaki_y = -1; + switch (e->type) { + case KeyPress : + len = XLookupString((XKeyEvent *)e, buf, sizeof(buf), &key, NULL); + + if (x == -1 || y == -1) { + x = em->x ; + y = em->y ; + } + switch(key) { + case XK_Escape: + tx_flush(); /* exit from text mode if any */ + rakugaki_toggle(); + break ; + + case XK_BackSpace: + case XK_Delete: + x -= (pl_fw*3/4) ; + break ; + + default: + XDrawString(display, state->target, gcpen, + x, y, buf, len); + tx_string(buf, len, x, y); + x += (pl_fw*3/4)*len ; + } return; + + case MotionNotify : + x = em->x; + y = em->y; + tx_point(x, y); + break ; + + case ButtonPress : + if (fn == 0) { /* acceptable. No buttons currently pressed */ + fn = e->xbutton.button ; + + /* XXX lr update this... */ + raku_set_color(fn == 1, -1 /* no color update */) ; + x = em->x; + y = em->y; + tx_color(fn == 1 ? rakugaki_color : -1 ); + tx_point(x, y); } + break ; + + case ButtonRelease : + if (e->xbutton.button == fn) { /* acceptable */ + x = em->x; + y = em->y; + tx_point(x, y); + tx_flush(); + fn = 0 ; + } + break ; + + default: + rakugaki_x = rakugaki_y = -1; /* reset coordinates */ + return; + } /* end switch */ - if (rakugaki_x < 0 || rakugaki_y < 0) + if (rakugaki_x < 0 ) XDrawRectangle(display, state->target, gcpen, x, y, 1, 1); + else + XDrawLine(display, state->target, gcpen,x, y, rakugaki_x, rakugaki_y); + if (e->type == ButtonRelease) + rakugaki_x = rakugaki_y = -1; else { - XDrawLine(display, state->target, gcpen, - x, y, - rakugaki_x, rakugaki_y); - XDrawLine(display, state->target, gcpen, - x + 1, y, - rakugaki_x + 1, rakugaki_y); - XDrawLine(display, state->target, gcpen, - x, y + 1, - rakugaki_x, rakugaki_y + 1); - XDrawLine(display, state->target, gcpen, - x + 1, y + 1, - rakugaki_x + 1, rakugaki_y + 1); - } rakugaki_x = x; rakugaki_y = y; } +} static void -rakugaki_updatecolor(cursor) +raku_next_color() +{ + rakugaki_updatecolor(pen_curs, -1); + XUndefineCursor(display, window); + XDefineCursor(display, window, pen_curs); + XFlush(display); + tx_flush(); + tx_color(rakugaki_color); +} + +void +rakugaki_updatecolor(cursor, newcolor) Cursor cursor; + int newcolor; { XColor junk; int maxidx; + if (newcolor >= 0) + rakugaki_color = newcolor ; + else + rakugaki_color++; maxidx = sizeof(rakugaki_forecolors)/sizeof(rakugaki_forecolors[0]); if (maxidx <= rakugaki_color) rakugaki_color %= maxidx; mgpm/patches/patch-ad100664 0 0 46036 6646634602 13320 0ustar rootwheel--- fileio.c.orig Thu Jan 7 18:16:25 1999 +++ fileio.c Tue Jan 12 12:49:32 1999 @@ -0,0 +1,773 @@ +/* net.c + + by Davide Devoti (davided@luna.it) and Luigi Rizzo (luigi@iet.unipi.it) + + File save/restore for mgp + * Copyright (c) 1998-1999 Universita` di Pisa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include +#include +#include "mgp.h" + +char *tmp_dir=NULL; + +/* + * ---- routines for loading/saving a file in internal format + * + + This is the file organizaton: + + STRING Magic string + I8 File version + + I8 number of pages + + For each page: + + page attributes (page_attribute) + + For each line in the page + list of directives + END_OF_LINE + + For each directive in the line + directive data (from page_control) + + * + * + */ + +/* we start wit a few miscellaneous utility functions */ + +static void +get_string(FILE *fp, char **dst) +{ +#define MAX_STRLEN 4096 + static char buf[MAX_STRLEN+1] ; + int index=0; + + for (;;) { + fread(buf+index, 1, 1, fp); + if (buf[index]=='\0' || index == MAX_STRLEN-1) + break ; + index++; + } + buf[index] = '\0' ; + *dst = strdup(buf) ; +} + +#define PUT_U32(i, fp) { u_int32_t d = htonl((u_int32_t)i) ; \ + fwrite( &d, sizeof(d), 1, fp); } + +#define PUT_U16(i, fp) { u_int16_t d = htons((u_int16_t)i) ; \ + fwrite( &d, sizeof(d), 1, fp); } + +#define PUT_U8(i, fp) { u_char d = i ; \ + fwrite( &d, 1, 1, fp); } + +#if (BYTE_ORDER == BIG_ENDIAN) +#error big endian +#define PUT_DOUBLE(i, fp) { double d = i ; \ + fwrite( &d, sizeof(d), 1, fp); } +#define GET_DOUBLE(i, fp) { double d ; \ + fread( &d, sizeof(d), 1, fp); i = d ; } +#endif + +#if (BYTE_ORDER == LITTLE_ENDIAN) +#define PUT_DOUBLE(i, fp) { u_int32_t d[2], tmp ; \ + *(double *)d = i ; \ + tmp = htonl(d[0]) ; d[0] = htonl(d[1]) ; d[1] = tmp ; \ + fwrite( d, sizeof(double), 1, fp); } + +#define GET_DOUBLE(i, fp) { u_int32_t d[2], tmp ; \ + fread( &d, sizeof(double), 1, fp); \ + tmp = ntohl(d[0]) ; d[0] = ntohl(d[1]) ; d[1] = tmp ; \ + i = *(double *)d ; } +#endif + +#define PUT_STRING(s, fp) { int l = strlen(s)+1 ; \ + fwrite((s), l, 1, fp); } + +#define GET_U8(i, fp) { u_int8_t d ;\ + fread(&d, sizeof(d), 1, fp); \ + i = d ; } + +#define GET_U16(i, fp) { u_int16_t d; \ + fread(&d, sizeof(d), 1, fp); \ + i = ntohs(d) ; } + +#define GET_U32(i, fp) { u_int32_t d; \ + fread(&d, sizeof(d), 1, fp); \ + i = ntohl(d) ; } + + +struct saved_list { + struct saved_list *next; + int is_new ; + char *fname; + char *newname; +} ; + +/* + * map_name is used to handle a list of files included by the presentation + * and their corresponding flat names. + * The list is initialized/cleaned up passing a NULL argument. Other + * calls return a pointer to the saved_list struct with both the + * original and the flat name. The flag is_new is set upon creation. + * The caller must clear it if the file has been saved. + */ +static +struct saved_list * +map_name(char *orig_fn) +{ + struct saved_list *tmp ; + char *s; + + static struct saved_list *list= NULL ; + static int i = 0 ; + + if (orig_fn == NULL) { + i = 0 ; + for ( ; list ; list = tmp ) { + tmp = list->next ; + free(list->fname); + free(list->newname); + free(list); + } + list = NULL ; + } else { + for (tmp = list ; tmp ; tmp = tmp->next) + if (!strcmp(tmp->fname, orig_fn)) + return tmp ; + tmp = (struct saved_list *)malloc(sizeof( *tmp )); + tmp->next = list ; + list = tmp ; + list->is_new = 1 ; + list->fname = strdup(orig_fn) ; + s = rindex(orig_fn, '.'); + if (s == NULL) + s = "" ; + if (!strcmp(s, ".gz") || !strcmp(s, ".GZ") || !strcmp(s, ".Z") ) { + /* compressed file... */ + char *s1 = s; + *s1 = '\0'; + s = rindex(orig_fn, '.'); + *s1 = '.' ; /* restore */ + if (s == NULL) /* keep old one */ + s = s1 ; + } + list->newname = malloc(6+strlen(s)); + sprintf(list->newname, "%05d%s", i++, s); + } + return list ; +} + +/* + * save_op() saves one opcode and related arguments. + */ +static void +save_op(struct ctrl *ct_temp, FILE *fp) +{ + int i ; + /* to get image files size */ + struct stat info; + + /* The next structure is to keep infos about which image files + * we have already put on file. + * Files are renamed to NNNN.type + */ + struct saved_list *map ; + + PUT_U8(ct_temp->ct_op, fp); + + switch (ct_temp->ct_op) { + case CTL_SIZE: + case CTL_HGAP: + PUT_DOUBLE(ct_temp->ctf_value, fp); + break; + + case CTL_VGAP: + case CTL_GAP: + case CTL_QUALITY: + case CTL_PAUSE: + PUT_U16(ct_temp->cti_value, fp); + break; + + case CTL_FORE: + case CTL_BACK: + case CTL_CCOLOR: + PUT_U32(ct_temp->ctl_value, fp); + break; + + case CTL_TAB: + PUT_U32(ct_temp->cti_value, fp ); + if (ct_temp->cti_value - 1 >= MAXTAB) + PUT_STRING(ct_temp->ctc_value, fp); + break; + + case CTL_FONT: + case CTL_DEFFONT: + case CTL_VFONT: + case CTL_TFONT: + case CTL_PREFIX: + case CTL_TABPREFIX: + case CTL_TEXT: + case CTL_VFCAP: + case CTL_TFDIR: + case CTL_TFONT0: + PUT_STRING(ct_temp->ctc_value, fp); + break; + + case CTL_XFONT2: + PUT_STRING(ct_temp->ctc2_value1, fp); + PUT_STRING(ct_temp->ctc2_value2, fp); + break; + + case CTL_BAR: + PUT_U32(ct_temp->ctb_color, fp); + PUT_U32(ct_temp->ctb_width, fp); + PUT_U32(ct_temp->ctb_start, fp); + PUT_U32(ct_temp->ctb_length, fp); + break; + + case CTL_IMPORT: + case CTL_IMAGE: + case CTL_BIMAGE: + map = map_name(ct_temp->ctm_fname); + PUT_STRING(map->newname, fp); + PUT_U32(ct_temp->ctm_numcolor, fp); + PUT_U32(ct_temp->ctm_ximagesize, fp); + PUT_U32(ct_temp->ctm_yimagesize, fp); + PUT_U32(ct_temp->ctm_zoomflag, fp); + + /* we have already put image infos on file ? */ + if (map->is_new == 0) + break ; + map->is_new = 0 ; + + /* we have to save now image file size + image file data*/ + + if (stat(ct_temp->ctm_fname, &info)==-1) { + fprintf(stderr, + "Error saving data about image %s\n", + ct_temp->ctm_fname); + cleanup(0); + } + + PUT_U32(info.st_size, fp); + + { +#define SAVE_BUFSIZE 65536 + char buffer[SAVE_BUFSIZE] ; + int res = info.st_size, sz = 0 ; + FILE *im_file = fopen(ct_temp->ctm_fname, "r"); + + for (; res > 0 ; res -= sz) { + sz = min(res, SAVE_BUFSIZE) ; + fread(buffer, sz, 1, im_file); + fwrite(buffer, sz, 1, fp); + } + fclose(im_file); + } + break; + + case CTL_BGRAD: + PUT_U32(ct_temp->ctd_numcolor, fp); + PUT_U32(ct_temp->ctd_dir, fp); + PUT_U32(ct_temp->ctd_width, fp); + PUT_U32(ct_temp->ctd_height, fp); + PUT_U32(ct_temp->ctd_zoomflag, fp); + PUT_U32(ct_temp->ctd_mode, fp); + PUT_U32(ct_temp->ctd_g_colors, fp); + + for (i=0; i < ct_temp->ctd_g_colors; i++) { + PUT_U32(ct_temp->ctd_colors[i]->r, fp); + PUT_U32(ct_temp->ctd_colors[i]->g, fp); + PUT_U32(ct_temp->ctd_colors[i]->b, fp); + PUT_U32(ct_temp->ctd_colors[i]->y, fp); + } + break; + + case CTL_SYSTEM: + case CTL_XSYSTEM: + PUT_U32(ct_temp->cta_argc, fp); + PUT_U32(ct_temp->cta_flag, fp); + for (i=0;icta_argc;i++) { + PUT_STRING(ct_temp->cta_argv[i], fp); + } + break; + + case CTL_ICON: + PUT_U32(ct_temp->ctic_color, fp); + PUT_U32(ct_temp->ctic_size, fp); + PUT_STRING(ct_temp->ctic_value, fp); + break; + + case CTL_DRAW: + PUT_U32(ct_temp->ctic_color, fp); + PUT_U32(ct_temp->ct_val.ctrl_drawcmd.cmd, fp); + PUT_U32(ct_temp->ct_val.ctrl_drawcmd.x0, fp); + PUT_U32(ct_temp->ct_val.ctrl_drawcmd.y0, fp); + PUT_U32(ct_temp->ct_val.ctrl_drawcmd.x1, fp); + PUT_U32(ct_temp->ct_val.ctrl_drawcmd.y1, fp); + break ; + + /* these do not need any parameter I hope... */ + case CTL_NOOP: + case CTL_LEFT: + case CTL_CENTER: + case CTL_CONT: + case CTL_LEFTFILL: + case CTL_PREFIXPOS: + case CTL_LINESTART: + case CTL_LINEEND: + break; + + default: + fprintf(stderr, "save: Unknown directive %d\n", + ct_temp->ct_op); + break ; + } +} + +/* +* the internal file format starts with the following magic string. +* The date code follows MGP-B- +*/ +#define MGP_BINARY_MAGIC_PREFIX "MGP-B-" +#define MGP_BINARY_MAGIC "MGP-B-19981222\n" + +void +save_binary_file(char *filename, char version) +{ + FILE *fp; + int i, page, line; + struct ctrl *ct_temp; + + char directory[1000]; + char curr_dir[1000]; + char *dir2=NULL; + + + fp=fopen(filename, "w"); + if (fp==NULL) { + fprintf(stderr, "Error opening internal data file %s\n", + filename); + cleanup(0); + } + + map_name(NULL); + + strcpy(directory, mgp_fname); + + if ((dir2=rindex(directory, '/'))!=NULL) { + /* we must cd to the directory that contains the current script file */ + getcwd(curr_dir, 1000); + dir2++; + *dir2=0; + chdir(directory); + } + + PUT_STRING(MGP_BINARY_MAGIC, fp); + PUT_U8(version, fp); + +#if 1 + /* XXX lr TODO: when supporting calls (and state stack). Save: + * default_control[], + * fontdef_control[], + * tab_control[] + */ + for (i = 0 ; i < 3 ; i++) { + struct ctrl **base ; + int lim ; + switch (i) { + case 0: + base = default_control ; + lim = MAXLINE ; + break ; + case 1: + base = fontdef_control ; + lim = MAXFONTDEF ; + break ; + default: /* really, 2 -- but this is to shut-up the compiler */ + base = tab_control ; + lim = MAXTAB+MAXSTYLE ; + break ; + } + for (line=0; line < lim ; line++) { + ct_temp = base[line] ; + if (ct_temp == NULL) + continue ; + PUT_U8( NEW_LINE, fp); + PUT_U8( line, fp); + for ( ; ct_temp ; ct_temp=ct_temp->ct_next ) + save_op(ct_temp, fp); + PUT_U8( END_OF_LINE, fp); + } + PUT_U8( END_OF_LINE, fp); + } +#endif + /* first we save the number of pages */ + + PUT_U8(NUMBER_OF_PAGES, fp); + PUT_U8(maxpage, fp); + for (page = 1 ; page<=maxpage ; page++) { + PUT_U8(NEW_PAGE, fp); + PUT_U32(page_attribute[page].pg_flag, fp); + PUT_U32(page_attribute[page].pg_linenum, fp); + + for (line=0; line<=page_attribute[page].pg_linenum; line++) { + for (ct_temp = page_control[page][line]; ct_temp ; + ct_temp=ct_temp->ct_next ) { + save_op(ct_temp, fp); + } + PUT_U8( END_OF_LINE, fp); + } + } /* end for page */ + fclose(fp); + + map_name(NULL); /* cleanup */ + + if (dir2!=NULL) + chdir(curr_dir); +} + + +static void +get_op(struct ctrl *ct_temp, FILE *fp) +{ + int i ; + char new_file_name[200]; + + switch (ct_temp->ct_op) { + /* these do not need any parameter I hope... */ + case CTL_NOOP: + case CTL_LEFT: + case CTL_CENTER: + case CTL_CONT: + case CTL_LEFTFILL: + case CTL_PREFIXPOS: + case CTL_LINESTART: + case CTL_LINEEND: + break; + + case CTL_SIZE: + case CTL_HGAP: + GET_DOUBLE(ct_temp->ctf_value, fp); + break; + + case CTL_VGAP: + case CTL_GAP: + case CTL_QUALITY: + case CTL_PAUSE: + GET_U16(ct_temp->cti_value, fp); + break; + + case CTL_FORE: + case CTL_BACK: + case CTL_CCOLOR: + GET_U32(ct_temp->ctl_value, fp); + break; + + case CTL_TAB: + GET_U32(ct_temp->cti_value, fp ); + if (ct_temp->cti_value - 1 >= MAXTAB) + get_string(fp, &(ct_temp->ctc_value) ); + break; + + case CTL_FONT: + case CTL_DEFFONT: + case CTL_VFONT: + case CTL_TFONT: + case CTL_PREFIX: + case CTL_TABPREFIX: + case CTL_TEXT: + case CTL_VFCAP: + case CTL_TFDIR: + case CTL_TFONT0: + get_string( fp, &(ct_temp->ctc_value) ); + break; + + case CTL_XFONT2: + get_string( fp, &(ct_temp->ctc2_value1) ); + get_string( fp, &(ct_temp->ctc2_value2) ); + break; + + case CTL_BAR: + GET_U32(ct_temp->ctb_color, fp); + GET_U32(ct_temp->ctb_width, fp); + GET_U32(ct_temp->ctb_start, fp); + GET_U32(ct_temp->ctb_length, fp); + break; + + case CTL_IMPORT: + case CTL_IMAGE: + case CTL_BIMAGE: + get_string( fp, &(ct_temp->ctm_fname) ); + GET_U32(ct_temp->ctm_numcolor, fp); + GET_U32(ct_temp->ctm_ximagesize, fp); + GET_U32(ct_temp->ctm_yimagesize, fp); + GET_U32(ct_temp->ctm_zoomflag, fp); + + if (index(ct_temp->ctm_fname, '/') ) { + /* All included files are remapped to unique names, + * so we do not allow a different path + */ + fprintf(stderr, "** warning, invalid file name %s\n", + ct_temp->ctm_fname); + free(ct_temp->ctm_fname); + ct_temp->ctm_fname = NULL ; /* XXX */ + break ; /* XXX lr maybe just terminate ? */ + } + sprintf(new_file_name, "%s/%s", + tmp_dir, ct_temp->ctm_fname); + /* does the file already exist ? */ + if (access(new_file_name, F_OK)!=0) { + /* + * read the image data and save to a temp file + */ +#define LOAD_BUFSIZE 65536 + char buffer[LOAD_BUFSIZE] ; + int fsize, sz = 0 ; + FILE *im_file = fopen(new_file_name, "w"); + + GET_U32(fsize, fp); + DDB(fprintf(stderr, "-- create %s size %d\n", + ct_temp->ctm_fname, fsize);) + + for (; fsize > 0 ; fsize -= sz) { + sz = min(fsize, LOAD_BUFSIZE) ; + fread(buffer, sz, 1, fp); + fwrite(buffer, sz, 1, im_file); + } + fclose(im_file); + } + + /* we must update the image file name + * to the temp file + */ + + free(ct_temp->ctm_fname); + ct_temp->ctm_fname = strdup(new_file_name); + break; + + case CTL_BGRAD: + GET_U32(ct_temp->ctd_numcolor, fp); + GET_U32(ct_temp->ctd_dir, fp); + GET_U32(ct_temp->ctd_width, fp); + GET_U32(ct_temp->ctd_height, fp); + GET_U32(ct_temp->ctd_zoomflag, fp); + GET_U32(ct_temp->ctd_mode, fp); + GET_U32(ct_temp->ctd_g_colors, fp); + + ct_temp->ctd_colors = + calloc(ct_temp->ctd_g_colors, sizeof(struct g_color *)); + for (i=0; i < ct_temp->ctd_g_colors; i++) { + ct_temp->ctd_colors[i] = + calloc(1, sizeof(struct g_color)); + GET_U32(ct_temp->ctd_colors[i]->r, fp); + GET_U32(ct_temp->ctd_colors[i]->g, fp); + GET_U32(ct_temp->ctd_colors[i]->b, fp); + GET_U32(ct_temp->ctd_colors[i]->y, fp); + } + break; + + case CTL_SYSTEM: + case CTL_XSYSTEM: + GET_U32(ct_temp->cta_argc, fp); + GET_U32(ct_temp->cta_flag, fp); + ct_temp->cta_argv = + calloc(ct_temp->cta_argc+1, sizeof(u_char *)); + ct_temp->cta_argv[ct_temp->cta_argc]=NULL; + for (i=0;icta_argc;i++) { + get_string(fp, &(ct_temp->cta_argv[i]) ); + } + break; + + case CTL_ICON: + GET_U32(ct_temp->ctic_color, fp); + GET_U32(ct_temp->ctic_size, fp); + get_string(fp, &(ct_temp->ctic_value) ); + break; + + case CTL_DRAW: + GET_U32(ct_temp->ctic_color, fp); + GET_U32(ct_temp->ct_val.ctrl_drawcmd.cmd, fp); + GET_U32(ct_temp->ct_val.ctrl_drawcmd.x0, fp); + GET_U32(ct_temp->ct_val.ctrl_drawcmd.y0, fp); + GET_U32(ct_temp->ct_val.ctrl_drawcmd.x1, fp); + GET_U32(ct_temp->ct_val.ctrl_drawcmd.y1, fp); + break ; + + default : + fprintf(stderr, "-- unk. directive %d\n", ct_temp->ct_op); + break; + } +} + +void +clean_internal_dir() +{ + char command_name[300]; + + if (tmp_dir) { + sprintf(command_name, "rm -r %s", tmp_dir); + system(command_name); + tmp_dir=NULL; + } +} + + +/* + * Load binary file. Returns 1 if success, 0 if failure + */ +int +load_binary_file(char *filename, char *version) +{ + FILE *fp; + int i, page, line; + struct ctrl *ct_temp, *ct_temp2; + unsigned char delim; + u_char *imbuff; + char v; + + fp=fopen(filename, "r"); + if (fp==NULL) + return 0 ; + + get_string(fp, &imbuff); + if (strcmp(imbuff, MGP_BINARY_MAGIC) ) { + DEB( fprintf(stderr, "-- unknown magic\n"); ) + fclose(fp); + free(imbuff); + return 0 ; + } + free(imbuff); + + GET_U8(v, fp); + if (version!=NULL) + *version=v; + +#if 1 + /* XXX lr TODO: when supporting calls (and state stack). Save: + * default_control[], + * fontdef_control[], + * tab_control[] + */ + for (i = 0 ; i < 3 ; i++) { + struct ctrl **base ; + int lim ; + switch (i) { + case 0: + base = default_control ; + lim = MAXLINE ; + break ; + case 1: + base = fontdef_control ; + lim = MAXFONTDEF ; + break ; + default : /* really 2, this just shuts up the compiler */ + base = tab_control ; + lim = MAXTAB+MAXSTYLE ; + break ; + } + for (;;) { + GET_U8(delim, fp) + if (delim == END_OF_LINE) + break ; + if (delim != NEW_LINE) { + fprintf(stderr, "-- protocol error in binary file\n"); + cleanup(0); + } + GET_U8(line, fp); + GET_U8(delim, fp); + while (delim != END_OF_LINE) { + ct_temp2=(struct ctrl *)malloc(sizeof(struct ctrl)); + if (base[line] == NULL) + base[line] = ct_temp2 ; + else + ct_temp->ct_next=ct_temp2; + ct_temp=ct_temp2; + ct_temp->ct_next=NULL; + ct_temp->ct_op = delim ; + get_op(ct_temp, fp); + GET_U8(delim, fp); + } /* end while delim */ + } + } +#endif + + GET_U8(delim, fp); + if (delim!=NUMBER_OF_PAGES) { + fprintf(stderr, + "Error reading internal data from file\n" + "Number of pages token expected and not found\n"); + fprintf(stderr, "delim = %d\n", delim); + cleanup(0); + } + + GET_U8(maxpage, fp); + + if (maxpage<1) { + fprintf(stderr, "Number of pages < 1 ???!!!????\n"); + cleanup(0); + } + + for (page = 1 ; page <= maxpage ; page++ ) { + GET_U8(delim, fp); + if (delim!=NEW_PAGE) { + fprintf(stderr, + "Error reading internal data from file\n" + "New page token expected and not found\n"); + cleanup(0); + } + GET_U32(page_attribute[page].pg_flag, fp); + GET_U32(page_attribute[page].pg_linenum, fp); + + for (line = 0 ; line<=page_attribute[page].pg_linenum ; line++) { + GET_U8(delim, fp); + while (delim != END_OF_LINE) { + ct_temp2=(struct ctrl *)malloc(sizeof(struct ctrl)); + if (page_control[page][line] == NULL) + page_control[page][line] = ct_temp2 ; + else + ct_temp->ct_next=ct_temp2; + ct_temp=ct_temp2; + ct_temp->ct_next=NULL; + ct_temp->ct_op = delim ; + ct_temp->ct_page = page ; /* never used, anyways */ + get_op(ct_temp, fp); + GET_U8(delim, fp); + } /* end while delim */ + } /* end for line */ + } /* end for page */ + fclose(fp); + return 1 ; +} + +/* --- end of file --- */ mgpm/patches/patch-bc100644 423 0 1714 6637210771 13464 0ustar luigiwheel--- globals.c.orig Sat Sep 26 17:32:33 1998 +++ globals.c Sun Dec 20 15:40:22 1998 @@ -36,11 +36,9 @@ * (hate to define these in two places, mgp.c and print.c, I've made * a separate file) */ -u_char *page_data[MAXPAGE][MAXLINE]; struct ctrl *page_control[MAXPAGE][MAXLINE]; struct ctrl *default_control[MAXLINE]; struct ctrl *tab_control[MAXTAB+MAXSTYLE]; -struct ctrl *init_control[MAXLINE]; struct ctrl *fontdef_control[MAXFONTDEF]; struct page_attribute page_attribute[MAXPAGE]; @@ -71,6 +69,7 @@ u_long fore_color; u_long back_color; u_long ctrl_color; +u_long draw_linewidth; u_int b_quality = DEFAULT_BQUALITY; u_int quality_flag = 0; @@ -130,5 +129,8 @@ /*CTL*/ { CTL_TFONT0, T_STR, "tfont0", 6 }, /*CTL*/ { CTL_EMBED, T_STR, "embed", 5 }, /*CTL*/ { CTL_ENDEMBED, T_VOID, "endembed", 8 }, +/*CTL*/ { CTL_CALL, T_SP, "call", 4 }, +/*CTL*/ { CTL_DRAW, T_SP, "draw", 4 }, +/*CTL*/ { CTL_IMPORT, T_SP, "import", 6 }, { 0, NULL, 0 }, }; mgpm/patches/patch-bd100644 423 0 4166 6637753205 13475 0ustar luigiwheel--- grammar.y.orig Mon Nov 16 14:04:34 1998 +++ grammar.y Mon Dec 21 00:24:48 1998 @@ -457,6 +457,47 @@ return ct; } +static struct _map { + drawcmds cmd; + char *name; +} _draw_cmds[] = { + {DC_LINE, "line" }, + {DC_RECT, "rect" }, + {DC_FRAME, "frame" }, + {DC_NONE, NULL } +} ; + +static struct ctrl * +gen_draw(n, color, x0, y0, x1, y1) + char *n; + char *color; + int x0, y0, x1, y1; +{ + struct ctrl *ct; + struct _map *p ; + + if (!(ct = ctlalloc1(CTL_DRAW))) { + yyerror("cannot allocate node (op=DRAW)"); + return ct; + } + for (p = _draw_cmds; p->cmd != DC_NONE ; p++) + if (!strcmp(p->name, n)) + break ; + if (p->cmd == DC_NONE) { + yyerror("invalid draw cmd %s", n); + return NULL ; + } + ct->ct_val.ctrl_drawcmd.cmd = p->cmd; + ct->ct_val.ctrl_drawcmd.x0 = x0; + ct->ct_val.ctrl_drawcmd.y0 = y0; + ct->ct_val.ctrl_drawcmd.x1 = x1; + ct->ct_val.ctrl_drawcmd.y1 = y1; + + if (get_color(color, &ct->ct_val.ctrl_drawcmd.color) < 0) + yyerror("cannot allocate color %s", color); + return ct; +} + static struct ctrl * gen_icon(n, color, siz) char *n; @@ -623,6 +664,7 @@ %token KW_QUALITY KW_ICON KW_LEFTFILL KW_XSYSTEM KW_VFCAP KW_TFONT KW_TFDIR %token KW_DEFFONT KW_FONT KW_TFONT0 KW_EMBED KW_ENDEMBED KW_NEWIMAGE %token KW_CHARSET +%token KW_DRAW KW_IMPORT %type toplevel %type line defaultline tabline shellline deffontline @@ -738,11 +780,12 @@ $$ = gen_str2(CTL_XFONT2, p, "iso8859-1"); } | KW_XFONT STRorID STRorID - { char *p; + { check_xfont($2, $3); /* lexical check */ $$ = gen_str2(CTL_XFONT2, $2, $3); } | KW_BIMAGE STRorID { $$ = gen_str(CTL_BIMAGE, $2); } + | KW_IMPORT STRorID { $$ = gen_str(CTL_IMPORT, $2); } | KW_VFONT STRorID { #ifdef VFLIB $$ = gen_str(CTL_VFONT, $2); @@ -810,6 +853,10 @@ { $$ = gen_icon($2, $3, $4); } | KW_ICON ID STRorID NUM { $$ = gen_icon($2, $3, $4); } + | KW_ICON STR STRorID NUM NUM NUM NUM + { $$ = gen_draw($2, $3, $4, $5, $6, $7); } + | KW_ICON ID STRorID NUM NUM NUM NUM + { $$ = gen_draw($2, $3, $4, $5, $6, $7); } | KW_VFCAP STR { #ifdef VFLIB $$ = gen_str(CTL_VFCAP, $2); mgpm/patches/patch-cc100644 423 0 4765 6637753257 13511 0ustar luigiwheel--- parse.c.orig Mon Nov 9 06:28:19 1998 +++ parse.c Mon Dec 21 00:26:01 1998 @@ -668,7 +667,6 @@ struct ctrl **ch; struct ctrl *cp; struct ctrl *cp1; - struct ctrl *cp2; /* * add CTL_PAUSE to the last line of a page. @@ -945,7 +943,11 @@ for (l = 0; l <= line; l++) { ch = &page_control[page][l]; if (default_control[l]) { +#ifdef DO_CALL + ctlinsert(ch, ctlcall(default_control[l])); +#else ctlinsert(ch, ctlcopy(default_control[l])); +#endif } } } @@ -963,7 +965,7 @@ /* * add CTL_LINEEND and CTL_LINESTART to each lines that contain - * CTL_TEXT/CTL_IMAGE/CTL_BAR/CTL_ICON. + * CTL_TEXT/CTL_IMAGE/CTL_BAR/CTL_ICON/CTL_DRAW. * note that we must carefully handle CTL_CONT. */ { @@ -979,6 +981,7 @@ if (cp->ct_op == CTL_TEXT || cp->ct_op == CTL_IMAGE || cp->ct_op == CTL_BAR + || cp->ct_op == CTL_DRAW || cp->ct_op == CTL_ICON) { textseen++; break; @@ -1010,6 +1013,7 @@ if ((*ch)->ct_op == CTL_TEXT || (*ch)->ct_op == CTL_IMAGE || (*ch)->ct_op == CTL_BAR + || (*ch)->ct_op == CTL_DRAW || (*ch)->ct_op == CTL_ICON) { break; } @@ -1041,6 +1045,7 @@ if (cp1->ct_op == CTL_TEXT || cp1->ct_op == CTL_IMAGE || cp1->ct_op == CTL_BAR + || cp1->ct_op == CTL_DRAW || cp1->ct_op == CTL_ICON) { cp2 = cp1; } @@ -1100,7 +1105,11 @@ if (tab_control[tab_depth]) { ctlinsert(&cp1->ct_next, +#ifdef DO_CALL + ctlcall(tab_control[tab_depth])); +#else ctlcopy(tab_control[tab_depth])); +#endif } } /* special: style escape */ @@ -1133,7 +1142,11 @@ p0 + 1); } else { ctlinsert(&cp1->ct_next, +#ifdef DO_CALL + ctlcall(tab_control[i]->ct_next)); +#else ctlcopy(tab_control[i]->ct_next)); +#endif } free(tmp); } @@ -1155,6 +1168,7 @@ for (cp = cp1; cp->ct_next; cp = cp->ct_next) { if (cp->ct_next->ct_op == CTL_TEXT || cp->ct_next->ct_op == CTL_IMAGE + || cp->ct_next->ct_op == CTL_DRAW || cp->ct_next->ct_op == CTL_ICON) { break; } @@ -1450,6 +1464,14 @@ return dst0; } +struct ctrl * +ctlcall(struct ctrl *target) +{ + struct ctrl *retval = ctlalloc1(CTL_CALL); + retval->ctc_value = (u_char *)target ; + return retval ; +} + int ctlcmp(a, b) struct ctrl *a; @@ -1461,8 +1483,6 @@ assert(b); if (a->ct_op != b->ct_op) - return 1; - if (a->ct_flag != b->ct_flag) return 1; switch (ctl_words[a->ct_op].ctl_vtype) { mgpm/patches/patch-ah100664 0 0 74236 6646634622 13331 0ustar rootwheel--- cmdio.c.orig Thu Jan 7 18:16:26 1999 +++ cmdio.c Tue Jan 12 12:55:10 1999 @@ -0,0 +1,1184 @@ +/* cmdio.c + + by Davide Devoti (davided@luna.it) and Luigi Rizzo (luigi@iet.unipi.it) + + Control stream for mgpm + + * Copyright (c) 1998-99 Universita` di Pisa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include "mgp.h" + +time_t resend_time ; +static int resend_delta ; + +u_int16_t sender_version=0; + /* sent file version, incremented each time the file is reloaded */ + +u_int16_t current_sender_version; + +extern char *tmp_dir; + +char *rx_addr = NULL ; /* address to receive mgp commands */ +char *tx_addr = NULL ; /* address to send commands */ + +/* the socket to send/receive presentation commands */ +int rx_socket; +static int tx_socket; + +/* added to support synchronization packets transfer */ + +/* The first byte in the last sent packet */ + +static char rx_pkt[MAX_SYNC_PKT_SIZE]; +static int rx_pkt_sz; + + +/* + * returns the size of a command stored in memory (net-order). + * We pass the pointer to the first byte and assume there is room + * for that and the essential parameter(s). + */ +static int +cmd_size(void *p) +{ + int size = 1; + u_int16_t count; + + switch (*(char *)p) { + case RC_REPAINT: + case RC_UNPAUSE: + size = 1; + break; + case RC_GOTO_PAGE: + size = 2; + break; + case RC_RESIZE: + size = 5; + break; + case RC_TEXT: + memcpy(&count, p+1, 2); + count = ntohs(count); + size = 8+count; + break; + case RC_DRAW: + memcpy(&count, p+1, 2); + count = ntohs(count); + size = 8+(count-1)*2; + break; + } + + return size; +} + + +struct tx_segment { + struct tx_segment *next ; + int len; + int seq; /* actually a duplicate of what is in the state... */ + struct net_pkt pkt ; +} ; + +/* tx infos about current page packets */ +struct tx_state { + u_int32_t source_id; /* source id of current command sender */ + struct tx_segment *head, *curr ; +}; + +static struct tx_state tx_infos; + +static void +fill_rtp_header(rtphdr *h) +{ + struct timeval t ; + + h->v = RTP_VERSION; + h->p = RTP_PAD; + h->x = RTP_EXTENSION; + h->cc= RTP_CSRC; + h->m = RTP_MARKER; + h->pt = 0 /* RTP_PAYLOAD_TYPE */ ; + + h->seq = htons( ntohs(h->seq) + 1 ); + h->ssrc= htonl(tx_infos.source_id); + gettimeofday(&t, NULL); + h->timestamp = (t.tv_sec * 8000 + t.tv_usec/125) & 0xffffffff ; + h->timestamp = htonl(h->timestamp) ; + + /* XXX lr not yet finished */ +} + +/* + * these structures hold the info for pending commands etc. + */ + + +static struct cmdbuf { + char cmd ; /* set to the pending command */ + u_char page ; + int len ; + int timeout ; + char color ; + + char buf[MAX_TEXT_CHARS+1] ; + u_int16_t x[MAX_DRAW_POINTS]; + u_int16_t y[MAX_DRAW_POINTS] ; +} cmdbuf ; + +static int +last_cmd_size() +{ + switch (cmdbuf.cmd) { + default : + return 1 ; + + case RC_GOTO_PAGE : + return 2 ; + + case RC_DRAW : + return 6 + 2 * cmdbuf.len ; + + case RC_TEXT : + return 8 + cmdbuf.len ; + + case RC_RESIZE : + return 5 ; + } +} + +/* + * tx_make_room (called with l > 0) does the following: + * + the current packet is shifted to make room to the new command; + * + if there is no overlap with previous pkt, make a copy of the + * packet + * + the ctrl_hdr is updated to reflect the initial status. + */ + +static void +tx_make_room(int l) +{ + struct tx_segment *head = tx_infos.head ; + struct tx_segment *next = tx_infos.head->next ; + ctrl_hdr s ; + u_char *d ; + + /* + * first, advance pointers and update a copy of the + * ctrl_hdr + */ + memcpy(&s, &(head->pkt.s), sizeof(s) ); + d = head->pkt.data ; + while (d - head->pkt.data < l) { + u_int16_t n16 ; + switch(*d++) { + default : + break ; + + case RC_GOTO_PAGE : + n16 = *d++ ; + s.page = htons(n16); + break ; + + case RC_DRAW : + memcpy(&n16, d, 2); + n16 = ntohs(n16); + d += 5 + 2 * n16 ; + break ; + + case RC_TEXT : + memcpy(&n16, d, 2); + n16 = ntohs(n16); + d += 7 + n16 ; + break ; + + case RC_RESIZE : + memcpy(&s.width, d, 2); + memcpy(&s.height, d+2, 2); + d += 4 ; + break ; + } + } + l = d - head->pkt.data ; + s.seq = htonl( ntohl(s.seq) + l ) ; + + if (next == NULL || /* no next pkt */ + (head->seq + l > next->seq + next->len) ) { /* no overlap */ + head = malloc( sizeof( *head ) ) ; + bcopy(tx_infos.head, head, sizeof( *head ) ); + head->next = tx_infos.head ; + tx_infos.head = head ; + } + /* + * update pointers and current packet. + */ + bcopy( &s, &(head->pkt.s), sizeof(s) ); + bcopy( d, head->pkt.data, head->len - l ); + head->len -= l ; + head->seq += l ; +} + +/* + * this function copies a pending command into the buffer + * and transmits a pkt. + */ +void +tx_flush() +{ + u_char *dst, *old ; + u_int16_t net_short ; + int i ; + + if (cmdbuf.cmd == RC_NONE) + return ; + + DEB(fprintf(stderr, "== tx_flush\n");) + i = last_cmd_size(); + + if (i + tx_infos.head->len > PAYLOAD_LEN ) + tx_make_room(tx_infos.head->len + i - PAYLOAD_LEN); + + fill_rtp_header(&(tx_infos.head->pkt.r)); + + dst = old = tx_infos.head->pkt.data + tx_infos.head->len ; + + *dst++ = cmdbuf.cmd ; /* store command opcode */ + switch (cmdbuf.cmd) { + default: + fprintf(stderr, "flushing cmd %d\n", cmdbuf.cmd); + return ; + + case RC_REPAINT: + case RC_UNPAUSE: + /* nothing to do in these cases */ + break; + + case RC_GOTO_PAGE: + memcpy(dst++, &cmdbuf.page, 1); + break; + + case RC_RESIZE: + net_short = htons(cmdbuf.x[0]); + memcpy(dst, &net_short, 2); + dst +=2; + + net_short = htons(cmdbuf.y[0]); + memcpy(dst, &net_short, 2); + dst +=2; + + break; + + case RC_DRAW: + DEB(fprintf(stderr, "flushing RC_DRAW %d points\n", cmdbuf.len);) + /* + * format of DRAW commands: + * ofs len content + * 0 1 RC_DRAW + * 1 2 # points + * 3 1 color + * 4 2 x0 + * 6 2 y0 + * 8 1 x1-x0 \___ n-1 times + * 9 1 y1-y0 / + * + * Note: the encoding is not very safe nor very compact. + */ + net_short=htons(cmdbuf.len); + memcpy(dst, &net_short, 2); + dst += 2 ; + + memcpy(dst++, &(cmdbuf.color), 1); + + /* now we save the coordinates of the first point */ + + net_short = htons(cmdbuf.x[0]); + memcpy(dst, &net_short, 2); + dst +=2; + + net_short = htons(cmdbuf.y[0]); + memcpy(dst, &net_short, 2); + dst +=2; + + for (i = 1; i < cmdbuf.len; i++) { + char diff ; +#if 0 + int dx, dy ; + dx = cmdbuf.x[i] - cmdbuf.x[i-1] ; + dy = cmdbuf.y[i] - cmdbuf.y[i-1] ; + fprintf(stderr, ".. mov %8.3f\n", + (double)sqrt( dx*dx + dy*dy ) ); +#endif + /* XXX lr TODO: check overflows */ + diff=(char)(cmdbuf.x[i] - cmdbuf.x[i-1]); + memcpy(dst++, &diff, 1); + diff=(char)(cmdbuf.y[i] - cmdbuf.y[i-1]); + memcpy(dst++, &diff, 1); + } + break; + + case RC_TEXT: + cmdbuf.buf[cmdbuf.len] = '\0'; + DEB(fprintf(stderr, "flushing RC_TXT at %d,%d: <%s>\n", + cmdbuf.x[0], cmdbuf.y[0], cmdbuf.buf);) + /* + * format of TEXT commands: + * ofs len content + * 0 1 RC_TEXT + * 1 2 # chars + * 3 1 color + * 4 2 x + * 6 2 y + * 8 1 char code -- n times + */ + + net_short = htons(cmdbuf.len); + memcpy(dst, &net_short, 2); + dst += 2 ; + + memcpy(dst++, &(cmdbuf.color), 1); + + net_short=htons(cmdbuf.x[0]); + memcpy(dst, &net_short, 2); + dst+=2; + + net_short=htons(cmdbuf.y[0]); + memcpy(dst, &net_short, 2); + dst+=2; + + memcpy(dst, cmdbuf.buf , cmdbuf.len); + dst += cmdbuf.len ; + break; + + } + cmdbuf.cmd = RC_NONE ; + cmdbuf.len = 0 ; + cmdbuf.x[0] = cmdbuf.y[0] = 0 ; + + tx_infos.head->len += (dst - old) ; + + DEB(fprintf(stderr, "++ send <%d, %d>\n", + tx_infos.head->seq, tx_infos.head->seq + tx_infos.head->len );) + send(tx_socket, &(tx_infos.head->pkt), + tx_infos.head->len + PAYLOAD_OFS, 0); + resend_delta = 2 ; + resend_time = resend_delta + time(NULL); +} + +/* + * change color + */ +void +tx_color(int color) +{ + tx_flush(); + cmdbuf.color = color ; +} + +/* + * add a new coordinate pair + */ +void +tx_point(int x, int y) +{ + if (tx_addr == NULL) + return ; + if (cmdbuf.cmd != RC_NONE && + (cmdbuf.cmd != RC_DRAW || cmdbuf.len == MAX_DRAW_POINTS)) { + tx_flush(); + } + cmdbuf.cmd = RC_DRAW ; + /* + * implement a threshold to avoid too small movements + */ + if (cmdbuf.len > 0) { + int dx = x - cmdbuf.x[cmdbuf.len - 1]; + int dy = y - cmdbuf.y[cmdbuf.len - 1]; + + if (dx*dx + dy*dy < 8) { + DEB(fprintf(stderr, "-- ignore < %d, %d >\n", dx, dy);) + return ; /* ignore point */ + } + } + cmdbuf.x[cmdbuf.len] = x; + cmdbuf.y[cmdbuf.len] = y; + cmdbuf.len ++ ; +} + +/* + * send a string. + */ +void +tx_string(char *string, int len, int x, int y) +{ + int l1 = len ; + + if (tx_addr == NULL) + return ; + if (cmdbuf.cmd == RC_NONE) + goto good ; + if (cmdbuf.cmd == RC_TEXT && cmdbuf.len < MAX_TEXT_CHARS) + goto good ; + tx_flush(); /* all other cases... */ +good: + if (cmdbuf.len == 0) { + cmdbuf.x[0] = x ; + cmdbuf.y[0] = y ; + } + while (len > 0) { + l1 = len ; + if (l1 > MAX_TEXT_CHARS - cmdbuf.len) + l1 = MAX_TEXT_CHARS - cmdbuf.len ; + cmdbuf.cmd = RC_TEXT ; + memcpy(cmdbuf.buf + cmdbuf.len, string, l1 ); + cmdbuf.len += l1 ; + string += l1 ; + len -= l1 ; + if (cmdbuf.len == MAX_TEXT_CHARS) + tx_flush(); + } +} + +/* + * generic command with 0, 1 or 2 parameters + */ +void +tx_cmd(char cmd, int x, int y) +{ + if (tx_addr == NULL) + return ; + + tx_flush(); + cmdbuf.cmd = cmd ; + switch(cmd) { + case RC_REPAINT: + case RC_UNPAUSE: + /* nothing to do in these cases */ + break; + + case RC_GOTO_PAGE: + cmdbuf.page = x ; + break; + + case RC_RESIZE: + cmdbuf.x[0] = window_width ; + cmdbuf.y[0] = window_height ; + break; + + } + tx_flush(); +} + +/* + * this is the function we call each RESEND_INTERVAL seconds + * to resend last sync packet + */ + +void +mcast_resend() +{ + tx_infos.curr = tx_infos.curr->next ; + if (tx_infos.curr == NULL) + tx_infos.curr = tx_infos.head ; + DEB(fprintf(stderr, "++ rxmt [%d,%d[\n", + tx_infos.curr->seq, tx_infos.curr->seq + tx_infos.curr->len);) + send(tx_socket, &(tx_infos.curr->pkt), + tx_infos.curr->len + PAYLOAD_OFS, 0); + + resend_delta = (resend_delta *3) / 2 ; + if (resend_delta > 10) + resend_delta = 10 ; + resend_time += resend_delta ; +} + +/* + * init transmitter data structures, including (static) buffers + * for local actions + */ +void +tx_init(int start_page) +{ + char tmpaddr[256]; + u_int16_t port1; + u_int32_t addr1; + int rate; + int ttl=10; + + struct tx_segment *p = malloc( sizeof(*p) ); + + bzero(p, sizeof (*p) ); + p->next = NULL ; + p->len = 0 ; + p->seq = 0 ; + p->pkt.s.page = htons(start_page) ; + p->pkt.s.width = htons(window_width); + p->pkt.s.height = htons(window_height); + p->pkt.s.seq = htons(0); + + tx_infos.head = tx_infos.curr = p ; + + /* sync packets data init */ + + srand(time(NULL)); + tx_infos.source_id = rand(); + + if (parse_addr(tx_addr, tmpaddr, sizeof(tmpaddr), + &port1, &ttl, &rate)<0) { + fprintf(stderr, "Error parsing multicast sync address\n"); + cleanup(0); + } + + addr1 = inet_addr(tmpaddr); + + if (tx_addr == rmdp_addr) { + DEB(fprintf(stderr, "XX implicit -s option\n");) + addr1 = htonl( ntohl(addr1) - 1 ) ; + } + if (!IN_CLASSD(ntohl(addr1))) { + fprintf(stderr, "Error -- non-multicast addr for control stream\n"); + cleanup(0); + } + + port1=htons(port1); + + if ((tx_socket = openssock(addr1, port1, ttl, 0))<0) { + fprintf(stderr, "Error opening tx cmd socket\n"); + cleanup(0); + } +} + +/*------------------------------------------------------------*/ + +/* + * receiver routines + */ + +char mcast_client_start_page[]= + "%page\n%nodefault\n%fore \"yellow\", size 7, back \"darkblue\"\n\n" + "\n%center, fore \"yellow\"\nMagicPoint Multicast Receiver\n" + "\n%size 5\nLoading presentation, Wait Please !\n" + "\n\nPress any key to abort and quit ...\n" + "%page\n%fore \"yellow\", size 7, back \"red\"" + "\n%center\n\n\n\n\nError receiving data\n" + "%page\n%fore \"yellow\", size 7, back \"green\"\n\n\n" + "\n%center, fore \"yellow\"\nMagicPoint Multicast Receiver\n" + "\n%size 5, fore \"aquamarine\"" + "\nFile has been modified\n\n%size 5\nReloading ....\n" + "\n%size 5\nWait Please !\n" + "\n\nPress any key to abort and quit ...\n"; + + +/* + * while the client is waiting to load a new file from + * the sender, show a default file, eother start.mgp in the + * current directory, or one created for the purpose. + */ +void +load_client_startup_file() +{ + if (access("start.mgp", F_OK) == 0) { + load_file("start.mgp"); + } else { + /* we must create a temp intro mgp file */ + FILE *fd; + char fname[500]; + + sprintf(fname, "%s/mgp_start_temp.mgp", tmp_dir); + fd=fopen(fname, "w"); + fprintf(stderr, "-- open %s returns %x\n", fname, fd); + + fwrite(mcast_client_start_page, + strlen(mcast_client_start_page), 1, fd); + fclose(fd); + load_file(fname); + } +} + +/* + * while the client is waiting to load a new file from + * the sender, show a default file, eother start.mgp in the + * current directory, or one created for the purpose. + */ +static void +client_startup(struct render_state *state, int new_page) +{ + u_char cmd[1024]; + + current_sender_version = sender_version; + draw_reinit(state); + cleanup_file(); + sprintf(cmd, "rm %s/*", tmp_dir); + system(cmd); + + load_client_startup_file(); + + memset(state, 0, sizeof(struct render_state)); + state->target = window; /*XXX*/ + state->width = window_width; + state->height = window_height; + state_goto(state, 3, 0); + draw_page(state, &stop_on_pause); + mcast_receiver(state); + state_goto(state, new_page, 1); +} + +void +rx_init() +{ + char tmpaddr[256]; + u_int16_t port1; + u_int32_t addr1; + int ttl, rate ; + + /* sync packets data init */ + memset(rx_pkt, 0, sizeof(rx_pkt)); + + if (parse_addr(rx_addr, tmpaddr,sizeof(tmpaddr), + &port1, &ttl, &rate)<0) { + fprintf(stderr, "Error parsing multicast sync address\n"); + cleanup(0); + } + + addr1 = inet_addr(tmpaddr); + + if (rx_addr == rmdp_addr) { + DEB(fprintf(stderr, "XX implicit -r option\n");) + addr1 = htonl( ntohl(addr1) - 1 ) ; + } + if (!IN_CLASSD(ntohl(addr1))) { + fprintf(stderr, "Error -- non-multicast addr for control stream\n"); + cleanup(0); + } + + port1 = htons(port1); + + if ( (rx_socket = openrsock(addr1, &port1)) < 0 ) { + fprintf(stderr, "Error opening rx sync socket\n"); + cleanup(0); + } +} + +/* + * rx_poll polls the receive socket, returns 1 and reads a pkt if + * one is available + */ +int +rx_poll() +{ + fd_set fds ; + struct timeval tout; + struct sockaddr_in from_addr; + int fromlen=sizeof(struct sockaddr_in); + + if (rx_addr) { + FD_ZERO(&fds); + FD_SET(rx_socket, &fds); + tout.tv_sec = tout.tv_usec = 0; + if ( select(rx_socket+1, &fds, NULL, NULL, &tout) > 0 && + (rx_pkt_sz = recvfrom(rx_socket, rx_pkt, MAX_SYNC_PKT_SIZE, + 0, (struct sockaddr *)&from_addr, &fromlen)) > 0 ) + return 1 ; + } + return 0 ; +} + +static void +rx_stream_init(struct rx_stream *str) +{ + bzero(str, sizeof(*str) ); + str->first = NULL ; + str->s_curr.vers = current_sender_version; +} + +/* + * reassemby of newly received packet. New segment is a service + * routine, seg_reass() is the good one. It returns 1 if + * the new segment modifies the last segment. + */ +static struct rx_segment * +new_segment(ctrl_hdr *s, int len, void *data) +{ + struct rx_segment *rxs = malloc(sizeof(*rxs)); + + memcpy(&(rxs->s), s, sizeof(*s) ); + rxs->len = len ; + rxs->next = NULL; + rxs->data = malloc(len) ; + memcpy(rxs->data, data, len); + return rxs; +} + +extern int need_redraw; + +static int +seg_reass(struct rx_stream *str) +{ + struct net_pkt *pkt = (struct net_pkt *)rx_pkt ; + int len = rx_pkt_sz - PAYLOAD_OFS ; + ctrl_hdr s ; + int n1, n2 ; /* boundaries of new segment */ + u_int32_t last_goto = 0, next_seq = 0 ; /* used to detect a change */ + int last_len = -1 ; + struct rx_segment *prev, *seg; + + if (str->last) { + /* make a copy of the boundaries of the last segment, + * in case i get an update + */ + next_seq = str->last->s.seq + str->last->len ; + last_goto = str->last_goto ; + last_len = str->last->len ; + } + /* copy the header in s and convert to host order */ + memcpy(&s, rx_pkt + sizeof(rtphdr), sizeof(s) ); + s.vers = ntohs(s.vers); + s.page = ntohs(s.page); + s.width = ntohs(s.width); + s.height = ntohs(s.height); + s.seq = ntohl(s.seq); + if (str->first == NULL) { + str->first = str->last = new_segment(&s, len, pkt->data) ; + str->s_curr = s ; + str->parse_start = str->s_curr.seq ; + } + n1 = s.seq ; + n2 = n1 + len ; + /* + * try to merge segments. (s1,s2) is in the list, (seq, seq+len) + * is the new one. There are 6 cases depending on the relative + * positions. After modifying one segment, we should check if it + * merges with the next ones. + * + * s1,s2 n1,n2 action + * [--- new segment ---] + * A: [---] next + * B: [-------]------------------] merge, final + * C: [---------------------------]]] break; + * D: [[[-------------]] merge, final + * E: [[[-------------------] merge, final (break?) + * F: [---] add, final + */ + + DEB(fprintf(stderr, "first; seg ; seg=seg->next ) + fprintf(stderr, "[%d,%d] ", seg->s.seq, seg->s.seq + seg->len); + fprintf(stderr, ">\n");) + + for (prev = NULL, seg = str->first; seg ; prev=seg, seg=seg->next ) { + struct rx_segment *tmp ; + int s1 = seg->s.seq ; + int s2 = s1 + seg->len ; + + DEB(fprintf(stderr, "** compare old: [%5d,%5d] new [%5d,%5d]\n", + s1, s2, n1, n2);) + if (s1 < n1) { + if (s2 < n1) {/* case A. Nothing to do, next... */ + DEB(fprintf(stderr, "case A: old: [%5d,%5d] new [%5d,%5d]\n", + s1, s2, n1, n2);) + if (seg->next != NULL) + continue ; + else { /* there is nothing after... */ + str->last = seg->next = new_segment(&s, len, pkt->data) ; + break ; + } + } else if (s2 < n2) {/* case B. Merge data, keep old hdr */ + DEB(fprintf(stderr, "case B: old: [%5d,%5d] new [%5d,%5d]\n", + s1, s2, n1, n2);) + seg->len = n2 - s1 ; + /* merge data */ + seg->data = realloc(seg->data, seg->len); + memcpy(seg->data + s2 - s1, pkt->data + s2 - n1, n2 - s2 ); + } else /* case C. No change, new is a subset of old */ + break ; + } else if (s1 <= n2) { /* case D or E, there is a merge... */ + seg->s = s; /* replace ctrl_hdr with new -- always works */ + if (s2 <= n2) { /* case D. New one includes old one */ + DEB(fprintf(stderr, "case D: old: [%5d,%5d] new [%5d,%5d]\n", + s1, s2, n1, n2);) + seg->len = len; + /* replace old data with new */ + seg->data = realloc(seg->data, seg->len); + memcpy(seg->data, pkt->data, len ); + } else { /* case E. Full merge (only if s1 > n1, or this is nop) */ + DEB(fprintf(stderr, "case E: old: [%5d,%5d] new [%5d,%5d]\n", + s1, s2, n1, n2);) + if (s1 > n1) { /* move old one forward */ + seg->len = s2 - n1 ; + /* merge data */ + seg->data = realloc(seg->data, seg->len); + bcopy(seg->data, seg->data + s1 - n1 , s2 - s1 ); + bcopy(pkt->data, seg->data, s1 - n1 ); + } + } + } else { /* case F. New is before, add an entry */ + DEB(fprintf(stderr, "case F: old: [%5d,%5d] new [%5d,%5d]\n", + s1, s2, n1, n2);) + tmp = new_segment(&s, len, pkt->data); + tmp->next = seg ; + if (prev) + prev->next = tmp ; + else + str->first = tmp ; + seg = tmp ; + } + /* + * Have added/modified an entry, should merge adjacent segments + * which can only be the ones after "seg" starting within the + * boundaries of the new entry, [n1,n2[ + * Segments coming next cannot start before n1 so i only + * need to check with n2. + */ + tmp = seg->next ; + n1 = seg->s.seq ; + n2 = n1 + seg->len ; + while ( tmp && (s1 = tmp->s.seq) <= n2 ) { + s2 = s1 + tmp->len ; + fprintf(stderr, "** merge: [%5d,%5d[ next [%5d,%5d[\n", + n1, n2, s1, s2 ) ; + /* XXX merge data */ + if (s2 > n2) { /* need to update length */ + seg->len = s2 - n1 ; + seg->data = realloc(seg->data, seg->len); + memcpy(seg->data + n2 - n1, tmp->data + n2 - s1 , s2 - n2 ); + n2 = s2 ; + } + /* now remove next segment */ + seg->next = tmp->next ; + if (str->last == tmp) + str->last = seg ; + /* free data portion */ + free(tmp->data); + free(tmp); + tmp = seg->next ; + } + break ; + } + /* + * XXX lr TODO: decide where to parse from. Two state vars are + * last_goto (marks the last known RC_GOTO) and parse_start (marks + * the next cmd to execute). Before the new segment comes in, + * all cmds from last_goto to parse_start-1 have been used. + * last_goto moves back if an old segment comes in and there + * are no GOTO in the last segment; moves forward if a new segment + * with a GOTO comes. + * If last_goto moves, then restart from there. Otherwise, restart + * from parse_start. + */ + rxs_find_start(str, -1 ) ; + if (str->last_goto != last_goto) { /*XXX lr complete! */ + need_redraw = 1 ; + str->parse_start = str->last_goto ; + return 1 ; + } else if (str->last->s.seq + str->last->len > next_seq) + return 1 ; + else + return 0 ; +} + +/* + * got_pkt checks the incoming (static) packet buffer + * which is rx_pkt, len + */ + +static int +got_pkt(struct stream_list **str_list, struct rx_stream **src_str) +{ + ctrl_hdr sheader; + rtphdr rheader; + u_int32_t rx_ssrc ; /* ssrc in received pkt */ + int retval ; + + struct rx_stream *curr; + struct stream_list *prev, *head; + + memcpy(&rheader, rx_pkt, sizeof(rtphdr)); + memcpy(&sheader, rx_pkt+sizeof(rtphdr), sizeof(ctrl_hdr)); + rx_ssrc = ntohl(rheader.ssrc) ; + + /* we have received an old version packet */ + if (ntohs(sheader.vers)next) + if (head->str->s_id == rx_ssrc) + break ; + if (head == NULL) { /* not found, create one */ + head = malloc(sizeof(struct stream_list)); + head->next = NULL; + head->str = malloc(sizeof(struct rx_stream)); + rx_stream_init(head->str); + head->str->s_id= rx_ssrc ; + + if (prev != NULL) /* list was not empty */ + head->next = *str_list ; + *str_list = head ; + } + *src_str = curr = head->str; + + retval = seg_reass(curr) ; +#if 0 + if (retval) + fprintf(stderr, "++ reass: new pkt page %d geo %dx%d\n", + curr->s_curr.page, curr->s_curr.width, curr->s_curr.height); + else + fprintf(stderr, "++ reass: old pkt\n"); +#endif + return retval; +} + +#define GET_RXS_I8(str, idx, dst) { \ + char *s = str->last->data + idx ; \ + dst = s[0] ; \ + idx += 1 ; } + +#define GET_RXS_I16(str, idx, dst) { \ + u_int16_t d ; \ + memcpy(&d, str->last->data + idx, 2) ; \ + dst = ntohs(d); \ + idx += 2 ; } + +#define GET_RXS_I32(str, idx, dst) { \ + u_char *d = (u_char *)(&dst), *s = str->last->data + idx ; \ + d[0] = s[0] ; d[1] = s[1] ; \ + d[2] = s[2] ; d[3] = s[3] ; \ + dst = ntohl(dst); \ + idx += 4 ; } + +/* + * parse last received packet, executing commands. + * Renderer state is updated. + */ + +extern Cursor pen_curs; + +/* + * this finds the last goto_page cmd in the stream. Additionally, + * interprets commands which update the state. XXX lr still to do! + * The optional parameter "page" is for matching a specific page, + * or -1 if any page is ok. + * If not found, return 0 if any page is looked for, + * the next cmd otherwise. + */ +static void +rxs_find_start(struct rx_stream *str, int page) +{ + int lim, found, i, is; + u_char *p ; + ctrl_hdr s = str->s_curr ; /* save a copy... */ + + if (str->last == NULL) { + fprintf(stderr, "-- warning, no data\n"); + return ; /* XXX */ + } + lim = str->last->len ; + found = 0 ; + str->s_curr = str->last->s ; + p = str->last->data ; + for (i = 0 ; i < lim ; i += cmd_size(p + i) ) { + switch (p[i]) { + case RC_GOTO_PAGE : + str->s_curr.page = p[i+1] ; + if (p[i] == RC_GOTO_PAGE && (page == -1 || p[i+1] == page) ) + found = i+2 ; /* no need to reexecute */ + break ; + case RC_RESIZE: + is = i+1 ; + GET_RXS_I16(str, is, str->s_curr.width); + GET_RXS_I16(str, is, str->s_curr.height); + break ; + } + } + str->last_goto = found + str->last->s.seq ; + if (found == 0) + str->s_curr = s ; +} + +static void +parse_rx_stream(struct render_state *state, struct rx_stream *str) +{ + u_char cmd; + int x,y, old_x, old_y ; + u_int16_t xo, yo; + u_int point_count, i, is, lim; + char diff; + int dcolor; + u_char text_char; + u_char page; + + if (sender_version > current_sender_version) + client_startup(state, str->s_curr.page); /* XXX lr check this */ + + if (need_redraw || state->page != str->s_curr.page) { + str->parse_start = str->last_goto ; + state_goto(state, str->s_curr.page, 0); + draw_page(state, &stop_on_pause); + } + need_redraw = 0 ; + + is = str->parse_start - str->last->s.seq ; + + DEB(fprintf(stderr, "++ stream %x [%d..%d]\n", + str, + str->last->s.seq + is, + str->last->s.seq + is + str->last->len );) + + str->parse_start = str->last->s.seq + str->last->len ; /* XXX update */ + lim = str->last->len ; + while (is < lim) { + GET_RXS_I8(str, is, cmd); + switch (cmd) { + case RC_GOTO_PAGE: + GET_RXS_I8(str, is, page); + DEB(fprintf(stderr, "==== rx: GOTO_PAGE %d\n", page);) + str->s_curr.page = page; + state_goto(state, page, 0); + draw_page(state, &stop_on_pause); + break; + + case RC_UNPAUSE: + DEB(fprintf(stderr, "==== rx: UNPAUSE\n");) + state_next(state); + draw_page(state, &stop_on_pause); + break; + + case RC_RESIZE: + GET_RXS_I16(str, is, str->s_curr.width); + GET_RXS_I16(str, is, str->s_curr.height); + DEB(fprintf(stderr, "==== rx: RESIZE %dx%d\n", + str->s_curr.width, str->s_curr.height);) + break; + + case RC_REPAINT: + DEB(fprintf(stderr, "==== rx: REPAINT\n");) + { + struct ctrl *lastcp = state->cp; /* stop here */ + state->repaint = 1; + state_goto(state, state->page, 1); + draw_page(state, lastcp); + + state->repaint = 0; + } + break; + + case RC_TEXT: + GET_RXS_I16(str, is, point_count); + GET_RXS_I8(str, is, dcolor); + + rakugaki_updatecolor(pen_curs, dcolor); + + GET_RXS_I16(str, is, xo); + GET_RXS_I16(str, is, yo); + xo=(state->width*xo)/str->s_curr.width; + yo=(state->height*yo)/str->s_curr.height; + for (i=0;itarget, gcpen, xo, yo, + &text_char, 1); + xo+=(pl_fw*3/4); + break; + } + } + break; + + case RC_DRAW: + GET_RXS_I16(str, is, point_count); + GET_RXS_I8(str, is, dcolor); + DEB(fprintf(stderr, "=== rx: RC_DRAW %d pts, color %d\n", + point_count, dcolor);) + + raku_set_color(dcolor >= 0, dcolor) ; + + /* now we read the coordinates of the first point */ + + GET_RXS_I16(str, is, old_x); + GET_RXS_I16(str, is, old_y); + xo = old_x; + yo = old_y; + + old_x=(state->width*old_x)/str->s_curr.width; + old_y=(state->height*old_y)/str->s_curr.height; + + XDrawRectangle(display, state->target, + gcpen, old_x, old_y, 1, 1); + + for (i=1; iwidth*xo)/str->s_curr.width; + GET_RXS_I8(str, is, diff); + yo=yo+diff; + y=(state->height*yo)/str->s_curr.height; + + XDrawLine(display, state->target, gcpen, + x, y, old_x, old_y); + old_x = x; + old_y = y; + } + break; + } + } + +} + +void +handle_pkt(struct render_state *state, struct rx_stream **str_list) +{ + struct rx_stream *src_str; + + if (got_pkt(str_list, &src_str)) + parse_rx_stream(state, src_str); +} + +void +free_stream_list(struct stream_list *str_list) +{ + struct stream_list *tmp_list, *t; + + tmp_list=str_list; + + while (tmp_list != NULL) { + free(tmp_list->str); + t = tmp_list->next; + free(tmp_list); + tmp_list = t; + } +} + +/* --- end of file */ mgpm/patches/patch-ce100644 423 0 22547 6637725035 13522 0ustar luigiwheel--- print.c.orig Thu Dec 10 18:14:23 1998 +++ print.c Tue Dec 22 00:17:16 1998 @@ -65,9 +65,11 @@ static struct textpool { int pfx; int xoffset; + int yoffset; int xsiz; struct fontmap *font; - int size; + int size; /* really, width */ + int height; /* really, width */ char *text; u_long fore; u_long back; @@ -197,7 +199,7 @@ static void print_string __P((u_char *, int)); static void print_fragment __P((u_char *, u_int, int, int)); static void text_remember __P((char *, int, int, int, int)); -static void icon_remember __P((int, int, int, u_long)); +static void icon_remember __P((int, int, int, int, int, u_long)); static void image_remember __P((struct ctrl *, struct imagepool *)); static void image_load_print __P((char *, int, int, int, int, int)); static void print_usage __P((char *)); @@ -365,7 +367,7 @@ char *aligns[] = { "center", "left", "right", NULL }; fprintf(fp, "%%!PS-Adobe-2.0 EPSF-2.0\n"); - fprintf(fp, "%%%%Creater: mgp2ps\n"); + fprintf(fp, "%%%%Creator: mgp2ps\n"); fprintf(fp, "%%%%Title: %s\n", mgp_fname); fprintf(fp, "%%%%Pages: %d\n", maxpage); fprintf(fp, "%%%%BoundingBox: 0 0 %d %d\n", paper->height, paper->width); @@ -636,6 +638,10 @@ break; } + case CTL_DRAW: + print_draw(cp); + break; + case CTL_ICON: print_icon(cp); break; @@ -819,27 +825,35 @@ struct textpool *tp; { int isize = tp->size; + int iheight = tp->height; int csize = tp->xsiz; int ixoff, iyoff; int paintit; + int icon = ((int)tp->font) ; + int x0 = tp->size ; + int y0 = tp->height ; + int x1 = tp->xoffset ; + int y1 = tp->yoffset ; iyoff = (csize - isize) / 3; /*XXX*/ ixoff = tp->xoffset + iyoff; paintit = (painticon || colorps); - switch ((int)tp->font) { /*XXX*/ - case 0: - /* XXX: image is not supported yet */ - break; + if (icon == 0) /* image, not supported yet */ + return ; + + fprintf(fp, "%% DRAW_TYPE %d x0 %d y0 %d x1 %d y1 %d\n", + icon, x0, y0, x1, y1); + switch (icon) { /*XXX*/ case 1: fprintf(fp, "currentpoint "); if (paintit) fprintf(fp, "currentpoint newpath moveto "); fprintf(fp, "%d %d rmoveto ", ixoff, iyoff); - fprintf(fp, "0 %d rlineto ", isize); + fprintf(fp, "0 %d rlineto ", iheight); fprintf(fp, "%d 0 rlineto ", isize); - fprintf(fp, "0 %d rlineto ", -isize); + fprintf(fp, "0 %d rlineto ", -iheight); fprintf(fp, "%d 0 rlineto ", -isize); if (paintit) fprintf(fp, "closepath eofill "); @@ -850,9 +864,9 @@ fprintf(fp, "currentpoint "); if (paintit) fprintf(fp, "currentpoint newpath moveto "); - fprintf(fp, "%d %d rmoveto ", ixoff + isize, iyoff + isize/2); + fprintf(fp, "%d %d rmoveto ", ixoff + isize, iyoff + iheight/2); fprintf(fp, "currentpoint exch %d add exch %d 0 360 arc ", - -isize/2, isize/2); + -isize/2, iheight/2); if (paintit) fprintf(fp, "closepath eofill "); fprintf(fp, "stroke moveto\n"); @@ -864,8 +878,8 @@ fprintf(fp, "currentpoint newpath moveto "); fprintf(fp, "%d %d rmoveto ", ixoff, iyoff); fprintf(fp, "%d 0 rlineto ", isize); - fprintf(fp, "%d %d rlineto ", -isize/2, isize); - fprintf(fp, "%d %d rlineto ", -isize/2, -isize); + fprintf(fp, "%d %d rlineto ", -isize/2, iheight); + fprintf(fp, "%d %d rlineto ", -isize/2, -iheight); if (paintit) fprintf(fp, "closepath eofill "); fprintf(fp, "stroke moveto\n"); @@ -875,10 +889,10 @@ fprintf(fp, "currentpoint "); if (paintit) fprintf(fp, "currentpoint newpath moveto "); - fprintf(fp, "%d %d rmoveto ", ixoff, iyoff + isize); + fprintf(fp, "%d %d rmoveto ", ixoff, iyoff + iheight); fprintf(fp, "%d 0 rlineto ", isize); - fprintf(fp, "%d %d rlineto ", -isize/2, -isize); - fprintf(fp, "%d %d rlineto ", -isize/2, isize); + fprintf(fp, "%d %d rlineto ", -isize/2, -iheight); + fprintf(fp, "%d %d rlineto ", -isize/2, iheight); if (paintit) fprintf(fp, "closepath eofill "); fprintf(fp, "stroke moveto\n"); @@ -889,9 +903,9 @@ if (paintit) fprintf(fp, "currentpoint newpath moveto "); fprintf(fp, "%d %d rmoveto ", ixoff, iyoff); - fprintf(fp, "0 %d rlineto ", isize); - fprintf(fp, "%d %d rlineto ", isize, -isize/2); - fprintf(fp, "%d %d rlineto ", -isize, -isize/2); + fprintf(fp, "0 %d rlineto ", iheight); + fprintf(fp, "%d %d rlineto ", isize, -iheight/2); + fprintf(fp, "%d %d rlineto ", -isize, -iheight/2); if (paintit) fprintf(fp, "closepath eofill "); fprintf(fp, "stroke moveto\n"); @@ -902,9 +916,9 @@ if (paintit) fprintf(fp, "currentpoint newpath moveto "); fprintf(fp, "%d %d rmoveto ", ixoff + isize, iyoff); - fprintf(fp, "0 %d rlineto ", isize); - fprintf(fp, "%d %d rlineto ", -isize, -isize/2); - fprintf(fp, "%d %d rlineto ", isize, -isize/2); + fprintf(fp, "0 %d rlineto ", iheight); + fprintf(fp, "%d %d rlineto ", -isize, -iheight/2); + fprintf(fp, "%d %d rlineto ", isize, -iheight/2); if (paintit) fprintf(fp, "closepath eofill "); fprintf(fp, "stroke moveto\n"); @@ -914,16 +928,39 @@ fprintf(fp, "currentpoint "); if (paintit) fprintf(fp, "currentpoint newpath moveto "); - fprintf(fp, "%d %d rmoveto ", ixoff, iyoff + isize/2); - fprintf(fp, "%d %d rlineto ", isize/2, isize/2); - fprintf(fp, "%d %d rlineto ", isize/2, -isize/2); - fprintf(fp, "%d %d rlineto ", -isize/2, -isize/2); - fprintf(fp, "%d %d rlineto ", -isize/2, isize/2); + fprintf(fp, "%d %d rmoveto ", ixoff, iyoff + iheight/2); + fprintf(fp, "%d %d rlineto ", isize/2, iheight/2); + fprintf(fp, "%d %d rlineto ", isize/2, -iheight/2); + fprintf(fp, "%d %d rlineto ", -isize/2, -iheight/2); + fprintf(fp, "%d %d rlineto ", -isize/2, iheight/2); if (paintit) fprintf(fp, "closepath eofill "); fprintf(fp, "stroke moveto\n"); fprintf(fp, "%d 0 rmoveto\n", ixoff * 2 + isize); break; + case 8: /* rect */ + case 9: /* frame */ + fprintf(fp, "currentpoint "); + if (paintit) + fprintf(fp, "currentpoint newpath moveto "); + fprintf(fp, "%d %d rmoveto ", x0, -y0 ); + fprintf(fp, "%d 0 rlineto ", x1 - x0 ); + fprintf(fp, "0 %d rlineto ", y0 - y1 ); + fprintf(fp, "%d 0 rlineto ", x0 - x1 ); + fprintf(fp, "0 %d rlineto ", y1 - y0 ); + if (paintit && icon == 8) + fprintf(fp, "closepath eofill "); + fprintf(fp, "stroke moveto\n"); + /* fprintf(fp, "currentpoint %d %d rmoveto ", -x0, y0 );*/ + fprintf(fp, "\n"); + break; + case 10 : /* line */ + fprintf(fp, "currentpoint "); + fprintf(fp, "%d %d rmoveto ", x0, -y0 ); + fprintf(fp, "%d %d rlineto ", x1-x0, y0-y1); + fprintf(fp, "%d %d rmoveto ", -x0, y0 ); + fprintf(fp, "stroke moveto\n"); + break ; } } @@ -962,11 +999,45 @@ } static void +print_draw(cp) + struct ctrl *cp; +{ + int sz = (int) char_size ; + int x0, y0, x1, y1; + drawcmds cmd = cp->ct_val.ctrl_drawcmd.cmd ; + int icon_x = linewidth ; + + int itype = 10 ; /* default: line */ + + x0 = icon_x + cp->ct_val.ctrl_drawcmd.x0*sz/100 ; + y0 = -(cp->ct_val.ctrl_drawcmd.y0*sz/100); + x1 = icon_x + cp->ct_val.ctrl_drawcmd.x1*sz/100 ; + y1 = -(cp->ct_val.ctrl_drawcmd.y1*sz/100); + switch (cmd) { + case DC_LINE: + itype = 10 ; + break ; + + case DC_RECT: + case DC_FRAME: + if (cmd == DC_RECT) + itype = 8 ; + else + itype = 9 ; /* frame, not filled */ + break ; + } +fprintf(stderr, "print_draw cmd %d %d,%d %d,%d\n", + itype, x0, y0, x1, y1); + icon_remember(itype, x0, y0, x1, y1, cp->ctic_color); + +} + +static void print_icon(cp) struct ctrl *cp; { int i; - int itype, isize; + int itype, isize, iheight; static struct ctl_words icon_words[] = { { 1, 'x', "box", 3 }, { 2, 'x', "arc", 3 }, @@ -975,6 +1046,8 @@ { 5, 'x', "delta3", 6 }, { 6, 'x', "delta4", 6 }, { 7, 'x', "dia", 3 }, + { 8, 'x', "rect", 4 }, + { 9, 'x', "frame", 5 }, { 0, 'x', NULL, 0 } }; @@ -985,7 +1058,12 @@ } itype = icon_words[i].ctl_type; isize = char_size * cp->ctic_size / 100; - icon_remember(itype, isize, linewidth, cp->ctic_color); + iheight = isize ; + if (cp->ctic_size > 1000) { + isize = char_size * cp->ctic_size / 100000 ; + iheight = char_size * (cp->ctic_size % 1000) / 100 ; + } + icon_remember(itype, isize, iheight, linewidth, 0, cp->ctic_color); linewidth += char_size; } @@ -1143,11 +1221,11 @@ } static void -text_remember(text, ctype, fontsize, offset, pfx) +text_remember(text, ctype, fontsize, xoffset, pfx) char *text; int ctype; int fontsize; - int offset; + int xoffset; int pfx; { /*XXX*/ @@ -1158,8 +1236,9 @@ return; } textpool[ntextpool].pfx = pfx; - textpool[ntextpool].xoffset = offset; - textpool[ntextpool].xsiz = linewidth - offset; + textpool[ntextpool].xoffset = xoffset; + textpool[ntextpool].yoffset = 0 ; + textpool[ntextpool].xsiz = linewidth - xoffset; textpool[ntextpool].size = fontsize; textpool[ntextpool].font = curfont[ctype]; textpool[ntextpool].text = strdup(text); @@ -1169,16 +1248,20 @@ } static void -icon_remember(icon, fontsize, offset, color) +icon_remember(icon, fontsize, height, xoffset, yoffset, color) int icon; int fontsize; - int offset; + int height; + int xoffset; + int yoffset; u_long color; { textpool[ntextpool].pfx = 1; - textpool[ntextpool].xoffset = offset; + textpool[ntextpool].xoffset = xoffset; + textpool[ntextpool].yoffset = yoffset; textpool[ntextpool].xsiz = char_size; textpool[ntextpool].size = fontsize; + textpool[ntextpool].height = height; textpool[ntextpool].font = (struct fontmap *)icon; /*XXX*/ textpool[ntextpool].text = NULL; textpool[ntextpool].fore = color; mgpm/patches/patch-cf100644 423 0 1354 6635530144 13465 0ustar luigiwheel--- x11.c.orig Tue Nov 10 07:20:54 1998 +++ x11.c Tue Dec 15 19:52:44 1998 @@ -153,6 +153,10 @@ ctrl_color = fore_color; (void)get_color(back_clname, &back_color); + if (window_width < 400) + draw_linewidth = 1 ; + else + draw_linewidth = 2 ; } void @@ -204,6 +208,8 @@ (void)get_color(pc->color, &color); XSetForeground(display, *pc->gc, color); } + XSetLineAttributes(display, *pc->gc, + draw_linewidth, LineSolid, CapRound, JoinRound); } if (mgp_flag & FL_OVER){ @@ -240,6 +246,7 @@ XSetFont(display, gc_pl, plfs->fid); XSetFont(display, gc_plrev, plfs->fid); XSetFont(display, gc_pta, plfs->fid); + XSetFont(display, gcpen, plfs->fid); } if (plkfs) XSetFont(display, gc_ptk, plkfs->fid); mgpm/patches/patch-ag100644 423 0 1512 6635530104 13454 0ustar luigiwheel--- compat.h.orig Tue Dec 15 19:52:44 1998 +++ compat.h Tue Dec 15 19:52:44 1998 @@ -0,0 +1,45 @@ +#ifndef MGP__COMPAT_H +#define MGP__COMPAT_H + +#include + +#ifdef IRIX +#include +#endif + +#ifdef HPUX +#include +#endif + +#ifdef FreeBSD +#include +#endif + +#ifdef Linux +#include +#endif + +#ifdef SunOS +#include +#endif + + +/* endianess... */ +#ifdef BYTE_ORDER +#if (BYTE_ORDER == LITTLE_ENDIAN) +#define _LITTLE_ENDIAN +#elif BYTE_ORDER == BIG_ENDIAN +#define _BIG_ENDIAN +#endif +#else /* BYTE_ORDER */ +#if ( !defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN) ) +#ifdef SunOS +#define _BIG_ENDIAN +/* #error We have SunOS assuming BIG_ENDIAN */ +#else +#error endianness not defined! check compat.h +#endif +#endif +#endif /* BYTE_ORDER */ + +#endif mgpm/pkg/ 40755 423 0 0 6620350425 11103 5ustar luigiwheelmgpm/pkg/COMMENT100644 423 0 71 6620351255 12165 0ustar luigiwheelA congestion control library for multicast applications. mgpm/pkg/DESCR100644 423 0 316 6620352336 11746 0ustar luigiwheelRLC is a library to support the development of congested-controlled multicast applications using a layered transmission scheme. Documentation is available at http://www.iet.unipi.it/~luigi/research.html/ mgpm/pkg/PLIST100644 423 0 11 6646653333 11762 0ustar luigiwheelbin/mgpm