[Return to Library] [Contents] [Previous Chapter] [Next Section] [Next Chapter] [Index] [Help]


3    Getting Started

This chapter describes the steps you follow to develop a typical application for the Display Postscript system and explains the steps that such an application performs. The chapter then presents a sample application.

Before reading this chapter, be sure you understand the following components and concepts, covered in Chapter 2; if you understand these, you are ready to start:


[Return to Library] [Contents] [Previous Chapter] [Next Section] [Next Chapter] [Index] [Help]


3.1    Developing a Typical Application

To develop a typical application, you follow six main steps, as shown in Figure 3-1. (Steps 3 through 5 take much less time than the others.)

  1. Design the application.

  2. Write the main C-language module and any custom PostScript language procedures that the application calls.

  3. Convert the custom PostScript language procedures into C-callable routines by running the pswrap translation program.

  4. Compile the C-language code with:

  5. Link the resulting object file with the X libraries and with the Client Library.

  6. Run and debug the executable application.

Figure 3-1: Developing a Typical Application


Step 1: Design the Application

In WS, Display PostScript system applications are written in C and send PostScript language code to a context, usually an X server. To design an application you must make several decisions; For example, you must decide:

For a typical simple application, the following design decisions are usually best:

A complete discussion of application design is beyond the scope of this book. To help you see and understand how design decisions affect XDPS applications, the WS distribution kit includes source files for several sample applications. (For more information about these sample applications, see Section 3.5.)

Step 2: Write Your C Code and PostScript Language Code

After you have designed your application, you write the C-language code and the PostScript language procedures that your application sends.

It is also possible to write applications that read PostScript language code from the user's keyboard or from a file. For a sample program of this type, see the program DPStest. By default, the source files for DPStest are installed in the directory /usr/examples/dps/dpstest. (For instructions on running the program, see Section 3.5.)

Step 3: Convert Your PostScript Language Procedures

If you have written any PostScript language procedures for your application, you should convert them to wraps, that is, to routines that can be called from your C-language code. To convert the PostScript language procedures, you process them with the pswrap translation program.

For each PostScript language input file, pswrap can produce two output files: a C-callable procedure and an associated header file.

Steps 4 and 5: Compile and Link

After you have converted your PostScript language procedures to C-callable routines, you compile and link your source files. That is, you compile your main C-language file with:

You link your application with the Client Library and with the X libraries. (For instructions on compiling and linking XDPS applications, see Section 3.4.)

Step 6: Run and Debug Your Application

You are now ready to run and debug your application.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


3.2    Basic Application Requirements

All applications send PostScript language statements to a context. Typically, the context is an execution context - in XDPS, the PostScript interpreter of an X server. Most XDPS applications perform three main steps:

  1. Initialization

  2. Communication

  3. Termination

Step 1: Initialization

Typically, to initialize an XDPS application, you perform three steps:

  1. Establish communication with an X server, create a window, and create a GC.

  2. Create a PostScript execution context by calling an X-specific Client Library routine such as XDPSCreateSimpleContext. (For more information on creating contexts, see the descriptions of XDPSCreateSimpleContext and XDPSCreateContext in Chapter 5.)

  3. Perform any additional X-specific initialization, such as mapping the window.

Step 2: Communication

After initializing, most XDPS applications call custom wraps, singleops, or other Client Library routines to send text and PostScript language statements to a context. For example, to send information to a context, an application might either call a custom wrap or call one of two Client Library routines: DPSWritePostScript (for PostScript language statements) or DPSWriteData (for data).

To process text or errors from a context, the Client Library calls the text-handling routine or error-handling routine that the application assigned when creating the context. The Client Library defines a default text-handling routine (DPSDefaultTextBackstop) and a default error-handling routine (DPSDefaultErrorProc). Although these routines are called default routines, to use them you must specify them explicitly when creating a context. (For more information on the default routines, see their descriptions in Chapter 5.)

Step 3: Termination

Terminating a typical XDPS application is like terminating any other typical X application. When you terminate an application, the X Window System destroys the application's contexts, their spaces, and any other X resources belonging to the application.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


3.3    Sample Application: examplemain

This section presents examplemain, a simple program that shows the fundamentals of XDPS programming. The program uses the Display PostScript system to paint a shaded square in a window of the user's screen, as shown in Figure 3-2.

Figure 3-2: Output of the examplemain Program

The examplemain program uses the Xlib interface to X, calls a custom wrap to pick the shade of gray for painting, and calls a Client Library single-operator procedure to do the actual painting.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


3.3.1    What the Sample Application Does

