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.