/*
Programmazione II - Helper grafico.
File : xhelper.c
Author : Francesco Prelz ($Author: prelz $)
e-mail : "francesco.prelz@mi.infn.it"
Revision history :
14-Jul-2000 Original release
Description: Helper routines for drawing on simple, deaf&dumb X-windows.
Their main use is to demonstrate graphics programming.
They can be engineered way better but that's not my job.
*/
#include
#include
#include
#include
#include
#include
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
Display *XHLP_display=NULL; /* X server connection */
Screen *XHLP_screen_id; /* ID of server screen. */
int XHLP_max_windows=0; /* Max Number of defined windows */
/* Window information */
typedef struct XHLP_winfo_t
{
Window window; /* Window */
GC gc; /* Graphic Context */
} XHLP_winfo;
XHLP_winfo **XHLP_window_handles=NULL; /* Window handle array */
/* Amount of pixels to "stagger" the initial position of windows */
#define XHLP_INITIAL_OPEN_STEP 20
#define XHLP_check_window_status() \
/* Is the display open ? */ \
if (XHLP_display == NULL) return(-1); \
/* Is this window a good one ? */ \
if (cur_h < 0 || cur_h >= XHLP_max_windows) return(-1); \
if (XHLP_window_handles[cur_h] == NULL) return(-1);
#ifdef TEST_LIBRARY
/* This is just a library test main program */
int
main(void)
{
int retcod;
int w_1,w_2;
float angle = 0;
int radius = 50;
int centerx, centery;
char *display;
unsigned int id;
char dumb[16];
retcod = XHLP_open_display(NULL);
printf("XHLP_open_display returns %d.\n",retcod);
retcod = XHLP_open_window(250,200,"Test1");
printf("XHLP_open_window returns %d.\n",retcod);
if (retcod >= 0) w_1 = retcod;
else exit(1);
retcod = XHLP_open_window(150,100,"Test2");
printf("XHLP_open_window returns %d.\n",retcod);
if (retcod >= 0) w_2 = retcod;
else exit(1);
XHLP_print(w_1, 10, 10, "Window # 1");
XHLP_print(w_2, 10, 10, "Window # 2");
XHLP_get_click(w_1, ¢erx, ¢ery);
XHLP_set_color(w_1, "#ffc000");
for (angle = 0; angle < 2*M_PI; angle += 0.1)
{
XHLP_draw_line(w_1, centerx, centery,
centerx + (int)(radius*cos(angle)),
centery + (int)(radius*sin(angle)));
}
XHLP_get_click(w_2, ¢erx, ¢ery);
XHLP_set_color(w_2, "darkblue");
for (angle = 0; angle < 2*M_PI; angle += 0.1)
{
XHLP_draw_line(w_2, centerx, centery,
centerx + (int)(radius*cos(angle)),
centery + (int)(radius*sin(angle)));
}
sleep(2);
XHLP_clear_window(w_2);
XHLP_set_color(w_2, "green2");
XHLP_get_click(w_2, ¢erx, ¢ery);
for (angle = 0; angle < 2*M_PI; angle += 0.1)
{
XHLP_draw_line(w_2, centerx, centery,
centerx + (int)(radius*cos(angle)),
centery + (int)(radius*sin(angle)));
}
XHLP_get_display_id(w_1, &display, &id);
printf("Window 1 is on display <%s>, id=0x%x\n", display, id);
printf("Press to close windows.");
fgets(dumb,sizeof(dumb),stdin);
retcod = XHLP_close_window(w_1);
printf("XHLP_close_window returns %d.\n",retcod);
retcod = XHLP_close_window(w_2);
printf("XHLP_close_window returns %d.\n",retcod);
XHLP_close_display();
exit(0);
}
#endif
int
XHLP_open_display(char *display)
{
/* Make sure we don't leave another display open */
if (XHLP_display != NULL) XHLP_close_display();
/* Open X display. If display is NULL the DISPLAY env variable will
be used. */
XHLP_display = XOpenDisplay(display);
if (XHLP_display == NULL)
{
return(-1);
}
/* Store screen ID. */
XHLP_screen_id = XDefaultScreenOfDisplay(XHLP_display);
return(0);
}
int
XHLP_close_display()
{
/* Close display if it's open */
if (XHLP_display == NULL) return(-1);
XCloseDisplay(XHLP_display);
XHLP_display = NULL;
return(0);
}
int
XHLP_open_window(int sx, int sy, char *name)
{
XSetWindowAttributes xswda; /* Window attributes */
XSizeHints xszhn; /* WM hints about window size */
XWMHints xwmhn; /* WM hints about input & startup */
XGCValues xgcvl; /* Graphic Context init parameters */
unsigned long amask=0; /* Mask for defined fields in xswda */
int screen_width, screen_height; /* Size of screen in pixels */
unsigned int req_sx, req_sy; /* Requested Window size */
int init_x, init_y; /* Initial window position */
int cur_h; /* Current window handle */
/* Is the display open ? */
if (XHLP_display == NULL) return(-1);
/* Check requested size against screen size. */
screen_width = XWidthOfScreen(XHLP_screen_id);
screen_height = XHeightOfScreen(XHLP_screen_id);
req_sx = sx;
if (sx <= 0 || sx > screen_width)
{
req_sx = screen_width;
}
req_sy = sy;
if (sy <= 0 || sy > screen_height)
{
req_sy = screen_height;
}
/* Set window attributes (background, colormap, bit gravity, backing store) */
xswda.background_pixel = XWhitePixelOfScreen(XHLP_screen_id);
amask |= CWBackPixel;
xswda.bit_gravity = StaticGravity;
amask |= CWBitGravity;
xswda.backing_store = XDoesBackingStore(XHLP_screen_id);
if (xswda.backing_store != NotUseful) /* Use it */
{
amask |= CWBackingStore;
xswda.save_under = TRUE;
amask |= CWSaveUnder;
}
xswda.colormap = XDefaultColormapOfScreen(XHLP_screen_id);
amask |= CWColormap;
/* Create window */
/* Find an empty window slot or create it*/
for (cur_h = 0; cur_h < XHLP_max_windows; cur_h ++)
{
if (XHLP_window_handles[cur_h] == NULL) break;
}
if (cur_h == XHLP_max_windows)
{
XHLP_max_windows++;
XHLP_window_handles = (XHLP_winfo **)realloc(XHLP_window_handles,
XHLP_max_windows * sizeof(XHLP_winfo *));
if (XHLP_window_handles == NULL)
{
fprintf(stderr,"XHLP: Out of memory\n");
return(-1);
}
}
init_x = init_y = (cur_h+1)*XHLP_INITIAL_OPEN_STEP;
XHLP_window_handles[cur_h] = (XHLP_winfo *) malloc(sizeof(XHLP_winfo));
if (XHLP_window_handles[cur_h] == NULL)
{
fprintf(stderr,"XHLP: Out of memory\n");
free(XHLP_window_handles);
XHLP_max_windows = 0;
return(-1);
}
XHLP_window_handles[cur_h]->window = XCreateWindow(XHLP_display,
XRootWindowOfScreen(XHLP_screen_id),
init_x, init_y,
req_sx,req_sy,
0, XDefaultDepthOfScreen(XHLP_screen_id),
InputOutput, XDefaultVisualOfScreen(XHLP_screen_id),
amask, &xswda);
/* Set window manager size hints on the window (WM_NORMAL_HINTS) */
xszhn.x = init_x;
xszhn.y = init_y;
xszhn.width = req_sx;
xszhn.height = req_sy;
xszhn.flags = (PPosition | PSize);
XSetNormalHints(XHLP_display, XHLP_window_handles[cur_h]->window, &xszhn);
/* Set WM hints about keyboard input focus and initial state (WM_HINTS) */
xwmhn.input = FALSE; /* WM should never give us input focus */
xwmhn.initial_state = NormalState;
xwmhn.flags = (InputHint | StateHint);
XSetWMHints(XHLP_display, XHLP_window_handles[cur_h]->window, &xwmhn);
/* Set WM hints about titles of window and icon (WM_NAME, WM_ICON_NAME), */
if (name != NULL)
{
XStoreName(XHLP_display, XHLP_window_handles[cur_h]->window, name);
XSetIconName(XHLP_display, XHLP_window_handles[cur_h]->window, name);
}
/* Create graphics context */
xgcvl.background = xswda.background_pixel;
XHLP_window_handles[cur_h]->gc = XCreateGC (XHLP_display, XHLP_window_handles[cur_h]->window,
GCBackground, &xgcvl);
/* Initialize event mask for window */
XSelectInput (XHLP_display, XHLP_window_handles[cur_h]->window, StructureNotifyMask);
/* Set Black foreground, just for starters */
XSetForeground(XHLP_display, XHLP_window_handles[cur_h]->gc,
BlackPixelOfScreen(XHLP_screen_id));
XMapWindow(XHLP_display, XHLP_window_handles[cur_h]->window);
XSync (XHLP_display, FALSE);
return(cur_h);
}
int
XHLP_close_window(int cur_h)
{
int i;
XHLP_check_window_status();
XUnmapWindow(XHLP_display, XHLP_window_handles[cur_h]->window);
XDestroyWindow(XHLP_display, XHLP_window_handles[cur_h]->window);
/* Free the window structure and mark the slot as empty */
free (XHLP_window_handles[cur_h]);
XHLP_window_handles[cur_h] = NULL;
XSync (XHLP_display, FALSE);
return(0);
}
int
XHLP_draw_line(int cur_h,int x1,int y1,int x2,int y2)
{
Status result;
XHLP_check_window_status();
XDrawLine(XHLP_display, XHLP_window_handles[cur_h]->window,
XHLP_window_handles[cur_h]->gc,
x1, y1, x2, y2);
XSync (XHLP_display, FALSE);
return(0);
}
int
XHLP_clear_window(int cur_h)
{
Status result; /* X call status */
XWindowAttributes xwda; /* Window attributes */
XHLP_check_window_status();
/* Need to access the window colormap */
result=XGetWindowAttributes(XHLP_display, XHLP_window_handles[cur_h]->window,
&xwda);
if (result == 0) return (-1); /* 0 is failure in X-Windows */
XClearArea (XHLP_display, XHLP_window_handles[cur_h]->window, 0, 0,
xwda.width, xwda.height, FALSE);
}
int
XHLP_plot(int cur_h,int x,int y)
{
Status result;
XHLP_check_window_status();
XDrawPoint(XHLP_display, XHLP_window_handles[cur_h]->window,
XHLP_window_handles[cur_h]->gc, x, y);
XSync (XHLP_display, FALSE);
return(0);
}
int
XHLP_print(int cur_h,int x,int y,char *text)
{
Status result;
XHLP_check_window_status();
if (text == NULL) return(-1);
XDrawString(XHLP_display, XHLP_window_handles[cur_h]->window,
XHLP_window_handles[cur_h]->gc, x, y,
text, strlen(text));
XSync (XHLP_display, FALSE);
return(0);
}
int
XHLP_set_color(int cur_h, char *colorname)
{
Status result; /* X call status */
XColor color; /* Requested color structure */
XWindowAttributes xwda; /* Window attributes */
XHLP_check_window_status();
/* Need to access the window colormap */
result=XGetWindowAttributes(XHLP_display, XHLP_window_handles[cur_h]->window,
&xwda);
if (result == 0) return (-1); /* 0 is failure in X-Windows */
result = XParseColor(XHLP_display, xwda.colormap, colorname, &color);
if (result == 0) return (-1); /* 0 is failure in X-Windows */
XAllocColor(XHLP_display, xwda.colormap, &color);
XSetForeground(XHLP_display, XHLP_window_handles[cur_h]->gc,
color.pixel);
XSync (XHLP_display, FALSE);
return(0);
}
int
XHLP_get_click(int cur_h, int *rx, int *ry)
{
int retcod = -1;
XEvent event; /* Next button event */
Cursor crosshair;
XHLP_check_window_status();
/* Change the cursor inside the selected window to a crosshair */
crosshair = XCreateFontCursor(XHLP_display, XC_crosshair);
XDefineCursor(XHLP_display, XHLP_window_handles[cur_h]->window,
crosshair);
/* Allow button clicks to be detected in the selected window */
XSelectInput(XHLP_display, XHLP_window_handles[cur_h]->window,
StructureNotifyMask|ButtonPressMask);
/* Wait for a button click */
while (XWindowEvent(XHLP_display, XHLP_window_handles[cur_h]->window,
ButtonPressMask, &event) >=0 )
{
if (event.type==ButtonPress)
{
*rx = event.xbutton.x;
*ry = event.xbutton.y;
retcod = 0;
break;
}
}
/* Restore the original cursor */
XUndefineCursor(XHLP_display, XHLP_window_handles[cur_h]->window);
XFreeCursor(XHLP_display, crosshair);
/* Remove button click detection */
XSelectInput(XHLP_display, XHLP_window_handles[cur_h]->window,
StructureNotifyMask);
return(retcod);
}
int
XHLP_get_display_id(int cur_h, char **display, unsigned int *id)
{
XHLP_check_window_status();
*display = XDisplayString(XHLP_display);
*id = (unsigned int)XHLP_window_handles[cur_h]->window;
return(0);
}