The sample application examplemain performs the following operations:

  1. Connects the client to an X server with XOpenDisplay.

  2. Creates a window with XCreateSimpleWindow.

  3. Selects X event types Expose and ButtonPress with XSelectInput.

  4. Creates a Display PostScript execution context with XDPSCreateSimpleContext, using the default text handler, the default error handler, and the default GC.

  5. Displays the window with XMapWindow.

  6. Chooses the shade of gray for painting, with a custom wrapped PostScript language procedure named ChooseGray.

  7. Sets the shade of gray with DPSsetgray, a singleop from the Client Library.

  8. Paints a gray square with the singleop DPSrectfill each time an Expose event is received, and exits when a ButtonPress event is received.

  9. Destroys the context and space with DPSDestroySpace, then closes the display connection and exits.

Unlike a more complete application, examplemain does not handle resizing of the X window. (For information about window resizing in XDPS applications, see Section 4.5.)


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


3.3.2    The Main Code

Example 3-1 is a complete listing of examplemain.c, the main C language file of the sample application.

Example 3-1: Sample Application: examplemain

/*
 * examplemain.c -- Simple X application that uses the DPS
 * system to draw a shaded square in a window, then exits
 * when the user clicks the mouse.
 */

 
#include <stdio.h>
 
#include <Xlib.h> /* Standard X Window C-lang library */ #include <dpsXclient.h> /* X interface to DPS Client Library */ #include <dpsops.h> /* Declarations of singleops */
 
#include "examplewraps.h" /* Interface to wrapped PS lang code*/
 
main () { Display *dpy; /* An X display */ Window window; /* A window of the X display */ DPSContext context; /* A single PostScript context */ float grayLevel; /* The shade of gray for the square */ XEvent event; /* An X event */ void TextOut(); /* Forward declaration */ void FatalError(); /* Forward declaration */ /* * Open a connection to the X display specified in the arg * to the XOpenDisplay routine. The NULL argument causes * XOpenDisplay to open a connection to the display specified * by the DISPLAY variable of the user's environment. */ dpy = XOpenDisplay(NULL); /* * If unable to open the display, return an error message and * exit immediately. */ if (dpy == NULL) FatalError("Can't open display.\n"); /* * Create a window on the X display. When mapped, the * window will be 10 pixels from the left edge and 20 pixels * from the upper edge. The window will be 800 pixels high * by 800 pixels wide, with a black border 1 pixel wide * and a white background. */ window = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 10, 20, 800, 800, 1, BlackPixel(dpy, DefaultScreen(dpy)), WhitePixel(dpy, DefaultScreen(dpy))); /* * Select the X event types that the window accepts from * the X server. The window accepts Expose events and * ButtonPress events. */ XSelectInput(dpy, window, ExposureMask | ButtonPressMask); /* * Create a PostScript execution context to draw in the window. * The origin of the context's coordinate grid is the point * (0, 800) of the window. The origin is therefore the bottom * left corner of the window (the typical origin for a * PostScript context). */ context = XDPSCreateSimpleContext(dpy, window, DefaultGC(dpy, DefaultScreen(dpy)), 0, 800, TextOut, DPSDefaultErrorProc, NULL); /* * If unable to create the context, return an error message * and exit immediately. */ if (context == NULL) FatalError("DPS refused to create a context.\n"); /* * Map the window--that is, make it appear on the display. * The window will appear only after the window manager of * the X server is free to process the mapping request. * When the window appears, the context receives an Expose * event as notification. */ XMapWindow(dpy, window); /* * Generate a random number that corresponds to the shade * of gray (the graylevel) to be used when painting. * To generate this number, call the ChooseGray routine, * which is exported from the examplewraps.c file. * ChooseGray sends wrapped PostScript language code to * the context, which then executes the code. */ ChooseGray(context, &grayLevel); /* * Set the current graylevel to the shade of gray chosen by * ChooseGray. Setting the graylevel does not cause any * painting; so you can set the graylevel even if the window * has not yet appeared. */ DPSsetgray(context, grayLevel); /* * Wait for events from the X server; process each one * received. For each Expose event, paint the same gray square * in the same place on the display. To do this, call the * DPSrectfill routine, a single-operator wrapped procedure * declared in dpsops.h, a DPS Client Library header file. * The bottom left corner of the square is 100 points above * the origin and 100 points to the right of it. Each side of * the square is 300 points. * * When a ButtonPress event is received, exit the * event-processing loop. */ for (;;) { XNextEvent(dpy, &event); if (event.type == Expose) { DPSrectfill(context, 100.0, 100.0, 300.0, 300.0); } else if (event.type == ButtonPress) { break; } } /* * Exit in an orderly manner. First, destroy the context by * destroying its space (its memory). Next, destroy * the window. Finally, close the connection to the X display. */ DPSDestroySpace(DPSSpaceFromContext(context)); XDestroyWindow(dpy, window); XCloseDisplay(dpy); } /* * Output procedure for plain text messages from the context. * Output is sent directly to standard error. */ void TextOut(context, buffer, count) DPSContext context; char *buffer; unsigned count; { fwrite(buffer, 1, count, stderr); fflush(stderr); } /* * Error procedure. The application has encountered an error * from which it cannot recover, so exit immediately. */ void FatalError(msg) char *msg; { fprintf(stderr, msg); exit(1); }


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


