From: M. Saggaf (alsaggaf@athena.mit.edu)
Date: 10/06/92


From: alsaggaf@athena.mit.edu (M. Saggaf)
Subject: Graphic Zmodem for X-Windows
Date: Wed, 7 Oct 1992 04:00:26 GMT

This is a patch against the stock zmodem code that gives it a graphical
look using the X-Windows environment. This is similar in its look to
the text version (whose patches I posted a few days ago) but adds a
few more niceties like color and the like.

From the programming point of view, however, it is quite different, and
I learned a lot writing it (this is my fist ever X program). The main
process forks a new child process whose sole purpose is to maintain
the contents of the window when it is hidden by other windows and then
exposed (I didn't't have to worry about that in the curses version). The
processes then communicate using pipes.

For those who have never written an X program, take a look at the
function 'xinit'. It gives you an idea on how to create a simple
window, set it up, and display it.

The code is far from complete and I don't know wither I'm going to
clean it up some more or not. However, It is at the same level of
functionality as the curses version. I'd be interested in suggestions
on enhancing it and also on choosing a pretty combination of colors
for the different parts of the display (right now it's quite
conservative in using colors).

As I said before, Zmodem is not public domain, and I don't know
exactly what the Omen Technology's copyright entails (I'd be
interested in some info in this regard, and in Omen Technology's email
address). So use it at your own responsibility. That's why I'm not
going to upload any modified sources or binaries, I'm simply posting
the patches.

To Build it, please do the following:
1) Patch the stock zmodem sources with included patches.
   (check oak.oakland.edu pub/unix-c/xyzmodem)
2) define MODEM at the top of the makefile.
3) Compile with the command 'make rz'.
4) Use it as follows:
        * in the shell (bash, tcsh ..etc) type 'rz -vv'.
        * in xcomm type '! rz -vv'.
        * in minicom do Ctl-A J, then 'rz -vv' in the shell.
        (i.e. no redirection of stdio)
5) If you like it, let me know.

Note: this is for rz only, not sz (i.e. receiving only).

                                        -- Muhammad

========== One Graphical Zmodem Coming Up .... ==========
diff -cNr czmodem/Makefile xzm/Makefile
*** czmodem/Makefile Sun Dec 15 15:35:56 1991
--- xzm/Makefile Tue Oct 6 23:30:08 1992
***************
*** 1,7 ****
  # Makefile for Unix/Xenix rz and sz programs
  # the makefile is not too well tested yet
! CC=cc
! OFLAG= -O
  
  
  ARCFILES= README rbsb.c gz *.t minirb.c zmodem.h \
--- 1,7 ----
  # Makefile for Unix/Xenix rz and sz programs
  # the makefile is not too well tested yet
! CC=gcc
! OFLAG= -O6 -DXRZ -DMODEM=\"/dev/ttys1\"
  
  
  ARCFILES= README rbsb.c gz *.t minirb.c zmodem.h \
***************
*** 88,133 ****
  
  .PRECIOUS:rz sz
  
! xenix:
! $(CC) $(CFLAGS) $(OFLAG) -M0 -K -i -DTXBSIZE=16384 -DNFGVMIN -DREADCHECK sz.c -lx -o sz
! size sz
! -ln sz sb
! -ln sz sx
! -ln sz zcommand
! -ln sz zcommandi
! $(CC) $(CFLAGS) $(OFLAG) -M0 -K -i -DMD rz.c -o rz
! size rz
! -ln rz rb
! -ln rz rx
! -ln rz rc
!
! x386:
! $(CC) $(CFLAGS) $(OFLAG) -DMD rz.c -o rz
! size rz
! -ln rz rb
! -ln rz rx
! $(CC) $(CFLAGS) $(OFLAG) -DTXBSIZE=32768 -DNFGVMIN -DREADCHECK sz.c -lx -o sz
! size sz
! -ln sz sb
! -ln sz sx
! -ln sz zcommand
! -ln sz zcommandi
!
! sysv:
! $(CC) $(CFLAGS) $(OFLAG) -DMD rz.c -o rz
! size rz
! -ln rz rb
! -ln rz rx
! -ln rz rc
! $(CC) $(CFLAGS) $(OFLAG) -DSV -DTXBSIZE=32768 -DNFGVMIN sz.c -o sz
! size sz
! -ln sz sb
! -ln sz sx
! -ln sz zcommand
! -ln sz zcommandi
!
! sysvr3:
! $(CC) $(CFLAGS) $(OFLAG) -DMD=2 rz.c -o rz
        size rz
        -ln rz rb
        -ln rz rx
