This is psh.c in view mode; [Download] [Up]
/* psh using the DPS library. Written by Bill Spitzak If you want to test drawing, first type "width height newwindow". This will make a movable, orderable window, into which all drawing goes. The window is "retained" and thus all drawing appears in it immediately. "erase" will restore the window to its initial blank state with a black border. "thiswindow" returns the window the mouse is pointing at. Useful for examining appkit windows. Several printing routines are modified to flush immediately. Except for defining these procedures, NO changes are made to the bare postscript server. */ #include <dpsclient/dpsclient.h> void printjunk(DPSContext ctxt, const char *buf, long unsigned int count) { unsigned char c; while (count--) { c = *buf++; if (c < ' ' && c != '\n') {putchar('^'); c ^= 0x40;} putchar(c); } } void myerrorproc( DPSContext ctxt, DPSErrorCode errorCode, long unsigned int arg1, long unsigned int arg2 ) { if (errorCode == 1000) { printf("%%%%[ %.*s: %.*s; OffendingCommand: %.*s ]%%%%\n", *(short *)(arg1+14),*(char **)(arg1+16)+arg1+4, *(short *)(arg1+22),*(char **)(arg1+24)+arg1+4, *(short *)(arg1+30),*(char **)(arg1+32)+arg1+4); } else { printf("DPS Error %d:\n",errorCode); printjunk(ctxt,(char *)arg1,arg2); putchar('\n'); } } /*============== event tester: If you want to test events, use "x currentwindow seteventmask". Make sure the 2 bit is on, or it won't get left-down events and thus you can't move the window. All other events are printed: */ const char *enames[] = { "NULLEVENT", "LMOUSEDOWN", "LMOUSEUP", "RMOUSEDOWN", "RMOUSEUP", "MOUSEMOVED", "LMOUSEDRAGGED", "RMOUSEDRAGGED", "MOUSEENTERED", "MOUSEEXITED", "KEYDOWN", "KEYUP", "FLAGSCHANGED", "KITDEFINED", "SYSDEFINED", "APPDEFINED", "TIMER", "CURSORUPDATE", "RESERVEDEVENT3", "RESERVEDEVENT4", "RESERVEDEVENT5", "RESERVEDEVENT6", "RESERVEDEVENT7", "RESERVEDEVENT8", "RESERVEDEVENT9", "RESERVEDEVENT10", "RESERVEDEVENT11", "RESERVEDEVENT12", "RESERVEDEVENT13", "RESERVEDEVENT14", "RESERVEDEVENT15", "RESERVEDEVENT16"}; void reportevent(NXEvent *e) { const char *c; if (e->type < 0 || e->type > 31) {printf("Event # %d, ",e->type); c="UNKNOWN";} else c = enames[e->type]; printf("%s at %g %g, flags %x, window %d, ", c,e->location.x,e->location.y,e->flags,e->window); switch(e->type) { case NX_NULLEVENT : break; case NX_LMOUSEDOWN : case NX_LMOUSEUP : case NX_RMOUSEDOWN : case NX_RMOUSEUP : case NX_MOUSEMOVED : case NX_LMOUSEDRAGGED : case NX_RMOUSEDRAGGED : printf("ev# %d, click %d", e->data.mouse.eventNum,e->data.mouse.click); break; case NX_KEYDOWN : case NX_KEYUP : case NX_FLAGSCHANGED : printf("repeat %d, set %x, code %x, key %x", e->data.key.repeat,e->data.key.charSet,e->data.key.charCode,e->data.key.keyCode); break; case NX_MOUSEENTERED : case NX_MOUSEEXITED : printf("ev# %d, trackingNum %d, userData %d", e->data.tracking.eventNum,e->data.tracking.trackingNum,e->data.tracking.userData); break; default: printf("%g %g (%lX %lX)", e->data.compound.misc.F[0], e->data.compound.misc.F[1], e->data.compound.misc.L[0], e->data.compound.misc.L[1]); break; } printf(".\n"); } /*================ main program ==================*/ /* Note yuckiness due to bad addfd implementation! This is the only way I have ever found to sync the main loop of a program with the input from a file. Since it requires posting event 0 it pretty much precludes any use of the "App Kit" which will choke or at least ignore such events. Use of DPSAddFD results in an annoying slowdown and is avoided except for the "interactive" use of stdin. I am mystified as to why such an interface was ever born. Far better and so obvious I can't believe they did not consider it, is a routine like "FDCausesEvent(int fd, int event)" so that DPSGetEvent will return immediately when an fd is ready. */ #define BUFLEN 0x2000 int doneflag; DPSContext d; char buf[BUFLEN]; void posteof(void) { NXEvent e; doneflag = 1; e.type = 0; e.ctxt = d; DPSPostEvent(&e,1); } void typedtext(int fd, void *userData) { int n; if (!gets(buf)) {posteof(); return;} n = strlen(buf); buf[n++] = '\n'; DPSWriteData(d,buf,n); DPSFlushContext(d); } main(int argc, char **argv) { NXEvent e; int i,n,fd; int hadinteractive=0; char *p; static const char send[] = "/= {//= exec flush} bind def\n" "/== {//== exec flush} bind def\n" "/stack {//stack exec flush} bind def\n" "/pstack {//pstack exec flush} bind def\n" /* print is NOT 'fixed', because it would cause NL between each */ "/erase {" "erasepage\n" "0 1 currentwindow currentwindowbounds\n" "4 -2 roll pop pop exch 1 sub exch 1 sub rectstroke" "} bind def\n" "/newwindow {" "0 0 4 2 roll 0 window windowdeviceround\n" "1 0 currentwindow orderwindow\n" "2 currentwindow seteventmask\n" "erase" "} bind def\n" "/thiswindow {" "workspaceWindow currentmouse Above 0 findwindow\n" "pop exch pop exch pop} bind def" ; d = DPSCreateContext(0,0,printjunk,myerrorproc); i = 1; do { if (i >= argc) { GETSTDIN: fd = 0; if (!isatty(0)) goto PIPED; if (hadinteractive) clearerr(stdin); else {DPSWriteData(d,send,sizeof(send)); hadinteractive = 1;} doneflag = 0; DPSAddFD(fd,typedtext,0,1); for (;;) { DPSGetEvent(d,&e,-1,NX_FOREVER,0); if (doneflag) break; if (e.type == NX_LMOUSEDOWN) { DPSPrintf(d,"1 0 %d orderwindow " "{%d stilldown not {exit} if\n" "workspaceWindow currentmouse %g sub exch %g sub exch\n" "%d movewindow} loop\n", e.window,e.data.mouse.eventNum, e.location.y,e.location.x,e.window); } else reportevent(&e); } DPSRemoveFD(fd); } else if (argv[i][0] == '-') { if (!argv[i][1]) goto GETSTDIN; printf("Unknown switch %s\n",argv[i]); continue; } else { fd = open(argv[i],0); if (fd < 0) {printf("%s : %s\n",argv[i],strerror(errno)); continue;} PIPED: n = read(fd,buf,BUFLEN); p = buf; if (n > 0 && *buf=='#') { /* strip #! at start of executables */ for (;p<buf+n;) if (*p++ == '\n') break; n -= (p-buf); } if (n > 0) DPSWriteData(d,p,n); while ((n = read(fd,buf,BUFLEN))>0) DPSWriteData(d,buf,n); close(fd); DPSWriteData(d,"\nflush\n",7); /* don't botch if file missing eol */ DPSWaitContext(d); /* let downloaded program finish before exit */ } } while (++i < argc); /* DPSDestroyContext(d); */ }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.