This is Bbl2rtf.m in view mode; [Download] [Up]
// Copyright H. Giesen, University of Koblenz-Landau 1996
#define LBRACE '{'
#define RBRACE '}'
#define LPARA '('
#define RPARA ')'
#define LBRACKET '['
#define RBRACKET ']'
#import "Bbl2rtf.h"
static char buf[512];
const char *rtfHeader =
"{\\rtf0\\ansi{\\fonttbl\\f0\\fswiss Helvetica;}\n"
"\\paperw8640\\paperh8280\\margl120\\margr120\n"
"\\f0\\pard\\tx200\\tx1040\\tx2080\\tx3920\\fc0\\cf0"
"\\fi-1060\\li1060\n";
const char *rtfTail = "}\\\n";
const char *htmlHeader = "<HTML><BODY>";
const char *htmlTail = "</BODY></HTML>";
typedef struct{
const char *texCmd;
const char *hdr[4];
}cvTblType;
cvTblType cvTable[] = {
{ "begin", {NULL, NULL, "<table>", NULL }},
{ "end", {NULL, NULL, "</table>", NULL }},
{ "bibitem", {"\\\n", NULL, "<P>", NULL }},
{ "newblock", {" ", NULL, " ", " " }},
{ "mbox", {NULL, NULL, NULL, NULL }},
{ "em", {"\\i", "\\i0", "<CITE>", "</CITE>" }},
{ "it", {"\\i", "\\i0", "<I>", "</I>" }},
{ "bf", {"\\b", "\\b0", "<B>", "</B>" }},
{ NULL, {NULL, NULL, NULL }}
};
@implementation Bbl2rtf
- initFromStream:(NXStream *)stream
{
[super init];
memStream = stream;
// create the output stream and position
textStream = NXOpenMemory(0, 0, NX_READWRITE);
NXSeek(textStream, 0L, NX_FROMSTART);
citeNumber = 0;
if( stack==nil )stack = [[List alloc] init];
return self;
}
- initFromFile:(const char *)fname
{
NXStream *locStream = NXMapFile(fname, NX_READONLY);
if( locStream ) return [self initFromStream:locStream];
return nil;
}
/* appendRTF: appends an arbitrary RTF string
* to the RTF object
*/
- appendRTF:(const char *)string
{
NXSeek(textStream, 0L, NX_FROMEND);
NXWrite(textStream, string, strlen(string));
return self;
}
- (void)nextChar
{
token = NXGetc( memStream );
if( token=='\n' ){
//lineNumber++;
}
if( token==EOF ) token=0;
}
- (int) indexOfCmd:(const char *)cmd
{
int i=0;
while( cvTable[i].texCmd ){
if( strcmp( cmd, cvTable[i].texCmd )==0 ){
return i;
}
i++;
}
return -1;
}
// called when '\' is found
- (int)cmd
{
int i=0;
[self nextChar];
while( NXIsAlpha(token) ){
buf[i++] = token;
[self nextChar];
}
if( i==0 ){ // was a quoted character
NXPutc(textStream, '\\');
/////NXUngetc( memStream );
return -1;
}
// TeX macro was found
buf[i] = '\0';
//if( token==LBRACE ) NXPutc(textStream, '\\');
//NXUngetc( memStream );
return [self indexOfCmd:buf];
}
- (void)copyBracket
{
while( token && (token!=LBRACKET) ) [self nextChar];
NXPutc(textStream, token); // output leftbracket
[self nextChar]; // skip leftbracket
while( token && (token!=RBRACKET) ){
NXPutc(textStream, token);
[self nextChar];
}
NXPutc(textStream, token);
[self nextChar]; // skip last bracket
}
// syntax of \bibitem :
// \bibitem[label]{cite_key}
// \bibitem{cite_key} // [label] must be generated
- (void) deleteBlock
{
while( token && (token!=LBRACE) ) [self nextChar];
while( token && (token!=RBRACE) )[self nextChar];
// token = rightbrace
lastToken = token;
[self nextChar]; // skip last rightbrace
}
- doBibItem
{
while( token && (token!=LBRACKET) && (token!=LBRACE) ) [self nextChar];
if( citeNumber && html ){
NXPrintf(textStream, "</td></tr>" ); // close last bibitem
}
citeNumber++;
if( html ) NXPrintf(textStream, "<tr><td valign=top>" ); // new row
if( token==LBRACKET ) [self copyBracket];
else{ // generate the label
NXPrintf(textStream, "[%d]", citeNumber );
}
if( html ) NXPrintf(textStream, "</td><td>" );
[self deleteBlock];
return self;
}
/* - convertTeX appends a TeX text, "escaping"
* all of the special characters in the text.
*/
- convertTeX
{
int count = 0;
int cmdInx;
[self nextChar];
while( token ){
switch( token ) {
/* escape special characters */
case '\n' :
if( lastToken=='\n' ){
if( html==2 ) NXPrintf(textStream, "<BR>");
else NXPrintf(textStream, "\\\n" );
}
break;
case '-' :{
unsigned char dash = '-'; // -X
if( html==2 ) break;
lastToken = '-';
[self nextChar];
if( token=='-' ){ // --
[self nextChar];
if( token=='-' ){ // ---
dash = 'Ð'; // emDash
}
else{// --X
dash = '±'; // enDash
}
}
NXPutc(textStream, dash);
continue;
}
case '~' :
if( html==2 ){
NXPrintf(textStream, " ");
lastToken = token;
[self nextChar];
continue;
}
else NXPutc(textStream, '\\');
break;
case LBRACE :
[self convertTeX];
lastToken = token; // is right brace
[self nextChar];
continue;
case RBRACE :
while( count ){
NXPrintf(textStream, "%s",
(char *)[stack removeLastObject]);
count--;
}
return self;
case '\\' :
cmdInx = [self cmd];
if( cmdInx<0 ){ // not in the table
lastToken = token;
continue;
}
// the TeX-command was found in the rtf/html - list
if( cvTable[cmdInx].hdr[html+0] )
NXPrintf(textStream, "%s", cvTable[cmdInx].hdr[html+0] );
if( cvTable[cmdInx].hdr[html+1] ){
[stack addObject:(id)cvTable[cmdInx].hdr[html+1]];
count++;
}
// evaluate the command
if( cmdInx==0 ){ //begin
// skip to end of line
while( token && (token!='\n') ) [self nextChar];
lastToken = token;
continue;
}
if( cmdInx==1 ){ //end
// skip to end of line
while( token && (token!='\n') ) [self nextChar];
lastToken = token;
continue;
}
if( cmdInx==2 ){ //bibitem
[self doBibItem];
NXPutc(textStream, '\t' );
continue;
}
lastToken = token;
continue;
default: break;
}
NXPutc(textStream, token);
lastToken = token;
[self nextChar];
}
return self;
}
- (BOOL) convert2Rtf
{
NXSeek(textStream, 0L, NX_FROMSTART);
NXWrite(textStream, rtfHeader, strlen(rtfHeader));
NXGetMemoryBuffer(memStream, &fBuffer, &fLength, &fMaxLength);
NXSeek(memStream, 0L, NX_FROMSTART);
token = lastToken = ' ';
html = 0;
[self convertTeX];
NXWrite(textStream, rtfTail, strlen(rtfTail));
return YES;
}
- (BOOL) convert2HTML
{
NXSeek(textStream, 0L, NX_FROMSTART);
NXWrite(textStream, htmlHeader, strlen(htmlHeader));
NXGetMemoryBuffer(memStream, &fBuffer, &fLength, &fMaxLength);
NXSeek(memStream, 0L, NX_FROMSTART);
token = lastToken = ' ';
html = 2;
[self convertTeX];
NXWrite(textStream, htmlTail, strlen(htmlTail));
return YES;
}
- saveTo:(const char *)fname
{
NXFlush( textStream );
NXSaveToFile( textStream, fname );
NXCloseMemory( textStream, NX_FREEBUFFER );
textStream = NULL;
return self;
}
- (NXStream *)stream
{
return textStream;
}
- free
{
if( textStream )NXCloseMemory(textStream, NX_FREEBUFFER);
if( memStream ) NXCloseMemory( memStream, NX_FREEBUFFER );
[stack free];
return [super free];
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.