3.3.3    Source File for Wrap

Example 3-2 is a complete listing of examplewraps.psw, the PostScript language source file for the wrapped procedure called by the sample application examplemain.

Processing examplewraps.psw with the pswrap translator produces two output files: examplewraps.c and examplewraps.h. These output files must then be compiled with examplemain.c.

Example 3-2: Source File for Wrap Called by examplemain

/*
 * examplewraps.psw -- source file for wrapped PostScript
 * language procedure
 *
 * This is an example of PostScript language code to be converted
 * to Client Library calls by pswrap.
 *
 * This PostScript language routine, ChooseGray, generates a random
 * number that corresponds to the graylevel (shade of gray) to be
 * used when the Display PostScript system paints. Note that the
 * PostScript operator rand always generates the same sequence of
 * random numbers. So each time the program examplemain runs,
 * ChooseGray chooses the same graylevel.
 */

 
defineps ChooseGray (DPSContext ctx| float *result) rand % Pick a random number between 0 and 2^31 - 1. 2 31 exp % 2^31 div % Random number between 0.0 and 1.0 result % Return result. endps


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


3.3.4    Running examplemain

By default, all the program-specific files needed to compile, link, and run examplemain are installed in the /usr/examples/dps/gray-square directory of your system. For instructions on compiling and linking, see Section 3.4.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


3.4    Building XDPS Applications

After you code an application, you build it by compiling and linking it. The following sections describe how to build an application, assuming that you are using the WS make utility. (For more information, see the make(1) reference page.)

Section 3.4.5 includes a complete makefile for the examplemain program presented in Section 3.3.2.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


3.4.1    Including Header Files

Before building an XDPS application, make sure that the main source module includes the appropriate X header files and the WS-specific Client Library header file, dpsXclient.h.

The dpsXclient.h file is the only Client Library header file that all XDPS applications must include. It, in turn, includes all other Client Library header files, except psops.h, dpsops.h, and dpsexcept.h.

If your application calls singleops, you should also include psops.h or dpsops.h, or both, depending on which defines the singleops that your application calls. If your application uses the exception handling capability of the Display PostScript system, you must also include dpsexcept.h. (Not to be confused with error handling; exception handling is an advanced capability that few applications require.)


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


3.4.2    Compiling

You compile the main C-language module of your XDPS application with:

The Display PostScript system header files (among them, dpsXclient.h, psops.h, and dpsops.h) are installed in the directory /usr/include/DPS. To automatically include these files at compilation, add the following statement to your makefile:

CFLAGS = -I/usr/include/DPS

The option -I/usr/include/DPS causes the Workstation Software C compiler to search for include files in /usr/include/DPS.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


3.4.3    Linking

You link your XDPS application with the following libraries, in the order listed:
Library Linker Option
Client Library -ldps
Xlib extensions for Display PostScript system -lXext
DECwindows toolkit library -ldwt
Xlib library -lX11
Workstation Station math library -lm


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


3.4.4    Invoking pswrap from a Makefile

Your makefile can automatically convert PostScript language procedures to C-callable routines by running the pswrap translation program. For example, if the PostScript language procedures have file names ending in .psw, the following make statements convert the procedures automatically:

.SUFFIXES: $(.SUFFIXES) .psw .h
.psw.o: $*.psw
        ${PSWRAP} -o $*.c $*.psw
        $(CC) $(CFLAGS) -c $*.c
        rm $*.c

 
.psw.h: $*.psw ${PSWRAP} -h $*.h $*.psw > /dev/null


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


3.4.5    Sample Makefile

Example 3-3 shows a complete Makefile that builds the examplemain program presented earlier in this chapter.

Example 3-3: Makefile for examplemain

# @(#)Makefile 1.5 9/2/88

 
DESTDIR= EXAMPLETOPDIR=${DESTDIR}/usr/examples/dps EXAMPLESUBDIR=${EXAMPLETOPDIR}/gray-square
 
INSTALLLIST = Makefile examplemain.c *.psw
 
OBJS = examplemain.o examplewraps.o
 