--- 88,94 ----
  
  .PRECIOUS:rz sz
  
! sysvr3: rz
        size rz
        -ln rz rb
        -ln rz rx
***************
*** 139,224 ****
        -ln sz zcommand
        -ln sz zcommandi
  
- sysvr4:
- $(CC) $(CFLAGS) $(OFLAG) -DMD=2 rz.c -o rz
- size rz
- -ln rz rb
- -ln rz rx
- -ln rz rc
- $(CC) $(CFLAGS) $(OFLAG) -DSV -DTXBSIZE=32768 sz.c -o sz
- size sz
- -ln sz sb
- -ln sz sx
- -ln sz zcommand
- -ln sz zcommandi
-
- odt:
- cc -Za -n -DMD=2 rz.c -o rz
- size rz
- -ln rz rb
- -ln rz rx
- -ln rz rc
- cc -Za -n -DSV -DTXBSIZE=32768 sz.c -o sz
- size sz
- -ln sz sb
- -ln sz sx
- -ln sz zcommand
- -ln sz zcommandi
-
- bsd:
- $(CC) $(CFLAGS) $(OFLAG) -DMD=2 -Dstrchr=index -DV7 rz.c -o rz
- size rz
- -ln rz rb
- -ln rz rx
- -ln rz rc
- $(CC) $(CFLAGS) $(OFLAG) -DV7 -DTXBSIZE=32768 -DNFGVMIN sz.c -o sz
- size sz
- -ln sz sb
- -ln sz sx
- -ln sz zcommand
- -ln sz zcommandi
  
! tandy:
! $(CC) $(CFLAGS) $(OFLAGS) -n -DMD -DT6K sz.c -lx -o sz
! size sz
! -ln sz sb
! -ln sz sx
! -ln sz zcommand
! -ln sz zcommandi
! $(CC) $(CFLAGS) $(OFLAGS) -n -DMD -DT6K rz.c -lx -o rz
! size rz
! -ln rz rb
! -ln rz rx
! -ln rz rc
  
! dnix:
! $(CC) $(CFLAGS) $(OFLAG) -DMD rz.c -o rz
! size rz
! -ln rz rb
! -ln rz rx
! -ln rz rc
! $(CC) $(CFLAGS) $(OFLAG) -DSV -DTXBSIZE=32768 -DNFGVMIN -DREADCHECK sz.c -o sz
! size sz
! -ln sz sb
! -ln sz sx
! -ln sz zcommand
! -ln sz zcommandi
  
! dnix5r3:
! $(CC) $(CFLAGS) $(OFLAG) -DMD=2 rz.c -o rz
! size rz
! -ln rz rb
! -ln rz rx
! -ln rz rc
! $(CC) $(CFLAGS) $(OFLAG) -DSV -DTXBSIZE=32768 -DNFGVMIN -DREADCHECK sz.c -o sz
! size sz
! -ln sz sb
! -ln sz sx
! -ln sz zcommand
! -ln sz zcommandi
  
  
  sz: nothing
  sb: nothing
- rz: nothing
  rb: nothing
--- 100,120 ----
        -ln sz zcommand
        -ln sz zcommandi
  
  
! rz: rz.o show_info.o xprocs.o
! $(CC) $(CFLAGS) $(OFLAG) -o rz rz.o show_info.o xprocs.o \
! -L/usr/X386/lib/jump -lX11
! # install -c -s rz /usr/bin/xrz
  
! rz.o: rz.c rbsb.c
! $(CC) $(CFLAGS) $(OFLAG) -DDSZ -DMD=2 -c rz.c
  
