xref: /petsc/src/sys/classes/draw/impls/x/xinit.c (revision 09440f2536211689395dd83abbfd05fbf503dd2c)
15c6c1daeSBarry Smith 
25c6c1daeSBarry Smith /*
35c6c1daeSBarry Smith    This file contains routines to open an X window display and window
45c6c1daeSBarry Smith    This consists of a number of routines that set the various
55c6c1daeSBarry Smith    fields in the Window structure, which is passed to
65c6c1daeSBarry Smith    all of these routines.
75c6c1daeSBarry Smith 
85c6c1daeSBarry Smith    Note that if you use the default visual and colormap, then you
95c6c1daeSBarry Smith    can use these routines with any X toolkit that will give you the
105c6c1daeSBarry Smith    Window id of the window that it is managing.  Use that instead of the
115c6c1daeSBarry Smith    call to PetscDrawXiCreateWindow .  Similarly for the Display.
125c6c1daeSBarry Smith */
135c6c1daeSBarry Smith 
145c6c1daeSBarry Smith #include <../src/sys/classes/draw/impls/x/ximpl.h>
155c6c1daeSBarry Smith 
1615d5bc79SLisandro Dalcin extern PetscErrorCode PetscDrawSetColormap_X(PetscDraw_X*,Colormap);
175c6c1daeSBarry Smith 
185c6c1daeSBarry Smith /*
1915d5bc79SLisandro Dalcin   PetscDrawXiOpenDisplay - Open and setup a display
205c6c1daeSBarry Smith */
215c6c1daeSBarry Smith #undef __FUNCT__
225c6c1daeSBarry Smith #define __FUNCT__ "PetscDrawXiOpenDisplay"
23*09440f25SLisandro Dalcin static PetscErrorCode PetscDrawXiOpenDisplay(PetscDraw_X *XiWin,const char display[])
245c6c1daeSBarry Smith {
255c6c1daeSBarry Smith   PetscFunctionBegin;
2615d5bc79SLisandro Dalcin   XiWin->disp = XOpenDisplay(display);
275c6c1daeSBarry Smith   if (!XiWin->disp) {
2815d5bc79SLisandro Dalcin     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to open display on %s\n\
2915d5bc79SLisandro Dalcin     Make sure your COMPUTE NODES are authorized to connect \n\
305c6c1daeSBarry Smith     to this X server and either your DISPLAY variable\n\
3115d5bc79SLisandro Dalcin     is set or you use the -display name option\n",display);
325c6c1daeSBarry Smith   }
335c6c1daeSBarry Smith   XiWin->screen     = DefaultScreen(XiWin->disp);
34481cee7bSLisandro Dalcin   XiWin->vis        = DefaultVisual(XiWin->disp,XiWin->screen);
35481cee7bSLisandro Dalcin   XiWin->depth      = DefaultDepth(XiWin->disp,XiWin->screen);
3615d5bc79SLisandro Dalcin   XiWin->cmap       = DefaultColormap(XiWin->disp,XiWin->screen);
3715d5bc79SLisandro Dalcin   XiWin->background = WhitePixel(XiWin->disp,XiWin->screen);
3815d5bc79SLisandro Dalcin   XiWin->foreground = BlackPixel(XiWin->disp,XiWin->screen);
395c6c1daeSBarry Smith   PetscFunctionReturn(0);
405c6c1daeSBarry Smith }
415c6c1daeSBarry Smith 
42815f00f0SLisandro Dalcin #undef __FUNCT__
43815f00f0SLisandro Dalcin #define __FUNCT__ "PetscDrawXiClose"
44815f00f0SLisandro Dalcin PetscErrorCode PetscDrawXiClose(PetscDraw_X *XiWin)
45815f00f0SLisandro Dalcin {
46815f00f0SLisandro Dalcin   PetscErrorCode ierr;
47815f00f0SLisandro Dalcin 
48815f00f0SLisandro Dalcin   PetscFunctionBegin;
49815f00f0SLisandro Dalcin   if (!XiWin) PetscFunctionReturn(0);
50815f00f0SLisandro Dalcin   ierr = PetscFree(XiWin->font);CHKERRQ(ierr);
51815f00f0SLisandro Dalcin   if (XiWin->disp) {
52815f00f0SLisandro Dalcin #if defined(PETSC_HAVE_SETJMP_H)
53815f00f0SLisandro Dalcin     jmp_buf              jmpbuf;
54815f00f0SLisandro Dalcin     PetscXIOErrorHandler xioerrhdl;
55815f00f0SLisandro Dalcin     ierr = PetscMemcpy(&jmpbuf,&PetscXIOErrorHandlerJumpBuf,sizeof(jmpbuf));CHKERRQ(ierr);
56815f00f0SLisandro Dalcin     xioerrhdl = PetscSetXIOErrorHandler(PetscXIOErrorHandlerJump);
57815f00f0SLisandro Dalcin     if (!setjmp(PetscXIOErrorHandlerJumpBuf))
58815f00f0SLisandro Dalcin #endif
59815f00f0SLisandro Dalcin     {
60815f00f0SLisandro Dalcin       XFreeGC(XiWin->disp,XiWin->gc.set);
61815f00f0SLisandro Dalcin       XCloseDisplay(XiWin->disp);
62815f00f0SLisandro Dalcin     }
63815f00f0SLisandro Dalcin     XiWin->disp = NULL;
64815f00f0SLisandro Dalcin #if defined(PETSC_HAVE_SETJMP_H)
65815f00f0SLisandro Dalcin     (void)PetscSetXIOErrorHandler(xioerrhdl);
66815f00f0SLisandro Dalcin     ierr = PetscMemcpy(&PetscXIOErrorHandlerJumpBuf,&jmpbuf,sizeof(jmpbuf));CHKERRQ(ierr);
67815f00f0SLisandro Dalcin #endif
68815f00f0SLisandro Dalcin   }
69815f00f0SLisandro Dalcin   PetscFunctionReturn(0);
70815f00f0SLisandro Dalcin }
71815f00f0SLisandro Dalcin 
725c6c1daeSBarry Smith /*
73*09440f25SLisandro Dalcin    PetscDrawXiCreateGC - setup the GC structure
745c6c1daeSBarry Smith */
755c6c1daeSBarry Smith #undef __FUNCT__
76*09440f25SLisandro Dalcin #define __FUNCT__ "PetscDrawXiCreateGC"
77*09440f25SLisandro Dalcin static PetscErrorCode PetscDrawXiCreateGC(PetscDraw_X *XiWin,PetscDrawXiPixVal fg)
785c6c1daeSBarry Smith {
795c6c1daeSBarry Smith   XGCValues gcvalues;             /* window graphics context values */
805c6c1daeSBarry Smith 
815c6c1daeSBarry Smith   PetscFunctionBegin;
825c6c1daeSBarry Smith   /* Set the graphics contexts */
835c6c1daeSBarry Smith   /* create a gc for the ROP_SET operation (writing the fg value to a pixel) */
845c6c1daeSBarry Smith   /* (do this with function GXcopy; GXset will automatically write 1) */
855c6c1daeSBarry Smith   gcvalues.function   = GXcopy;
865c6c1daeSBarry Smith   gcvalues.foreground = fg;
875c6c1daeSBarry Smith   XiWin->gc.cur_pix   = fg;
885c6c1daeSBarry Smith   XiWin->gc.set       = XCreateGC(XiWin->disp,RootWindow(XiWin->disp,XiWin->screen),GCFunction|GCForeground,&gcvalues);
8915d5bc79SLisandro Dalcin   if (!XiWin->gc.set) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to create X graphics context");
9015d5bc79SLisandro Dalcin   PetscFunctionReturn(0);
9115d5bc79SLisandro Dalcin }
9215d5bc79SLisandro Dalcin 
9315d5bc79SLisandro Dalcin /*
94815f00f0SLisandro Dalcin    PetscDrawXiInit - basic setup the draw (display, graphics context, font)
9515d5bc79SLisandro Dalcin */
9615d5bc79SLisandro Dalcin #undef __FUNCT__
97815f00f0SLisandro Dalcin #define __FUNCT__ "PetscDrawXiInit"
9865d9662dSLisandro Dalcin PetscErrorCode PetscDrawXiInit(PetscDraw_X *XiWin,const char display[])
9915d5bc79SLisandro Dalcin {
10015d5bc79SLisandro Dalcin   PetscErrorCode ierr;
10115d5bc79SLisandro Dalcin   PetscFunctionBegin;
10215d5bc79SLisandro Dalcin   ierr = PetscDrawXiOpenDisplay(XiWin,display);CHKERRQ(ierr);
103*09440f25SLisandro Dalcin   ierr = PetscDrawXiCreateGC(XiWin,XiWin->foreground);CHKERRQ(ierr);
10415d5bc79SLisandro Dalcin   ierr = PetscDrawXiFontFixed(XiWin,6,10,&XiWin->font);CHKERRQ(ierr);
1055c6c1daeSBarry Smith   PetscFunctionReturn(0);
1065c6c1daeSBarry Smith }
1075c6c1daeSBarry Smith 
1085c6c1daeSBarry Smith /*
109*09440f25SLisandro Dalcin     This routine waits until the window is actually created or destroyed
110*09440f25SLisandro Dalcin     Returns 0 if window is mapped; 1 if window is destroyed.
111*09440f25SLisandro Dalcin  */
112*09440f25SLisandro Dalcin #undef __FUNCT__
113*09440f25SLisandro Dalcin #define __FUNCT__ "PetscDrawXiWaitMap"
114*09440f25SLisandro Dalcin static PetscErrorCode PetscDrawXiWaitMap(PetscDraw_X *XiWin)
115*09440f25SLisandro Dalcin {
116*09440f25SLisandro Dalcin   XEvent event;
117*09440f25SLisandro Dalcin 
118*09440f25SLisandro Dalcin   PetscFunctionBegin;
119*09440f25SLisandro Dalcin   while (1) {
120*09440f25SLisandro Dalcin     XMaskEvent(XiWin->disp,ExposureMask|StructureNotifyMask,&event);
121*09440f25SLisandro Dalcin     if (event.xany.window != XiWin->win) break;
122*09440f25SLisandro Dalcin     else {
123*09440f25SLisandro Dalcin       switch (event.type) {
124*09440f25SLisandro Dalcin       case ConfigureNotify:
125*09440f25SLisandro Dalcin         /* window has been moved or resized */
126*09440f25SLisandro Dalcin         XiWin->w = event.xconfigure.width  - 2 * event.xconfigure.border_width;
127*09440f25SLisandro Dalcin         XiWin->h = event.xconfigure.height - 2 * event.xconfigure.border_width;
128*09440f25SLisandro Dalcin         break;
129*09440f25SLisandro Dalcin       case DestroyNotify:
130*09440f25SLisandro Dalcin         PetscFunctionReturn(1);
131*09440f25SLisandro Dalcin       case Expose:
132*09440f25SLisandro Dalcin         PetscFunctionReturn(0);
133*09440f25SLisandro Dalcin         /* else ignore event */
134*09440f25SLisandro Dalcin       }
135*09440f25SLisandro Dalcin     }
136*09440f25SLisandro Dalcin   }
137*09440f25SLisandro Dalcin   PetscFunctionReturn(0);
138*09440f25SLisandro Dalcin }
139*09440f25SLisandro Dalcin 
140*09440f25SLisandro Dalcin /*
1415c6c1daeSBarry Smith     Actually display a window at [x,y] with sizes (w,h)
1425c6c1daeSBarry Smith */
1435c6c1daeSBarry Smith #undef __FUNCT__
1445c6c1daeSBarry Smith #define __FUNCT__ "PetscDrawXiDisplayWindow"
145*09440f25SLisandro Dalcin static PetscErrorCode PetscDrawXiDisplayWindow(PetscDraw_X *XiWin,char *label,int x,int y,int w,int h)
1465c6c1daeSBarry Smith {
1475c6c1daeSBarry Smith   unsigned int         wavail,havail;
1485c6c1daeSBarry Smith   XSizeHints           size_hints;
1495c6c1daeSBarry Smith   XWindowAttributes    in_window_attributes;
1505c6c1daeSBarry Smith   XSetWindowAttributes window_attributes;
15115d5bc79SLisandro Dalcin   unsigned int         border_width = 0;
15215d5bc79SLisandro Dalcin   unsigned long        backgnd_pixel = WhitePixel(XiWin->disp,XiWin->screen);
1535c6c1daeSBarry Smith   unsigned long        wmask;
1545c6c1daeSBarry Smith 
1555c6c1daeSBarry Smith   PetscFunctionBegin;
1565c6c1daeSBarry Smith   /* get the available widths */
1575c6c1daeSBarry Smith   wavail = DisplayWidth(XiWin->disp,XiWin->screen);
1585c6c1daeSBarry Smith   havail = DisplayHeight(XiWin->disp,XiWin->screen);
1595c6c1daeSBarry Smith   if (w <= 0 || h <= 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"X Window display has invalid height or width");
1605c6c1daeSBarry Smith   if ((unsigned int)w > wavail) w = wavail;
1615c6c1daeSBarry Smith   if ((unsigned int)h > havail) h = havail;
1625c6c1daeSBarry Smith 
16315d5bc79SLisandro Dalcin   if (x < 0) x = (int)(wavail - (unsigned int)w + (unsigned int)x);
16415d5bc79SLisandro Dalcin   if (y < 0) y = (int)(havail - (unsigned int)h + (unsigned int)y);
16515d5bc79SLisandro Dalcin   x = ((unsigned int)x + w > wavail) ? (int)(wavail - (unsigned int)w) : x;
16615d5bc79SLisandro Dalcin   y = ((unsigned int)y + h > havail) ? (int)(havail - (unsigned int)h) : y;
1675c6c1daeSBarry Smith 
1685c6c1daeSBarry Smith   /* We need XCreateWindow since we may need an visual other than the default one */
1695c6c1daeSBarry Smith   XGetWindowAttributes(XiWin->disp,RootWindow(XiWin->disp,XiWin->screen),&in_window_attributes);
1705c6c1daeSBarry Smith   window_attributes.background_pixmap = None;
1715c6c1daeSBarry Smith   window_attributes.background_pixel  = backgnd_pixel;
1725c6c1daeSBarry Smith   /* No border for now */
1735c6c1daeSBarry Smith   window_attributes.border_pixmap     = None;
1745c6c1daeSBarry Smith   /*
1755c6c1daeSBarry Smith   window_attributes.border_pixel      = border_pixel;
1765c6c1daeSBarry Smith   */
1775c6c1daeSBarry Smith   window_attributes.bit_gravity       = in_window_attributes.bit_gravity;
1785c6c1daeSBarry Smith   window_attributes.win_gravity       = in_window_attributes.win_gravity;
1795c6c1daeSBarry Smith   /* Backing store is too slow in color systems */
18015d5bc79SLisandro Dalcin   window_attributes.backing_store     = NotUseful;
1815c6c1daeSBarry Smith   window_attributes.backing_pixel     = backgnd_pixel;
1825c6c1daeSBarry Smith   window_attributes.save_under        = 1;
1835c6c1daeSBarry Smith   window_attributes.event_mask        = 0;
1845c6c1daeSBarry Smith   window_attributes.do_not_propagate_mask = 0;
1855c6c1daeSBarry Smith   window_attributes.override_redirect = 0;
1865c6c1daeSBarry Smith   window_attributes.colormap          = XiWin->cmap;
1875c6c1daeSBarry Smith   /* None for cursor does NOT mean none, it means cursor of Parent */
1885c6c1daeSBarry Smith   window_attributes.cursor            = None;
189a297a907SKarl Rupp 
1905c6c1daeSBarry Smith   wmask = CWBackPixmap | CWBackPixel    | CWBorderPixmap  | CWBitGravity |
1915c6c1daeSBarry Smith           CWWinGravity | CWBackingStore | CWBackingPixel  | CWOverrideRedirect |
1925c6c1daeSBarry Smith           CWSaveUnder  | CWEventMask    | CWDontPropagate |
1935c6c1daeSBarry Smith           CWCursor     | CWColormap;
1945c6c1daeSBarry Smith 
19515d5bc79SLisandro Dalcin   XiWin->win = XCreateWindow(XiWin->disp,RootWindow(XiWin->disp,XiWin->screen),x,y,w,h,border_width,XiWin->depth,InputOutput,XiWin->vis,wmask,&window_attributes);
1965c6c1daeSBarry Smith   if (!XiWin->win) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to open X window");
1975c6c1daeSBarry Smith 
1985c6c1daeSBarry Smith   /* set window manager hints */
1995c6c1daeSBarry Smith   {
2005c6c1daeSBarry Smith     XWMHints      wm_hints;
2015c6c1daeSBarry Smith     XClassHint    class_hints;
2025c6c1daeSBarry Smith     XTextProperty windowname,iconname;
2035c6c1daeSBarry Smith 
204a297a907SKarl Rupp     if (label) XStringListToTextProperty(&label,1,&windowname);
205a297a907SKarl Rupp     else       XStringListToTextProperty(&label,0,&windowname);
206a297a907SKarl Rupp     if (label) XStringListToTextProperty(&label,1,&iconname);
207a297a907SKarl Rupp     else       XStringListToTextProperty(&label,0,&iconname);
2085c6c1daeSBarry Smith 
2095c6c1daeSBarry Smith     wm_hints.initial_state = NormalState;
2105c6c1daeSBarry Smith     wm_hints.input         = True;
2115c6c1daeSBarry Smith     wm_hints.flags         = StateHint|InputHint;
2125c6c1daeSBarry Smith 
2135c6c1daeSBarry Smith     /* These properties can be used by window managers to decide how to display a window */
2145c6c1daeSBarry Smith     class_hints.res_name  = (char*)"petsc";
2155c6c1daeSBarry Smith     class_hints.res_class = (char*)"PETSc";
2165c6c1daeSBarry Smith 
2175c6c1daeSBarry Smith     size_hints.x          = x;
2185c6c1daeSBarry Smith     size_hints.y          = y;
2195c6c1daeSBarry Smith     size_hints.min_width  = 4*border_width;
2205c6c1daeSBarry Smith     size_hints.min_height = 4*border_width;
2215c6c1daeSBarry Smith     size_hints.width      = w;
2225c6c1daeSBarry Smith     size_hints.height     = h;
2235c6c1daeSBarry Smith     size_hints.flags      = USPosition | USSize | PMinSize;
2245c6c1daeSBarry Smith 
2255c6c1daeSBarry Smith     XSetWMProperties(XiWin->disp,XiWin->win,&windowname,&iconname,0,0,&size_hints,&wm_hints,&class_hints);
2265c6c1daeSBarry Smith     XFree((void*)windowname.value);
2275c6c1daeSBarry Smith     XFree((void*)iconname.value);
2285c6c1daeSBarry Smith   }
229481cee7bSLisandro Dalcin 
2305c6c1daeSBarry Smith   /* make the window visible */
2315c6c1daeSBarry Smith   XSelectInput(XiWin->disp,XiWin->win,ExposureMask|StructureNotifyMask);
2325c6c1daeSBarry Smith   XMapWindow(XiWin->disp,XiWin->win);
2335c6c1daeSBarry Smith 
2345c6c1daeSBarry Smith   /* some window systems are cruel and interfere with the placement of
2355c6c1daeSBarry Smith      windows.  We wait here for the window to be created or to die */
236*09440f25SLisandro Dalcin   if (PetscDrawXiWaitMap(XiWin)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Wait for X window failed");
2375c6c1daeSBarry Smith   PetscFunctionReturn(0);
2385c6c1daeSBarry Smith }
2395c6c1daeSBarry Smith 
2405c6c1daeSBarry Smith #undef __FUNCT__
2415c6c1daeSBarry Smith #define __FUNCT__ "PetscDrawXiQuickWindow"
24215d5bc79SLisandro Dalcin PetscErrorCode PetscDrawXiQuickWindow(PetscDraw_X *XiWin,char *name,int x,int y,int nx,int ny)
2435c6c1daeSBarry Smith {
24415d5bc79SLisandro Dalcin   Window         root;
24515d5bc79SLisandro Dalcin   unsigned int   w,h,dummy;
2465c6c1daeSBarry Smith   PetscErrorCode ierr;
2475c6c1daeSBarry Smith 
2485c6c1daeSBarry Smith   PetscFunctionBegin;
24915d5bc79SLisandro Dalcin   ierr = PetscDrawSetColormap_X(XiWin,(Colormap)0);CHKERRQ(ierr);
25015d5bc79SLisandro Dalcin   ierr = PetscDrawXiDisplayWindow(XiWin,name,x,y,nx,ny);CHKERRQ(ierr);
25115d5bc79SLisandro Dalcin   XSetWindowBackground(XiWin->disp,XiWin->win,XiWin->background);
25215d5bc79SLisandro Dalcin   XClearWindow(XiWin->disp,XiWin->win);
2535c6c1daeSBarry Smith 
25415d5bc79SLisandro Dalcin   XGetGeometry(XiWin->disp,XiWin->win,&root,&x,&y,&w,&h,&dummy,&dummy);
25515d5bc79SLisandro Dalcin   XiWin->x = x;
25615d5bc79SLisandro Dalcin   XiWin->y = y;
25715d5bc79SLisandro Dalcin   XiWin->w = (int)w;
25815d5bc79SLisandro Dalcin   XiWin->h = (int)h;
2595c6c1daeSBarry Smith   PetscFunctionReturn(0);
2605c6c1daeSBarry Smith }
2615c6c1daeSBarry Smith 
2625c6c1daeSBarry Smith /*
2635c6c1daeSBarry Smith    A version from an already defined window
2645c6c1daeSBarry Smith */
2655c6c1daeSBarry Smith #undef __FUNCT__
2665c6c1daeSBarry Smith #define __FUNCT__ "PetscDrawXiQuickWindowFromWindow"
26715d5bc79SLisandro Dalcin PetscErrorCode PetscDrawXiQuickWindowFromWindow(PetscDraw_X *XiWin,Window win)
2685c6c1daeSBarry Smith {
2695c6c1daeSBarry Smith   Window            root;
27015d5bc79SLisandro Dalcin   int               x,y;
27115d5bc79SLisandro Dalcin   unsigned int      w,h,dummy;
2725c6c1daeSBarry Smith   XWindowAttributes attributes;
27315d5bc79SLisandro Dalcin   PetscErrorCode    ierr;
2745c6c1daeSBarry Smith 
2755c6c1daeSBarry Smith   PetscFunctionBegin;
27615d5bc79SLisandro Dalcin   XiWin->win = win;
27715d5bc79SLisandro Dalcin   XGetWindowAttributes(XiWin->disp,XiWin->win,&attributes);
27815d5bc79SLisandro Dalcin   ierr = PetscDrawSetColormap_X(XiWin,attributes.colormap);CHKERRQ(ierr);
279481cee7bSLisandro Dalcin 
28015d5bc79SLisandro Dalcin   XGetGeometry(XiWin->disp,XiWin->win,&root,&x,&y,&w,&h,&dummy,&dummy);
28115d5bc79SLisandro Dalcin   XiWin->x = x;
28215d5bc79SLisandro Dalcin   XiWin->y = y;
28315d5bc79SLisandro Dalcin   XiWin->w = (int)w;
28415d5bc79SLisandro Dalcin   XiWin->h = (int)h;
2855c6c1daeSBarry Smith   PetscFunctionReturn(0);
2865c6c1daeSBarry Smith }
2875c6c1daeSBarry Smith 
2885c6c1daeSBarry Smith 
289*09440f25SLisandro Dalcin #undef __FUNCT__
290*09440f25SLisandro Dalcin #define __FUNCT__ "PetscDrawXiQuickPixmap"
291*09440f25SLisandro Dalcin PetscErrorCode PetscDrawXiQuickPixmap(PetscDraw_X* XiWin)
292*09440f25SLisandro Dalcin {
2935c6c1daeSBarry Smith   PetscFunctionBegin;
294*09440f25SLisandro Dalcin   if (XiWin->drw) XFreePixmap(XiWin->disp,XiWin->drw);
295*09440f25SLisandro Dalcin   XiWin->drw = XCreatePixmap(XiWin->disp,RootWindow(XiWin->disp,XiWin->screen),XiWin->w,XiWin->h,XiWin->depth);
296*09440f25SLisandro Dalcin   PetscDrawXiSetPixVal(XiWin,XiWin->background);
297*09440f25SLisandro Dalcin   XFillRectangle(XiWin->disp,XiWin->drw,XiWin->gc.set,0,0,XiWin->w,XiWin->h);
298*09440f25SLisandro Dalcin   XSync(XiWin->disp,False);
2995c6c1daeSBarry Smith   PetscFunctionReturn(0);
3005c6c1daeSBarry Smith }
3015c6c1daeSBarry Smith 
302*09440f25SLisandro Dalcin PETSC_INTERN PetscErrorCode PetscDrawSetSave_X(PetscDraw,const char[]);
303*09440f25SLisandro Dalcin 
3045c6c1daeSBarry Smith #undef __FUNCT__
3055c6c1daeSBarry Smith #define __FUNCT__ "PetscDrawSetSave_X"
3065c6c1daeSBarry Smith PetscErrorCode PetscDrawSetSave_X(PetscDraw draw,const char *filename)
3075c6c1daeSBarry Smith {
3085c6c1daeSBarry Smith   PetscErrorCode ierr;
3095c6c1daeSBarry Smith #if defined(PETSC_HAVE_POPEN)
3105c6c1daeSBarry Smith   PetscMPIInt    rank;
3115c6c1daeSBarry Smith #endif
3125c6c1daeSBarry Smith 
3135c6c1daeSBarry Smith   PetscFunctionBegin;
3145c6c1daeSBarry Smith   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
3155c6c1daeSBarry Smith #if defined(PETSC_HAVE_POPEN)
316ce94432eSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);CHKERRQ(ierr);
3175c6c1daeSBarry Smith   if (!rank) {
318d45a07a7SBarry Smith     char  command[PETSC_MAX_PATH_LEN];
319d45a07a7SBarry Smith     FILE  *fd;
320d45a07a7SBarry Smith     int   err;
321d45a07a7SBarry Smith 
322d45a07a7SBarry Smith     ierr = PetscMemzero(command,sizeof(command));CHKERRQ(ierr);
3239982bd17SBarry Smith     ierr = PetscSNPrintf(command,PETSC_MAX_PATH_LEN,"rm -fr %s %s.m4v",draw->savefilename,draw->savefilename);CHKERRQ(ierr);
324e97f6855SBarry Smith     ierr = PetscPOpen(PETSC_COMM_SELF,NULL,command,"r",&fd);CHKERRQ(ierr);
3250076e027SBarry Smith     ierr = PetscPClose(PETSC_COMM_SELF,fd,&err);CHKERRQ(ierr);
3269982bd17SBarry Smith     ierr = PetscSNPrintf(command,PETSC_MAX_PATH_LEN,"mkdir %s",draw->savefilename);CHKERRQ(ierr);
327e97f6855SBarry Smith     ierr = PetscPOpen(PETSC_COMM_SELF,NULL,command,"r",&fd);CHKERRQ(ierr);
3280076e027SBarry Smith     ierr = PetscPClose(PETSC_COMM_SELF,fd,&err);CHKERRQ(ierr);
3295c6c1daeSBarry Smith   }
3305c6c1daeSBarry Smith #endif
3315c6c1daeSBarry Smith   PetscFunctionReturn(0);
3325c6c1daeSBarry Smith }
3335c6c1daeSBarry Smith 
3341cda70a7SBarry Smith 
3355c6c1daeSBarry Smith #if defined(PETSC_HAVE_AFTERIMAGE)
3365c6c1daeSBarry Smith #include <afterimage.h>
337aee23540SBarry Smith 
33876f01e85SBarry Smith /* String names of possible Afterimage formats */
33976f01e85SBarry Smith const char *PetscAfterImageFormats[] = {
34076f01e85SBarry Smith         ".Xpm",
34176f01e85SBarry Smith 	".Xpm.Z",
34276f01e85SBarry Smith 	".Xpm.gz",
34376f01e85SBarry Smith 	".Png",
34476f01e85SBarry Smith 	".Jpeg",
345f140b876SBarry Smith 	".Xcf", /* Gimp format */
34676f01e85SBarry Smith 	".Ppm",
34776f01e85SBarry Smith 	".Pnm",
348f140b876SBarry Smith 	"MS Windows Bitmap",
349f140b876SBarry Smith 	"MS Windows Icon",
350f140b876SBarry Smith 	"MS Windows Cursor",
35176f01e85SBarry Smith 	".Gif",
35276f01e85SBarry Smith 	".Tiff",
353f140b876SBarry Smith 	"Afterstep XMLScript",
354f140b876SBarry Smith 	"Scalable Vector Graphics (SVG)",
35576f01e85SBarry Smith 	".Xbm",
35676f01e85SBarry Smith 	"Targa",
35776f01e85SBarry Smith 	".Pcx",
35876f01e85SBarry Smith 	".HTML",
35976f01e85SBarry Smith 	"XML",
36076f01e85SBarry Smith 	"Unknown"
361aee23540SBarry Smith };
362aee23540SBarry Smith 
363aee23540SBarry Smith #undef __FUNCT__
36476f01e85SBarry Smith #define __FUNCT__ "PetscAfterimageStringToFormat"
36576f01e85SBarry Smith static PetscErrorCode PetscAfterimageStringToFormat(const char *ext,ASImageFileTypes *format)
366aee23540SBarry Smith {
36776f01e85SBarry Smith   PetscInt       i;
368aee23540SBarry Smith   PetscErrorCode ierr;
36976f01e85SBarry Smith   PetscBool      flg;
370aee23540SBarry Smith 
371aee23540SBarry Smith   PetscFunctionBegin;
372f140b876SBarry Smith   ierr = PetscStrcasecmp(".Jpg",ext,&flg);CHKERRQ(ierr);
373f140b876SBarry Smith   if (flg) ext = ".Jpeg";
37476f01e85SBarry Smith   for (i=0; i<sizeof(PetscAfterImageFormats)/sizeof(char**); i++) {
37576f01e85SBarry Smith     ierr = PetscStrcasecmp(PetscAfterImageFormats[i],ext,&flg);CHKERRQ(ierr);
37676f01e85SBarry Smith     if (flg) {
37776f01e85SBarry Smith       *format = (ASImageFileTypes)i;
37876f01e85SBarry Smith       PetscFunctionReturn(0);
37976f01e85SBarry Smith     }
38076f01e85SBarry Smith   }
38176f01e85SBarry Smith   *format = ASIT_Unknown;
38276f01e85SBarry Smith   PetscFunctionReturn(0);
38376f01e85SBarry Smith }
38476f01e85SBarry Smith 
38576f01e85SBarry Smith #if defined(PETSC_HAVE_SAWS)
38676f01e85SBarry Smith #include <petscviewersaws.h>
38776f01e85SBarry Smith /*
38876f01e85SBarry Smith   The PetscAfterimage object and functions are used to maintain a list of file images created by Afterimage that can
38976f01e85SBarry Smith   be displayed by the SAWs webserver.
39076f01e85SBarry Smith */
39176f01e85SBarry Smith typedef struct _P_PetscAfterimage *PetscAfterimage;
39276f01e85SBarry Smith struct _P_PetscAfterimage {
39376f01e85SBarry Smith   PetscAfterimage next;
39476f01e85SBarry Smith   char            *filename;
39576f01e85SBarry Smith   char            *ext;
39676f01e85SBarry Smith   PetscInt        cnt;
39776f01e85SBarry Smith } ;
39876f01e85SBarry Smith 
39976f01e85SBarry Smith static PetscAfterimage afterimages = 0;
40076f01e85SBarry Smith 
40176f01e85SBarry Smith #undef __FUNCT__
40276f01e85SBarry Smith #define __FUNCT__ "PetscAfterimageDestroy"
40376f01e85SBarry Smith static PetscErrorCode PetscAfterimageDestroy(void)
40476f01e85SBarry Smith {
40576f01e85SBarry Smith   PetscErrorCode ierr;
40676f01e85SBarry Smith   PetscAfterimage       afterimage,oafterimage = afterimages;
40776f01e85SBarry Smith 
40876f01e85SBarry Smith   PetscFunctionBegin;
40976f01e85SBarry Smith   while (oafterimage) {
41076f01e85SBarry Smith     afterimage = oafterimage->next;
41176f01e85SBarry Smith     ierr = PetscFree(oafterimage->filename);CHKERRQ(ierr);
41276f01e85SBarry Smith     ierr = PetscFree(oafterimage->ext);CHKERRQ(ierr);
41376f01e85SBarry Smith     ierr = PetscFree(oafterimage);CHKERRQ(ierr);
41476f01e85SBarry Smith     oafterimage = afterimage;
415aee23540SBarry Smith   }
416aee23540SBarry Smith   PetscFunctionReturn(0);
417aee23540SBarry Smith }
418aee23540SBarry Smith 
419aee23540SBarry Smith #undef __FUNCT__
42076f01e85SBarry Smith #define __FUNCT__ "PetscAfterimageAdd"
42176f01e85SBarry Smith static PetscErrorCode PetscAfterimageAdd(const char *filename,const char *ext,PetscInt cnt)
422aee23540SBarry Smith {
423aee23540SBarry Smith   PetscErrorCode   ierr;
42476f01e85SBarry Smith   PetscAfterimage  afterimage,oafterimage = afterimages;
425aee23540SBarry Smith   PetscBool        flg;
426aee23540SBarry Smith 
427aee23540SBarry Smith   PetscFunctionBegin;
42876f01e85SBarry Smith   if (oafterimage){
42976f01e85SBarry Smith     ierr = PetscStrcmp(filename,oafterimage->filename,&flg);CHKERRQ(ierr);
43076f01e85SBarry Smith     if (flg) {
43176f01e85SBarry Smith       oafterimage->cnt = cnt;
43276f01e85SBarry Smith       PetscFunctionReturn(0);
433aee23540SBarry Smith     }
43476f01e85SBarry Smith     while (oafterimage->next) {
43576f01e85SBarry Smith       oafterimage = oafterimage->next;
43676f01e85SBarry Smith       ierr = PetscStrcmp(filename,oafterimage->filename,&flg);CHKERRQ(ierr);
43776f01e85SBarry Smith       if (flg) {
43876f01e85SBarry Smith         oafterimage->cnt = cnt;
43976f01e85SBarry Smith         PetscFunctionReturn(0);
44076f01e85SBarry Smith       }
44176f01e85SBarry Smith     }
44276f01e85SBarry Smith     ierr = PetscNew(&afterimage);CHKERRQ(ierr);
44376f01e85SBarry Smith     oafterimage->next = afterimage;
444aee23540SBarry Smith   } else {
44576f01e85SBarry Smith     ierr = PetscNew(&afterimage);CHKERRQ(ierr);
44676f01e85SBarry Smith     afterimages = afterimage;
447aee23540SBarry Smith   }
44876f01e85SBarry Smith   ierr = PetscStrallocpy(filename,&afterimage->filename);CHKERRQ(ierr);
44976f01e85SBarry Smith   ierr = PetscStrallocpy(ext,&afterimage->ext);CHKERRQ(ierr);
45076f01e85SBarry Smith   afterimage->cnt = cnt;
45176f01e85SBarry Smith   ierr = PetscRegisterFinalize(PetscAfterimageDestroy);CHKERRQ(ierr);
452aee23540SBarry Smith   PetscFunctionReturn(0);
453aee23540SBarry Smith }
454aee23540SBarry Smith 
455aee23540SBarry Smith #endif
456aee23540SBarry Smith 
457*09440f25SLisandro Dalcin PETSC_INTERN PetscErrorCode PetscDrawSave_X(PetscDraw);
458*09440f25SLisandro Dalcin 
4595c6c1daeSBarry Smith #undef __FUNCT__
4605c6c1daeSBarry Smith #define __FUNCT__ "PetscDrawSave_X"
4615c6c1daeSBarry Smith PetscErrorCode PetscDrawSave_X(PetscDraw draw)
4625c6c1daeSBarry Smith {
4635c6c1daeSBarry Smith   PetscDraw_X      *drawx = (PetscDraw_X*)draw->data;
4645c6c1daeSBarry Smith   XImage           *image;
4655c6c1daeSBarry Smith   ASImage          *asimage;
466681455b2SBarry Smith   struct  ASVisual *asv;
4675c6c1daeSBarry Smith   char             filename[PETSC_MAX_PATH_LEN];
4685c6c1daeSBarry Smith   PetscErrorCode   ierr;
4695c6c1daeSBarry Smith   PetscMPIInt      rank;
470681455b2SBarry Smith   int              depth;
47176f01e85SBarry Smith   ASImageFileTypes format;
4725c6c1daeSBarry Smith 
4735c6c1daeSBarry Smith   PetscFunctionBegin;
4745c6c1daeSBarry Smith   if (!draw->savefilename) PetscFunctionReturn(0);
4755b399a63SLisandro Dalcin   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);CHKERRQ(ierr);
4765b399a63SLisandro Dalcin 
4775b399a63SLisandro Dalcin   ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
4785b399a63SLisandro Dalcin   XSync(drawx->disp,True);
4795b399a63SLisandro Dalcin   ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
4805b399a63SLisandro Dalcin   ierr = MPI_Barrier(PetscObjectComm((PetscObject)draw));CHKERRQ(ierr);
4815b399a63SLisandro Dalcin 
4825b399a63SLisandro Dalcin   ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
4835b399a63SLisandro Dalcin   if (rank) goto finally; /* only process 0 handles the saving business */
484681455b2SBarry Smith   depth = DefaultDepth(drawx->disp,drawx->screen);
485681455b2SBarry Smith   asv   = create_asvisual(drawx->disp,drawx->screen,depth,NULL);if (!asv) SETERRQ(PetscObjectComm((PetscObject)draw),PETSC_ERR_PLIB,"Cannot create AfterImage ASVisual");
4865b399a63SLisandro Dalcin   image = XGetImage(drawx->disp,PetscDrawXiDrawable(drawx),0,0,drawx->w,drawx->h,AllPlanes,ZPixmap);
48776f01e85SBarry Smith   if (!image) SETERRQ(PetscObjectComm((PetscObject)draw),PETSC_ERR_PLIB,"Cannot XGetImage()");
488ce94432eSBarry Smith   asimage = picture_ximage2asimage(asv,image,0,0);if (!asimage) SETERRQ(PetscObjectComm((PetscObject)draw),PETSC_ERR_PLIB,"Cannot create AfterImage ASImage");
4898b7fcac6SBarry Smith   if (draw->savesinglefile) {
49076f01e85SBarry Smith     ierr = PetscSNPrintf(filename,PETSC_MAX_PATH_LEN,"%s/%s%s",draw->savefilename,draw->savefilename,draw->savefilenameext);CHKERRQ(ierr);
4918b7fcac6SBarry Smith   } else {
49276f01e85SBarry Smith     ierr = PetscSNPrintf(filename,PETSC_MAX_PATH_LEN,"%s/%s_%d%s",draw->savefilename,draw->savefilename,draw->savefilecount++,draw->savefilenameext);CHKERRQ(ierr);
4938b7fcac6SBarry Smith   }
49476f01e85SBarry Smith   ierr = PetscAfterimageStringToFormat(draw->savefilenameext,&format);CHKERRQ(ierr);
49576f01e85SBarry Smith   ASImage2file(asimage,0,filename,format,0);
4961cda70a7SBarry Smith #if defined(PETSC_HAVE_SAWS)
4971cda70a7SBarry Smith   {
498aee23540SBarry Smith     char     body[4096];
49976f01e85SBarry Smith     PetscAfterimage afterimage;
500aee23540SBarry Smith     size_t   len = 0;
501aee23540SBarry Smith 
50276f01e85SBarry Smith     ierr = PetscAfterimageAdd(draw->savefilename,draw->savefilenameext,draw->savefilecount-1);CHKERRQ(ierr);
50376f01e85SBarry Smith     afterimage  = afterimages;
50476f01e85SBarry Smith     while (afterimage) {
50576f01e85SBarry Smith       if (draw->savesinglefile) {
50676f01e85SBarry Smith         ierr = PetscSNPrintf(body+len,4086-len,"<img src=\"%s/%s%s\" alt=\"None\">",afterimage->filename,afterimage->filename,afterimage->ext);CHKERRQ(ierr);
50776f01e85SBarry Smith       } else {
50876f01e85SBarry Smith         ierr = PetscSNPrintf(body+len,4086-len,"<img src=\"%s/%s_%d%s\" alt=\"None\">",afterimage->filename,afterimage->filename,afterimage->cnt,afterimage->ext);CHKERRQ(ierr);
50976f01e85SBarry Smith       }
510aee23540SBarry Smith       ierr = PetscStrlen(body,&len);CHKERRQ(ierr);
51176f01e85SBarry Smith       afterimage  = afterimage->next;
512aee23540SBarry Smith     }
513aee23540SBarry Smith     ierr = PetscStrcat(body,"<br>\n");CHKERRQ(ierr);
51443da4ab2SBarry Smith     if (draw->savefilecount > 0) PetscStackCallSAWs(SAWs_Pop_Body,("index.html",1));
51543da4ab2SBarry Smith     PetscStackCallSAWs(SAWs_Push_Body,("index.html",1,body));
5161cda70a7SBarry Smith   }
5171cda70a7SBarry Smith #endif
518681455b2SBarry Smith   destroy_asvisual(asv,0);
5195b399a63SLisandro Dalcin   XDestroyImage(image);
5205b399a63SLisandro Dalcin finally:
5215b399a63SLisandro Dalcin   ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
5225c6c1daeSBarry Smith   PetscFunctionReturn(0);
5235c6c1daeSBarry Smith }
5245b399a63SLisandro Dalcin 
5255c6c1daeSBarry Smith /*
5265c6c1daeSBarry Smith    There are routines wanted by AfterImage for PNG files
5275c6c1daeSBarry Smith  */
5285c6c1daeSBarry Smith void crc32(void) {;}
5295c6c1daeSBarry Smith void inflateReset(void) {;}
5305c6c1daeSBarry Smith void deflateReset(void) {;}
5315c6c1daeSBarry Smith void deflateInit2(void) {;}
5325c6c1daeSBarry Smith void deflateInit2_(void) {;}
5335c6c1daeSBarry Smith void deflate(void) {;}
5345c6c1daeSBarry Smith void deflateEnd(void) {;}
5355c6c1daeSBarry Smith 
5365c6c1daeSBarry Smith #endif
5375c6c1daeSBarry Smith 
5385c6c1daeSBarry Smith 
5395c6c1daeSBarry Smith 
540