home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / x / xcrash16.zip / xcrash1.6 / xcrash.c < prev    next >
C/C++ Source or Header  |  1992-07-27  |  20KB  |  791 lines

  1. /*
  2. xcrash - Run tests attempting to crash and find bugs in the X server
  3.  
  4. Copyright 1992 by Hal Computer Systems, Incorporated.  All Rights Reserved.
  5.  
  6. Permission to use, copy, modify, and distribute this software and its
  7. documentation for any purpose and without fee is hereby granted,
  8. provided that the above copyright notice appear in all copies and that
  9. both that copyright notice and this permission notice appear in
  10. supporting documentation, and that the name of HaL not be
  11. used in advertising or publicity pertaining to distribution of the
  12. software without specific, written prior permission.
  13.  
  14. HaL disclaims all warranties with regard to this software, including
  15. all implied warranties of metchantability and fitness, in no event shall
  16. HaL be liable for any special, indirect or consequential damages or
  17. any damages whatsoever resulting from loss of use, data or profits,
  18. whether in an action of contract, negligence or other tortious action,
  19. arising out of or in connection with the use of performance of this
  20. software.
  21. */
  22.  
  23. #include <sys/types.h>
  24. #include <sys/time.h>
  25. #include <stdio.h>
  26. #include <X11/Xlib.h>
  27. #include <X11/Intrinsic.h>
  28.  
  29. static char Xcrash_version[] = "xcrash_v1.5";
  30.  
  31. void Xcrash_error();
  32.  
  33. typedef struct Xcrash_struct
  34.     {
  35.     int        x,y;            /* current window loc */
  36.     unsigned int    w,h;            /* current window size */
  37.     int        scr;            /* Screen */
  38.     int        depth;            /* depth of Screen */
  39.     int        trace;            /* display trace of activity */
  40.     int        quiet;            /* be very very quiet */
  41.     int        numtests;        /* # of tests to perform */
  42.     int        nasty;            /* perform nasty tests */
  43.     int        seed;            /* random number seed */
  44.     FILE        *infile;        /* input file */
  45.     Display        *dpy;            /* Display */
  46.     Window        win;            /* Window */
  47.     GC        gc;            /* Graphics Context */
  48.     Pixel        fg,bg;            /* fg and bg colors */
  49.     Colormap    cmap;
  50.     } *Xcrash;
  51.  
  52. Xcrash    Xcrash_new(display,numtests,infile,trace,quiet,nasty,seed)
  53. char *display,*infile;
  54. int numtests,trace,quiet,nasty,seed;
  55. /* Create a new instance of an Xcrash object. numtests is the number of
  56. tests to perform.  quiet and trace are boolean values which tell me
  57. how verbose I should be in displaying what Im doing.  infile is a file
  58. to read data from (if null dont read).  display is a character string
  59. display to connect to */
  60.     {
  61.     Xcrash c;
  62.     Window root,win;
  63.         XVisualInfo vinfo;
  64.     XSetWindowAttributes attrib;
  65.     unsigned int loop,in;
  66.     XColor color[256];
  67.  
  68.     c = (Xcrash)malloc(sizeof(struct Xcrash_struct));
  69.     if (!c)
  70.         return((Xcrash)0);
  71.     c->numtests = numtests;
  72.     c->trace = trace;
  73.     c->quiet = quiet;
  74.     c->nasty = nasty;
  75.     c->seed = seed;
  76.     if (infile)
  77.         {
  78.         c->infile =  fopen(infile,"r");
  79.         if (!c->infile)
  80.             {
  81.             Xcrash_error(c,"ERROR: count not open input file");
  82.             free(c);
  83.             return((Xcrash)0);
  84.             }
  85.         }
  86.     else
  87.         c->infile = (FILE *)0;
  88.     c->dpy = XOpenDisplay(display);
  89.     if (!c->dpy)
  90.         {
  91.         if (c->infile)
  92.             fclose(c->infile);
  93.         Xcrash_error(c,"ERROR: could not open display");
  94.         free(c);
  95.         return ((Xcrash)0);
  96.         }
  97.         c->scr = DefaultScreen(c->dpy);
  98.     c->fg = WhitePixel(c->dpy,c->scr);
  99.     c->bg = BlackPixel(c->dpy,c->scr);
  100.     root = RootWindow(c->dpy,c->scr);
  101.     c->depth = DefaultDepth(c->dpy,c->scr);
  102.     if (XMatchVisualInfo(c->dpy,c->scr,8,PseudoColor,&vinfo))
  103.         {
  104.         /* set up a bogus 3x3x2 colormap */
  105.         c->cmap = XCreateColormap(c->dpy,root,vinfo.visual,AllocAll);
  106.         for (loop=0;loop<256;loop++)
  107.             {
  108.             color[loop].pixel = loop;
  109.             color[loop].red = (loop & 0x7) << 13;   /* 00000111 */
  110.             color[loop].green = (loop & 0x38) << 10;/* 00111000 */
  111.             color[loop].blue = (loop & 0xc0) << 8;  /* 11000000 */
  112.             color[loop].flags = DoRed | DoGreen | DoBlue;
  113.             }
  114.         XStoreColors(c->dpy,c->cmap,color,256);
  115.         }
  116.     else
  117.         {
  118.         vinfo.visual = DefaultVisual(c->dpy,c->scr);
  119.         c->cmap = XCreateColormap(c->dpy,root,vinfo.visual,AllocNone);
  120.         }
  121.     c->w = WidthOfScreen(ScreenOfDisplay(c->dpy,c->scr))/2;
  122.     c->h = HeightOfScreen(ScreenOfDisplay(c->dpy,c->scr));
  123.     attrib.colormap = c->cmap;
  124.     attrib.background_pixel = c->bg;
  125.     attrib.override_redirect = 1;
  126.     c->win = XCreateWindow(c->dpy,root,0,0,c->w,c->h,0,c->depth,
  127.         InputOutput,vinfo.visual,CWOverrideRedirect|CWBackPixel|
  128.         CWColormap,&attrib);
  129.     XSelectInput(c->dpy,c->win,KeyPressMask|ExposureMask|
  130.         StructureNotifyMask);
  131.     XMapWindow(c->dpy,c->win);
  132.     XGetGeometry(c->dpy,c->win,&win,&c->x,&c->y,&c->w,&c->h,&in,&in);
  133.     XInstallColormap(c->dpy,c->cmap);
  134.         c->gc = XCreateGC(c->dpy,root,0,(XGCValues *)NULL);
  135.     XSetPlaneMask(c->dpy,c->gc,AllPlanes);
  136.     return(c);
  137.     }
  138.  
  139. void    Xcrash_free(c)
  140. Xcrash c;
  141. /* Free an Xcrash object (doesnt free everything right now) */
  142.     {
  143.     if (!c)
  144.         return;
  145.     if (c->infile)
  146.         fclose(c->infile);
  147.     XDestroyWindow(c->dpy,c->win);
  148.     XCloseDisplay(c->dpy);
  149.     free(c);
  150.     }
  151.  
  152. void Xcrash_error(c,msg)
  153. Xcrash c;
  154. char *msg;
  155. /* Display message to stderr.  Not always an error even though youd
  156. think so looking at the function name. */
  157.     {
  158.     if (!c->quiet)
  159.         {
  160.         fprintf(stderr,"xcrash: ");
  161.         fprintf(stderr,msg);
  162.         fprintf(stderr,"\n");
  163.         fflush(stderr);
  164.         }
  165.     }
  166.  
  167. int Xcrash_ranint(c,name,max)
  168. Xcrash c;
  169. char *name;
  170. int max;
  171. /* Return an random integer with bounds 0 > value < max.  If Im reading
  172. from an input stream, read the value from the stream.  Otherwise, Ill
  173. generate the random value myself. */
  174.     {
  175.     static int initialized;
  176.     int value,numread;
  177.     char namein[100];
  178.  
  179.     if (!initialized)
  180.         {
  181.         if (c->seed == -1)
  182.             srandom((int)time((time_t *)0));
  183.         else
  184.             srandom(c->seed);
  185.         initialized = 1;
  186.         }
  187.     if (c->infile)
  188.         {
  189.         numread = fscanf(c->infile,"%90s%10d",namein,&value);
  190.         if (numread == EOF)
  191.             return(-1);
  192.         if (numread != 2)
  193.             {
  194.             Xcrash_error(c,"ERROR: bad input file");
  195.             return(-1);
  196.             }
  197.         if (strcmp(namein,name))
  198.             {
  199.             Xcrash_error(c,"ERROR: bad value name in input file");
  200.             return(-1);
  201.             }
  202.         }
  203.     else
  204.         value = random()%max;
  205.     if (c->trace)
  206.         {
  207.         printf ("%s %d\n",name,value);
  208.         fflush(stdout);
  209.         }
  210.     return(value);
  211.     }
  212.  
  213. void    Xcrash_random_xy(c,x,y)
  214. Xcrash c;
  215. short *x,*y;
  216. /* Generate a random (can be out of screen bounds) value and place in x
  217. and y */
  218.     {
  219.     if (!c->nasty)
  220.         {
  221.         *x = Xcrash_ranint(c,"x",c->w+10)-20;
  222.         *y = Xcrash_ranint(c,"y",c->h+10)-20;
  223.         }
  224.     else
  225.         {
  226.         *x = Xcrash_ranint(c,"x",100000);
  227.         *y = Xcrash_ranint(c,"y",100000);
  228.         }
  229.     }
  230.  
  231. Pixmap Xcrash_random_pixmap(c,depth)
  232. Xcrash c;
  233. int depth;
  234. /* Allocate a random pixmap and return it */
  235.     {
  236.     int loop,width,height;
  237.     char bits[25]; /* 5x5 max */
  238.  
  239.     width = Xcrash_ranint(c,"pw",5);
  240.     width++;
  241.     height= Xcrash_ranint(c,"ph",5);
  242.     height++;
  243.     for(loop=0;loop<(width*height);loop++)
  244.         bits[loop] = Xcrash_ranint(c,"bm",256);
  245.            return(XCreatePixmapFromBitmapData(c->dpy,c->win,bits,
  246.         width,height,c->fg,c->bg,depth));
  247.     }
  248.  
  249. void    Xcrash_change_GC(c,gcmask)
  250. Xcrash c;
  251. unsigned long gcmask;
  252. /* Change the graphics context.  The mask signifies which parts are
  253. possible for me to change */
  254.     {
  255.     Pixmap tilepix = 0,stipplepix = 0;
  256.     XGCValues g;
  257.     char dashes[5];
  258.     unsigned long bitmask;
  259.     int fontnum,loop,numdashes,dashoffset=0,numdashpixels;
  260.     static XFontStruct *currentfont = 0;
  261.     XColor color;
  262.     static char *fonts[] = 
  263.         {
  264.         "10x20","12x24","12x24kana","5x8","6x12",
  265.         "8x13bold","8x16romankana","9x15bold","fixed",
  266.         "heb6x13","kana14","kanji24","lucidasans-10",
  267.         "lucidasans-bolditalic-14","lucidasanstypewriter-bold-8",
  268.         "olcursor","olglyph-12","r16","rk16"
  269.         };
  270.  
  271.     if (gcmask & GCArcMode)
  272.         g.arc_mode = Xcrash_ranint(c,"am",2);
  273.     if (gcmask & GCBackground)
  274.         {
  275.         color.red = Xcrash_ranint(c,"rd",65536);
  276.         color.green = Xcrash_ranint(c,"gr",65536);
  277.         color.blue = Xcrash_ranint(c,"bl",65536);
  278.         color.flags = DoRed|DoGreen|DoBlue;
  279.         XAllocColor(c->dpy,c->cmap,&color); /* needs FreeColors? */
  280.         g.background = color.pixel;
  281.         }
  282.     if (gcmask & GCCapStyle)
  283.         g.cap_style = Xcrash_ranint(c,"cs",4);
  284.     if (gcmask & GCClipMask)
  285.         gcmask ^= GCClipMask; /* not used */
  286.     if (gcmask & GCClipXOrigin)
  287.         gcmask ^= GCClipXOrigin; /* not used */
  288.     if (gcmask & GCClipYOrigin)
  289.         gcmask ^= GCClipYOrigin; /* not used */
  290.     if (gcmask & GCLineStyle)
  291.         g.line_style = Xcrash_ranint(c,"ls",3);
  292.     if (gcmask & GCDashList)
  293.         {
  294.         if (g.line_style != LineSolid)
  295.             {
  296.             numdashes = Xcrash_ranint(c,"nd",4);
  297.             numdashes++;
  298.             numdashpixels = 0;
  299.             for (loop=0;loop<numdashes;loop++)
  300.                 {
  301.                 dashes[loop] = Xcrash_ranint(c,"ds",10);
  302.                 dashes[loop]++;
  303.                 numdashpixels += dashes[loop];
  304.                 }
  305.             dashoffset = Xcrash_ranint(c,"do",numdashpixels);
  306.             XSetDashes(c->dpy,c->gc,dashoffset,dashes,numdashes);
  307.             }
  308.         gcmask ^= GCDashList;
  309.         }
  310.     if (gcmask & GCDashOffset)
  311.         gcmask ^= GCDashOffset; /* performed in GCDashList */
  312.     if (gcmask & GCFillRule)
  313.         g.fill_rule = Xcrash_ranint(c,"fr",2);
  314.     if (gcmask & GCFillStyle)
  315.         g.fill_style = Xcrash_ranint(c,"fs",4);
  316.     if (gcmask & GCFont)
  317.         {
  318.         if (currentfont)
  319.             XFreeFont(c->dpy,currentfont);
  320.         fontnum = Xcrash_ranint(c,"ft",sizeof(fonts)/sizeof(char *));
  321.         currentfont = XLoadQueryFont(c->dpy,fonts[fontnum]); 
  322.         if (currentfont)
  323.             g.font = currentfont->fid;
  324.         else
  325.             {
  326.             Xcrash_error(c,"ERROR: Could not load basic font");
  327.             gcmask ^= GCFont;
  328.             }
  329.         }
  330.     if (gcmask & GCForeground)
  331.         {
  332.         color.red = Xcrash_ranint(c,"rd",65536);
  333.         color.green = Xcrash_ranint(c,"gr",65536);
  334.         color.blue = Xcrash_ranint(c,"bl",65536);
  335.         color.flags = DoRed|DoGreen|DoBlue;
  336.         XAllocColor(c->dpy,c->cmap,&color);
  337.         g.foreground = color.pixel;
  338.         }
  339.     if (gcmask & GCFunction)
  340.         g.function = Xcrash_ranint(c,"func",16);
  341.     if (gcmask & GCGraphicsExposures)
  342.         g.graphics_exposures = Xcrash_ranint(c,"ge",2);
  343.     if (gcmask & GCJoinStyle)
  344.         g.join_style = Xcrash_ranint(c,"js",3);
  345.     if (gcmask & GCLineWidth)
  346.         g.line_width = Xcrash_ranint(c,"lw",50);
  347.     if (gcmask & GCPlaneMask)
  348.         {
  349.         bitmask = 1 << Xcrash_ranint(c,"pm",c->depth);
  350.         g.plane_mask ^= bitmask;
  351.         }
  352.     if (gcmask & GCStipple)
  353.         {
  354.         if (stipplepix)
  355.             XFreePixmap(c->dpy,stipplepix);
  356.         stipplepix = Xcrash_random_pixmap(c,1);
  357.         g.stipple = stipplepix;
  358.         }
  359.     if (gcmask & GCSubwindowMode)
  360.         g.subwindow_mode = Xcrash_ranint(c,"sw",2);
  361.     if (gcmask & GCTile)
  362.         {
  363.         if (tilepix)
  364.             XFreePixmap(c->dpy,tilepix);
  365.         tilepix = Xcrash_random_pixmap(c,c->depth);
  366.         g.tile = tilepix;
  367.         }
  368.     if (gcmask & GCTileStipXOrigin)
  369.         g.ts_x_origin = Xcrash_ranint(c,"tsx",10);
  370.     if (gcmask & GCTileStipYOrigin)
  371.         g.ts_y_origin = Xcrash_ranint(c,"tsy",10);
  372.     XChangeGC(c->dpy,c->gc,gcmask,&g);
  373.     }
  374.  
  375. void    Xcrash_test_line(c)
  376. Xcrash c;
  377.     {
  378.     unsigned long gcmask;
  379.     int count,loop;
  380.     XPoint *points;
  381.     
  382.     gcmask=    GCFunction|GCPlaneMask|GCLineWidth|GCLineStyle|
  383.         GCCapStyle|GCJoinStyle|
  384.         GCFillStyle|GCSubwindowMode|GCClipXOrigin|
  385.         GCClipYOrigin|GCClipMask|GCForeground|GCBackground|
  386.         GCTile|GCStipple|GCTileStipXOrigin|GCTileStipYOrigin|
  387.         GCCapStyle|GCDashOffset|GCDashList;
  388.     Xcrash_change_GC(c,gcmask);
  389.     count = Xcrash_ranint(c,"count",10);
  390.     count++;
  391.     points = (XPoint *)malloc(sizeof(XPoint)*count);
  392.     if (!points)
  393.         return;
  394.     for (loop=0;loop<count;loop++)
  395.         Xcrash_random_xy(c,&points[loop].x,&points[loop].y);
  396.     XDrawLines(c->dpy,c->win,c->gc,points,count,CoordModeOrigin);
  397.     free(points);
  398.     }
  399.  
  400. void    Xcrash_test_segment(c)
  401. Xcrash c;
  402.     {
  403.     int count,loop;
  404.     XSegment *segments;
  405.     unsigned long gcmask;
  406.  
  407.     gcmask=    GCFunction|GCPlaneMask|GCLineWidth|GCLineStyle|
  408.         GCCapStyle|GCJoinStyle|
  409.         GCFillStyle|GCSubwindowMode|GCClipXOrigin|
  410.         GCClipYOrigin|GCClipMask|GCForeground|GCBackground|
  411.         GCTile|GCStipple|GCTileStipXOrigin|GCTileStipYOrigin|
  412.         GCCapStyle|GCDashOffset|GCDashList;
  413.     Xcrash_change_GC(c,gcmask);
  414.     count = Xcrash_ranint(c,"count",10);
  415.     count++;
  416.     segments = (XSegment *)malloc(sizeof(XSegment)*count);
  417.     if (!segments)
  418.         return;
  419.     for(loop=0;loop<count;loop++)
  420.         {
  421.         if (!loop)
  422.             Xcrash_random_xy(c,&segments[0].x1,&segments[0].y1);
  423.         else
  424.             {
  425.             segments[loop].x1=segments[loop-1].x2;
  426.             segments[loop].y1=segments[loop-1].y2;
  427.             }
  428.         Xcrash_random_xy(c,&segments[loop].x2,&segments[loop].y2);
  429.         }
  430.     XDrawSegments(c->dpy,c->win,c->gc,segments,count);
  431.     free(segments);
  432.     }
  433.  
  434. void    Xcrash_test_point(c)
  435. Xcrash c;
  436.     {
  437.     unsigned long gcmask;
  438.     int loop,count;
  439.     XPoint *points;
  440.  
  441.     gcmask=    GCFunction|GCPlaneMask|GCForeground|GCSubwindowMode|
  442.         GCClipXOrigin|GCClipYOrigin|GCClipMask;
  443.     Xcrash_change_GC(c,gcmask);
  444.     count = Xcrash_ranint(c,"count",10);
  445.     count++;
  446.     points = (XPoint *)malloc(sizeof(XPoint)*count);
  447.     if (!points)
  448.         return;
  449.     for (loop=0;loop<count;loop++)
  450.         Xcrash_random_xy(c,&points[loop].x,&points[loop].y);
  451.     XDrawPoints(c->dpy,c->win,c->gc,points,count,CoordModeOrigin);
  452.     free(points);
  453.     }
  454.  
  455. void    Xcrash_test_rect(c)
  456. Xcrash c;
  457.     {
  458.     unsigned long gcmask;
  459.     int count,loop;
  460.     XRectangle *recs;
  461.  
  462.     gcmask=    GCFunction|GCPlaneMask|GCLineWidth|GCLineStyle|
  463.         GCFillStyle|GCSubwindowMode|GCClipXOrigin|
  464.         GCClipYOrigin|GCClipMask|GCForeground|GCBackground|
  465.         GCTile|GCStipple|GCTileStipXOrigin|GCTileStipYOrigin|
  466.         GCCapStyle|GCDashOffset|GCDashList;
  467.     Xcrash_change_GC(c,gcmask);
  468.     count = Xcrash_ranint(c,"count",8);
  469.     count++;
  470.     recs = (XRectangle *)malloc(sizeof(XRectangle)*count);
  471.     if (!recs)
  472.         return;
  473.     for (loop=0;loop<count;loop++)
  474.         {
  475.         Xcrash_random_xy(c,&recs[loop].x,&recs[loop].y);
  476.         recs[loop].width = Xcrash_ranint(c,"width",200);
  477.         recs[loop].height = Xcrash_ranint(c,"height",200);
  478.                 }
  479.     XDrawRectangles(c->dpy,c->win,c->gc,recs,count);
  480.     XFillRectangles(c->dpy,c->win,c->gc,recs,count);
  481.     free(recs);
  482.     }
  483.  
  484. void    Xcrash_test_polygon(c)
  485. Xcrash c;
  486.     {
  487.     unsigned long gcmask;
  488.     int count,loop;
  489.     XPoint *points;
  490.  
  491.     gcmask=    GCFunction|GCPlaneMask|GCFillStyle|GCFillRule|
  492.         GCSubwindowMode|GCClipXOrigin|
  493.         GCClipYOrigin|GCClipMask|GCForeground|GCBackground|
  494.         GCTile|GCStipple|GCTileStipXOrigin|GCTileStipYOrigin;
  495.     Xcrash_change_GC(c,gcmask);
  496.     count = Xcrash_ranint(c,"count",10);
  497.     count++;
  498.     points =(XPoint *)malloc(sizeof(XPoint)*count);
  499.     if (!points)
  500.         return;
  501.     for (loop=0;loop<count;loop++)
  502.         Xcrash_random_xy(c,&points[loop].x,&points[loop].y);
  503.     XFillPolygon(c->dpy,c->win,c->gc,points,count,Complex,CoordModeOrigin);
  504.     free(points);
  505.     }
  506.  
  507. void    Xcrash_test_arc(c)
  508. Xcrash c;
  509.     {
  510.     XArc *arcs;
  511.     int loop,count;
  512.     unsigned long gcmask;
  513.  
  514.     gcmask=    GCFunction|GCPlaneMask|GCLineWidth|GCLineStyle|
  515.         GCFillStyle|GCArcMode|GCSubwindowMode|GCClipXOrigin|
  516.         GCClipYOrigin|GCClipMask|GCForeground|GCBackground|
  517.         GCTile|GCStipple|GCTileStipXOrigin|GCTileStipYOrigin|
  518.         GCCapStyle|GCDashOffset|GCDashList;
  519.     Xcrash_change_GC(c,gcmask);
  520.     count = Xcrash_ranint(c,"count",10);
  521.     count++;
  522.     arcs = (XArc *)malloc(sizeof(XArc)*count);
  523.     if (!arcs)
  524.         return;
  525.     for (loop=0;loop<count;loop++)
  526.         {
  527.         Xcrash_random_xy(c,&arcs[loop].x,&arcs[loop].y);
  528.         arcs[loop].width = Xcrash_ranint(c,"width",200);
  529.         arcs[loop].height = Xcrash_ranint(c,"height",200);
  530.         arcs[loop].angle1 = Xcrash_ranint(c,"ang1",400*64);
  531.         arcs[loop].angle2 = Xcrash_ranint(c,"ang2",400*64);
  532.                 }
  533.     XDrawArcs(c->dpy,c->win,c->gc,arcs,count);
  534.     XFillArcs(c->dpy,c->win,c->gc,arcs,count);
  535.     free(arcs);
  536.     }
  537.  
  538. void    Xcrash_test_text(c)
  539. Xcrash c;
  540.     {
  541.     short x,y;
  542.     unsigned long gcmask;
  543.     int loop;
  544.     static char string[20] = "Hal Computers ";
  545.  
  546.     gcmask=    GCFunction|GCPlaneMask|GCFillStyle|
  547.         GCFont|GCSubwindowMode|GCClipXOrigin|
  548.         GCClipYOrigin|GCClipMask|GCForeground|
  549.         GCBackground|GCTile|GCStipple|GCTileStipXOrigin|
  550.         GCTileStipYOrigin;
  551.     Xcrash_change_GC(c,gcmask);
  552.     Xcrash_random_xy(c,&x,&y);
  553.     for (loop=14;loop<20;loop++)
  554.         string[loop] = Xcrash_ranint(c,"ch",256);
  555.     XDrawString(c->dpy,c->win,c->gc,x,y,string,20);
  556.     XDrawImageString(c->dpy,c->win,c->gc,x,y,string,20);
  557.     }
  558.  
  559. void    Xcrash_test_text16(c)
  560. Xcrash c;
  561.     {
  562.     short x,y;
  563.     int loop;
  564.     XChar2b string[4];
  565.     unsigned long gcmask;
  566.  
  567.     gcmask=    GCFunction|GCPlaneMask|GCFillStyle|
  568.         GCFont|GCSubwindowMode|GCClipXOrigin|
  569.         GCClipYOrigin|GCClipMask|GCForeground|
  570.         GCBackground|GCTile|GCStipple|GCTileStipXOrigin|
  571.         GCTileStipYOrigin;
  572.     Xcrash_change_GC(c,gcmask);
  573.     Xcrash_random_xy(c,&x,&y);
  574.     for (loop=0;loop<4;loop++)
  575.         {
  576.         string[loop].byte1 = Xcrash_ranint(c,"c1",256);
  577.         string[loop].byte2 = Xcrash_ranint(c,"c2",256);
  578.         }
  579.     XDrawString16(c->dpy,c->win,c->gc,x,y,string,4);
  580.     XDrawImageString16(c->dpy,c->win,c->gc,x,y,string,4);
  581.     }
  582.  
  583. void    Xcrash_test_image(c)
  584. Xcrash c;
  585.     {
  586.     XImage *image;
  587.     short x1,y1,x2,y2,w,h;
  588.     unsigned long gcmask;
  589.  
  590.     gcmask=    GCFunction|GCPlaneMask|GCSubwindowMode|
  591.         GCClipXOrigin|GCClipYOrigin|
  592.         GCClipMask|GCForeground|GCBackground;
  593.     Xcrash_change_GC(c,gcmask);
  594.     w = Xcrash_ranint(c,"w",c->w);
  595.     h = Xcrash_ranint(c,"h",c->h);
  596.     x1 = Xcrash_ranint(c,"x1",c->w - w);
  597.     y1 = Xcrash_ranint(c,"y1",c->h - h);
  598.     Xcrash_random_xy(c,&x2,&y2);
  599.     image = XGetImage(c->dpy,c->win,x1,y1,w,h,AllPlanes,XYPixmap);
  600.     if (image)
  601.         {
  602.         XPutImage(c->dpy,c->win,c->gc,image,0,0,x2,y2,w,h);
  603.         XDestroyImage(image);
  604.         }
  605.     else
  606.         Xcrash_error(c,"ERROR: XGetImage returned null");
  607.     }
  608.  
  609. void    Xcrash_test_copy(c)
  610. Xcrash c;
  611.     {
  612.     short x1,y1,x2,y2,w,h;
  613.     unsigned long gcmask;
  614.     int plane;
  615.  
  616.     gcmask=    GCFunction|GCPlaneMask|GCSubwindowMode|
  617.         GCGraphicsExposures|GCClipXOrigin|GCClipYOrigin|
  618.         GCClipMask|GCForeground|GCBackground;
  619.     Xcrash_change_GC(c,gcmask);
  620.     w = Xcrash_ranint(c,"w",c->w);
  621.     h = Xcrash_ranint(c,"h",c->h);
  622.     x1 = Xcrash_ranint(c,"x1",c->w - w);
  623.     y1 = Xcrash_ranint(c,"y1",c->h - h);
  624.     Xcrash_random_xy(c,&x2,&y2);
  625.     XCopyArea(c->dpy,c->win,c->win,c->gc,x1,y1,w,h,x2,y2);
  626.     plane = 1 << Xcrash_ranint(c,"pl",c->depth);
  627.     XCopyPlane(c->dpy,c->win,c->win,c->gc,x1,y1,w,h,x2,y2,plane);
  628.     }
  629.  
  630. void    Xcrash_flush_events(c)
  631. Xcrash c;
  632. /* Flush the X event queue, placing window geometry changes in myself */
  633.     {
  634.     XEvent pe;
  635.     XExposeEvent *ee;
  636.     XConfigureEvent *ce;
  637.  
  638.     while (XPending(c->dpy))
  639.         {
  640.         XNextEvent(c->dpy, &pe);
  641.         switch (pe.type)
  642.             {
  643.             case Expose:
  644.                 ee = (XExposeEvent *)&pe;
  645.                 while (ee->count)
  646.                     {
  647.                     XNextEvent(c->dpy,&pe);
  648.                     ee = (XExposeEvent *)&pe;
  649.                     }
  650.                 break;
  651.             case KeyPress:
  652.                 exit(0);
  653.                 break;
  654.             case ConfigureNotify:
  655.                 /* hopefully wont happen.. */
  656.                 ce = (XConfigureEvent *)&pe;
  657.                 c->x = ce->x;
  658.                 c->y = ce->y;
  659.                 c->w = ce->width;
  660.                 c->h = ce->height;
  661.                 break;
  662.             default:
  663.                 break;
  664.             }
  665.         }
  666.     }
  667.  
  668. void    Xcrash_test_all(c)
  669. Xcrash c;
  670. /* Run through the different tests until the input file is empty, or
  671. until I am out of tests. */
  672.     {
  673.     int numtests,currentfunc,done=0;
  674.     static struct func_struct
  675.         {
  676.         void (*f)();
  677.         char *name;
  678.         } funcs[] =
  679.         {
  680.         {Xcrash_test_line,    "XDrawLines"},
  681.         {Xcrash_test_segment,    "XDrawSegments"},
  682.         {Xcrash_test_point,    "XDrawPoints"},
  683.         {Xcrash_test_rect,    "XDrawRectangles/XFillRectangles"},
  684.         {Xcrash_test_polygon,    "XFillPolygon"},
  685.         {Xcrash_test_arc,    "XDrawArcs/XFillArcs"},
  686.         {Xcrash_test_image,    "XGetImage/XPutImage"},
  687.         {Xcrash_test_copy,    "XCopyArea/XCopyPlane"},
  688.         {Xcrash_test_text,    "XDrawString/XDrawImageString"},
  689.         {Xcrash_test_text16,    "XDrawString16/XDrawImageString16"}
  690.         };
  691.         
  692.     if (!c)
  693.         return;
  694.     numtests = sizeof(funcs)/sizeof(struct func_struct);
  695.     Xcrash_ranint(c,Xcrash_version,1); /* version header for file */
  696.     while(!done)
  697.         {
  698.         Xcrash_flush_events(c);
  699.         currentfunc = Xcrash_ranint(c,"function",numtests);
  700.         if (currentfunc == -1)
  701.             done = 1;
  702.         else
  703.             {
  704.             Xcrash_error(c,funcs[currentfunc].name);
  705.             funcs[currentfunc].f(c);
  706.             XFlush(c->dpy);
  707.             }
  708.         if (!c->infile)
  709.             done = (--(c->numtests) <= 0);
  710.         }
  711.     }
  712.  
  713. void Xcrash_usage()
  714.     {
  715.     fprintf (stderr,"usage: xcrash\n    ");
  716.     fprintf (stderr," [-display {host}] [-tests {number}]");
  717.     fprintf (stderr," [-input {file}] [-quiet]\n    ");
  718.     fprintf (stderr," [-verbose] [-nasty] [-seed {number}]\n");
  719.     }
  720.  
  721. int main(argc,argv)
  722. int argc;
  723. char **argv;
  724.     {
  725.     Xcrash c;
  726.     int numtests=100,trace=0,quiet=0,nasty=0,seed= -1,loop;
  727.     char *infile=0,*display=0;
  728.  
  729.     for (loop=1;loop<argc;loop++)
  730.         {
  731.         if (argv[loop][0] != '-')
  732.             {
  733.             Xcrash_usage();
  734.             return(1);
  735.             }
  736.         switch (argv[loop][1])
  737.             {
  738.             case 'd':    /* display */
  739.                 if (++loop >= argc)
  740.                     {
  741.                     Xcrash_usage();
  742.                     return(1);
  743.                     }
  744.                 display = argv[loop];
  745.                 break;
  746.             case 'i':    /* input from file */
  747.                 if (++loop >= argc)
  748.                     {
  749.                     Xcrash_usage();
  750.                     return(1);
  751.                     }
  752.                 infile = argv[loop];
  753.                 break;
  754.             case 'n':    /* nasty mode */
  755.                 nasty = 1;
  756.                 break;
  757.             case 's':
  758.                 if (++loop >= argc)
  759.                     {
  760.                     Xcrash_usage();
  761.                     return(1);
  762.                     }
  763.                 seed = atoi(argv[loop]);
  764.                 break;
  765.             case 't':    /* number of tests */
  766.                 if (++loop >= argc)
  767.                     {
  768.                     Xcrash_usage();
  769.                     return(1);
  770.                     }
  771.                 numtests = atoi(argv[loop]);
  772.                 break;
  773.             case 'v':
  774.                 trace = 1;
  775.                 break;
  776.             case 'q':
  777.                 quiet = 1;
  778.                 break;
  779.             default:
  780.                 Xcrash_usage();
  781.                 return(1);
  782.             }
  783.         }
  784.  
  785.     c = Xcrash_new(display,numtests,infile,trace,quiet,nasty,seed);
  786.     Xcrash_test_all(c);
  787.     Xcrash_free(c);
  788.  
  789.     return(0);
  790.     }
  791.