! show_info.o: show_info.c
! $(CC) $(CFLAGS) $(OFLAG) -c show_info.c
  
+ xprocs.o: xprocs.c
+ $(CC) $(CFLAGS) $(OFLAG) -c xprocs.c
  
  sz: nothing
  sb: nothing
  rb: nothing
diff -cNr czmodem/main.c xzm/main.c
*** czmodem/main.c
--- xzm/main.c Mon Oct 5 18:56:51 1992
***************
*** 0 ****
--- 1,16 ----
+ #include <stdio.h>
+
+
+ Display *display;
+ int screen;
+ Window win;
+ XFontStruct *font;
+ GC gc;
+ XEvent event;
+
+
+ main()
+ {
+ xinit();
+ sleep(10);
+ }
diff -cNr czmodem/rbsb.c xzm/rbsb.c
*** czmodem/rbsb.c Wed Oct 30 19:59:16 1991
--- xzm/rbsb.c Mon Oct 5 19:24:27 1992
***************
*** 336,345 ****
--- 336,352 ----
  /* Initialize tty device for serial file xfer */
  inittty()
  {
+ #ifndef XRZ
        Tty = open("/dev/tty", 2);
        if (Tty < 0) {
                perror("/dev/tty"); exit(2);
        }
+ #else
+ Tty = open(MODEM, 2);
+ if (Tty < 0) {
+ perror(MODEM); exit(2);
+ }
+ #endif
        Ttystream = fdopen(Tty, "w");
        setbuf(Ttystream, xXbuf);
  }
diff -cNr czmodem/rz.c xzm/rz.c
*** czmodem/rz.c Wed Oct 30 19:57:48 1991
--- xzm/rz.c Tue Oct 6 23:20:57 1992
***************
*** 67,72 ****
--- 67,79 ----
  #include <signal.h>
  #include <ctype.h>
  #include <errno.h>
+ #ifdef XRZ
+ #include <unistd.h>
+ #include <sys/times.h>
+ #include <limits.h>
+ #include <fcntl.h>
+ #include <X11/Xlib.h>
+ #endif
  extern int errno;
  FILE *popen();
  
***************
*** 133,138 ****
--- 140,164 ----
  int errors;
  int Restricted=0; /* restricted; no /.. or ../ in filenames */
  
+ #ifdef XRZ
+ #define CNULL NULL
+
+ long GTotalleft = 0;
+ long btime, ttime;
+ char Fname[40], **gargv, sdummy[80];
+ struct tms tdummy;
+ pid_t epid;
+ int pfd[2], gargc;
+
+
+ Display *display;
+ int screen;
+ Window win;
+ XFontStruct *font;
+ GC gc;
+ XEvent event;
+ #endif
+
  #define DEFBYTL 2000000000L /* default rx file size */
  long Bytesleft; /* number of bytes of incoming file left */
  long Modtime; /* Unix style mod time for incoming file */
***************
*** 192,197 ****
--- 218,228 ----
        char *getenv();
        int exitcode = 0;
  
+ #ifdef XRZ
+ gargc = argc;
+ gargv = argv;
+ #endif
+
        Rxtimeout = 100;
        setbuf(stderr, NULL);
        if ((cp=getenv("SHELL")) && (substr(cp, "rsh") || substr(cp, "rksh")))
***************
*** 246,256 ****
--- 277,294 ----
        if (Batch && npats)
                usage();
        if (Verbose) {
+ #ifndef XRZ
                if (freopen(LOGFILE, "a", stderr)==NULL) {
                        printf("Can't open log file %s\n",LOGFILE);
                        exit(2);
                }
+ #endif
                setbuf(stderr, NULL);
+
+ #ifdef XRZ
+ xinit();
+ #endif
+
                fprintf(stderr, "argv[0]=%s Progname=%s\n", virgin, Progname);
        }
        vfile("%s %s for %s\n", Progname, VERSION, OS);
***************
*** 273,278 ****
--- 311,319 ----
                printf(" %s: %s\r\n", Progname, endmsg);
        printf("%s %s finished.\r\n", Progname, VERSION);
        fflush(stdout);
