/* This program is FFC, the font file converter, whose purpose is to convert TeX PXL files into (an approximation to) the DEC Common Font File Format. Copyright (c) 1984, 1985 by Digital Equipment Corporation, Maynard, Massachusetts. Author: Flavio Rose, shasta!decwrl!dec-rhea!dec-dvinci!rose. This program is being developed. It is quite incomplete. The present FFC is a revised version of an earlier program of the same name, written in Web. The initial goal of those programs was to convert TeX PXL files into the DEC Common Font File Format (CFFF). However, because of the complexity of that format, because of some residual ambiguities regarding its definition, and because there is no software to verify that a file conforms to it, I have been forced to postpone the implementation of this initial goal. Currently, the FFC program writes what I call NFT files. These are files in a format resembling the DEC CFFF, which the TeX LN03 driver can convert into font loads that the LN03 accepts. The FFC program can also read some files in the DEC CFFF and display their rasters on the screen. These are files that make no use of raster compression or font segmentation. This program is meant to be fairly portable, so I have tried to make a clear distinction between longwords and ints. The program should continue to function if int is replaced by short int throughout. Readers of this program should have on hand the DEC CFFF documentation. A preliminary version of this documentation is available within DEC on the Easynet as raja::user$e:[hastings.psrm]fontfile.mem. Some documentation also seems to have been distributed to certain customers. The final customer documentation seems to be still in preparation as of 6/2/85. */ #ifdef vms #include stdio #else #include #endif #ifdef vms #define GLOBAL globaldef #define EXTERN globalref #else #define GLOBAL #define EXTERN extern #endif /* User input is read into an array called inline. The pointers istart and ilp are used to keep track of a position in inline. */ GLOBAL char inline[513]; GLOBAL int ilp,istart; GLOBAL char *help_string = "\n Available commands:\ \n exit rpxl tpxlr tpxll spxll\ \n initnft cptonft wnft\ \n wstr"; #define skipb for(; inline[ilp]==' '; ilp++); #define skipnb for(; inline[ilp]!='\0' && inline[ilp]!=' '; ilp++); /* The main program of FFC is an interactive loop that receives commands from the user's terminal and writes replies. */ main() { printf("\n Font File Converter 4\n"); for(;;) { printf("\nFFC> "); gets(inline); if (feof(stdin)) goto exit_label; ilp = 0; skipb; istart = ilp; for (; inline[ilp]!='\0' && inline[ilp]!=' '; ilp++) #ifdef vms inline[ilp] = tolower(inline[ilp]); #else ; #endif if (strncmp(&inline[istart],"rpxl",4) == 0) handle_rpxl(); else if (strncmp(&inline[istart],"tpxlr",5) == 0) handle_tpxlr(); else if (strncmp(&inline[istart],"tpxll",5) == 0) handle_tpxll(); else if (strncmp(&inline[istart],"spxll",5) == 0) handle_spxll(); else if (strncmp(&inline[istart],"initnft",7) == 0) handle_initnft(); else if (strncmp(&inline[istart],"cptonft",7) == 0) handle_cptonft(); else if (strncmp(&inline[istart],"wnft",4) == 0) handle_wnft(); else if (strncmp(&inline[istart],"wstr",4) == 0) handle_wstr(); else if (strncmp(&inline[istart],"exit",4) == 0) goto exit_label; else if (inline[istart] == '?') printf(help_string); else { inline[ilp] = '\0'; printf("\nNo such command: %s",&inline[istart]); } } exit_label: ; } /* For handling VMS file specifications, we sometimes want to size an array which can hold the largest possible one. */ #define FILESPECLEN 252 /* Large buffers are used for the PXL and NFT files. */ #define PXLBUFSIZE 512*256 #define NFTBUFSIZE 512*256 GLOBAL unsigned char pxlbuf[PXLBUFSIZE]; GLOBAL unsigned char nftbuf[NFTBUFSIZE]; GLOBAL long pxllen, nftlen; /* The value conv is computed to be the correct conversion factor from the widths in the PXL file, which are expressed in units of 2^-20 times the design size, to pixels. */ GLOBAL float conv; /* As usual when dealing with TeX files, we have to rearrange bytes in an overlay to combine them into longwords. The reason for this is that bytes in TeX files are combined into longwords the opposite way from how the VAX combines them. Hence, the following overlay and macro: */ GLOBAL union lc { unsigned long int ul; long int l; unsigned char c[4]; } lcx; #define copy_from_pxl(_x) { lcx.c[3] = pxlbuf[_x]; \ lcx.c[2] = pxlbuf[(_x)+1]; lcx.c[1] = pxlbuf[(_x)+2]; \ lcx.c[0] = pxlbuf[(_x)+3]; } /* Handle_rpxl handles an rpxl command, which orders FFC to read a PXL file into the pxlbuf. To speed up the operation of this program, the reading is done with Unix I/O. Under VMS, this will only work if the file has record attributes = none. Otherwise, spurious bytes get inserted at record boundaries. It is difficult to get rid of these bytes. There does not seem to be any good way to detect record boundaries with Unix I/O, if and bytes can also be a part of the record being read. [[Eventually, we should check that the PXL file does indeed meet this requirement, and perhaps read it in a different way if it doesn't. This will probably require opening the file by direct use of VMS Record Management Services calls.]] */ int handle_rpxl() { long i,j; int pxlf; float two_to_the_20th; skipb; istart = ilp; skipnb; inline[ilp] = '\0'; pxlf = open_input_file(&inline[istart],".pxl"); if (pxlf == -1) { printf("\nUnable to open file %s",&inline[istart]); return(1); } pxllen = 0; j = 512; while (j != 0) { i = read(pxlf,&pxlbuf[pxllen],j); if (i < 0) { printf("\nError while reading PXL file."); close(pxlf); return(1); } if (i == 0) break; pxllen += i; if (PXLBUFSIZE-pxllen < 512) j = PXLBUFSIZE-pxllen; } if (j == 0) { printf("\nPXL file too large for FFC's buffer (%d bytes long)", PXLBUFSIZE-1); close(pxlf); return(1); } close(pxlf); /* Now that we have read the PXL file, check that it is in correct format by looking for a trailing ID byte of 1001. */ if (locate_pxldir() != 0) return(1); /* If the format is correct, derive the design size and magnification from the final longwords of the PXL file and print them. */ copy_from_pxl(pxllen-12); conv = lcx.ul; two_to_the_20th = 0x100000; printf("\nDesign size %.2f points",conv/two_to_the_20th); copy_from_pxl(pxllen-16); conv = (conv/two_to_the_20th)*(lcx.ul/5.0)*(1.0/(72.27*two_to_the_20th)); printf("\nPixels per em = %.1f",conv*two_to_the_20th); printf("\nMagnification = %.3f (at 300 dpi)",lcx.ul/1500.0); } int open_input_file (s,ext) char s[], ext[]; { char fs[FILESPECLEN]; int jnam,jext; strcpy(fs,s); find_VMS_filename(fs,&jnam,&jext); if (fs[jext] == '\0') strcat(fs,ext); return(open(fs,0)); } /* Find_VMS_filename finds the filename part of a VMS filespec passed in s, returning the index of the first character in *ns, and the index of the character after the last in *ne. */ int find_VMS_filename(s,ns,ne) char s[]; int *ns,*ne; { int jnam,jext,j,slen; slen = strlen(s); jnam = 0; for (j = slen-1; j >= 0; j--) { if (s[j] == ':' || s[j] == ']' || s[j] == '>') { jnam = j+1; break; } } jext = slen; for (j = jnam; j < slen; j++) { if (s[j] == '.' || s[j] == ';') { jext = j; break; } } *ns = jnam; *ne = jext; } /* PXL files have a "directory" at the end. Locate_pxldir searches for the PXL id 1001, starting at the end of the PXL file. The directory is 517 longwords back of there. If locate_pxldir can't find the PXL id, it outputs an error message. */ GLOBAL long pxldir; int locate_pxldir () { long i; pxldir = 0; if (pxllen < 517*4) { printf("\nPXL file too short, must be at least 517 longwords."); return(1); } if (pxllen%4 != 0) { printf("\nPXL file length should be multiple of 4."); pxllen -= pxllen%4; } for (i=pxllen-4; i>0; i-=4) { copy_from_pxl(i); if (lcx.ul == 1001) { pxllen = i+4; if (pxllen < 517*4) { printf("\nPXL file too short, must be at least 517 longwords"); return(1); } pxldir = pxllen-517*4; printf("\n%d bytes read.",pxllen); return(0); } } printf("\nUnable to find directory in PXL file."); return(1); } /* The tpxll command instructs FFC to type a longword from the PXL file. */ int handle_tpxll() { long i; i = atoi(&inline[ilp]); if (i < 0 || i > pxllen-4) { printf("\nRequested location %ld lies outside PXL file.",i); return(1); } else { copy_from_pxl(i); printf("\n%ld: %10lu = %%x\"%08lx\"",i,lcx.ul,lcx.ul); return(0); } } /* The spxll command sets a longword in the pxl file to a value, expressed in HEXADECIMAL. */ int handle_spxll() { long i; skipb; i = atoi(&inline[ilp]); if (i < 0 || i > pxllen-4) { printf("\nRequested location %d lies outside PXL file.",i); return(1); } skipnb; copy_from_pxl(i); sscanf(&inline[ilp],"%X",&lcx.ul); pxlbuf[i] = lcx.c[3]; pxlbuf[i+1] = lcx.c[2]; pxlbuf[i+2] = lcx.c[1]; pxlbuf[i+3] = lcx.c[0]; printf("\n%ld: %10lu = %%x\"%08lx\"",i,lcx.ul,lcx.ul); return(0); } #define pxl_word(_x) (pxlbuf[_x]*256+pxlbuf[(_x)+1]) #define signed_pxl_word(_x) ((pxl_word(_x)>0x8000) ? \ (pxl_word(_x)-0x10000) : pxl_word(_x)) GLOBAL char visible_byte[9]; /* Handle_tpxlr handles the tpxlr command, which directs FFC to type the rasters corresponding to a character code in the PXL file. We print out not just the rasters themselves, but also the directory information for the character. This information comprises the byte offset of the rasters within the PXL file; the number of rows and columns in the rasters; the location of the reference point of the glyph with respect to the upper left corner of the rasters; and the width of the glyph. */ int handle_tpxlr () { int code; unsigned int rows,cols,k,l,m; long ds,rs; if (pxldir == 0) { printf("\nCan't display rasters because there isn't a good PXL"); printf(" file in the PXL buffer."); return(1); } code = atoi(&inline[ilp]); if (code < 0 || code > 127) { printf("\nCharacter code must be between 0 and 127"); return(1); } /* Determine the location of the rasters within the PXL file. */ ds = pxldir+16*code; copy_from_pxl(ds+8); rs = 4*lcx.ul; if (rs == 0) { printf("\nNo rasters for code %d",code); return(0); } printf("\n Rasters begin at %d",rs); if (rs > pxllen) { printf("\n ... outside the PXL file"); return(1); } /* Compute and display the remaining directory information for the glyph. */ cols = pxl_word(ds); rows = pxl_word(ds+2); copy_from_pxl(ds+12); printf("\n %d rows, %d columns",rows,cols); printf("\n width %.2f pixels",conv*lcx.ul); printf("\n xoffset %d, yoffset %d",signed_pxl_word(ds+4), signed_pxl_word(ds+6)); /* Now print out the rasters themselves. Compute k as the number of longwords required to hold each row of rasters. */ k = (cols+31)/32; for (l=0; l 255 || c2 < 0 || c2 > 255 || c1 > c2) { printf("\n Bad character code range: [%d, %d]",c1,c2); return(1); } nft_first = c1; nft_last = c2; init_nft(); buffer_fixedp = 0; return(0); } #define copy_to_nft(_x) { nftbuf[_x] = lcx.c[0]; \ nftbuf[(_x)+1] = lcx.c[1]; nftbuf[(_x)+2] = lcx.c[2]; \ nftbuf[(_x)+3] = lcx.c[3]; } #define copy_from_nft(_x) { lcx.c[0] = nftbuf[_x]; \ lcx.c[1] = nftbuf[(_x)+1]; lcx.c[2] = nftbuf[(_x)+2]; \ lcx.c[3] = nftbuf[(_x)+3]; } int init_nft() { int i; /* The following array holds reasonable values for bytes 0-479 of an NFT file. These bytes were copied from a font load which the LN03 was known to accept. The NFT files generated by this program are initialized using these values. Some of these get overwritten later, however. */ static char good_opening[512] = { 104,38,0,0,70,79,78,84, 1,0,0,0,31,0,0,0, 20,0,0,0,85,48,48,48, 48,48,48,48,48,50,83,75, 48,48,71,71,48,48,48,49, 85,90,90,90,90,48,50,70, 48,48,48,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 181,7,9,0,11,0,14,0, 0,0,0,0,104,0,0,0, 252,0,0,0,124,0,0,0, 100,1,0,0,120,1,0,0, 224,1,0,0,4,0,0,0, 88,3,0,0,0,0,0,0, 92,3,0,0,48,0,0,0, 92,3,0,0,0,0,0,0, 140,3,0,0,212,34,0,0, 140,3,0,0,33,0,0,0, 126,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 32,0,0,0,168,0,0,0, 16,0,0,0,94,0,0,0, 0,0,0,0,94,0,0,0, 0,0,0,0,94,0,0,0, 0,0,0,0,236,25,0,0, 54,25,0,0,14,27,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,2,0,0,0, 7,0,0,0,92,3,0,0, 7,0,0,0,99,3,0,0, 16,0,0,0,106,3,0,0, 16,0,0,0,122,3,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 10,0,0,0,244,1,0,0, 0,0,24,0,16,0,0,0, 16,0,0,0,1,0,1,0, 1,0,1,0,0,0,1,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 30,0,0,0,20,0,0,0, 196,255,255,255,20,0,0,0, 106,255,255,255,20,0,0,0, 0,0,1,0,0,0,30,0, 166,255,255,255,0,0,0,0, 40,0,0,0,0,0,0,0, 60,0,0,0,240,0,0,0, 60,0,0,0,100,0,0,0, 240,0,0,0,120,0,0,0, 40,0,0,0,120,0,0,0, 96,255,255,255,136,255,255,255, 186,255,255,255,240,0,0,0, 76,255,255,255,60,0,0,0, 160,0,0,0,120,0,0,0, 20,0,0,0,20,0,0,0, 140,3,0,0,194,3,0,0, 244,3,0,0,160,4,0,0, 254,4,0,0,162,5,0,0, 46,6,0,0,84,6,0,0}; int pool_beg,nft_chardir; /* The character directory always begins at position 480 in the Common Font File Format. */ nft_chardir = 480; /* Copy the good values into nftbuf */ for (i=0; i<480; i++) nftbuf[i] = good_opening[i]; for (i=480; i<480+(nft_last-nft_first+1)*4; i++) nftbuf[i] = 0; /* Set the first and last character codes */ #define fnt__l_first_character 164 nftbuf[fnt__l_first_character] = nft_first; nftbuf[fnt__l_first_character+4] = nft_last; #define fnt__l_char_directory 116 lcx.ul = 4*(nft_last-nft_first+1); copy_to_nft(fnt__l_char_directory); /* Set the character counts */ #define fnt__l_infile_locators 204 #define fnt__l_character_definitions 212 #define fnt__l_raster_count 220 i = nft_last-nft_first+1; nftlen = nft_chardir+4*i+4+48; nftbuf[fnt__l_infile_locators] = i; nftbuf[fnt__l_character_definitions] = i; nftbuf[fnt__l_raster_count] = i; /* We now have to set some fields in the font format that are pointers to where other fields begin. These pointers depend on the number of glyphs we are placing in the font file. */ #define fnt__a_subset_tables 128 lcx.ul = nft_chardir+4*i; copy_to_nft(fnt__a_subset_tables); lcx.ul = lcx.ul+4; copy_to_nft(fnt__a_subset_tables+8); copy_to_nft(fnt__a_subset_tables+16); lcx.ul = lcx.ul+48; copy_to_nft(fnt__a_subset_tables+24); #define fnt__a_char_definitions 160 copy_to_nft(fnt__a_char_definitions); /* Set up the string pool (48 bytes). */ pool_beg = nftlen-48; strncpy(&nftbuf[pool_beg],"0B\tZZZZ",7); /* For reasons that are beyond my comprehension, the Format requires us to copy the first seven characters of the font file id into one piece of the string pool, and the first sixteen into another place. */ #define fnt__t_font_file_id 20 for (i=1; i<8; i++) nftbuf[pool_beg+7+i-1] = nftbuf[fnt__t_font_file_id+i-1]; for (i=1; i<17; i++) nftbuf[pool_beg+7+7+i-1] = ' '; for (i=1; i<17; i++) nftbuf[pool_beg+7+7+16+i-1] = nftbuf[fnt__t_font_file_id+i-1]; /* Now make string descriptors point into the string pool. */ #define fnt__a_char_set 260 #define fnt__a_family_id 268 #define fnt__a_family_name 276 #define fnt__a_font_id 284 lcx.ul = pool_beg; copy_to_nft(fnt__a_char_set); lcx.ul = pool_beg+7; copy_to_nft(fnt__a_family_id); lcx.ul = pool_beg+7+7; copy_to_nft(fnt__a_family_name); lcx.ul = pool_beg+7+7+16; copy_to_nft(fnt__a_font_id); nft_next_code = nft_first; #define fnt__l_portrait_byte_count 228 #define fnt__l_landscape_byte_count 232 #define fnt__l_mixed_byte_count 236 lcx.ul = 0; copy_to_nft(fnt__l_portrait_byte_count); copy_to_nft(fnt__l_landscape_byte_count); copy_to_nft(fnt__l_mixed_byte_count); } /* Cptonft copies one or more glyphs from the PXL file to the NFT file buffer. It reads from the command line two codes. Beginning at the first code and proceeding sequentially, it copies glyphs. As cptonft copies, it updates nftlen and nft_next_code to reflect what is going on, as well as the portrait, landscape and mixed sizes. */ int handle_cptonft () { int i,c1,c2; skipb; c1 = atoi(&inline[ilp]); skipnb; skipb; c2 = atoi(&inline[ilp]); if (c1 < 0 || c1 > 127 || c2 < 0 || c2 > 127 || c1 > c2) { printf("\nBad range of codes: [%d, %d]",c1,c2); return(1); } if (nft_next_code > nft_last) { printf("\nCan't copy more glyphs -- no slots left in NFT file."); return(1); } if (pxldir == 0) { printf("\nCan't copy because there isn't a good PXL file in"); printf(" the PXL buffer."); return(1); } if (c2-c1+1 > nft_last+1-nft_next_code) { c2 = c1+nft_last-nft_next_code; printf("\nCopying only up to code %d",c2); printf("\n -- no slots left for more glyphs in the NFT file."); } if (buffer_fixedp) { nftlen -= 8; buffer_fixedp = 0; } for(i=c1; i<=c2; i++) if (copy_glyph(i) != 0) return(1); return(0); } GLOBAL unsigned char rev_byte[256] = { 0,128,64,192,32,160,96,224, 16,144,80,208,48,176,112,240, 8,136,72,200,40,168,104,232, 24,152,88,216,56,184,120,248, 4,132,68,196,36,164,100,228, 20,148,84,212,52,180,116,244, 12,140,76,204,44,172,108,236, 28,156,92,220,60,188,124,252, 2,130,66,194,34,162,98,226, 18,146,82,210,50,178,114,242, 10,138,74,202,42,170,106,234, 26,154,90,218,58,186,122,250, 6,134,70,198,38,166,102,230, 22,150,86,214,54,182,118,246, 14,142,78,206,46,174,110,238, 30,158,94,222,62,190,126,254, 1,129,65,193,33,161,97,225, 17,145,81,209,49,177,113,241, 9,137,73,201,41,169,105,233, 25,153,89,217,57,185,121,249, 5,133,69,197,37,165,101,229, 21,149,85,213,53,181,117,245, 13,141,77,205,45,173,109,237, 29,157,93,221,61,189,125,253, 3,131,67,195,35,163,99,227, 19,147,83,211,51,179,115,243, 11,139,75,203,43,171,107,235, 27,155,91,219,59,187,123,251, 7,135,71,199,39,167,103,231, 23,151,87,215,55,183,119,247, 15,143,79,207,47,175,111,239, 31,159,95,223,63,191,127,255 }; /* Copy_glyph copies the rasters and character directory information corresponding to code i in the PXL file, into the nft_next_code position of the NFT file buffer. */ int copy_glyph(code) int code; { unsigned long ds,rs,i,j; unsigned int rows,cols,k,l,m,n; int xoffset, yoffset; float width; char all_blank; /* Locate the definition and the rasters for code in the PXL file. Check that the rasters are indeed within the pxl file. [[This check may need to be modified if we implement commands to add rasters to the pxl file.]] */ ds = pxldir+16*code; copy_from_pxl(ds+8); rs = 4*lcx.ul; cols = pxl_word(ds); rows = pxl_word(ds+2); if (rs+rows*4*((cols+31)/32) > pxllen) { printf("\nPXL file entry for code %d points outside file",code); printf("\nCopy to NFT file terminated before code %d",nft_next_code); return(1); } /* If a glyph has no rasters, an "undocumented feature" of the LN03 seems to cause the glyph to be printed incorrectly. Because of this, we set the number of rows and columns to 1, and put in a blank byte (below). */ all_blank = (rows == 0) & (cols == 0); if (all_blank) { cols = 1; rows = 1; } /* Check that we have enough room left in the NFT buffer. */ if (nftlen+rows*((cols+7)/32)+24 > NFTBUFSIZE) { printf("\nNo more room in NFT file buffer (%ld bytes long)", NFTBUFSIZE); printf("\nCopy to NFT file terminated before code %d",nft_next_code); return(1); } /* Compute the width of the glyph in pixels, the xoffset, and the yoffset. */ copy_from_pxl(ds+12); width = conv*lcx.ul; xoffset = signed_pxl_word(ds+4); yoffset = signed_pxl_word(ds+6); /* Clear the character definition area in the NFT file buffer. */ for(i=0; i<24+rows*((cols+7)/8); i++) nftbuf[nftlen+i] = 0; /* Set the fields in the first six longwords of the NFT character definition. The first assignment sets the so-called "flag flag", which must be always be set according to the DEC Common Font File Format. A conversion factor of 24 is used in converting pixel values, because the values are supposed to be in centipoints in the NFT file, and if we assume there are 300 pixels in an inch, then there are 7200 centipoints in an inch. [[Eventually, the resolution of the printer will have to be settable!]] */ nftbuf[nftlen+3] = 0x80; lcx.ul = 24*width+0.5; copy_to_nft(nftlen+4); lcx.l = -24*xoffset; copy_to_nft(nftlen+8); lcx.l = -24*yoffset; copy_to_nft(nftlen+12); /* The rasters are always placed in portrait into the NFT file, with no use of run-length encoding. Thus, the orient field in the raster format will be 0, and the Type 1 field is set to 0x81. */ nftbuf[nftlen+17] = 0x81; nftbuf[nftlen+20] = rows%256; nftbuf[nftlen+21] = rows/256; nftbuf[nftlen+22] = cols%256; nftbuf[nftlen+23] = cols/256; /* Now we copy the rasters themselves. As we do so, we have to reverse the bits within each byte. */ k = (cols+31)/32; n = (cols+7)/8; if (!all_blank) for (l=0; l j) ? i : j; copy_to_nft(fnt__l_mixed_byte_count); nft_next_code++; return(0); } /* The wnft command writes the contents of an NFT buffer into a file. It is necessary to do some fixup on the buffer the first time this is done. */ int handle_wnft() { int nftf; unsigned long i; skipb; istart = ilp; skipnb; inline[ilp] = '\0'; nftf = open_output_file(&inline[istart],".nft"); if (nftf == -1) { printf("\nUnable to open NFT file %s",&inline[istart]); return(1); } /* At this point we have to clean up a few fields before writing the file. */ #define fnt__l_char_definitions_length 156 if (!buffer_fixedp) { lcx.ul = nftlen-(480+(nft_last-nft_first+1)*4+48+4); copy_to_nft(fnt__l_char_definitions_length); nftlen += 8; lcx.ul = nftlen; copy_to_nft(0); copy_to_nft(nftlen-8); nftbuf[nftlen-4] = 'F'; nftbuf[nftlen-3] = 'O'; nftbuf[nftlen-2] = 'N'; nftbuf[nftlen-1] = 'T'; buffer_fixedp = 0; } /* Pad the file out to a multiple of 512 bytes */ if (nftlen%512 != 0) for (i=0; i<512-nftlen%512; i++) nftbuf[nftlen+i] = 0; /* Now for the actual writing */ for (i=0; i 512) target = 512; if (write(strf,&pxlbuf[i],target) == -1) { printf("\nError writing PXL file."); close(strf); return(1); } } close(strf); return(0); } int open_output_file (s,ext) char s[], ext[]; { char fs[FILESPECLEN]; int jnam,jext; strcpy(fs,s); find_VMS_filename(fs,&jnam,&jext); if (fs[jext] == '\0') strcat(fs,ext); return(creat(fs,0,"rfm=fix","mrs=512")); }