This is ps2pcl.m in view mode; [Download] [Up]
static char *ID = {"By:Kevin Peckover -- July 1995 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 "" #define TIME_TO_WAIT_FOR_ACTIVE_PORT 5 // seconds #define TIME_OUTOF_RENDEREDPAGE_FROM_WINDOWSERVER 20 // seconds #define NO_MORE_PAGES 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 ReplyMsg { msg_header_t h; msg_type_t t; } replyMsg; typedef struct _ChildParam { char *basename; int compression; int res; } ChildParam; enum CompressType { none = 0, runLenEnc, TIFF_v40, DeltaRow }; // Global variables char outName[MAX_DEVICE_NAME_LEN] ={DEF_DEVICE} ; unsigned char* rleCompressForPCL(unsigned char* origData, unsigned char* newData, int *length) { // Initialize for begining of line int origDataLength = *length, indToNewData = 0, indToOldData = 0; unsigned char baseByte = *origData; if (*length < 2) return origData; // essentally a NULL line case do { unsigned char byteCount = 0; while (baseByte == origData[1 + indToOldData + byteCount] && byteCount < 255 && (1 + indToOldData + byteCount) < origDataLength ) byteCount++; newData[indToNewData++] = (unsigned char)byteCount; newData[indToNewData++] = (unsigned char)baseByte; if ( (1+indToOldData + byteCount) >= origDataLength ) { // Were done! Set length and get out. *length = indToNewData+1; // adding one makes it a count return newData; }; indToOldData += byteCount; baseByte = origData[indToOldData]; } while (indToNewData < (origDataLength-1)); // will dropp out of loop if longer return origData; // don't use the compressed version, length did not change } void writeHPRast(FILE *stream, char *data, int pWidth, int pixelsHigh, int bytesWide, int res) { int i, bytesToSend; unsigned char *lineOfData = malloc(sizeof(unsigned char)*bytesWide), *lineToSend = 0; #define COMPRESS_TYPE '1' /* run length encoding */ 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++) { bytesToSend = bytesWide; lineToSend = rleCompressForPCL(&data[bytesWide*i],lineOfData, &bytesToSend); fprintf(stream,"%c*b%cm%dW", ASCII_ESC, ((unsigned char *)lineToSend == (unsigned char *) &data[bytesWide*i])?'0':COMPRESS_TYPE, bytesToSend); fwrite(lineToSend, 1, bytesToSend, stream); } fprintf(stream,"%c%s%c", ASCII_ESC,"*rB", ASCII_FF); // stop graphics mode free(lineOfData); } 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 = 0; BOOL getNextPage = TRUE; char fname[MAX_FILE_PATH]; int pagesPrinted=0; // 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 NO_MORE_PAGES: getNextPage = NO; break; case NX_PRINTPAGEMSGID: if(*fname) { sprintf(fname,"%s", baseFileName); out = fopen(fname,"wb"); } else out=stdout; if(out) { writeHPRast(out, msg.printerData, msg.pixelsWide, msg.pixelsHigh, msg.bytesPerRow, res); if(*fname) 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++; 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); }; } while (getNextPage) ; if(!*fname) fclose(out); } 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; 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}; 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; NXPrintPageMessage 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((int)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) ; 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)) { int count; count=fread((void *)line, sizeof(char), BUFSIZ, psin); DPSWriteData(toWindowServer, line, count); }; DPSFlushContext(toWindowServer); DPSWaitContext(toWindowServer); DPSSendEOF(toWindowServer); // Send a termination message for child to expect ret = port_allocate(task_self(), &parentPort); if (ret == KERN_SUCCESS) { send.msgHeader.msg_id = NO_MORE_PAGES ; send.msgHeader.msg_simple = TRUE; send.msgHeader.msg_size = sizeof(NXPrintPageMessage); send.msgHeader.msg_type = MSG_TYPE_NORMAL ; send.msgHeader.msg_local_port = parentPort ; send.msgHeader.msg_remote_port = server; send.integerParams.msg_type_name = MSG_TYPE_INTEGER_32 ; send.integerParams.msg_type_size = 32; send.integerParams.msg_type_number = NX_PPMNUMINTS; send.integerParams.msg_type_inline = TRUE; send.integerParams.msg_type_longform = FALSE; ret = msg_send(&send.msgHeader, 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.