ftp.nice.ch/pub/next/tools/postscript/ps2_.s.tar.gz#/ps2pcl/ps2pcl.m

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)&param);

// 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.