This is main.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/cthreads.h> #import <mach/mach_error.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> #import "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 TIME_TO_WAIT_FOR_ACTIVE_PORT 5 // seconds #define TIME_OUTOF_RENDEREDPAGE_FROM_WINDOWSERVER 20 // seconds // First integer is number of pages, second int is to do with double sided // pages or something like that. #define PS_PAGES_SEARCH_FORMAT "%%%%Pages:%d%*s" #define PAGES_MSG_ID 666 typedef struct ReplyMsg { msg_header_t h; msg_type_t t; } replyMsg; typedef struct _ChildParam { char *basename; int compression; } ChildParam; 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; } long rawTIFFData(NXStream *tiffFile,int imageNum) // Function sets file pointer at begining of data and returns the number // of bytes in that data block. { TIFFHeader TIFFhead; // TIFFDirEntry seledtedDir; // unsigned short itemSize = 0; //Get TIFF Headder NXSeek(tiffFile, 0, NX_FROMSTART); NXRead(tiffFile, &TIFFhead.tiff_magic, sizeof(TIFFhead.tiff_magic)); NXRead(tiffFile, &TIFFhead.tiff_version, sizeof(TIFFhead.tiff_version)); NXRead(tiffFile, &TIFFhead.tiff_diroff, sizeof(TIFFhead.tiff_diroff)); //WARNING: This is a total hack! It works for G3, Probably G4, and probably // any TIFF with one bitmap in it that has been generated by the // NXBitmapImageRep class. This algorithm has only been tested with the // G3 output from the NXBitmapImageRep. // // Image data will follow immediately after the TIFFhead. The image // directory is located at the end if the bitmap. File structure // for one TIFF only is: // // 2 bytes - TIFFhead.tiff_magic // 2 bytes - TIFFhead.tiff_version // 4 bytes - TIFFhead.tiff_diroff <- to first directoy // n bytes - image data // 1 bytes - number of directories (or is it two?) // 2 bytes - seledtedDir.tdir_tag // 2 bytes - seledtedDir.tdir_type // m bytes - not exactly sure from here... // // n = TIFFhead.tiff_diroff - 2 bytes // // NOTE: TIFFhead.tiff_diroff is offset from the first byte of the // offset number. NOT the byte following that number. // // A correct treatment of this issue of stripping bitmap data out of a // TIFF file would be MUCH appreciated. // // I would think that the 3 should be a one or a two but...it isn't return (TIFFhead.tiff_diroff-sizeof(TIFFhead.tiff_diroff)-3); }; void server_loop(port_t port, char *baseFileName, int compression) { id renderingImage; int pagesPrinted=0, pagesExpected = -1; NXPrintPageMessage msg; replyMsg reply; kern_return_t ret; NXStream *stream ; FILE *out; BOOL getNextPage = TRUE; char fname[MAX_FILE_PATH]; // 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.%.3d", baseFileName, msg.pageNum); if((out=fopen(fname,"wb"))) { NXStream *tmpFile; tmpFile = NXOpenMemory(0, 0, NX_READWRITE); stream = NXOpenFile(fileno(out), NX_WRITEONLY); renderingImage = [[NXBitmapImageRep alloc] initData:msg.printerData pixelsWide:(int)msg.pixelsWide pixelsHigh:(int)msg.pixelsHigh bitsPerSample:msg.bitsPerSample samplesPerPixel:msg.samplesPerPixel hasAlpha:NO isPlanar:msg.isPlanar colorSpace:msg.colorSpace bytesPerRow:0 bitsPerPixel:0 ]; [renderingImage writeTIFF:tmpFile usingCompression:compression]; [renderingImage free]; NXWrite(stream, tmpFile->buf_ptr, rawTIFFData(tmpFile,1)); NXClose(stream); NXCloseMemory(tmpFile, NX_FREEBUFFER); 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; // sent from 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 error 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 error from Window Server.\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); 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 [Pwhrg] <infn> <outfn>\n %s %s %s %s %s %s\n", progName, "[-w<0|1|2>]\t width of 0-215 mm, 1-255 mm, 2-303 mm (def=0)\n", "[-h<0|1|2>]\t hight of 0-281 mm, 1-297 mm, 2-364 mm (def=0)\n", "[-r<0|1>]\t vert.res.of 0-98 lpi or 1-196 lpi (def=0)\n", "[-g<0|1>]\t comp.type 0-G3 Fax, 1-G4 Fax (def=0)\n", "<infn>\t\t name of PostScript file to convert\n", "<outfn>\t base name for G3/4 files\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} ; FILE *psin = 0; int width = 1728, height = 2166, topMargin = 0, leftMargin = 0, vFaxDpi = 98, compType = NX_TIFF_COMPRESSION_CCITTFAX3; const float hFaxDpi = 204.1451; cthread_t proc=0; ChildParam param; msg_header_t send; kern_return_t ret; port_t parentPort; while ((c = getopt(argc, argv, "w:h:r:g:")) != -1) switch (c) { case 'w': width = (atoi(optarg)==1)?2048:(atoi(optarg)==2)?2432:1728 ; break; case 'h': height = (atoi(optarg)==1)?2292:(atoi(optarg)==2)?2810:2166 ; break; case 'r': vFaxDpi = (atoi(optarg)==0)?98:196 ; break; case 'g': compType = (atoi(optarg)==1) ?NX_TIFF_COMPRESSION_CCITTFAX4 :NX_TIFF_COMPRESSION_CCITTFAX3 ; break; case '?': usage(argv[0]); }; if (vFaxDpi == 98) height /= 2; switch(argc - optind){ case 1: psin = stdin ; break; case 2: if (!(psin = fopen(argv[argc-2],"r"))) { fprintf(stderr,"** Could not open \'%s\'.\n", argv[argc-2]); exit(1); }; break; default: usage(argv[0]); } // Run the child here. param.basename = argv[argc-1]; param.compression = compType; 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, "[%f 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 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.