+ #ifdef XRZ
+ /* kill(epid, SIGKILL);*/
+ #endif
        exit(exitcode != 0);
  }
  
***************
*** 576,586 ****
--- 617,629 ----
                  &dummy, &Filesleft, &Totalleft, &dummy, &dummy);
                if (Filemode & UNIXFILE)
                        ++Thisbinary;
+ #ifndef XRZ
                if (Verbose) {
                        fprintf(stderr, "Incoming: %s %ld %lo %o\n",
                          name, Bytesleft, Modtime, Filemode);
                        fprintf(stderr, "YMODEM header: %s\n", p);
                }
+ #endif
        }
  
  
***************
*** 811,821 ****
--- 854,875 ----
  zperr(s,p,u)
  char *s, *p, *u;
  {
+ #ifdef XRZ
+ char sdummy2[80];
+
+ if (Verbose <= 0)
+ return;
+ sprintf(sdummy, "Retry %d: ", errors);
+ sprintf(sdummy2, s, p, u);
+ strcat(sdummy, sdummy2);
+ zmessage(sdummy);
+ #else
        if (Verbose <= 0)
                return;
        fprintf(stderr, "Retry %d: ", errors);
        fprintf(stderr, s, p, u);
        fprintf(stderr, "\n");
+ #endif
  }
  
  report(sct)
***************
*** 988,995 ****
--- 1042,1060 ----
  {
        register c;
  
+ #ifdef XRZ
+ ttime = times(&tdummy);
+ #endif
+
        for (;;) {
+ #ifdef XRZ
+ pipe(pfd);
+ c = rzfile();
+ kill(epid, SIGKILL);
+ switch (c) {
+ #else
                switch (c = rzfile()) {
+ #endif
                case ZEOF:
                case ZSKIP:
                        switch (tryz()) {
***************
*** 1016,1021 ****
--- 1081,1089 ----
  rzfile()
  {
        register c, n;
+ #ifdef XRZ
+ long orxbytes = 0;
+ #endif
  
        Eofseen=FALSE;
        n = 20; rxbytes = 0l;
***************
*** 1024,1029 ****
--- 1092,1121 ----
                return (tryzhdrtype = c);
        }
  
+ #ifdef XRZ
+ if (GTotalleft < Totalleft)
+ GTotalleft = Totalleft;
+
+ if (strlen(secbuf) > 14) {
+ strncpy(Fname, secbuf, 11);
+ Fname[11] = 0; /*NULL;*/
+ strcat(Fname, "...");
+ }
+ else
+ strcpy(Fname, secbuf);
+
+ btime = times(&tdummy);
+ xdisp1();
+
+ epid = fork();
+ if(epid == 0) {
+ fcntl(pfd[0], F_SETFL, O_NONBLOCK);
+ event_proc();
+ fprintf(stderr, "Child exited prematurely\n");
+ exit(-1);
+ }
+ #endif
+
        for (;;) {
  #ifdef SEGMENTS
                chinseg = 0;
***************
*** 1119,1127 ****
                                zmputs(Attn); continue;
                        }
  moredata:
! if (Verbose>1)
                                fprintf(stderr, "\r%7ld ZMODEM%s ",
                                  rxbytes, Crc32r?" CRC-32":"");
  #ifdef SEGMENTS
                        if (chinseg >= (1024 * SEGMENTS)) {
                                putsec(secbuf, chinseg);
--- 1211,1230 ----
                                zmputs(Attn); continue;
                        }
  moredata:
! #ifndef XRZ
! if (Verbose>1) {
                                fprintf(stderr, "\r%7ld ZMODEM%s ",
                                  rxbytes, Crc32r?" CRC-32":"");
+ }
+ #else
+ if(rxbytes - orxbytes > 0 || !orxbytes) {
+ orxbytes = rxbytes;
+ show_info();
+ if(write(pfd[1], (char *)&rxbytes, sizeof(rxbytes)) == -1)
+ fprintf(stderr, "could not write to pipe\n");
+ }
+ #endif
+
  #ifdef SEGMENTS
                        if (chinseg >= (1024 * SEGMENTS)) {
                                putsec(secbuf, chinseg);
diff -cNr czmodem/show_info.c xzm/show_info.c
*** czmodem/show_info.c
--- xzm/show_info.c Tue Oct 6 22:40:59 1992
***************
*** 0 ****
--- 1,101 ----
+ #include <stdio.h>
+ #include <sys/times.h>
+ #include <unistd.h>
+ #include <X11/Xlib.h>
+
+ #define CNULL NULL
+ #define MAX_COLORS 3
+
+ extern Display *display;
+ extern int screen;
+ extern Window win;
+ extern GC gc;
+ extern XEvent event;
+
+ unsigned long colors[MAX_COLORS];
+
+ extern int pfd[2];
+ extern char sdummy[80];
+
+ extern int Crc32r;
+ extern long rxbytes, Bytesleft, Filesleft, Totalleft, GTotalleft;
+ extern long btime, ttime;
+
+ int show_info()
+ {
+ long rxtotal, curtime;
+ long btelpsd, btleft, ttelpsd, ttleft;
+ int perc, tperc, bytesthru, totalthru;
+ int i;
+ char sbuf[80];
+ struct tms tdummy;
+
+ #define DIS 10
+ #define TDIS 30
+
+ rxtotal = GTotalleft-Totalleft+rxbytes;
+ perc = 100*rxbytes/Bytesleft;
+ tperc = 100*rxtotal/GTotalleft;
+
+ curtime = times(&tdummy);
+ btelpsd = (curtime-btime)>100 ? (curtime-btime)/100 : 1;
+ ttelpsd = (curtime-ttime)>100 ? (curtime-ttime)/100 : 1;
+ btleft = rxbytes>100 ? (Bytesleft-rxbytes)*1.0/rxbytes*btelpsd : 0 ;
+ ttleft = rxtotal>100 ? (Totalleft-rxbytes)*1.0/rxtotal*ttelpsd : 0 ;
+ bytesthru = rxbytes/btelpsd;
+ totalthru = rxtotal/ttelpsd;
+
+ sprintf(sbuf, "%dk ", rxbytes/1024); xwaddstr(2, 4+DIS, sbuf);
+ sprintf(sbuf, "%d%% ", perc); xwaddstr(4, 4+DIS, sbuf);
+ sprintf(sbuf, "%02d:%02d", btelpsd/60, btelpsd%60);
+ xwaddstr(5, 4+DIS, sbuf);
+ sprintf(sbuf, "%02d:%02d", btleft/60, btleft%60); xwaddstr(6, 4+DIS, sbuf);
+ sprintf(sbuf, "%d cps ", bytesthru); xwaddstr(7, 4+DIS, sbuf);
+
+ sprintf(sbuf, "%dk ", rxtotal/1024);
+ xwaddstr(2, TDIS+4+DIS, sbuf);
+ sprintf(sbuf, "%d%% ", tperc);
+ xwaddstr(4, TDIS+4+DIS, sbuf);
+ sprintf(sbuf, "%02d:%02d", ttelpsd/60, ttelpsd%60);
+ xwaddstr(5, TDIS+4+DIS, sbuf);
+ sprintf(sbuf, "%02d:%02d", ttleft/60, ttleft%60);
+ xwaddstr(6, TDIS+4+DIS, sbuf);
+ sprintf(sbuf, "%d cps ", totalthru);
+ xwaddstr(7, TDIS+4+DIS, sbuf);
+
+ XSetForeground(display, gc, colors[1]);
+ draw_rec(9.0, 2.0, (float)perc/2.0);
+ XSetForeground(display, gc, colors[0]);
+ draw_rec(12.0, 2.0, (float)tperc/2.0);
+ XSetForeground(display, gc, BlackPixel(display, screen));
+
+ zmessage("Receiving file OK");
+
+ /*mvwprintw(win, 3, 1, "\r< %d%% >< %dk of %dk >< %df = %dk >< %s > \r",
+ 100*rxbytes/Bytesleft, rxbytes/1024, Bytesleft/1024,
+ Filesleft, Totalleft/1024, Crc32r?"CRC-32":"");*/
+ }
+
+ zmessage(msg)
+ char *msg;
+ {
+ if (strlen(msg) > 40)
+ msg[40] = CNULL;
+
+ /* wclrtoeol(win);*/
+ xwaddstr(16, 12, msg);
+
+ XFlush(display);
+ }
+
+ event_proc()
+ {
+ while(1) {
+ XNextEvent(display, &event);
+ if(event.type == Expose) {
+ while(read(pfd[0], (char *)&rxbytes, sizeof(long)) != -1);
+ xdisp1();
+ show_info();
+ }
+ }
+ }
diff -cNr czmodem/xprocs.c xzm/xprocs.c
*** czmodem/xprocs.c
--- xzm/xprocs.c Tue Oct 6 22:41:00 1992
***************
*** 0 ****
--- 1,209 ----
+ #include <stdio.h>
+ #include <X11/Xlib.h>
+ #include <X11/Xutil.h>
+ #include <X11/Xos.h>
+
+ #define MAX_COLORS 3
+
+ extern Display *display;
+ extern int screen;
+ extern Window win;
+ extern XFontStruct *font;
+ extern GC gc;
+ extern XEvent event;
+ XWindowAttributes win_attr;
+
+ extern unsigned long colors[MAX_COLORS];
+
+ extern char Fname[40], **gargv;;
+ extern long rxbytes, Bytesleft, Filesleft, Totalleft, GTotalleft;
+ extern int gargc;
+
+ getGC(win, gc, font)
+ Window win;
+ GC *gc;
+ XFontStruct *font;
+ {
+ unsigned long valuemask = 0;
+ XGCValues values;
+
+ *gc = XCreateGC(display, win, valuemask, &values);
+
+ XSetFont(display, *gc, font->fid);
+ XSetForeground(display, *gc, BlackPixel(display,screen));
+ XSetBackground(display, *gc, WhitePixel(display,screen));
+ }
+
+ load_font(font)
+ XFontStruct **font;
+ {
+ if(!(*font = XLoadQueryFont(display, "6x13"))) {
+ fprintf(stderr, "Cannot open font, exiting\n");
+ exit(-1);
+ }
+ }
+
+ draw_text(win, gc, font)
+ Window win;
+ GC gc;
+ XFontStruct *font;
+ {
+ int fh, fw;
+ char *str;
+
+ #define DIS 10
+ #define TDIS 30
+
+ /*#define xdisp(x, y, str) \
+ XDrawString(display, win, gc, x, y, str, strlen(str))
+
+ fh = font->ascent + font->descent;
+ fw = font->max_bounds.lbearing + font->max_bounds.rbearing;
+ */
+ }
+
+ xdisp1()
+ {
+ char sbuf[256];
+
+ sprintf(sbuf, "This File: %s", Fname);
+ xwaddstr(1, 2, sbuf);
+ xwaddstr(2, 4, "Received:");
+ sprintf(sbuf, "Expected: %dk", Bytesleft/1024);
+ xwaddstr(3, 4, sbuf);
+ xwaddstr(4, 4, "Percent :");
+ xwaddstr(5, 4, "T. Elpsd:");
+ xwaddstr(6, 4, "T. Left :");
+ xwaddstr(7, 4, "Thruput :");
+ xwaddstr(16, 2, "Messages:");
+
+ sprintf(sbuf, "Total: %d files left", Filesleft);
+ xwaddstr(1, TDIS+2, sbuf);
+ xwaddstr(2, TDIS+4, "Received:");
+ sprintf(sbuf, "Expected: %dk", GTotalleft/1024);
+ xwaddstr(3, TDIS+4, sbuf);
+ xwaddstr(4, TDIS+4, "Percent :");
+ xwaddstr(5, TDIS+4, "T. Elpsd:");
+ xwaddstr(6, TDIS+4, "T. Left :");
+ xwaddstr(7, TDIS+4, "Thruput :");
+
+ xwaddstr(9, 2, "This File:");
+ draw_hline(9.5, 2.0, 50.0);
+ /* xwaddstr(10, 2, "+-----------+------------+------------+-----------+");*/
+ xwaddstr(11, 2, "0% 25% 50% 75% 100%");
+ xwaddstr(12, 2, "Total:");
+ draw_hline(12.5, 2.0, 50.0);
+ /* xwaddstr(13, 2, "+-----------+------------+------------+-----------+");*/
+ xwaddstr(14, 2, "0% 25% 50% 75% 100%");
+
+ draw_lines();
+ }
+
+ xwaddstr(row, col, str)
+ int row, col;
+ char *str;
+ {
+ int fh, fw;
+
+ fh = font->ascent + font->descent;
+ fw = font->max_bounds.rbearing + font->min_bounds.lbearing;
+
+ XDrawImageString(display, win, gc, col*fw, row*fh, str, strlen(str));
+ }
+
+ xinit()
+ {
+ if(!(display = XOpenDisplay(NULL))) {
+ fprintf(stderr, "Error: Cannot open display. Exiting\n");
+ exit(-1);
+ }
+
+ screen = DefaultScreen(display);
+
+ win = XCreateSimpleWindow(display, RootWindow(display,screen), 100, 100,
+ 350, 225, 10, BlackPixel(display, screen),
+ WhitePixel(display, screen));
+
+ XmbSetWMProperties(display, win, "Graphic RZ", NULL, gargv, gargc,
+ NULL, NULL, NULL);
+
+ XSelectInput(display, win, ExposureMask | KeyPressMask |
+ ButtonPressMask | StructureNotifyMask);
+
+ load_font(&font);
+ getGC(win, &gc, font);
+
+ get_colors();
+
+ XMapWindow(display, win);
+ XFlush(display);
+
+ XGetWindowAttributes(display, win, &win_attr);
+ }
+
+ get_colors()
+ {
+ int default_depth;
+ Visual *default_visual;
+ Colormap default_cmap;
+ XVisualInfo visual_info;
+ XColor exact_def;
+ static char *name[] = {"Red", "Blue", "Yellow"};
+ int i = 5;
+
+ default_depth = DefaultDepth(display, screen);
+ default_visual = DefaultVisual(display, screen);
+ default_cmap = DefaultColormap(display, screen);
+
+ for (i = 0; i < MAX_COLORS; i++) {
+
+ if (!XParseColor(display, default_cmap, name[i], &exact_def)) {
+ fprintf(stderr, "color name %s not in database", name[i]);
+ exit(0);
+ }
+ if (!XAllocColor(display, default_cmap, &exact_def)) {
+ fprintf(stderr, "can't allocate color: all colorcells allocated and no matching cell found.\n");
+ exit(0);
+ }
+ colors[i] = exact_def.pixel;
+ }
+ }
+
+ #define Y1 (7.5*fh)
+ #define Y2 (14.5*fh)
+
+ draw_lines()
+ {
+ int fh;
+
+ fh = font->ascent + font->descent;
+
+ XDrawLine(display, win, gc, 0, (int)Y1, win_attr.width, (int)Y1);
+ XDrawLine(display, win, gc, 0, (int)Y2, win_attr.width, (int)Y2);
+ XDrawLine(display, win, gc, win_attr.width/2, 0, win_attr.width/2,
+ (int)Y1);
+ }
+
+ draw_hline(row, col, len)
+ float row, col, len;
+ {
+ int fh, fw;
+
+ fh = font->ascent + font->descent;
+ fw = font->max_bounds.rbearing + font->min_bounds.lbearing;
+
+ XDrawLine(display, win, gc, (int)(col*fw), (int)(row*fh),
+ (int)((col+len)*fw), (int)(row*fh));
+ }
+
+ draw_rec(row, col, len)
+ float row, col, len;
+ {
+ int fh, fw;
+
+ fh = font->ascent + font->descent;
+ fw = font->max_bounds.rbearing + font->min_bounds.lbearing;
+
+ XFillRectangle(display, win, gc, (int)(col*fw), (int)(row*fh),
+ (unsigned int)(len*fw), fh);
+ }
========================================end============================