mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-05-29 20:57:38 +00:00
Moved text conversion classes to separate bundle
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@10755 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
e4dd491dad
commit
30d3fd1bc0
22 changed files with 409 additions and 844 deletions
36
TextConverters/GNUmakefile
Normal file
36
TextConverters/GNUmakefile
Normal file
|
@ -0,0 +1,36 @@
|
|||
#
|
||||
# Makefile for TextConverters bundles
|
||||
#
|
||||
# Copyright (C) 2001 Free Software Foundation, Inc.
|
||||
#
|
||||
# Author: Adam Fedor <fedor@gnu.org>
|
||||
#
|
||||
# This file is part of the GNUstep GUI Library.
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Library General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2 of the License, or (at your option) any later version.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Library General Public License for more details.
|
||||
#
|
||||
# If you are interested in a warranty or support for this source code,
|
||||
# contact Scott Christley at scottc@net-community.com
|
||||
#
|
||||
# You should have received a copy of the GNU Library General Public
|
||||
# License along with this library; see the file COPYING.LIB.
|
||||
# If not, write to the Free Software Foundation,
|
||||
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
GNUSTEP_MAKEFILES = $(GNUSTEP_SYSTEM_ROOT)/Makefiles
|
||||
|
||||
include $(GNUSTEP_MAKEFILES)/common.make
|
||||
#
|
||||
# The list of subproject directories
|
||||
#
|
||||
SUBPROJECTS = RTF
|
||||
|
||||
include $(GNUSTEP_MAKEFILES)/aggregate.make
|
41
TextConverters/RTF/GNUmakefile
Normal file
41
TextConverters/RTF/GNUmakefile
Normal file
|
@ -0,0 +1,41 @@
|
|||
# GNUmakefile
|
||||
#
|
||||
# Copyright (C) 2001 Free Software Foundation, Inc.
|
||||
#
|
||||
# Author: Adam Fedor <fedor@gnu.org>
|
||||
#
|
||||
# This file is part of GNUstep
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
include $(GNUSTEP_MAKEFILES)/common.make
|
||||
|
||||
BUNDLE_NAME = RTFConverter
|
||||
BUNDLE_INSTALL_DIR =$(GNUSTEP_BUNDLES)/TextConverters
|
||||
|
||||
RTFConverter_OBJC_FILES = \
|
||||
RTFConsumer.m RTFProducer.m
|
||||
|
||||
RTFConverter_C_FILES = \
|
||||
rtfGrammer.tab.c rtfScanner.c
|
||||
|
||||
RTFConverter_PRINCIPAL_CLASS = RTFConsumer
|
||||
|
||||
-include GNUmakefile.preamble
|
||||
|
||||
include $(GNUSTEP_MAKEFILES)/bundle.make
|
||||
|
||||
-include GNUmakefile.postamble
|
||||
|
32
TextConverters/RTF/GNUmakefile.postamble
Normal file
32
TextConverters/RTF/GNUmakefile.postamble
Normal file
|
@ -0,0 +1,32 @@
|
|||
# GNUmakefile.postamble
|
||||
#
|
||||
# Copyright (C) 2001 Free Software Foundation, Inc.
|
||||
#
|
||||
# Author: Philippe C.D. Robert <prh@3dkit.org>
|
||||
#
|
||||
# This file is part of GNUstep
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Library General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2 of the License, or (at your option) any later version.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Library General Public License for more details.
|
||||
#
|
||||
# If you are interested in a warranty or support for this source code,
|
||||
# contact Scott Christley at scottc@net-community.com
|
||||
#
|
||||
# You should have received a copy of the GNU Library General Public
|
||||
# License along with this library; see the file COPYING.LIB.
|
||||
# If not, write to the Free Software Foundation,
|
||||
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
BISON_FLAGS = -d -p GSRTF
|
||||
BISON = BISON_SIMPLE=bison.simple bison
|
||||
|
||||
# This parser doesn't compile with newer bison programs. Needs to be fixed...
|
||||
#rtfGrammer.tab.c: rtfGrammer.y
|
||||
# $(BISON) $(BISON_FLAGS) $<
|
73
TextConverters/RTF/GNUmakefile.preamble
Normal file
73
TextConverters/RTF/GNUmakefile.preamble
Normal file
|
@ -0,0 +1,73 @@
|
|||
# GNUmakefile.preamble
|
||||
#
|
||||
# Copyright (C) 2001 Free Software Foundation, Inc.
|
||||
#
|
||||
# Author: Philippe C.D. Robert <prh@3dkit.org>
|
||||
#
|
||||
# This file is part of GNUstep
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Library General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2 of the License, or (at your option) any later version.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Library General Public License for more details.
|
||||
#
|
||||
# If you are interested in a warranty or support for this source code,
|
||||
# contact Scott Christley at scottc@net-community.com
|
||||
#
|
||||
# You should have received a copy of the GNU Library General Public
|
||||
# License along with this library; see the file COPYING.LIB.
|
||||
# If not, write to the Free Software Foundation,
|
||||
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#
|
||||
# Makefile.preamble
|
||||
#
|
||||
# Project specific makefile variables, and additional
|
||||
#
|
||||
# Do not put any Makefile rules in this file, instead they should
|
||||
# be put into Makefile.postamble.
|
||||
#
|
||||
|
||||
#
|
||||
# Flags dealing with compiling and linking
|
||||
#
|
||||
|
||||
# Additional flags to pass to the preprocessor
|
||||
ADDITIONAL_CPPFLAGS +=
|
||||
|
||||
# Additional flags to pass to the Objective-C compiler
|
||||
ADDITIONAL_OBJCFLAGS +=
|
||||
|
||||
# Additional flags to pass to the C compiler
|
||||
ADDITIONAL_CFLAGS +=
|
||||
#ADDITIONAL_CFLAGS +=
|
||||
|
||||
# Additional include directories the compiler should search
|
||||
ADDITIONAL_INCLUDE_DIRS +=-I../../Headers
|
||||
|
||||
# Additional LDFLAGS to pass to the linker
|
||||
#ADDITIONAL_LDFLAGS +=
|
||||
|
||||
# Additional library directories the linker should search
|
||||
#ADDITIONAL_LIB_DIRS +=
|
||||
|
||||
#ADDITIONAL_TOOL_LIBS +=
|
||||
|
||||
#
|
||||
# Flags dealing with installing and uninstalling
|
||||
#
|
||||
|
||||
# Additional directories to be created during installation
|
||||
#ADDITIONAL_INSTALL_DIRS +=
|
||||
|
||||
#
|
||||
# Local configuration
|
||||
#
|
||||
|
||||
|
||||
|
51
TextConverters/RTF/RTFConsumer.h
Normal file
51
TextConverters/RTF/RTFConsumer.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
/* rtfConsumer.h created by pingu on Fri 12-Nov-1999
|
||||
|
||||
Copyright (C) 1999 Free Software Foundation, Inc.
|
||||
|
||||
Author: Stefan Bðhringer (stefan.boehringer@uni-bochum.de)
|
||||
Date: Dec 1999
|
||||
|
||||
This file is part of the GNUstep GUI Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; see the file COPYING.LIB.
|
||||
If not, write to the Free Software Foundation,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef _rtfConsumer_h_INCLUDE
|
||||
#define _rtfConsumer_h_INCLUDE
|
||||
|
||||
#include <AppKit/GSTextConverter.h>
|
||||
|
||||
@class NSMutableDictionary;
|
||||
@class NSMutableArray;
|
||||
@class NSMutableAttributedString;
|
||||
|
||||
@interface RTFConsumer: NSObject <GSTextConsumer>
|
||||
{
|
||||
@public
|
||||
NSMutableDictionary *documentAttributes;
|
||||
NSMutableDictionary *fonts;
|
||||
NSMutableArray *colours;
|
||||
NSMutableArray *attrs;
|
||||
NSMutableAttributedString *result;
|
||||
int ignore;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface RTFDConsumer: RTFConsumer
|
||||
@end
|
||||
|
||||
#endif
|
913
TextConverters/RTF/RTFConsumer.m
Normal file
913
TextConverters/RTF/RTFConsumer.m
Normal file
|
@ -0,0 +1,913 @@
|
|||
/* attributedStringConsumer.m
|
||||
|
||||
Copyright (C) 1999 Free Software Foundation, Inc.
|
||||
|
||||
Author: Stefan Bðhringer (stefan.boehringer@uni-bochum.de)
|
||||
Date: Dec 1999
|
||||
Author: Fred Kiefer <FredKiefer@gmx.de>
|
||||
Date: June 2000
|
||||
|
||||
This file is part of the GNUstep GUI Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; see the file COPYING.LIB.
|
||||
If not, write to the Free Software Foundation,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <Foundation/Foundation.h>
|
||||
#include <AppKit/AppKit.h>
|
||||
#include "RTFConsumer.h"
|
||||
#include "RTFConsumerFunctions.h"
|
||||
#include "RTFProducer.h"
|
||||
|
||||
/* we have to satisfy the scanner with a stream reading function */
|
||||
typedef struct {
|
||||
NSString *string;
|
||||
int position;
|
||||
int length;
|
||||
} StringContext;
|
||||
|
||||
static void
|
||||
initStringContext (StringContext *ctxt, NSString *string)
|
||||
{
|
||||
ctxt->string = string;
|
||||
ctxt->position = 0;
|
||||
ctxt->length = [string length];
|
||||
}
|
||||
|
||||
static int
|
||||
readNSString (StringContext *ctxt)
|
||||
{
|
||||
return (ctxt->position < ctxt->length )
|
||||
? [ctxt->string characterAtIndex:ctxt->position++]: EOF;
|
||||
}
|
||||
|
||||
// Hold the attributs of the current run
|
||||
@interface RTFAttribute: NSObject <NSCopying>
|
||||
{
|
||||
@public
|
||||
BOOL changed;
|
||||
BOOL tabChanged;
|
||||
NSMutableParagraphStyle *paragraph;
|
||||
NSColor *fgColour;
|
||||
NSColor *bgColour;
|
||||
NSString *fontName;
|
||||
float fontSize;
|
||||
BOOL bold;
|
||||
BOOL italic;
|
||||
BOOL underline;
|
||||
int script;
|
||||
}
|
||||
|
||||
- (NSFont*) currentFont;
|
||||
- (NSNumber*) script;
|
||||
- (NSNumber*) underline;
|
||||
- (void) resetParagraphStyle;
|
||||
- (void) resetFont;
|
||||
- (void) addTab: (float)location type: (NSTextTabType)type;
|
||||
|
||||
@end
|
||||
|
||||
@implementation RTFAttribute
|
||||
|
||||
- (id) init
|
||||
{
|
||||
[self resetFont];
|
||||
[self resetParagraphStyle];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
RELEASE(paragraph);
|
||||
RELEASE(fontName);
|
||||
RELEASE(fgColour);
|
||||
RELEASE(bgColour);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (id) copyWithZone: (NSZone*)zone
|
||||
{
|
||||
RTFAttribute *new = (RTFAttribute *)NSCopyObject (self, 0, zone);
|
||||
|
||||
new->paragraph = [paragraph copyWithZone: zone];
|
||||
RETAIN(new->fontName);
|
||||
RETAIN(new->fgColour);
|
||||
RETAIN(new->bgColour);
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
- (NSFont*) currentFont
|
||||
{
|
||||
NSFont *font;
|
||||
NSFontTraitMask traits = 0;
|
||||
int weight;
|
||||
|
||||
if (bold)
|
||||
{
|
||||
weight = 9;
|
||||
traits |= NSBoldFontMask;
|
||||
}
|
||||
else
|
||||
{
|
||||
weight = 5;
|
||||
traits |= NSUnboldFontMask;
|
||||
}
|
||||
|
||||
if (italic)
|
||||
{
|
||||
traits |= NSItalicFontMask;
|
||||
}
|
||||
else
|
||||
{
|
||||
traits |= NSUnitalicFontMask;
|
||||
}
|
||||
|
||||
font = [[NSFontManager sharedFontManager] fontWithFamily: fontName
|
||||
traits: traits
|
||||
weight: weight
|
||||
size: fontSize];
|
||||
if (font == nil)
|
||||
{
|
||||
NSDebugMLLog(@"RTFParser",
|
||||
@"Could not find font %@ size %f traits %d weight %d",
|
||||
fontName, fontSize, traits, weight);
|
||||
font = [NSFont userFontOfSize: fontSize];
|
||||
}
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
- (NSNumber*) script
|
||||
{
|
||||
return [NSNumber numberWithInt: script];
|
||||
}
|
||||
|
||||
- (NSNumber*) underline
|
||||
{
|
||||
if (underline)
|
||||
return [NSNumber numberWithInt: NSSingleUnderlineStyle];
|
||||
else
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void) resetParagraphStyle
|
||||
{
|
||||
ASSIGN(paragraph, [NSMutableParagraphStyle defaultParagraphStyle]);
|
||||
|
||||
tabChanged = NO;
|
||||
changed = YES;
|
||||
}
|
||||
|
||||
- (void) resetFont
|
||||
{
|
||||
NSFont *font = [NSFont userFontOfSize:12];
|
||||
|
||||
ASSIGN(fontName, [font familyName]);
|
||||
fontSize = 12.0;
|
||||
italic = NO;
|
||||
bold = NO;
|
||||
|
||||
underline = NO;
|
||||
script = 0;
|
||||
DESTROY(fgColour);
|
||||
DESTROY(bgColour);
|
||||
|
||||
changed = YES;
|
||||
}
|
||||
|
||||
- (void) addTab: (float) location type: (NSTextTabType) type
|
||||
{
|
||||
NSTextTab *tab = [[NSTextTab alloc] initWithType: NSLeftTabStopType
|
||||
location: location];
|
||||
|
||||
if (!tabChanged)
|
||||
{
|
||||
// remove all tab stops
|
||||
[paragraph setTabStops: [NSArray arrayWithObject: tab]];
|
||||
tabChanged = YES;
|
||||
}
|
||||
else
|
||||
{
|
||||
[paragraph addTabStop: tab];
|
||||
}
|
||||
|
||||
changed = YES;
|
||||
RELEASE(tab);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface RTFConsumer (Private)
|
||||
|
||||
- (NSAttributedString*) parseRTF: (NSData *)rtfData
|
||||
documentAttributes: (NSDictionary **)dict;
|
||||
- (NSDictionary*) documentAttributes;
|
||||
- (NSAttributedString*) result;
|
||||
|
||||
- (RTFAttribute*) attr;
|
||||
- (void) push;
|
||||
- (void) pop;
|
||||
|
||||
@end
|
||||
|
||||
@implementation RTFConsumer
|
||||
|
||||
/* RTFConsumer is the principal class and thus implements this */
|
||||
+ (Class) classForFormat: (NSString *)format producer: (BOOL)flag
|
||||
{
|
||||
Class cClass = Nil;
|
||||
|
||||
if (flag)
|
||||
{
|
||||
if ([format isEqual: @"RTFD"])
|
||||
cClass = [RTFDProducer class];
|
||||
else if ([format isEqual: @"RTF"])
|
||||
cClass = [RTFProducer class];
|
||||
}
|
||||
else
|
||||
{
|
||||
if ([format isEqual: @"RTFD"])
|
||||
cClass = [RTFDConsumer class];
|
||||
else if ([format isEqual: @"RTF"])
|
||||
cClass = [RTFConsumer class];
|
||||
}
|
||||
return cClass;
|
||||
}
|
||||
|
||||
+ (NSAttributedString*) parseFile: (NSFileWrapper *)wrapper
|
||||
documentAttributes: (NSDictionary **)dict
|
||||
{
|
||||
RTFConsumer *consumer = [RTFConsumer new];
|
||||
NSAttributedString *text = nil;
|
||||
|
||||
if ([wrapper isRegularFile])
|
||||
{
|
||||
text = [consumer parseRTF: [wrapper regularFileContents]
|
||||
documentAttributes: dict];
|
||||
}
|
||||
else if ([wrapper isDirectory])
|
||||
{
|
||||
NSDictionary *files = [wrapper fileWrappers];
|
||||
NSFileWrapper *contents;
|
||||
|
||||
//FIXME: We should store the files in the consumer
|
||||
// We try to read the main file in the directory
|
||||
if ((contents = [files objectForKey: @"TXT.rtf"]) != nil)
|
||||
{
|
||||
text = [consumer parseRTF: [contents regularFileContents]
|
||||
documentAttributes: dict];
|
||||
}
|
||||
}
|
||||
|
||||
RELEASE(consumer);
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
+ (NSAttributedString*) parseData: (NSData *)rtfData
|
||||
documentAttributes: (NSDictionary **)dict
|
||||
{
|
||||
RTFConsumer *consumer = [RTFConsumer new];
|
||||
NSAttributedString *text;
|
||||
|
||||
text = [consumer parseRTF: rtfData
|
||||
documentAttributes: dict];
|
||||
RELEASE(consumer);
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
- (id) init
|
||||
{
|
||||
ignore = 0;
|
||||
result = nil;
|
||||
documentAttributes = nil;
|
||||
fonts = nil;
|
||||
attrs = nil;
|
||||
colours = nil;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
RELEASE(fonts);
|
||||
RELEASE(attrs);
|
||||
RELEASE(colours);
|
||||
RELEASE(result);
|
||||
RELEASE(documentAttributes);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation RTFDConsumer
|
||||
|
||||
+ (NSAttributedString*) parseFile: (NSFileWrapper *)wrapper
|
||||
documentAttributes: (NSDictionary **)dict
|
||||
{
|
||||
return [super parseFile: wrapper
|
||||
documentAttributes: dict];
|
||||
}
|
||||
|
||||
+ (NSAttributedString*) parseData: (NSData *)rtfData
|
||||
documentAttributes: (NSDictionary **)dict
|
||||
{
|
||||
NSAttributedString *str;
|
||||
NSFileWrapper *wrapper = [[NSFileWrapper alloc]
|
||||
initWithSerializedRepresentation: rtfData];
|
||||
|
||||
str = [self parseFile: wrapper documentAttributes: dict];
|
||||
RELEASE (wrapper);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation RTFConsumer (Private)
|
||||
|
||||
- (NSDictionary*) documentAttributes
|
||||
{
|
||||
RETAIN(documentAttributes);
|
||||
return AUTORELEASE(documentAttributes);
|
||||
}
|
||||
|
||||
- (void) reset
|
||||
{
|
||||
RTFAttribute *attr = [RTFAttribute new];
|
||||
|
||||
ignore = 0;
|
||||
DESTROY(result);
|
||||
result = [[NSMutableAttributedString alloc] init];
|
||||
ASSIGN(documentAttributes, [NSMutableDictionary dictionary]);
|
||||
ASSIGN(fonts, [NSMutableDictionary dictionary]);
|
||||
ASSIGN(attrs, [NSMutableArray array]);
|
||||
ASSIGN(colours, [NSMutableArray array]);
|
||||
[attrs addObject: attr];
|
||||
RELEASE(attr);
|
||||
}
|
||||
|
||||
- (RTFAttribute*) attr
|
||||
{
|
||||
return [attrs lastObject];
|
||||
}
|
||||
|
||||
- (void) push
|
||||
{
|
||||
RTFAttribute *attr = [[attrs lastObject] copy];
|
||||
|
||||
[attrs addObject: attr];
|
||||
RELEASE(attr);
|
||||
}
|
||||
|
||||
- (void) pop
|
||||
{
|
||||
[attrs removeLastObject];
|
||||
((RTFAttribute*)[attrs lastObject])->changed = YES;
|
||||
}
|
||||
|
||||
- (NSAttributedString*) result
|
||||
{
|
||||
RETAIN(result);
|
||||
return AUTORELEASE(result);
|
||||
}
|
||||
|
||||
- (NSAttributedString*) parseRTF: (NSData *)rtfData
|
||||
documentAttributes: (NSDictionary **)dict
|
||||
{
|
||||
CREATE_AUTORELEASE_POOL(pool);
|
||||
RTFscannerCtxt scanner;
|
||||
StringContext stringCtxt;
|
||||
// We should read in the first few characters to find out which
|
||||
// encoding we have
|
||||
NSString *rtfString = [[NSString alloc]
|
||||
initWithData: rtfData
|
||||
encoding: NSASCIIStringEncoding];
|
||||
|
||||
// Reset this RFTConsumer, as it might already have been used!
|
||||
[self reset];
|
||||
|
||||
initStringContext(&stringCtxt, rtfString);
|
||||
lexInitContext(&scanner, &stringCtxt, (int (*)(void*))readNSString);
|
||||
NS_DURING
|
||||
GSRTFparse((void *)self, &scanner);
|
||||
NS_HANDLER
|
||||
NSLog(@"Problem during RTF Parsing: %@",
|
||||
[localException reason]);
|
||||
//[localException raise];
|
||||
NS_ENDHANDLER
|
||||
|
||||
RELEASE(rtfString);
|
||||
RELEASE(pool);
|
||||
// document attributes
|
||||
if (dict)
|
||||
{
|
||||
*dict = [self documentAttributes];
|
||||
}
|
||||
|
||||
return [self result];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#undef IGNORE
|
||||
#define FONTS ((RTFConsumer *)ctxt)->fonts
|
||||
#define COLOURS ((RTFConsumer *)ctxt)->colours
|
||||
#define RESULT ((RTFConsumer *)ctxt)->result
|
||||
#define IGNORE ((RTFConsumer *)ctxt)->ignore
|
||||
#define TEXTPOSITION [RESULT length]
|
||||
#define DOCUMENTATTRIBUTES ((RTFConsumer*)ctxt)->documentAttributes
|
||||
|
||||
#define CTXT [((RTFConsumer *)ctxt) attr]
|
||||
#define CHANGED CTXT->changed
|
||||
#define PARAGRAPH CTXT->paragraph
|
||||
#define FONTNAME CTXT->fontName
|
||||
#define SCRIPT CTXT->script
|
||||
#define ITALIC CTXT->italic
|
||||
#define BOLD CTXT->bold
|
||||
#define UNDERLINE CTXT->underline
|
||||
#define FGCOLOUR CTXT->fgColour
|
||||
#define BGCOLOUR CTXT->bgColour
|
||||
|
||||
#define PAPERSIZE @"PaperSize"
|
||||
#define LEFTMARGIN @"LeftMargin"
|
||||
#define RIGHTMARGIN @"RightMargin"
|
||||
#define TOPMARGIN @"TopMargin"
|
||||
#define BUTTOMMARGIN @"ButtomMargin"
|
||||
|
||||
/*
|
||||
we must implement from the rtfConsumerFunctions.h file (Supporting files)
|
||||
this includes the yacc error handling and output
|
||||
*/
|
||||
|
||||
/* handle errors (this is the yacc error mech) */
|
||||
void GSRTFerror (const char *msg)
|
||||
{
|
||||
[NSException raise:NSInvalidArgumentException
|
||||
format:@"Syntax error in RTF: %s", msg];
|
||||
}
|
||||
|
||||
void GSRTFgenericRTFcommand (void *ctxt, RTFcmd cmd)
|
||||
{
|
||||
NSDebugLLog(@"RTFParser", @"encountered rtf cmd:%s", cmd.name);
|
||||
if (!cmd.isEmpty)
|
||||
NSDebugLLog(@"RTFParser", @" argument is %d\n", cmd.parameter);
|
||||
}
|
||||
|
||||
//Start: we're doing some initialization
|
||||
void GSRTFstart (void *ctxt)
|
||||
{
|
||||
NSDebugLLog(@"RTFParser", @"Start RTF parsing");
|
||||
[RESULT beginEditing];
|
||||
}
|
||||
|
||||
// Finished to parse one piece of RTF.
|
||||
void GSRTFstop (void *ctxt)
|
||||
{
|
||||
//<!> close all open bolds et al.
|
||||
[RESULT endEditing];
|
||||
NSDebugLLog(@"RTFParser", @"End RTF parsing");
|
||||
}
|
||||
|
||||
void GSRTFopenBlock (void *ctxt, BOOL ignore)
|
||||
{
|
||||
if (!IGNORE)
|
||||
{
|
||||
[(RTFConsumer *)ctxt push];
|
||||
}
|
||||
// Switch off any output for ignored block statements
|
||||
if (ignore)
|
||||
{
|
||||
IGNORE++;
|
||||
}
|
||||
}
|
||||
|
||||
void GSRTFcloseBlock (void *ctxt, BOOL ignore)
|
||||
{
|
||||
if (ignore)
|
||||
{
|
||||
IGNORE--;
|
||||
}
|
||||
if (!IGNORE)
|
||||
{
|
||||
[(RTFConsumer *)ctxt pop];
|
||||
}
|
||||
}
|
||||
|
||||
void GSRTFmangleText (void *ctxt, const char *text)
|
||||
{
|
||||
int oldPosition = TEXTPOSITION;
|
||||
int textlen = strlen(text);
|
||||
NSRange insertionRange = NSMakeRange(oldPosition,0);
|
||||
NSMutableDictionary *attributes;
|
||||
|
||||
if (!IGNORE && textlen)
|
||||
{
|
||||
[RESULT replaceCharactersInRange: insertionRange
|
||||
withString: [NSString stringWithCString:text]];
|
||||
|
||||
if (CHANGED)
|
||||
{
|
||||
attributes = [NSMutableDictionary
|
||||
dictionaryWithObjectsAndKeys:
|
||||
[CTXT currentFont], NSFontAttributeName,
|
||||
PARAGRAPH, NSParagraphStyleAttributeName,
|
||||
nil];
|
||||
if (UNDERLINE)
|
||||
{
|
||||
[attributes setObject: [CTXT underline]
|
||||
forKey: NSUnderlineStyleAttributeName];
|
||||
}
|
||||
if (SCRIPT)
|
||||
{
|
||||
[attributes setObject: [CTXT script]
|
||||
forKey: NSSuperscriptAttributeName];
|
||||
}
|
||||
if (FGCOLOUR != nil)
|
||||
{
|
||||
[attributes setObject: FGCOLOUR
|
||||
forKey: NSForegroundColorAttributeName];
|
||||
}
|
||||
if (BGCOLOUR != nil)
|
||||
{
|
||||
[attributes setObject: BGCOLOUR
|
||||
forKey: NSBackgroundColorAttributeName];
|
||||
}
|
||||
|
||||
[RESULT setAttributes: attributes
|
||||
range: NSMakeRange(oldPosition, textlen)];
|
||||
CHANGED = NO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GSRTFregisterFont (void *ctxt, const char *fontName,
|
||||
RTFfontFamily family, int fontNumber)
|
||||
{
|
||||
NSString *fontNameString;
|
||||
NSNumber *fontId = [NSNumber numberWithInt: fontNumber];
|
||||
|
||||
if (!fontName || !*fontName)
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Error in RTF (font omitted?), position:%d",
|
||||
TEXTPOSITION];
|
||||
}
|
||||
// exclude trailing ';' from fontName
|
||||
fontNameString = [NSString stringWithCString: fontName
|
||||
length: strlen(fontName)-1];
|
||||
[FONTS setObject: fontNameString forKey: fontId];
|
||||
}
|
||||
|
||||
void GSRTFfontNumber (void *ctxt, int fontNumber)
|
||||
{
|
||||
NSNumber *fontId = [NSNumber numberWithInt: fontNumber];
|
||||
NSString *fontName = [FONTS objectForKey: fontId];
|
||||
|
||||
if (fontName == nil)
|
||||
{
|
||||
/* we're about to set an unknown font */
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Error in RTF (referring to undefined font \\f%d), position:%d",
|
||||
fontNumber,
|
||||
TEXTPOSITION];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (![fontName isEqual: FONTNAME])
|
||||
{
|
||||
ASSIGN(FONTNAME, fontName);
|
||||
CHANGED = YES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// <N> fontSize is in halfpoints according to spec
|
||||
void GSRTFfontSize (void *ctxt, int fontSize)
|
||||
{
|
||||
float size = halfpoints2points(fontSize);
|
||||
|
||||
if (size != CTXT->fontSize)
|
||||
{
|
||||
CTXT->fontSize = size;
|
||||
CHANGED = YES;
|
||||
}
|
||||
}
|
||||
|
||||
void GSRTFpaperWidth (void *ctxt, int width)
|
||||
{
|
||||
float fwidth = twips2points(width);
|
||||
NSMutableDictionary *dict = DOCUMENTATTRIBUTES;
|
||||
NSValue *val = [dict objectForKey: PAPERSIZE];
|
||||
NSSize size;
|
||||
|
||||
if (val == nil)
|
||||
{
|
||||
size = NSMakeSize(fwidth, 792);
|
||||
}
|
||||
else
|
||||
{
|
||||
size = [val sizeValue];
|
||||
size.width = fwidth;
|
||||
}
|
||||
[dict setObject: [NSValue valueWithSize: size] forKey: PAPERSIZE];
|
||||
}
|
||||
|
||||
void GSRTFpaperHeight (void *ctxt, int height)
|
||||
{
|
||||
float fheight = twips2points(height);
|
||||
NSMutableDictionary *dict = DOCUMENTATTRIBUTES;
|
||||
NSValue *val = [dict objectForKey: PAPERSIZE];
|
||||
NSSize size;
|
||||
|
||||
if (val == nil)
|
||||
{
|
||||
size = NSMakeSize(612, fheight);
|
||||
}
|
||||
else
|
||||
{
|
||||
size = [val sizeValue];
|
||||
size.height = fheight;
|
||||
}
|
||||
[dict setObject: [NSValue valueWithSize: size] forKey: PAPERSIZE];
|
||||
}
|
||||
|
||||
void GSRTFmarginLeft (void *ctxt, int margin)
|
||||
{
|
||||
float fmargin = twips2points(margin);
|
||||
NSMutableDictionary *dict = DOCUMENTATTRIBUTES;
|
||||
|
||||
[dict setObject: [NSNumber numberWithFloat: fmargin] forKey: LEFTMARGIN];
|
||||
}
|
||||
|
||||
void GSRTFmarginRight (void *ctxt, int margin)
|
||||
{
|
||||
float fmargin = twips2points(margin);
|
||||
NSMutableDictionary *dict = DOCUMENTATTRIBUTES;
|
||||
|
||||
[dict setObject: [NSNumber numberWithFloat: fmargin] forKey: RIGHTMARGIN];
|
||||
}
|
||||
|
||||
void GSRTFmarginTop (void *ctxt, int margin)
|
||||
{
|
||||
float fmargin = twips2points(margin);
|
||||
NSMutableDictionary *dict = DOCUMENTATTRIBUTES;
|
||||
|
||||
[dict setObject: [NSNumber numberWithFloat: fmargin] forKey: TOPMARGIN];
|
||||
}
|
||||
|
||||
void GSRTFmarginButtom (void *ctxt, int margin)
|
||||
{
|
||||
float fmargin = twips2points(margin);
|
||||
NSMutableDictionary *dict = DOCUMENTATTRIBUTES;
|
||||
|
||||
[dict setObject: [NSNumber numberWithFloat: fmargin] forKey: BUTTOMMARGIN];
|
||||
}
|
||||
|
||||
void GSRTFfirstLineIndent (void *ctxt, int indent)
|
||||
{
|
||||
NSMutableParagraphStyle *para = PARAGRAPH;
|
||||
float findent = twips2points(indent);
|
||||
|
||||
// FIXME: This should changed the left indent of the paragraph, if < 0
|
||||
// for attributed strings only positiv indent is allowed
|
||||
if ((findent >= 0.0) && ([para firstLineHeadIndent] != findent))
|
||||
{
|
||||
[para setFirstLineHeadIndent: findent];
|
||||
CHANGED = YES;
|
||||
}
|
||||
}
|
||||
|
||||
void GSRTFleftIndent (void *ctxt, int indent)
|
||||
{
|
||||
NSMutableParagraphStyle *para = PARAGRAPH;
|
||||
float findent = twips2points(indent);
|
||||
|
||||
// for attributed strings only positiv indent is allowed
|
||||
if ((findent >= 0.0) && ([para headIndent] != findent))
|
||||
{
|
||||
[para setHeadIndent: findent];
|
||||
CHANGED = YES;
|
||||
}
|
||||
}
|
||||
|
||||
void GSRTFrightIndent (void *ctxt, int indent)
|
||||
{
|
||||
NSMutableParagraphStyle *para = PARAGRAPH;
|
||||
float findent = twips2points(indent);
|
||||
|
||||
// for attributed strings only positiv indent is allowed
|
||||
if ((findent >= 0.0) && ([para tailIndent] != findent))
|
||||
{
|
||||
[para setTailIndent: findent];
|
||||
CHANGED = YES;
|
||||
}
|
||||
}
|
||||
|
||||
void GSRTFtabstop (void *ctxt, int location)
|
||||
{
|
||||
float flocation = twips2points(location);
|
||||
|
||||
if (flocation >= 0.0)
|
||||
{
|
||||
[CTXT addTab: flocation type: NSLeftTabStopType];
|
||||
}
|
||||
}
|
||||
|
||||
void GSRTFalignCenter (void *ctxt)
|
||||
{
|
||||
NSMutableParagraphStyle *para = PARAGRAPH;
|
||||
|
||||
if ([para alignment] != NSCenterTextAlignment)
|
||||
{
|
||||
[para setAlignment: NSCenterTextAlignment];
|
||||
CHANGED = YES;
|
||||
}
|
||||
}
|
||||
|
||||
void GSRTFalignJustified (void *ctxt)
|
||||
{
|
||||
NSMutableParagraphStyle *para = PARAGRAPH;
|
||||
|
||||
if ([para alignment] != NSJustifiedTextAlignment)
|
||||
{
|
||||
[para setAlignment: NSJustifiedTextAlignment];
|
||||
CHANGED = YES;
|
||||
}
|
||||
}
|
||||
|
||||
void GSRTFalignLeft (void *ctxt)
|
||||
{
|
||||
NSMutableParagraphStyle *para = PARAGRAPH;
|
||||
|
||||
if ([para alignment] != NSLeftTextAlignment)
|
||||
{
|
||||
[para setAlignment: NSLeftTextAlignment];
|
||||
CHANGED = YES;
|
||||
}
|
||||
}
|
||||
|
||||
void GSRTFalignRight (void *ctxt)
|
||||
{
|
||||
NSMutableParagraphStyle *para = PARAGRAPH;
|
||||
|
||||
if ([para alignment] != NSRightTextAlignment)
|
||||
{
|
||||
[para setAlignment: NSRightTextAlignment];
|
||||
CHANGED = YES;
|
||||
}
|
||||
}
|
||||
|
||||
void GSRTFspaceAbove (void *ctxt, int space)
|
||||
{
|
||||
NSMutableParagraphStyle *para = PARAGRAPH;
|
||||
float fspace = twips2points(space);
|
||||
|
||||
if (fspace >= 0.0)
|
||||
{
|
||||
[para setParagraphSpacing: fspace];
|
||||
}
|
||||
}
|
||||
|
||||
void GSRTFlineSpace (void *ctxt, int space)
|
||||
{
|
||||
NSMutableParagraphStyle *para = PARAGRAPH;
|
||||
float fspace = twips2points(space);
|
||||
|
||||
if (space == 1000)
|
||||
{
|
||||
[para setMinimumLineHeight: 0.0];
|
||||
[para setMaximumLineHeight: 0.0];
|
||||
}
|
||||
else if (fspace < 0.0)
|
||||
{
|
||||
[para setMaximumLineHeight: -fspace];
|
||||
}
|
||||
else
|
||||
{
|
||||
[para setMinimumLineHeight: fspace];
|
||||
}
|
||||
}
|
||||
|
||||
void GSRTFdefaultParagraph (void *ctxt)
|
||||
{
|
||||
[CTXT resetParagraphStyle];
|
||||
}
|
||||
|
||||
void GSRTFstyle (void *ctxt, int style)
|
||||
{
|
||||
}
|
||||
|
||||
void GSRTFdefaultCharacterStyle (void *ctxt)
|
||||
{
|
||||
[CTXT resetFont];
|
||||
}
|
||||
|
||||
void GSRTFaddColor (void *ctxt, int red, int green, int blue)
|
||||
{
|
||||
NSColor *colour = [NSColor colorWithCalibratedRed: red/255.0
|
||||
green: green/255.0
|
||||
blue: blue/255.0
|
||||
alpha: 1.0];
|
||||
|
||||
[COLOURS addObject: colour];
|
||||
}
|
||||
|
||||
void GSRTFaddDefaultColor (void *ctxt)
|
||||
{
|
||||
[COLOURS addObject: [NSColor textColor]];
|
||||
}
|
||||
|
||||
void GSRTFcolorbg (void *ctxt, int color)
|
||||
{
|
||||
if ([COLOURS count] <= color)
|
||||
{
|
||||
ASSIGN (BGCOLOUR, [NSColor whiteColor]);
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSIGN (BGCOLOUR, [COLOURS objectAtIndex: color]);
|
||||
}
|
||||
}
|
||||
|
||||
void GSRTFcolorfg (void *ctxt, int color)
|
||||
{
|
||||
if ([COLOURS count] <= color)
|
||||
{
|
||||
ASSIGN (FGCOLOUR, [NSColor blackColor]);
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSIGN (FGCOLOUR, [COLOURS objectAtIndex: color]);
|
||||
}
|
||||
}
|
||||
|
||||
void GSRTFsubscript (void *ctxt, int script)
|
||||
{
|
||||
script = (int) (-halfpoints2points(script) / 3.0);
|
||||
|
||||
if (script != SCRIPT)
|
||||
{
|
||||
SCRIPT = script;
|
||||
CHANGED = YES;
|
||||
}
|
||||
}
|
||||
|
||||
void GSRTFsuperscript (void *ctxt, int script)
|
||||
{
|
||||
script = (int) (halfpoints2points(script) / 3.0);
|
||||
|
||||
if (script != SCRIPT)
|
||||
{
|
||||
SCRIPT = script;
|
||||
CHANGED = YES;
|
||||
}
|
||||
}
|
||||
|
||||
void GSRTFitalic (void *ctxt, BOOL state)
|
||||
{
|
||||
if (state != ITALIC)
|
||||
{
|
||||
ITALIC = state;
|
||||
CHANGED = YES;
|
||||
}
|
||||
}
|
||||
|
||||
void GSRTFbold (void *ctxt, BOOL state)
|
||||
{
|
||||
if (state != BOLD)
|
||||
{
|
||||
BOLD = state;
|
||||
CHANGED = YES;
|
||||
}
|
||||
}
|
||||
|
||||
void GSRTFunderline (void *ctxt, BOOL state)
|
||||
{
|
||||
if (state != UNDERLINE)
|
||||
{
|
||||
UNDERLINE = state;
|
||||
CHANGED = YES;
|
||||
}
|
||||
}
|
||||
|
||||
void GSRTFparagraph (void *ctxt)
|
||||
{
|
||||
GSRTFmangleText(ctxt, "\n");
|
||||
CTXT->tabChanged = NO;
|
||||
}
|
135
TextConverters/RTF/RTFConsumerFunctions.h
Normal file
135
TextConverters/RTF/RTFConsumerFunctions.h
Normal file
|
@ -0,0 +1,135 @@
|
|||
/* rtfConsumerFunctions.h created by pingu on Wed 17-Nov-1999
|
||||
|
||||
Copyright (C) 1999 Free Software Foundation, Inc.
|
||||
|
||||
Author: Stefan Bðhringer (stefan.boehringer@uni-bochum.de)
|
||||
Date: Dec 1999
|
||||
|
||||
This file is part of the GNUstep GUI Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; see the file COPYING.LIB.
|
||||
If not, write to the Free Software Foundation,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* here we define the interface functions to grammer consumers */
|
||||
|
||||
#ifndef rtfConsumerFunctions_h_INCLUDE
|
||||
#define rtfConsumerFunctions_h_INCLUDE
|
||||
|
||||
#include "rtfScanner.h"
|
||||
|
||||
/* general statements:
|
||||
measurement is usually in twips: one twentieth of a point (this is about 0.01764 mm)
|
||||
a tabstop of 540 twips (as it occurs on NeXT) is therefore about 0.95 cm
|
||||
*/
|
||||
#define halfpoints2points(a) ((a)/2.0)
|
||||
#define twips2points(a) ((a)/20.0)
|
||||
#define twips2mm(a) ((a)*0.01764)
|
||||
|
||||
/* prepare the ctxt, or whatever you want */
|
||||
void GSRTFstart(void *ctxt);
|
||||
|
||||
/* seal the parsing process, the context or whatever you want */
|
||||
void GSRTFstop(void *ctxt);
|
||||
|
||||
/* those pairing functions enclose RTFBlocks. Use it to capture the hierarchical attribute changes of blocks.
|
||||
i.e. attributes of a block are forgotten once a block is closed
|
||||
*/
|
||||
void GSRTFopenBlock(void *ctxt, BOOL ignore);
|
||||
void GSRTFcloseBlock(void *ctxt, BOOL ignore);
|
||||
|
||||
/* handle errors */
|
||||
void GSRTFerror(const char *msg);
|
||||
|
||||
/* handle rtf commands not expicated in the grammer */
|
||||
void GSRTFgenericRTFcommand(void *ctxt, RTFcmd cmd);
|
||||
|
||||
/* go, handle text */
|
||||
void GSRTFmangleText(void *ctxt, const char *text);
|
||||
|
||||
/*
|
||||
font functions
|
||||
*/
|
||||
|
||||
/* get noticed that a particular font is introduced */
|
||||
void GSRTFregisterFont(void *ctxt, const char *fontName,
|
||||
RTFfontFamily family, int fontNumber);
|
||||
|
||||
/* change font number */
|
||||
void GSRTFfontNumber(void *ctxt, int fontNumber);
|
||||
/* change font size in half points*/
|
||||
void GSRTFfontSize(void *ctxt, int fontSize);
|
||||
|
||||
/* set paper width in twips */
|
||||
void GSRTFpaperWidth(void *ctxt, int width);
|
||||
/* set paper height in twips */
|
||||
void GSRTFpaperHeight(void *ctxt, int height);
|
||||
/* set left margin in twips */
|
||||
void GSRTFmarginLeft(void *ctxt, int margin);
|
||||
/* set right margin in twips */
|
||||
void GSRTFmarginRight(void *ctxt, int margin);
|
||||
/* set top margin in twips */
|
||||
void GSRTFmarginTop(void *ctxt, int margin);
|
||||
/* set buttom margin in twips */
|
||||
void GSRTFmarginButtom(void *ctxt, int margin);
|
||||
/* set first line indent */
|
||||
void GSRTFfirstLineIndent(void *ctxt, int indent);
|
||||
/* set left indent */
|
||||
void GSRTFleftIndent(void *ctxt, int indent);
|
||||
/* set right indent */
|
||||
void GSRTFrightIndent(void *ctxt, int indent);
|
||||
/* set tabstop */
|
||||
void GSRTFtabstop(void *ctxt, int location);
|
||||
/* set center alignment */
|
||||
void GSRTFalignCenter(void *ctxt);
|
||||
/* set justified alignment */
|
||||
void GSRTFalignJustified(void *ctxt);
|
||||
/* set left alignment */
|
||||
void GSRTFalignLeft(void *ctxt);
|
||||
/* set right alignment */
|
||||
void GSRTFalignRight(void *ctxt);
|
||||
/* set space above */
|
||||
void GSRTFspaceAbove(void *ctxt, int location);
|
||||
/* set line space */
|
||||
void GSRTFlineSpace(void *ctxt, int location);
|
||||
/* set default paragraph style */
|
||||
void GSRTFdefaultParagraph(void *ctxt);
|
||||
/* set paragraph style */
|
||||
void GSRTFstyle(void *ctxt, int style);
|
||||
/* Add a colour to the colour table*/
|
||||
void GSRTFaddColor(void *ctxt, int red, int green, int blue);
|
||||
/* Add the default colour to the colour table*/
|
||||
void GSRTFaddDefaultColor(void *ctxt);
|
||||
/* set background colour */
|
||||
void GSRTFcolorbg(void *ctxt, int color);
|
||||
/* set foreground colour */
|
||||
void GSRTFcolorfg(void *ctxt, int color);
|
||||
/* set default character style */
|
||||
void GSRTFdefaultCharacterStyle(void *ctxt);
|
||||
/* set subscript in half points */
|
||||
void GSRTFsubscript(void *ctxt, int script);
|
||||
/* set superscript in half points */
|
||||
void GSRTFsuperscript(void *ctxt, int script);
|
||||
/* Switch bold mode on or off */
|
||||
void GSRTFbold(void *ctxt, BOOL on);
|
||||
/* Switch italic mode on or off */
|
||||
void GSRTFitalic(void *ctxt, BOOL on);
|
||||
/* Switch underline mode on or off */
|
||||
void GSRTFunderline(void *ctxt, BOOL on);
|
||||
/* new paragraph */
|
||||
void GSRTFparagraph(void *ctxt);
|
||||
|
||||
#endif
|
||||
|
57
TextConverters/RTF/RTFProducer.h
Normal file
57
TextConverters/RTF/RTFProducer.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
RTFProducer.h
|
||||
|
||||
Writes out a NSAttributedString as RTF
|
||||
|
||||
Copyright (C) 2000 Free Software Foundation, Inc.
|
||||
|
||||
Author: Fred Kiefer <FredKiefer@gmx.de>
|
||||
Date: June 2000
|
||||
|
||||
This file is part of the GNUstep GUI Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; see the file COPYING.LIB.
|
||||
If not, write to the Free Software Foundation,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <AppKit/GSTextConverter.h>
|
||||
|
||||
@class NSAttributedString;
|
||||
@class NSMutableDictionary;
|
||||
@class NSColor;
|
||||
@class NSFont;
|
||||
@class NSMutableParagraphStyle;
|
||||
|
||||
@interface RTFDProducer: NSObject <GSTextProducer>
|
||||
{
|
||||
@public
|
||||
NSAttributedString *text;
|
||||
NSMutableDictionary *fontDict;
|
||||
NSMutableDictionary *colorDict;
|
||||
NSMutableDictionary *docDict;
|
||||
|
||||
NSColor *fgColor;
|
||||
NSColor *bgColor;
|
||||
NSFont *currentFont;
|
||||
/*
|
||||
NSMutableParagraphStyle *paragraph;
|
||||
*/
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface RTFProducer: RTFDProducer
|
||||
// Subclass with no special interface
|
||||
@end
|
704
TextConverters/RTF/RTFProducer.m
Normal file
704
TextConverters/RTF/RTFProducer.m
Normal file
|
@ -0,0 +1,704 @@
|
|||
/*
|
||||
RTFProducer.m
|
||||
|
||||
Writes out a NSAttributedString as RTF
|
||||
|
||||
Copyright (C) 1999 Free Software Foundation, Inc.
|
||||
|
||||
Author: Daniel Bðhringer
|
||||
Date: November 1999
|
||||
Modifications: Fred Kiefer <FredKiefer@gmx.de>
|
||||
Date: June 2000
|
||||
|
||||
This file is part of the GNUstep GUI Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; see the file COPYING.LIB.
|
||||
If not, write to the Free Software Foundation,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#include <Foundation/Foundation.h>
|
||||
#include <AppKit/AppKit.h>
|
||||
#include "RTFProducer.h"
|
||||
|
||||
// FIXME: Should be defined in a central place
|
||||
#define PAPERSIZE @"PaperSize"
|
||||
#define LEFTMARGIN @"LeftMargin"
|
||||
#define RIGHTMARGIN @"RightMargin"
|
||||
#define TOPMARGIN @"TopMargin"
|
||||
#define BUTTOMMARGIN @"ButtomMargin"
|
||||
|
||||
#define points2twips(a) ((a)*20.0)
|
||||
|
||||
@interface RTFDProducer (Private)
|
||||
|
||||
- (NSString*) headerString;
|
||||
- (NSString*) trailerString;
|
||||
- (NSString*) bodyString;
|
||||
- (NSString*) RTFDStringFromAttributedString: (NSAttributedString*)aText
|
||||
documentAttributes: (NSDictionary*)dict;
|
||||
@end
|
||||
|
||||
@implementation RTFDProducer
|
||||
|
||||
+ (NSFileWrapper*) produceFileFrom: (NSAttributedString*) aText
|
||||
documentAttributes: (NSDictionary*)dict
|
||||
{
|
||||
RTFDProducer *new = [self new];
|
||||
NSData *data;
|
||||
NSFileWrapper *wrapper;
|
||||
|
||||
data = [[new RTFDStringFromAttributedString: aText
|
||||
documentAttributes: dict]
|
||||
dataUsingEncoding: NSISOLatin1StringEncoding];
|
||||
|
||||
if ([aText containsAttachments])
|
||||
{
|
||||
NSMutableDictionary *fileDict = [NSMutableDictionary dictionary];
|
||||
NSFileWrapper *txt = [[NSFileWrapper alloc]
|
||||
initRegularFileWithContents: data];
|
||||
|
||||
[fileDict setObject: txt forKey: @"TXT.rtf"];
|
||||
RELEASE(txt);
|
||||
// FIXME: We have to add the attachments to the directory file wrapper
|
||||
|
||||
wrapper = [[NSFileWrapper alloc] initDirectoryWithFileWrappers: fileDict];
|
||||
}
|
||||
else
|
||||
wrapper = [[NSFileWrapper alloc] initRegularFileWithContents: data];
|
||||
|
||||
|
||||
RELEASE(new);
|
||||
return AUTORELEASE(wrapper);
|
||||
}
|
||||
|
||||
+ (NSData*) produceDataFrom: (NSAttributedString*) aText
|
||||
documentAttributes: (NSDictionary*)dict
|
||||
{
|
||||
return [[self produceFileFrom: aText
|
||||
documentAttributes: dict] serializedRepresentation];
|
||||
}
|
||||
|
||||
- (id)init
|
||||
{
|
||||
/*
|
||||
* maintain a dictionary for the used colours
|
||||
* (for rtf-header generation)
|
||||
*/
|
||||
colorDict = [NSMutableDictionary new];
|
||||
/*
|
||||
* maintain a dictionary for the used fonts
|
||||
* (for rtf-header generation)
|
||||
*/
|
||||
fontDict = [NSMutableDictionary new];
|
||||
|
||||
currentFont = nil;
|
||||
ASSIGN(fgColor, [NSColor textColor]);
|
||||
ASSIGN(bgColor, [NSColor textBackgroundColor]);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
RELEASE(text);
|
||||
RELEASE(fontDict);
|
||||
RELEASE(colorDict);
|
||||
RELEASE(docDict);
|
||||
|
||||
RELEASE(currentFont);
|
||||
RELEASE(fgColor);
|
||||
RELEASE(bgColor);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation RTFProducer
|
||||
|
||||
+ (NSData*) produceDataFrom: (NSAttributedString*) aText
|
||||
documentAttributes: (NSDictionary*)dict
|
||||
{
|
||||
RTFProducer *new = [self new];
|
||||
NSData *data;
|
||||
|
||||
data = [[new RTFDStringFromAttributedString: aText
|
||||
documentAttributes: dict]
|
||||
dataUsingEncoding: NSISOLatin1StringEncoding];
|
||||
RELEASE(new);
|
||||
return data;
|
||||
}
|
||||
|
||||
+ (NSFileWrapper*) produceFileFrom: (NSAttributedString*) aText
|
||||
documentAttributes: (NSDictionary*)dict
|
||||
{
|
||||
return [[NSFileWrapper alloc] initRegularFileWithContents:
|
||||
[self produceDataFrom: aText
|
||||
documentAttributes: dict]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation RTFDProducer (Private)
|
||||
|
||||
- (NSString*) fontTable
|
||||
{
|
||||
// write Font Table
|
||||
if ([fontDict count])
|
||||
{
|
||||
NSMutableString *fontlistString = [NSMutableString string];
|
||||
NSEnumerator *fontEnum;
|
||||
NSString *currFont;
|
||||
NSArray *keyArray;
|
||||
|
||||
keyArray = [fontDict allKeys];
|
||||
keyArray = [keyArray sortedArrayUsingSelector: @selector(compare:)];
|
||||
|
||||
fontEnum = [keyArray objectEnumerator];
|
||||
while ((currFont = [fontEnum nextObject]) != nil)
|
||||
{
|
||||
NSString *fontFamily;
|
||||
NSString *detail;
|
||||
|
||||
// If we ever have more fonts to map to families, we should use a dictionary
|
||||
if ([currFont isEqualToString: @"Symbol"])
|
||||
fontFamily = @"tech";
|
||||
else if ([currFont isEqualToString: @"Helvetica"])
|
||||
fontFamily = @"swiss";
|
||||
else if ([currFont isEqualToString: @"Courier"])
|
||||
fontFamily = @"modern";
|
||||
else if ([currFont isEqualToString: @"Times"])
|
||||
fontFamily = @"roman";
|
||||
else
|
||||
fontFamily = @"nil";
|
||||
|
||||
detail = [NSString stringWithFormat: @"%@\\f%@ %@;",
|
||||
[fontDict objectForKey: currFont], fontFamily, currFont];
|
||||
[fontlistString appendString: detail];
|
||||
}
|
||||
return [NSString stringWithFormat: @"{\\fonttbl%@}\n", fontlistString];
|
||||
}
|
||||
else
|
||||
return @"";
|
||||
}
|
||||
|
||||
- (NSString*) colorTable
|
||||
{
|
||||
// write Colour table
|
||||
if ([colorDict count])
|
||||
{
|
||||
NSMutableString *result;
|
||||
unsigned int count = [colorDict count];
|
||||
NSMutableArray *list = [NSMutableArray arrayWithCapacity: count];
|
||||
NSEnumerator *keyEnum = [colorDict keyEnumerator];
|
||||
id next;
|
||||
int i;
|
||||
|
||||
while ((next = [keyEnum nextObject]) != nil)
|
||||
{
|
||||
NSNumber *cn = [colorDict objectForKey: next];
|
||||
[list insertObject: next atIndex: [cn intValue]-1];
|
||||
}
|
||||
|
||||
result = (NSMutableString*)[NSMutableString stringWithString: @"{\\colortbl;"];
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
NSColor *color = [[list objectAtIndex: i]
|
||||
colorUsingColorSpaceName: NSCalibratedRGBColorSpace];
|
||||
[result appendString: [NSString stringWithFormat:
|
||||
@"\\red%d\\green%d\\blue%d;",
|
||||
(int)([color redComponent]*255),
|
||||
(int)([color greenComponent]*255),
|
||||
(int)([color blueComponent]*255)]];
|
||||
}
|
||||
|
||||
[result appendString: @"}\n"];
|
||||
return result;
|
||||
}
|
||||
else
|
||||
return @"";
|
||||
}
|
||||
|
||||
- (NSString*) documentAttributes
|
||||
{
|
||||
if (docDict != nil)
|
||||
{
|
||||
NSMutableString *result;
|
||||
NSString *detail;
|
||||
NSValue *val;
|
||||
NSNumber *num;
|
||||
|
||||
result = (NSMutableString*)[NSMutableString string];
|
||||
|
||||
val = [docDict objectForKey: PAPERSIZE];
|
||||
if (val != nil)
|
||||
{
|
||||
NSSize size = [val sizeValue];
|
||||
detail = [NSString stringWithFormat: @"\\paperw%d \\paperh%d",
|
||||
(int)points2twips(size.width),
|
||||
(int)points2twips(size.height)];
|
||||
[result appendString: detail];
|
||||
}
|
||||
|
||||
num = [docDict objectForKey: LEFTMARGIN];
|
||||
if (num != nil)
|
||||
{
|
||||
float f = [num floatValue];
|
||||
detail = [NSString stringWithFormat: @"\\margl%d",
|
||||
(int)points2twips(f)];
|
||||
[result appendString: detail];
|
||||
}
|
||||
num = [docDict objectForKey: RIGHTMARGIN];
|
||||
if (num != nil)
|
||||
{
|
||||
float f = [num floatValue];
|
||||
detail = [NSString stringWithFormat: @"\\margr%d",
|
||||
(int)points2twips(f)];
|
||||
[result appendString: detail];
|
||||
}
|
||||
num = [docDict objectForKey: TOPMARGIN];
|
||||
if (num != nil)
|
||||
{
|
||||
float f = [num floatValue];
|
||||
detail = [NSString stringWithFormat: @"\\margt%d",
|
||||
(int)points2twips(f)];
|
||||
[result appendString: detail];
|
||||
}
|
||||
num = [docDict objectForKey: BUTTOMMARGIN];
|
||||
if (num != nil)
|
||||
{
|
||||
float f = [num floatValue];
|
||||
detail = [NSString stringWithFormat: @"\\margb%d",
|
||||
(int)points2twips(f)];
|
||||
[result appendString: detail];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
else
|
||||
return @"";
|
||||
}
|
||||
|
||||
- (NSString*) headerString
|
||||
{
|
||||
NSMutableString *result;
|
||||
|
||||
result = (NSMutableString*)[NSMutableString stringWithString: @"{\\rtf1\\ansi"];
|
||||
|
||||
[result appendString: [self fontTable]];
|
||||
[result appendString: [self colorTable]];
|
||||
[result appendString: [self documentAttributes]];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
- (NSString*) trailerString
|
||||
{
|
||||
return @"}";
|
||||
}
|
||||
|
||||
- (NSString*) fontToken: (NSString*) fontName
|
||||
{
|
||||
NSString *fCount = [fontDict objectForKey: fontName];
|
||||
|
||||
if (fCount == nil)
|
||||
{
|
||||
unsigned count = [fontDict count];
|
||||
|
||||
fCount = [NSString stringWithFormat: @"\\f%d", count];
|
||||
[fontDict setObject: fCount forKey: fontName];
|
||||
}
|
||||
|
||||
return fCount;
|
||||
}
|
||||
|
||||
- (int) numberForColor: (NSColor*)color
|
||||
{
|
||||
unsigned int cn;
|
||||
NSNumber *num = [colorDict objectForKey: color];
|
||||
|
||||
if (num == nil)
|
||||
{
|
||||
cn = [colorDict count] + 1;
|
||||
|
||||
[colorDict setObject: [NSNumber numberWithInt: cn]
|
||||
forKey: color];
|
||||
}
|
||||
else
|
||||
cn = [num intValue];
|
||||
|
||||
return cn;
|
||||
}
|
||||
|
||||
- (NSString*) paragraphStyle: (NSParagraphStyle*) paraStyle
|
||||
{
|
||||
NSMutableString *headerString = (NSMutableString *)[NSMutableString
|
||||
stringWithString:
|
||||
@"\\pard\\plain"];
|
||||
int twips;
|
||||
|
||||
if (paraStyle == nil)
|
||||
return headerString;
|
||||
|
||||
switch ([paraStyle alignment])
|
||||
{
|
||||
case NSRightTextAlignment:
|
||||
[headerString appendString: @"\\qr"];
|
||||
break;
|
||||
case NSCenterTextAlignment:
|
||||
[headerString appendString: @"\\qc"];
|
||||
break;
|
||||
case NSLeftTextAlignment:
|
||||
[headerString appendString: @"\\ql"];
|
||||
break;
|
||||
case NSJustifiedTextAlignment:
|
||||
[headerString appendString: @"\\qj"];
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
// write first line indent and left indent
|
||||
twips = (int)points2twips([paraStyle firstLineHeadIndent]);
|
||||
if (twips != 0.0)
|
||||
{
|
||||
[headerString appendString: [NSString stringWithFormat:
|
||||
@"\\fi%d",
|
||||
twips]];
|
||||
}
|
||||
twips = (int)points2twips([paraStyle headIndent]);
|
||||
if (twips != 0.0)
|
||||
{
|
||||
[headerString appendString: [NSString stringWithFormat:
|
||||
@"\\li%d",
|
||||
twips]];
|
||||
}
|
||||
twips = (int)points2twips([paraStyle tailIndent]);
|
||||
if (twips != 0.0)
|
||||
{
|
||||
[headerString appendString: [NSString stringWithFormat:
|
||||
@"\\ri%d",
|
||||
twips]];
|
||||
}
|
||||
twips = (int)points2twips([paraStyle paragraphSpacing]);
|
||||
if (twips != 0.0)
|
||||
{
|
||||
[headerString appendString: [NSString stringWithFormat:
|
||||
@"\\sa%d",
|
||||
twips]];
|
||||
}
|
||||
twips = (int)points2twips([paraStyle minimumLineHeight]);
|
||||
if (twips != 0.0)
|
||||
{
|
||||
[headerString appendString: [NSString stringWithFormat:
|
||||
@"\\sl%d",
|
||||
twips]];
|
||||
}
|
||||
twips = (int)points2twips([paraStyle maximumLineHeight]);
|
||||
if (twips != 0.0)
|
||||
{
|
||||
[headerString appendString: [NSString stringWithFormat:
|
||||
@"\\sl-%d",
|
||||
twips]];
|
||||
}
|
||||
// FIXME: Tab definitions are still missing
|
||||
|
||||
return headerString;
|
||||
}
|
||||
|
||||
- (NSString*) runStringForString: (NSString*) substring
|
||||
attributes: (NSDictionary*) attributes
|
||||
paragraphStart: (BOOL) first
|
||||
{
|
||||
NSMutableString *result = [NSMutableString stringWithCapacity:
|
||||
[substring length]*2];
|
||||
NSMutableString *headerString = [NSMutableString stringWithCapacity: 20];
|
||||
NSMutableString *trailerString = [NSMutableString stringWithCapacity: 20];
|
||||
NSEnumerator *attribEnum;
|
||||
id currAttrib;
|
||||
|
||||
if (first)
|
||||
{
|
||||
NSParagraphStyle *paraStyle = [attributes objectForKey:
|
||||
NSParagraphStyleAttributeName];
|
||||
[headerString appendString: [self paragraphStyle: paraStyle]];
|
||||
DESTROY(currentFont);
|
||||
}
|
||||
|
||||
/*
|
||||
* analyze attributes of current run
|
||||
*
|
||||
* FIXME: All the character attributes should be output relative to the font
|
||||
* attributes of the paragraph. So if the paragraph has underline on it should
|
||||
* still be possible to switch it off for some characters, which currently is
|
||||
* not possible.
|
||||
*/
|
||||
attribEnum = [attributes keyEnumerator];
|
||||
while ((currAttrib = [attribEnum nextObject]) != nil)
|
||||
{
|
||||
if ([currAttrib isEqualToString: NSFontAttributeName])
|
||||
{
|
||||
/*
|
||||
* handle fonts
|
||||
*/
|
||||
NSFont *font;
|
||||
NSString *fontName;
|
||||
NSFontTraitMask traits;
|
||||
NSFontTraitMask oldTraits;
|
||||
|
||||
font = [attributes objectForKey: NSFontAttributeName];
|
||||
fontName = [font familyName];
|
||||
traits = [[NSFontManager sharedFontManager] traitsOfFont: font];
|
||||
|
||||
if (currentFont == nil)
|
||||
oldTraits = 0;
|
||||
else
|
||||
oldTraits = [[NSFontManager sharedFontManager] traitsOfFont: currentFont];
|
||||
|
||||
/*
|
||||
* font name
|
||||
*/
|
||||
if (currentFont == nil ||
|
||||
![fontName isEqualToString: [currentFont familyName]])
|
||||
{
|
||||
[headerString appendString: [self fontToken: fontName]];
|
||||
}
|
||||
/*
|
||||
* font size
|
||||
*/
|
||||
if (currentFont == nil ||
|
||||
[font pointSize] != [currentFont pointSize])
|
||||
{
|
||||
int points = (int)[font pointSize]*2;
|
||||
NSString *pString;
|
||||
|
||||
pString = [NSString stringWithFormat: @"\\fs%d", points];
|
||||
[headerString appendString: pString];
|
||||
}
|
||||
/*
|
||||
* font attributes
|
||||
*/
|
||||
if ((traits & NSItalicFontMask) != (oldTraits & NSItalicFontMask))
|
||||
{
|
||||
if (traits & NSItalicFontMask)
|
||||
{
|
||||
[headerString appendString: @"\\i"];
|
||||
[trailerString appendString: @"\\i0"];
|
||||
}
|
||||
else
|
||||
{
|
||||
[headerString appendString: @"\\i0"];
|
||||
[trailerString appendString: @"\\i"];
|
||||
}
|
||||
}
|
||||
if ((traits & NSBoldFontMask) != (oldTraits & NSBoldFontMask))
|
||||
{
|
||||
if (traits & NSBoldFontMask)
|
||||
{
|
||||
[headerString appendString: @"\\b"];
|
||||
[trailerString appendString: @"\\b0"];
|
||||
}
|
||||
else
|
||||
{
|
||||
[headerString appendString: @"\\b0"];
|
||||
[trailerString appendString: @"\\b"];
|
||||
}
|
||||
}
|
||||
|
||||
if (first)
|
||||
ASSIGN(currentFont, font);
|
||||
}
|
||||
else if ([currAttrib isEqualToString: NSForegroundColorAttributeName])
|
||||
{
|
||||
NSColor *color = [attributes objectForKey: NSForegroundColorAttributeName];
|
||||
if (![color isEqual: fgColor])
|
||||
{
|
||||
[headerString appendString: [NSString stringWithFormat:
|
||||
@"\\cf%d",
|
||||
[self numberForColor: color]]];
|
||||
[trailerString appendString: @"\\cf0"];
|
||||
}
|
||||
}
|
||||
else if ([currAttrib isEqualToString: NSBackgroundColorAttributeName])
|
||||
{
|
||||
NSColor *color = [attributes objectForKey: NSBackgroundColorAttributeName];
|
||||
if (![color isEqual: bgColor])
|
||||
{
|
||||
[headerString appendString: [NSString stringWithFormat:
|
||||
@"\\cb%d",
|
||||
[self numberForColor: color]]];
|
||||
[trailerString appendString: @"\\cb0"];
|
||||
}
|
||||
}
|
||||
else if ([currAttrib isEqualToString: NSUnderlineStyleAttributeName])
|
||||
{
|
||||
[headerString appendString: @"\\ul"];
|
||||
[trailerString appendString: @"\\ulnone"];
|
||||
}
|
||||
else if ([currAttrib isEqualToString: NSSuperscriptAttributeName])
|
||||
{
|
||||
NSNumber *value = [attributes objectForKey: NSSuperscriptAttributeName];
|
||||
int svalue = [value intValue] * 6;
|
||||
|
||||
if (svalue > 0)
|
||||
{
|
||||
[headerString appendString: [NSString stringWithFormat:
|
||||
@"\\up%d", svalue]];
|
||||
[trailerString appendString: @"\\up0"];
|
||||
}
|
||||
else if (svalue < 0)
|
||||
{
|
||||
[headerString appendString: [NSString stringWithFormat:
|
||||
@"\\dn-%d", svalue]];
|
||||
[trailerString appendString: @"\\dn0"];
|
||||
}
|
||||
}
|
||||
else if ([currAttrib isEqualToString: NSBaselineOffsetAttributeName])
|
||||
{
|
||||
NSNumber *value = [attributes objectForKey: NSBaselineOffsetAttributeName];
|
||||
int svalue = (int)[value floatValue] * 2;
|
||||
|
||||
if (svalue > 0)
|
||||
{
|
||||
[headerString appendString: [NSString stringWithFormat:
|
||||
@"\\up%d", svalue]];
|
||||
[trailerString appendString: @"\\up0"];
|
||||
}
|
||||
else if (svalue < 0)
|
||||
{
|
||||
[headerString appendString: [NSString stringWithFormat:
|
||||
@"\\dn-%d", svalue]];
|
||||
[trailerString appendString: @"\\dn0"];
|
||||
}
|
||||
}
|
||||
else if ([currAttrib isEqualToString: NSAttachmentAttributeName])
|
||||
{
|
||||
}
|
||||
else if ([currAttrib isEqualToString: NSLigatureAttributeName])
|
||||
{
|
||||
}
|
||||
else if ([currAttrib isEqualToString: NSKernAttributeName])
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: There should be a more efficient way to replace these
|
||||
substring = [substring stringByReplacingString: @"\\"
|
||||
withString: @"\\\\"];
|
||||
substring = [substring stringByReplacingString: @"\n"
|
||||
withString: @"\\par\n"];
|
||||
substring = [substring stringByReplacingString: @"\t"
|
||||
withString: @"\\tab "];
|
||||
substring = [substring stringByReplacingString: @"{"
|
||||
withString: @"\\{"];
|
||||
substring = [substring stringByReplacingString: @"}"
|
||||
withString: @"\\}"];
|
||||
// FIXME: All characters not in the standard encoding must be
|
||||
// replaced by \'xx
|
||||
|
||||
if (!first)
|
||||
{
|
||||
NSString *braces;
|
||||
|
||||
if ([headerString length])
|
||||
braces = [NSString stringWithFormat: @"{%@ %@}",
|
||||
headerString, substring];
|
||||
else
|
||||
braces = substring;
|
||||
|
||||
[result appendString: braces];
|
||||
}
|
||||
else
|
||||
{
|
||||
NSString *nobraces;
|
||||
|
||||
if ([headerString length])
|
||||
nobraces = [NSString stringWithFormat: @"%@ %@",
|
||||
headerString, substring];
|
||||
else
|
||||
nobraces = substring;
|
||||
|
||||
/* This has no result, as the character style is reset for each paragraph
|
||||
if ([trailerString length])
|
||||
nobraces = [NSString stringWithFormat: @"%@%@ ",
|
||||
nobraces, trailerString];
|
||||
*/
|
||||
|
||||
[result appendString: nobraces];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
- (NSString*) bodyString
|
||||
{
|
||||
NSString *string = [text string];
|
||||
NSMutableString *result = [NSMutableString string];
|
||||
unsigned loc = 0;
|
||||
unsigned length = [string length];
|
||||
|
||||
while (loc < length)
|
||||
{
|
||||
// Range of the current run
|
||||
NSRange currRange = NSMakeRange(loc, 0);
|
||||
// Range of the current paragraph
|
||||
NSRange completeRange = [string lineRangeForRange: currRange];
|
||||
BOOL first = YES;
|
||||
|
||||
while (NSMaxRange(currRange) < NSMaxRange(completeRange)) // save all "runs"
|
||||
{
|
||||
NSDictionary *attributes;
|
||||
NSString *substring;
|
||||
NSString *runString;
|
||||
|
||||
attributes = [text attributesAtIndex: NSMaxRange(currRange)
|
||||
longestEffectiveRange: &currRange
|
||||
inRange: completeRange];
|
||||
substring = [string substringWithRange: currRange];
|
||||
|
||||
runString = [self runStringForString: substring
|
||||
attributes: attributes
|
||||
paragraphStart: first];
|
||||
[result appendString: runString];
|
||||
first = NO;
|
||||
}
|
||||
|
||||
loc = NSMaxRange(completeRange);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
- (NSString*) RTFDStringFromAttributedString: (NSAttributedString*)aText
|
||||
documentAttributes: (NSDictionary*)dict
|
||||
{
|
||||
NSMutableString *output = [NSMutableString string];
|
||||
NSString *headerString;
|
||||
NSString *trailerString;
|
||||
NSString *bodyString;
|
||||
|
||||
ASSIGN(text, aText);
|
||||
ASSIGN(docDict, dict);
|
||||
|
||||
/*
|
||||
* do not change order! (esp. body has to be generated first; builds context)
|
||||
*/
|
||||
bodyString = [self bodyString];
|
||||
trailerString = [self trailerString];
|
||||
headerString = [self headerString];
|
||||
|
||||
[output appendString: headerString];
|
||||
[output appendString: bodyString];
|
||||
[output appendString: trailerString];
|
||||
return (NSString*)output;
|
||||
}
|
||||
@end
|
1556
TextConverters/RTF/rtfGrammer.tab.c
Normal file
1556
TextConverters/RTF/rtfGrammer.tab.c
Normal file
File diff suppressed because it is too large
Load diff
94
TextConverters/RTF/rtfGrammer.tab.h
Normal file
94
TextConverters/RTF/rtfGrammer.tab.h
Normal file
|
@ -0,0 +1,94 @@
|
|||
typedef union {
|
||||
int number;
|
||||
const char *text;
|
||||
RTFcmd cmd;
|
||||
} YYSTYPE;
|
||||
|
||||
#ifndef YYLTYPE
|
||||
typedef
|
||||
struct yyltype
|
||||
{
|
||||
int timestamp;
|
||||
int first_line;
|
||||
int first_column;
|
||||
int last_line;
|
||||
int last_column;
|
||||
char *text;
|
||||
}
|
||||
yyltype;
|
||||
|
||||
#define YYLTYPE yyltype
|
||||
#endif
|
||||
|
||||
#define RTFtext 258
|
||||
#define RTFstart 259
|
||||
#define RTFansi 260
|
||||
#define RTFmac 261
|
||||
#define RTFpc 262
|
||||
#define RTFpca 263
|
||||
#define RTFignore 264
|
||||
#define RTFinfo 265
|
||||
#define RTFstylesheet 266
|
||||
#define RTFfootnote 267
|
||||
#define RTFheader 268
|
||||
#define RTFfooter 269
|
||||
#define RTFpict 270
|
||||
#define RTFplain 271
|
||||
#define RTFparagraph 272
|
||||
#define RTFdefaultParagraph 273
|
||||
#define RTFrow 274
|
||||
#define RTFcell 275
|
||||
#define RTFtabulator 276
|
||||
#define RTFemdash 277
|
||||
#define RTFendash 278
|
||||
#define RTFemspace 279
|
||||
#define RTFenspace 280
|
||||
#define RTFbullet 281
|
||||
#define RTFlquote 282
|
||||
#define RTFrquote 283
|
||||
#define RTFldblquote 284
|
||||
#define RTFrdblquote 285
|
||||
#define RTFred 286
|
||||
#define RTFgreen 287
|
||||
#define RTFblue 288
|
||||
#define RTFcolorbg 289
|
||||
#define RTFcolorfg 290
|
||||
#define RTFcolortable 291
|
||||
#define RTFfont 292
|
||||
#define RTFfontSize 293
|
||||
#define RTFpaperWidth 294
|
||||
#define RTFpaperHeight 295
|
||||
#define RTFmarginLeft 296
|
||||
#define RTFmarginRight 297
|
||||
#define RTFmarginTop 298
|
||||
#define RTFmarginButtom 299
|
||||
#define RTFfirstLineIndent 300
|
||||
#define RTFleftIndent 301
|
||||
#define RTFrightIndent 302
|
||||
#define RTFalignCenter 303
|
||||
#define RTFalignJustified 304
|
||||
#define RTFalignLeft 305
|
||||
#define RTFalignRight 306
|
||||
#define RTFlineSpace 307
|
||||
#define RTFspaceAbove 308
|
||||
#define RTFstyle 309
|
||||
#define RTFbold 310
|
||||
#define RTFitalic 311
|
||||
#define RTFunderline 312
|
||||
#define RTFunderlineStop 313
|
||||
#define RTFsubscript 314
|
||||
#define RTFsuperscript 315
|
||||
#define RTFtabstop 316
|
||||
#define RTFfcharset 317
|
||||
#define RTFfprq 318
|
||||
#define RTFcpg 319
|
||||
#define RTFOtherStatement 320
|
||||
#define RTFfontListStart 321
|
||||
#define RTFfamilyNil 322
|
||||
#define RTFfamilyRoman 323
|
||||
#define RTFfamilySwiss 324
|
||||
#define RTFfamilyModern 325
|
||||
#define RTFfamilyScript 326
|
||||
#define RTFfamilyDecor 327
|
||||
#define RTFfamilyTech 328
|
||||
|
418
TextConverters/RTF/rtfGrammer.y
Normal file
418
TextConverters/RTF/rtfGrammer.y
Normal file
|
@ -0,0 +1,418 @@
|
|||
/* rtfGrammer.y
|
||||
|
||||
Copyright (C) 1999 Free Software Foundation, Inc.
|
||||
|
||||
Author: Stefan Bðhringer (stefan.boehringer@uni-bochum.de)
|
||||
Date: Dec 1999
|
||||
|
||||
This file is part of the GNUstep GUI Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; see the file COPYING.LIB.
|
||||
If not, write to the Free Software Foundation,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
if processed using -p GSRTFP (as recommended) it will introduce the following global symbols:
|
||||
'GSRTFPparse', `GSRTFPlex', `GSRTFPerror', `GSRTFPnerrs', `GSRTFPlval',
|
||||
`GSRTFPchar', `GSRTFPdebug
|
||||
*/
|
||||
|
||||
/* we request for a reentrant parser */
|
||||
%pure_parser
|
||||
|
||||
%{
|
||||
|
||||
/*
|
||||
The overall plan is to make this grammer universal in usage.
|
||||
Intrested buddies can implement plain C functions to consume what
|
||||
the grammer is producing. this way the rtf-grammer-tree can be
|
||||
converted to what is needed: GNUstep attributed strings, tex files,
|
||||
...
|
||||
|
||||
The plan is laid out by defining a set of C functions which cover
|
||||
all what is needed to mangle rtf information (it is NeXT centric
|
||||
however and may even lack some features). Be aware that some
|
||||
functions are called at specific times when some information may or
|
||||
may not be available. The first argument of all functions is a
|
||||
context, which is asked to be maintained by the consumer at
|
||||
whichever purpose seems appropriate. This context must be passed to
|
||||
the parser by issuing 'value = GSRTFparse(ctxt, lctxt);' in the
|
||||
first place.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "rtfScanner.h"
|
||||
|
||||
/* this context is passed to the interface functions */
|
||||
typedef void * GSRTFctxt;
|
||||
#define YYPARSE_PARAM ctxt, lctxt
|
||||
#define YYLEX_PARAM lctxt
|
||||
#define CTXT ctxt
|
||||
|
||||
#define YYERROR_VERBOSE
|
||||
|
||||
#include "RTFConsumerFunctions.h"
|
||||
|
||||
%}
|
||||
|
||||
%union {
|
||||
int number;
|
||||
const char *text;
|
||||
RTFcmd cmd;
|
||||
}
|
||||
|
||||
/* <!><p> RTFtext values have to be freed */
|
||||
%token <text> RTFtext
|
||||
%token RTFstart
|
||||
%token RTFansi
|
||||
%token RTFmac
|
||||
%token RTFpc
|
||||
%token RTFpca
|
||||
%token RTFignore
|
||||
%token RTFinfo
|
||||
%token RTFstylesheet
|
||||
%token RTFfootnote
|
||||
%token RTFheader
|
||||
%token RTFfooter
|
||||
%token RTFpict
|
||||
%token RTFplain
|
||||
%token RTFparagraph
|
||||
%token RTFdefaultParagraph
|
||||
%token RTFrow
|
||||
%token RTFcell
|
||||
%token RTFtabulator
|
||||
%token RTFemdash
|
||||
%token RTFendash
|
||||
%token RTFemspace
|
||||
%token RTFenspace
|
||||
%token RTFbullet
|
||||
%token RTFlquote
|
||||
%token RTFrquote
|
||||
%token RTFldblquote
|
||||
%token RTFrdblquote
|
||||
%token <cmd> RTFred
|
||||
%token <cmd> RTFgreen
|
||||
%token <cmd> RTFblue
|
||||
%token <cmd> RTFcolorbg
|
||||
%token <cmd> RTFcolorfg
|
||||
%token <cmd> RTFcolortable
|
||||
%token <cmd> RTFfont
|
||||
%token <cmd> RTFfontSize
|
||||
%token <cmd> RTFpaperWidth
|
||||
%token <cmd> RTFpaperHeight
|
||||
%token <cmd> RTFmarginLeft
|
||||
%token <cmd> RTFmarginRight
|
||||
%token <cmd> RTFmarginTop
|
||||
%token <cmd> RTFmarginButtom
|
||||
%token <cmd> RTFfirstLineIndent
|
||||
%token <cmd> RTFleftIndent
|
||||
%token <cmd> RTFrightIndent
|
||||
%token <cmd> RTFalignCenter
|
||||
%token <cmd> RTFalignJustified
|
||||
%token <cmd> RTFalignLeft
|
||||
%token <cmd> RTFalignRight
|
||||
%token <cmd> RTFlineSpace
|
||||
%token <cmd> RTFspaceAbove
|
||||
%token <cmd> RTFstyle
|
||||
%token <cmd> RTFbold
|
||||
%token <cmd> RTFitalic
|
||||
%token <cmd> RTFunderline
|
||||
%token <cmd> RTFunderlineStop
|
||||
%token <cmd> RTFsubscript
|
||||
%token <cmd> RTFsuperscript
|
||||
%token <cmd> RTFtabstop
|
||||
%token <cmd> RTFfcharset
|
||||
%token <cmd> RTFfprq
|
||||
%token <cmd> RTFcpg
|
||||
%token <cmd> RTFOtherStatement
|
||||
%token RTFfontListStart
|
||||
|
||||
// <!> we assume token numbers to be sequential
|
||||
// \fnil | \froman | \fswiss | \fmodern | \fscript | \fdecor | \ftech
|
||||
// look at rtfScanner.h for enum definition
|
||||
%token RTFfamilyNil
|
||||
%token RTFfamilyRoman
|
||||
%token RTFfamilySwiss
|
||||
%token RTFfamilyModern
|
||||
%token RTFfamilyScript
|
||||
%token RTFfamilyDecor
|
||||
%token RTFfamilyTech
|
||||
|
||||
%type <number> rtfFontFamily rtfCharset rtfFontStatement
|
||||
|
||||
/* let's go */
|
||||
|
||||
%%
|
||||
|
||||
rtfFile: '{' { GSRTFstart(CTXT); } RTFstart rtfCharset rtfIngredients { GSRTFstop(CTXT); } '}'
|
||||
;
|
||||
|
||||
rtfCharset: RTFansi { $$ = 1; }
|
||||
| RTFmac { $$ = 2; }
|
||||
| RTFpc { $$ = 3; }
|
||||
| RTFpca { $$ = 4; }
|
||||
;
|
||||
|
||||
rtfIngredients: /* empty */
|
||||
| rtfIngredients rtfFontList
|
||||
| rtfIngredients rtfColorDef
|
||||
| rtfIngredients rtfStatement
|
||||
| rtfIngredients RTFtext { GSRTFmangleText(CTXT, $2); free((void *)$2); }
|
||||
| rtfIngredients rtfBlock
|
||||
;
|
||||
|
||||
rtfBlock: '{' { GSRTFopenBlock(CTXT, NO); } rtfIngredients '}' { GSRTFcloseBlock(CTXT, NO); }
|
||||
| '{' { GSRTFopenBlock(CTXT, YES); } RTFignore rtfIngredients '}' { GSRTFcloseBlock(CTXT, YES); }
|
||||
| '{' { GSRTFopenBlock(CTXT, YES); } RTFinfo rtfIngredients '}' { GSRTFcloseBlock(CTXT, YES); }
|
||||
| '{' { GSRTFopenBlock(CTXT, YES); } RTFstylesheet rtfIngredients '}' { GSRTFcloseBlock(CTXT, YES); }
|
||||
| '{' { GSRTFopenBlock(CTXT, YES); } RTFfootnote rtfIngredients '}' { GSRTFcloseBlock(CTXT, YES); }
|
||||
| '{' { GSRTFopenBlock(CTXT, YES); } RTFheader rtfIngredients '}' { GSRTFcloseBlock(CTXT, YES); }
|
||||
| '{' { GSRTFopenBlock(CTXT, YES); } RTFfooter rtfIngredients '}' { GSRTFcloseBlock(CTXT, YES); }
|
||||
| '{' { GSRTFopenBlock(CTXT, YES); } RTFpict rtfIngredients '}' { GSRTFcloseBlock(CTXT, YES); }
|
||||
| '{' '}' /* empty */
|
||||
;
|
||||
|
||||
|
||||
/*
|
||||
RTF statements start with a '\', have a alpha name and a number argument
|
||||
*/
|
||||
|
||||
rtfStatement: RTFfont { int font;
|
||||
|
||||
if ($1.isEmpty)
|
||||
font = 0;
|
||||
else
|
||||
font = $1.parameter;
|
||||
GSRTFfontNumber(CTXT, font); }
|
||||
| RTFfontSize { int size;
|
||||
|
||||
if ($1.isEmpty)
|
||||
size = 24;
|
||||
else
|
||||
size = $1.parameter;
|
||||
GSRTFfontSize(CTXT, size); }
|
||||
| RTFpaperWidth { int width;
|
||||
|
||||
if ($1.isEmpty)
|
||||
width = 12240;
|
||||
else
|
||||
width = $1.parameter;
|
||||
GSRTFpaperWidth(CTXT, width);}
|
||||
| RTFpaperHeight { int height;
|
||||
|
||||
if ($1.isEmpty)
|
||||
height = 15840;
|
||||
else
|
||||
height = $1.parameter;
|
||||
GSRTFpaperHeight(CTXT, height);}
|
||||
| RTFmarginLeft { int margin;
|
||||
|
||||
if ($1.isEmpty)
|
||||
margin = 1800;
|
||||
else
|
||||
margin = $1.parameter;
|
||||
GSRTFmarginLeft(CTXT, margin);}
|
||||
| RTFmarginRight { int margin;
|
||||
|
||||
if ($1.isEmpty)
|
||||
margin = 1800;
|
||||
else
|
||||
margin = $1.parameter;
|
||||
GSRTFmarginRight(CTXT, margin); }
|
||||
| RTFmarginTop { int margin;
|
||||
|
||||
if ($1.isEmpty)
|
||||
margin = 1440;
|
||||
else
|
||||
margin = $1.parameter;
|
||||
GSRTFmarginTop(CTXT, margin); }
|
||||
| RTFmarginButtom { int margin;
|
||||
|
||||
if ($1.isEmpty)
|
||||
margin = 1440;
|
||||
else
|
||||
margin = $1.parameter;
|
||||
GSRTFmarginButtom(CTXT, margin); }
|
||||
| RTFfirstLineIndent { int indent;
|
||||
|
||||
if ($1.isEmpty)
|
||||
indent = 0;
|
||||
else
|
||||
indent = $1.parameter;
|
||||
GSRTFfirstLineIndent(CTXT, indent); }
|
||||
| RTFleftIndent { int indent;
|
||||
|
||||
if ($1.isEmpty)
|
||||
indent = 0;
|
||||
else
|
||||
indent = $1.parameter;
|
||||
GSRTFleftIndent(CTXT, indent);}
|
||||
| RTFrightIndent { int indent;
|
||||
|
||||
if ($1.isEmpty)
|
||||
indent = 0;
|
||||
else
|
||||
indent = $1.parameter;
|
||||
GSRTFrightIndent(CTXT, indent);}
|
||||
| RTFtabstop { int location;
|
||||
|
||||
if ($1.isEmpty)
|
||||
location = 0;
|
||||
else
|
||||
location = $1.parameter;
|
||||
GSRTFtabstop(CTXT, location);}
|
||||
| RTFalignCenter { GSRTFalignCenter(CTXT); }
|
||||
| RTFalignJustified { GSRTFalignJustified(CTXT); }
|
||||
| RTFalignLeft { GSRTFalignLeft(CTXT); }
|
||||
| RTFalignRight { GSRTFalignRight(CTXT); }
|
||||
| RTFspaceAbove { int space;
|
||||
|
||||
if ($1.isEmpty)
|
||||
space = 0;
|
||||
else
|
||||
space = $1.parameter;
|
||||
GSRTFspaceAbove(CTXT, space); }
|
||||
| RTFlineSpace { GSRTFlineSpace(CTXT, $1.parameter); }
|
||||
| RTFdefaultParagraph { GSRTFdefaultParagraph(CTXT); }
|
||||
| RTFstyle { GSRTFstyle(CTXT, $1.parameter); }
|
||||
| RTFcolorbg { int color;
|
||||
|
||||
if ($1.isEmpty)
|
||||
color = 0;
|
||||
else
|
||||
color = $1.parameter;
|
||||
GSRTFcolorbg(CTXT, color); }
|
||||
| RTFcolorfg { int color;
|
||||
|
||||
if ($1.isEmpty)
|
||||
color = 0;
|
||||
else
|
||||
color = $1.parameter;
|
||||
GSRTFcolorfg(CTXT, color); }
|
||||
| RTFsubscript { int script;
|
||||
|
||||
if ($1.isEmpty)
|
||||
script = 6;
|
||||
else
|
||||
script = $1.parameter;
|
||||
GSRTFsubscript(CTXT, script); }
|
||||
| RTFsuperscript { int script;
|
||||
|
||||
if ($1.isEmpty)
|
||||
script = 6;
|
||||
else
|
||||
script = $1.parameter;
|
||||
GSRTFsuperscript(CTXT, script); }
|
||||
| RTFbold { BOOL on;
|
||||
|
||||
if ($1.isEmpty || $1.parameter)
|
||||
on = YES;
|
||||
else
|
||||
on = NO;
|
||||
GSRTFbold(CTXT, on); }
|
||||
| RTFitalic { BOOL on;
|
||||
|
||||
if ($1.isEmpty || $1.parameter)
|
||||
on = YES;
|
||||
else
|
||||
on = NO;
|
||||
GSRTFitalic(CTXT, on); }
|
||||
| RTFunderline { BOOL on;
|
||||
|
||||
if ($1.isEmpty || $1.parameter)
|
||||
on = YES;
|
||||
else
|
||||
on = NO;
|
||||
GSRTFunderline(CTXT, on); }
|
||||
| RTFunderlineStop { GSRTFunderline(CTXT, NO); }
|
||||
| RTFplain { GSRTFdefaultCharacterStyle(CTXT); }
|
||||
| RTFparagraph { GSRTFparagraph(CTXT); }
|
||||
| RTFrow { GSRTFparagraph(CTXT); }
|
||||
| RTFOtherStatement { GSRTFgenericRTFcommand(CTXT, $1); }
|
||||
;
|
||||
|
||||
/*
|
||||
Font description
|
||||
*/
|
||||
|
||||
rtfFontList: '{' RTFfontListStart rtfFonts '}'
|
||||
;
|
||||
|
||||
rtfFonts:
|
||||
| rtfFonts rtfFontStatement
|
||||
| rtfFonts '{' rtfFontStatement '}'
|
||||
|
||||
;
|
||||
|
||||
/* the first RTFfont tags the font with a number */
|
||||
/* RTFtext introduces the fontName */
|
||||
rtfFontStatement: RTFfont rtfFontFamily rtfFontAttrs RTFtext { GSRTFregisterFont(CTXT, $4, $2, $1.parameter);
|
||||
free((void *)$4); }
|
||||
;
|
||||
|
||||
rtfFontAttrs: /* empty */
|
||||
| rtfFontAttrs RTFfcharset
|
||||
| rtfFontAttrs RTFfprq
|
||||
| rtfFontAttrs RTFcpg
|
||||
| rtfFontAttrs rtfBlock
|
||||
;
|
||||
|
||||
|
||||
rtfFontFamily:
|
||||
RTFfamilyNil { $$ = RTFfamilyNil - RTFfamilyNil; }
|
||||
| RTFfamilyRoman { $$ = RTFfamilyRoman - RTFfamilyNil; }
|
||||
| RTFfamilySwiss { $$ = RTFfamilySwiss - RTFfamilyNil; }
|
||||
| RTFfamilyModern { $$ = RTFfamilyModern - RTFfamilyNil; }
|
||||
| RTFfamilyScript { $$ = RTFfamilyScript - RTFfamilyNil; }
|
||||
| RTFfamilyDecor { $$ = RTFfamilyDecor - RTFfamilyNil; }
|
||||
| RTFfamilyTech { $$ = RTFfamilyTech - RTFfamilyNil; }
|
||||
;
|
||||
|
||||
|
||||
/*
|
||||
Colour definition
|
||||
*/
|
||||
|
||||
rtfColorDef: '{' RTFcolortable rtfColors '}'
|
||||
;
|
||||
|
||||
rtfColors: /* empty */
|
||||
| rtfColors rtfColorStatement
|
||||
;
|
||||
|
||||
/* We get the ';' as RTFText */
|
||||
rtfColorStatement: RTFred RTFgreen RTFblue RTFtext
|
||||
{
|
||||
GSRTFaddColor(CTXT, $1.parameter, $2.parameter, $3.parameter);
|
||||
free((void *)$4);
|
||||
}
|
||||
| RTFtext
|
||||
{
|
||||
GSRTFaddDefaultColor(CTXT);
|
||||
free((void *)$1);
|
||||
}
|
||||
;
|
||||
|
||||
/*
|
||||
some cludgy trailer
|
||||
*/
|
||||
dummyNonTerminal: '\\' { @1.first_line; } /* we introduce a @n to fix the lex attributes */
|
||||
;
|
||||
|
||||
%%
|
||||
|
||||
/* some C code here */
|
||||
|
445
TextConverters/RTF/rtfScanner.c
Normal file
445
TextConverters/RTF/rtfScanner.c
Normal file
|
@ -0,0 +1,445 @@
|
|||
/* rtcScanner
|
||||
|
||||
Copyright (C) 1999 Free Software Foundation, Inc.
|
||||
|
||||
Author: Stefan Bðhringer (stefan.boehringer@uni-bochum.de)
|
||||
Date: Dec 1999
|
||||
|
||||
This file is part of the GNUstep GUI Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; see the file COPYING.LIB.
|
||||
If not, write to the Free Software Foundation,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include "rtfScanner.h"
|
||||
#include "rtfGrammer.tab.h"
|
||||
|
||||
// <§> scanner types and helpers
|
||||
|
||||
#define CArraySize(a) (sizeof(a)/sizeof((a)[0])-1)
|
||||
|
||||
typedef struct {
|
||||
char *bf;
|
||||
int length, position, chunkSize;
|
||||
} DynamicString;
|
||||
typedef struct {
|
||||
const char *string;
|
||||
int token;
|
||||
} LexKeyword;
|
||||
|
||||
GSLexError initDynamicString(DynamicString *string)
|
||||
{
|
||||
string->length = 0, string->position = 0, string->chunkSize = 128;
|
||||
string->bf = calloc(1, string->length = string->chunkSize);
|
||||
if (!string->bf)
|
||||
return LEXoutOfMemory;
|
||||
return NoError;
|
||||
}
|
||||
|
||||
GSLexError appendChar(DynamicString *string, int c)
|
||||
{
|
||||
if (string->position == string->length)
|
||||
{
|
||||
if (!(string->bf = realloc(string->bf,
|
||||
string->length += string->chunkSize)))
|
||||
return LEXoutOfMemory;
|
||||
else
|
||||
string->chunkSize <<= 1;
|
||||
}
|
||||
|
||||
string->bf[string->position++] = c;
|
||||
return NoError;
|
||||
}
|
||||
|
||||
void lexInitContext(RTFscannerCtxt *lctxt, void *customContext,
|
||||
int (*getcharFunction)(void *))
|
||||
{
|
||||
lctxt->streamLineNumber = 1;
|
||||
lctxt->streamPosition = lctxt->pushbackCount = 0;
|
||||
lctxt->lgetchar = getcharFunction;
|
||||
lctxt->customContext = customContext;
|
||||
}
|
||||
|
||||
int lexGetchar(RTFscannerCtxt *lctxt)
|
||||
{
|
||||
int c;
|
||||
if (lctxt->pushbackCount)
|
||||
{
|
||||
lctxt->pushbackCount--;
|
||||
c = lctxt->pushbackBuffer[lctxt->pushbackCount];
|
||||
}
|
||||
else
|
||||
{
|
||||
lctxt->streamPosition++;
|
||||
c = lctxt->lgetchar(lctxt->customContext);
|
||||
}
|
||||
if (c == '\n')
|
||||
lctxt->streamLineNumber++;
|
||||
return c;
|
||||
}
|
||||
|
||||
void lexUngetchar(RTFscannerCtxt *lctxt, int c)
|
||||
{
|
||||
if (c == '\n')
|
||||
lctxt->streamLineNumber--;
|
||||
lctxt->pushbackBuffer[lctxt->pushbackCount++] = c; //<!> no checking here
|
||||
}
|
||||
|
||||
int lexStreamPosition(RTFscannerCtxt *lctxt)
|
||||
{
|
||||
return lctxt->streamPosition - lctxt->pushbackCount;
|
||||
}
|
||||
|
||||
char *my_strdup(const char *str)
|
||||
{
|
||||
char *copy = str? malloc(strlen(str) + 1): 0;
|
||||
return !copy? 0: strcpy(copy, str);
|
||||
}
|
||||
|
||||
int findStringFromKeywordArray(const char *string, const LexKeyword *array,
|
||||
int arrayCount)
|
||||
{
|
||||
int min, max, mid, cmp;
|
||||
const LexKeyword *currentKeyword;
|
||||
|
||||
for (min=0, max=arrayCount; min<=max; )
|
||||
{
|
||||
mid = (min+max)>>1;
|
||||
currentKeyword = array + mid;
|
||||
if (!(cmp = strcmp(string, currentKeyword->string)))
|
||||
{
|
||||
return currentKeyword->token;
|
||||
}
|
||||
else if (cmp>0)
|
||||
min=mid+1;
|
||||
else
|
||||
max=mid-1;
|
||||
}
|
||||
return 0; // couldn't find
|
||||
}
|
||||
|
||||
// end <§> scanner types and helpers
|
||||
|
||||
// <§> core scanner functions
|
||||
|
||||
#define token(a) (a)
|
||||
|
||||
// <!> must be sorted
|
||||
LexKeyword RTFcommands[]={
|
||||
"ansi", token(RTFansi),
|
||||
"b", token(RTFbold),
|
||||
"blue", token(RTFblue),
|
||||
"bullet", token(RTFbullet),
|
||||
"cb", token(RTFcolorbg),
|
||||
"cell", token(RTFcell),
|
||||
"cf", token(RTFcolorfg),
|
||||
"colortbl", token(RTFcolortable),
|
||||
"cpg", token(RTFcpg),
|
||||
"dn", token(RTFsubscript),
|
||||
"emdash", token(RTFemdash),
|
||||
"emspace", token(RTFemspace),
|
||||
"endash", token(RTFendash),
|
||||
"enspace", token(RTFenspace),
|
||||
"f", token(RTFfont),
|
||||
"fcharset", token(RTFfcharset),
|
||||
"fdecor", token(RTFfamilyDecor),
|
||||
"fi", token(RTFfirstLineIndent),
|
||||
"fmodern", token(RTFfamilyModern),
|
||||
"fnil", token(RTFfamilyNil),
|
||||
"fonttbl", token(RTFfontListStart),
|
||||
/* All footers are mapped on one entry */
|
||||
"footer", token(RTFfooter),
|
||||
"footerf", token(RTFfooter),
|
||||
"footerl", token(RTFfooter),
|
||||
"footerr", token(RTFfooter),
|
||||
"footnote", token(RTFfootnote),
|
||||
"fprq", token(RTFfprq),
|
||||
"froman", token(RTFfamilyRoman),
|
||||
"fs", token(RTFfontSize),
|
||||
"fscript", token(RTFfamilyScript),
|
||||
"fswiss", token(RTFfamilySwiss),
|
||||
"ftech", token(RTFfamilyTech),
|
||||
"green", token(RTFgreen),
|
||||
/* All headers are mapped on one entry */
|
||||
"header", token(RTFheader),
|
||||
"headerf", token(RTFheader),
|
||||
"headerl", token(RTFheader),
|
||||
"headerr", token(RTFheader),
|
||||
"i", token(RTFitalic),
|
||||
"info", token(RTFinfo),
|
||||
"ldblquote", token(RTFldblquote),
|
||||
"li", token(RTFleftIndent),
|
||||
"lquote", token(RTFlquote),
|
||||
"mac", token(RTFmac),
|
||||
"margb", token(RTFmarginButtom),
|
||||
"margl", token(RTFmarginLeft),
|
||||
"margr", token(RTFmarginRight),
|
||||
"margt", token(RTFmarginTop),
|
||||
"paperh", token(RTFpaperHeight),
|
||||
"paperw", token(RTFpaperWidth),
|
||||
"par", token(RTFparagraph),
|
||||
"pard", token(RTFdefaultParagraph),
|
||||
"pc", token(RTFpc),
|
||||
"pca", token(RTFpca),
|
||||
"pict", token(RTFpict),
|
||||
"plain", token(RTFplain),
|
||||
"qc", token(RTFalignCenter),
|
||||
"qj", token(RTFalignJustified),
|
||||
"ql", token(RTFalignLeft),
|
||||
"qr", token(RTFalignRight),
|
||||
"rdblquote", token(RTFrdblquote),
|
||||
"red", token(RTFred),
|
||||
"ri", token(RTFrightIndent),
|
||||
"row", token(RTFrow),
|
||||
"rquote", token(RTFrquote),
|
||||
"rtf", token(RTFstart),
|
||||
"s", token(RTFstyle),
|
||||
"sa", token(RTFspaceAbove),
|
||||
"sl", token(RTFlineSpace),
|
||||
"stylesheet", token(RTFstylesheet),
|
||||
"tab", token(RTFtabulator),
|
||||
"tx", token(RTFtabstop),
|
||||
/* All underline are mapped on one entry */
|
||||
"ul", token(RTFunderline),
|
||||
"uld", token(RTFunderline),
|
||||
"uldb", token(RTFunderline),
|
||||
"ulnone", token(RTFunderlineStop),
|
||||
"ulw", token(RTFunderline),
|
||||
"up", token(RTFsuperscript)
|
||||
};
|
||||
|
||||
BOOL probeCommand(RTFscannerCtxt *lctxt)
|
||||
{
|
||||
int c = lexGetchar(lctxt);
|
||||
lexUngetchar(lctxt, c);
|
||||
if (isalpha(c))
|
||||
return YES;
|
||||
return NO;
|
||||
}
|
||||
|
||||
// <N> According to spec a cmdLength of 32 is respected
|
||||
#define RTFMaxCmdLength 32
|
||||
#define RTFMaxArgumentLength 64
|
||||
GSLexError readCommand(RTFscannerCtxt *lctxt, YYSTYPE *lvalp, int *token) // the '\\' is already read
|
||||
{
|
||||
char cmdNameBf[RTFMaxCmdLength+1], *cmdName = cmdNameBf;
|
||||
char argumentBf[RTFMaxArgumentLength+1], *argument = argumentBf;
|
||||
int c, foundToken;
|
||||
|
||||
lvalp->cmd.name = 0; // initialize
|
||||
while (isalpha( c = lexGetchar(lctxt) ))
|
||||
{
|
||||
*cmdName++ = c;
|
||||
if (cmdName >= cmdNameBf + RTFMaxCmdLength)
|
||||
return LEXsyntaxError;
|
||||
}
|
||||
*cmdName = 0;
|
||||
if (!(foundToken = findStringFromKeywordArray(cmdNameBf, RTFcommands,
|
||||
CArraySize(RTFcommands))))
|
||||
{
|
||||
if (!(lvalp->cmd.name = my_strdup(cmdNameBf)))
|
||||
return LEXoutOfMemory;
|
||||
*token = RTFOtherStatement;
|
||||
}
|
||||
else
|
||||
{
|
||||
*token = foundToken;
|
||||
}
|
||||
if (c == ' ') // this is an empty argument
|
||||
{
|
||||
lvalp->cmd.isEmpty = YES;
|
||||
}
|
||||
else if (isdigit(c) || c == '-') // we've found a numerical argument
|
||||
{
|
||||
do
|
||||
{
|
||||
*argument++ = c;
|
||||
if (argument >= argumentBf + RTFMaxArgumentLength)
|
||||
return LEXsyntaxError;
|
||||
} while (isdigit(c = lexGetchar(lctxt)));
|
||||
*argument = 0;
|
||||
if (c != ' ')
|
||||
lexUngetchar(lctxt, c); // <N> ungetc non-digit
|
||||
// the consumption of the space seems necessary on NeXT but
|
||||
// is not according to spec
|
||||
lvalp->cmd.isEmpty = NO;
|
||||
lvalp->cmd.parameter = atoi(argumentBf);
|
||||
}
|
||||
else
|
||||
{
|
||||
lvalp->cmd.isEmpty = YES;
|
||||
lexUngetchar(lctxt, c); // ungetc non-whitespace delimiter
|
||||
}
|
||||
return NoError;
|
||||
}
|
||||
|
||||
GSLexError readText(RTFscannerCtxt *lctxt, YYSTYPE *lvalp)
|
||||
{
|
||||
int c;
|
||||
DynamicString text;
|
||||
GSLexError error;
|
||||
|
||||
if ((error = initDynamicString(&text)))
|
||||
return error;
|
||||
for (;;)
|
||||
{
|
||||
c = lexGetchar(lctxt);
|
||||
|
||||
if (c == EOF || c == '{' || c == '}' || c == '\\')
|
||||
{
|
||||
lexUngetchar(lctxt, c);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (c != '\n' && c != '\r') // <N> newline and cr are ignored if not quoted
|
||||
appendChar(&text, c);
|
||||
}
|
||||
}
|
||||
appendChar(&text, 0);
|
||||
lvalp->text = text.bf; // release is up to the consumer
|
||||
return NoError;
|
||||
}
|
||||
|
||||
// read in a character as two hex digit
|
||||
static int gethex(RTFscannerCtxt *lctxt)
|
||||
{
|
||||
int c = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
int c1 = lexGetchar(lctxt);
|
||||
|
||||
if (!isxdigit(c1))
|
||||
{
|
||||
lexUngetchar(lctxt, c1);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = c * 16;
|
||||
if (isdigit(c1))
|
||||
c += c1 - '0';
|
||||
else if (isupper(c1))
|
||||
c += c1 - 'A' + 10;
|
||||
else
|
||||
c += c1 - 'a' + 10;
|
||||
}
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
int GSRTFlex(YYSTYPE *lvalp, YYLTYPE *llocp, RTFscannerCtxt *lctxt) /* provide value and position in the params */
|
||||
{
|
||||
int c;
|
||||
int token = 0;
|
||||
char *cv;
|
||||
|
||||
do
|
||||
c = lexGetchar(lctxt);
|
||||
while ( c == '\n' || c == '\r' ); // <A> the listed characters are to be ignored
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case EOF: token = 0;
|
||||
break;
|
||||
case '{': token = '{';
|
||||
break;
|
||||
case '}': token = '}';
|
||||
break;
|
||||
case '\\':
|
||||
if (probeCommand(lctxt) == YES)
|
||||
{
|
||||
readCommand(lctxt, lvalp, &token);
|
||||
switch (token)
|
||||
{
|
||||
case RTFtabulator: c = '\t';
|
||||
break;
|
||||
case RTFcell: c = '\t';
|
||||
break;
|
||||
case RTFemdash: c = '-';
|
||||
break;
|
||||
case RTFendash: c = '-';
|
||||
break;
|
||||
case RTFbullet: c = '*';
|
||||
break;
|
||||
case RTFlquote: c = '`';
|
||||
break;
|
||||
case RTFrquote: c = '\'';
|
||||
break;
|
||||
case RTFldblquote: c = '"';
|
||||
break;
|
||||
case RTFrdblquote: c = '"';
|
||||
break;
|
||||
default:
|
||||
return token;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
c = lexGetchar(lctxt);
|
||||
switch (c)
|
||||
{
|
||||
case EOF: token = 0;
|
||||
return token;
|
||||
case '\'':
|
||||
// Convert the next two hex digits into a char
|
||||
c = gethex(lctxt);
|
||||
break;
|
||||
case '*': return RTFignore;
|
||||
case '|':
|
||||
case '-':
|
||||
case ':':
|
||||
// Ignore these characters
|
||||
c = lexGetchar(lctxt);
|
||||
break;
|
||||
case '_': c = '-';
|
||||
break;
|
||||
case '~': c = ' ';
|
||||
break;
|
||||
case '\n':
|
||||
case '\r':
|
||||
return RTFparagraph;
|
||||
case '{':
|
||||
case '}':
|
||||
case '\\':
|
||||
// release is up to the consumer
|
||||
cv = calloc(1, 2);
|
||||
cv[0] = c;
|
||||
cv[1] = '\0';
|
||||
lvalp->text = cv;
|
||||
token = RTFtext;
|
||||
return token;
|
||||
default:
|
||||
// fall through
|
||||
}
|
||||
}
|
||||
// else fall through to default: read text <A>
|
||||
// no break <A>
|
||||
default:
|
||||
lexUngetchar(lctxt, c);
|
||||
readText(lctxt, lvalp);
|
||||
token = RTFtext;
|
||||
break;
|
||||
}
|
||||
|
||||
//*llocp = lctxt->position();
|
||||
return token;
|
||||
}
|
68
TextConverters/RTF/rtfScanner.h
Normal file
68
TextConverters/RTF/rtfScanner.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
/* rtcScanner.h
|
||||
|
||||
Copyright (C) 1999 Free Software Foundation, Inc.
|
||||
|
||||
Author: Stefan Bðhringer (stefan.boehringer@uni-bochum.de)
|
||||
Date: Dec 1999
|
||||
|
||||
This file is part of the GNUstep GUI Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; see the file COPYING.LIB.
|
||||
If not, write to the Free Software Foundation,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef rtfScanner_h_INCLUDE
|
||||
#define rtfScanner_h_INCLUDE
|
||||
|
||||
#include <objc/objc.h>
|
||||
|
||||
#if !defined(YES)
|
||||
typedef char BOOL;
|
||||
enum { NO, YES };
|
||||
#endif
|
||||
|
||||
typedef enum { NoError, LEXoutOfMemory, LEXsyntaxError } GSLexError;
|
||||
|
||||
typedef struct _RTFscannerCtxt {
|
||||
int (*lgetchar)(void *);
|
||||
char pushbackBuffer[4]; // gaurantee 4 chars of pushback
|
||||
int pushbackCount;
|
||||
int streamPosition;
|
||||
int streamLineNumber;
|
||||
void *customContext;
|
||||
} RTFscannerCtxt;
|
||||
|
||||
typedef struct {
|
||||
BOOL isEmpty;
|
||||
int parameter;
|
||||
int token;
|
||||
const char *name;
|
||||
} RTFcmd;
|
||||
|
||||
typedef enum {
|
||||
GSRTFfamilyNil, GSRTFfamilyRoman, GSRTFfamilySwiss,
|
||||
GSRTFfamilyModern, GSRTFfamilyScript, GSRTFfamilyDecor,
|
||||
GSRTFfamilyTech
|
||||
} RTFfontFamily;
|
||||
|
||||
|
||||
void lexInitContext(RTFscannerCtxt *lctxt, void *customContext, int (*getcharFunction)());
|
||||
|
||||
/* external symbols from the grammer */
|
||||
/*int GSRTFparse(void *ctxt, RTFscannerCtxt *lctxt);*/
|
||||
int GSRTFparse(void *ctxt, void *lctxt);
|
||||
|
||||
#endif
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue