it consists of three files, an include file that contains the declarations of the data
structures, the object.c file that contains the routines that maintain the data structures
for the objects, and editor.c that contains the event handlers and the code that creates
the widgets
/**************************************************
*
* list.h
*
* Include file for simple drawing program example
*
****************************************************/
typedef void (*func)();
struct line_struct {
int type;
func draw;
func update;
char *next;
double x1, y1;
double x2, y2;
};
typedef struct line_struct *Line;
struct rect_struct {
int type;
func draw;
func update;
char *next;
double x1, y1;
double x2, y2;
};
typedef struct rect_struct *Rectangle;
#define LINE 1
#define RECTANGLE 2
Line make_line();
Rectangle make_rectangle();
/*****************************************************
*
* object.c
*
* Graphics routines for the simple editing program
*
*****************************************************/
#include < X11/StringDefs.h >
#include < X11/Intrinsic.h >
#include "list.h"
static short width;
static short height;
static char *display_list = NULL;
redisplay(w)
Widget w; {
char *list;
Line node;
func p;
int n;
Arg wargs[5];
GC gc;
XClearWindow(XtDisplay(w), XtWindow(w));
n=0;
XtSetArg(wargs[n], XtNheight, &height); n++;
XtSetArg(wargs[n], XtNwidth, &width); n++;
XtGetValues(w, wargs, n);
gc = XCreateGC(XtDisplay(w), XtWindow(w), NULL, NULL);
XSetForeground(XtDisplay(w), gc, 1);
XSetBackground(XtDisplay(w), gc, 0);
list = display_list;
while(list != NULL) {
node = (Line) list;
p = node->draw;
(*p)(w, gc, node);
list = node->next;
}
}
void display_line(w,gc,line)
Widget w;
GC gc;
Line line; {
int x1, y1, x2, y2;
x1 = width * line->x1;
y1 = height * (1.0 - line->y1);
x2 = width * line->x2;
y2 = height * (1.0 - line->y2);
XDrawLine(XtDisplay(w), XtWindow(w), gc, x1, y1, x2, y2);
}
void update_line(w,line,x,y)
Widget w;
Line line;
int x, y; {
double x2, y2;
x2 = x;
y2 = y;
line->x2 = x2/width;
line->y2 = 1.0 - y2/height;
}
Line make_line(x1, y1, x2, y2)
int x1, y1, x2, y2; {
Line result;
result = (Line) malloc(sizeof *result);
result->type = LINE;
result->draw = display_line;
result->update = update_line;
result->x1 = ((double) x1) / width;
result->y1 = 1.0 - ((double) y1) / height;
result->x2 = ((double) x2) / width;
result->y2 = 1.0 - ((double) y2) / height;
result->next = display_list;
display_list = (char *) result;
return(result);
}
void display_rectangle(w,gc,rect)
Widget w;
GC gc;
Rectangle rect; {
int x1, y1, x2, y2;
int Width, Height;
x1 = width * rect->x1;
y1 = height * (1.0 - rect->y1);
x2 = width * rect->x2;
y2 = height * (1.0 - rect->y2);
Width = x2 - x1;
Height = y2 - y1;
if(Width < 0) {
Width = -Width;
x1 = x2;
}
if(Height < 0) {
Height = -Height;
y1 = y2;
}
XDrawRectangle(XtDisplay(w), XtWindow(w), gc, x1, y1,
Width, Height);
}
void update_rectangle(w, rect, x, y)
Widget w;
Rectangle rect;
int x, y; {
double x2, y2;
x2 = x;
y2 = y;
rect->x2 = x2/width;
rect->y2 = 1.0 - y2/height;
}
Rectangle make_rectangle(x1, y1, x2, y2)
int x1, y1, x2, y2; {
Rectangle result;
result = (Rectangle) malloc(sizeof *result);
result->type = RECTANGLE;
result->draw = display_rectangle;
result->update = update_rectangle;
result->x1 = ((double) x1) / width;
result->y1 = 1.0 - ((double) y1) / height;
result->x2 = ((double) x2) / width;
result->y2 = 1.0 - ((double) y2) / height;
result->next = display_list;
display_list = (char *) result;
return(result);
}
/********************************************************
*
* editor.c
*
* Simple editing program that shows how events are
* used in X.
*
*******************************************************/
#include < X11/StringDefs.h >
#include < X11/Intrinsic.h >
#include < X11/Core.h >
#include < X11/Xaw/Form.h >
#include "list.h"
#include "../lib/lib.h"
void redisplay_event(w, client, ev)
Widget w;
XtPointer client;
XExposeEvent *ev; {
if(ev->type == ConfigureNotify)
redisplay(w);
if(ev->type == Expose && ev->count == 0)
redisplay(w);
}
struct drag_struct {
GC gc;
GC xor_gc;
char *object;
} drag_client;
void press_event(w, drag, ev)
Widget w;
struct drag_struct *drag;
XButtonEvent *ev; {
if(ev->button == Button1) {
drag->object = (char *) make_line(ev->x, ev->y,
ev->x, ev->y);
}
if(ev->button == Button2) {
drag->object = (char *) make_rectangle(ev->x, ev->y,
ev->x, ev->y);
}
}
void release_event(w, drag, ev)
Widget w;
struct drag_struct *drag;
XButtonEvent *ev; {
Line obj;
obj = (Line) drag->object;
(*obj->draw)(w, drag->gc, obj);
}
void motion_event(w, drag, ev)
Widget w;
struct drag_struct *drag;
XMotionEvent *ev; {
func draw;
Line obj;
obj = (Line) drag->object;
draw = obj->draw;
draw(w, drag->xor_gc, obj);
(*obj->update)(w, obj, ev->x, ev->y);
draw(w, drag->xor_gc, obj);
}
main(argc,argv)
int argc;
char **argv; {
Widget toplevel;
Widget form;
Widget drawing;
Widget quit;
int n;
Arg wargs[10];
toplevel = XtInitialize(argv[0], "editor", NULL, 0,
&argc, argv);
form = XtCreateManagedWidget("form", formWidgetClass,
toplevel, NULL, 0);
quit = quit_button(form);
drawing = XtCreateManagedWidget("drawing", coreWidgetClass,
form, NULL, 0);
n = 0;
XtSetArg(wargs[n], XtNheight, 300); n++;
XtSetArg(wargs[n], XtNwidth, 300); n++;
XtSetArg(wargs[n], XtNfromVert, quit); n++;
XtSetValues(drawing, wargs, n);
XtAddEventHandler(drawing, ExposureMask | StructureNotifyMask,
FALSE, redisplay_event, NULL);
XtAddEventHandler(drawing, ButtonPressMask, FALSE,
press event, &drag_client);
XtAddEventHandler(drawing, ButtonReleaseMask, FALSE,
release_event, &drag_client);
XtAddEventHandler(drawing, ButtonMotionMask, FALSE,
motion_event, &drag_client);
XtRealizeWidget(toplevel);
/*
* we can't create the graphics contexts until
* after the widgets have been realized
*/
drag_client.gc = XCreateGC(XtDisplay(drawing),
XtWindow(drawing),NULL,NULL);
XSetForeground(XtDisplay(drawing), drag_client.gc, 1);
XSetBackground(XtDisplay(drawing), drag_client.gc, 0);
drag_client.xor_gc = XCreateGC(XtDisplay(drawing),
XtWindow(drawing),NULL,NULL);
XSetForeground(XtDisplay(drawing), drag_client.xor_gc, 1);
XSetBackground(XtDisplay(drawing), drag_client.xor_gc, 0);
XSetFunction(XtDisplay(drawing), drag_client.xor_gc, GXxor);
XtMainLoop();
}