This is ps2pcl.m in view mode; [Download] [Up]
static char *ID = {"By:Kevin Peckover -- Dec.1994 Ottawa, Canada."}; #import <stdio.h> #import <strings.h> #import <bsd/libc.h> #import <sys/types.h> #import <servers/netname.h> #import <mach/message.h> #import <mach/mach_init.h> #import <mach/mach_interface.h> #import <mach/mach_error.h> #import <mach/cthreads.h> #import <dpsclient/dpsNeXT.h> #import <dpsclient/dpsclient.h> #import <windowserver/printmessage.h> #import <appkit/NXBitmapImageRep.h> #import <appkit/Application.h> #import <appkit/tiff.h> #define TIFF_SERVER_NAME "tiff_fd" #define HEADDER_SIZE 1024 #define MAX_DEVICE_NAME_LEN 256 #define MAX_FILE_PATH 256 #define TIFFSERVER_NAME "TIFFServer" #define DEF_DEVICE_NAME "NeXTLaser-400" #define DEF_DEVICE "/dev/pp0" #define TIME_TO_WAIT_FOR_ACTIVE_PORT 5 // seconds #define TIME_OUTOF_RENDEREDPAGE_FROM_WINDOWSERVER 20 // seconds #define PS_PAGES_SEARCH_FORMAT "%%%%Pages:%d%*s" #define PAGES_MSG_ID 666 #define ASCII_ESC 0x1b #define ASCII_FF 0x0c #define HPPCL_BITCOMPMODE_NONE 0 #define HPPCL_BITCOMPMODE_RLENENC 1 #define HPPCL_BITCOMPMODE_TIFFV4 2 #define HPPCL_BITCOMPMODE_DELROW 3 typedef struct _ChildParam { char *basename; int compression; int res; } ChildParam; void writeHPRast(FILE *stream, char *data, int pWidth, int pixelsHigh, int bytesWide, int res) { int i; fprintf(stream,"%c%s%c%s%d%s%c%s%c%s%d%s%c%s%d%s%c%s", ASCII_ESC,"*p0x0Y", /* set postion */ ASCII_ESC,"*t", res, "R", /* set resoulution { 75,100,150,300 } */ ASCII_ESC,"*r0F", /* write raster on logical page */ ASCII_ESC,"*r", pWidth,"S", /* width */ ASCII_ESC,"*r", pixelsHigh,"T", /* height */ ASCII_ESC,"*r1A" /* start graphics mode */ ); for(i=0;i<pixelsHigh;i++) { fprintf(stream,"%c*b%dW", ASCII_ESC, bytesWide); fwrite(&data[bytesWide*i], 1, bytesWide, stream); } fprintf(stream,"%c%s%c", ASCII_ESC,"*rB", ASCII_FF); // stop graphics mode } typedef struct ReplyMsg { msg_header_t h; msg_type_t t; } replyMsg; port_t tiff_look_up() // This function checks for an advertized Mach Port. { port_t port; kern_return_t ret; // Use "" instead of "*", so we look only on this machine. ret = netname_look_up(name_server_port, "", TIFF_SERVER_NAME, &port); if (ret != KERN_SUCCESS) return PORT_NULL; return port; } void server_loop(port_t port, char *baseFileName, int compression, int res) { NXPrintPageMessage msg; replyMsg reply; kern_return_t ret; FILE *out; BOOL getNextPage = TRUE; char fname[MAX_FILE_PATH]; int pagesPrinted=0, pagesExpected = -1; // The reply message which does not change reply.h.msg_simple = TRUE; reply.h.msg_size = sizeof(replyMsg); reply.h.msg_type = MSG_TYPE_NORMAL ; reply.h.msg_id = NX_PRINTPAGEMSGID; reply.t.msg_type_name = MSG_TYPE_INTEGER_32 ; reply.t.msg_type_size = 32; reply.t.msg_type_number = 0; reply.t.msg_type_inline = TRUE; reply.t.msg_type_longform = FALSE; do { msg.msgHeader.msg_local_port = port; msg.msgHeader.msg_size = sizeof(NXPrintPageMessage); ret = msg_receive(&msg.msgHeader , RCV_TIMEOUT, TIME_OUTOF_RENDEREDPAGE_FROM_WINDOWSERVER*1000); switch(ret) { case RCV_SUCCESS: switch(msg.msgHeader.msg_id) { case PAGES_MSG_ID: if(pagesExpected < 0) { pagesExpected = (int)msg.msgHeader.msg_unused ; } break; case NX_PRINTPAGEMSGID: sprintf(fname,"%s", baseFileName); if((out=fopen(fname,"wb"))) { writeHPRast(out, msg.printerData, msg.pixelsWide, msg.pixelsHigh, msg.bytesPerRow, res); fclose(out); } else fprintf(stderr,"** Could Not open file %s\n", fname); vm_deallocate(task_self(), (vm_address_t)msg.printerData, (vm_size_t)(msg.samplesPerPixel*msg.pixelsWide* msg.pixelsHigh*msg.bitsPerSample/8)); // Send the reply to Window Server that we are ready for next page reply.h.msg_local_port = port ; //send to reply.h.msg_remote_port = msg.msgHeader.msg_remote_port; reply.h.msg_id = NX_PRINTPAGEMSGID; ret = msg_send(&reply.h, MSG_OPTION_NONE, 0); switch(ret) { case SEND_SUCCESS: // Continue in loop for next page pagesPrinted++; if(pagesExpected>0) if(pagesPrinted >= pagesExpected) getNextPage = FALSE; break; case SEND_INVALID_PORT: // There is Probably no more pages getNextPage = FALSE; break; default: mach_error("TIFFServer:** SEND to Window Server.\n", ret); }; break; } break; case RCV_TIMED_OUT: getNextPage = FALSE; return ; // exit receive loop completely with no error message default: mach_error("TIFFServer:** RECV to TIFF routine.\n", ret); }; // 'pagesExpected < 0' flags that expected pages are unknown } while (getNextPage && (pagesExpected>0 || pagesExpected < 0)) ; } int TIFFReceptorMain(ChildParam *param) { port_t server_port; kern_return_t r; if(!strstr(ID, "Peckover")) exit(1); r = port_allocate(task_self(), &server_port); if (r != KERN_SUCCESS) { mach_error("port_allocate failed",r); return 0; } r = netname_check_in(name_server_port, TIFF_SERVER_NAME, PORT_NULL, server_port); if (r != KERN_SUCCESS) { mach_error("netname_check_in failed ",r); return 0; } server_loop(server_port, param->basename, param->compression, param->res); return 1; } extern void DPSMyTextProc( DPSContext ctxt, const char *buf, long unsigned int count ) { fprintf(stderr,"Context:\t%s\n", ctxt->priv); fprintf(stderr,"Message:\t%s\n", buf); }; extern void DPSMyErrorProc( DPSContext ctxt, DPSErrorCode errorCode, long unsigned int arg1, long unsigned int arg2 ) { char *string = (char *)arg1; string[arg2] = 0; fprintf(stderr,"PS_ERROR: Context:\t%s\t", ctxt->priv); fprintf(stderr,"ErrCode:\t%d\t", errorCode); fprintf(stderr,"A1:\t%s\n", string); }; void usage(char *progName) { fprintf(stderr,"Usage: %s [Prf] <infn> <outfn>\n %s %s %s\n", progName, "[-r<0|1|2|3>]\t res. 0-75dpi, 1-100dpi, 2-150dpi, 3-300dpi\n", "[-f<outfn>]\t write each page to file(s)\n", "<infn>\t\t name of PostScript file to convert\n"); exit(1); }; void main(int argc, char *argv[]) { port_t server; DPSContext toWindowServer; int pages = 0 ; time_t checkInTime, currTime; char line[BUFSIZ], c, device_name[MAX_DEVICE_NAME_LEN] = {DEF_DEVICE_NAME}, server_name[MAX_DEVICE_NAME_LEN] = {TIFF_SERVER_NAME}, outName[MAX_DEVICE_NAME_LEN] ={DEF_DEVICE} ; FILE *psin = 0; int width = 0, height = 0, topMargin = 0, leftMargin = 0, vFaxDpi = 75, hFaxDpi , compType = NX_TIFF_COMPRESSION_CCITTFAX3; cthread_t proc=0; ChildParam param; msg_header_t send; kern_return_t ret; port_t parentPort; while ((c = getopt(argc, argv, "r:f:?")) != -1) switch (c) { case 'r': switch(atoi(optarg)) { case 1: vFaxDpi = 100; break; case 2: vFaxDpi = 150; break; case 3: vFaxDpi = 300; break; default: vFaxDpi = 75; } break; case 'f': strncpy(outName, optarg, MAX_DEVICE_NAME_LEN); break; case '?': usage(argv[0]); }; width = (int)(8.5*vFaxDpi); height = (int)(11*vFaxDpi); hFaxDpi = vFaxDpi; switch(argc - optind){ case 0: psin = stdin ; break; case 1: if (!(psin = fopen(argv[argc-1],"r"))) { fprintf(stderr,"** Could not open \'%s\'.\n", argv[argc-1]); exit(1); }; break; default: usage(argv[0]); } // Run the child here. param.basename = outName; param.compression = compType; param.res = hFaxDpi ; // hFaxDpi == vFaxDpi proc=cthread_fork((cthread_fn_t)TIFFReceptorMain,(any_t)¶m); // Check if the server is up time(&checkInTime); do { server = tiff_look_up(); time(&currTime); } while (TIME_TO_WAIT_FOR_ACTIVE_PORT > difftime(checkInTime, currTime) && server == PORT_NULL); if (server == PORT_NULL) { fprintf(stderr, "** Couldn't find the Tiff server.\n"); fclose(psin); if(proc>0) { thread_suspend((thread_t)proc); cthread_abort(proc); cthread_join(proc); } exit(5); } //Communicating with Window Server toWindowServer = DPSCreateContext(NULL, NULL, (DPSTextProc)DPSMyTextProc, (DPSErrorProc)DPSMyErrorProc) ; DPSSetContext(toWindowServer) ; DPSWaitContext(toWindowServer) ; // Sifft through Comments and insert our headder to send image to port // immediately after them. do { fgets(line, BUFSIZ, psin) ; sscanf(line, PS_PAGES_SEARCH_FORMAT, &pages); DPSPrintf(toWindowServer,"%s", line) ; } while (strstr(line,"%%")||strstr(line,"%!")); // This is the next line after the comments. (or mabe within the comments) // put mach port description here. DPSPrintf(toWindowServer,"\n"); DPSPrintf(toWindowServer,"/width %d def ", width); DPSPrintf(toWindowServer,"/height %d def ", height); DPSPrintf(toWindowServer,"/topdots %d def ", topMargin); DPSPrintf(toWindowServer,"/leftdots %d def ", leftMargin); DPSPrintf(toWindowServer, "width height [ leftdots topdots width leftdots sub height topdots sub]"); DPSPrintf(toWindowServer, "[%d 72 div 0 0 %d -72 div leftdots height topdots sub] () ", hFaxDpi, vFaxDpi); DPSPrintf(toWindowServer,"(%s) %s machportdevice \n\n", server_name, device_name); //Continue sending the rest of the postScript while(!feof(psin)) { fgets(line, BUFSIZ, psin) ; if(pages<=0) sscanf(line, PS_PAGES_SEARCH_FORMAT, &pages); DPSPrintf(toWindowServer,"%s", line) ; }; DPSFlushContext(toWindowServer); DPSSendEOF(toWindowServer); // Send the number of pages message for child to expect if(pages) { // doing this because 'msg_unused' is unsigned etc.. ret = port_allocate(task_self(), &parentPort); if (ret == KERN_SUCCESS) { send.msg_unused = (unsigned int)pages; send.msg_simple = TRUE; send.msg_size = sizeof(msg_header_t); send.msg_type = MSG_TYPE_NORMAL ; send.msg_local_port = parentPort; //send to send.msg_remote_port = server; // sent from send.msg_id = PAGES_MSG_ID; ret = msg_send(&send, MSG_OPTION_NONE, 0); switch(ret) { case SEND_SUCCESS: // Continue in loop for next page case SEND_INVALID_PORT: // printing has finished by time-out break; default: mach_error("TIFFServer:** SEND error to Window Server", ret); }; ret=port_deallocate(task_self(), parentPort); if (ret != KERN_SUCCESS) { mach_error("port_deallocate", ret); exit(1); } } else mach_error("port_allocate",ret); } // Wait here for child to finish cthread_join(proc); DPSDestroyContext(toWindowServer); fclose(psin); exit(0); };
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.