PSWRAP= ${DESTDIR}/usr/bin/pswrap
 
.SUFFIXES: $(.SUFFIXES) .psw .h .psw.o: $*.psw ${PSWRAP} -o $*.c $*.psw $(CC) $(CFLAGS) -c $*.c rm $*.c
 
.psw.h: $*.psw ${PSWRAP} -h $*.h $*.psw > /dev/null
 
.SUFFIXES: .uil .uid
 
CFLAGS = -g -I${DESTDIR}/usr/include/X11 \ -I${DESTDIR}/usr/include/DPS \ -I${DESTDIR}/usr/include -I.
 
LIBS = ${DESTDIR}/usr/lib/libdps.a \ ${DESTDIR}/usr/lib/libXext.a \ ${DESTDIR}/usr/lib/libdwt.a \ ${DDIFROOT}/usr/lib/libddif.a \ ${DESTDIR}/usr/lib/libX11.a \ -lm
 
all: examplemain
 
examplemain: $(OBJS) $(CC) -o examplemain $(OBJS) $(LIBS)
 
examplemain.o: examplemain.c examplewraps.h
 
clean: rm -f *.o examplemain examplewraps.[ch] \#* *~ core
 
clobber: clean -rm -f *
 
relink:: rm -f examplemain
 
relink:: all


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


3.5    More Sample Applications

In addition to examplemain, the WS software includes source listings of several other sample XDPS applications.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


3.5.1    Examples Contrasting Design Approaches

WS includes source listings and makefiles for four related sample programs: calc0, calc1, calc2, and calc3. Each of these sample programs is an implementation of the same application: a desktop calculator. Although all four programs present a similar user interface (shown in Figure 3-3), the source code of each program shows a different approach to XDPS application design.

Figure 3-3: Output of the Sample Calculator Programs

For the location of the sample calculator programs, see Table 3-1, which lists and describes the sample Display PostScript system applications included in WS.

Table 3-1: Online Sample Programs

Program Name Description Location
calc0 Calculator coded mainly in C, with one window and one context /usr/examples/dps/calc0
calc1 Calculator coded mainly in the PostScript language, with one window and one context /usr/examples/dps/calc1
calc2 Calculator coded mainly in C, with multiple windows and one context /usr/examples/dps/calc2
calc3 Calculator coded mainly in C, with multiple windows, multiple contexts, and intercontext communication /usr/examples/dps/calc3
DPStest Executes PostScript language statements entered from the keyboard /usr/examples/dps/dpstest
examplemain Displays a gray square generated from a custom wrap and a singleop /usr/examples/dps/gray-square
psclock An implementation of xclock that uses the Display PostScript system /usr/examples/dps/psclock
psdraw A graphic editor that paints PostScript language images; a complex sample application /usr/examples/dps/psdraw
pyro Displays fireworks generated from custom wraps /usr/examples/dps/pyro


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


3.5.2    Running the Sample Applications

To run a sample application, you must first build it by following these steps:

  1. Log on to your system and find the subdirectory where the sample application is stored.

  2. Copy the entire contents of that subdirectory to a subdirectory in your account. (Note that the sample programs calc0, calc1, calc2, and calc3 must be copied to sibling directories, that is, to subdirectories at the same level of the file system.)

  3. Set your working directory to the subdirectory that received the copies in Step 2.

  4. Invoke the WS make utility by entering the command make at the system prompt. The make utility compiles and links the program. (Note that for the sample application psdraw, you must enter make install instead of make. For information, see the make(1) reference page.

You can then run the program by entering its name at the system prompt. (For more information on building XDPS applications, see Section 3.4.)


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Chapter] [Index] [Help]


3.6    Summary of Basic Tasks

Table 3-2 lists common XDPS programming tasks, shows the operators (in bold type), and Client Library routines for performing each task.

Table 3-2: Summary of Basic Tasks

Task Associated Routines and Operators
Create an execution context XDPSCreateSimpleContext or XDPSCreateContext
Create a text context XDPSCreateTextContext
Use the default text handler DPSDefaultTextBackstop
Use the default error handler DPSDefaultErrorBackstop
Find the space of a context DPSSpaceFromContext
Find the default user space origin currentXoffset
Set the default user space origin setXoffset
Find the GC of a context currentXgcdrawable
Set the GC of a context setXgcdrawable
Restart a context DPSResetContext
Find the current drawable currentXgcdrawable
Set the current drawable setXgcdrawable
Convert between PostScript language IDs and XIDs XDPSXIDFromContext XDPSXIDFromSpace XDPSContextFromXID XDPSSpaceFromXID
Destroy a space DPSDestroySpace
Destroy a context DPSDestroyContext