diff --git a/.mtn-ignore b/.mtn-ignore index 9f016fef4..3a0bd502c 100644 --- a/.mtn-ignore +++ b/.mtn-ignore @@ -4,9 +4,7 @@ obj err$ build\.log imgs-.* -diff .*\.bak$ -.*\.diff$ .*\.d$ .*\.log$ .*\.ifb$ diff --git a/ChangeLog b/ChangeLog index e00378f4f..9d97a55a7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2011-11-17 Wolfgang Sourdeau + + * OpenChange/MAPIStoreSamDBUtils.m: new module containing helpers + pertaining to the SamDB. + (MAPIStoreSamDBUserAttribute): new function that returns the value + of a specified key from a user record matching one simple criteria. + (MAPIStoreInternalEntrydId, MAPIStoreExternalEntryId): moved + functions from MAPIStoreMessage.m. + + * OpenChange/MAPIStoreMessage.m (MAPIStoreInternalEntryId): now + takes a ldb_context * parameter pointing to the samdb, which + enables us: 1) to return the real legacyExchangeDN 2) to make use + of sAMAccountName as search parameter for the username. + +2011-11-16 Ludovic Marcotte + + * SoObjects/SOGo/SOGoSieveManager.m (-updateFiltersForLogin:...) + We now handle connection exceptions to avoid crashing sogod. + 2011-11-13 Wolfgang Sourdeau * OpenChange/MAPIStoreContactsMessage.m (-getPrBody:inMemCtx:): diff --git a/OpenChange/GNUmakefile b/OpenChange/GNUmakefile index c3ecc8805..cd4aca1d6 100644 --- a/OpenChange/GNUmakefile +++ b/OpenChange/GNUmakefile @@ -7,6 +7,8 @@ include ../Version BACKEND_VERSION = 1.0.0 +UNRTF_VERSION = 0.21.2 + ### bootstrap library MAPISTORESOGO = MAPIStoreSOGo LIBRARY_NAME = $(MAPISTORESOGO) @@ -23,6 +25,12 @@ BUNDLE_NAME = $(SOGOBACKEND) BUNDLE_EXTENSION = .MAPIStore BUNDLE_INSTALL_DIR = $(SOGO_LIBDIR) +UNRTF_DIR = unrtf-$(UNRTF_VERSION) + +$(SOGOBACKEND)_CPPFLAGS += -I$(UNRTF_DIR)/src + +$(SOGOBACKEND)_SUBPROJECTS = $(UNRTF_DIR)/src + $(SOGOBACKEND)_PRINCIPAL_CLASS = MAPIApplication $(SOGOBACKEND)_OBJC_FILES += \ @@ -120,7 +128,28 @@ $(SOGOBACKEND)_OBJC_FILES += \ $(SOGOBACKEND)_RESOURCE_FILES += \ - product.plist + product.plist \ + $(UNRTF_DIR)/charmaps/SYMBOL.charmap \ + $(UNRTF_DIR)/outputs/html.conf + +### unrtf +all:: $(UNRTF_DIR)/config.h $(UNRTF_DIR)/src/GNUmakefile + +$(UNRTF_DIR): $(UNRTF_DIR).tar.gz $(UNRTF_DIR).diff + @echo " Extracting and patching $(UNRTF_DIR)..." + @rm -rf $(UNRTF_DIR) + @$(TAR) -xvzf $< > /dev/null + @(cd $(UNRTF_DIR) && patch -p1 < ../$(UNRTF_DIR).diff) > /dev/null + @touch $(UNRTF_DIR) + +$(UNRTF_DIR)-stamp: $(UNRTF_DIR) + @touch $@ + +$(UNRTF_DIR)/config.h: $(UNRTF_DIR)-stamp unrtf_config_h + @cp unrtf_config_h $(UNRTF_DIR)/config.h + +$(UNRTF_DIR)/src/GNUmakefile: $(UNRTF_DIR)-stamp GNUmakefile.unrtf + @cp GNUmakefile.unrtf $@ ### pl reader PLREADER_TOOL = plreader @@ -133,7 +162,7 @@ TEST_TOOL_NAME += $(PLREADER_TOOL) LIBMAPI_CFLAGS = $(shell pkg-config libmapi --cflags) LIBMAPISTORE_CFLAGS = $(shell pkg-config libmapistore --cflags) -DSAMBA_PREFIX="\"$(shell pkg-config libmapistore --variable=prefix)\"" -ifeq ($(LIBMAPISTORE_CFLAGS),) +ifeq ($(LIBMAPI_CFLAGS),) all install:: @echo "Cannot build the OpenChange SOGo backend (empty CFLAGS for libmapistore)" else @@ -160,6 +189,7 @@ SAMBA_LIB_DIR = $(shell pkg-config libmapistore --variable=libdir) include $(GNUSTEP_MAKEFILES)/bundle.make include $(GNUSTEP_MAKEFILES)/library.make include $(GNUSTEP_MAKEFILES)/test-tool.make +include $(GNUSTEP_MAKEFILES)/aggregate.make -include GNUmakefile.postamble endif diff --git a/OpenChange/GNUmakefile.unrtf b/OpenChange/GNUmakefile.unrtf new file mode 100644 index 000000000..eaac4764a --- /dev/null +++ b/OpenChange/GNUmakefile.unrtf @@ -0,0 +1,34 @@ +# -*-makefile-*- + +# GNUstep makefile + +include $(GNUSTEP_MAKEFILES)/common.make + +UNRTF = unrtf + +SUBPROJECT_NAME = $(UNRTF) + +$(UNRTF)_C_FILES = \ + attr.c \ + convert.c \ + error.c \ + hash.c \ + malloc.c \ + my_iconv.c \ + output.c \ + parse.c \ + unicode.c \ + user.c \ + util.c \ + word.c + +$(UNRTF)_CFLAGS = -DHAVE_CONFIG_H=1 -I. -I../ + +# Option include to set any additional variables +-include GNUmakefile.preamble + +# Include in the rules for making libraries +include $(GNUSTEP_MAKEFILES)/subproject.make + +# Option include to define any additional rules +-include GNUmakefile.postamble diff --git a/OpenChange/MAPIStoreAppointmentWrapper.h b/OpenChange/MAPIStoreAppointmentWrapper.h index 7f14c5401..fa1cb8f20 100644 --- a/OpenChange/MAPIStoreAppointmentWrapper.h +++ b/OpenChange/MAPIStoreAppointmentWrapper.h @@ -39,6 +39,7 @@ extern NSTimeZone *utcTZ; @interface MAPIStoreAppointmentWrapper : NSObject { + struct mapistore_connection_info *connInfo; iCalCalendar *calendar; iCalEvent *event; NSTimeZone *timeZone; @@ -56,11 +57,13 @@ extern NSTimeZone *utcTZ; + (id) wrapperWithICalEvent: (iCalEvent *) newEvent andUser: (SOGoUser *) newUser andSenderEmail: (NSString *) newSenderEmail - inTimeZone: (NSTimeZone *) newTimeZone; + inTimeZone: (NSTimeZone *) newTimeZone + withConnectionInfo: (struct mapistore_connection_info *) newConnInfo; - (id) initWithICalEvent: (iCalEvent *) newEvent andUser: (SOGoUser *) newUser andSenderEmail: (NSString *) newSenderEmail - inTimeZone: (NSTimeZone *) newTimeZone; + inTimeZone: (NSTimeZone *) newTimeZone + withConnectionInfo: (struct mapistore_connection_info *) newConnInfo; /* getters */ - (void) fillMessageData: (struct mapistore_message *) dataPtr @@ -92,8 +95,6 @@ extern NSTimeZone *utcTZ; inMemCtx: (TALLOC_CTX *) memCtx; - (int) getPrMessageClass: (void **) data inMemCtx: (TALLOC_CTX *) memCtx; -- (int) getPrBody: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx; - (int) getPrStartDate: (void **) data inMemCtx: (TALLOC_CTX *) memCtx; - (int) getPidLidAppointmentStateFlags: (void **) data @@ -129,6 +130,8 @@ extern NSTimeZone *utcTZ; inMemCtx: (TALLOC_CTX *) memCtx; - (int) getPrImportance: (void **) data inMemCtx: (TALLOC_CTX *) memCtx; +- (int) getPrBody: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx; - (int) getPidLidIsRecurring: (void **) data inMemCtx: (TALLOC_CTX *) memCtx; - (int) getPidLidRecurring: (void **) data diff --git a/OpenChange/MAPIStoreAppointmentWrapper.m b/OpenChange/MAPIStoreAppointmentWrapper.m index cbd62fca8..c1f0e8b90 100644 --- a/OpenChange/MAPIStoreAppointmentWrapper.m +++ b/OpenChange/MAPIStoreAppointmentWrapper.m @@ -37,8 +37,8 @@ #import #import -#import "MAPIStoreMessage.h" #import "MAPIStoreRecurrenceUtils.h" +#import "MAPIStoreSamDBUtils.h" #import "MAPIStoreTypes.h" #import "NSData+MAPIStore.h" #import "NSDate+MAPIStore.h" @@ -53,6 +53,7 @@ #include #include #include +#include #include #include #include @@ -79,13 +80,15 @@ static NSCharacterSet *hexCharacterSet = nil; andUser: (SOGoUser *) newUser andSenderEmail: (NSString *) newSenderEmail inTimeZone: (NSTimeZone *) newTimeZone + withConnectionInfo: (struct mapistore_connection_info *) newConnInfo { MAPIStoreAppointmentWrapper *wrapper; wrapper = [[self alloc] initWithICalEvent: newEvent andUser: newUser andSenderEmail: newSenderEmail - inTimeZone: newTimeZone]; + inTimeZone: newTimeZone + withConnectionInfo: newConnInfo]; [wrapper autorelease]; return wrapper; @@ -95,6 +98,7 @@ static NSCharacterSet *hexCharacterSet = nil; { if ((self = [super init])) { + connInfo = NULL; calendar = nil; event = nil; timeZone = nil; @@ -177,9 +181,11 @@ static NSCharacterSet *hexCharacterSet = nil; andUser: (SOGoUser *) newUser andSenderEmail: (NSString *) newSenderEmail inTimeZone: (NSTimeZone *) newTimeZone + withConnectionInfo: (struct mapistore_connection_info *) newConnInfo { if ((self = [self init])) { + connInfo = newConnInfo; ASSIGN (event, newEvent); ASSIGN (calendar, [event parent]); ASSIGN (timeZone, newTimeZone); @@ -255,7 +261,7 @@ static NSCharacterSet *hexCharacterSet = nil; { username = [contactInfos objectForKey: @"c_uid"]; recipient->username = [username asUnicodeInMemCtx: msgData]; - entryId = MAPIStoreInternalEntryId (username); + entryId = MAPIStoreInternalEntryId (connInfo->sam_ctx, username); } else { @@ -356,7 +362,7 @@ static NSCharacterSet *hexCharacterSet = nil; { username = [contactInfos objectForKey: @"c_uid"]; recipient->username = [username asUnicodeInMemCtx: msgData]; - entryId = MAPIStoreInternalEntryId (username); + entryId = MAPIStoreInternalEntryId (connInfo->sam_ctx, username); } else { @@ -628,20 +634,6 @@ static NSCharacterSet *hexCharacterSet = nil; return [self getYes: data inMemCtx: memCtx]; } -- (int) getPrBody: (void **) data - inMemCtx: (TALLOC_CTX *) memCtx -{ - NSString *stringValue; - - stringValue = [event comment]; - if (!stringValue) - stringValue = @""; - - *data = [stringValue asUnicodeInMemCtx: memCtx]; - - return MAPISTORE_SUCCESS; -} - - (int) getPrStartDate: (void **) data inMemCtx: (TALLOC_CTX *) memCtx { @@ -740,7 +732,7 @@ static NSCharacterSet *hexCharacterSet = nil; if (contactInfos) { username = [contactInfos objectForKey: @"c_uid"]; - entryId = MAPIStoreInternalEntryId (username); + entryId = MAPIStoreInternalEntryId (connInfo->sam_ctx, username); } else entryId = MAPIStoreExternalEntryId (cn, email); @@ -1034,6 +1026,22 @@ static NSCharacterSet *hexCharacterSet = nil; return MAPISTORE_SUCCESS; } +- (int) getPrBody: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + int rc = MAPISTORE_SUCCESS; + NSString *stringValue; + + /* FIXME: there is a confusion in NGCards around "comment" and "description" */ + stringValue = [event comment]; + if ([stringValue length] > 0) + *data = [stringValue asUnicodeInMemCtx: memCtx]; + else + rc = MAPISTORE_ERR_NOT_FOUND; + + return rc; +} + - (int) getPidLidIsRecurring: (void **) data inMemCtx: (TALLOC_CTX *) memCtx { @@ -1402,7 +1410,8 @@ _fillAppointmentRecurrencePattern (struct AppointmentRecurrencePattern *arp, { startDate = [event startDate]; relation = [[trigger relationType] lowercaseString]; - interval = [[trigger value] durationAsTimeInterval]; + interval = [[trigger flattenedValuesForKey: @""] + durationAsTimeInterval]; if ([relation isEqualToString: @"end"]) relationDate = [event endDate]; else diff --git a/OpenChange/MAPIStoreCalendarMessage.m b/OpenChange/MAPIStoreCalendarMessage.m index 70efa4585..73729cc66 100644 --- a/OpenChange/MAPIStoreCalendarMessage.m +++ b/OpenChange/MAPIStoreCalendarMessage.m @@ -25,6 +25,7 @@ - take the tz definitions from Outlook */ #include +#include #import #import @@ -45,6 +46,7 @@ #import #import #import +#import #import "MAPIStoreAppointmentWrapper.h" #import "MAPIStoreCalendarAttachment.h" @@ -102,15 +104,18 @@ - (MAPIStoreAppointmentWrapper *) appointmentWrapper { iCalEvent *event; + MAPIStoreContext *context; if (!appointmentWrapper) { event = [sogoObject component: NO secure: NO]; + context = [self context]; ASSIGN (appointmentWrapper, [MAPIStoreAppointmentWrapper wrapperWithICalEvent: event - andUser: [[self context] activeUser] + andUser: [context activeUser] andSenderEmail: nil - inTimeZone: [self ownerTimeZone]]); + inTimeZone: [self ownerTimeZone] + withConnectionInfo: [context connectionInfo]]); } return appointmentWrapper; @@ -240,6 +245,12 @@ return [[self appointmentWrapper] getPrImportance: data inMemCtx: memCtx]; } +- (int) getPrBody: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + return [[self appointmentWrapper] getPrBody: data inMemCtx: memCtx]; +} + - (int) getPidLidIsRecurring: (void **) data inMemCtx: (TALLOC_CTX *) memCtx { @@ -599,7 +610,9 @@ [alarm setAction: @"DISPLAY"]; trigger = [iCalTrigger elementWithTag: @"trigger"]; [trigger setValueType: @"DURATION"]; - [trigger setValue: [NSString stringWithFormat: @"-PT%@M", delta]]; + [trigger + setSingleValue: [NSString stringWithFormat: @"-PT%@M", delta] + forKey: @""]; [alarm setTrigger: trigger]; [newEvent addToAlarms: alarm]; [alarm release]; @@ -610,6 +623,7 @@ - (void) save { iCalCalendar *vCalendar; + BOOL isAllDay; iCalDateTime *start, *end; iCalTimeZone *tz; NSCalendarDate *now; @@ -711,9 +725,16 @@ if (value) [newEvent setLocation: value]; - tzName = [[self ownerTimeZone] name]; - tz = [iCalTimeZone timeZoneForName: tzName]; - [vCalendar addTimeZone: tz]; + isAllDay = [[properties + objectForKey: MAPIPropertyKey (PidLidAppointmentSubType)] + boolValue]; + + if (!isAllDay) + { + tzName = [[self ownerTimeZone] name]; + tz = [iCalTimeZone timeZoneForName: tzName]; + [vCalendar addTimeZone: tz]; + } // start value = [properties objectForKey: MAPIPropertyKey (PR_START_DATE)]; @@ -723,8 +744,13 @@ if (value) { start = (iCalDateTime *) [newEvent uniqueChildWithTag: @"dtstart"]; - [start setTimeZone: tz]; - [start setDateTime: value]; + if (isAllDay) + [start setDate: value]; + else + { + [start setTimeZone: tz]; + [start setDateTime: value]; + } } /* end */ @@ -734,8 +760,13 @@ if (value) { end = (iCalDateTime *) [newEvent uniqueChildWithTag: @"dtend"]; - [end setTimeZone: tz]; - [end setDateTime: value]; + if (isAllDay) + [end setDate: value]; + else + { + [end setTimeZone: tz]; + [end setDateTime: value]; + } } /* priority */ @@ -778,6 +809,22 @@ [newEvent setTransparency: @"OPAQUE"]; } } + + /* Comment */ + value = [properties objectForKey: MAPIPropertyKey (PR_BODY_UNICODE)]; + if (!value) + { + value = [properties objectForKey: MAPIPropertyKey (PR_HTML)]; + if (value) + { + value = [[NSString alloc] initWithData: value + encoding: NSUTF8StringEncoding]; + [value autorelease]; + value = [value htmlToText]; + } + } + if (value) + [newEvent setComment: value]; /* recurrence */ value = [properties @@ -793,75 +840,101 @@ /* alarm */ [self _setupAlarmDataInEvent: newEvent]; - // Organizer - value = [properties objectForKey: @"recipients"]; - if (value) + if ([[properties objectForKey: MAPIPropertyKey (PidLidAppointmentStateFlags)] intValue] + != 0) { - NSArray *recipients; - NSDictionary *dict; - iCalPerson *person; - iCalPersonPartStat newPartStat; - NSNumber *flags, *trackStatus; - int i; - - /* We must set the organizer preliminarily here because, unlike what - the doc states, Outlook does not always pass the real organizer - in the recipients list. */ - dict = [activeUser primaryIdentity]; - person = [iCalPerson new]; - [person setCn: [dict objectForKey: @"fullName"]]; - [person setEmail: [dict objectForKey: @"email"]]; - [newEvent setOrganizer: person]; - [person release]; - - recipients = [value objectForKey: @"to"]; - - for (i = 0; i < [recipients count]; i++) + // Organizer + value = [properties objectForKey: @"recipients"]; + if (value) { - dict = [recipients objectAtIndex: i]; - flags = [dict objectForKey: MAPIPropertyKey (PR_RECIPIENT_FLAGS)]; - if (!flags) - { - [self logWithFormat: @"no recipient flags specified"]; - break; - } + NSArray *recipients; + NSDictionary *dict; + NSString *orgEmail, *attEmail; + iCalPerson *person; + iCalPersonPartStat newPartStat; + NSNumber *flags, *trackStatus; + int i, effective; + /* We must set the organizer preliminarily here because, unlike what + the doc states, Outlook does not always pass the real organizer + in the recipients list. */ + dict = [activeUser primaryIdentity]; person = [iCalPerson new]; [person setCn: [dict objectForKey: @"fullName"]]; - [person setEmail: [dict objectForKey: @"email"]]; + orgEmail = [dict objectForKey: @"email"]; + [person setEmail: orgEmail]; + [newEvent setOrganizer: person]; + [person release]; - if (([flags unsignedIntValue] & 0x0002)) /* recipOrganizer */ - [newEvent setOrganizer: person]; - else + recipients = [value objectForKey: @"to"]; + effective = 0; + for (i = 0; i < [recipients count]; i++) { - trackStatus - = [dict - objectForKey: MAPIPropertyKey (PR_RECIPIENT_TRACKSTATUS)]; + dict = [recipients objectAtIndex: i]; - /* FIXME: we should provide a data converter between OL - partstats and SOGo */ - switch ([trackStatus unsignedIntValue]) + flags = [dict objectForKey: MAPIPropertyKey (PR_RECIPIENT_FLAGS)]; + if (!flags) { - case 0x02: /* respTentative */ - newPartStat = iCalPersonPartStatTentative; - break; - case 0x03: /* respAccepted */ - newPartStat = iCalPersonPartStatAccepted; - break; - case 0x04: /* respDeclined */ - newPartStat = iCalPersonPartStatDeclined; - break; - default: - newPartStat = iCalPersonPartStatNeedsAction; + [self logWithFormat: + @"no recipient flags specified: skipping recipient"]; + continue; } - [person setParticipationStatus: newPartStat]; - [person setRsvp: @"TRUE"]; - [person setRole: @"REQ-PARTICIPANT"]; - [newEvent addToAttendees: person]; + person = [iCalPerson new]; + [person setCn: [dict objectForKey: @"fullName"]]; + attEmail = [dict objectForKey: @"email"]; + [person setEmail: attEmail]; + + if (([flags unsignedIntValue] & 0x0002)) /* recipOrganizer */ + [newEvent setOrganizer: person]; + else + { + /* Work-around: it happens that Outlook still passes the + organizer as a recipient, maybe because of a feature + documented in a pre-mesozoic PDF still buried in a + cavern... In that case we remove it, and we keep the + number of effective recipients in "effective". If the + total is 0, we remove the "ORGANIZER" too. */ + if ([attEmail isEqualToString: orgEmail]) + { + [self logWithFormat: + @"avoiding setting organizer as recipient"]; + continue; + } + + trackStatus + = [dict + objectForKey: MAPIPropertyKey (PR_RECIPIENT_TRACKSTATUS)]; + + /* FIXME: we should provide a data converter between OL + partstats and SOGo */ + switch ([trackStatus unsignedIntValue]) + { + case 0x02: /* respTentative */ + newPartStat = iCalPersonPartStatTentative; + break; + case 0x03: /* respAccepted */ + newPartStat = iCalPersonPartStatAccepted; + break; + case 0x04: /* respDeclined */ + newPartStat = iCalPersonPartStatDeclined; + break; + default: + newPartStat = iCalPersonPartStatNeedsAction; + } + + [person setParticipationStatus: newPartStat]; + [person setRsvp: @"TRUE"]; + [person setRole: @"REQ-PARTICIPANT"]; + [newEvent addToAttendees: person]; + effective++; + } + + [person release]; } - [person release]; + if (effective == 0) /* See work-around above */ + [newEvent setOrganizer: nil]; } } diff --git a/OpenChange/MAPIStoreContactsAttachment.m b/OpenChange/MAPIStoreContactsAttachment.m index ff010ff7e..99cb65538 100644 --- a/OpenChange/MAPIStoreContactsAttachment.m +++ b/OpenChange/MAPIStoreContactsAttachment.m @@ -142,7 +142,8 @@ extern NSTimeZone *utcTZ; inMemCtx: (TALLOC_CTX *) memCtx { if (!photoData) - ASSIGN (photoData, [[photo value: 0] dataByDecodingBase64]); + ASSIGN (photoData, + [[photo flattenedValuesForKey: @""] dataByDecodingBase64]); *data = [photoData asBinaryInMemCtx: memCtx]; @@ -153,7 +154,8 @@ extern NSTimeZone *utcTZ; inMemCtx: (TALLOC_CTX *) memCtx { if (!photoData) - ASSIGN (photoData, [[photo value: 0] dataByDecodingBase64]); + ASSIGN (photoData, + [[photo flattenedValuesForKey: @""] dataByDecodingBase64]); *data = MAPILongValue (memCtx, [photoData length]); diff --git a/OpenChange/MAPIStoreContactsMessage.m b/OpenChange/MAPIStoreContactsMessage.m index 764e1ea90..f2732ecb7 100644 --- a/OpenChange/MAPIStoreContactsMessage.m +++ b/OpenChange/MAPIStoreContactsMessage.m @@ -27,10 +27,12 @@ #import #import #import -#import #import #import +#import +#import #import +#import #import "MAPIStoreContactsAttachment.h" #import "MAPIStoreContactsFolder.h" @@ -147,18 +149,11 @@ - (int) getPrCompanyName: (void **) data inMemCtx: (TALLOC_CTX *) memCtx { - NSArray *values; - NSString *stringValue; + CardElement *org; - values = [[sogoObject vCard] org]; - stringValue = nil; - - if ([values count] > 0) - stringValue = [values objectAtIndex: 0]; - else - stringValue = @""; - - *data = [stringValue asUnicodeInMemCtx: memCtx]; + org = [[sogoObject vCard] org]; + *data = [[org flattenedValueAtIndex: 0 forKey: @""] + asUnicodeInMemCtx: memCtx]; return MAPISTORE_SUCCESS; } @@ -166,18 +161,11 @@ - (int) getPrDepartmentName: (void **) data inMemCtx: (TALLOC_CTX *) memCtx { - NSArray *values; - NSString *stringValue; + CardElement *org; - values = [[sogoObject vCard] org]; - stringValue = nil; - - if ([values count] > 1) - stringValue = [values objectAtIndex: 1]; - else - stringValue = @""; - - *data = [stringValue asUnicodeInMemCtx: memCtx]; + org = [[sogoObject vCard] org]; + *data = [[org flattenedValueAtIndex: 1 forKey: @""] + asUnicodeInMemCtx: memCtx]; return MAPISTORE_SUCCESS; } @@ -312,7 +300,7 @@ max = [emails count]; for (count = 0; !stringValue && count < max; count++) { - email = [[emails objectAtIndex: count] value: 0]; + email = [[emails objectAtIndex: count] flattenedValuesForKey: @""]; if ([email caseInsensitiveCompare: [card preferredEMail]] != NSOrderedSame) stringValue = email; @@ -372,7 +360,7 @@ ce = [elements objectAtIndex: count]; if (!aTypeToExclude || ![ce hasAttribute: @"type" havingValue: aTypeToExclude]) - stringValue = [ce value: pos]; + stringValue = [ce flattenedValueAtIndex: pos forKey: @""]; } if (!stringValue) @@ -463,7 +451,7 @@ NSString *stringValue; stringValue = [[[sogoObject vCard] uniqueChildWithTag: @"x-aim"] - value: 0]; + flattenedValuesForKey: @""]; if (!stringValue) stringValue = @""; *data = [stringValue asUnicodeInMemCtx: memCtx]; @@ -697,7 +685,9 @@ { NSString *stringValue; - stringValue = [[[sogoObject vCard] firstChildWithTag: @"n"] value: 0]; + stringValue = [[[sogoObject vCard] firstChildWithTag: @"n"] + flattenedValueAtIndex: 0 + forKey: @""]; *data = [stringValue asUnicodeInMemCtx: memCtx]; return MAPISTORE_SUCCESS; @@ -708,7 +698,9 @@ { NSString *stringValue; - stringValue = [[[sogoObject vCard] firstChildWithTag: @"n"] value: 1]; + stringValue = [[[sogoObject vCard] firstChildWithTag: @"n"] + flattenedValueAtIndex: 1 + forKey: @""]; *data = [stringValue asUnicodeInMemCtx: memCtx]; return MAPISTORE_SUCCESS; @@ -719,7 +711,9 @@ { NSString *stringValue; - stringValue = [[[sogoObject vCard] firstChildWithTag: @"n"] value: 2]; + stringValue = [[[sogoObject vCard] firstChildWithTag: @"n"] + flattenedValueAtIndex: 2 + forKey: @""]; *data = [stringValue asUnicodeInMemCtx: memCtx]; return MAPISTORE_SUCCESS; @@ -730,7 +724,9 @@ { NSString *stringValue; - stringValue = [[[sogoObject vCard] firstChildWithTag: @"n"] value: 3]; + stringValue = [[[sogoObject vCard] firstChildWithTag: @"n"] + flattenedValueAtIndex: 3 + forKey: @""]; *data = [stringValue asUnicodeInMemCtx: memCtx]; return MAPISTORE_SUCCESS; @@ -741,7 +737,9 @@ { NSString *stringValue; - stringValue = [[[sogoObject vCard] firstChildWithTag: @"n"] value: 4]; + stringValue = [[[sogoObject vCard] firstChildWithTag: @"n"] + flattenedValueAtIndex: 4 + forKey: @""]; *data = [stringValue asUnicodeInMemCtx: memCtx]; return MAPISTORE_SUCCESS; @@ -836,9 +834,9 @@ to: photoType]; [photo setValue: 0 ofAttribute: @"encoding" to: @"b"]; - [photo setValue: 0 - to: [content stringByReplacingString: @"\n" - withString: @""]]; + [photo setSingleValue: [content stringByReplacingString: @"\n" + withString: @""] + atIndex: 0 forKey: @""]; } } } @@ -885,7 +883,7 @@ if (value) { if ([elements count] > 0) - [[elements objectAtIndex: 0] setValue: 0 to: value]; + [[elements objectAtIndex: 0] setSingleValue: value forKey: @""]; else [newCard addEmail: value types: [NSArray arrayWithObject: @"pref"]]; @@ -894,7 +892,7 @@ if (value) { if ([elements count] > 1) - [[elements objectAtIndex: 1] setValue: 0 to: value]; + [[elements objectAtIndex: 1] setSingleValue: value forKey: @""]; else [newCard addEmail: value types: nil]; } @@ -902,7 +900,7 @@ if (value) { if ([elements count] > 2) - [[elements objectAtIndex: 2] setValue: 0 to: value]; + [[elements objectAtIndex: 2] setSingleValue: value forKey: @""]; else [newCard addEmail: value types: nil]; } @@ -942,7 +940,7 @@ [element addAttribute: @"type" value: @"pref"]; } - [element setValue: 0 to: value]; + [element setSingleValue: value forKey: @""]; } elements = [newCard childrenWithTag: @"adr" @@ -960,22 +958,22 @@ [element addAttribute: @"type" value: @"pref"]; value = [properties objectForKey: MAPIPropertyKey(PidLidWorkAddressPostOfficeBox)]; if (value) - [element setValue: 0 to: value]; + [element setSingleValue: value atIndex: 0 forKey: @""]; value = [properties objectForKey: MAPIPropertyKey(PidLidWorkAddressStreet)]; if (value) - [element setValue: 2 to: value]; + [element setSingleValue: value atIndex: 2 forKey: @""]; value = [properties objectForKey: MAPIPropertyKey(PidLidWorkAddressCity)]; if (value) - [element setValue: 3 to: value]; + [element setSingleValue: value atIndex: 3 forKey: @""]; value = [properties objectForKey: MAPIPropertyKey(PidLidWorkAddressState)]; if (value) - [element setValue: 4 to: value]; + [element setSingleValue: value atIndex: 4 forKey: @""]; value = [properties objectForKey: MAPIPropertyKey(PidLidWorkAddressPostalCode)]; if (value) - [element setValue: 5 to: value]; + [element setSingleValue: value atIndex: 5 forKey: @""]; value = [properties objectForKey: MAPIPropertyKey(PidLidWorkAddressCountry)]; if (value) - [element setValue: 6 to: value]; + [element setSingleValue: value atIndex: 6 forKey: @""]; // // home postal addresses handling @@ -1001,7 +999,7 @@ [element addAttribute: @"type" value: @"pref"]; } - [element setValue: 0 to: value]; + [element setSingleValue: value forKey: @""]; } elements = [newCard childrenWithTag: @"adr" @@ -1020,22 +1018,22 @@ value = [properties objectForKey: MAPIPropertyKey(PR_HOME_ADDRESS_POST_OFFICE_BOX_UNICODE)]; if (value) - [element setValue: 0 to: value]; + [element setSingleValue: value atIndex: 0 forKey: @""]; value = [properties objectForKey: MAPIPropertyKey( PR_HOME_ADDRESS_STREET_UNICODE)]; if (value) - [element setValue: 2 to: value]; + [element setSingleValue: value atIndex: 2 forKey: @""]; value = [properties objectForKey: MAPIPropertyKey(PR_HOME_ADDRESS_CITY_UNICODE)]; if (value) - [element setValue: 3 to: value]; + [element setSingleValue: value atIndex: 3 forKey: @""]; value = [properties objectForKey: MAPIPropertyKey(PR_HOME_ADDRESS_STATE_OR_PROVINCE_UNICODE)]; if (value) - [element setValue: 4 to: value]; + [element setSingleValue: value atIndex: 4 forKey: @""]; value = [properties objectForKey: MAPIPropertyKey(PR_HOME_ADDRESS_POSTAL_CODE_UNICODE)]; if (value) - [element setValue: 5 to: value]; + [element setSingleValue: value atIndex: 5 forKey: @""]; value = [properties objectForKey: MAPIPropertyKey(PR_HOME_ADDRESS_COUNTRY_UNICODE)]; if (value) - [element setValue: 6 to: value]; + [element setSingleValue: value atIndex: 6 forKey: @""]; // @@ -1044,27 +1042,27 @@ element = [self _elementWithTag: @"tel" ofType: @"work" forCard: newCard]; value = [properties objectForKey: MAPIPropertyKey(PR_OFFICE_TELEPHONE_NUMBER_UNICODE)]; if (value) - [element setValue: 0 to: value]; + [element setSingleValue: value forKey: @""]; element = [self _elementWithTag: @"tel" ofType: @"home" forCard: newCard]; value = [properties objectForKey: MAPIPropertyKey(PR_HOME_TELEPHONE_NUMBER_UNICODE)]; if (value) - [element setValue: 0 to: value]; + [element setSingleValue: value forKey: @""]; element = [self _elementWithTag: @"tel" ofType: @"fax" forCard: newCard]; value = [properties objectForKey: MAPIPropertyKey(PR_BUSINESS_FAX_NUMBER_UNICODE)]; if (value) - [element setValue: 0 to: value]; + [element setSingleValue: value forKey: @""]; element = [self _elementWithTag: @"tel" ofType: @"pager" forCard: newCard]; value = [properties objectForKey: MAPIPropertyKey(PR_PAGER_TELEPHONE_NUMBER_UNICODE)]; if (value) - [element setValue: 0 to: value]; + [element setSingleValue: value forKey: @""]; element = [self _elementWithTag: @"tel" ofType: @"cell" forCard: newCard]; value = [properties objectForKey: MAPIPropertyKey(PR_MOBILE_TELEPHONE_NUMBER_UNICODE)]; if (value) - [element setValue: 0 to: value]; + [element setSingleValue: value forKey: @""]; // @@ -1092,15 +1090,14 @@ if (value) { [[self _elementWithTag: @"url" ofType: @"work" forCard: newCard] - setValue: 0 to: value]; + setSingleValue: value forKey: @""]; } value = [properties objectForKey: MAPIPropertyKey(PidLidInstantMessagingAddress)]; if (value) { [[newCard uniqueChildWithTag: @"x-aim"] - setValue: 0 - to: value]; + setSingleValue: value forKey: @""]; } value = [properties objectForKey: MAPIPropertyKey(PR_BIRTHDAY)]; @@ -1117,6 +1114,22 @@ fromProperties: [attachment properties]]; } + /* Note */ + value = [properties objectForKey: MAPIPropertyKey (PR_BODY_UNICODE)]; + if (!value) + { + value = [properties objectForKey: MAPIPropertyKey (PR_HTML)]; + if (value) + { + value = [[NSString alloc] initWithData: value + encoding: NSUTF8StringEncoding]; + [value autorelease]; + value = [value htmlToText]; + } + } + if (value) + [newCard setNote: value]; + // // we save the new/modified card // diff --git a/OpenChange/MAPIStoreContext.m b/OpenChange/MAPIStoreContext.m index 312b20ec4..ec431228c 100644 --- a/OpenChange/MAPIStoreContext.m +++ b/OpenChange/MAPIStoreContext.m @@ -56,6 +56,7 @@ #undef DEBUG #include #include +#include #include #include #include diff --git a/OpenChange/MAPIStoreFAIMessage.m b/OpenChange/MAPIStoreFAIMessage.m index 68e9c952d..8ae940af0 100644 --- a/OpenChange/MAPIStoreFAIMessage.m +++ b/OpenChange/MAPIStoreFAIMessage.m @@ -26,6 +26,8 @@ #import "MAPIStoreFAIMessage.h" #undef DEBUG +#include +#include #include @implementation MAPIStoreFAIMessage diff --git a/OpenChange/MAPIStoreFAIMessageTable.m b/OpenChange/MAPIStoreFAIMessageTable.m index 46c23e7d7..fb7b6df1f 100644 --- a/OpenChange/MAPIStoreFAIMessageTable.m +++ b/OpenChange/MAPIStoreFAIMessageTable.m @@ -28,6 +28,8 @@ #import "MAPIStoreFAIMessageTable.h" #undef DEBUG +#include +#include #include static Class MAPIStoreFAIMessageK = Nil; diff --git a/OpenChange/MAPIStoreFSBaseContext.m b/OpenChange/MAPIStoreFSBaseContext.m index d57225056..bb34b4795 100644 --- a/OpenChange/MAPIStoreFSBaseContext.m +++ b/OpenChange/MAPIStoreFSBaseContext.m @@ -34,9 +34,6 @@ #import "MAPIStoreFSBaseContext.h" -#undef DEBUG -#include - static Class MAPIStoreFSFolderK; @implementation MAPIStoreFSBaseContext diff --git a/OpenChange/MAPIStoreFSMessage.m b/OpenChange/MAPIStoreFSMessage.m index 352c0931a..6104cc72a 100644 --- a/OpenChange/MAPIStoreFSMessage.m +++ b/OpenChange/MAPIStoreFSMessage.m @@ -80,7 +80,7 @@ [sogoObject appendProperties: properties]; [sogoObject save]; - [self resetProperties]; + [properties removeAllObjects]; } - (NSDate *) creationTime diff --git a/OpenChange/MAPIStoreFolder.m b/OpenChange/MAPIStoreFolder.m index 9083cbe24..4630f7246 100644 --- a/OpenChange/MAPIStoreFolder.m +++ b/OpenChange/MAPIStoreFolder.m @@ -51,6 +51,7 @@ #include #undef DEBUG +#include #include #include #include @@ -898,33 +899,28 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe return rc; } -- (int) addPropertiesFromRow: (struct SRow *) aRow +- (void) addProperties: (NSDictionary *) newProperties { static enum MAPITAGS bannedProps[] = { PR_MID, PR_FID, PR_PARENT_FID, PR_SOURCE_KEY, PR_PARENT_SOURCE_KEY, PR_CHANGE_KEY, 0x00000000 }; enum MAPITAGS *currentProp; - int rc; - - rc = [super addPropertiesFromRow: aRow]; + NSMutableDictionary *propsCopy; /* TODO: this should no longer be required once mapistore v2 API is in place, when we can then do this from -dealloc below */ - if ([properties count] > 0) - { - currentProp = bannedProps; - while (*currentProp) - { - [properties removeObjectForKey: MAPIPropertyKey (*currentProp)]; - currentProp++; - } - [propsMessage appendProperties: properties]; - [propsMessage save]; - [self resetProperties]; + propsCopy = [newProperties mutableCopy]; + currentProp = bannedProps; + while (*currentProp) + { + [propsCopy removeObjectForKey: MAPIPropertyKey (*currentProp)]; + currentProp++; } - return rc; + [propsMessage appendProperties: propsCopy]; + [propsMessage save]; + [propsCopy release]; } - (void) dealloc diff --git a/OpenChange/MAPIStoreMailFolder.m b/OpenChange/MAPIStoreMailFolder.m index aac7d66e7..e99ec2059 100644 --- a/OpenChange/MAPIStoreMailFolder.m +++ b/OpenChange/MAPIStoreMailFolder.m @@ -64,6 +64,7 @@ static Class SOGoMailFolderK; #undef DEBUG +#include #include #include #include diff --git a/OpenChange/MAPIStoreMailMessage.m b/OpenChange/MAPIStoreMailMessage.m index 7ab44bd2b..8c165cc6e 100644 --- a/OpenChange/MAPIStoreMailMessage.m +++ b/OpenChange/MAPIStoreMailMessage.m @@ -48,6 +48,7 @@ #import "MAPIStoreMailAttachment.h" #import "MAPIStoreMailFolder.h" #import "MAPIStoreMapping.h" +#import "MAPIStoreSamDBUtils.h" #import "MAPIStoreTypes.h" #import "MAPIStoreMailMessage.h" @@ -263,6 +264,7 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data) iCalCalendar *calendar; iCalEvent *event; NSString *stringValue, *senderEmail; + MAPIStoreContext *context; if (!appointmentWrapper) { @@ -280,11 +282,13 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data) senderEmail = [[from objectAtIndex: 0] email]; else senderEmail = nil; + context = [self context]; appointmentWrapper = [MAPIStoreAppointmentWrapper wrapperWithICalEvent: event - andUser: [[self context] activeUser] + andUser: [context activeUser] andSenderEmail: senderEmail - inTimeZone: [self ownerTimeZone]]; + inTimeZone: [self ownerTimeZone] + withConnectionInfo: [context connectionInfo]]; [appointmentWrapper retain]; } } @@ -721,6 +725,7 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data) NSDictionary *contactInfos; NGMailAddress *ngAddress; NSData *entryId; + struct ldb_context *samCtx; int rc; if (fullMail) @@ -743,7 +748,8 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data) if (contactInfos) { username = [contactInfos objectForKey: @"c_uid"]; - entryId = MAPIStoreInternalEntryId (username); + samCtx = [[self context] connectionInfo]->sam_ctx; + entryId = MAPIStoreInternalEntryId (samCtx, username); } else entryId = MAPIStoreExternalEntryId (cn, email); @@ -1349,9 +1355,11 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data) NSData *entryId; NSDictionary *contactInfos; SOGoUserManager *mgr; + struct ldb_context *samCtx; struct mapistore_message *msgData; struct mapistore_message_recipient *recipient; + samCtx = [[self context] connectionInfo]->sam_ctx; [super getMessageData: &msgData inMemCtx: memCtx]; if (!headerSetup) @@ -1397,7 +1405,7 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data) { username = [contactInfos objectForKey: @"c_uid"]; recipient->username = [username asUnicodeInMemCtx: msgData]; - entryId = MAPIStoreInternalEntryId (username); + entryId = MAPIStoreInternalEntryId (samCtx, username); } else { diff --git a/OpenChange/MAPIStoreMailVolatileMessage.m b/OpenChange/MAPIStoreMailVolatileMessage.m index 2ae6a131f..5952eb405 100644 --- a/OpenChange/MAPIStoreMailVolatileMessage.m +++ b/OpenChange/MAPIStoreMailVolatileMessage.m @@ -54,6 +54,7 @@ #import "MAPIStoreMailFolder.h" #import "MAPIStoreMIME.h" #import "MAPIStoreMapping.h" +#import "MAPIStoreSamDBUtils.h" #import "MAPIStoreTypes.h" #import "NSData+MAPIStore.h" #import "NSObject+MAPIStore.h" @@ -249,10 +250,13 @@ static NSString *recTypes[] = { @"orig", @"to", @"cc", @"bcc" }; NSData *entryId; NSDictionary *allRecipients, *dict, *contactInfos; SOGoUserManager *mgr; + struct ldb_context *samCtx; struct mapistore_message *msgData; struct mapistore_message_recipient *recipient; enum ulRecipClass type; + samCtx = [[self context] connectionInfo]->sam_ctx; + [super getMessageData: &msgData inMemCtx: memCtx]; allRecipients = [[sogoObject properties] objectForKey: @"recipients"]; @@ -295,7 +299,7 @@ static NSString *recTypes[] = { @"orig", @"to", @"cc", @"bcc" }; { username = [contactInfos objectForKey: @"c_uid"]; recipient->username = [username asUnicodeInMemCtx: msgData]; - entryId = MAPIStoreInternalEntryId (username); + entryId = MAPIStoreInternalEntryId (samCtx, username); } else { @@ -759,7 +763,7 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts, messageData = cleanedMessage; } - [messageData writeToFile: @"/tmp/mimegen.eml" atomically: NO]; + // [messageData writeToFile: @"/tmp/mimegen.eml" atomically: NO]; return messageData; } @@ -812,7 +816,7 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts, mapping = [[self context] mapping]; [mapping unregisterURLWithID: [self objectId]]; [self setIsNew: NO]; - [self resetProperties]; + [properties removeAllObjects]; [[self container] cleanupCaches]; return MAPISTORE_SUCCESS; diff --git a/OpenChange/MAPIStoreMessage.h b/OpenChange/MAPIStoreMessage.h index 85c3d2d9b..83dfa57a2 100644 --- a/OpenChange/MAPIStoreMessage.h +++ b/OpenChange/MAPIStoreMessage.h @@ -37,9 +37,6 @@ #import "MAPIStoreObject.h" -extern NSData *MAPIStoreInternalEntryId (NSString *username); -extern NSData *MAPIStoreExternalEntryId (NSString *cn, NSString *email); - @interface MAPIStoreMessage : MAPIStoreObject { NSArray *attachmentKeys; diff --git a/OpenChange/MAPIStoreMessage.m b/OpenChange/MAPIStoreMessage.m index d3a2f3bd4..f2c78814e 100644 --- a/OpenChange/MAPIStoreMessage.m +++ b/OpenChange/MAPIStoreMessage.m @@ -21,6 +21,7 @@ */ #import +#import #import #import #import @@ -35,6 +36,7 @@ #import "MAPIStoreContext.h" #import "MAPIStoreFolder.h" #import "MAPIStorePropertySelectors.h" +#import "MAPIStoreSamDBUtils.h" #import "MAPIStoreTypes.h" #import "NSData+MAPIStore.h" #import "NSObject+MAPIStore.h" @@ -42,6 +44,8 @@ #import "MAPIStoreMessage.h" +#include + #undef DEBUG #include #include @@ -49,102 +53,64 @@ #include #include -NSData * -MAPIStoreInternalEntryId (NSString *username) +static NSString *resourcesDir = nil; + +/* rtf conversion via unrtf */ +static int +unrtf_data_output (void *data, const char *str, size_t str_len) { - NSMutableData *entryId; - static uint8_t providerUid[] = { 0xdc, 0xa7, 0x40, 0xc8, - 0xc0, 0x42, 0x10, 0x1a, - 0xb4, 0xb9, 0x08, 0x00, - 0x2b, 0x2f, 0xe1, 0x82 }; - NSString *x500dn; + NSMutableData *rtfData = data; - /* structure: - flags: 32 - provideruid: 32 * 4 - version: 32 - type: 32 - X500DN: variable */ + [rtfData appendBytes: str length: str_len]; - entryId = [NSMutableData dataWithCapacity: 256]; - [entryId appendUInt32: 0]; // flags - [entryId appendBytes: providerUid length: 16]; // provideruid - [entryId appendUInt32: 1]; // version - [entryId appendUInt32: 0]; // type (local mail user) - - /* X500DN */ - /* FIXME: the DN will likely work on DEMO installations for now but we - really should get the dn prefix from the server */ - x500dn = [NSString stringWithFormat: @"/O=FIRST ORGANIZATION" - @"/OU=FIRST ADMINISTRATIVE GROUP" - @"/CN=RECIPIENTS/CN=%@", username]; - [entryId appendData: [x500dn dataUsingEncoding: NSISOLatin1StringEncoding]]; - [entryId appendUInt8: 0]; - - return entryId; + return str_len; } -NSData * -MAPIStoreExternalEntryId (NSString *cn, NSString *email) +static NSData * +uncompressRTF (NSData *compressedRTF) { - NSMutableData *entryId; - static uint8_t providerUid[] = { 0x81, 0x2b, 0x1f, 0xa4, - 0xbe, 0xa3, 0x10, 0x19, - 0x9d, 0x6e, 0x00, 0xdd, - 0x01, 0x0f, 0x54, 0x02 }; - uint8_t flags21, flags22; + NSData *rtfData = nil; + DATA_BLOB *rtf; + TALLOC_CTX *mem_ctx; - /* structure: - flags: 32 - provideruid: 32 * 4 - version: 16 - { - PaD: 1 - MAE: 2 - Format: 4 - M: 1 - U: 1 - R: 2 - L: 1 - Pad: 4 - } - DisplayName: variable - AddressType: variable - EmailAddress: variable */ + mem_ctx = talloc_zero (NULL, TALLOC_CTX); + rtf = talloc_zero (mem_ctx, DATA_BLOB); - entryId = [NSMutableData dataWithCapacity: 256]; - [entryId appendUInt32: 0]; // flags - [entryId appendBytes: providerUid length: 16]; // provideruid - [entryId appendUInt16: 0]; // version + if (uncompress_rtf (mem_ctx, + (uint8_t *) [compressedRTF bytes], [compressedRTF length], + rtf) + == MAPI_E_SUCCESS) + rtfData = [NSData dataWithBytes: rtf->data length: rtf->length]; - flags21 = 0; /* PaD, MAE, R, Pad = 0 */ - flags21 |= 0x16; /* Format: text and HTML */ - flags21 |= 0x01; /* M: mime format */ + talloc_free (mem_ctx); - flags22 = 0x90; /* U: unicode, L: no lookup */ - [entryId appendUInt8: flags21]; - [entryId appendUInt8: flags22]; + return rtfData; +} - /* DisplayName */ - if (!cn) - cn = @""; - [entryId - appendData: [cn dataUsingEncoding: NSUTF16LittleEndianStringEncoding]]; - [entryId appendUInt16: 0]; +static NSData * +rtf2html (NSData *compressedRTF) +{ + NSData *rtf; + NSMutableData *html = nil; + int rc; + struct unRTFOptions unrtfOptions; - /* AddressType */ - [entryId - appendData: [@"SMTP" dataUsingEncoding: NSUTF16LittleEndianStringEncoding]]; - [entryId appendUInt16: 0]; + rtf = uncompressRTF (compressedRTF); + if (rtf) + { + html = [NSMutableData data]; + memset (&unrtfOptions, 0, sizeof (struct unRTFOptions)); + unrtf_set_output_device (&unrtfOptions, unrtf_data_output, html); + unrtfOptions.config_directory = [resourcesDir UTF8String]; + unrtfOptions.output_format = "html"; + unrtfOptions.nopict_mode = YES; + rc = unrtf_convert_from_string (&unrtfOptions, + [rtf bytes], [rtf length]); + if (!rc) + html = nil; + } - /* EMailAddress */ - if (!email) - email = @""; - [entryId - appendData: [email dataUsingEncoding: NSUTF16LittleEndianStringEncoding]]; - [entryId appendUInt16: 0]; - - return entryId; + return html; } @interface SOGoObject (MAPIStoreProtocol) @@ -156,6 +122,15 @@ MAPIStoreExternalEntryId (NSString *cn, NSString *email) @implementation MAPIStoreMessage ++ (void) initialize +{ + if (!resourcesDir) + { + resourcesDir = [[NSBundle bundleForClass: self] resourcePath]; + [resourcesDir retain]; + } +} + - (id) init { if ((self = [super init])) @@ -304,6 +279,38 @@ MAPIStoreExternalEntryId (NSString *cn, NSString *email) return MAPISTORE_SUCCESS; } +- (void) addProperties: (NSDictionary *) newNewProperties +{ + NSData *htmlData, *rtfData; + static NSNumber *htmlKey = nil, *rtfKey = nil; + + [super addProperties: newNewProperties]; + + if (!htmlKey) + { + htmlKey = MAPIPropertyKey (PR_HTML); + [htmlKey retain]; + } + + if (!rtfKey) + { + rtfKey = MAPIPropertyKey (PR_RTF_COMPRESSED); + [rtfKey retain]; + } + + if (![properties objectForKey: htmlKey]) + { + rtfData = [properties objectForKey: rtfKey]; + if (rtfData) + { + htmlData = rtf2html (rtfData); + [properties setObject: htmlData forKey: htmlKey]; + [properties removeObjectForKey: rtfKey]; + [properties removeObjectForKey: MAPIPropertyKey (PR_RTF_IN_SYNC)]; + } + } +} + - (MAPIStoreAttachment *) createAttachment { MAPIStoreAttachment *newAttachment; @@ -460,7 +467,7 @@ MAPIStoreExternalEntryId (NSString *cn, NSString *email) [[containerTables objectAtIndex: count] notifyChangesForChild: self]; [self setIsNew: NO]; - [self resetProperties]; + [properties removeAllObjects]; [container cleanupCaches]; return MAPISTORE_SUCCESS; @@ -744,7 +751,7 @@ MAPIStoreExternalEntryId (NSString *cn, NSString *email) - (int) setReadFlag: (uint8_t) flag { - [self subclassResponsibility: _cmd]; + // [self subclassResponsibility: _cmd]; return MAPISTORE_ERROR; } diff --git a/OpenChange/MAPIStoreObject.h b/OpenChange/MAPIStoreObject.h index 31ace625c..d3b10cfbe 100644 --- a/OpenChange/MAPIStoreObject.h +++ b/OpenChange/MAPIStoreObject.h @@ -86,7 +86,6 @@ - (void) addProperties: (NSDictionary *) newProperties; - (NSDictionary *) properties; -- (void) resetProperties; /* ops */ - (int) getAvailableProperties: (struct SPropTagArray **) propertiesP diff --git a/OpenChange/MAPIStoreObject.m b/OpenChange/MAPIStoreObject.m index bc831acf5..f2ac7374e 100644 --- a/OpenChange/MAPIStoreObject.m +++ b/OpenChange/MAPIStoreObject.m @@ -235,11 +235,6 @@ static Class NSExceptionK, MAPIStoreFolderK; return properties; } -- (void) resetProperties -{ - [properties removeAllObjects]; -} - - (int) getProperty: (void **) data withTag: (enum MAPITAGS) propTag inMemCtx: (TALLOC_CTX *) memCtx @@ -451,14 +446,18 @@ static Class NSExceptionK, MAPIStoreFolderK; { struct SPropValue *cValue; NSUInteger counter; + NSMutableDictionary *newProperties; + newProperties = [NSMutableDictionary dictionaryWithCapacity: aRow->cValues]; for (counter = 0; counter < aRow->cValues; counter++) { cValue = aRow->lpProps + counter; - [properties setObject: NSObjectFromSPropValue (cValue) - forKey: MAPIPropertyKey (cValue->ulPropTag)]; + [newProperties setObject: NSObjectFromSPropValue (cValue) + forKey: MAPIPropertyKey (cValue->ulPropTag)]; } + [self addProperties: newProperties]; + return MAPISTORE_SUCCESS; } diff --git a/OpenChange/MAPIStoreRecurrenceUtils.h b/OpenChange/MAPIStoreRecurrenceUtils.h index e1f50c1e8..4fdf8c54e 100644 --- a/OpenChange/MAPIStoreRecurrenceUtils.h +++ b/OpenChange/MAPIStoreRecurrenceUtils.h @@ -26,9 +26,6 @@ #import #import -#include -#include - @class NSCalendarDate; @class iCalRepeatableEntityObject; @class iCalRecurrenceRule; diff --git a/OpenChange/MAPIStoreRecurrenceUtils.m b/OpenChange/MAPIStoreRecurrenceUtils.m index 7f283b698..010066e43 100644 --- a/OpenChange/MAPIStoreRecurrenceUtils.m +++ b/OpenChange/MAPIStoreRecurrenceUtils.m @@ -32,6 +32,10 @@ #import "NSDate+MAPIStore.h" #import "MAPIStoreRecurrenceUtils.h" +#include +#include +#include + @implementation iCalCalendar (MAPIStoreRecurrence) - (void) setupRecurrenceWithMasterEntity: (iCalRepeatableEntityObject *) entity @@ -92,7 +96,7 @@ [rule setFrequency: iCalRecurrenceFrequenceYearly]; [rule setRepeatInterval: rp->Period / 12]; month = [NSString stringWithFormat: @"%d", [startDate monthOfYear]]; - [rule setNamedValue: @"bymonth" to: month]; + [rule setSingleValue: month forKey: @"bymonth"]; } else [self errorWithFormat: @@ -112,7 +116,7 @@ else monthDay = [NSString stringWithFormat: @"%d", rp->PatternTypeSpecific.MonthRecurrencePattern.N]; - [rule setNamedValue: @"bymonthday" to: monthDay]; + [rule setSingleValue: monthDay forKey: @"bymonthday"]; } else if ((rp->PatternTypeSpecific.MonthRecurrencePattern.WeekRecurrencePattern == 0x3e) /* Nth week day */ @@ -135,8 +139,9 @@ else bySetPos = rp->PatternTypeSpecific.MonthRecurrencePattern.N; - [rule setNamedValue: @"bysetpos" - to: [NSString stringWithFormat: @"%d", bySetPos]]; + [rule + setSingleValue: [NSString stringWithFormat: @"%d", bySetPos] + forKey: @"bysetpos"]; } else { @@ -163,9 +168,10 @@ || (rp->PatternType & 4) == 4) { /* MonthEnd, HjMonth and HjMonthEnd */ - [rule setNamedValue: @"bymonthday" - to: [NSString stringWithFormat: @"%d", - rp->PatternTypeSpecific.Day]]; + [rule + setSingleValue: [NSString stringWithFormat: @"%d", + rp->PatternTypeSpecific.Day] + forKey: @"bymonthday"]; } else [self errorWithFormat: @"invalid value for PatternType: %.4x", @@ -305,6 +311,14 @@ rp->FirstDateTime = [moduloDate asMinutesSince1601]; byMonthDay = [[self byMonthDay] objectAtIndex: 0]; + if (!byMonthDay && (freq == iCalRecurrenceFrequenceYearly)) + { + byMonthDay = [NSString stringWithFormat: @"%d", [startDate dayOfMonth]]; + [self warnWithFormat: @"no month day specified in yearly" + @" recurrence: we deduce it from the start date: %@", + byMonthDay]; + } + if (byMonthDay) { if ([byMonthDay intValue] < 0) @@ -325,15 +339,18 @@ { rp->PatternType = PatternType_MonthNth; byDayMask = [self byDayMask]; - days = [byDayMask weekDayOccurrences]; mask = 0; - for (count = 0; count < 7; count++) - if (days[0][count]) - mask |= 1 << count; + days = [byDayMask weekDayOccurrences]; + if (days) + { + for (count = 0; count < 7; count++) + if (days[0][count]) + mask |= 1 << count; + } if (mask) { rp->PatternTypeSpecific.MonthRecurrencePattern.WeekRecurrencePattern = mask; - bySetPos = [self namedValue: @"bysetpos"]; + bySetPos = [self flattenedValuesForKey: @"bysetpos"]; if ([bySetPos length]) rp->PatternTypeSpecific.MonthRecurrencePattern.N = ([bySetPos hasPrefix: @"-"] diff --git a/OpenChange/MAPIStoreSamDBUtils.h b/OpenChange/MAPIStoreSamDBUtils.h new file mode 100644 index 000000000..c58a12686 --- /dev/null +++ b/OpenChange/MAPIStoreSamDBUtils.h @@ -0,0 +1,37 @@ +/* MAPIStoreSamDBUtils.h - this file is part of SOGo + * + * Copyright (C) 2011 Inverse inc + * + * Author: Wolfgang Sourdeau + * + * This file 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, or (at your option) + * any later version. + * + * This file 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; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef MAPISTORESAMDBUTILS_H +#define MAPISTORESAMDBUTILS_H + +@class NSString; + +struct ldb_context; + +NSString *MAPIStoreSamDBUserAttribute (struct ldb_context *samCtx, + NSString *userKey, + NSString *value, + NSString *attributeName); +NSData *MAPIStoreInternalEntryId (struct ldb_context *, NSString *username); +NSData *MAPIStoreExternalEntryId (NSString *cn, NSString *email); + +#endif /* MAPISTORESAMDBUTILS_H */ diff --git a/OpenChange/MAPIStoreSamDBUtils.m b/OpenChange/MAPIStoreSamDBUtils.m new file mode 100644 index 000000000..4d7caff63 --- /dev/null +++ b/OpenChange/MAPIStoreSamDBUtils.m @@ -0,0 +1,165 @@ +/* MAPIStoreSamDBUtils.m - this file is part of SOGo + * + * Copyright (C) 2011 Inverse inc + * + * Author: Wolfgang Sourdeau + * + * This file 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, or (at your option) + * any later version. + * + * This file 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; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#import +#import +#include +#include + +#import "NSData+MAPIStore.h" + +#import "MAPIStoreSamDBUtils.h" + +NSString * +MAPIStoreSamDBUserAttribute (struct ldb_context *samCtx, + NSString *userKey, + NSString *value, + NSString *attributeName) +{ + NSString *resultValue = nil; + const char *attrs[] = { "", NULL }; + NSString *searchFormat; + const char *result; + struct ldb_result *res = NULL; + TALLOC_CTX *memCtx; + int ret; + + memCtx = talloc_zero(NULL, TALLOC_CTX); + + attrs[0] = [attributeName UTF8String]; + searchFormat + = [NSString stringWithFormat: @"(&(objectClass=user)(%@=%%s))", userKey]; + ret = ldb_search (samCtx, memCtx, &res, ldb_get_default_basedn(samCtx), + LDB_SCOPE_SUBTREE, attrs, + [searchFormat UTF8String], + [value UTF8String]); + if (ret == LDB_SUCCESS && res->count == 1) + { + result = ldb_msg_find_attr_as_string (res->msgs[0], attrs[0], NULL); + if (result) + resultValue = [NSString stringWithUTF8String: result]; + } + + talloc_free (memCtx); + + return resultValue; +} + +NSData * +MAPIStoreInternalEntryId (struct ldb_context *samCtx, NSString *username) +{ + static const uint8_t const providerUid[] = { 0xdc, 0xa7, 0x40, 0xc8, + 0xc0, 0x42, 0x10, 0x1a, + 0xb4, 0xb9, 0x08, 0x00, + 0x2b, 0x2f, 0xe1, 0x82 }; + NSMutableData *entryId; + NSData *legacyDNData; + NSString *legacyDN; + + /* structure: + flags: 32 + provideruid: 32 * 4 + version: 32 + type: 32 + X500DN: variable */ + + legacyDN = MAPIStoreSamDBUserAttribute (samCtx, @"sAMAccountName", username, + @"legacyExchangeDN"); + if (legacyDN) + { + entryId = [NSMutableData dataWithCapacity: 256]; + [entryId appendUInt32: 0]; // flags + [entryId appendBytes: providerUid length: 16]; // provideruid + [entryId appendUInt32: 1]; // version + [entryId appendUInt32: 0]; // type (local mail user) + legacyDNData = [legacyDN dataUsingEncoding: NSASCIIStringEncoding]; + [entryId appendData: legacyDNData]; // x500dn + [entryId appendUInt8: 0]; // end of string + } + else + entryId = nil; + + return entryId; +} + +NSData * +MAPIStoreExternalEntryId (NSString *cn, NSString *email) +{ + NSMutableData *entryId; + static uint8_t providerUid[] = { 0x81, 0x2b, 0x1f, 0xa4, + 0xbe, 0xa3, 0x10, 0x19, + 0x9d, 0x6e, 0x00, 0xdd, + 0x01, 0x0f, 0x54, 0x02 }; + uint8_t flags21, flags22; + + /* structure: + flags: 32 + provideruid: 32 * 4 + version: 16 + { + PaD: 1 + MAE: 2 + Format: 4 + M: 1 + U: 1 + R: 2 + L: 1 + Pad: 4 + } + DisplayName: variable + AddressType: variable + EmailAddress: variable */ + + entryId = [NSMutableData dataWithCapacity: 256]; + [entryId appendUInt32: 0]; // flags + [entryId appendBytes: providerUid length: 16]; // provideruid + [entryId appendUInt16: 0]; // version + + flags21 = 0; /* PaD, MAE, R, Pad = 0 */ + flags21 |= 0x16; /* Format: text and HTML */ + flags21 |= 0x01; /* M: mime format */ + + flags22 = 0x90; /* U: unicode, L: no lookup */ + [entryId appendUInt8: flags21]; + [entryId appendUInt8: flags22]; + + /* DisplayName */ + if (!cn) + cn = @""; + [entryId + appendData: [cn dataUsingEncoding: NSUTF16LittleEndianStringEncoding]]; + [entryId appendUInt16: 0]; + + /* AddressType */ + [entryId + appendData: [@"SMTP" dataUsingEncoding: NSUTF16LittleEndianStringEncoding]]; + [entryId appendUInt16: 0]; + + /* EMailAddress */ + if (!email) + email = @""; + [entryId + appendData: [email dataUsingEncoding: NSUTF16LittleEndianStringEncoding]]; + [entryId appendUInt16: 0]; + + return entryId; +} diff --git a/OpenChange/MAPIStoreTypes.h b/OpenChange/MAPIStoreTypes.h index 6272f94e1..23dc03b12 100644 --- a/OpenChange/MAPIStoreTypes.h +++ b/OpenChange/MAPIStoreTypes.h @@ -26,6 +26,8 @@ #import #include +#include +#include #include @class NSData; diff --git a/OpenChange/MAPIStoreTypes.m b/OpenChange/MAPIStoreTypes.m index a278f0594..87e01792a 100644 --- a/OpenChange/MAPIStoreTypes.m +++ b/OpenChange/MAPIStoreTypes.m @@ -20,13 +20,6 @@ * Boston, MA 02111-1307, USA. */ -#undef DEBUG -#include -#include -#include -#include -#include - #import #import #import @@ -38,6 +31,10 @@ #import "MAPIStoreTypes.h" +#undef DEBUG +#include +#include + uint8_t * MAPIBoolValue (void *memCtx, BOOL value) { diff --git a/OpenChange/MAPIStoreVolatileMessage.m b/OpenChange/MAPIStoreVolatileMessage.m index 2c427424b..56bfe6984 100644 --- a/OpenChange/MAPIStoreVolatileMessage.m +++ b/OpenChange/MAPIStoreVolatileMessage.m @@ -80,25 +80,10 @@ Class NSNumberK; [super dealloc]; } -- (int) addPropertiesFromRow: (struct SRow *) aRow -{ - int rc; - - rc = [super addPropertiesFromRow: aRow]; - if (rc == MAPISTORE_SUCCESS) - { - [sogoObject appendProperties: properties]; - [properties removeAllObjects]; - ASSIGN (lastModificationTime, [NSDate date]); - } - - return rc; -} - - (void) addProperties: (NSDictionary *) newProperties { [super addProperties: newProperties]; - [sogoObject appendProperties: newProperties]; + [sogoObject appendProperties: properties]; [properties removeAllObjects]; ASSIGN (lastModificationTime, [NSDate date]); } diff --git a/OpenChange/NSArray+MAPIStore.m b/OpenChange/NSArray+MAPIStore.m index a651888f4..000bc3ec7 100644 --- a/OpenChange/NSArray+MAPIStore.m +++ b/OpenChange/NSArray+MAPIStore.m @@ -28,6 +28,7 @@ #undef DEBUG #include +#include #include @implementation NSArray (MAPIStoreFolders) diff --git a/OpenChange/NSData+MAPIStore.m b/OpenChange/NSData+MAPIStore.m index f998ef27d..e9fe04076 100644 --- a/OpenChange/NSData+MAPIStore.m +++ b/OpenChange/NSData+MAPIStore.m @@ -24,8 +24,9 @@ #undef DEBUG #include -#include #include +#include +#include @implementation NSData (MAPIStoreDataTypes) diff --git a/OpenChange/NSDate+MAPIStore.m b/OpenChange/NSDate+MAPIStore.m index 63d83a0a7..d36ff6729 100644 --- a/OpenChange/NSDate+MAPIStore.m +++ b/OpenChange/NSDate+MAPIStore.m @@ -27,8 +27,9 @@ #import "NSDate+MAPIStore.h" #undef DEBUG -#include #include +#include +#include static NSCalendarDate *refDate = nil; diff --git a/OpenChange/NSString+MAPIStore.m b/OpenChange/NSString+MAPIStore.m index e6cf8fad7..a4a894b6a 100644 --- a/OpenChange/NSString+MAPIStore.m +++ b/OpenChange/NSString+MAPIStore.m @@ -28,6 +28,8 @@ #import "NSString+MAPIStore.h" #undef DEBUG +#include +#include #include @implementation NSString (MAPIStoreDataTypes) diff --git a/OpenChange/SOGoMAPIFSFolder.m b/OpenChange/SOGoMAPIFSFolder.m index 8389830de..67c592543 100644 --- a/OpenChange/SOGoMAPIFSFolder.m +++ b/OpenChange/SOGoMAPIFSFolder.m @@ -35,6 +35,8 @@ #import "SOGoMAPIFSFolder.h" #undef DEBUG +#include +#include #include #include #include diff --git a/OpenChange/gen-property-selectors.py b/OpenChange/gen-property-selectors.py index 36bdc88c7..abf2fb283 100755 --- a/OpenChange/gen-property-selectors.py +++ b/OpenChange/gen-property-selectors.py @@ -81,6 +81,8 @@ h_template = """/* %(filename)s (auto-generated) - this file is part of SOGo #import #include +#include +#include #include extern const NSUInteger MAPIStorePropertyGettersCount; diff --git a/OpenChange/unrtf-0.21.2.diff b/OpenChange/unrtf-0.21.2.diff new file mode 100644 index 000000000..1c054cac1 --- /dev/null +++ b/OpenChange/unrtf-0.21.2.diff @@ -0,0 +1,11531 @@ +diff -durpN unrtf-0.21.2.old/outputs/html.conf unrtf-0.21.2/outputs/html.conf +--- unrtf-0.21.2.old/outputs/html.conf 2010-08-15 08:44:09.000000000 -0400 ++++ unrtf-0.21.2/outputs/html.conf 2011-11-09 15:48:29.982798286 -0500 +@@ -5,7 +5,7 @@ comment_end + --> + + document_begin +- ++ + #Second test of comments + + +diff -durpN unrtf-0.21.2.old/src/attr.c unrtf-0.21.2/src/attr.c +--- unrtf-0.21.2.old/src/attr.c 2010-07-03 22:30:58.000000000 -0400 ++++ unrtf-0.21.2/src/attr.c 2011-11-09 15:48:29.990798214 -0500 +@@ -1,23 +1,23 @@ + /*============================================================================= +- GNU UnRTF, a command-line program to convert RTF documents to other formats. +- Copyright (C) 2000,2001,2004 by Zachary Smith ++ GNU UnRTF, a command-line program to convert RTF documents to other formats. ++ Copyright (C) 2000,2001,2004 by Zachary Smith + +- 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 3 of the License, or +- (at your option) any later version. ++ 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 3 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. ++ 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +- The maintainer is reachable by electronic mail at daved@physiol.usyd.edu.au +-=============================================================================*/ ++ The maintainer is reachable by electronic mail at daved@physiol.usyd.edu.au ++ =============================================================================*/ + + + /*---------------------------------------------------------------------- +@@ -57,47 +57,20 @@ + #include + #endif + ++#include "attr.h" ++#include "convert.h" + #include "malloc.h" + #include "defs.h" + #include "error.h" ++#include "output.h" ++#include "unrtf.h" + + #ifndef HAVE_ATTR_H +-#include "attr.h" + #define HAVE_ATTR_H + #endif + + #include "main.h" + +-extern void starting_body(); +-extern void starting_text(); +- +-extern int simulate_allcaps; +-extern int simulate_smallcaps; +- +- +-#define MAX_ATTRS (10000) +- +- +-/* For each RTF text block (the text within braces) we must keep +- * an AttrStack which is a stack of attributes and their optional +- * parameter. Since RTF text blocks are nested, these make up a +- * stack of stacks. And, since RTF text blocks inherit attributes +- * from parent blocks, all new AttrStacks do the same from +- * their parent AttrStack. +- */ +-typedef struct _stack { +- unsigned char attr_stack[MAX_ATTRS]; +- char *attr_stack_params[MAX_ATTRS]; +- int tos; +- struct _stack *next; +-} AttrStack; +- +-/*@null@*/ static AttrStack *stack_of_stacks = NULL; +-/*@null@*/ static AttrStack *stack_of_stacks_top = NULL; +- +- +- +- + /*======================================================================== + * Name: attr_express_begin + * Purpose: Print the HTML for beginning an attribute. +@@ -106,95 +79,96 @@ typedef struct _stack { + *=======================================================================*/ + + void +-attr_express_begin (int attr, char* param) { +- switch(attr) +- { +- case ATTR_BOLD: +- if (safe_printf(0, op->bold_begin)) fprintf(stderr, TOO_MANY_ARGS, "bold_begin");; +- break; +- case ATTR_ITALIC: +- if (safe_printf(0, op->italic_begin)) fprintf(stderr, TOO_MANY_ARGS, "italic_begin");; +- break; ++attr_express_begin (int attr, char* param, const struct OutputContext *oc) { ++ const struct unRTFOutputDevice *device = &oc->conversion->options->device; ++ switch(attr) ++ { ++ case ATTR_BOLD: ++ if (safe_printf(device, 0, oc->personality->bold_begin)) fprintf(stderr, TOO_MANY_ARGS, "bold_begin");; ++ break; ++ case ATTR_ITALIC: ++ if (safe_printf(device, 0, oc->personality->italic_begin)) fprintf(stderr, TOO_MANY_ARGS, "italic_begin");; ++ break; + +- /* Various underlines, they all resolve to HTML's */ +- case ATTR_THICK_UL: +- case ATTR_WAVE_UL: +- case ATTR_DASH_UL: +- case ATTR_DOT_UL: +- case ATTR_DOT_DASH_UL: +- case ATTR_2DOT_DASH_UL: +- case ATTR_WORD_UL: +- case ATTR_UNDERLINE: +- if (safe_printf(0, op->underline_begin)) fprintf(stderr, TOO_MANY_ARGS, "underline_begin");; +- break; ++ /* Various underlines, they all resolve to HTML's */ ++ case ATTR_THICK_UL: ++ case ATTR_WAVE_UL: ++ case ATTR_DASH_UL: ++ case ATTR_DOT_UL: ++ case ATTR_DOT_DASH_UL: ++ case ATTR_2DOT_DASH_UL: ++ case ATTR_WORD_UL: ++ case ATTR_UNDERLINE: ++ if (safe_printf(device, 0, oc->personality->underline_begin)) fprintf(stderr, TOO_MANY_ARGS, "underline_begin");; ++ break; + +- case ATTR_DOUBLE_UL: +- if (safe_printf(0, op->dbl_underline_begin)) fprintf(stderr, TOO_MANY_ARGS, "dbl_underline_begin");; +- break; ++ case ATTR_DOUBLE_UL: ++ if (safe_printf(device, 0, oc->personality->dbl_underline_begin)) fprintf(stderr, TOO_MANY_ARGS, "dbl_underline_begin");; ++ break; + +- case ATTR_FONTSIZE: +- op_begin_std_fontsize (op, atoi (param)); +- break; ++ case ATTR_FONTSIZE: ++ op_begin_std_fontsize (oc, atoi (param)); ++ break; + +- case ATTR_FONTFACE: +- if (safe_printf(1, op->font_begin,param)) fprintf(stderr, TOO_MANY_ARGS, "font_begin");; +- break; ++ case ATTR_FONTFACE: ++ if (safe_printf(device, 1, oc->personality->font_begin,param)) fprintf(stderr, TOO_MANY_ARGS, "font_begin");; ++ break; + +- case ATTR_FOREGROUND: +- if (safe_printf(1, op->foreground_begin, param)) fprintf(stderr, TOO_MANY_ARGS, "foreground_begin");; +- break; ++ case ATTR_FOREGROUND: ++ if (safe_printf(device, 1, oc->personality->foreground_begin, param)) fprintf(stderr, TOO_MANY_ARGS, "foreground_begin");; ++ break; + +- case ATTR_BACKGROUND: +- if (!simple_mode) +- if (safe_printf(1, op->background_begin,param)) fprintf(stderr, TOO_MANY_ARGS, "background_begin");; +- break; ++ case ATTR_BACKGROUND: ++ if (!oc->conversion->options->simple_mode) ++ if (safe_printf(device, 1, oc->personality->background_begin,param)) fprintf(stderr, TOO_MANY_ARGS, "background_begin");; ++ break; + +- case ATTR_SUPER: +- if (safe_printf(0, op->superscript_begin)) fprintf(stderr, TOO_MANY_ARGS, "superscript_begin");; +- break; +- case ATTR_SUB: +- if (safe_printf(0, op->subscript_begin)) fprintf(stderr, TOO_MANY_ARGS, "subscript_begin");; +- break; ++ case ATTR_SUPER: ++ if (safe_printf(device, 0, oc->personality->superscript_begin)) fprintf(stderr, TOO_MANY_ARGS, "superscript_begin");; ++ break; ++ case ATTR_SUB: ++ if (safe_printf(device, 0, oc->personality->subscript_begin)) fprintf(stderr, TOO_MANY_ARGS, "subscript_begin");; ++ break; + +- case ATTR_STRIKE: +- if (safe_printf(0, op->strikethru_begin)) fprintf(stderr, TOO_MANY_ARGS, "strikethru_begin");; +- break; ++ case ATTR_STRIKE: ++ if (safe_printf(device, 0, oc->personality->strikethru_begin)) fprintf(stderr, TOO_MANY_ARGS, "strikethru_begin");; ++ break; + +- case ATTR_DBL_STRIKE: +- if (safe_printf(0, op->dbl_strikethru_begin)) fprintf(stderr, TOO_MANY_ARGS, "dbl_strikethru_begin");; +- break; ++ case ATTR_DBL_STRIKE: ++ if (safe_printf(device, 0, oc->personality->dbl_strikethru_begin)) fprintf(stderr, TOO_MANY_ARGS, "dbl_strikethru_begin");; ++ break; + +- case ATTR_EXPAND: +- if (safe_printf(1, op->expand_begin, param)) fprintf(stderr, TOO_MANY_ARGS, "expand_begin");; +- break; ++ case ATTR_EXPAND: ++ if (safe_printf(device, 1, oc->personality->expand_begin, param)) fprintf(stderr, TOO_MANY_ARGS, "expand_begin");; ++ break; + +- case ATTR_OUTLINE: +- if (safe_printf(0, op->outline_begin)) fprintf(stderr, TOO_MANY_ARGS, "outline_begin");; +- break; +- case ATTR_SHADOW: +- if (safe_printf(0, op->shadow_begin)) fprintf(stderr, TOO_MANY_ARGS, "shadow_begin");; +- break; +- case ATTR_EMBOSS: +- if (safe_printf(0, op->emboss_begin)) fprintf(stderr, TOO_MANY_ARGS, "emboss_begin");; +- break; +- case ATTR_ENGRAVE: +- if (safe_printf(0, op->engrave_begin)) fprintf(stderr, TOO_MANY_ARGS, "engrave_begin");; +- break; ++ case ATTR_OUTLINE: ++ if (safe_printf(device, 0, oc->personality->outline_begin)) fprintf(stderr, TOO_MANY_ARGS, "outline_begin");; ++ break; ++ case ATTR_SHADOW: ++ if (safe_printf(device, 0, oc->personality->shadow_begin)) fprintf(stderr, TOO_MANY_ARGS, "shadow_begin");; ++ break; ++ case ATTR_EMBOSS: ++ if (safe_printf(device, 0, oc->personality->emboss_begin)) fprintf(stderr, TOO_MANY_ARGS, "emboss_begin");; ++ break; ++ case ATTR_ENGRAVE: ++ if (safe_printf(device, 0, oc->personality->engrave_begin)) fprintf(stderr, TOO_MANY_ARGS, "engrave_begin");; ++ break; + +- case ATTR_CAPS: +- if (op->simulate_all_caps) +- simulate_allcaps = TRUE; +- break; ++ case ATTR_CAPS: ++ if (oc->personality->simulate_all_caps) ++ oc->conversion->simulate_allcaps = TRUE; ++ break; + +- case ATTR_SMALLCAPS: +- if (op->simulate_small_caps) +- simulate_smallcaps = TRUE; +- else { +- if (op->small_caps_begin) +- if (safe_printf(0, op->small_caps_begin)) fprintf(stderr, TOO_MANY_ARGS, "small_caps_begin");; +- } +- break; +- } ++ case ATTR_SMALLCAPS: ++ if (oc->personality->simulate_small_caps) ++ oc->conversion->simulate_smallcaps = TRUE; ++ else { ++ if (oc->personality->small_caps_begin) ++ if (safe_printf(device, 0, oc->personality->small_caps_begin)) fprintf(stderr, TOO_MANY_ARGS, "small_caps_begin");; ++ } ++ break; ++ } + } + + +@@ -206,95 +180,96 @@ attr_express_begin (int attr, char* para + *=======================================================================*/ + + void +-attr_express_end (int attr, char *param) ++attr_express_end (int attr, char *param, const struct OutputContext *oc) + { +- switch(attr) +- { +- case ATTR_BOLD: +- if (safe_printf(0, op->bold_end)) fprintf(stderr, TOO_MANY_ARGS, "bold_end");; +- break; +- case ATTR_ITALIC: +- if (safe_printf(0, op->italic_end)) fprintf(stderr, TOO_MANY_ARGS, "italic_end");; +- break; ++ const struct unRTFOutputDevice *device = &oc->conversion->options->device; ++ switch(attr) ++ { ++ case ATTR_BOLD: ++ if (safe_printf(device, 0, oc->personality->bold_end)) fprintf(stderr, TOO_MANY_ARGS, "bold_end");; ++ break; ++ case ATTR_ITALIC: ++ if (safe_printf(device, 0, oc->personality->italic_end)) fprintf(stderr, TOO_MANY_ARGS, "italic_end");; ++ break; + +- /* Various underlines, they all resolve to HTML's */ +- case ATTR_THICK_UL: +- case ATTR_WAVE_UL: +- case ATTR_DASH_UL: +- case ATTR_DOT_UL: +- case ATTR_DOT_DASH_UL: +- case ATTR_2DOT_DASH_UL: +- case ATTR_WORD_UL: +- case ATTR_UNDERLINE: +- if (safe_printf(0, op->underline_end)) fprintf(stderr, TOO_MANY_ARGS, "underline_end");; +- break; ++ /* Various underlines, they all resolve to HTML's */ ++ case ATTR_THICK_UL: ++ case ATTR_WAVE_UL: ++ case ATTR_DASH_UL: ++ case ATTR_DOT_UL: ++ case ATTR_DOT_DASH_UL: ++ case ATTR_2DOT_DASH_UL: ++ case ATTR_WORD_UL: ++ case ATTR_UNDERLINE: ++ if (safe_printf(device, 0, oc->personality->underline_end)) fprintf(stderr, TOO_MANY_ARGS, "underline_end");; ++ break; + +- case ATTR_DOUBLE_UL: +- if (safe_printf(0, op->dbl_underline_end)) fprintf(stderr, TOO_MANY_ARGS, "dbl_underline_end");; +- break; ++ case ATTR_DOUBLE_UL: ++ if (safe_printf(device, 0, oc->personality->dbl_underline_end)) fprintf(stderr, TOO_MANY_ARGS, "dbl_underline_end");; ++ break; + +- case ATTR_FONTSIZE: +- op_end_std_fontsize (op, atoi (param)); +- break; ++ case ATTR_FONTSIZE: ++ op_end_std_fontsize (oc, atoi (param)); ++ break; + +- case ATTR_FONTFACE: +- if (safe_printf(0, op->font_end)) fprintf(stderr, TOO_MANY_ARGS, "font_end");; +- break; ++ case ATTR_FONTFACE: ++ if (safe_printf(device, 0, oc->personality->font_end)) fprintf(stderr, TOO_MANY_ARGS, "font_end");; ++ break; + +- case ATTR_FOREGROUND: +- if (safe_printf(0, op->foreground_end)) fprintf(stderr, TOO_MANY_ARGS, "foreground_end");; +- break; +- case ATTR_BACKGROUND: +- if (!simple_mode) +- if (safe_printf(0, op->background_end)) fprintf(stderr, TOO_MANY_ARGS, "background_end");; +- break; ++ case ATTR_FOREGROUND: ++ if (safe_printf(device, 0, oc->personality->foreground_end)) fprintf(stderr, TOO_MANY_ARGS, "foreground_end");; ++ break; ++ case ATTR_BACKGROUND: ++ if (!oc->conversion->options->simple_mode) ++ if (safe_printf(device, 0, oc->personality->background_end)) fprintf(stderr, TOO_MANY_ARGS, "background_end");; ++ break; + +- case ATTR_SUPER: +- if (safe_printf(0, op->superscript_end)) fprintf(stderr, TOO_MANY_ARGS, "superscript_end");; +- break; +- case ATTR_SUB: +- if (safe_printf(0, op->subscript_end)) fprintf(stderr, TOO_MANY_ARGS, "subscript_end");; +- break; ++ case ATTR_SUPER: ++ if (safe_printf(device, 0, oc->personality->superscript_end)) fprintf(stderr, TOO_MANY_ARGS, "superscript_end");; ++ break; ++ case ATTR_SUB: ++ if (safe_printf(device, 0, oc->personality->subscript_end)) fprintf(stderr, TOO_MANY_ARGS, "subscript_end");; ++ break; + +- case ATTR_STRIKE: +- if (safe_printf(0, op->strikethru_end)) fprintf(stderr, TOO_MANY_ARGS, "strikethru_end");; +- break; ++ case ATTR_STRIKE: ++ if (safe_printf(device, 0, oc->personality->strikethru_end)) fprintf(stderr, TOO_MANY_ARGS, "strikethru_end");; ++ break; + +- case ATTR_DBL_STRIKE: +- if (safe_printf(0, op->dbl_strikethru_end)) fprintf(stderr, TOO_MANY_ARGS, "dbl_strikethru_end");; +- break; ++ case ATTR_DBL_STRIKE: ++ if (safe_printf(device, 0, oc->personality->dbl_strikethru_end)) fprintf(stderr, TOO_MANY_ARGS, "dbl_strikethru_end");; ++ break; + +- case ATTR_OUTLINE: +- if (safe_printf(0, op->outline_end)) fprintf(stderr, TOO_MANY_ARGS, "outline_end");; +- break; +- case ATTR_SHADOW: +- if (safe_printf(0, op->shadow_end)) fprintf(stderr, TOO_MANY_ARGS, "shadow_end");; +- break; +- case ATTR_EMBOSS: +- if (safe_printf(0, op->emboss_end)) fprintf(stderr, TOO_MANY_ARGS, "emboss_end");; +- break; +- case ATTR_ENGRAVE: +- if (safe_printf(0, op->engrave_end)) fprintf(stderr, TOO_MANY_ARGS, "engrave_end");; +- break; ++ case ATTR_OUTLINE: ++ if (safe_printf(device, 0, oc->personality->outline_end)) fprintf(stderr, TOO_MANY_ARGS, "outline_end");; ++ break; ++ case ATTR_SHADOW: ++ if (safe_printf(device, 0, oc->personality->shadow_end)) fprintf(stderr, TOO_MANY_ARGS, "shadow_end");; ++ break; ++ case ATTR_EMBOSS: ++ if (safe_printf(device, 0, oc->personality->emboss_end)) fprintf(stderr, TOO_MANY_ARGS, "emboss_end");; ++ break; ++ case ATTR_ENGRAVE: ++ if (safe_printf(device, 0, oc->personality->engrave_end)) fprintf(stderr, TOO_MANY_ARGS, "engrave_end");; ++ break; + +- case ATTR_EXPAND: +- if (safe_printf(0, op->expand_end)) fprintf(stderr, TOO_MANY_ARGS, "expand_end");; +- break; ++ case ATTR_EXPAND: ++ if (safe_printf(device, 0, oc->personality->expand_end)) fprintf(stderr, TOO_MANY_ARGS, "expand_end");; ++ break; + +- case ATTR_CAPS: +- if (op->simulate_all_caps) +- simulate_allcaps = FALSE; +- break; ++ case ATTR_CAPS: ++ if (oc->personality->simulate_all_caps) ++ oc->conversion->simulate_allcaps = FALSE; ++ break; + +- case ATTR_SMALLCAPS: +- if (op->simulate_small_caps) +- simulate_smallcaps = FALSE; +- else { +- if (op->small_caps_end) +- if (safe_printf(0, op->small_caps_end)) fprintf(stderr, TOO_MANY_ARGS, "small_caps_end");; +- } +- break; +- } ++ case ATTR_SMALLCAPS: ++ if (oc->personality->simulate_small_caps) ++ oc->conversion->simulate_smallcaps = FALSE; ++ else { ++ if (oc->personality->small_caps_end) ++ if (safe_printf(device, 0, oc->personality->small_caps_end)) fprintf(stderr, TOO_MANY_ARGS, "small_caps_end");; ++ } ++ break; ++ } + } + + +@@ -307,32 +282,32 @@ attr_express_end (int attr, char *param) + *=======================================================================*/ + + void +-attr_push(int attr, char* param) ++attr_push(int attr, char* param, const struct OutputContext *oc) + { +- AttrStack *stack = stack_of_stacks_top; +- if (!stack) { +- warning_handler("No stack to push attribute onto"); +- return; +- } ++ AttrStack *stack = oc->conversion->stack_of_stacks_top; ++ if (!stack) { ++ warning_handler("No stack to push attribute onto"); ++ return; ++ } + +- if (stack->tos >= MAX_ATTRS) { +- fprintf(stderr, "Too many attributes!\n"); +- return; +- } ++ if (stack->tos >= MAX_ATTRS) { ++ fprintf(stderr, "Too many attributes!\n"); ++ return; ++ } + +- /* Make sure it's understood we're in the section. */ +- /* KLUDGE */ +- starting_body(); +- starting_text(); ++ /* Make sure it's understood we're in the section. */ ++ /* KLUDGE */ ++ starting_body(oc); ++ starting_text(oc); + +- ++stack->tos; +- stack->attr_stack[stack->tos] = attr; +- if (param) +- stack->attr_stack_params[stack->tos] = my_strdup(param); +- else +- stack->attr_stack_params[stack->tos] = NULL; ++ ++stack->tos; ++ stack->attr_stack[stack->tos] = attr; ++ if (param) ++ stack->attr_stack_params[stack->tos] = my_strdup(oc->conversion, param); ++ else ++ stack->attr_stack_params[stack->tos] = NULL; + +- attr_express_begin(attr, param); ++ attr_express_begin(attr, param, oc); + } + + +@@ -344,62 +319,25 @@ attr_push(int attr, char* param) + *=======================================================================*/ + + char * +-attr_get_param(int attr) +-{ +- int i; +- AttrStack *stack = stack_of_stacks_top; +- if (!stack) { +- warning_handler("No stack to get attribute from"); +- return; +- } +- +- i=stack->tos; +- while (i>=0) +- { +- if(stack->attr_stack [i] == attr) +- { +- if(stack->attr_stack_params [i] != NULL) +- return stack->attr_stack_params [i]; +- else +- return NULL; +- } +- i--; +- } +- return NULL; +-} +- +- +-/*======================================================================== +- * Name: attrstack_copy_all +- * Purpose: Routine to copy all attributes from one stack to another. +- * Args: Two stacks. +- * Returns: None. +- *=======================================================================*/ +- +-void +-attrstack_copy_all (AttrStack *src, AttrStack *dest) ++attr_get_param(const struct ConversionContext *cc, int attr) + { +- int i; +- int total; +- +- CHECK_PARAM_NOT_NULL(src); +- CHECK_PARAM_NOT_NULL(dest); +- +- total = src->tos + 1; +- +- for (i=0; iattr_stack [i]; +- char *param=src->attr_stack_params [i]; +- +- dest->attr_stack[i] = attr; +- if (param) +- dest->attr_stack_params[i] = my_strdup (param); +- else +- dest->attr_stack_params[i] = NULL; +- } ++ int i; ++ AttrStack *stack = cc->stack_of_stacks_top; ++ if (!stack) { ++ warning_handler("No stack to get attribute from"); ++ return NULL; ++ } + +- dest->tos = src->tos; ++ i=stack->tos; ++ while (i>=0) ++ { ++ if(stack->attr_stack[i] == attr) ++ { ++ return stack->attr_stack_params[i]; ++ } ++ i--; ++ } ++ return NULL; + } + + /*======================================================================== +@@ -414,21 +352,21 @@ attrstack_copy_all (AttrStack *src, Attr + *=======================================================================*/ + + void +-attrstack_unexpress_all (AttrStack *stack) ++attrstack_unexpress_all (AttrStack *stack, const struct OutputContext *oc) + { +- int i; ++ int i; + +- CHECK_PARAM_NOT_NULL(stack); ++ CHECK_PARAM_NOT_NULL(stack); + +- i=stack->tos; +- while (i>=0) +- { +- int attr=stack->attr_stack [i]; +- char *param=stack->attr_stack_params [i]; ++ i=stack->tos; ++ while (i>=0) ++ { ++ int attr=stack->attr_stack[i]; ++ char *param=stack->attr_stack_params[i]; + +- attr_express_end (attr, param); +- i--; +- } ++ attr_express_end (attr, param, oc); ++ i--; ++ } + } + + +@@ -440,23 +378,20 @@ attrstack_unexpress_all (AttrStack *stac + * Returns: None. + *=======================================================================*/ + void +-attrstack_push () ++attrstack_push (struct ConversionContext *cc) + { +- AttrStack *new_stack; +- AttrStack *prev_stack; +- +- new_stack = (AttrStack*) my_malloc (sizeof (AttrStack)); +- memset ((void*) new_stack, 0, sizeof (AttrStack)); ++ AttrStack *new_stack; + +- prev_stack = stack_of_stacks_top; ++ new_stack = (AttrStack*) my_malloc (sizeof (AttrStack)); ++ memset ((void*) new_stack, 0, sizeof (AttrStack)); ++ new_stack->tos = -1; + +- if (!stack_of_stacks) { +- stack_of_stacks = new_stack; +- } else { +- stack_of_stacks_top->next = new_stack; +- } +- stack_of_stacks_top = new_stack; +- new_stack->tos = -1; ++ if (!cc->stack_of_stacks) { ++ cc->stack_of_stacks = new_stack; ++ } else { ++ cc->stack_of_stacks_top->next = new_stack; ++ } ++ cc->stack_of_stacks_top = new_stack; + } + + +@@ -470,29 +405,30 @@ attrstack_push () + *=======================================================================*/ + + int +-attr_pop (int attr) ++attr_pop (int attr, const struct OutputContext *oc) + { +- AttrStack *stack = stack_of_stacks_top; ++ AttrStack *stack = oc->conversion->stack_of_stacks_top; + +- if (!stack) { +- warning_handler ("no stack to pop attribute from"); +- return FALSE; +- } ++ if (!stack) { ++ warning_handler ("no stack to pop attribute from"); ++ return FALSE; ++ } + +- if(stack->tos>=0 && stack->attr_stack[stack->tos]==attr) +- { +- char *param = stack->attr_stack_params [stack->tos]; ++ if(stack->tos>=0 && stack->attr_stack[stack->tos]==attr) ++ { ++ char *param = stack->attr_stack_params[stack->tos]; + +- attr_express_end (attr, param); ++ attr_express_end (attr, param, oc); + +- if (param) my_free(param); ++ if (param) my_free(param); ++ stack->attr_stack_params[stack->tos] = NULL; + +- stack->tos--; ++ stack->tos--; + +- return TRUE; +- } +- else +- return FALSE; ++ return TRUE; ++ } ++ else ++ return FALSE; + } + + +@@ -506,20 +442,20 @@ attr_pop (int attr) + *=======================================================================*/ + + int +-attr_read() { +- AttrStack *stack = stack_of_stacks_top; +- if (!stack) { +- warning_handler ("no stack to read attribute from"); +- return FALSE; +- } ++attr_read(const struct ConversionContext *cc) { ++ AttrStack *stack = cc->stack_of_stacks_top; ++ if (!stack) { ++ warning_handler ("no stack to read attribute from"); ++ return FALSE; ++ } + +- if(stack->tos>=0) +- { +- int attr = stack->attr_stack [stack->tos]; +- return attr; +- } +- else +- return ATTR_NONE; ++ if(stack->tos>=0) ++ { ++ int attr = stack->attr_stack[stack->tos]; ++ return attr; ++ } ++ else ++ return ATTR_NONE; + } + + +@@ -531,20 +467,21 @@ attr_read() { + *=======================================================================*/ + + void +-attr_drop_all () ++attr_drop_all (const struct ConversionContext *cc) + { +- AttrStack *stack = stack_of_stacks_top; +- if (!stack) { +- warning_handler ("no stack to drop all attributes from"); +- return; +- } ++ AttrStack *stack = cc->stack_of_stacks_top; ++ if (!stack) { ++ warning_handler ("no stack to drop all attributes from"); ++ return; ++ } + +- while (stack->tos>=0) +- { +- char *param=stack->attr_stack_params [stack->tos]; +- if (param) my_free(param); +- stack->tos--; +- } ++ while (stack->tos>=0) ++ { ++ char *param=stack->attr_stack_params[stack->tos]; ++ if (param) my_free(param); ++ stack->attr_stack_params[stack->tos] = NULL; ++ stack->tos--; ++ } + } + + +@@ -557,30 +494,34 @@ attr_drop_all () + *=======================================================================*/ + + void +-attrstack_drop () ++attrstack_drop (const struct OutputContext *oc) + { +- AttrStack *stack = stack_of_stacks_top; +- AttrStack *prev_stack; +- if (!stack) { +- warning_handler ("no attr-stack to drop"); +- return; +- } ++ AttrStack *stack = oc->conversion->stack_of_stacks_top; ++ AttrStack *prev_stack; ++ if (!stack) { ++ warning_handler ("no attr-stack to drop"); ++ return; ++ } + +- attr_pop_all (); +- prev_stack = stack_of_stacks; ++ attr_pop_all (oc); + +- while(prev_stack && prev_stack->next && prev_stack->next != stack) +- prev_stack = prev_stack->next; ++ if (stack == oc->conversion->stack_of_stacks) { ++ oc->conversion->stack_of_stacks_top = NULL; ++ oc->conversion->stack_of_stacks = NULL; ++ } ++ else { ++ prev_stack = oc->conversion->stack_of_stacks; + +- if (prev_stack) { +- stack_of_stacks_top = prev_stack; +- prev_stack->next = NULL; +- } else { +- stack_of_stacks_top = NULL; +- stack_of_stacks = NULL; +- } ++ while (prev_stack->next && prev_stack->next != stack) ++ prev_stack = prev_stack->next; + +- my_free ((void*) stack); ++ if (prev_stack) { ++ oc->conversion->stack_of_stacks_top = prev_stack; ++ prev_stack->next = NULL; ++ } ++ } ++ ++ my_free ((void*) stack); + } + + /*======================================================================== +@@ -592,21 +533,22 @@ attrstack_drop () + *=======================================================================*/ + + void +-attr_pop_all() ++attr_pop_all(const struct OutputContext *oc) + { +- AttrStack *stack = stack_of_stacks_top; +- if (!stack) { +- warning_handler ("no stack to pop from"); +- return; +- } ++ AttrStack *stack = oc->conversion->stack_of_stacks_top; ++ if (!stack) { ++ warning_handler ("no stack to pop from"); ++ return; ++ } + +- while (stack->tos>=0) { +- int attr=stack->attr_stack [stack->tos]; +- char *param=stack->attr_stack_params [stack->tos]; +- attr_express_end (attr,param); +- if (param) my_free(param); +- stack->tos--; +- } ++ while (stack->tos>=0) { ++ int attr=stack->attr_stack[stack->tos]; ++ char *param=stack->attr_stack_params[stack->tos]; ++ attr_express_end (attr,param, oc); ++ if (param) my_free(param); ++ stack->attr_stack_params[stack->tos] = NULL; ++ stack->tos--; ++ } + } + + +@@ -621,23 +563,23 @@ attr_pop_all() + *=======================================================================*/ + + void +-attrstack_express_all() { +- AttrStack *stack = stack_of_stacks_top; +- int i; ++attrstack_express_all(const struct OutputContext *oc) { ++ AttrStack *stack = oc->conversion->stack_of_stacks_top; ++ int i; + +- if (!stack) { +- warning_handler ("no stack to pop from"); +- return; +- } ++ if (!stack) { ++ warning_handler ("no stack to pop from"); ++ return; ++ } + +- i=0; +- while (i<=stack->tos) +- { +- int attr=stack->attr_stack [i]; +- char *param=stack->attr_stack_params [i]; +- attr_express_begin (attr, param); +- i++; +- } ++ i=0; ++ while (i<=stack->tos) ++ { ++ int attr=stack->attr_stack[i]; ++ char *param=stack->attr_stack_params[i]; ++ attr_express_begin (attr, param, oc); ++ i++; ++ } + } + + +@@ -652,78 +594,112 @@ attrstack_express_all() { + *=======================================================================*/ + + void +-attr_pop_dump() { +- AttrStack *stack = stack_of_stacks_top; +- int i; ++attr_pop_dump(const struct OutputContext *oc) { ++ AttrStack *stack = oc->conversion->stack_of_stacks_top; ++ int i; + +- if (!stack) return; ++ if (!stack) return; + +- i=stack->tos; +- while (i>=0) +- { +- int attr=stack->attr_stack [i]; +- attr_pop (attr); +- i--; +- } ++ i=stack->tos; ++ while (i>=0) ++ { ++ int attr=stack->attr_stack[i]; ++ attr_pop (attr, oc); ++ i--; ++ } + } + + /*======================================================================== + * Name: safe_printf + * Purpose: Prevents format string attack and writes empty string +- instead of NULL. ++ instead of NULL. + * Args: Number of parameters (without a string), string to write, +- additional parameters to print (have to be strings). ++ additional parameters to print (have to be strings). + * Returns: Returns 0 if number of not escaped '%' in string +- is not greater than nr, else returns -1 ++ is not greater than nr, else returns -1 + *=======================================================================*/ + +- + int +-safe_printf(int nr, char *string, ...) ++safe_printf(const struct unRTFOutputDevice *od, int nr, char *string, ...) + { ++ char *s, *output; ++ int i = 0, ret_code = 0, written; ++ size_t output_len = 0, output_max = 0, size_max; ++ va_list arguments; + +- char *s; +- int i = 0, ret_code = 0; +- va_list arguments; ++ if (string != NULL) ++ { ++ output_max = 1024; ++ output = malloc(output_max * sizeof (char)); ++ *output = 0; ++ va_start(arguments, string); + +- if (string == NULL) +- printf(""); +- else +- { +- va_start(arguments, string); ++ for (; nr > 0; nr--) ++ { ++ while (string[i] != '\0' && (string[i] != '%' || (string[i] == '%' && (i != 0 && string[i-1] == '\\')))) ++ { ++ if (string[i] != '\\' || string[i+1] != '%') ++ { ++ if (output_len + 1 > output_max) ++ { ++ output_max += 1024; ++ output = realloc(output, output_max * sizeof (char)); ++ } ++ output[output_len] = string[i]; ++ output_len++; ++ } ++ i++; ++ } + +- for (; nr > 0; nr--) +- { +- while (string[i] != '\0' && (string[i] != '%' || (string[i] == '%' && (i != 0 && string[i-1] == '\\')))) +- { +- if (string[i] != '\\' || string[i+1] != '%') +- printf("%c", string[i]); +- i++; +- } ++ if (string[i] != '\0') ++ { ++ s = va_arg(arguments, char *); ++ size_max = output_max - output_len; ++ written = snprintf(output + output_len, size_max, "%s", s); ++ if (written > size_max) ++ { ++ output_max += 1024 + written; ++ output = realloc(output, (output_max + 1) * sizeof (char)); ++ sprintf(output + output_len, "%s", s); ++ } ++ output_len += written; ++ i++; ++ } ++ } ++ va_end(arguments); + +- if (string[i] != '\0') +- { +- s = va_arg(arguments, char *); +- printf("%s", s); +- i++; +- } +- } +- va_end(arguments); ++ while (string[i] != '\0') ++ { ++ if (string[i] != '\\' || (string[i] == '\\' && string[i+1] != '%')) ++ { ++ if (string[i] != '%' || (string[i] == '%' && (i != 0 && string[i-1] == '\\'))) ++ { ++ if (output_len + 1 > output_max) ++ { ++ output_max += 1024; ++ output = realloc(output, output_max * sizeof (char)); ++ } ++ output[output_len] = string[i]; ++ output_len++; ++ } ++ else ++ ret_code = -1; ++ } ++ i++; ++ } + +- while (string[i] != '\0') +- { +- if (string[i] != '\\' || (string[i] == '\\' && string[i+1] != '%')) +- { +- if (string[i] != '%' || (string[i] == '%' && (i != 0 && string[i-1] == '\\'))) +- printf("%c", string[i]); +- else +- ret_code = -1; +- } +- i++; +- } +- } ++ if (output_len + 1 > output_max) ++ { ++ output_max += 1; ++ output = realloc(output, output_max * sizeof (char)); ++ } ++ output[output_len] = 0; + +- return ret_code; ++ od->print(od->data, output, output_len); ++ free(output); ++ } ++ ++ return ret_code; + } + + /*======================================================================== +@@ -731,51 +707,51 @@ safe_printf(int nr, char *string, ...) + * Purpose: See Returns + * Args: String to return and int to put into first parameter. + * Returns: Returns first parameter where first not escaped +- character % is substituted with second parameter. ++ character % is substituted with second parameter. + *=======================================================================*/ + + char * + assemble_string(char *string, int nr) + { + +- char *s, tmp[12];/* Number of characters that can be in int type (including '\0') - AF */ +- int i = 0, j = 0; ++ char *s, tmp[12];/* Number of characters that can be in int type (including '\0') - AF */ ++ int i = 0, j = 0; + +- if (string == NULL) +- return NULL; +- else { +- s = my_malloc(strlen(string) + 1 + 12/* Number of characters that can be in int type (including '\0') - AF */); +- while(string[i] != '\0' && (string[i] != '%' || (string[i] == '%' && (i != 0 && string[i-1] == '\\')))) { +- if (string[i] != '\\' || string[i+1] != '%') { +- s[j] = string[i]; +- j++; +- } +- i++; +- } ++ if (string == NULL) ++ return NULL; ++ else { ++ s = my_malloc(strlen(string) + 1 + 12/* Number of characters that can be in int type (including '\0') - AF */); ++ while(string[i] != '\0' && (string[i] != '%' || (string[i] == '%' && (i != 0 && string[i-1] == '\\')))) { ++ if (string[i] != '\\' || string[i+1] != '%') { ++ s[j] = string[i]; ++ j++; ++ } ++ i++; ++ } + +- if (string[i] != '\0') { +- sprintf(tmp, "%d", nr); +- strcpy(&s[j], tmp); +- j = j + strlen(tmp); +- } ++ if (string[i] != '\0') { ++ sprintf(tmp, "%d", nr); ++ strcpy(&s[j], tmp); ++ j = j + strlen(tmp); ++ } + +- while (string[i] != '\0') { +- if (string[i] != '\\' || (string[i] == '\\' && string[i+1] != '%')) { +- if (string[i] != '%' || (string[i] == '%' && (i != 0 && string[i-1] == '\\'))) { +- s[j] = string[i]; +- j++; +- } +- else { +- /* More than one char % occured */ +- } +- } +- i++; +- } +- } ++ while (string[i] != '\0') { ++ if (string[i] != '\\' || (string[i] == '\\' && string[i+1] != '%')) { ++ if (string[i] != '%' || (string[i] == '%' && (i != 0 && string[i-1] == '\\'))) { ++ s[j] = string[i]; ++ j++; ++ } ++ else { ++ /* More than one char % occured */ ++ } ++ } ++ i++; ++ } ++ } + +- s[j] = '\0'; ++ s[j] = '\0'; + +- return s; ++ return s; + } + + +@@ -789,39 +765,39 @@ assemble_string(char *string, int nr) + Collection * + add_to_collection(Collection *col, int nr, char *text) + { +- Collection *c = col; ++ Collection *c = col; + +- if (col == NULL) +- { +- col = (Collection *)my_malloc(sizeof(Collection)); +- col->nr = nr; +- col->text = text; +- col->next = NULL; +- } +- else +- { +- while (c->next != NULL) +- { +- if (c->nr == nr) +- { +-/* Here is a memory leak but not heavy. Do we need to care about this? +- my_free(a->alias.text); +-*/ +- c->text = text; ++ if (col == NULL) ++ { ++ col = (Collection *)my_malloc(sizeof(Collection)); ++ col->nr = nr; ++ col->text = text; ++ col->next = NULL; ++ } ++ else ++ { ++ while (c->next != NULL) ++ { ++ if (c->nr == nr) ++ { ++ /* Here is a memory leak but not heavy. Do we need to care about this? ++ my_free(a->alias.text); ++ */ ++ c->text = text; + +- return col; +- } ++ return col; ++ } + +- c = c->next; +- } ++ c = c->next; ++ } + +- c->next = (Collection *)my_malloc(sizeof(Collection)); +- c->next->nr = nr; +- c->next->text = text; +- c->next->next = NULL; +- } ++ c->next = (Collection *)my_malloc(sizeof(Collection)); ++ c->next->nr = nr; ++ c->next->text = text; ++ c->next->next = NULL; ++ } + +- return col; ++ return col; + } + + /*======================================================================== +@@ -834,15 +810,15 @@ add_to_collection(Collection *col, int n + char * + get_from_collection(Collection *c, int nr) + { +- while (c != NULL) +- { +- if (c->nr == nr) +- return c->text; ++ while (c != NULL) ++ { ++ if (c->nr == nr) ++ return c->text; + +- c = c->next; +- } ++ c = c->next; ++ } + +- return NULL; ++ return NULL; + } + + /*======================================================================== +@@ -855,13 +831,13 @@ get_from_collection(Collection *c, int n + void + free_collection(Collection *c) + { +- Collection *c2; ++ Collection *c2; + +- while (c != NULL) +- { +- c2 = c->next; +- my_free((void *)c); +- c = c2; +- } ++ while (c != NULL) ++ { ++ c2 = c->next; ++ my_free((void *)c); ++ c = c2; ++ } + } + +diff -durpN unrtf-0.21.2.old/src/attr.h unrtf-0.21.2/src/attr.h +--- unrtf-0.21.2.old/src/attr.h 2010-07-03 22:30:58.000000000 -0400 ++++ unrtf-0.21.2/src/attr.h 2011-11-09 15:48:29.990798214 -0500 +@@ -1,23 +1,23 @@ + /*============================================================================= +- GNU UnRTF, a command-line program to convert RTF documents to other formats. +- Copyright (C) 2000,2001,2004 by Zachary Smith ++ GNU UnRTF, a command-line program to convert RTF documents to other formats. ++ Copyright (C) 2000,2001,2004 by Zachary Smith + +- 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 3 of the License, or +- (at your option) any later version. ++ 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 3 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. ++ 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +- The maintainer is reachable by electronic mail at daved@physiol.usyd.edu.au +-=============================================================================*/ ++ The maintainer is reachable by electronic mail at daved@physiol.usyd.edu.au ++ =============================================================================*/ + + + /*---------------------------------------------------------------------- +@@ -35,69 +35,77 @@ + * 09 Nov 08, arkadiusz.firus@gmail.com: adopt safe_printf & collection funcs + *--------------------------------------------------------------------*/ + ++#ifndef ATTR_H ++#define ATTR_H ++ + enum { +- ATTR_NONE=0, +- ATTR_BOLD, ATTR_ITALIC, ++ ATTR_NONE=0, ++ ATTR_BOLD, ATTR_ITALIC, + +- ATTR_UNDERLINE, ATTR_DOUBLE_UL, ATTR_WORD_UL, ++ ATTR_UNDERLINE, ATTR_DOUBLE_UL, ATTR_WORD_UL, + +- ATTR_THICK_UL, ATTR_WAVE_UL, ++ ATTR_THICK_UL, ATTR_WAVE_UL, + +- ATTR_DOT_UL, ATTR_DASH_UL, ATTR_DOT_DASH_UL, ATTR_2DOT_DASH_UL, ++ ATTR_DOT_UL, ATTR_DASH_UL, ATTR_DOT_DASH_UL, ATTR_2DOT_DASH_UL, + +- ATTR_FONTSIZE, ATTR_STD_FONTSIZE, +- ATTR_FONTFACE, +- ATTR_FOREGROUND, ATTR_BACKGROUND, +- ATTR_CAPS, +- ATTR_SMALLCAPS, ++ ATTR_FONTSIZE, ATTR_STD_FONTSIZE, ++ ATTR_FONTFACE, ++ ATTR_FOREGROUND, ATTR_BACKGROUND, ++ ATTR_CAPS, ++ ATTR_SMALLCAPS, + +- ATTR_SHADOW, +- ATTR_OUTLINE, +- ATTR_EMBOSS, +- ATTR_ENGRAVE, ++ ATTR_SHADOW, ++ ATTR_OUTLINE, ++ ATTR_EMBOSS, ++ ATTR_ENGRAVE, + +- ATTR_SUPER, ATTR_SUB, +- ATTR_STRIKE, +- ATTR_DBL_STRIKE, ++ ATTR_SUPER, ATTR_SUB, ++ ATTR_STRIKE, ++ ATTR_DBL_STRIKE, + +- ATTR_EXPAND, +- /* ATTR_CONDENSE */ ++ ATTR_EXPAND, ++ /* ATTR_CONDENSE */ + }; + + typedef struct _c + { +- int nr; +- char *text; +- struct _c *next; ++ int nr; ++ char *text; ++ struct _c *next; + } Collection; + + Collection *add_to_collection(Collection *col, int nr, char *text); + char *get_from_collection(Collection *c, int nr); + void free_collection(Collection *c); + ++struct ConversionContext; ++struct OutputContext; ++struct unRTFOutputDevice; ++ + extern void attr_push_core (int attr, char* param); + + extern void attr_pop_core (int attr); + +-extern void attr_push(int attr, char* param); ++extern void attr_push(int attr, char* param, const struct OutputContext *oc); + +-extern void attrstack_push(); +-extern void attrstack_drop(); ++extern void attrstack_push(struct ConversionContext *cc); ++extern void attrstack_drop(const struct OutputContext *oc); + extern void attrstack_express_all(); + +-extern int attr_pop(int attr); ++extern int attr_pop(int attr, const struct OutputContext *oc); + +-extern int attr_read(); ++extern int attr_read(const struct ConversionContext *cc); + + extern void attr_drop_all (); + +-extern void attr_pop_all(); ++extern void attr_pop_all(const struct OutputContext *oc); + + extern void attr_pop_dump(); + +-char * attr_get_param(int attr); ++char * attr_get_param(const struct ConversionContext *cc, int attr); + +-int safe_printf(int nr, char *string, ...); ++int safe_printf(const struct unRTFOutputDevice *device, int nr, char *string, ...); + char *assemble_string(char *string, int nr); + #define TOO_MANY_ARGS "Tag name \"%s\" do not take so many arguments" + ++#endif /* ATTR_H */ +diff -durpN unrtf-0.21.2.old/src/convert.c unrtf-0.21.2/src/convert.c +--- unrtf-0.21.2.old/src/convert.c 2011-06-07 08:00:23.000000000 -0400 ++++ unrtf-0.21.2/src/convert.c 2011-11-09 15:52:04.710787385 -0500 +@@ -1,24 +1,24 @@ + + /*=========================================================================== +- GNU UnRTF, a command-line program to convert RTF documents to other formats. +- Copyright (C) 2000,2001,2004 Zachary Thayer Smith ++ GNU UnRTF, a command-line program to convert RTF documents to other formats. ++ Copyright (C) 2000,2001,2004 Zachary Thayer Smith + +- 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 3 of the License, or +- (at your option) any later version. ++ 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 3 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. ++ 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +- The maintainer is reachable by electronic mail at daved@physiol.usyd.edu.au +-===========================================================================*/ ++ The maintainer is reachable by electronic mail at daved@physiol.usyd.edu.au ++ ===========================================================================*/ + + + /*---------------------------------------------------------------------- +@@ -56,8 +56,8 @@ + * 31 Mar 05, daved@physiol.usyd.edu.au: strcat security bug fixed + * 06 Jan 06, marcossamaral@terra.com.br: patch from debian 0.19.3-1.1 + * 03 Mar 06, daved@physiol.usyd.edu.au: fixed creation date spelling +- and added support for accented characters in titles from +- Laurent Monin ++ and added support for accented characters in titles from ++ Laurent Monin + * 09 Mar 06, daved@physiol.usyd.edu.au: don't print null post_trans + * 18 Jun 06, daved@physiol.usyd.edu.au: fixed some incorrect comment_end + * 18 Jun 06, frolovs@internet2.ru: codepage support +@@ -68,7 +68,7 @@ + * 04 Jan 10, arkadiusz.firus@gmail.com: deal with (faulty) negative unicodes + * 04 Jan 10, daved@physiol.usyd.edu.au: suppress + * 21 Aug 10, daved@physiol.usyd.edu.au: add support for hex char doublet +- representation of special characters output by some rtf writers ++ representation of special characters output by some rtf writers + *--------------------------------------------------------------------*/ + + #ifdef HAVE_CONFIG_H +@@ -91,15 +91,21 @@ + #include + #endif + ++#ifdef HAVE_UNISTD_H ++#include ++#endif ++ + #include "defs.h" + #include "parse.h" + #include "util.h" + #include "malloc.h" +-#include "main.h" + #include "error.h" + #include "word.h" + #include "hash.h" ++#include "output.h" + #include "convert.h" ++#include "user.h" ++#include "unrtf.h" + + #ifndef HAVE_ATTR_H + #include "attr.h" +@@ -107,506 +113,460 @@ + #endif + + static CodepageInfo codepages[14] = +-{ +-/*-- cp850 --*/ +-{ +- 850, +- { +- /* 0x80 */ +- 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7, +- 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5, +- /* 0x90 */ +- 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9, +- 0x00ff, 0x00d6, 0x00dc, 0x00f8, 0x00a3, 0x00d8, 0x00d7, 0x0192, +- /* 0xa0 */ +- 0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba, +- 0x00bf, 0x00ae, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb, +- /* 0xb0 */ +- 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00c1, 0x00c2, 0x00c0, +- 0x00a9, 0x2563, 0x2551, 0x2557, 0x255d, 0x00a2, 0x00a5, 0x2510, +- /* 0xc0 */ +- 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x00e3, 0x00c3, +- 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x00a4, +- /* 0xd0 */ +- 0x00f0, 0x00d0, 0x00ca, 0x00cb, 0x00c8, 0x0131, 0x00cd, 0x00ce, +- 0x00cf, 0x2518, 0x250c, 0x2588, 0x2584, 0x00a6, 0x00cc, 0x2580, +- /* 0xe0 */ +- 0x00d3, 0x00df, 0x00d4, 0x00d2, 0x00f5, 0x00d5, 0x00b5, 0x00fe, +- 0x00de, 0x00da, 0x00db, 0x00d9, 0x00fd, 0x00dd, 0x00af, 0x00b4, +- /* 0xf0 */ +- 0x00ad, 0x00b1, 0x2017, 0x00be, 0x00b6, 0x00a7, 0x00f7, 0x00b8, +- 0x00b0, 0x00a8, 0x00b7, 0x00b9, 0x00b3, 0x00b2, 0x25a0, 0x00a0, +- } +-}, +-/*-- cp866 --*/ +-{ +- 866, +- { +- /* 0x80 */ +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- /* 0x90 */ +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- /* 0xa0 */ +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- /* 0xb0 */ +- 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, +- 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510, +- /* 0xc0 */ +- 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f, +- 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567, +- /* 0xd0 */ +- 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b, +- 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580, +- /* 0xe0 */ +- 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, +- 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f, +- /* 0xf0 */ +- 0x0401, 0x0451, 0x0404, 0x0454, 0x0407, 0x0457, 0x040e, 0x045e, +- 0x00b0, 0x2219, 0x00b7, 0x221a, 0x2116, 0x00a4, 0x25a0, 0x00a0, +- } +-}, +-/*-- cp874 --*/ +-{ +- 874, +- { +- /* 0x80 */ +- 0x20ac, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x2026, 0xfffd, 0xfffd, +- 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, +- /* 0x90 */ +- 0xfffd, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, +- 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, +- /* 0xa0 */ +- 0x00a0, 0x0e01, 0x0e02, 0x0e03, 0x0e04, 0x0e05, 0x0e06, 0x0e07, +- 0x0e08, 0x0e09, 0x0e0a, 0x0e0b, 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f, +- /* 0xb0 */ +- 0x0e10, 0x0e11, 0x0e12, 0x0e13, 0x0e14, 0x0e15, 0x0e16, 0x0e17, +- 0x0e18, 0x0e19, 0x0e1a, 0x0e1b, 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f, +- /* 0xc0 */ +- 0x0e20, 0x0e21, 0x0e22, 0x0e23, 0x0e24, 0x0e25, 0x0e26, 0x0e27, +- 0x0e28, 0x0e29, 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f, +- /* 0xd0 */ +- 0x0e30, 0x0e31, 0x0e32, 0x0e33, 0x0e34, 0x0e35, 0x0e36, 0x0e37, +- 0x0e38, 0x0e39, 0x0e3a, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x0e3f, +- /* 0xe0 */ +- 0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47, +- 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x0e4e, 0x0e4f, +- /* 0xf0 */ +- 0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57, +- 0x0e58, 0x0e59, 0x0e5a, 0x0e5b, 0xfffd, 0xfffd, 0xfffd, 0xfffd, +- } +-}, +-/*-- cp1133 --*/ +-{ +- 1133, +- { +- /* 0x80 */ +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- /* 0x90 */ +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- /* 0xa0 */ +- 0x00a0, 0x0e81, 0x0e82, 0x0e84, 0x0e87, 0x0e88, 0x0eaa, 0x0e8a, +- 0x0e8d, 0x0e94, 0x0e95, 0x0e96, 0x0e97, 0x0e99, 0x0e9a, 0x0e9b, +- /* 0xb0 */ +- 0x0e9c, 0x0e9d, 0x0e9e, 0x0e9f, 0x0ea1, 0x0ea2, 0x0ea3, 0x0ea5, +- 0x0ea7, 0x0eab, 0x0ead, 0x0eae, 0xfffd, 0xfffd, 0xfffd, 0x0eaf, +- /* 0xc0 */ +- 0x0eb0, 0x0eb2, 0x0eb3, 0x0eb4, 0x0eb5, 0x0eb6, 0x0eb7, 0x0eb8, +- 0x0eb9, 0x0ebc, 0x0eb1, 0x0ebb, 0x0ebd, 0xfffd, 0xfffd, 0xfffd, +- /* 0xd0 */ +- 0x0ec0, 0x0ec1, 0x0ec2, 0x0ec3, 0x0ec4, 0x0ec8, 0x0ec9, 0x0eca, +- 0x0ecb, 0x0ecc, 0x0ecd, 0x0ec6, 0xfffd, 0x0edc, 0x0edd, 0x20ad, +- /* 0xe0 */ +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- /* 0xf0 */ +- 0x0ed0, 0x0ed1, 0x0ed2, 0x0ed3, 0x0ed4, 0x0ed5, 0x0ed6, 0x0ed7, +- 0x0ed8, 0x0ed9, 0xfffd, 0xfffd, 0x00a2, 0x00ac, 0x00a6, 0xfffd, +- } +-}, +-/*-- cp1250 --*/ +-{ +- 1250, + { +- /* 0x80 */ +- 0x20ac, 0xfffd, 0x201a, 0xfffd, 0x201e, 0x2026, 0x2020, 0x2021, +- 0xfffd, 0x2030, 0x0160, 0x2039, 0x015a, 0x0164, 0x017d, 0x0179, +- /* 0x90 */ +- 0xfffd, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, +- 0xfffd, 0x2122, 0x0161, 0x203a, 0x015b, 0x0165, 0x017e, 0x017a, +- /* 0xa0 */ +- 0x00a0, 0x02c7, 0x02d8, 0x0141, 0x00a4, 0x0104, 0x00a6, 0x00a7, +- 0x00a8, 0x00a9, 0x015e, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x017b, +- /* 0xb0 */ +- 0x00b0, 0x00b1, 0x02db, 0x0142, 0x00b4, 0x00b5, 0x00b6, 0x00b7, +- 0x00b8, 0x0105, 0x015f, 0x00bb, 0x013d, 0x02dd, 0x013e, 0x017c, +- /* 0xc0 */ +- 0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7, +- 0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e, +- /* 0xd0 */ +- 0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7, +- 0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df, +- /* 0xe0 */ +- 0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7, +- 0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f, +- /* 0xf0 */ +- 0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7, +- 0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9, +- } +-}, +-/*-- cp1251 --*/ +-{ +- 1251, +- { +- /* 0x80 */ +- 0x0402, 0x0403, 0x201a, 0x0453, 0x201e, 0x2026, 0x2020, 0x2021, +- 0x20ac, 0x2030, 0x0409, 0x2039, 0x040a, 0x040c, 0x040b, 0x040f, +- /* 0x90 */ +- 0x0452, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, +- 0xfffd, 0x2122, 0x0459, 0x203a, 0x045a, 0x045c, 0x045b, 0x045f, +- /* 0xa0 */ +- 0x00a0, 0x040e, 0x045e, 0x0408, 0x00a4, 0x0490, 0x00a6, 0x00a7, +- 0x0401, 0x00a9, 0x0404, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x0407, +- /* 0xb0 */ +- 0x00b0, 0x00b1, 0x0406, 0x0456, 0x0491, 0x00b5, 0x00b6, 0x00b7, +- 0x0451, 0x2116, 0x0454, 0x00bb, 0x0458, 0x0405, 0x0455, 0x0457, +- /* 0xc0 */ +- 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, +- 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f, +- /* 0xd0 */ +- 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, +- 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f, +- /* 0xe0 */ +- 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, +- 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f, +- /* 0xf0 */ +- 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, +- 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f, +- } +-}, +-/*-- cp1252 --*/ +-{ +- 1252, +- { +- /* 0x80 */ +- 0x20ac, 0xfffd, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, +- 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0xfffd, 0x017d, 0xfffd, +- /* 0x90 */ +-/* daved - don't process 93 & 94 as we want entities */ +- 0xfffd, 0x2018, 0x2019, 0, 0, 0x2022, 0x2013, 0x2014, +- 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0xfffd, 0x017e, 0x0178, +- /* 0xa0 */ +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- /* 0xb0 */ +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- /* 0xc0 */ +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- /* 0xd0 */ +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- /* 0xe0 */ +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- /* 0xf0 */ +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- } +-}, +-/*-- cp1253 --*/ +-{ +- 1253, +- { +- /* 0x80 */ +- 0x20ac, 0xfffd, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, +- 0xfffd, 0x2030, 0xfffd, 0x2039, 0xfffd, 0xfffd, 0xfffd, 0xfffd, +- /* 0x90 */ +- 0xfffd, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, +- 0xfffd, 0x2122, 0xfffd, 0x203a, 0xfffd, 0xfffd, 0xfffd, 0xfffd, +- /* 0xa0 */ +- 0x00a0, 0x0385, 0x0386, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, +- 0x00a8, 0x00a9, 0xfffd, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x2015, +- /* 0xb0 */ +- 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x0384, 0x00b5, 0x00b6, 0x00b7, +- 0x0388, 0x0389, 0x038a, 0x00bb, 0x038c, 0x00bd, 0x038e, 0x038f, +- /* 0xc0 */ +- 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, +- 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, +- /* 0xd0 */ +- 0x03a0, 0x03a1, 0xfffd, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7, +- 0x03a8, 0x03a9, 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03ae, 0x03af, +- /* 0xe0 */ +- 0x03b0, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, +- 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, +- /* 0xf0 */ +- 0x03c0, 0x03c1, 0x03c2, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, +- 0x03c8, 0x03c9, 0x03ca, 0x03cb, 0x03cc, 0x03cd, 0x03ce, 0xfffd, +- } +-}, +-/*-- 1254 --*/ +-{ +- 1254, +- { +- /* 0x80 */ +- 0x20ac, 0xfffd, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, +- 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0xfffd, 0xfffd, 0xfffd, +- /* 0x90 */ +- 0xfffd, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, +- 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0xfffd, 0xfffd, 0x0178, +- /* 0xa0 */ +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- /* 0xb0 */ +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- /* 0xc0 */ +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- /* 0xd0 */ +- 0x011e, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, +- 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x0130, 0x015e, 0x00df, +- /* 0xe0 */ +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- /* 0xf0 */ +- 0x011f, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, +- 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x0131, 0x015f, 0x00ff, +- } +-}, +-/*-- cp1255 --*/ +-{ +- 1255, +- { +- /* 0x80 */ +- 0x20ac, 0xfffd, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, +- 0x02c6, 0x2030, 0xfffd, 0x2039, 0xfffd, 0xfffd, 0xfffd, 0xfffd, +- /* 0x90 */ +- 0xfffd, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, +- 0x02dc, 0x2122, 0xfffd, 0x203a, 0xfffd, 0xfffd, 0xfffd, 0xfffd, +- /* 0xa0 */ +- 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x20aa, 0x00a5, 0x00a6, 0x00a7, +- 0x00a8, 0x00a9, 0x00d7, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, +- /* 0xb0 */ +- 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, +- 0x00b8, 0x00b9, 0x00f7, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf, +- /* 0xc0 */ +- 0x05b0, 0x05b1, 0x05b2, 0x05b3, 0x05b4, 0x05b5, 0x05b6, 0x05b7, +- 0x05b8, 0x05b9, 0xfffd, 0x05bb, 0x05bc, 0x05bd, 0x05be, 0x05bf, +- /* 0xd0 */ +- 0x05c0, 0x05c1, 0x05c2, 0x05c3, 0x05f0, 0x05f1, 0x05f2, 0x05f3, +- 0x05f4, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, +- /* 0xe0 */ +- 0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7, +- 0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd, 0x05de, 0x05df, +- /* 0xf0 */ +- 0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5, 0x05e6, 0x05e7, +- 0x05e8, 0x05e9, 0x05ea, 0xfffd, 0xfffd, 0x200e, 0x200f, 0xfffd, +- } +-}, +-/*-- cp1256 --*/ +-{ +- 1256, +- { +- /* 0x80 */ +- 0x20ac, 0x067e, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, +- 0x02c6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688, +- /* 0x90 */ +- 0x06af, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, +- 0x06a9, 0x2122, 0x0691, 0x203a, 0x0153, 0x200c, 0x200d, 0x06ba, +- /* 0xa0 */ +- 0x00a0, 0x060c, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, +- 0x00a8, 0x00a9, 0x06be, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, +- /* 0xb0 */ +- 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, +- 0x00b8, 0x00b9, 0x061b, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x061f, +- /* 0xc0 */ +- 0x06c1, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, +- 0x0628, 0x0629, 0x062a, 0x062b, 0x062c, 0x062d, 0x062e, 0x062f, +- /* 0xd0 */ +- 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x00d7, +- 0x0637, 0x0638, 0x0639, 0x063a, 0x0640, 0x0641, 0x0642, 0x0643, +- /* 0xe0 */ +- 0x00e0, 0x0644, 0x00e2, 0x0645, 0x0646, 0x0647, 0x0648, 0x00e7, +- 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x0649, 0x064a, 0x00ee, 0x00ef, +- /* 0xf0 */ +- 0x064b, 0x064c, 0x064d, 0x064e, 0x00f4, 0x064f, 0x0650, 0x00f7, +- 0x0651, 0x00f9, 0x0652, 0x00fb, 0x00fc, 0x200e, 0x200f, 0x06d2, +- } +-}, +-{ +- 1257, +- { +- /* 0x80 */ +- 0x20ac, 0xfffd, 0x201a, 0xfffd, 0x201e, 0x2026, 0x2020, 0x2021, +- 0xfffd, 0x2030, 0xfffd, 0x2039, 0xfffd, 0x00a8, 0x02c7, 0x00b8, +- /* 0x90 */ +- 0xfffd, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, +- 0xfffd, 0x2122, 0xfffd, 0x203a, 0xfffd, 0x00af, 0x02db, 0xfffd, +- /* 0xa0 */ +- 0x00a0, 0xfffd, 0x00a2, 0x00a3, 0x00a4, 0xfffd, 0x00a6, 0x00a7, +- 0x00d8, 0x00a9, 0x0156, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00c6, +- /* 0xb0 */ +- 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, +- 0x00f8, 0x00b9, 0x0157, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00e6, +- /* 0xc0 */ +- 0x0104, 0x012e, 0x0100, 0x0106, 0x00c4, 0x00c5, 0x0118, 0x0112, +- 0x010c, 0x00c9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012a, 0x013b, +- /* 0xd0 */ +- 0x0160, 0x0143, 0x0145, 0x00d3, 0x014c, 0x00d5, 0x00d6, 0x00d7, +- 0x0172, 0x0141, 0x015a, 0x016a, 0x00dc, 0x017b, 0x017d, 0x00df, +- /* 0xe0 */ +- 0x0105, 0x012f, 0x0101, 0x0107, 0x00e4, 0x00e5, 0x0119, 0x0113, +- 0x010d, 0x00e9, 0x017a, 0x0117, 0x0123, 0x0137, 0x012b, 0x013c, +- /* 0xf0 */ +- 0x0161, 0x0144, 0x0146, 0x00f3, 0x014d, 0x00f5, 0x00f6, 0x00f7, +- 0x0173, 0x0142, 0x015b, 0x016b, 0x00fc, 0x017c, 0x017e, 0x02d9, +- } +-}, +-{ +- 1258, +- { +- /* 0x80 */ +- 0x20ac, 0xfffd, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, +- 0x02c6, 0x2030, 0xfffd, 0x2039, 0x0152, 0xfffd, 0xfffd, 0xfffd, +- /* 0x90 */ +- 0xfffd, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, +- 0x02dc, 0x2122, 0xfffd, 0x203a, 0x0153, 0xfffd, 0xfffd, 0x0178, +- /* 0xa0 */ +- 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, +- 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, +- /* 0xb0 */ +- 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, +- 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf, +- /* 0xc0 */ +- 0x00c0, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x00c5, 0x00c6, 0x00c7, +- 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x0300, 0x00cd, 0x00ce, 0x00cf, +- /* 0xd0 */ +- 0x0110, 0x00d1, 0x0309, 0x00d3, 0x00d4, 0x01a0, 0x00d6, 0x00d7, +- 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x01af, 0x0303, 0x00df, +- /* 0xe0 */ +- 0x00e0, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x00e5, 0x00e6, 0x00e7, +- 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x0301, 0x00ed, 0x00ee, 0x00ef, +- /* 0xf0 */ +- 0x0111, 0x00f1, 0x0323, 0x00f3, 0x00f4, 0x01a1, 0x00f6, 0x00f7, +- 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x01b0, 0x20ab, 0x00ff, +- } +-}, +-/*-- null --*/ +-{ +- 0, +- { +- /* 0x80 */ +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- /* 0x90 */ +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- /* 0xa0 */ +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- /* 0xb0 */ +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- /* 0xc0 */ +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- /* 0xd0 */ +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- /* 0xe0 */ +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- /* 0xf0 */ +- 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, +- } +-}, +-}; +- ++ /*-- cp850 --*/ ++ { ++ 850, ++ { ++ /* 0x80 */ ++ 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7, ++ 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5, ++ /* 0x90 */ ++ 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9, ++ 0x00ff, 0x00d6, 0x00dc, 0x00f8, 0x00a3, 0x00d8, 0x00d7, 0x0192, ++ /* 0xa0 */ ++ 0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba, ++ 0x00bf, 0x00ae, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb, ++ /* 0xb0 */ ++ 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00c1, 0x00c2, 0x00c0, ++ 0x00a9, 0x2563, 0x2551, 0x2557, 0x255d, 0x00a2, 0x00a5, 0x2510, ++ /* 0xc0 */ ++ 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x00e3, 0x00c3, ++ 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x00a4, ++ /* 0xd0 */ ++ 0x00f0, 0x00d0, 0x00ca, 0x00cb, 0x00c8, 0x0131, 0x00cd, 0x00ce, ++ 0x00cf, 0x2518, 0x250c, 0x2588, 0x2584, 0x00a6, 0x00cc, 0x2580, ++ /* 0xe0 */ ++ 0x00d3, 0x00df, 0x00d4, 0x00d2, 0x00f5, 0x00d5, 0x00b5, 0x00fe, ++ 0x00de, 0x00da, 0x00db, 0x00d9, 0x00fd, 0x00dd, 0x00af, 0x00b4, ++ /* 0xf0 */ ++ 0x00ad, 0x00b1, 0x2017, 0x00be, 0x00b6, 0x00a7, 0x00f7, 0x00b8, ++ 0x00b0, 0x00a8, 0x00b7, 0x00b9, 0x00b3, 0x00b2, 0x25a0, 0x00a0, ++ } ++ }, ++ /*-- cp866 --*/ ++ { ++ 866, ++ { ++ /* 0x80 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ /* 0x90 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ /* 0xa0 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ /* 0xb0 */ ++ 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, ++ 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510, ++ /* 0xc0 */ ++ 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f, ++ 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567, ++ /* 0xd0 */ ++ 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b, ++ 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580, ++ /* 0xe0 */ ++ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, ++ 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f, ++ /* 0xf0 */ ++ 0x0401, 0x0451, 0x0404, 0x0454, 0x0407, 0x0457, 0x040e, 0x045e, ++ 0x00b0, 0x2219, 0x00b7, 0x221a, 0x2116, 0x00a4, 0x25a0, 0x00a0, ++ } ++ }, ++ /*-- cp874 --*/ ++ { ++ 874, ++ { ++ /* 0x80 */ ++ 0x20ac, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x2026, 0xfffd, 0xfffd, ++ 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, ++ /* 0x90 */ ++ 0xfffd, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, ++ 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, ++ /* 0xa0 */ ++ 0x00a0, 0x0e01, 0x0e02, 0x0e03, 0x0e04, 0x0e05, 0x0e06, 0x0e07, ++ 0x0e08, 0x0e09, 0x0e0a, 0x0e0b, 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f, ++ /* 0xb0 */ ++ 0x0e10, 0x0e11, 0x0e12, 0x0e13, 0x0e14, 0x0e15, 0x0e16, 0x0e17, ++ 0x0e18, 0x0e19, 0x0e1a, 0x0e1b, 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f, ++ /* 0xc0 */ ++ 0x0e20, 0x0e21, 0x0e22, 0x0e23, 0x0e24, 0x0e25, 0x0e26, 0x0e27, ++ 0x0e28, 0x0e29, 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f, ++ /* 0xd0 */ ++ 0x0e30, 0x0e31, 0x0e32, 0x0e33, 0x0e34, 0x0e35, 0x0e36, 0x0e37, ++ 0x0e38, 0x0e39, 0x0e3a, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0x0e3f, ++ /* 0xe0 */ ++ 0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47, ++ 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x0e4e, 0x0e4f, ++ /* 0xf0 */ ++ 0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57, ++ 0x0e58, 0x0e59, 0x0e5a, 0x0e5b, 0xfffd, 0xfffd, 0xfffd, 0xfffd, ++ } ++ }, ++ /*-- cp1133 --*/ ++ { ++ 1133, ++ { ++ /* 0x80 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ /* 0x90 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ /* 0xa0 */ ++ 0x00a0, 0x0e81, 0x0e82, 0x0e84, 0x0e87, 0x0e88, 0x0eaa, 0x0e8a, ++ 0x0e8d, 0x0e94, 0x0e95, 0x0e96, 0x0e97, 0x0e99, 0x0e9a, 0x0e9b, ++ /* 0xb0 */ ++ 0x0e9c, 0x0e9d, 0x0e9e, 0x0e9f, 0x0ea1, 0x0ea2, 0x0ea3, 0x0ea5, ++ 0x0ea7, 0x0eab, 0x0ead, 0x0eae, 0xfffd, 0xfffd, 0xfffd, 0x0eaf, ++ /* 0xc0 */ ++ 0x0eb0, 0x0eb2, 0x0eb3, 0x0eb4, 0x0eb5, 0x0eb6, 0x0eb7, 0x0eb8, ++ 0x0eb9, 0x0ebc, 0x0eb1, 0x0ebb, 0x0ebd, 0xfffd, 0xfffd, 0xfffd, ++ /* 0xd0 */ ++ 0x0ec0, 0x0ec1, 0x0ec2, 0x0ec3, 0x0ec4, 0x0ec8, 0x0ec9, 0x0eca, ++ 0x0ecb, 0x0ecc, 0x0ecd, 0x0ec6, 0xfffd, 0x0edc, 0x0edd, 0x20ad, ++ /* 0xe0 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ /* 0xf0 */ ++ 0x0ed0, 0x0ed1, 0x0ed2, 0x0ed3, 0x0ed4, 0x0ed5, 0x0ed6, 0x0ed7, ++ 0x0ed8, 0x0ed9, 0xfffd, 0xfffd, 0x00a2, 0x00ac, 0x00a6, 0xfffd, ++ } ++ }, ++ /*-- cp1250 --*/ ++ { ++ 1250, ++ { ++ /* 0x80 */ ++ 0x20ac, 0xfffd, 0x201a, 0xfffd, 0x201e, 0x2026, 0x2020, 0x2021, ++ 0xfffd, 0x2030, 0x0160, 0x2039, 0x015a, 0x0164, 0x017d, 0x0179, ++ /* 0x90 */ ++ 0xfffd, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, ++ 0xfffd, 0x2122, 0x0161, 0x203a, 0x015b, 0x0165, 0x017e, 0x017a, ++ /* 0xa0 */ ++ 0x00a0, 0x02c7, 0x02d8, 0x0141, 0x00a4, 0x0104, 0x00a6, 0x00a7, ++ 0x00a8, 0x00a9, 0x015e, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x017b, ++ /* 0xb0 */ ++ 0x00b0, 0x00b1, 0x02db, 0x0142, 0x00b4, 0x00b5, 0x00b6, 0x00b7, ++ 0x00b8, 0x0105, 0x015f, 0x00bb, 0x013d, 0x02dd, 0x013e, 0x017c, ++ /* 0xc0 */ ++ 0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7, ++ 0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e, ++ /* 0xd0 */ ++ 0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7, ++ 0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df, ++ /* 0xe0 */ ++ 0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7, ++ 0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f, ++ /* 0xf0 */ ++ 0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7, ++ 0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9, ++ } ++ }, ++ /*-- cp1251 --*/ ++ { ++ 1251, ++ { ++ /* 0x80 */ ++ 0x0402, 0x0403, 0x201a, 0x0453, 0x201e, 0x2026, 0x2020, 0x2021, ++ 0x20ac, 0x2030, 0x0409, 0x2039, 0x040a, 0x040c, 0x040b, 0x040f, ++ /* 0x90 */ ++ 0x0452, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, ++ 0xfffd, 0x2122, 0x0459, 0x203a, 0x045a, 0x045c, 0x045b, 0x045f, ++ /* 0xa0 */ ++ 0x00a0, 0x040e, 0x045e, 0x0408, 0x00a4, 0x0490, 0x00a6, 0x00a7, ++ 0x0401, 0x00a9, 0x0404, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x0407, ++ /* 0xb0 */ ++ 0x00b0, 0x00b1, 0x0406, 0x0456, 0x0491, 0x00b5, 0x00b6, 0x00b7, ++ 0x0451, 0x2116, 0x0454, 0x00bb, 0x0458, 0x0405, 0x0455, 0x0457, ++ /* 0xc0 */ ++ 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, ++ 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f, ++ /* 0xd0 */ ++ 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, ++ 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f, ++ /* 0xe0 */ ++ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, ++ 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f, ++ /* 0xf0 */ ++ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, ++ 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f, ++ } ++ }, ++ /*-- cp1252 --*/ ++ { ++ 1252, ++ { ++ /* 0x80 */ ++ 0x20ac, 0xfffd, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, ++ 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0xfffd, 0x017d, 0xfffd, ++ /* 0x90 */ ++ /* daved - don't process 93 & 94 as we want entities */ ++ 0xfffd, 0x2018, 0x2019, 0, 0, 0x2022, 0x2013, 0x2014, ++ 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0xfffd, 0x017e, 0x0178, ++ /* 0xa0 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ /* 0xb0 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ /* 0xc0 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ /* 0xd0 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ /* 0xe0 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ /* 0xf0 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ } ++ }, ++ /*-- cp1253 --*/ ++ { ++ 1253, ++ { ++ /* 0x80 */ ++ 0x20ac, 0xfffd, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, ++ 0xfffd, 0x2030, 0xfffd, 0x2039, 0xfffd, 0xfffd, 0xfffd, 0xfffd, ++ /* 0x90 */ ++ 0xfffd, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, ++ 0xfffd, 0x2122, 0xfffd, 0x203a, 0xfffd, 0xfffd, 0xfffd, 0xfffd, ++ /* 0xa0 */ ++ 0x00a0, 0x0385, 0x0386, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, ++ 0x00a8, 0x00a9, 0xfffd, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x2015, ++ /* 0xb0 */ ++ 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x0384, 0x00b5, 0x00b6, 0x00b7, ++ 0x0388, 0x0389, 0x038a, 0x00bb, 0x038c, 0x00bd, 0x038e, 0x038f, ++ /* 0xc0 */ ++ 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, ++ 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, ++ /* 0xd0 */ ++ 0x03a0, 0x03a1, 0xfffd, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7, ++ 0x03a8, 0x03a9, 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03ae, 0x03af, ++ /* 0xe0 */ ++ 0x03b0, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, ++ 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, ++ /* 0xf0 */ ++ 0x03c0, 0x03c1, 0x03c2, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, ++ 0x03c8, 0x03c9, 0x03ca, 0x03cb, 0x03cc, 0x03cd, 0x03ce, 0xfffd, ++ } ++ }, ++ /*-- 1254 --*/ ++ { ++ 1254, ++ { ++ /* 0x80 */ ++ 0x20ac, 0xfffd, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, ++ 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0xfffd, 0xfffd, 0xfffd, ++ /* 0x90 */ ++ 0xfffd, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, ++ 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0xfffd, 0xfffd, 0x0178, ++ /* 0xa0 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ /* 0xb0 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ /* 0xc0 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ /* 0xd0 */ ++ 0x011e, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, ++ 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x0130, 0x015e, 0x00df, ++ /* 0xe0 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ /* 0xf0 */ ++ 0x011f, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, ++ 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x0131, 0x015f, 0x00ff, ++ } ++ }, ++ /*-- cp1255 --*/ ++ { ++ 1255, ++ { ++ /* 0x80 */ ++ 0x20ac, 0xfffd, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, ++ 0x02c6, 0x2030, 0xfffd, 0x2039, 0xfffd, 0xfffd, 0xfffd, 0xfffd, ++ /* 0x90 */ ++ 0xfffd, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, ++ 0x02dc, 0x2122, 0xfffd, 0x203a, 0xfffd, 0xfffd, 0xfffd, 0xfffd, ++ /* 0xa0 */ ++ 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x20aa, 0x00a5, 0x00a6, 0x00a7, ++ 0x00a8, 0x00a9, 0x00d7, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, ++ /* 0xb0 */ ++ 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, ++ 0x00b8, 0x00b9, 0x00f7, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf, ++ /* 0xc0 */ ++ 0x05b0, 0x05b1, 0x05b2, 0x05b3, 0x05b4, 0x05b5, 0x05b6, 0x05b7, ++ 0x05b8, 0x05b9, 0xfffd, 0x05bb, 0x05bc, 0x05bd, 0x05be, 0x05bf, ++ /* 0xd0 */ ++ 0x05c0, 0x05c1, 0x05c2, 0x05c3, 0x05f0, 0x05f1, 0x05f2, 0x05f3, ++ 0x05f4, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, ++ /* 0xe0 */ ++ 0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7, ++ 0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd, 0x05de, 0x05df, ++ /* 0xf0 */ ++ 0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5, 0x05e6, 0x05e7, ++ 0x05e8, 0x05e9, 0x05ea, 0xfffd, 0xfffd, 0x200e, 0x200f, 0xfffd, ++ } ++ }, ++ /*-- cp1256 --*/ ++ { ++ 1256, ++ { ++ /* 0x80 */ ++ 0x20ac, 0x067e, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, ++ 0x02c6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688, ++ /* 0x90 */ ++ 0x06af, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, ++ 0x06a9, 0x2122, 0x0691, 0x203a, 0x0153, 0x200c, 0x200d, 0x06ba, ++ /* 0xa0 */ ++ 0x00a0, 0x060c, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, ++ 0x00a8, 0x00a9, 0x06be, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, ++ /* 0xb0 */ ++ 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, ++ 0x00b8, 0x00b9, 0x061b, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x061f, ++ /* 0xc0 */ ++ 0x06c1, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, ++ 0x0628, 0x0629, 0x062a, 0x062b, 0x062c, 0x062d, 0x062e, 0x062f, ++ /* 0xd0 */ ++ 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x00d7, ++ 0x0637, 0x0638, 0x0639, 0x063a, 0x0640, 0x0641, 0x0642, 0x0643, ++ /* 0xe0 */ ++ 0x00e0, 0x0644, 0x00e2, 0x0645, 0x0646, 0x0647, 0x0648, 0x00e7, ++ 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x0649, 0x064a, 0x00ee, 0x00ef, ++ /* 0xf0 */ ++ 0x064b, 0x064c, 0x064d, 0x064e, 0x00f4, 0x064f, 0x0650, 0x00f7, ++ 0x0651, 0x00f9, 0x0652, 0x00fb, 0x00fc, 0x200e, 0x200f, 0x06d2, ++ } ++ }, ++ { ++ 1257, ++ { ++ /* 0x80 */ ++ 0x20ac, 0xfffd, 0x201a, 0xfffd, 0x201e, 0x2026, 0x2020, 0x2021, ++ 0xfffd, 0x2030, 0xfffd, 0x2039, 0xfffd, 0x00a8, 0x02c7, 0x00b8, ++ /* 0x90 */ ++ 0xfffd, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, ++ 0xfffd, 0x2122, 0xfffd, 0x203a, 0xfffd, 0x00af, 0x02db, 0xfffd, ++ /* 0xa0 */ ++ 0x00a0, 0xfffd, 0x00a2, 0x00a3, 0x00a4, 0xfffd, 0x00a6, 0x00a7, ++ 0x00d8, 0x00a9, 0x0156, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00c6, ++ /* 0xb0 */ ++ 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, ++ 0x00f8, 0x00b9, 0x0157, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00e6, ++ /* 0xc0 */ ++ 0x0104, 0x012e, 0x0100, 0x0106, 0x00c4, 0x00c5, 0x0118, 0x0112, ++ 0x010c, 0x00c9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012a, 0x013b, ++ /* 0xd0 */ ++ 0x0160, 0x0143, 0x0145, 0x00d3, 0x014c, 0x00d5, 0x00d6, 0x00d7, ++ 0x0172, 0x0141, 0x015a, 0x016a, 0x00dc, 0x017b, 0x017d, 0x00df, ++ /* 0xe0 */ ++ 0x0105, 0x012f, 0x0101, 0x0107, 0x00e4, 0x00e5, 0x0119, 0x0113, ++ 0x010d, 0x00e9, 0x017a, 0x0117, 0x0123, 0x0137, 0x012b, 0x013c, ++ /* 0xf0 */ ++ 0x0161, 0x0144, 0x0146, 0x00f3, 0x014d, 0x00f5, 0x00f6, 0x00f7, ++ 0x0173, 0x0142, 0x015b, 0x016b, 0x00fc, 0x017c, 0x017e, 0x02d9, ++ } ++ }, ++ { ++ 1258, ++ { ++ /* 0x80 */ ++ 0x20ac, 0xfffd, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, ++ 0x02c6, 0x2030, 0xfffd, 0x2039, 0x0152, 0xfffd, 0xfffd, 0xfffd, ++ /* 0x90 */ ++ 0xfffd, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, ++ 0x02dc, 0x2122, 0xfffd, 0x203a, 0x0153, 0xfffd, 0xfffd, 0x0178, ++ /* 0xa0 */ ++ 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, ++ 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, ++ /* 0xb0 */ ++ 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, ++ 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf, ++ /* 0xc0 */ ++ 0x00c0, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x00c5, 0x00c6, 0x00c7, ++ 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x0300, 0x00cd, 0x00ce, 0x00cf, ++ /* 0xd0 */ ++ 0x0110, 0x00d1, 0x0309, 0x00d3, 0x00d4, 0x01a0, 0x00d6, 0x00d7, ++ 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x01af, 0x0303, 0x00df, ++ /* 0xe0 */ ++ 0x00e0, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x00e5, 0x00e6, 0x00e7, ++ 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x0301, 0x00ed, 0x00ee, 0x00ef, ++ /* 0xf0 */ ++ 0x0111, 0x00f1, 0x0323, 0x00f3, 0x00f4, 0x01a1, 0x00f6, 0x00f7, ++ 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x01b0, 0x20ab, 0x00ff, ++ } ++ }, ++ /*-- null --*/ ++ { ++ 0, ++ { ++ /* 0x80 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ /* 0x90 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ /* 0xa0 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ /* 0xb0 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ /* 0xc0 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ /* 0xd0 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ /* 0xe0 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ /* 0xf0 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ } ++ }, ++ }; + +-extern int nopict_mode; + + /* +-#define BINARY_ATTRS ++ #define BINARY_ATTRS + */ + +-my_iconv_t desc = MY_ICONV_T_CLEAR, desc2 = MY_ICONV_T_CLEAR; +- + /* Nested tables aren't supported. + */ +-static int coming_pars_that_are_tabular = 0; +-static int within_table = FALSE; +-static int have_printed_row_begin=FALSE; +-static int have_printed_cell_begin=FALSE; +-static int have_printed_row_end=FALSE; +-static int have_printed_cell_end=FALSE; +- +- +-/* Previously in word_print_core function +- */ +-static int total_chars_this_line=0; /* for simulating \tab */ +- + + /* Paragraph alignment (kludge) + */ + enum { +- ALIGN_LEFT=0, +- ALIGN_RIGHT, +- ALIGN_CENTER, +- ALIGN_JUSTIFY ++ ALIGN_LEFT=0, ++ ALIGN_RIGHT, ++ ALIGN_CENTER, ++ ALIGN_JUSTIFY + }; + +- +- +-/* This value is set by attr_push and attr_pop +- */ +-int simulate_smallcaps; +-int simulate_allcaps; +- +- + /* Most pictures must be written to files. */ + enum { +- PICT_UNKNOWN=0, +- PICT_WM, +- PICT_MAC, +- PICT_PM, +- PICT_DI, +- PICT_WB, +- PICT_JPEG, +- PICT_PNG, ++ PICT_UNKNOWN=0, ++ PICT_WM, ++ PICT_MAC, ++ PICT_PM, ++ PICT_DI, ++ PICT_WB, ++ PICT_JPEG, ++ PICT_PNG, + }; +-static int within_picture=FALSE; +-static int picture_file_number=1; +-static char picture_path[255]; +-static int picture_width; +-static int picture_height; +-static int picture_bits_per_pixel=1; +-static int picture_type=PICT_UNKNOWN; +-static int picture_wmetafile_type; +-static char *picture_wmetafile_type_str; +- +- +-static int have_printed_body=FALSE; +-static int within_header=TRUE; +- +- +- +-static char *hyperlink_base = NULL; +- +- +- +-void starting_body(); +-void starting_text(); +-void print_with_special_exprs (char *s); +- +-static int banner_printed=FALSE; + ++void starting_body(const struct OutputContext *oc); ++void starting_text(const struct OutputContext *oc); ++void print_with_special_exprs (const struct OutputContext *oc, char *s); + + /*======================================================================== + * Name: print_banner +@@ -616,15 +576,17 @@ static int banner_printed=FALSE; + *=======================================================================*/ + + void +-print_banner () { +- if (!banner_printed) { +- if (safe_printf(0, op->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); +- printf(" Translation from RTF performed by "); +- printf("UnRTF, version "); +- printf("%s ", PACKAGE_VERSION); +- if (safe_printf(0, op->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); +- } +- banner_printed=TRUE; ++print_banner (const struct OutputContext *oc) { ++ const struct unRTFOutputDevice *device = &oc->conversion->options->device; ++ ++ if (!oc->conversion->banner_printed) { ++ if (safe_printf(device, 0, oc->personality->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); ++ printf(" Translation from RTF performed by "); ++ printf("UnRTF, version "); ++ printf("%s ", PACKAGE_VERSION); ++ if (safe_printf(device, 0, oc->personality->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); ++ } ++ oc->conversion->banner_printed=TRUE; + } + + +@@ -636,16 +598,18 @@ print_banner () { + *=======================================================================*/ + + void +-starting_body () ++starting_body (const struct OutputContext *oc) + { +- if (!have_printed_body) { +- if (!inline_mode) { +- if (safe_printf(0, op->header_end)) fprintf(stderr, TOO_MANY_ARGS, "header_end"); +- if (safe_printf(0, op->body_begin)) fprintf(stderr, TOO_MANY_ARGS, "body_begin"); +- } +- within_header = FALSE; +- have_printed_body = TRUE; +- } ++ const struct unRTFOutputDevice *device = &oc->conversion->options->device; ++ ++ if (!oc->conversion->have_printed_body) { ++ if (!oc->conversion->options->inline_mode) { ++ if (safe_printf(device, 0, oc->personality->header_end)) fprintf(stderr, TOO_MANY_ARGS, "header_end"); ++ if (safe_printf(device, 0, oc->personality->body_begin)) fprintf(stderr, TOO_MANY_ARGS, "body_begin"); ++ } ++ oc->conversion->within_header = FALSE; ++ oc->conversion->have_printed_body = TRUE; ++ } + } + + +@@ -691,55 +655,44 @@ static char *month_strings[12]= { + *=======================================================================*/ + + void +-word_dump_date (Word *w) ++word_dump_date (const struct ConversionContext *cc, Word *w) + { +- int year=0, month=0, day=0, hour=0, minute=0; +- CHECK_PARAM_NOT_NULL(w); +- while (w) { +- char *s = word_string (w); +- if (*s == '\\') { +- ++s; +- if (!strncmp (s, "yr", 2) && isdigit(s[2])) { +- year = atoi (&s[2]); +- } +- else if (!strncmp (s, "mo", 2) && isdigit(s[2])) { +- month= atoi (&s[2]); +- } +- else if (!strncmp (s, "dy", 2) && isdigit(s[2])) { +- day= atoi (&s[2]); +- } +- else if (!strncmp (s, "min", 3) && isdigit(s[3])) { +- minute= atoi (&s[3]); +- } +- else if (!strncmp (s, "hr", 2) && isdigit(s[2])) { +- hour= atoi (&s[2]); +- } +- } +- w=w->next; +- } +- if (year && month && day) { +- printf("%d %s %d ", day, month_strings[month-1], year); +- } +- if (hour && minute) { +- printf("%02d:%02d ", hour, minute); +- } ++ int year=0, month=0, day=0, hour=0, minute=0; ++ CHECK_PARAM_NOT_NULL(w); ++ while (w) { ++ char *s = word_string (cc, w); ++ if (*s == '\\') { ++ ++s; ++ if (!strncmp (s, "yr", 2) && isdigit(s[2])) { ++ year = atoi (&s[2]); ++ } ++ else if (!strncmp (s, "mo", 2) && isdigit(s[2])) { ++ month= atoi (&s[2]); ++ } ++ else if (!strncmp (s, "dy", 2) && isdigit(s[2])) { ++ day= atoi (&s[2]); ++ } ++ else if (!strncmp (s, "min", 3) && isdigit(s[3])) { ++ minute= atoi (&s[3]); ++ } ++ else if (!strncmp (s, "hr", 2) && isdigit(s[2])) { ++ hour= atoi (&s[2]); ++ } ++ } ++ w=w->next; ++ } ++ if (year && month && day) { ++ printf("%d %s %d ", day, month_strings[month-1], year); ++ } ++ if (hour && minute) { ++ printf("%02d:%02d ", hour, minute); ++ } + } + + + + /*-------------------------------------------------------------------*/ + +-typedef struct { +- int num; +- char *name; +-} FontEntry; +- +-#define MAX_FONTS (8192) +-static FontEntry font_table[MAX_FONTS]; +-static int total_fonts=0; +- +- +- + /*======================================================================== + * Name: lookup_fontname + * Purpose: Fetches the name of a font from the already-read font table. +@@ -748,14 +701,14 @@ static int total_fonts=0; + *=======================================================================*/ + + char* +-lookup_fontname (int num) { +- int i; +- if (total_fonts) +- for(i=0;itotal_fonts) ++ for(i=0;itotal_fonts;i++) { ++ if (cc->font_table[i].num==num) ++ return cc->font_table[i].name; ++ } ++ return NULL; + } + + +@@ -767,73 +720,87 @@ lookup_fontname (int num) { + *=======================================================================*/ + + void +-process_font_table (Word *w) ++process_font_table (const struct OutputContext *oc, Word *w) + { +- Word *w2; ++ Word *w2; ++ const struct unRTFOutputDevice *device = &oc->conversion->options->device; + +- CHECK_PARAM_NOT_NULL(w); ++ CHECK_PARAM_NOT_NULL(w); + +- if (safe_printf(0, op->fonttable_begin)) fprintf(stderr, TOO_MANY_ARGS, "fonttable_begin"); ++ if (safe_printf(device, 0, oc->personality->fonttable_begin)) fprintf(stderr, TOO_MANY_ARGS, "fonttable_begin"); + +- while (w) { +- int num; +- char name[BUFSIZ]; +- char *tmp; ++ while (w) { ++ int num; ++ char name[BUFSIZ]; ++ char *tmp; + +- if ((w2 = w->child)) { +- tmp = word_string(w2); +- if (!strncmp("\\f", tmp, 2)) { +- num = atoi(&tmp[2]); +- name[0] = 0; ++ if ((w2 = w->child)) { ++ tmp = word_string (oc->conversion, w2); ++ if (!strncmp("\\f", tmp, 2)) { ++ num = atoi(&tmp[2]); ++ name[0] = 0; + +- w2 = w2->next; +- while (w2) { +- tmp = word_string (w2); +- if (tmp && tmp[0] != '\\') { +- if (strlen(tmp) + strlen(name) > BUFSIZ - 1) { +- printf("Invalid font table entry\n"); +- name[0] = 0; +- } +- else +- strncat(name,tmp,sizeof(name) - strlen(name) - 1); +- } +- w2 = w2->next; +- } ++ w2 = w2->next; ++ while (w2) { ++ tmp = word_string (oc->conversion, w2); ++ if (tmp && tmp[0] != '\\') { ++ if (strlen(tmp) + strlen(name) > BUFSIZ - 1) { ++ printf("Invalid font table entry\n"); ++ name[0] = 0; ++ } ++ else ++ strncat(name,tmp,sizeof(name) - strlen(name) - 1); ++ } ++ w2 = w2->next; ++ } + +- /* Chop the gall-derned semicolon. */ +- if ((tmp = strchr(name, ';'))) +- *tmp = 0; ++ /* Chop the gall-derned semicolon. */ ++ if ((tmp = strchr(name, ';'))) ++ *tmp = 0; + +- font_table[total_fonts].num=num; +- font_table[total_fonts].name=my_strdup(name); +- if (safe_printf(0, assemble_string(op->fonttable_fontnr, num))) fprintf(stderr, TOO_MANY_ARGS, "fonttable_fontnr"); +- if (safe_printf(1, op->fonttable_fontname, name)) fprintf(stderr, TOO_MANY_ARGS, "fonttable_fontname"); +- total_fonts++; +- } +- } +- w=w->next; +- } ++ oc->conversion->font_table[oc->conversion->total_fonts].num=num; ++ oc->conversion->font_table[oc->conversion->total_fonts].name=my_strdup(oc->conversion, name); ++ if (safe_printf(device, 0, assemble_string(oc->personality->fonttable_fontnr, num))) fprintf(stderr, TOO_MANY_ARGS, "fonttable_fontnr"); ++ if (safe_printf(device, 1, oc->personality->fonttable_fontname, name)) fprintf(stderr, TOO_MANY_ARGS, "fonttable_fontname"); ++ oc->conversion->total_fonts++; ++ } ++ } ++ w=w->next; ++ } + +- if (safe_printf(0, op->fonttable_end)) fprintf(stderr, TOO_MANY_ARGS, "fonttable_end"); ++ if (safe_printf(device, 0, oc->personality->fonttable_end)) fprintf(stderr, TOO_MANY_ARGS, "fonttable_end"); + +- if (safe_printf(0, op->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); +- printf("font table contains %d fonts total",total_fonts); +- if (safe_printf(0, op->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); ++ if (safe_printf(device, 0, oc->personality->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); ++ printf("font table contains %d fonts total", oc->conversion->total_fonts); ++ if (safe_printf(device, 0, oc->personality->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); + +- if (debug_mode) { +- int i; ++ if (oc->conversion->options->debug_mode) { ++ int i; + +- if (safe_printf(0, op->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); +- printf("font table dump: \n"); +- for (i=0; ipersonality->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); ++ printf("font table dump: \n"); ++ for (i=0; i< oc->conversion->total_fonts; i++) { ++ printf(" font %d = %s\n", oc->conversion->font_table[i].num, ++ oc->conversion->font_table[i].name); ++ } + +- if (safe_printf(0, op->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); +- } ++ if (safe_printf(device, 0, oc->personality->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); ++ } + } + ++static void ++fonttable_free(struct ConversionContext *cc) ++{ ++ int i; ++ ++ for (i = 0; i < cc->total_fonts; i++) { ++ if (cc->font_table[i].name) { ++ my_free(cc->font_table[i].name); ++ cc->font_table[i].name = NULL; ++ } ++ } ++ cc->total_fonts = 0; ++} + + /*======================================================================== + * Name: process_index_entry +@@ -843,24 +810,25 @@ process_font_table (Word *w) + *=======================================================================*/ + + void +-process_index_entry (Word *w) ++process_index_entry (const struct OutputContext *oc, Word *w) + { +- Word *w2; ++ Word *w2; ++ const struct unRTFOutputDevice *device = &oc->conversion->options->device; + +- CHECK_PARAM_NOT_NULL(w); ++ CHECK_PARAM_NOT_NULL(w); + +- while(w) { +- if ((w2=w->child)) { +- char *str = word_string (w2); ++ while(w) { ++ if ((w2=w->child)) { ++ char *str = word_string (oc->conversion, w2); + +- if (debug_mode && str) { +- if (safe_printf(0, op->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); +- printf("index entry word: %s ", str); +- if (safe_printf(0, op->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); +- } +- } +- w=w->next; +- } ++ if (oc->conversion->options->debug_mode && str) { ++ if (safe_printf(device, 0, oc->personality->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); ++ printf("index entry word: %s ", str); ++ if (safe_printf(device, 0, oc->personality->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); ++ } ++ } ++ w=w->next; ++ } + } + + +@@ -872,27 +840,28 @@ process_index_entry (Word *w) + *=======================================================================*/ + + void +-process_toc_entry (Word *w, int include_page_num) ++process_toc_entry (const struct OutputContext *oc, Word *w, int include_page_num) + { +- Word *w2; ++ Word *w2; ++ const struct unRTFOutputDevice *device = &oc->conversion->options->device; + +- CHECK_PARAM_NOT_NULL(w); ++ CHECK_PARAM_NOT_NULL(w); + +- while(w) { +- if ((w2=w->child)) { +- char *str = word_string (w2); ++ while(w) { ++ if ((w2=w->child)) { ++ char *str = word_string (oc->conversion, w2); + +- if (debug_mode && str) { ++ if (oc->conversion->options->debug_mode && str) { + +- if (safe_printf(0, op->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); +- printf("toc %s entry word: %s ", +- include_page_num ? "page#":"no page#", +- str); +- if (safe_printf(0, op->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); +- } +- } +- w=w->next; +- } ++ if (safe_printf(device, 0, oc->personality->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); ++ printf("toc %s entry word: %s ", ++ include_page_num ? "page#":"no page#", ++ str); ++ if (safe_printf(device, 0, oc->personality->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); ++ } ++ } ++ w=w->next; ++ } + } + + +@@ -904,183 +873,173 @@ process_toc_entry (Word *w, int include_ + *=======================================================================*/ + + void +-process_info_group (Word *w) ++process_info_group (const struct OutputContext *oc, Word *w) + { +- Word *child; ++ Word *child; ++ const struct unRTFOutputDevice *device = &oc->conversion->options->device; + +- /* amaral - 0.19.2 */ +- /* CHECK_PARAM_NOT_NULL(w); */ +- if (!w) printf("AUTHOR'S COMMENT: \\info command is null!\n"); ++ /* amaral - 0.19.2 */ ++ /* CHECK_PARAM_NOT_NULL(w); */ ++ if (!w) printf("AUTHOR'S COMMENT: \\info command is null!\n"); + +- while(w) { +- child = w->child; +- if (child) { +- Word *w2; +- char *s; ++ while(w) { ++ child = w->child; ++ if (child) { ++ Word *w2; ++ char *s; + +- s = word_string(child); ++ s = word_string (oc->conversion, child); + +- if (!inline_mode) { +- if (!strcmp("\\title", s)) { ++ if (!oc->conversion->options->inline_mode) { ++ if (!strcmp("\\title", s)) { + +- if (safe_printf(0, op->document_title_begin)) fprintf(stderr, TOO_MANY_ARGS, "document_title_begin"); +- w2=child->next; +- while (w2) { +- char *s2 = word_string(w2); +- if (s2[0] != '\\') +- { +- print_with_special_exprs (s2); +- } +- else +- { +- if (s2[1] == '\'') +- { +- int ch = h2toi (&s2[2]); ++ if (safe_printf(device, 0, oc->personality->document_title_begin)) fprintf(stderr, TOO_MANY_ARGS, "document_title_begin"); ++ w2=child->next; ++ while (w2) { ++ char *s2 = word_string (oc->conversion, w2); ++ if (s2[0] != '\\') ++ { ++ print_with_special_exprs (oc, s2); ++ } ++ else ++ { ++ if (s2[1] == '\'') ++ { ++ int ch = h2toi (&s2[2]); + +- char *s3; +- s3 = op_translate_char (op, desc, ch); +- if (!s3 || !*s3) +- { +- if (safe_printf(0, op->comment_begin)) +- fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); +- printf("char 0x%02x",ch); +- if (safe_printf(0, op->comment_end)) +- fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); +- } +- else +- { +- if (op->word_begin) +- if (safe_printf(0, op->word_begin)) +- fprintf(stderr, TOO_MANY_ARGS, "word_begin"); +- printf("%s", s3); +- if (op->word_end) +- if (safe_printf(0, op->word_end)) +- fprintf(stderr, TOO_MANY_ARGS, "word_end"); +- } +- } +- } ++ char *s3; ++ s3 = op_translate_char (oc->conversion, oc->personality, ch); ++ if (!s3 || !*s3) ++ { ++ if (safe_printf(device, 0, oc->personality->comment_begin)) ++ fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); ++ printf("char 0x%02x",ch); ++ if (safe_printf(device, 0, oc->personality->comment_end)) ++ fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); ++ } ++ else ++ { ++ if (oc->personality->word_begin) ++ if (safe_printf(device, 0, oc->personality->word_begin)) ++ fprintf(stderr, TOO_MANY_ARGS, "word_begin"); ++ printf("%s", s3); ++ if (oc->personality->word_end) ++ if (safe_printf(device, 0, oc->personality->word_end)) ++ fprintf(stderr, TOO_MANY_ARGS, "word_end"); ++ } ++ } ++ } + +- w2 = w2->next; +- } +- if (safe_printf(0, op->document_title_end)) fprintf(stderr, TOO_MANY_ARGS, "document_title_end"); +- } +- else if (!strcmp("\\keywords", s)) { +- if (safe_printf(0, op->document_keywords_begin)) fprintf(stderr, TOO_MANY_ARGS, "document_keywords_begin"); +- w2=child->next; +- while (w2) { +- char *s2 = word_string(w2); +- if (s2[0] != '\\') +- printf("%s,", s2); +- w2 = w2->next; +- } +- if (safe_printf(0, op->document_keywords_end)) fprintf(stderr, TOO_MANY_ARGS, "document_keywords_end"); +- } +- else if (!strcmp("\\author", s)) { +- if (safe_printf(0, op->document_author_begin)) fprintf(stderr, TOO_MANY_ARGS, "document_author_begin"); +- w2=child->next; +- while (w2) { +- char *s2 = word_string(w2); +- if (s2[0] != '\\') +- printf("%s", s2); +- w2 = w2->next; +- } +- if (safe_printf(0, op->document_author_end)) fprintf(stderr, TOO_MANY_ARGS, "document_author_end"); +- } +- else if (!strcmp("\\comment", s)) { +- if (safe_printf(0, op->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); +- printf("comments: "); +- w2=child->next; +- while (w2) { +- char *s2 = word_string(w2); +- if (s2[0] != '\\') +- printf("%s", s2); +- w2 = w2->next; +- } +- if (safe_printf(0, op->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); +- } +- else if (!strncmp("\\nofpages", s, 9)) { +- if (safe_printf(0, op->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); +- printf("total pages: %s",&s[9]); +- if (safe_printf(0, op->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); +- } +- else if (!strncmp("\\nofwords", s, 9)) { +- if (safe_printf(0, op->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); +- printf("total words: %s",&s[9]); +- if (safe_printf(0, op->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); +- } +- else if (!strncmp("\\nofchars", s, 9) && isdigit(s[9])) { +- if (safe_printf(0, op->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); +- printf("total chars: %s",&s[9]); +- if (safe_printf(0, op->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); +- } +- else if (!strcmp("\\creatim", s)) { +- if (safe_printf(0, op->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); +- printf("creation date: "); +- if (child->next) word_dump_date (child->next); +- if (safe_printf(0, op->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); +- } +- else if (!strcmp("\\printim", s)) { +- if (safe_printf(0, op->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); +- printf("last printed: "); +- if (child->next) word_dump_date (child->next); +- if (safe_printf(0, op->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); +- } +- else if (!strcmp("\\buptim", s)) { +- if (safe_printf(0, op->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); +- printf("last backup: "); +- if (child->next) word_dump_date (child->next); +- if (safe_printf(0, op->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); +- } +- else if (!strcmp("\\revtim", s)) { +- if (safe_printf(0, op->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); +- printf("revision date: "); +- if (child->next) word_dump_date (child->next); +- if (safe_printf(0, op->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); +- } +- } ++ w2 = w2->next; ++ } ++ if (safe_printf(device, 0, oc->personality->document_title_end)) fprintf(stderr, TOO_MANY_ARGS, "document_title_end"); ++ } ++ else if (!strcmp("\\keywords", s)) { ++ if (safe_printf(device, 0, oc->personality->document_keywords_begin)) fprintf(stderr, TOO_MANY_ARGS, "document_keywords_begin"); ++ w2=child->next; ++ while (w2) { ++ char *s2 = word_string (oc->conversion, w2); ++ if (s2[0] != '\\') ++ printf("%s,", s2); ++ w2 = w2->next; ++ } ++ if (safe_printf(device, 0, oc->personality->document_keywords_end)) fprintf(stderr, TOO_MANY_ARGS, "document_keywords_end"); ++ } ++ else if (!strcmp("\\author", s)) { ++ if (safe_printf(device, 0, oc->personality->document_author_begin)) fprintf(stderr, TOO_MANY_ARGS, "document_author_begin"); ++ w2=child->next; ++ while (w2) { ++ char *s2 = word_string (oc->conversion, w2); ++ if (s2[0] != '\\') ++ printf("%s", s2); ++ w2 = w2->next; ++ } ++ if (safe_printf(device, 0, oc->personality->document_author_end)) fprintf(stderr, TOO_MANY_ARGS, "document_author_end"); ++ } ++ else if (!strcmp("\\comment", s)) { ++ if (safe_printf(device, 0, oc->personality->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); ++ printf("comments: "); ++ w2=child->next; ++ while (w2) { ++ char *s2 = word_string (oc->conversion, w2); ++ if (s2[0] != '\\') ++ printf("%s", s2); ++ w2 = w2->next; ++ } ++ if (safe_printf(device, 0, oc->personality->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); ++ } ++ else if (!strncmp("\\nofpages", s, 9)) { ++ if (safe_printf(device, 0, oc->personality->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); ++ printf("total pages: %s",&s[9]); ++ if (safe_printf(device, 0, oc->personality->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); ++ } ++ else if (!strncmp("\\nofwords", s, 9)) { ++ if (safe_printf(device, 0, oc->personality->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); ++ printf("total words: %s",&s[9]); ++ if (safe_printf(device, 0, oc->personality->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); ++ } ++ else if (!strncmp("\\nofchars", s, 9) && isdigit(s[9])) { ++ if (safe_printf(device, 0, oc->personality->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); ++ printf("total chars: %s",&s[9]); ++ if (safe_printf(device, 0, oc->personality->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); ++ } ++ else if (!strcmp("\\creatim", s)) { ++ if (safe_printf(device, 0, oc->personality->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); ++ printf("creation date: "); ++ if (child->next) word_dump_date (oc->conversion, child->next); ++ if (safe_printf(device, 0, oc->personality->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); ++ } ++ else if (!strcmp("\\printim", s)) { ++ if (safe_printf(device, 0, oc->personality->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); ++ printf("last printed: "); ++ if (child->next) word_dump_date (oc->conversion, child->next); ++ if (safe_printf(device, 0, oc->personality->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); ++ } ++ else if (!strcmp("\\buptim", s)) { ++ if (safe_printf(device, 0, oc->personality->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); ++ printf("last backup: "); ++ if (child->next) word_dump_date (oc->conversion, child->next); ++ if (safe_printf(device, 0, oc->personality->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); ++ } ++ else if (!strcmp("\\revtim", s)) { ++ if (safe_printf(device, 0, oc->personality->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); ++ printf("revision date: "); ++ if (child->next) word_dump_date (oc->conversion, child->next); ++ if (safe_printf(device, 0, oc->personality->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); ++ } ++ } + +- /* Irregardless of whether we're in inline mode, +- * we want to process the following. +- */ +- if (!strcmp("\\hlinkbase", s)) { +- char *linkstr = NULL; ++ /* Irregardless of whether we're in inline mode, ++ * we want to process the following. ++ */ ++ if (!strcmp("\\hlinkbase", s)) { ++ char *linkstr = NULL; + +- if (safe_printf(0, op->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); +- printf("hyperlink base: "); +- if (child->next) { +- Word *nextword = child->next; ++ if (safe_printf(device, 0, oc->personality->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); ++ printf("hyperlink base: "); ++ if (child->next) { ++ Word *nextword = child->next; + +- if (nextword) +- linkstr=word_string (nextword); +- } ++ if (nextword) ++ linkstr=word_string (oc->conversion, nextword); ++ } + +- if (linkstr) +- printf("%s", linkstr); +- else +- printf("(none)"); +- if (safe_printf(0, op->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); ++ if (linkstr) ++ printf("%s", linkstr); ++ else ++ printf("(none)"); ++ if (safe_printf(device, 0, oc->personality->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); + +- /* Store the pointer, it will remain good. */ +- hyperlink_base = linkstr; +- } +- } +- w = w->next; +- } ++ /* Store the pointer, it will remain good. */ ++ oc->conversion->hyperlink_base = linkstr; ++ } ++ } ++ w = w->next; ++ } + } + + /*-------------------------------------------------------------------*/ + +-/* RTF color table colors are RGB */ +- +-typedef struct { +- unsigned char r,g,b; +-} Color; +- +-#define MAX_COLORS (1024) +-static Color color_table[MAX_COLORS]; +-static int total_colors=0; +- +- + /*======================================================================== + * Name: process_color_table + * Purpose: Processes the color table of an RTF file. +@@ -1089,59 +1048,60 @@ static int total_colors=0; + *=======================================================================*/ + + void +-process_color_table (Word *w) ++process_color_table (const struct OutputContext *oc, Word *w) + { +- int r,g,b; ++ int r,g,b; ++ const struct unRTFOutputDevice *device = &oc->conversion->options->device; + +- CHECK_PARAM_NOT_NULL(w); ++ CHECK_PARAM_NOT_NULL(w); + +- /* Sometimes, RTF color tables begin with a semicolon, +- * i.e. an empty color entry. This seems to indicate that color 0 +- * will not be used, so here I set it to black. +- */ +- r=g=b=0; ++ /* Sometimes, RTF color tables begin with a semicolon, ++ * i.e. an empty color entry. This seems to indicate that color 0 ++ * will not be used, so here I set it to black. ++ */ ++ r=g=b=0; + +- while(w) { +- char *s = word_string (w); ++ while(w) { ++ char *s = word_string (oc->conversion, w); + +- if (!strncmp("\\red",s,4)) { +- r = atoi(&s[4]); +- while(r>255) r>>=8; +- } +- else if (!strncmp("\\green",s,6)) { +- g = atoi(&s[6]); +- while(g>255) g>>=8; +- } +- else if (!strncmp("\\blue",s,5)) { +- b = atoi(&s[5]); +- while(b>255) b>>=8; +- } +- else +- /* If we find the semicolon which denotes the end of +- * a color entry then store the color, even if we don't +- * have all of it. +- */ +- if (!strcmp (";", s)) { +- color_table[total_colors].r = r; +- color_table[total_colors].g = g; +- color_table[total_colors++].b = b; +- if (debug_mode) { +- if (safe_printf(0, op->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); +- printf("storing color entry %d: %02x%02x%02x", +- total_colors-1, r,g,b); +- if (safe_printf(0, op->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); +- } +- r=g=b=0; +- } ++ if (!strncmp("\\red",s,4)) { ++ r = atoi(&s[4]); ++ while(r>255) r>>=8; ++ } ++ else if (!strncmp("\\green",s,6)) { ++ g = atoi(&s[6]); ++ while(g>255) g>>=8; ++ } ++ else if (!strncmp("\\blue",s,5)) { ++ b = atoi(&s[5]); ++ while(b>255) b>>=8; ++ } ++ else ++ /* If we find the semicolon which denotes the end of ++ * a color entry then store the color, even if we don't ++ * have all of it. ++ */ ++ if (!strcmp (";", s)) { ++ oc->conversion->color_table[oc->conversion->total_colors].r = r; ++ oc->conversion->color_table[oc->conversion->total_colors].g = g; ++ oc->conversion->color_table[oc->conversion->total_colors++].b = b; ++ if (oc->conversion->options->debug_mode) { ++ if (safe_printf(device, 0, oc->personality->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); ++ printf("storing color entry %d: %02x%02x%02x", ++ oc->conversion->total_colors-1, r,g,b); ++ if (safe_printf(device, 0, oc->personality->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); ++ } ++ r=g=b=0; ++ } + +- w=w->next; +- } ++ w=w->next; ++ } + +- if (debug_mode) { +- if (safe_printf(0, op->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); +- printf("color table had %d entries -->\n", total_colors); +- if (safe_printf(0, op->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); +- } ++ if (oc->conversion->options->debug_mode) { ++ if (safe_printf(device, 0, oc->personality->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); ++ printf("color table had %d entries -->\n", oc->conversion->total_colors); ++ if (safe_printf(device, 0, oc->personality->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); ++ } + } + + /*======================================================================== +@@ -1152,21 +1112,21 @@ process_color_table (Word *w) + *=======================================================================*/ + + static int +-cmd_cf (Word *w, int align, char has_param, int num) { +- char str[40]; ++cmd_cf (const struct OutputContext *oc, Word *w, int align, char has_param, int num) { ++ char str[40]; + +- if (!has_param || num>=total_colors) { +- warning_handler ("font color change attempted is invalid"); +- } +- else +- { +- sprintf(str,"#%02x%02x%02x", +- color_table[num].r, +- color_table[num].g, +- color_table[num].b); +- attr_push(ATTR_FOREGROUND,str); +- } +- return FALSE; ++ if (!has_param || num>=oc->conversion->total_colors) { ++ warning_handler ("font color change attempted is invalid"); ++ } ++ else ++ { ++ sprintf(str,"#%02x%02x%02x", ++ oc->conversion->color_table[num].r, ++ oc->conversion->color_table[num].g, ++ oc->conversion->color_table[num].b); ++ attr_push(ATTR_FOREGROUND,str, oc); ++ } ++ return FALSE; + } + + +@@ -1179,21 +1139,21 @@ cmd_cf (Word *w, int align, char has_par + *=======================================================================*/ + + static int +-cmd_cb (Word *w, int align, char has_param, int num) { +- char str[40]; ++cmd_cb (const struct OutputContext *oc, Word *w, int align, char has_param, int num) { ++ char str[40]; + +- if (!has_param || num>=total_colors) { +- warning_handler ("font color change attempted is invalid"); +- } +- else +- { +- sprintf(str,"#%02x%02x%02x", +- color_table[num].r, +- color_table[num].g, +- color_table[num].b); +- attr_push(ATTR_BACKGROUND,str); +- } +- return FALSE; ++ if (!has_param || num>=oc->conversion->total_colors) { ++ warning_handler ("font color change attempted is invalid"); ++ } ++ else ++ { ++ sprintf(str,"#%02x%02x%02x", ++ oc->conversion->color_table[num].r, ++ oc->conversion->color_table[num].g, ++ oc->conversion->color_table[num].b); ++ attr_push(ATTR_BACKGROUND,str, oc); ++ } ++ return FALSE; + } + + +@@ -1204,18 +1164,18 @@ cmd_cb (Word *w, int align, char has_par + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + static int +-cmd_fs (Word *w, int align, char has_param, int points) { +- char str[20]; ++cmd_fs (const struct OutputContext *oc, Word *w, int align, char has_param, int points) { ++ char str[20]; + +- if (!has_param) return FALSE; ++ if (!has_param) return FALSE; + +- /* Note, fs20 means 10pt */ +- points /= 2; ++ /* Note, fs20 means 10pt */ ++ points /= 2; + +- sprintf(str,"%d",points); +- attr_push(ATTR_FONTSIZE,str); ++ sprintf(str,"%d",points); ++ attr_push(ATTR_FONTSIZE,str, oc); + +- return FALSE; ++ return FALSE; + } + + +@@ -1229,95 +1189,99 @@ cmd_fs (Word *w, int align, char has_par + *=======================================================================*/ + + static int +-cmd_field (Word *w, int align, char has_param, int num) { +- Word *child; ++cmd_field (const struct OutputContext *oc, Word *w, int align, char has_param, int num) { ++ Word *child; ++ const struct unRTFOutputDevice *device = &oc->conversion->options->device; + +- CHECK_PARAM_NOT_NULL(w); ++ CHECK_PARAM_NOT_NULL(w); + +- while(w) { +- child = w->child; +- if (child) { +- Word *w2; +- char *s; ++ while(w) { ++ child = w->child; ++ if (child) { ++ Word *w2; ++ char *s; + +- s = word_string(child); ++ s = word_string (oc->conversion, child); + #if 1 /* daved experimenting with fldrslt */ +- if(!strcmp("\\fldrslt", s)) +- return FALSE; ++ if(!strcmp("\\fldrslt", s)) ++ return FALSE; + #endif + + +- if (!strcmp("\\*", s)) +- { +- w2=child->next; +- while (w2) +- { +- char *s2 = word_string(w2); +- if (s2 && !strcmp("\\fldinst", s2)) +- { +- Word *w3; +- char *s; +- char *s4; +- Word *w4; +- w3=w2->next; +- s = word_string(w3); +- if (s && !strcmp(s, "SYMBOL") ) +- { +- w4=w3->next; +- while(w4 && !strcmp(word_string(w4), " ")) +- w4 = w4->next; +- s4 = word_string(w4); +- if (s4) +- { +- int char_num; +- char *string; +- my_iconv_t d; +- char_num = atoi(s4); ++ if (!strcmp("\\*", s)) ++ { ++ w2=child->next; ++ while (w2) ++ { ++ char *s2 = word_string (oc->conversion, w2); ++ if (s2 && !strcmp("\\fldinst", s2)) ++ { ++ Word *w3; ++ char *s; ++ char *s4; ++ Word *w4; ++ w3=w2->next; ++ s = word_string (oc->conversion, w3); ++ if (s && !strcmp(s, "SYMBOL") ) ++ { ++ w4=w3->next; ++ while(w4 && !strcmp(word_string (oc->conversion, w4), " ")) ++ w4 = w4->next; ++ s4 = word_string (oc->conversion, w4); ++ if (s4) ++ { ++ int char_num; ++ char *string; ++ my_iconv_t d, olddesc; ++ char_num = atoi(s4); + +- if (my_iconv_is_valid((d = my_iconv_open("utf8", FONT_SYMBOL)))) +- { +- string = op_translate_char (op, d, char_num); +- if (string != NULL) +- printf("%s", string); +- my_iconv_close(d); +- } +- else +- fprintf(stderr, "unrtf: Error in translation SYMBOL character\n"); +- } +- } +- while (w3 && !w3->child) { +- w3=w3->next; +- } +- if (w3) w3=w3->child; +- while (w3) +- { +- char *s3=word_string(w3); +- if (s3 && !strcmp("HYPERLINK",s3)) { +- Word *w4; +- char *s4; +- w4=w3->next; +- while (w4 && !strcmp(" ", word_string(w4))) +- w4=w4->next; +- if (w4) { +- s4=word_string(w4); +- if (safe_printf(0, op->hyperlink_begin)) fprintf(stderr, TOO_MANY_ARGS, "hyperlink_begin"); +- printf("%s", s4); +- if (safe_printf(0, op->hyperlink_end)) fprintf(stderr, TOO_MANY_ARGS, "hyperlink_end"); +- return TRUE; +- } ++ if (my_iconv_is_valid((d = my_iconv_open(oc->conversion, "utf8", FONT_SYMBOL)))) ++ { ++ olddesc = oc->conversion->desc; ++ oc->conversion->desc = d; ++ string = op_translate_char (oc->conversion, oc->personality/* , d */, char_num); ++ if (string != NULL) ++ printf("%s", string); ++ my_iconv_close(d); ++ oc->conversion->desc = olddesc; ++ } ++ else ++ fprintf(stderr, "unrtf: Error in translation SYMBOL character\n"); ++ } ++ } ++ while (w3 && !w3->child) { ++ w3=w3->next; ++ } ++ if (w3) w3=w3->child; ++ while (w3) ++ { ++ char *s3=word_string (oc->conversion, w3); ++ if (s3 && !strcmp("HYPERLINK",s3)) { ++ Word *w4; ++ char *s4; ++ w4=w3->next; ++ while (w4 && !strcmp(" ", word_string (oc->conversion, w4))) ++ w4=w4->next; ++ if (w4) { ++ s4=word_string (oc->conversion, w4); ++ if (safe_printf(device, 0, oc->personality->hyperlink_begin)) fprintf(stderr, TOO_MANY_ARGS, "hyperlink_begin"); ++ printf("%s", s4); ++ if (safe_printf(device, 0, oc->personality->hyperlink_end)) fprintf(stderr, TOO_MANY_ARGS, "hyperlink_end"); ++ return TRUE; ++ } + +- } +- w3=w3->next; +- } +- } +- w2 = w2->next; +- } ++ } ++ w3=w3->next; ++ } ++ } ++ w2 = w2->next; ++ } + +- } +- } +- w=w->next; +- } +- return TRUE; ++ } ++ } ++ w=w->next; ++ } ++ return TRUE; + } + + /*======================================================================== +@@ -1327,59 +1291,60 @@ cmd_field (Word *w, int align, char has_ + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + static int +-cmd_f (Word *w, int align, char has_param, int num) { +- char *name; ++cmd_f (const struct OutputContext *oc, Word *w, int align, char has_param, int num) { ++ char *name; ++ const struct unRTFOutputDevice *device = &oc->conversion->options->device; + +- /* no param exit early XX */ +- if (!has_param) +- return FALSE; ++ /* no param exit early XX */ ++ if (!has_param) ++ return FALSE; + +- name = lookup_fontname(num); +- if (!name) { +- if (safe_printf(0, op->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); +- printf("invalid font number %d",num); +- if (safe_printf(0, op->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); +- } else { +- if (op->fonttable_begin != NULL) +- { +- name = my_malloc(12); +- sprintf(name, "%d", num); +- } ++ name = lookup_fontname(oc->conversion, num); ++ if (!name) { ++ if (safe_printf(device, 0, oc->personality->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); ++ printf("invalid font number %d",num); ++ if (safe_printf(device, 0, oc->personality->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); ++ } else { ++ if (oc->personality->fonttable_begin != NULL) ++ { ++ name = my_malloc(12); ++ sprintf(name, "%d", num); ++ } + #if 1 /* daved 0.21.1 */ +- /* we are going to output entities, so should not output font */ +- if(strstr(name,"Symbol") == NULL) ++ /* we are going to output entities, so should not output font */ ++ if(strstr(name,"Symbol") == NULL) + #endif +- attr_push(ATTR_FONTFACE,name); +- if (strstr(name,"Symbol") != NULL) +- { +- if (!my_iconv_is_valid(desc2)) +- desc2 = desc; +- else +- my_iconv_close(desc); ++ attr_push(ATTR_FONTFACE,name, oc); ++ if (strstr(name,"Symbol") != NULL) ++ { ++ if (!my_iconv_is_valid(oc->conversion->desc2)) ++ oc->conversion->desc2 = oc->conversion->desc; ++ else ++ my_iconv_close(oc->conversion->desc); + +- desc = my_iconv_open("UTF-8", FONT_SYMBOL); +- } +- else if (strstr(name,"Greek") != NULL) +- { +- if (!my_iconv_is_valid(desc2)) +- desc2 = desc; +- else +- my_iconv_close(desc); ++ oc->conversion->desc = my_iconv_open(oc->conversion, "UTF-8", FONT_SYMBOL); ++ } ++ else if (strstr(name,"Greek") != NULL) ++ { ++ if (!my_iconv_is_valid(oc->conversion->desc2)) ++ oc->conversion->desc2 = oc->conversion->desc; ++ else ++ my_iconv_close(oc->conversion->desc); + +- desc = my_iconv_open("UTF-8", FONT_GREEK); +- } +- else +- { +- if (my_iconv_is_valid(desc2)) +- { +- desc = my_iconv_close(desc); +- desc = desc2; +- my_iconv_t_make_invalid(&desc2); +- } +- } +- } ++ oc->conversion->desc = my_iconv_open(oc->conversion, "UTF-8", FONT_GREEK); ++ } ++ else ++ { ++ if (my_iconv_is_valid(oc->conversion->desc2)) ++ { ++ oc->conversion->desc = my_iconv_close(oc->conversion->desc); ++ oc->conversion->desc = oc->conversion->desc2; ++ my_iconv_t_make_invalid(&oc->conversion->desc2); ++ } ++ } ++ } + +- return FALSE; ++ return FALSE; + } + + +@@ -1391,22 +1356,22 @@ cmd_f (Word *w, int align, char has_para + *=======================================================================*/ + + static int +-cmd_highlight (Word *w, int align, char has_param, int num) ++cmd_highlight (const struct OutputContext *oc, Word *w, int align, char has_param, int num) + { +- char str[40]; ++ char str[40]; + +- if (!has_param || num>=total_colors) { +- warning_handler ("font background color change attempted is invalid"); +- } +- else +- { +- sprintf(str,"#%02x%02x%02x", +- color_table[num].r, +- color_table[num].g, +- color_table[num].b); +- attr_push(ATTR_BACKGROUND,str); +- } +- return FALSE; ++ if (!has_param || num>=oc->conversion->total_colors) { ++ warning_handler ("font background color change attempted is invalid"); ++ } ++ else ++ { ++ sprintf(str,"#%02x%02x%02x", ++ oc->conversion->color_table[num].r, ++ oc->conversion->color_table[num].g, ++ oc->conversion->color_table[num].b); ++ attr_push(ATTR_BACKGROUND,str, oc); ++ } ++ return FALSE; + } + + +@@ -1419,22 +1384,24 @@ cmd_highlight (Word *w, int align, char + *=======================================================================*/ + + static int +-cmd_tab (Word *w, int align, char has_param, int param) ++cmd_tab (const struct OutputContext *oc, Word *w, int align, char has_param, int param) + { +- /* Tab presents a genuine problem +- * since some output formats don't have +- * an equivalent. As a kludge fix, I shall +- * assume the font is fixed width and that +- * the tabstops are 8 characters apart. +- */ +- int need= 8-(total_chars_this_line%8); +- total_chars_this_line += need; +- while(need>0) { +- if (safe_printf(0, op->forced_space)) fprintf(stderr, TOO_MANY_ARGS, "forced_space"); +- need--; +- } +- printf("\n"); +- return FALSE; ++ /* Tab presents a genuine problem ++ * since some output formats don't have ++ * an equivalent. As a kludge fix, I shall ++ * assume the font is fixed width and that ++ * the tabstops are 8 characters apart. ++ */ ++ int need= 8-(oc->conversion->total_chars_this_line%8); ++ const struct unRTFOutputDevice *device = &oc->conversion->options->device; ++ ++ oc->conversion->total_chars_this_line += need; ++ while(need>0) { ++ if (safe_printf(device, 0, oc->personality->forced_space)) fprintf(stderr, TOO_MANY_ARGS, "forced_space"); ++ need--; ++ } ++ printf("\n"); ++ return FALSE; + } + + +@@ -1446,9 +1413,9 @@ cmd_tab (Word *w, int align, char has_pa + *=======================================================================*/ + + static int +-cmd_plain (Word *w, int align, char has_param, int param) { +- attr_pop_all(); +- return FALSE; ++cmd_plain (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ attr_pop_all(oc); ++ return FALSE; + } + + +@@ -1459,9 +1426,9 @@ cmd_plain (Word *w, int align, char has_ + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + static int +-cmd_fnil (Word *w, int align, char has_param, int param) { +- attr_push(ATTR_FONTFACE,FONTNIL_STR); +- return FALSE; ++cmd_fnil (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ attr_push(ATTR_FONTFACE,FONTNIL_STR, oc); ++ return FALSE; + } + + +@@ -1473,9 +1440,9 @@ cmd_fnil (Word *w, int align, char has_p + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + static int +-cmd_froman (Word *w, int align, char has_param, int param) { +- attr_push(ATTR_FONTFACE,FONTROMAN_STR); +- return FALSE; ++cmd_froman (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ attr_push(ATTR_FONTFACE,FONTROMAN_STR, oc); ++ return FALSE; + } + + +@@ -1487,9 +1454,9 @@ cmd_froman (Word *w, int align, char has + *=======================================================================*/ + + static int +-cmd_fswiss (Word *w, int align, char has_param, int param) { +- attr_push(ATTR_FONTFACE,FONTSWISS_STR); +- return FALSE; ++cmd_fswiss (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ attr_push(ATTR_FONTFACE,FONTSWISS_STR, oc); ++ return FALSE; + } + + +@@ -1501,9 +1468,9 @@ cmd_fswiss (Word *w, int align, char has + *=======================================================================*/ + + static int +-cmd_fmodern (Word *w, int align, char has_param, int param) { +- attr_push(ATTR_FONTFACE,FONTMODERN_STR); +- return FALSE; ++cmd_fmodern (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ attr_push(ATTR_FONTFACE,FONTMODERN_STR, oc); ++ return FALSE; + } + + +@@ -1515,9 +1482,9 @@ cmd_fmodern (Word *w, int align, char ha + *=======================================================================*/ + + static int +-cmd_fscript (Word *w, int align, char has_param, int param) { +- attr_push(ATTR_FONTFACE,FONTSCRIPT_STR); +- return FALSE; ++cmd_fscript (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ attr_push(ATTR_FONTFACE,FONTSCRIPT_STR, oc); ++ return FALSE; + } + + /*======================================================================== +@@ -1528,9 +1495,9 @@ cmd_fscript (Word *w, int align, char ha + *=======================================================================*/ + + static int +-cmd_fdecor (Word *w, int align, char has_param, int param) { +- attr_push(ATTR_FONTFACE,FONTDECOR_STR); +- return FALSE; ++cmd_fdecor (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ attr_push(ATTR_FONTFACE,FONTDECOR_STR, oc); ++ return FALSE; + } + + /*======================================================================== +@@ -1541,9 +1508,9 @@ cmd_fdecor (Word *w, int align, char has + *=======================================================================*/ + + static int +-cmd_ftech (Word *w, int align, char has_param, int param) { +- attr_push(ATTR_FONTFACE,FONTTECH_STR); +- return FALSE; ++cmd_ftech (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ attr_push(ATTR_FONTFACE,FONTTECH_STR, oc); ++ return FALSE; + } + + /*======================================================================== +@@ -1554,16 +1521,16 @@ cmd_ftech (Word *w, int align, char has_ + *=======================================================================*/ + + static int +-cmd_expand (Word *w, int align, char has_param, int param) { +- char str[10]; +- if (has_param) { +- sprintf(str, "%d", param/4); +- if (!param) +- attr_pop(ATTR_EXPAND); +- else +- attr_push(ATTR_EXPAND, str); +- } +- return FALSE; ++cmd_expand (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ char str[10]; ++ if (has_param) { ++ sprintf(str, "%d", param/4); ++ if (!param) ++ attr_pop(ATTR_EXPAND, oc); ++ else ++ attr_push(ATTR_EXPAND, str, oc); ++ } ++ return FALSE; + } + + +@@ -1575,16 +1542,16 @@ cmd_expand (Word *w, int align, char has + *=======================================================================*/ + + static int +-cmd_emboss (Word *w, int align, char has_param, int param) { +- char str[10]; +- if (has_param && !param) +- attr_pop(ATTR_EMBOSS); +- else +- { +- sprintf(str, "%d", param); +- attr_push(ATTR_EMBOSS, str); +- } +- return FALSE; ++cmd_emboss (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ char str[10]; ++ if (has_param && !param) ++ attr_pop(ATTR_EMBOSS, oc); ++ else ++ { ++ sprintf(str, "%d", param); ++ attr_push(ATTR_EMBOSS, str, oc); ++ } ++ return FALSE; + } + + +@@ -1596,16 +1563,16 @@ cmd_emboss (Word *w, int align, char has + *=======================================================================*/ + + static int +-cmd_engrave (Word *w, int align, char has_param, int param) { +- char str[10]; +- if (has_param && !param) +- attr_pop(ATTR_ENGRAVE); +- else +- { +- sprintf(str, "%d", param); +- attr_push(ATTR_ENGRAVE, str); +- } +- return FALSE; ++cmd_engrave (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ char str[10]; ++ if (has_param && !param) ++ attr_pop(ATTR_ENGRAVE, oc); ++ else ++ { ++ sprintf(str, "%d", param); ++ attr_push(ATTR_ENGRAVE, str, oc); ++ } ++ return FALSE; + } + + /*======================================================================== +@@ -1616,12 +1583,12 @@ cmd_engrave (Word *w, int align, char ha + *=======================================================================*/ + + static int +-cmd_caps (Word *w, int align, char has_param, int param) { +- if (has_param && !param) +- attr_pop(ATTR_CAPS); +- else +- attr_push(ATTR_CAPS,NULL); +- return FALSE; ++cmd_caps (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ if (has_param && !param) ++ attr_pop(ATTR_CAPS, oc); ++ else ++ attr_push(ATTR_CAPS,NULL, oc); ++ return FALSE; + } + + +@@ -1632,12 +1599,12 @@ cmd_caps (Word *w, int align, char has_p + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + static int +-cmd_scaps (Word *w, int align, char has_param, int param) { +- if (has_param && !param) +- attr_pop(ATTR_SMALLCAPS); +- else +- attr_push(ATTR_SMALLCAPS,NULL); +- return FALSE; ++cmd_scaps (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ if (has_param && !param) ++ attr_pop(ATTR_SMALLCAPS, oc); ++ else ++ attr_push(ATTR_SMALLCAPS,NULL, oc); ++ return FALSE; + } + + +@@ -1648,12 +1615,14 @@ cmd_scaps (Word *w, int align, char has_ + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + static int +-cmd_bullet (Word *w, int align, char has_param, int param) { +- if (op->chars.bullet) { +- if (safe_printf(0, op->chars.bullet)) fprintf(stderr, TOO_MANY_ARGS, "chars.bullet"); +- ++total_chars_this_line; /* \tab */ +- } +- return FALSE; ++cmd_bullet (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ const struct unRTFOutputDevice *device = &oc->conversion->options->device; ++ ++ if (oc->personality->chars.bullet) { ++ if (safe_printf(device, 0, oc->personality->chars.bullet)) fprintf(stderr, TOO_MANY_ARGS, "chars.bullet"); ++ ++oc->conversion->total_chars_this_line; /* \tab */ ++ } ++ return FALSE; + } + + /*======================================================================== +@@ -1663,12 +1632,14 @@ cmd_bullet (Word *w, int align, char has + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + static int +-cmd_ldblquote (Word *w, int align, char has_param, int param) { +- if (op->chars.left_dbl_quote) { +- if (safe_printf(0, op->chars.left_dbl_quote)) fprintf(stderr, TOO_MANY_ARGS, "chars.left_dbl_quote"); +- ++total_chars_this_line; /* \tab */ +- } +- return FALSE; ++cmd_ldblquote (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ const struct unRTFOutputDevice *device = &oc->conversion->options->device; ++ ++ if (oc->personality->chars.left_dbl_quote) { ++ if (safe_printf(device, 0, oc->personality->chars.left_dbl_quote)) fprintf(stderr, TOO_MANY_ARGS, "chars.left_dbl_quote"); ++ ++oc->conversion->total_chars_this_line; /* \tab */ ++ } ++ return FALSE; + } + + +@@ -1680,12 +1651,14 @@ cmd_ldblquote (Word *w, int align, char + *=======================================================================*/ + + static int +-cmd_rdblquote (Word *w, int align, char has_param, int param) { +- if (op->chars.right_dbl_quote) { +- if (safe_printf(0, op->chars.right_dbl_quote)) fprintf(stderr, TOO_MANY_ARGS, "chars.right_dbl_quote"); +- ++total_chars_this_line; /* \tab */ +- } +- return FALSE; ++cmd_rdblquote (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ const struct unRTFOutputDevice *device = &oc->conversion->options->device; ++ ++ if (oc->personality->chars.right_dbl_quote) { ++ if (safe_printf(device, 0, oc->personality->chars.right_dbl_quote)) fprintf(stderr, TOO_MANY_ARGS, "chars.right_dbl_quote"); ++ ++oc->conversion->total_chars_this_line; /* \tab */ ++ } ++ return FALSE; + } + + +@@ -1696,12 +1669,14 @@ cmd_rdblquote (Word *w, int align, char + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + static int +-cmd_lquote (Word *w, int align, char has_param, int param) { +- if (op->chars.left_quote) { +- if (safe_printf(0, op->chars.left_quote)) fprintf(stderr, TOO_MANY_ARGS, "chars.left_quote"); +- ++total_chars_this_line; /* \tab */ +- } +- return FALSE; ++cmd_lquote (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ const struct unRTFOutputDevice *device = &oc->conversion->options->device; ++ ++ if (oc->personality->chars.left_quote) { ++ if (safe_printf(device, 0, oc->personality->chars.left_quote)) fprintf(stderr, TOO_MANY_ARGS, "chars.left_quote"); ++ ++oc->conversion->total_chars_this_line; /* \tab */ ++ } ++ return FALSE; + } + + +@@ -1713,12 +1688,14 @@ cmd_lquote (Word *w, int align, char has + *=======================================================================*/ + + static int +-cmd_nonbreaking_space (Word *w, int align, char has_param, int param) { +- if (op->chars.nonbreaking_space) { +- if (safe_printf(0, op->chars.nonbreaking_space)) fprintf(stderr, TOO_MANY_ARGS, "chars.nonbreaking_space"); +- ++total_chars_this_line; /* \tab */ +- } +- return FALSE; ++cmd_nonbreaking_space (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ const struct unRTFOutputDevice *device = &oc->conversion->options->device; ++ ++ if (oc->personality->chars.nonbreaking_space) { ++ if (safe_printf(device, 0, oc->personality->chars.nonbreaking_space)) fprintf(stderr, TOO_MANY_ARGS, "chars.nonbreaking_space"); ++ ++oc->conversion->total_chars_this_line; /* \tab */ ++ } ++ return FALSE; + } + + +@@ -1730,12 +1707,14 @@ cmd_nonbreaking_space (Word *w, int alig + *=======================================================================*/ + + static int +-cmd_nonbreaking_hyphen (Word *w, int align, char has_param, int param) { +- if (op->chars.nonbreaking_hyphen) { +- if (safe_printf(0, op->chars.nonbreaking_hyphen)) fprintf(stderr, TOO_MANY_ARGS, "chars.nonbreaking_hyphen"); +- ++total_chars_this_line; /* \tab */ +- } +- return FALSE; ++cmd_nonbreaking_hyphen (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ const struct unRTFOutputDevice *device = &oc->conversion->options->device; ++ ++ if (oc->personality->chars.nonbreaking_hyphen) { ++ if (safe_printf(device, 0, oc->personality->chars.nonbreaking_hyphen)) fprintf(stderr, TOO_MANY_ARGS, "chars.nonbreaking_hyphen"); ++ ++oc->conversion->total_chars_this_line; /* \tab */ ++ } ++ return FALSE; + } + + +@@ -1747,12 +1726,14 @@ cmd_nonbreaking_hyphen (Word *w, int ali + *=======================================================================*/ + + static int +-cmd_optional_hyphen (Word *w, int align, char has_param, int param) { +- if (op->chars.optional_hyphen) { +- if (safe_printf(0, op->chars.optional_hyphen)) fprintf(stderr, TOO_MANY_ARGS, "chars.optional_hyphen"); +- ++total_chars_this_line; /* \tab */ +- } +- return FALSE; ++cmd_optional_hyphen (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ const struct unRTFOutputDevice *device = &oc->conversion->options->device; ++ ++ if (oc->personality->chars.optional_hyphen) { ++ if (safe_printf(device, 0, oc->personality->chars.optional_hyphen)) fprintf(stderr, TOO_MANY_ARGS, "chars.optional_hyphen"); ++ ++oc->conversion->total_chars_this_line; /* \tab */ ++ } ++ return FALSE; + } + + +@@ -1763,12 +1744,14 @@ cmd_optional_hyphen (Word *w, int align, + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + static int +-cmd_emdash (Word *w, int align, char has_param, int param) { +- if (op->chars.emdash) { +- if (safe_printf(0, op->chars.emdash)) fprintf(stderr, TOO_MANY_ARGS, "chars.emdash"); +- ++total_chars_this_line; /* \tab */ +- } +- return FALSE; ++cmd_emdash (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ const struct unRTFOutputDevice *device = &oc->conversion->options->device; ++ ++ if (oc->personality->chars.emdash) { ++ if (safe_printf(device, 0, oc->personality->chars.emdash)) fprintf(stderr, TOO_MANY_ARGS, "chars.emdash"); ++ ++oc->conversion->total_chars_this_line; /* \tab */ ++ } ++ return FALSE; + } + + +@@ -1780,12 +1763,14 @@ cmd_emdash (Word *w, int align, char has + *=======================================================================*/ + + static int +-cmd_endash (Word *w, int align, char has_param, int param) { +- if (op->chars.endash) { +- if (safe_printf(0, op->chars.endash)) fprintf(stderr, TOO_MANY_ARGS, "chars.endash"); +- ++total_chars_this_line; /* \tab */ +- } +- return FALSE; ++cmd_endash (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ const struct unRTFOutputDevice *device = &oc->conversion->options->device; ++ ++ if (oc->personality->chars.endash) { ++ if (safe_printf(device, 0, oc->personality->chars.endash)) fprintf(stderr, TOO_MANY_ARGS, "chars.endash"); ++ ++oc->conversion->total_chars_this_line; /* \tab */ ++ } ++ return FALSE; + } + + +@@ -1797,12 +1782,14 @@ cmd_endash (Word *w, int align, char has + *=======================================================================*/ + + static int +-cmd_rquote (Word *w, int align, char has_param, int param) { +- if (op->chars.right_quote) { +- if (safe_printf(0, op->chars.right_quote)) fprintf(stderr, TOO_MANY_ARGS, "chars.right_quote"); +- ++total_chars_this_line; /* \tab */ +- } +- return FALSE; ++cmd_rquote (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ const struct unRTFOutputDevice *device = &oc->conversion->options->device; ++ ++ if (oc->personality->chars.right_quote) { ++ if (safe_printf(device, 0, oc->personality->chars.right_quote)) fprintf(stderr, TOO_MANY_ARGS, "chars.right_quote"); ++ ++oc->conversion->total_chars_this_line; /* \tab */ ++ } ++ return FALSE; + } + + +@@ -1813,12 +1800,14 @@ cmd_rquote (Word *w, int align, char has + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + static int +-cmd_par (Word *w, int align, char has_param, int param) { +- if (op->line_break) { +- if (safe_printf(0, op->line_break)) fprintf(stderr, TOO_MANY_ARGS, "line_break"); +- total_chars_this_line = 0; /* \tab */ +- } +- return FALSE; ++cmd_par (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ const struct unRTFOutputDevice *device = &oc->conversion->options->device; ++ ++ if (oc->personality->line_break) { ++ if (safe_printf(device, 0, oc->personality->line_break)) fprintf(stderr, TOO_MANY_ARGS, "line_break"); ++ oc->conversion->total_chars_this_line = 0; /* \tab */ ++ } ++ return FALSE; + } + + +@@ -1830,12 +1819,14 @@ cmd_par (Word *w, int align, char has_pa + *=======================================================================*/ + + static int +-cmd_line (Word *w, int align, char has_param, int param) { +- if (op->line_break) { +- if (safe_printf(0, op->line_break)) fprintf(stderr, TOO_MANY_ARGS, "line_break"); +- total_chars_this_line = 0; /* \tab */ +- } +- return FALSE; ++cmd_line (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ const struct unRTFOutputDevice *device = &oc->conversion->options->device; ++ ++ if (oc->personality->line_break) { ++ if (safe_printf(device, 0, oc->personality->line_break)) fprintf(stderr, TOO_MANY_ARGS, "line_break"); ++ oc->conversion->total_chars_this_line = 0; /* \tab */ ++ } ++ return FALSE; + } + + +@@ -1846,12 +1837,14 @@ cmd_line (Word *w, int align, char has_p + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_page (Word *w, int align, char has_param, int param) { +- if (op->page_break) { +- if (safe_printf(0, op->page_break)) fprintf(stderr, TOO_MANY_ARGS, "page_break"); +- total_chars_this_line = 0; /* \tab */ +- } +- return FALSE; ++static int cmd_page (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ const struct unRTFOutputDevice *device = &oc->conversion->options->device; ++ ++ if (oc->personality->page_break) { ++ if (safe_printf(device, 0, oc->personality->page_break)) fprintf(stderr, TOO_MANY_ARGS, "page_break"); ++ oc->conversion->total_chars_this_line = 0; /* \tab */ ++ } ++ return FALSE; + } + + +@@ -1862,9 +1855,9 @@ static int cmd_page (Word *w, int align, + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_intbl (Word *w, int align, char has_param, int param) { +- ++coming_pars_that_are_tabular; +- return FALSE; ++static int cmd_intbl (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ ++oc->conversion->coming_pars_that_are_tabular; ++ return FALSE; + } + + +@@ -1875,31 +1868,31 @@ static int cmd_intbl (Word *w, int align + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_ulnone (Word *w, int align, char has_param, int param) { +- int attr, more=TRUE; +- ++static int cmd_ulnone (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ int attr, more=TRUE; ++ + #ifdef BINARY_ATTRS +- attr_remove_underlining()) fprintf(stderr, TOO_MANY_ARGS, ); ++ attr_remove_underlining() fprintf(stderr, TOO_MANY_ARGS, ); + #else +- do { +- attr = attr_read(); +- if (attr==ATTR_UNDERLINE || +- attr==ATTR_DOT_UL || +- attr==ATTR_DASH_UL || +- attr==ATTR_DOT_DASH_UL || +- attr==ATTR_2DOT_DASH_UL || +- attr==ATTR_WORD_UL || +- attr==ATTR_WAVE_UL || +- attr==ATTR_THICK_UL || +- attr==ATTR_DOUBLE_UL) +- { +- if (!attr_pop(ATTR_UNDERLINE)) +- ; +- } else +- more=FALSE; +- } while(more); ++ do { ++ attr = attr_read(oc->conversion); ++ if (attr==ATTR_UNDERLINE || ++ attr==ATTR_DOT_UL || ++ attr==ATTR_DASH_UL || ++ attr==ATTR_DOT_DASH_UL || ++ attr==ATTR_2DOT_DASH_UL || ++ attr==ATTR_WORD_UL || ++ attr==ATTR_WAVE_UL || ++ attr==ATTR_THICK_UL || ++ attr==ATTR_DOUBLE_UL) ++ { ++ if (!attr_pop(ATTR_UNDERLINE, oc)) ++ ; ++ } else ++ more=FALSE; ++ } while(more); + #endif +- return FALSE; ++ return FALSE; + } + + /*======================================================================== +@@ -1909,13 +1902,13 @@ static int cmd_ulnone (Word *w, int alig + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_ul (Word *w, int align, char has_param, int param) { +- if (has_param && param == 0) { +- cmd_ulnone(w, align, has_param, param); +- } else { +- attr_push(ATTR_UNDERLINE, NULL); +- } +- return FALSE; ++static int cmd_ul (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ if (has_param && param == 0) { ++ cmd_ulnone(oc, w, align, has_param, param); ++ } else { ++ attr_push(ATTR_UNDERLINE, NULL, oc); ++ } ++ return FALSE; + } + + /*======================================================================== +@@ -1925,9 +1918,9 @@ static int cmd_ul (Word *w, int align, c + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_uld (Word *w, int align, char has_param, int param) { +- attr_push(ATTR_DOUBLE_UL, NULL); +- return FALSE; ++static int cmd_uld (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ attr_push(ATTR_DOUBLE_UL, NULL, oc); ++ return FALSE; + } + + /*======================================================================== +@@ -1937,9 +1930,9 @@ static int cmd_uld (Word *w, int align, + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_uldb (Word *w, int align, char has_param, int param) { +- attr_push(ATTR_DOT_UL, NULL); +- return FALSE; ++static int cmd_uldb (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ attr_push(ATTR_DOT_UL, NULL, oc); ++ return FALSE; + } + + +@@ -1950,9 +1943,9 @@ static int cmd_uldb (Word *w, int align, + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_uldash (Word *w, int align, char has_param, int param) { +- attr_push(ATTR_DASH_UL, NULL); +- return FALSE; ++static int cmd_uldash (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ attr_push(ATTR_DASH_UL, NULL, oc); ++ return FALSE; + } + + +@@ -1963,9 +1956,9 @@ static int cmd_uldash (Word *w, int alig + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_uldashd (Word *w, int align, char has_param, int param) { +- attr_push(ATTR_DOT_DASH_UL,NULL); +- return FALSE; ++static int cmd_uldashd (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ attr_push(ATTR_DOT_DASH_UL,NULL, oc); ++ return FALSE; + } + + +@@ -1976,9 +1969,9 @@ static int cmd_uldashd (Word *w, int ali + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_uldashdd (Word *w, int align, char has_param, int param) { +- attr_push(ATTR_2DOT_DASH_UL,NULL); +- return FALSE; ++static int cmd_uldashdd (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ attr_push(ATTR_2DOT_DASH_UL,NULL, oc); ++ return FALSE; + } + + +@@ -1989,9 +1982,9 @@ static int cmd_uldashdd (Word *w, int al + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_ulw (Word *w, int align, char has_param, int param) { +- attr_push(ATTR_WORD_UL,NULL); +- return FALSE; ++static int cmd_ulw (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ attr_push(ATTR_WORD_UL,NULL, oc); ++ return FALSE; + } + + +@@ -2002,9 +1995,9 @@ static int cmd_ulw (Word *w, int align, + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_ulth (Word *w, int align, char has_param, int param) { +- attr_push(ATTR_THICK_UL,NULL); +- return FALSE; ++static int cmd_ulth (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ attr_push(ATTR_THICK_UL,NULL, oc); ++ return FALSE; + } + + +@@ -2015,9 +2008,9 @@ static int cmd_ulth (Word *w, int align, + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_ulthd (Word *w, int align, char has_param, int param) { +- attr_push(ATTR_THICK_UL, NULL); +- return FALSE; ++static int cmd_ulthd (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ attr_push(ATTR_THICK_UL, NULL, oc); ++ return FALSE; + } + + +@@ -2028,9 +2021,9 @@ static int cmd_ulthd (Word *w, int align + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_ulthdash (Word *w, int align, char has_param, int param) { +- attr_push(ATTR_THICK_UL, NULL); +- return FALSE; ++static int cmd_ulthdash (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ attr_push(ATTR_THICK_UL, NULL, oc); ++ return FALSE; + } + + +@@ -2041,9 +2034,9 @@ static int cmd_ulthdash (Word *w, int al + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_ulwave (Word *w, int align, char has_param, int param) { +- attr_push(ATTR_WAVE_UL,NULL); +- return FALSE; ++static int cmd_ulwave (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ attr_push(ATTR_WAVE_UL,NULL, oc); ++ return FALSE; + } + + +@@ -2054,12 +2047,12 @@ static int cmd_ulwave (Word *w, int alig + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_strike (Word *w, int align, char has_param, int param) { +- if (has_param && param==0) +- attr_pop(ATTR_STRIKE); +- else +- attr_push(ATTR_STRIKE,NULL); +- return FALSE; ++static int cmd_strike (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ if (has_param && param==0) ++ attr_pop(ATTR_STRIKE, oc); ++ else ++ attr_push(ATTR_STRIKE,NULL, oc); ++ return FALSE; + } + + /*======================================================================== +@@ -2069,12 +2062,12 @@ static int cmd_strike (Word *w, int alig + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_strikedl (Word *w, int align, char has_param, int param) { +- if (has_param && param==0) +- attr_pop(ATTR_DBL_STRIKE); +- else +- attr_push(ATTR_DBL_STRIKE,NULL); +- return FALSE; ++static int cmd_strikedl (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ if (has_param && param==0) ++ attr_pop(ATTR_DBL_STRIKE, oc); ++ else ++ attr_push(ATTR_DBL_STRIKE,NULL, oc); ++ return FALSE; + } + + +@@ -2085,12 +2078,12 @@ static int cmd_strikedl (Word *w, int al + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_striked (Word *w, int align, char has_param, int param) { +- if (has_param && param==0) +- attr_pop(ATTR_DBL_STRIKE); +- else +- attr_push(ATTR_DBL_STRIKE,NULL); +- return FALSE; ++static int cmd_striked (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ if (has_param && param==0) ++ attr_pop(ATTR_DBL_STRIKE, oc); ++ else ++ attr_push(ATTR_DBL_STRIKE,NULL, oc); ++ return FALSE; + } + + +@@ -2101,8 +2094,8 @@ static int cmd_striked (Word *w, int ali + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_rtf (Word *w, int align, char has_param, int param) { +- return FALSE; ++static int cmd_rtf (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ return FALSE; + } + + +@@ -2113,12 +2106,12 @@ static int cmd_rtf (Word *w, int align, + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_up (Word *w, int align, char has_param, int param) { +- if (has_param && param==0) +- attr_pop(ATTR_SUPER); +- else +- attr_push(ATTR_SUPER,NULL); +- return FALSE; ++static int cmd_up (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ if (has_param && param==0) ++ attr_pop(ATTR_SUPER, oc); ++ else ++ attr_push(ATTR_SUPER,NULL, oc); ++ return FALSE; + } + + /*======================================================================== +@@ -2128,61 +2121,63 @@ static int cmd_up (Word *w, int align, c + * Returns: Flag, always false + *=======================================================================*/ + +-static int cmd_u (Word *w, int align, char has_param, int param) { +-/* TODO: Unicode characters won't be correctly preprocessed if sizeof(int) < 4 +- * and document have unicode character which value is greater than 65536 +- */ ++static int cmd_u (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ /* TODO: Unicode characters won't be correctly preprocessed if sizeof(int) < 4 ++ * and document have unicode character which value is greater than 65536 ++ */ + +- short done=0; +- long unicode_number = (long) param; /* On 16bit architectures int is too small to store unicode characters. - AF */ +- char tmp[12]; /* Number of characters that can be in int type (including '\0'). If int size is greater than 4 bytes change this value. - AF */ +- char *alias; ++ const struct unRTFOutputDevice *device = &oc->conversion->options->device; ++ short done=0; ++ long unicode_number = (long) param; /* On 16bit architectures int is too small to store unicode characters. - AF */ ++ char tmp[12]; /* Number of characters that can be in int type (including '\0'). If int size is greater than 4 bytes change this value. - AF */ ++ char *alias; + #if DEBUG +- char *str; +- if (has_param == TRUE) +- { +- fprintf(stderr,"param is %d (x%x) (0%o)\n", param, +- param, param); +- } +- if (w->hash_index) +- { +- str=hash_get_string (w->hash_index); +- fprintf(stderr,"string is %s\n", str); +- } ++ char *str; ++ ++ if (has_param == TRUE) ++ { ++ fprintf(stderr,"param is %d (x%x) (0%o)\n", param, ++ param, param); ++ } ++ if (w->hash_index) ++ { ++ str=hash_get_string (oc->conversion, w->hash_index); ++ fprintf(stderr,"string is %s\n", str); ++ } + #endif +- /* 0.20.3 - daved added missing function call for unprocessed chars */ +- if ((alias = get_alias(op, param)) != NULL) +- { +- printf("%s", alias); +- done++; +- } +- else +- if(!done && op->unisymbol_print) +- { +- if (unicode_number < 0) +- { ++ /* 0.20.3 - daved added missing function call for unprocessed chars */ ++ if ((alias = get_alias(oc->personality, param)) != NULL) ++ { ++ printf("%s", alias); ++ done++; ++ } ++ else ++ if(!done && oc->personality->unisymbol_print) ++ { ++ if (unicode_number < 0) ++ { + #if DEBUG +- fprintf(stderr, "Invalid unicode character number accured: %ld\n", unicode_number); ++ fprintf(stderr, "Invalid unicode character number accured: %ld\n", unicode_number); + #endif +- unicode_number += 65536; ++ unicode_number += 65536; + #if DEBUG +- fprintf(stderr, "Assumes it should be: %ld\n", unicode_number); ++ fprintf(stderr, "Assumes it should be: %ld\n", unicode_number); + #endif +- } +- sprintf(tmp, "%ld", unicode_number); +- +- if (safe_printf(1, op->unisymbol_print, tmp)) fprintf(stderr, TOO_MANY_ARGS, "unisymbol_print"); +- done++; +- } +- +- /* +- ** if we know how to represent the unicode character in the +- ** output language, we need to skip the next word, otherwise +- ** we will output that alternative. +- */ +- if (done) +- return(SKIP_ONE_WORD); +- return(FALSE); ++ } ++ sprintf(tmp, "%ld", unicode_number); ++ ++ if (safe_printf(device, 1, oc->personality->unisymbol_print, tmp)) fprintf(stderr, TOO_MANY_ARGS, "unisymbol_print"); ++ done++; ++ } ++ ++ /* ++ ** if we know how to represent the unicode character in the ++ ** output language, we need to skip the next word, otherwise ++ ** we will output that alternative. ++ */ ++ if (done) ++ return(SKIP_ONE_WORD); ++ return(FALSE); + } + + /*======================================================================== +@@ -2192,12 +2187,12 @@ static int cmd_u (Word *w, int align, ch + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_dn (Word *w, int align, char has_param, int param) { +- if (has_param && param==0) +- attr_pop(ATTR_SUB); +- else +- attr_push(ATTR_SUB,NULL); +- return FALSE; ++static int cmd_dn (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ if (has_param && param==0) ++ attr_pop(ATTR_SUB, oc); ++ else ++ attr_push(ATTR_SUB,NULL, oc); ++ return FALSE; + } + + /*======================================================================== +@@ -2207,10 +2202,10 @@ static int cmd_dn (Word *w, int align, c + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_nosupersub (Word *w, int align, char has_param, int param) { +- attr_pop(ATTR_SUPER); +- attr_pop(ATTR_SUB); +- return FALSE; ++static int cmd_nosupersub (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ attr_pop(ATTR_SUPER, oc); ++ attr_pop(ATTR_SUB, oc); ++ return FALSE; + } + + /*======================================================================== +@@ -2220,12 +2215,12 @@ static int cmd_nosupersub (Word *w, int + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_super (Word *w, int align, char has_param, int param) { +- if (has_param && param==0) +- attr_pop(ATTR_SUPER); +- else +- attr_push(ATTR_SUPER,NULL); +- return FALSE; ++static int cmd_super (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ if (has_param && param==0) ++ attr_pop(ATTR_SUPER, oc); ++ else ++ attr_push(ATTR_SUPER,NULL, oc); ++ return FALSE; + } + + /*======================================================================== +@@ -2235,12 +2230,12 @@ static int cmd_super (Word *w, int align + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_sub (Word *w, int align, char has_param, int param) { +- if (has_param && param==0) +- attr_pop(ATTR_SUB); +- else +- attr_push(ATTR_SUB,NULL); +- return FALSE; ++static int cmd_sub (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ if (has_param && param==0) ++ attr_pop(ATTR_SUB, oc); ++ else ++ attr_push(ATTR_SUB,NULL, oc); ++ return FALSE; + } + + /*======================================================================== +@@ -2250,12 +2245,12 @@ static int cmd_sub (Word *w, int align, + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_shad (Word *w, int align, char has_param, int param) { +- if (has_param && param==0) +- attr_pop(ATTR_SHADOW); +- else +- attr_push(ATTR_SHADOW,NULL); +- return FALSE; ++static int cmd_shad (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ if (has_param && param==0) ++ attr_pop(ATTR_SHADOW, oc); ++ else ++ attr_push(ATTR_SHADOW,NULL, oc); ++ return FALSE; + } + + /*======================================================================== +@@ -2266,13 +2261,13 @@ static int cmd_shad (Word *w, int align, + *=======================================================================*/ + + static int +-cmd_b (Word *w, int align, char has_param, int param) { +- if (has_param && param==0) { +- attr_pop(ATTR_BOLD); +- } +- else +- attr_push(ATTR_BOLD,NULL); +- return FALSE; ++cmd_b (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ if (has_param && param==0) { ++ attr_pop(ATTR_BOLD, oc); ++ } ++ else ++ attr_push(ATTR_BOLD,NULL, oc); ++ return FALSE; + } + + /*======================================================================== +@@ -2282,12 +2277,12 @@ cmd_b (Word *w, int align, char has_para + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_i (Word *w, int align, char has_param, int param) { +- if (has_param && param==0) +- attr_pop(ATTR_ITALIC); +- else +- attr_push(ATTR_ITALIC,NULL); +- return FALSE; ++static int cmd_i (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ if (has_param && param==0) ++ attr_pop(ATTR_ITALIC, oc); ++ else ++ attr_push(ATTR_ITALIC,NULL, oc); ++ return FALSE; + } + + /*======================================================================== +@@ -2296,8 +2291,8 @@ static int cmd_i (Word *w, int align, ch + * Args: Word, paragraph align info, and numeric param if any. + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ +-static int cmd_s (Word *w, int align, char has_param, int param) { +- return FALSE; ++static int cmd_s (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ return FALSE; + } + + /*======================================================================== +@@ -2307,12 +2302,14 @@ static int cmd_s (Word *w, int align, ch + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_sect (Word *w, int align, char has_param, int param) { +- /* XX kludge */ +- if (op->paragraph_begin) { +- if (safe_printf(0, op->paragraph_begin)) fprintf(stderr, TOO_MANY_ARGS, "paragraph_begin"); +- } +- return FALSE; ++static int cmd_sect (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ const struct unRTFOutputDevice *device = &oc->conversion->options->device; ++ ++ /* XX kludge */ ++ if (oc->personality->paragraph_begin) { ++ if (safe_printf(device, 0, oc->personality->paragraph_begin)) fprintf(stderr, TOO_MANY_ARGS, "paragraph_begin"); ++ } ++ return FALSE; + } + + /*======================================================================== +@@ -2322,14 +2319,16 @@ static int cmd_sect (Word *w, int align, + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_shp (Word *w, int align, char has_param, int param) { +- if (op->comment_begin) { +- if (safe_printf(0, op->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); +- printf("Drawn Shape (ignored--not implemented yet)"); +- if (safe_printf(0, op->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); +- } ++static int cmd_shp (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ const struct unRTFOutputDevice *device = &oc->conversion->options->device; + +- return FALSE; ++ if (oc->personality->comment_begin) { ++ if (safe_printf(device, 0, oc->personality->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); ++ printf("Drawn Shape (ignored--not implemented yet)"); ++ if (safe_printf(device, 0, oc->personality->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); ++ } ++ ++ return FALSE; + } + + /*======================================================================== +@@ -2339,12 +2338,12 @@ static int cmd_shp (Word *w, int align, + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_outl (Word *w, int align, char has_param, int param) { +- if (has_param && param==0) +- attr_pop(ATTR_OUTLINE); +- else +- attr_push(ATTR_OUTLINE,NULL); +- return FALSE; ++static int cmd_outl (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ if (has_param && param==0) ++ attr_pop(ATTR_OUTLINE, oc); ++ else ++ attr_push(ATTR_OUTLINE,NULL, oc); ++ return FALSE; + } + + /*======================================================================== +@@ -2354,12 +2353,12 @@ static int cmd_outl (Word *w, int align, + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_ansi (Word *w, int align, char has_param, int param) { +- if (my_iconv_is_valid(desc)) +- desc = my_iconv_close(desc); ++static int cmd_ansi (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ if (my_iconv_is_valid(oc->conversion->desc)) ++ oc->conversion->desc = my_iconv_close(oc->conversion->desc); + +- desc = my_iconv_open("UTF-8", "cp1252"); +- return FALSE; ++ oc->conversion->desc = my_iconv_open(oc->conversion, "UTF-8", "cp1252"); ++ return FALSE; + } + + /*======================================================================== +@@ -2369,18 +2368,18 @@ static int cmd_ansi (Word *w, int align, + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_ansicpg (Word *w, int align, char has_param, int param) ++static int cmd_ansicpg (const struct OutputContext *oc, Word *w, int align, char has_param, int param) + { +- char tmp[8]; ++ char tmp[8]; + +- snprintf(tmp, 8, "cp%d", param); ++ snprintf(tmp, 8, "cp%d", param); + +- if (my_iconv_is_valid(desc)) +- desc = my_iconv_close(desc); ++ if (my_iconv_is_valid(oc->conversion->desc)) ++ oc->conversion->desc = my_iconv_close(oc->conversion->desc); + +- desc = my_iconv_open("UTF-8", tmp); ++ oc->conversion->desc = my_iconv_open(oc->conversion, "UTF-8", tmp); + +- return FALSE; ++ return FALSE; + } + + /*======================================================================== +@@ -2390,13 +2389,13 @@ static int cmd_ansicpg (Word *w, int ali + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_pc (Word *w, int align, char has_param, int param) { +- if (my_iconv_is_valid(desc)) +- desc = my_iconv_close(desc); ++static int cmd_pc (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ if (my_iconv_is_valid(oc->conversion->desc)) ++ oc->conversion->desc = my_iconv_close(oc->conversion->desc); + +- desc = my_iconv_open("UTF-8", "cp437"); ++ oc->conversion->desc = my_iconv_open(oc->conversion, "UTF-8", "cp437"); + +- return FALSE; ++ return FALSE; + } + + /*======================================================================== +@@ -2406,14 +2405,14 @@ static int cmd_pc (Word *w, int align, c + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_pca (Word *w, int align, char has_param, int param) { ++static int cmd_pca (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { + +- if (my_iconv_is_valid(desc)) +- my_iconv_close(desc); ++ if (my_iconv_is_valid(oc->conversion->desc)) ++ my_iconv_close(oc->conversion->desc); + +- desc = my_iconv_open("UTF-8", "cp850"); ++ oc->conversion->desc = my_iconv_open(oc->conversion, "UTF-8", "cp850"); + +- return FALSE; ++ return FALSE; + } + + /*======================================================================== +@@ -2423,13 +2422,13 @@ static int cmd_pca (Word *w, int align, + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_mac (Word *w, int align, char has_param, int param) { ++static int cmd_mac (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { + +- if (my_iconv_is_valid(desc)) +- my_iconv_close(desc); ++ if (my_iconv_is_valid(oc->conversion->desc)) ++ my_iconv_close(oc->conversion->desc); + +- desc = my_iconv_open("UTF-8", "mac"); +- return FALSE; ++ oc->conversion->desc = my_iconv_open(oc->conversion, "UTF-8", "mac"); ++ return FALSE; + } + + /*======================================================================== +@@ -2439,11 +2438,11 @@ static int cmd_mac (Word *w, int align, + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_colortbl (Word *w, int align, char has_param, int param) { +- if (w->next) { +- process_color_table(w->next); +- } +- return TRUE; ++static int cmd_colortbl (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ if (w->next) { ++ process_color_table (oc, w->next); ++ } ++ return TRUE; + } + + /*======================================================================== +@@ -2453,11 +2452,11 @@ static int cmd_colortbl (Word *w, int al + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_fonttbl (Word *w, int align, char has_param, int param) { +- if (w->next) { +- process_font_table(w->next); +- } +- return TRUE; ++static int cmd_fonttbl (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ if (w->next) { ++ process_font_table (oc, w->next); ++ } ++ return TRUE; + } + + /*======================================================================== +@@ -2467,8 +2466,8 @@ static int cmd_fonttbl (Word *w, int ali + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_header (Word *w, int align, char has_param, int param) { +- return TRUE; ++static int cmd_header (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ return TRUE; + } + + /*======================================================================== +@@ -2478,8 +2477,8 @@ static int cmd_header (Word *w, int alig + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_headerl (Word *w, int align, char has_param, int param) { +- return TRUE; ++static int cmd_headerl (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ return TRUE; + } + + /*======================================================================== +@@ -2489,8 +2488,8 @@ static int cmd_headerl (Word *w, int ali + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_headerr (Word *w, int align, char has_param, int param) { +- return TRUE; ++static int cmd_headerr (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ return TRUE; + } + + /*======================================================================== +@@ -2500,8 +2499,8 @@ static int cmd_headerr (Word *w, int ali + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_headerf (Word *w, int align, char has_param, int param) { +- return TRUE; ++static int cmd_headerf (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ return TRUE; + } + + /*======================================================================== +@@ -2511,8 +2510,8 @@ static int cmd_headerf (Word *w, int ali + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_footer (Word *w, int align, char has_param, int param) { +- return TRUE; ++static int cmd_footer (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ return TRUE; + } + + /*======================================================================== +@@ -2522,8 +2521,8 @@ static int cmd_footer (Word *w, int alig + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_footerl (Word *w, int align, char has_param, int param) { +- return TRUE; ++static int cmd_footerl (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ return TRUE; + } + + /*======================================================================== +@@ -2533,8 +2532,8 @@ static int cmd_footerl (Word *w, int ali + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_footerr (Word *w, int align, char has_param, int param) { +- return TRUE; ++static int cmd_footerr (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ return TRUE; + } + + /*======================================================================== +@@ -2544,8 +2543,8 @@ static int cmd_footerr (Word *w, int ali + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_footerf (Word *w, int align, char has_param, int param) { +- return TRUE; ++static int cmd_footerf (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ return TRUE; + } + + /*======================================================================== +@@ -2555,8 +2554,8 @@ static int cmd_footerf (Word *w, int ali + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_ignore (Word *w, int align, char has_param, int param) { +- return TRUE; ++static int cmd_ignore (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ return TRUE; + } + + /*======================================================================== +@@ -2566,9 +2565,9 @@ static int cmd_ignore (Word *w, int alig + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_info (Word *w, int align, char has_param, int param) { +- process_info_group (w->next); +- return TRUE; ++static int cmd_info (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ process_info_group (oc, w->next); ++ return TRUE; + } + + /*======================================================================== +@@ -2578,11 +2577,11 @@ static int cmd_info (Word *w, int align, + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_pict (Word *w, int align, char has_param, int param) { +- within_picture=TRUE; +- picture_width = picture_height = 0; +- picture_type = PICT_WB; +- return FALSE; ++static int cmd_pict (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ oc->conversion->within_picture=TRUE; ++ oc->conversion->picture_width = oc->conversion->picture_height = 0; ++ oc->conversion->picture_type = PICT_WB; ++ return FALSE; + } + + /*======================================================================== +@@ -2592,8 +2591,8 @@ static int cmd_pict (Word *w, int align, + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_bin (Word *w, int align, char has_param, int param) { +- return FALSE; ++static int cmd_bin (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ return FALSE; + } + + +@@ -2604,9 +2603,9 @@ static int cmd_bin (Word *w, int align, + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_macpict (Word *w, int align, char has_param, int param) { +- picture_type = PICT_MAC; +- return FALSE; ++static int cmd_macpict (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ oc->conversion->picture_type = PICT_MAC; ++ return FALSE; + } + + /*======================================================================== +@@ -2616,9 +2615,9 @@ static int cmd_macpict (Word *w, int ali + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_jpegblip (Word *w, int align, char has_param, int param) { +- picture_type = PICT_JPEG; +- return FALSE; ++static int cmd_jpegblip (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ oc->conversion->picture_type = PICT_JPEG; ++ return FALSE; + } + + /*======================================================================== +@@ -2628,9 +2627,9 @@ static int cmd_jpegblip (Word *w, int al + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_pngblip (Word *w, int align, char has_param, int param) { +- picture_type = PICT_PNG; +- return FALSE; ++static int cmd_pngblip (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ oc->conversion->picture_type = PICT_PNG; ++ return FALSE; + } + + /*======================================================================== +@@ -2640,9 +2639,9 @@ static int cmd_pngblip (Word *w, int ali + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_pnmetafile (Word *w, int align, char has_param, int param) { +- picture_type = PICT_PM; +- return FALSE; ++static int cmd_pnmetafile (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ oc->conversion->picture_type = PICT_PM; ++ return FALSE; + } + + /*======================================================================== +@@ -2652,23 +2651,23 @@ static int cmd_pnmetafile (Word *w, int + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_wmetafile (Word *w, int align, char has_param, int param) { +- picture_type = PICT_WM; +- if (within_picture && has_param) { +- picture_wmetafile_type=param; +- switch(param) { +- case 1: picture_wmetafile_type_str="MM_TEXT"; break; +- case 2: picture_wmetafile_type_str="MM_LOMETRIC"; break; +- case 3: picture_wmetafile_type_str="MM_HIMETRIC"; break; +- case 4: picture_wmetafile_type_str="MM_LOENGLISH"; break; +- case 5: picture_wmetafile_type_str="MM_HIENGLISH"; break; +- case 6: picture_wmetafile_type_str="MM_TWIPS"; break; +- case 7: picture_wmetafile_type_str="MM_ISOTROPIC"; break; +- case 8: picture_wmetafile_type_str="MM_ANISOTROPIC"; break; +- default: picture_wmetafile_type_str="default:MM_TEXT"; break; +- } +- } +- return FALSE; ++static int cmd_wmetafile (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ oc->conversion->picture_type = PICT_WM; ++ if (oc->conversion->within_picture && has_param) { ++ oc->conversion->picture_wmetafile_type=param; ++ switch(param) { ++ case 1: oc->conversion->picture_wmetafile_type_str="MM_TEXT"; break; ++ case 2: oc->conversion->picture_wmetafile_type_str="MM_LOMETRIC"; break; ++ case 3: oc->conversion->picture_wmetafile_type_str="MM_HIMETRIC"; break; ++ case 4: oc->conversion->picture_wmetafile_type_str="MM_LOENGLISH"; break; ++ case 5: oc->conversion->picture_wmetafile_type_str="MM_HIENGLISH"; break; ++ case 6: oc->conversion->picture_wmetafile_type_str="MM_TWIPS"; break; ++ case 7: oc->conversion->picture_wmetafile_type_str="MM_ISOTROPIC"; break; ++ case 8: oc->conversion->picture_wmetafile_type_str="MM_ANISOTROPIC"; break; ++ default: oc->conversion->picture_wmetafile_type_str="default:MM_TEXT"; break; ++ } ++ } ++ return FALSE; + } + + /*======================================================================== +@@ -2678,10 +2677,10 @@ static int cmd_wmetafile (Word *w, int a + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_wbmbitspixel (Word *w, int align, char has_param, int param) { +- if (within_picture && has_param) +- picture_bits_per_pixel = param; +- return FALSE; ++static int cmd_wbmbitspixel (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ if (oc->conversion->within_picture && has_param) ++ oc->conversion->picture_bits_per_pixel = param; ++ return FALSE; + } + + /*======================================================================== +@@ -2691,10 +2690,10 @@ static int cmd_wbmbitspixel (Word *w, in + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_picw (Word *w, int align, char has_param, int param) { +- if (within_picture && has_param) +- picture_width = param; +- return FALSE; ++static int cmd_picw (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ if (oc->conversion->within_picture && has_param) ++ oc->conversion->picture_width = param; ++ return FALSE; + } + + /*======================================================================== +@@ -2704,10 +2703,10 @@ static int cmd_picw (Word *w, int align, + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_pich (Word *w, int align, char has_param, int param) { +- if (within_picture && has_param) +- picture_height = param; +- return FALSE; ++static int cmd_pich (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ if (oc->conversion->within_picture && has_param) ++ oc->conversion->picture_height = param; ++ return FALSE; + } + + +@@ -2718,9 +2717,9 @@ static int cmd_pich (Word *w, int align, + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_xe (Word *w, int align, char has_param, int param) { +- process_index_entry (w); +- return TRUE; ++static int cmd_xe (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ process_index_entry (oc, w); ++ return TRUE; + } + + /*======================================================================== +@@ -2730,9 +2729,9 @@ static int cmd_xe (Word *w, int align, c + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_tc (Word *w, int align, char has_param, int param) { +- process_toc_entry (w, TRUE); +- return TRUE; ++static int cmd_tc (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ process_toc_entry (oc, w, TRUE); ++ return TRUE; + } + + /*======================================================================== +@@ -2742,282 +2741,282 @@ static int cmd_tc (Word *w, int align, c + * Returns: Flag, true only if rest of Words on line should be ignored. + *=======================================================================*/ + +-static int cmd_tcn (Word *w, int align, char has_param, int param) { +- process_toc_entry (w, FALSE); +- return TRUE; ++static int cmd_tcn (const struct OutputContext *oc, Word *w, int align, char has_param, int param) { ++ process_toc_entry (oc, w, FALSE); ++ return TRUE; + } + + + typedef struct { +- char *name; +- int (*func)(Word*, int, char, int); +- char *debug_print; +-} HashItem; ++ char *name; ++ int (*func)(const struct OutputContext *, Word*, int, char, int); ++ char *debug_print; ++} CmdHashItem; + + + /* All of the possible commands that RTF might recognize. */ +-static HashItem hashArray_other [] = { +- { "*", cmd_ignore, NULL }, +- { "-", cmd_optional_hyphen, "optional hyphen" }, +- { "_", cmd_nonbreaking_hyphen, "nonbreaking hyphen" }, +- { "~", cmd_nonbreaking_space, NULL }, +- { NULL, NULL, NULL} ++static CmdHashItem hashArray_other [] = { ++ { "*", cmd_ignore, NULL }, ++ { "-", cmd_optional_hyphen, "optional hyphen" }, ++ { "_", cmd_nonbreaking_hyphen, "nonbreaking hyphen" }, ++ { "~", cmd_nonbreaking_space, NULL }, ++ { NULL, NULL, NULL} + }; +-static HashItem hashArray_a [] = { +- { "ansi", &cmd_ansi , NULL }, +- { "ansicpg", &cmd_ansicpg , NULL }, +- { NULL, NULL, NULL} ++static CmdHashItem hashArray_a [] = { ++ { "ansi", &cmd_ansi , NULL }, ++ { "ansicpg", &cmd_ansicpg , NULL }, ++ { NULL, NULL, NULL} + }; +-static HashItem hashArray_b [] = { +- { "b", &cmd_b, NULL }, +- { "bullet", &cmd_bullet, NULL }, +- { "bin", &cmd_bin, "picture is binary" }, ++static CmdHashItem hashArray_b [] = { ++ { "b", &cmd_b, NULL }, ++ { "bullet", &cmd_bullet, NULL }, ++ { "bin", &cmd_bin, "picture is binary" }, + #if 0 +- { "bgbdiag", NULL, NULL }, +- { "bgcross", NULL, NULL }, +- { "bgdcross", NULL, NULL }, +- { "bgfdiag", NULL, NULL }, +- { "bghoriz", NULL, NULL }, +- { "bgkbdiag", NULL, NULL }, +- { "bgkcross", NULL, NULL }, +- { "bgkdcross", NULL, NULL }, +- { "bgkfdiag", NULL, NULL }, +- { "bgkhoriz", NULL, NULL }, +- { "bgkvert", NULL, NULL }, +- { "bgvert", NULL, NULL }, +- { "brdrcf", NULL, NULL }, +- { "brdrdb", NULL, NULL }, +- { "brdrdot", NULL, NULL }, +- { "brdrhair", NULL, NULL }, +- { "brdrs", NULL, NULL }, +- { "brdrsh", NULL, NULL }, +- { "brdrth", NULL, NULL }, +- { "brdrw", NULL, NULL }, ++ { "bgbdiag", NULL, NULL }, ++ { "bgcross", NULL, NULL }, ++ { "bgdcross", NULL, NULL }, ++ { "bgfdiag", NULL, NULL }, ++ { "bghoriz", NULL, NULL }, ++ { "bgkbdiag", NULL, NULL }, ++ { "bgkcross", NULL, NULL }, ++ { "bgkdcross", NULL, NULL }, ++ { "bgkfdiag", NULL, NULL }, ++ { "bgkhoriz", NULL, NULL }, ++ { "bgkvert", NULL, NULL }, ++ { "bgvert", NULL, NULL }, ++ { "brdrcf", NULL, NULL }, ++ { "brdrdb", NULL, NULL }, ++ { "brdrdot", NULL, NULL }, ++ { "brdrhair", NULL, NULL }, ++ { "brdrs", NULL, NULL }, ++ { "brdrsh", NULL, NULL }, ++ { "brdrth", NULL, NULL }, ++ { "brdrw", NULL, NULL }, + #endif +- { NULL, NULL, NULL} ++ { NULL, NULL, NULL} + }; +-static HashItem hashArray_c [] = { +- { "caps", &cmd_caps, NULL }, +- { "cb", cmd_cb, NULL }, +- { "cf", cmd_cf, NULL }, +- { "colortbl", &cmd_colortbl, "color table" }, +- { "cols", NULL, "columns (not implemented)" }, +- { "column", NULL, "column break (not implemented)" }, +- { "cbpat", NULL, "Paragraph Shading" }, +- { "cellx", NULL, "Table Definitions" }, +- { "cfpat", NULL, NULL }, +- { "cgrid", NULL, NULL }, +- { "charrsid", NULL, "Revision Mark (ignore)" }, +- { "clbgbcross", NULL, NULL }, +- { "clbgbdiag", NULL, NULL }, +- { "clbgbkbdiag", NULL, NULL }, +- { "clbgbkcross", NULL, NULL }, +- { "clbgbkdcross", NULL, NULL }, +- { "clbgbkfdiag", NULL, NULL }, +- { "clbgbkhor", NULL, NULL }, +- { "clbgbkvert", NULL, NULL }, +- { "clbgdcross", NULL, NULL }, +- { "clbgfdiag", NULL, NULL }, +- { "clbghoriz", NULL, NULL }, +- { "clbgvert", NULL, NULL }, +- { "clbrdrb", NULL, NULL }, +- { "clbrdrl", NULL, NULL }, +- { "clbrdrr", NULL, NULL }, +- { "clbrdrt", NULL, NULL }, +- { "clcbpat", NULL, NULL }, +- { "clcfpat", NULL, NULL }, +- { "clmgf", NULL, NULL }, +- { "clmrg", NULL, NULL }, +- { "clshdng", NULL, NULL }, +- { NULL, NULL, NULL} ++static CmdHashItem hashArray_c [] = { ++ { "caps", &cmd_caps, NULL }, ++ { "cb", cmd_cb, NULL }, ++ { "cf", cmd_cf, NULL }, ++ { "colortbl", &cmd_colortbl, "color table" }, ++ { "cols", NULL, "columns (not implemented)" }, ++ { "column", NULL, "column break (not implemented)" }, ++ { "cbpat", NULL, "Paragraph Shading" }, ++ { "cellx", NULL, "Table Definitions" }, ++ { "cfpat", NULL, NULL }, ++ { "cgrid", NULL, NULL }, ++ { "charrsid", NULL, "Revision Mark (ignore)" }, ++ { "clbgbcross", NULL, NULL }, ++ { "clbgbdiag", NULL, NULL }, ++ { "clbgbkbdiag", NULL, NULL }, ++ { "clbgbkcross", NULL, NULL }, ++ { "clbgbkdcross", NULL, NULL }, ++ { "clbgbkfdiag", NULL, NULL }, ++ { "clbgbkhor", NULL, NULL }, ++ { "clbgbkvert", NULL, NULL }, ++ { "clbgdcross", NULL, NULL }, ++ { "clbgfdiag", NULL, NULL }, ++ { "clbghoriz", NULL, NULL }, ++ { "clbgvert", NULL, NULL }, ++ { "clbrdrb", NULL, NULL }, ++ { "clbrdrl", NULL, NULL }, ++ { "clbrdrr", NULL, NULL }, ++ { "clbrdrt", NULL, NULL }, ++ { "clcbpat", NULL, NULL }, ++ { "clcfpat", NULL, NULL }, ++ { "clmgf", NULL, NULL }, ++ { "clmrg", NULL, NULL }, ++ { "clshdng", NULL, NULL }, ++ { NULL, NULL, NULL} + }; +-static HashItem hashArray_d [] = { +- { "deff", NULL, "Default Font" }, +- { "dn", &cmd_dn, NULL }, ++static CmdHashItem hashArray_d [] = { ++ { "deff", NULL, "Default Font" }, ++ { "dn", &cmd_dn, NULL }, + #if 0 +- { "dibitmap", NULL, NULL }, ++ { "dibitmap", NULL, NULL }, + #endif +- { NULL, NULL, NULL} ++ { NULL, NULL, NULL} + }; +-static HashItem hashArray_e [] = { +- { "emdash", cmd_emdash, NULL }, +- { "endash", cmd_endash, NULL }, +- { "embo", &cmd_emboss, NULL }, +- { "expand", &cmd_expand, NULL }, +- { "expnd", &cmd_expand, NULL }, +- { NULL, NULL, NULL} ++static CmdHashItem hashArray_e [] = { ++ { "emdash", cmd_emdash, NULL }, ++ { "endash", cmd_endash, NULL }, ++ { "embo", &cmd_emboss, NULL }, ++ { "expand", &cmd_expand, NULL }, ++ { "expnd", &cmd_expand, NULL }, ++ { NULL, NULL, NULL} + }; +-static HashItem hashArray_f [] = { +- { "f", cmd_f, NULL }, +- { "fdecor", cmd_fdecor, NULL }, +- { "fmodern", cmd_fmodern, NULL }, +- { "fnil", cmd_fnil, NULL }, +- { "fonttbl", cmd_fonttbl, "font table" }, +- { "froman", cmd_froman, NULL }, +- { "fs", cmd_fs, NULL }, +- { "fscript", cmd_fscript, NULL }, +- { "fswiss", cmd_fswiss, NULL }, +- { "ftech", cmd_ftech, NULL }, +- { "field", cmd_field, NULL }, +- { "footer", cmd_footer, NULL }, +- { "footerf", cmd_footerf, NULL }, +- { "footerl", cmd_footerl, NULL }, +- { "footerr", cmd_footerr, NULL }, +- { NULL, NULL, NULL} ++static CmdHashItem hashArray_f [] = { ++ { "f", cmd_f, NULL }, ++ { "fdecor", cmd_fdecor, NULL }, ++ { "fmodern", cmd_fmodern, NULL }, ++ { "fnil", cmd_fnil, NULL }, ++ { "fonttbl", cmd_fonttbl, "font table" }, ++ { "froman", cmd_froman, NULL }, ++ { "fs", cmd_fs, NULL }, ++ { "fscript", cmd_fscript, NULL }, ++ { "fswiss", cmd_fswiss, NULL }, ++ { "ftech", cmd_ftech, NULL }, ++ { "field", cmd_field, NULL }, ++ { "footer", cmd_footer, NULL }, ++ { "footerf", cmd_footerf, NULL }, ++ { "footerl", cmd_footerl, NULL }, ++ { "footerr", cmd_footerr, NULL }, ++ { NULL, NULL, NULL} + }; +-static HashItem hashArray_h [] = { +- { "highlight", &cmd_highlight, NULL }, +- { "header", cmd_header, NULL }, +- { "headerf", cmd_headerf, NULL }, +- { "headerl", cmd_headerl, NULL }, +- { "headerr", cmd_headerr, NULL }, +- { "hl", cmd_ignore, "hyperlink within object" }, +- { NULL, NULL, NULL} ++static CmdHashItem hashArray_h [] = { ++ { "highlight", &cmd_highlight, NULL }, ++ { "header", cmd_header, NULL }, ++ { "headerf", cmd_headerf, NULL }, ++ { "headerl", cmd_headerl, NULL }, ++ { "headerr", cmd_headerr, NULL }, ++ { "hl", cmd_ignore, "hyperlink within object" }, ++ { NULL, NULL, NULL} + }; +-static HashItem hashArray_i [] = { +- { "i", &cmd_i, NULL }, +- { "info", &cmd_info, NULL }, +- { "insrsid", NULL, "Revision Mark (ignore)" }, +- { "intbl", &cmd_intbl, NULL }, +- { "impr", &cmd_engrave, NULL }, +- { NULL, NULL, NULL} ++static CmdHashItem hashArray_i [] = { ++ { "i", &cmd_i, NULL }, ++ { "info", &cmd_info, NULL }, ++ { "insrsid", NULL, "Revision Mark (ignore)" }, ++ { "intbl", &cmd_intbl, NULL }, ++ { "impr", &cmd_engrave, NULL }, ++ { NULL, NULL, NULL} + }; +-static HashItem hashArray_j [] = { +- { "jpegblip", &cmd_jpegblip, NULL }, +- { NULL, NULL, NULL} ++static CmdHashItem hashArray_j [] = { ++ { "jpegblip", &cmd_jpegblip, NULL }, ++ { NULL, NULL, NULL} + }; +-static HashItem hashArray_l [] = { +- { "ldblquote", &cmd_ldblquote, NULL }, +- { "line", &cmd_line, NULL }, +- { "lquote", &cmd_lquote, NULL }, +- { NULL, NULL, NULL} ++static CmdHashItem hashArray_l [] = { ++ { "ldblquote", &cmd_ldblquote, NULL }, ++ { "line", &cmd_line, NULL }, ++ { "lquote", &cmd_lquote, NULL }, ++ { NULL, NULL, NULL} + }; +-static HashItem hashArray_m [] = { +- { "mac", &cmd_mac , NULL }, +- { "macpict", &cmd_macpict, NULL }, +- { NULL, NULL, NULL} ++static CmdHashItem hashArray_m [] = { ++ { "mac", &cmd_mac , NULL }, ++ { "macpict", &cmd_macpict, NULL }, ++ { NULL, NULL, NULL} + }; +-static HashItem hashArray_n [] = { +- { "nosupersub", &cmd_nosupersub, NULL }, +- { NULL, NULL, NULL} ++static CmdHashItem hashArray_n [] = { ++ { "nosupersub", &cmd_nosupersub, NULL }, ++ { NULL, NULL, NULL} + }; +-static HashItem hashArray_o [] = { +- { "outl", &cmd_outl, NULL }, +- { NULL, NULL, NULL} ++static CmdHashItem hashArray_o [] = { ++ { "outl", &cmd_outl, NULL }, ++ { NULL, NULL, NULL} + }; +-static HashItem hashArray_p [] = { +- { "page", &cmd_page, NULL }, +- { "par", &cmd_par, NULL }, +- { "pc", &cmd_pc , NULL }, +- { "pca", &cmd_pca , NULL }, +- { "pich", &cmd_pich, NULL }, +- { "pict", &cmd_pict, "picture" }, +- { "picw", &cmd_picw, NULL }, +- { "plain", &cmd_plain, NULL }, +- { "pngblip", &cmd_pngblip, NULL }, +- { "pnmetafile", &cmd_pnmetafile, NULL }, ++static CmdHashItem hashArray_p [] = { ++ { "page", &cmd_page, NULL }, ++ { "par", &cmd_par, NULL }, ++ { "pc", &cmd_pc , NULL }, ++ { "pca", &cmd_pca , NULL }, ++ { "pich", &cmd_pich, NULL }, ++ { "pict", &cmd_pict, "picture" }, ++ { "picw", &cmd_picw, NULL }, ++ { "plain", &cmd_plain, NULL }, ++ { "pngblip", &cmd_pngblip, NULL }, ++ { "pnmetafile", &cmd_pnmetafile, NULL }, + #if 0 +- { "piccropb", NULL, NULL }, +- { "piccropl", NULL, NULL }, +- { "piccropr", NULL, NULL }, +- { "piccropt", NULL, NULL }, +- { "pichgoal", NULL, NULL }, +- { "pichgoal", NULL, NULL }, +- { "picscaled", NULL, NULL }, +- { "picscalex", NULL, NULL }, +- { "picwgoal", NULL, NULL }, ++ { "piccropb", NULL, NULL }, ++ { "piccropl", NULL, NULL }, ++ { "piccropr", NULL, NULL }, ++ { "piccropt", NULL, NULL }, ++ { "pichgoal", NULL, NULL }, ++ { "pichgoal", NULL, NULL }, ++ { "picscaled", NULL, NULL }, ++ { "picscalex", NULL, NULL }, ++ { "picwgoal", NULL, NULL }, + #endif +- { NULL, NULL, NULL} ++ { NULL, NULL, NULL} + }; +-static HashItem hashArray_r [] = { +- { "rdblquote", &cmd_rdblquote, NULL }, +- { "rquote", &cmd_rquote, NULL }, +- { "rtf", &cmd_rtf, NULL }, +- { NULL, NULL, NULL} ++static CmdHashItem hashArray_r [] = { ++ { "rdblquote", &cmd_rdblquote, NULL }, ++ { "rquote", &cmd_rquote, NULL }, ++ { "rtf", &cmd_rtf, NULL }, ++ { NULL, NULL, NULL} + }; +-static HashItem hashArray_s [] = { +- { "s", cmd_s, "style" }, +- { "sect", &cmd_sect, "section break"}, +- { "scaps", &cmd_scaps, NULL }, +- { "super", &cmd_super, NULL }, +- { "sub", &cmd_sub, NULL }, +- { "shad", &cmd_shad, NULL }, +- { "strike", &cmd_strike, NULL }, +- { "striked", &cmd_striked, NULL }, +- { "strikedl", &cmd_strikedl, NULL }, +- { "stylesheet", &cmd_ignore, "style sheet" }, +- { "shp", cmd_shp, "drawn shape" }, ++static CmdHashItem hashArray_s [] = { ++ { "s", cmd_s, "style" }, ++ { "sect", &cmd_sect, "section break"}, ++ { "scaps", &cmd_scaps, NULL }, ++ { "super", &cmd_super, NULL }, ++ { "sub", &cmd_sub, NULL }, ++ { "shad", &cmd_shad, NULL }, ++ { "strike", &cmd_strike, NULL }, ++ { "striked", &cmd_striked, NULL }, ++ { "strikedl", &cmd_strikedl, NULL }, ++ { "stylesheet", &cmd_ignore, "style sheet" }, ++ { "shp", cmd_shp, "drawn shape" }, + #if 0 +- { "shading", NULL, NULL }, ++ { "shading", NULL, NULL }, + #endif +- { NULL, NULL, NULL} ++ { NULL, NULL, NULL} + }; +-static HashItem hashArray_t [] = { +- { "tab", &cmd_tab, NULL }, +- { "tc", cmd_tc, "TOC entry" }, +- { "tcn", cmd_tcn, "TOC entry" }, +- { NULL, NULL, NULL} ++static CmdHashItem hashArray_t [] = { ++ { "tab", &cmd_tab, NULL }, ++ { "tc", cmd_tc, "TOC entry" }, ++ { "tcn", cmd_tcn, "TOC entry" }, ++ { NULL, NULL, NULL} + }; +-static HashItem hashArray_u [] = { +- { "u", &cmd_u, NULL }, +- { "ul", &cmd_ul, NULL }, +- { "up", &cmd_up, NULL }, +- { "uld", &cmd_uld, NULL }, +- { "uldash", &cmd_uldash, NULL }, +- { "uldashd", &cmd_uldashd, NULL }, +- { "uldashdd", &cmd_uldashdd, NULL }, +- { "uldb", &cmd_uldb, NULL }, +- { "ulnone", &cmd_ulnone, NULL }, +- { "ulth", &cmd_ulth, NULL }, +- { "ulthd", &cmd_ulthd, NULL }, +- { "ulthdash", &cmd_ulthdash, NULL }, +- { "ulw", &cmd_ulw, NULL }, +- { "ulwave", &cmd_ulwave, NULL }, +- { NULL, NULL, NULL} ++static CmdHashItem hashArray_u [] = { ++ { "u", &cmd_u, NULL }, ++ { "ul", &cmd_ul, NULL }, ++ { "up", &cmd_up, NULL }, ++ { "uld", &cmd_uld, NULL }, ++ { "uldash", &cmd_uldash, NULL }, ++ { "uldashd", &cmd_uldashd, NULL }, ++ { "uldashdd", &cmd_uldashdd, NULL }, ++ { "uldb", &cmd_uldb, NULL }, ++ { "ulnone", &cmd_ulnone, NULL }, ++ { "ulth", &cmd_ulth, NULL }, ++ { "ulthd", &cmd_ulthd, NULL }, ++ { "ulthdash", &cmd_ulthdash, NULL }, ++ { "ulw", &cmd_ulw, NULL }, ++ { "ulwave", &cmd_ulwave, NULL }, ++ { NULL, NULL, NULL} + }; + +-static HashItem hashArray_v [] = { +- { "v", NULL, "Hidden Text" }, +- { NULL, NULL, NULL } ++static CmdHashItem hashArray_v [] = { ++ { "v", NULL, "Hidden Text" }, ++ { NULL, NULL, NULL } + }; + +-static HashItem hashArray_w [] = { +- { "wbmbitspixel", &cmd_wbmbitspixel, NULL }, +- { "wmetafile", &cmd_wmetafile, NULL }, +- { NULL, NULL, NULL} ++static CmdHashItem hashArray_w [] = { ++ { "wbmbitspixel", &cmd_wbmbitspixel, NULL }, ++ { "wmetafile", &cmd_wmetafile, NULL }, ++ { NULL, NULL, NULL} + }; + +-static HashItem hashArray_x [] = { +- { "xe", cmd_xe, "index entry" }, +- { NULL, NULL, NULL} ++static CmdHashItem hashArray_x [] = { ++ { "xe", cmd_xe, "index entry" }, ++ { NULL, NULL, NULL} + }; + +-static HashItem *hash [26] = { +- hashArray_a, +- hashArray_b, +- hashArray_c, +- hashArray_d, +- hashArray_e, +- hashArray_f, +- NULL, +- hashArray_h, +- hashArray_i, +- hashArray_j, +- NULL, +- hashArray_l, +- hashArray_m, +- hashArray_n, +- hashArray_o, +- hashArray_p, +- NULL, +- hashArray_r, +- hashArray_s, +- hashArray_t, +- hashArray_u, +- hashArray_v, +- hashArray_w, +- hashArray_x, +- NULL, NULL ++static CmdHashItem *hash [26] = { ++ hashArray_a, ++ hashArray_b, ++ hashArray_c, ++ hashArray_d, ++ hashArray_e, ++ hashArray_f, ++ NULL, ++ hashArray_h, ++ hashArray_i, ++ hashArray_j, ++ NULL, ++ hashArray_l, ++ hashArray_m, ++ hashArray_n, ++ hashArray_o, ++ hashArray_p, ++ NULL, ++ hashArray_r, ++ hashArray_s, ++ hashArray_t, ++ hashArray_u, ++ hashArray_v, ++ hashArray_w, ++ hashArray_x, ++ NULL, NULL + }; + + +@@ -3038,53 +3037,56 @@ static HashItem *hash [26] = { + *=======================================================================*/ + + void +-print_with_special_exprs (char *s) { +- int ch; +- int state; ++print_with_special_exprs (const struct OutputContext *oc, char *s) { ++ int ch; ++ int state; ++ const struct unRTFOutputDevice *device = &oc->conversion->options->device; + +-enum { SMALL=0, BIG=1 }; ++ enum { SMALL=0, BIG=1 }; + +- CHECK_PARAM_NOT_NULL(s); ++ CHECK_PARAM_NOT_NULL(s); + +- state=SMALL; /* Pacify gcc, st001906 - 0.19.6 */ +- if (simulate_smallcaps) { +- if (*s >= 'a' && *s <= 'z') { +- state=SMALL; +- if (safe_printf(0, op->smaller_begin)) fprintf(stderr, TOO_MANY_ARGS, "smaller_begin"); +- } +- else +- state=BIG; +- } ++ state=SMALL; /* Pacify gcc, st001906 - 0.19.6 */ ++ if (oc->conversion->simulate_smallcaps) { ++ if (*s >= 'a' && *s <= 'z') { ++ state=SMALL; ++ if (safe_printf(device, 0, oc->personality->smaller_begin)) fprintf(stderr, TOO_MANY_ARGS, "smaller_begin"); ++ } ++ else ++ state=BIG; ++ } + +- while ((ch=*s)) { +- char *post_trans = NULL; ++ while ((ch=*s)) { ++ char *post_trans = NULL; + +- if (simulate_allcaps || simulate_smallcaps) +- ch = toupper (ch); ++ if (oc->conversion->simulate_allcaps || oc->conversion->simulate_smallcaps) ++ ch = toupper (ch); + +- if (ch >= 0x20 && ch < 0x80) { +- post_trans = op_translate_char (op, desc, ch); +- if(post_trans) +- printf("%s",post_trans); +- } ++ if (ch >= 0x20 && ch < 0x80) { ++ post_trans = op_translate_char (oc->conversion, oc->personality, ch); ++ if(post_trans) { ++ safe_printf(device, 0, post_trans); ++ free(post_trans); ++ } ++ } + +- s++; ++ s++; + +- if (simulate_smallcaps) { +- ch = *s; +- if (ch >= 'a' && ch <= 'z') { +- if (state==BIG) +- if (safe_printf(0, op->smaller_begin)) fprintf(stderr, TOO_MANY_ARGS, "smaller_begin"); +- state=SMALL; +- } +- else +- { +- if (state==SMALL) +- if (safe_printf(0, op->smaller_end)) fprintf(stderr, TOO_MANY_ARGS, "smaller_end"); +- state=BIG; +- } +- } +- } ++ if (oc->conversion->simulate_smallcaps) { ++ ch = *s; ++ if (ch >= 'a' && ch <= 'z') { ++ if (state==BIG) ++ if (safe_printf(device, 0, oc->personality->smaller_begin)) fprintf(stderr, TOO_MANY_ARGS, "smaller_begin"); ++ state=SMALL; ++ } ++ else ++ { ++ if (state==SMALL) ++ if (safe_printf(device, 0, oc->personality->smaller_end)) fprintf(stderr, TOO_MANY_ARGS, "smaller_end"); ++ state=BIG; ++ } ++ } ++ } + } + + +@@ -3097,16 +3099,18 @@ enum { SMALL=0, BIG=1 }; + *=======================================================================*/ + + static void +-begin_table() ++begin_table(const struct OutputContext *oc) + { +- within_table=TRUE; +- have_printed_row_begin = FALSE; +- have_printed_cell_begin = FALSE; +- have_printed_row_end = FALSE; +- have_printed_cell_end = FALSE; +- attrstack_push(); +- starting_body(); +- if (safe_printf(0, op->table_begin)) fprintf(stderr, TOO_MANY_ARGS, "table_begin"); ++ const struct unRTFOutputDevice *device = &oc->conversion->options->device; ++ ++ oc->conversion->within_table=TRUE; ++ oc->conversion->have_printed_row_begin = FALSE; ++ oc->conversion->have_printed_cell_begin = FALSE; ++ oc->conversion->have_printed_row_end = FALSE; ++ oc->conversion->have_printed_cell_end = FALSE; ++ attrstack_push(oc->conversion); ++ starting_body(oc); ++ if (safe_printf(device, 0, oc->personality->table_begin)) fprintf(stderr, TOO_MANY_ARGS, "table_begin"); + } + + +@@ -3119,23 +3123,25 @@ begin_table() + *=======================================================================*/ + + void +-end_table () ++end_table (const struct OutputContext *oc) + { +- if (within_table) { +- if (!have_printed_cell_end) { +- attr_pop_dump(); +- if (safe_printf(0, op->table_cell_end)) fprintf(stderr, TOO_MANY_ARGS, "table_cell_end"); +- } +- if (!have_printed_row_end) { +- if (safe_printf(0, op->table_row_end)) fprintf(stderr, TOO_MANY_ARGS, "table_row_end"); +- } +- if (safe_printf(0, op->table_end)) fprintf(stderr, TOO_MANY_ARGS, "table_end"); +- within_table=FALSE; +- have_printed_row_begin = FALSE; +- have_printed_cell_begin = FALSE; +- have_printed_row_end = FALSE; +- have_printed_cell_end = FALSE; +- } ++ const struct unRTFOutputDevice *device = &oc->conversion->options->device; ++ ++ if (oc->conversion->within_table) { ++ if (!oc->conversion->have_printed_cell_end) { ++ attr_pop_dump(); ++ if (safe_printf(device, 0, oc->personality->table_cell_end)) fprintf(stderr, TOO_MANY_ARGS, "table_cell_end"); ++ } ++ if (!oc->conversion->have_printed_row_end) { ++ if (safe_printf(device, 0, oc->personality->table_row_end)) fprintf(stderr, TOO_MANY_ARGS, "table_row_end"); ++ } ++ if (safe_printf(device, 0, oc->personality->table_end)) fprintf(stderr, TOO_MANY_ARGS, "table_end"); ++ oc->conversion->within_table=FALSE; ++ oc->conversion->have_printed_row_begin = FALSE; ++ oc->conversion->have_printed_cell_begin = FALSE; ++ oc->conversion->have_printed_row_end = FALSE; ++ oc->conversion->have_printed_cell_end = FALSE; ++ } + } + + +@@ -3148,21 +3154,23 @@ end_table () + *=======================================================================*/ + + void +-starting_text() { +- if (within_table) { +- if (!have_printed_row_begin) { +- if (safe_printf(0, op->table_row_begin)) fprintf(stderr, TOO_MANY_ARGS, "table_row_begin"); +- have_printed_row_begin=TRUE; +- have_printed_row_end=FALSE; +- have_printed_cell_begin=FALSE; +- } +- if (!have_printed_cell_begin) { +- if (safe_printf(0, op->table_cell_begin)) fprintf(stderr, TOO_MANY_ARGS, "table_cell_begin"); +- attrstack_express_all(); +- have_printed_cell_begin=TRUE; +- have_printed_cell_end=FALSE; +- } +- } ++starting_text(const struct OutputContext *oc) { ++ const struct unRTFOutputDevice *device = &oc->conversion->options->device; ++ ++ if (oc->conversion->within_table) { ++ if (!oc->conversion->have_printed_row_begin) { ++ if (safe_printf(device, 0, oc->personality->table_row_begin)) fprintf(stderr, TOO_MANY_ARGS, "table_row_begin"); ++ oc->conversion->have_printed_row_begin=TRUE; ++ oc->conversion->have_printed_row_end=FALSE; ++ oc->conversion->have_printed_cell_begin=FALSE; ++ } ++ if (!oc->conversion->have_printed_cell_begin) { ++ if (safe_printf(device, 0, oc->personality->table_cell_begin)) fprintf(stderr, TOO_MANY_ARGS, "table_cell_begin"); ++ attrstack_express_all(); ++ oc->conversion->have_printed_cell_begin=TRUE; ++ oc->conversion->have_printed_cell_end=FALSE; ++ } ++ } + } + + +@@ -3176,25 +3184,27 @@ starting_text() { + *=======================================================================*/ + + static void +-starting_paragraph_align (int align) ++starting_paragraph_align (const struct OutputContext *oc, int align) + { +- if (within_header && align != ALIGN_LEFT) +- starting_body(); ++ const struct unRTFOutputDevice *device = &oc->conversion->options->device; + +- switch (align) +- { +- case ALIGN_CENTER: +- if (safe_printf(0, op->center_begin)) fprintf(stderr, TOO_MANY_ARGS, "center_begin"); +- break; +- case ALIGN_LEFT: +- break; +- case ALIGN_RIGHT: +- if (safe_printf(0, op->align_right_begin)) fprintf(stderr, TOO_MANY_ARGS, "align_right_begin"); +- break; +- case ALIGN_JUSTIFY: +- if (safe_printf(0, op->justify_begin)) fprintf(stderr, TOO_MANY_ARGS, "justify_begin"); /* But this is correct */ +- break; +- } ++ if (oc->conversion->within_header && align != ALIGN_LEFT) ++ starting_body(oc); ++ ++ switch (align) ++ { ++ case ALIGN_CENTER: ++ if (safe_printf(device, 0, oc->personality->center_begin)) fprintf(stderr, TOO_MANY_ARGS, "center_begin"); ++ break; ++ case ALIGN_LEFT: ++ break; ++ case ALIGN_RIGHT: ++ if (safe_printf(device, 0, oc->personality->align_right_begin)) fprintf(stderr, TOO_MANY_ARGS, "align_right_begin"); ++ break; ++ case ALIGN_JUSTIFY: ++ if (safe_printf(device, 0, oc->personality->justify_begin)) fprintf(stderr, TOO_MANY_ARGS, "justify_begin"); /* But this is correct */ ++ break; ++ } + } + + +@@ -3207,21 +3217,23 @@ starting_paragraph_align (int align) + *=======================================================================*/ + + static void +-ending_paragraph_align (int align) ++ending_paragraph_align (const struct OutputContext *oc, int align) + { +- switch (align) { +- case ALIGN_CENTER: +- if (safe_printf(0, op->center_end)) fprintf(stderr, TOO_MANY_ARGS, "center_end"); +- break; +- case ALIGN_LEFT: +- break; +- case ALIGN_RIGHT: +- if (safe_printf(0, op->align_right_end)) fprintf(stderr, TOO_MANY_ARGS, "align_right_end"); +- break; +- case ALIGN_JUSTIFY: +- if (safe_printf(0, op->justify_end)) fprintf(stderr, TOO_MANY_ARGS, "justify_end"); +- break; +- } ++ const struct unRTFOutputDevice *device = &oc->conversion->options->device; ++ ++ switch (align) { ++ case ALIGN_CENTER: ++ if (safe_printf(device, 0, oc->personality->center_end)) fprintf(stderr, TOO_MANY_ARGS, "center_end"); ++ break; ++ case ALIGN_LEFT: ++ break; ++ case ALIGN_RIGHT: ++ if (safe_printf(device, 0, oc->personality->align_right_end)) fprintf(stderr, TOO_MANY_ARGS, "align_right_end"); ++ break; ++ case ALIGN_JUSTIFY: ++ if (safe_printf(device, 0, oc->personality->justify_end)) fprintf(stderr, TOO_MANY_ARGS, "justify_end"); ++ break; ++ } + } + + +@@ -3234,411 +3246,411 @@ ending_paragraph_align (int align) + *=======================================================================*/ + + static void +-word_print_core (Word *w) ++word_print_core (const struct OutputContext *oc, Word *w) + { +- char *s; +- FILE *pictfile=NULL; +- int is_cell_group=FALSE; +- int paragraph_begined=FALSE; +- int paragraph_align=ALIGN_LEFT; ++ char *s; ++ FILE *pictfile=NULL; ++ int is_cell_group=FALSE; ++ int paragraph_begined=FALSE; ++ int paragraph_align=ALIGN_LEFT; ++ const struct unRTFOutputDevice *device = &oc->conversion->options->device; + +- CHECK_PARAM_NOT_NULL(w); ++ CHECK_PARAM_NOT_NULL(w); + +- if (!coming_pars_that_are_tabular && within_table) { +- end_table(); +- } +- else if (coming_pars_that_are_tabular && !within_table) { +- begin_table(); +- } ++ if (!oc->conversion->coming_pars_that_are_tabular && oc->conversion->within_table) { ++ end_table(oc); ++ } ++ else if (oc->conversion->coming_pars_that_are_tabular && !oc->conversion->within_table) { ++ begin_table(oc); ++ } + +- /* Mark our place in the stack */ +- attrstack_push(); ++ /* Mark our place in the stack */ ++ attrstack_push(oc->conversion); + +- while (w) { ++ while (w) { + +- s = word_string (w); ++ s = word_string (oc->conversion, w); + +- if (s) { ++ if (s) { + +- /*--Ignore whitespace in header--------------------*/ +- if (*s==' ' && within_header) { +- /* no op */ +- } +- else +- /*--Handle word -----------------------------------*/ +- if (s[0] != '\\') +- { +- starting_body(); +- starting_text(); ++ /*--Ignore whitespace in header--------------------*/ ++ if (*s==' ' && oc->conversion->within_header) { ++ /* no op */ ++ } ++ else ++ /*--Handle word -----------------------------------*/ ++ if (s[0] != '\\') ++ { ++ starting_body(oc); ++ starting_text(oc); + +- if (!paragraph_begined) { +- starting_paragraph_align (paragraph_align); +- paragraph_begined=TRUE; +- } ++ if (!paragraph_begined) { ++ starting_paragraph_align (oc, paragraph_align); ++ paragraph_begined=TRUE; ++ } + +- /*----------------------------------------*/ +- if (within_picture) { +- starting_body(); +- if (!pictfile && !nopict_mode) { +- char *ext=NULL; +- switch (picture_type) { +- case PICT_WB: ext="bmp"; break; +- case PICT_WM: ext="wmf"; break; +- case PICT_MAC: ext="pict"; break; +- case PICT_JPEG: ext="jpg"; break; +- case PICT_PNG: ext="png"; break; +- case PICT_DI: ext="dib"; break; /* Device independent bitmap=??? */ +- case PICT_PM: ext="pmm"; break; /* OS/2 metafile=??? */ +- } +- sprintf(picture_path, "pict%03d.%s", +- picture_file_number++,ext); +- pictfile=fopen(picture_path,"w"); +- } ++ /*----------------------------------------*/ ++ if (oc->conversion->within_picture) { ++ starting_body(oc); ++ if (!pictfile && !oc->conversion->options->nopict_mode) { ++ char *ext=NULL; ++ switch (oc->conversion->picture_type) { ++ case PICT_WB: ext="bmp"; break; ++ case PICT_WM: ext="wmf"; break; ++ case PICT_MAC: ext="pict"; break; ++ case PICT_JPEG: ext="jpg"; break; ++ case PICT_PNG: ext="png"; break; ++ case PICT_DI: ext="dib"; break; /* Device independent bitmap=??? */ ++ case PICT_PM: ext="pmm"; break; /* OS/2 metafile=??? */ ++ } ++ sprintf(oc->conversion->picture_path, "pict%03d.%s", ++ oc->conversion->picture_file_number++,ext); ++ pictfile=fopen(oc->conversion->picture_path,"w"); ++ } + +- if (s[0]!=' ') { +- char *s2; +- if (safe_printf(0, op->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); +- printf("picture data found, "); +- if (picture_wmetafile_type_str) { +- printf("WMF type is %s, ", +- picture_wmetafile_type_str); +- } +- printf("picture dimensions are %d by %d, depth %d", +- picture_width, picture_height, picture_bits_per_pixel); +- if (safe_printf(0, op->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); +- if (picture_width && picture_height && picture_bits_per_pixel) { +- s2=s; +- while (*s2) { +- unsigned int tmp,value; +- tmp=tolower(*s2++); +- if (tmp>'9') tmp-=('a'-10); +- else tmp-='0'; +- value=16*tmp; +- tmp=tolower(*s2++); +- if (tmp>'9') tmp-=('a'-10); +- else tmp-='0'; +- value+=tmp; +- if (pictfile) { +- fprintf(pictfile,"%c", value); +- } +- } +- } +- } +- } +- /*----------------------------------------*/ +- else { +- total_chars_this_line += strlen(s); ++ if (s[0]!=' ') { ++ char *s2; ++ if (safe_printf(device, 0, oc->personality->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); ++ printf("picture data found, "); ++ if (oc->conversion->picture_wmetafile_type_str) { ++ printf("WMF type is %s, ", ++ oc->conversion->picture_wmetafile_type_str); ++ } ++ printf("picture dimensions are %d by %d, depth %d", ++ oc->conversion->picture_width, oc->conversion->picture_height, oc->conversion->picture_bits_per_pixel); ++ if (safe_printf(device, 0, oc->personality->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); ++ if (oc->conversion->picture_width && oc->conversion->picture_height && oc->conversion->picture_bits_per_pixel) { ++ s2=s; ++ while (*s2) { ++ unsigned int tmp,value; ++ tmp=tolower(*s2++); ++ if (tmp>'9') tmp-=('a'-10); ++ else tmp-='0'; ++ value=16*tmp; ++ tmp=tolower(*s2++); ++ if (tmp>'9') tmp-=('a'-10); ++ else tmp-='0'; ++ value+=tmp; ++ if (pictfile) { ++ fprintf(pictfile,"%c", value); ++ } ++ } ++ } ++ } ++ } ++ /*----------------------------------------*/ ++ else { ++ oc->conversion->total_chars_this_line += strlen(s); + +- if (op->word_begin) +- if (safe_printf(0, op->word_begin)) fprintf(stderr, TOO_MANY_ARGS, "word_begin"); ++ if (oc->personality->word_begin) ++ if (safe_printf(device, 0, oc->personality->word_begin)) fprintf(stderr, TOO_MANY_ARGS, "word_begin"); + +- print_with_special_exprs (s); ++ print_with_special_exprs (oc, s); + +- if (op->word_end) +- if (safe_printf(0, op->word_end)) fprintf(stderr, TOO_MANY_ARGS, "word_end"); +- } ++ if (oc->personality->word_end) ++ if (safe_printf(device, 0, oc->personality->word_end)) fprintf(stderr, TOO_MANY_ARGS, "word_end"); ++ } + + +- } +- /* output an escaped backslash */ +- /* do we need special handling for latex? */ +- else if (*(s+1) == '\\') +- { +- s++; +- putchar('\\'); +- } +- else if (*(s+1) == '{') +- { +- s++; +- putchar('{'); +- } +- else if (*(s+1) == '}') +- { +- s++; +- putchar('}'); +- } +- /*---Handle RTF keywords---------------------------*/ +- else { ++ } ++ /* output an escaped backslash */ ++ /* do we need special handling for latex? */ ++ else if (*(s+1) == '\\') ++ { ++ s++; ++ putchar('\\'); ++ } ++ else if (*(s+1) == '{') ++ { ++ s++; ++ putchar('{'); ++ } ++ else if (*(s+1) == '}') ++ { ++ s++; ++ putchar('}'); ++ } ++ /*---Handle RTF keywords---------------------------*/ ++ else { + +- int done=FALSE; +- s++; +-/*----Paragraph alignment----------------------------------------------------*/ +- if (!strcmp ("ql", s)) +- paragraph_align = ALIGN_LEFT; +- else if (!strcmp ("qr", s)) +- paragraph_align = ALIGN_RIGHT; +- else if (!strcmp ("qj", s)) +- paragraph_align = ALIGN_JUSTIFY; +- else if (!strcmp ("qc", s)) +- paragraph_align = ALIGN_CENTER; +- else if (!strcmp ("pard", s)) +- { +- /* Clear out all font attributes. +- */ +- attr_pop_all(); ++ int done=FALSE; ++ s++; ++ /*----Paragraph alignment----------------------------------------------------*/ ++ if (!strcmp ("ql", s)) ++ paragraph_align = ALIGN_LEFT; ++ else if (!strcmp ("qr", s)) ++ paragraph_align = ALIGN_RIGHT; ++ else if (!strcmp ("qj", s)) ++ paragraph_align = ALIGN_JUSTIFY; ++ else if (!strcmp ("qc", s)) ++ paragraph_align = ALIGN_CENTER; ++ else if (!strcmp ("pard", s)) ++ { ++ /* Clear out all font attributes. ++ */ ++ attr_pop_all(oc); + +- if (coming_pars_that_are_tabular) { +- --coming_pars_that_are_tabular; +- } ++ if (oc->conversion->coming_pars_that_are_tabular) { ++ --oc->conversion->coming_pars_that_are_tabular; ++ } + +- /* Clear out all paragraph attributes. +- */ +- ending_paragraph_align(paragraph_align); +- paragraph_align = ALIGN_LEFT; +- paragraph_begined = FALSE; +- } +-/*----Table keywords---------------------------------------------------------*/ +- else +- if (!strcmp (s, "cell")) { ++ /* Clear out all paragraph attributes. ++ */ ++ ending_paragraph_align (oc, paragraph_align); ++ paragraph_align = ALIGN_LEFT; ++ paragraph_begined = FALSE; ++ } ++ /*----Table keywords---------------------------------------------------------*/ ++ else ++ if (!strcmp (s, "cell")) { + +- is_cell_group=TRUE; +- if (!have_printed_cell_begin) { +- /* Need this with empty cells */ +- if (safe_printf(0, op->table_cell_begin)) fprintf(stderr, TOO_MANY_ARGS, "table_cell_begin"); +- attrstack_express_all(); +- } +- attr_pop_dump(); +- if (safe_printf(0, op->table_cell_end)) fprintf(stderr, TOO_MANY_ARGS, "table_cell_end"); +- have_printed_cell_begin = FALSE; +- have_printed_cell_end=TRUE; +- } +- else if (!strcmp (s, "row")) { ++ is_cell_group=TRUE; ++ if (!oc->conversion->have_printed_cell_begin) { ++ /* Need this with empty cells */ ++ if (safe_printf(device, 0, oc->personality->table_cell_begin)) fprintf(stderr, TOO_MANY_ARGS, "table_cell_begin"); ++ attrstack_express_all(); ++ } ++ attr_pop_dump(); ++ if (safe_printf(device, 0, oc->personality->table_cell_end)) fprintf(stderr, TOO_MANY_ARGS, "table_cell_end"); ++ oc->conversion->have_printed_cell_begin = FALSE; ++ oc->conversion->have_printed_cell_end=TRUE; ++ } ++ else if (!strcmp (s, "row")) { + +- if (within_table) { +- if (safe_printf(0, op->table_row_end)) fprintf(stderr, TOO_MANY_ARGS, "table_row_end"); +- have_printed_row_begin = FALSE; +- have_printed_row_end=TRUE; +- } else { +- if (debug_mode) { +- if (safe_printf(0, op->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); +- printf("end of table row"); +- if (safe_printf(0, op->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); +- } +- } +- } ++ if (oc->conversion->within_table) { ++ if (safe_printf(device, 0, oc->personality->table_row_end)) fprintf(stderr, TOO_MANY_ARGS, "table_row_end"); ++ oc->conversion->have_printed_row_begin = FALSE; ++ oc->conversion->have_printed_row_end=TRUE; ++ } else { ++ if (oc->conversion->options->debug_mode) { ++ if (safe_printf(device, 0, oc->personality->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); ++ printf("end of table row"); ++ if (safe_printf(device, 0, oc->personality->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); ++ } ++ } ++ } + +-/*----Special chars---------------------------------------------------------*/ +- else if (*s == '\'') { +- /* \'XX is a hex char code expression */ ++ /*----Special chars---------------------------------------------------------*/ ++ else if (*s == '\'') { ++ /* \'XX is a hex char code expression */ + +- int ch = h2toi (&s[1]); +- char *s2; ++ int ch = h2toi (&s[1]); ++ char *s2; + + #if 1 /* daved - 0.21.2 */ +- if(ch > h2toi("7f") && ch < h2toi("a1")) +- { +- /* 2 byte char - read 2nd */ +- int ch2; +- char *snext; +- int *doublet; +- w = w->next; +- snext = word_string (w); +- if(*snext == '\\' && *(snext+1) == '\'') +- { +- /* all looks good */ +- ch2 = h2toi(&snext[2]); ++ if(ch > h2toi("7f") && ch < h2toi("a1")) ++ { ++ /* 2 byte char - read 2nd */ ++ int ch2; ++ char *snext; ++ int *doublet; ++ w = w->next; ++ snext = word_string (oc->conversion, w); ++ if(*snext == '\\' && *(snext+1) == '\'') ++ { ++ /* all looks good */ ++ ch2 = h2toi(&snext[2]); + #if 0 +- fprintf(stderr,"ch, ch2 = %o %o\n", ch, ch2); ++ fprintf(stderr,"ch, ch2 = %o %o\n", ch, ch2); + #endif +- doublet = (int *)my_malloc(12); +- *doublet = (int)ch; +- *(doublet+1) = (int)ch2; +- *(doublet+2) = 0; ++ doublet = (int *)my_malloc(12); ++ *doublet = (int)ch; ++ *(doublet+1) = (int)ch2; ++ *(doublet+2) = 0; + #if 0 +- fprintf(stderr, "doublet = %o %o\n", *doublet, *(doublet+1)); ++ fprintf(stderr, "doublet = %o %o\n", *doublet, *(doublet+1)); + #endif +- desc2 = desc; +- desc = my_iconv_open("UTF-8", "SHIFT_JIS"); ++ oc->conversion->desc2 = oc->conversion->desc; ++ oc->conversion->desc = my_iconv_open(oc->conversion, "UTF-8", "SHIFT_JIS"); + #if 1 +- s2 = op_translate_doublet (op, desc, ch, ch2); ++ s2 = op_translate_doublet (oc->conversion, oc->personality, ch, ch2); + #else +- s2 = op_translate_str (op, desc, doublet); ++ s2 = op_translate_str (oc->conversion, oc->personality, doublet); + #endif +- free(doublet); +- desc = my_iconv_close(desc); +- desc = desc2; +- my_iconv_t_make_invalid(&desc2); +- } +- } +- else ++ free(doublet); ++ oc->conversion->desc = my_iconv_close(oc->conversion->desc); ++ oc->conversion->desc = oc->conversion->desc2; ++ my_iconv_t_make_invalid(&oc->conversion->desc2); ++ } ++ } ++ else + #endif +-//standard +- s2 = op_translate_char (op, desc, ch); +- if (!s2 || !*s2) { +- if (safe_printf(0, op->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); +- printf("char 0x%02x",ch); +- if (safe_printf(0, op->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); +- } else { +- if (op->word_begin) +- if (safe_printf(0, op->word_begin)) fprintf(stderr, TOO_MANY_ARGS, "word_begin"); +- +- printf("%s", s2); ++ //standard ++ s2 = op_translate_char (oc->conversion, oc->personality, ch); ++ if (!s2 || !*s2) { ++ if (safe_printf(device, 0, oc->personality->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); ++ printf("char 0x%02x",ch); ++ if (safe_printf(device, 0, oc->personality->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); ++ } else { ++ if (oc->personality->word_begin) ++ if (safe_printf(device, 0, oc->personality->word_begin)) fprintf(stderr, TOO_MANY_ARGS, "word_begin"); + +- if (op->word_end) +- if (safe_printf(0, op->word_end)) fprintf(stderr, TOO_MANY_ARGS, "word_end"); +- } +- } +- else +-/*----Search the RTF command hash-------------------------------------------*/ +- { +- int ch; +- int index=0; +- int have_param = FALSE, param = 0; +- HashItem *hip; +- char *p; +- int match = FALSE; /* Pacify gcc, st001906 - 0.19.6 */ ++ printf("%s", s2); + +- /* Look for a parameter */ +- p = s; +- while (*p && (!isdigit(*p) && *p != '-')) p++; +- if (*p && (isdigit(*p) || *p == '-')) { +- have_param = TRUE; +- param = atoi(p); +- } ++ if (oc->personality->word_end) ++ if (safe_printf(device, 0, oc->personality->word_end)) fprintf(stderr, TOO_MANY_ARGS, "word_end"); ++ } ++ } ++ else ++ /*----Search the RTF command hash-------------------------------------------*/ ++ { ++ int ch; ++ int index=0; ++ int have_param = FALSE, param = 0; ++ CmdHashItem *hip; ++ char *p; ++ int match = FALSE; /* Pacify gcc, st001906 - 0.19.6 */ + +- /* Generate a hash index */ +- ch = tolower(*s); +- if (ch >= 'a' && ch <= 'z') +- hip = hash[ch - 'a']; +- else +- hip = hashArray_other; ++ /* Look for a parameter */ ++ p = s; ++ while (*p && (!isdigit(*p) && *p != '-')) p++; ++ if (*p && (isdigit(*p) || *p == '-')) { ++ have_param = TRUE; ++ param = atoi(p); ++ } + +- if (!hip) { +- if (debug_mode) { +- if (safe_printf(0, op->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); +- printf("Unfamiliar RTF command: %s (HashIndex not found)", s); +- if (safe_printf(0, op->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); +- } +- } +- else { +- while (!done) { +- match = FALSE; ++ /* Generate a hash index */ ++ ch = tolower(*s); ++ if (ch >= 'a' && ch <= 'z') ++ hip = hash[ch - 'a']; ++ else ++ hip = hashArray_other; + +- if (have_param) { +- int len=p-s; +- if (!hip[index].name[len] && !strncmp(s, hip[index].name, len)) +- match = TRUE; +- } +- else +- match = !strcmp(s, hip[index].name); ++ if (!hip) { ++ if (oc->conversion->options->debug_mode) { ++ if (safe_printf(device, 0, oc->personality->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); ++ printf("Unfamiliar RTF command: %s (HashIndex not found)", s); ++ if (safe_printf(device, 0, oc->personality->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); ++ } ++ } ++ else { ++ while (!done) { ++ match = FALSE; + +- if (match) { ++ if (have_param) { ++ int len=p-s; ++ if (!hip[index].name[len] && !strncmp(s, hip[index].name, len)) ++ match = TRUE; ++ } ++ else ++ match = !strcmp(s, hip[index].name); + +- char *debug; +- int terminate_group; ++ if (match) { + +- if (hip[index].func) { +-//unicode +- terminate_group = hip[index].func (w,paragraph_align, have_param, param); +- /* daved - 0.19.4 - unicode support may need to skip only one word */ +- if (terminate_group == SKIP_ONE_WORD) +- w=w->next; +- else +- if (terminate_group) +- while(w) w=w->next; +- } ++ char *debug; ++ int terminate_group; + +- debug=hip[index].debug_print; ++ if (hip[index].func) { ++ //unicode ++ terminate_group = hip[index].func (oc, w, paragraph_align, have_param, param); ++ /* daved - 0.19.4 - unicode support may need to skip only one word */ ++ if (terminate_group == SKIP_ONE_WORD) ++ w=w->next; ++ else ++ if (terminate_group) ++ while(w) w=w->next; ++ } + +- if (debug && debug_mode) { +- if (safe_printf(0, op->comment_begin)) +- fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); +- printf("%s", debug); +- if (safe_printf(0, op->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); +- } ++ debug=hip[index].debug_print; + +- done=TRUE; +- } +- else { +- index++; +- if (!hip[index].name) +- done = TRUE; +- } +- } +- } +- if (!match) { +- if (debug_mode) { +- if (safe_printf(0, op->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); +- printf("Unfamiliar RTF command: %s", s); +- if (safe_printf(0, op->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); +- } +- } +- } +- } +-/*-------------------------------------------------------------------------*/ +- } else { ++ if (debug && oc->conversion->options->debug_mode) { ++ if (safe_printf(device, 0, oc->personality->comment_begin)) ++ fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); ++ printf("%s", debug); ++ if (safe_printf(device, 0, oc->personality->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); ++ } + +- Word *child; ++ done=TRUE; ++ } ++ else { ++ index++; ++ if (!hip[index].name) ++ done = TRUE; ++ } ++ } ++ } ++ if (!match) { ++ if (oc->conversion->options->debug_mode) { ++ if (safe_printf(device, 0, oc->personality->comment_begin)) fprintf(stderr, TOO_MANY_ARGS, "comment_begin"); ++ printf("Unfamiliar RTF command: %s", s); ++ if (safe_printf(device, 0, oc->personality->comment_end)) fprintf(stderr, TOO_MANY_ARGS, "comment_end"); ++ } ++ } ++ } ++ } ++ /*-------------------------------------------------------------------------*/ ++ } else { + +- child = w->child; ++ Word *child; + +- if (!paragraph_begined) { +- starting_paragraph_align (paragraph_align); +- paragraph_begined=TRUE; +- } ++ child = w->child; + +- if (child) +- word_print_core (child); +- } ++ if (!paragraph_begined) { ++ starting_paragraph_align (oc, paragraph_align); ++ paragraph_begined=TRUE; ++ } + +- if (w) +- w = w->next; +- } ++ if (child) ++ word_print_core (oc, child); ++ } + +- if (within_picture) { +- if(pictfile) { +- fclose(pictfile); +- if (safe_printf(0, op->imagelink_begin)) fprintf(stderr, TOO_MANY_ARGS, "imagelink_begin"); +- printf("%s", picture_path); +- if (safe_printf(0, op->imagelink_end)) fprintf(stderr, TOO_MANY_ARGS, "imagelink_end"); +- } +- within_picture=FALSE; +- } ++ if (w) ++ w = w->next; ++ } + +- /* Undo font attributes UNLESS we're doing table cells +- * since they would appear between and . +- */ ++ if (oc->conversion->within_picture) { ++ if(pictfile) { ++ fclose(pictfile); ++ if (safe_printf(device, 0, oc->personality->imagelink_begin)) fprintf(stderr, TOO_MANY_ARGS, "imagelink_begin"); ++ printf("%s", oc->conversion->picture_path); ++ if (safe_printf(device, 0, oc->personality->imagelink_end)) fprintf(stderr, TOO_MANY_ARGS, "imagelink_end"); ++ } ++ oc->conversion->within_picture=FALSE; ++ } + +- if (!is_cell_group) +- attr_pop_all(); +- else +- attr_drop_all(); ++ /* Undo font attributes UNLESS we're doing table cells ++ * since they would appear between and . ++ */ + +- /* Undo paragraph alignment +- */ +- if (paragraph_begined) +- ending_paragraph_align (paragraph_align); ++ if (!is_cell_group) ++ attr_pop_all(oc); ++ else ++ attr_drop_all(); + +- attrstack_drop(); ++ /* Undo paragraph alignment ++ */ ++ if (paragraph_begined) ++ ending_paragraph_align (oc, paragraph_align); + +- if((s = attr_get_param(ATTR_FONTFACE)) != NULL && +- strstr(s,"Symbol") != NULL) +- { +- if (!my_iconv_is_valid(desc2)) +- desc2 = desc; +- else +- desc = my_iconv_close(desc); ++ attrstack_drop(oc); + +- desc = my_iconv_open("UTF-8", FONT_SYMBOL); +- } +- else if((s = attr_get_param(ATTR_FONTFACE)) != NULL && +- strstr(s,"Greek") != NULL) +- { +- if (!my_iconv_is_valid(desc2)) +- desc2 = desc; +- else +- desc = my_iconv_close(desc); ++ if((s = attr_get_param(oc->conversion, ATTR_FONTFACE)) != NULL && ++ strstr(s,"Symbol") != NULL) ++ { ++ if (!my_iconv_is_valid(oc->conversion->desc2)) ++ oc->conversion->desc2 = oc->conversion->desc; ++ else ++ oc->conversion->desc = my_iconv_close(oc->conversion->desc); + +- desc = my_iconv_open("UTF-8", FONT_GREEK); +- } +- else +- if (my_iconv_is_valid(desc2)) /* AF - 0.21.0-rc2 */ +- { +- my_iconv_close(desc); +- desc = desc2; +- my_iconv_t_make_invalid(&desc2); +- } ++ oc->conversion->desc = my_iconv_open(oc->conversion, "UTF-8", FONT_SYMBOL); ++ } ++ else if((s = attr_get_param(oc->conversion, ATTR_FONTFACE)) != NULL && ++ strstr(s,"Greek") != NULL) ++ { ++ if (!my_iconv_is_valid(oc->conversion->desc2)) ++ oc->conversion->desc2 = oc->conversion->desc; ++ else ++ oc->conversion->desc = my_iconv_close(oc->conversion->desc); + ++ oc->conversion->desc = my_iconv_open(oc->conversion, "UTF-8", FONT_GREEK); ++ } ++ else ++ if (my_iconv_is_valid(oc->conversion->desc2)) /* AF - 0.21.0-rc2 */ ++ { ++ my_iconv_close(oc->conversion->desc); ++ oc->conversion->desc = oc->conversion->desc2; ++ my_iconv_t_make_invalid(&oc->conversion->desc2); ++ } + } + + +@@ -3652,37 +3664,225 @@ word_print_core (Word *w) + *=======================================================================*/ + + void +-word_print (Word *w) ++word_print (const struct OutputContext *oc, Word *w) + { +- CHECK_PARAM_NOT_NULL (w); ++ const struct unRTFOutputDevice *device = &oc->conversion->options->device; + +- if (!inline_mode) { ++ CHECK_PARAM_NOT_NULL (w); ++ ++ if (!oc->conversion->options->inline_mode) { + #if 1 /* AK3 - AF */ +- if (safe_printf(0, op->document_begin)) fprintf(stderr, TOO_MANY_ARGS, "document_begin"); +- if (safe_printf(0, op->header_begin)) fprintf(stderr, TOO_MANY_ARGS, "header_begin"); +- if (safe_printf(0, op->utf8_encoding)) fprintf(stderr, TOO_MANY_ARGS, "utf8_encoding"); ++ if (safe_printf(device, 0, oc->personality->document_begin)) fprintf(stderr, TOO_MANY_ARGS, "document_begin"); ++ if (safe_printf(device, 0, oc->personality->header_begin)) fprintf(stderr, TOO_MANY_ARGS, "header_begin"); ++ if (safe_printf(device, 0, oc->personality->utf8_encoding)) fprintf(stderr, TOO_MANY_ARGS, "utf8_encoding"); + #else +- printf(op->document_begin); +- printf(op->header_begin); ++ printf(oc->personality->document_begin); ++ printf(oc->personality->header_begin); + #endif +- } ++ } + +- print_banner (); ++ print_banner (oc); + +- within_header=TRUE; +- have_printed_body=FALSE; +- within_table=FALSE; +- simulate_allcaps=FALSE; +- word_print_core (w); +- end_table(); ++ oc->conversion->within_header=TRUE; ++ oc->conversion->have_printed_body=FALSE; ++ oc->conversion->within_table=FALSE; ++ oc->conversion->simulate_allcaps=FALSE; ++ word_print_core (oc, w); ++ end_table (oc); + +- if (!inline_mode) { ++ if (!oc->conversion->options->inline_mode) { + #if 1 /* AK3 - AF */ +- if (safe_printf(0, op->body_end)) fprintf(stderr, TOO_MANY_ARGS, "body_end"); +- if (safe_printf(0, op->document_end)) fprintf(stderr, TOO_MANY_ARGS, "document_end"); ++ if (safe_printf(device, 0, oc->personality->body_end)) fprintf(stderr, TOO_MANY_ARGS, "body_end"); ++ if (safe_printf(device, 0, oc->personality->document_end)) fprintf(stderr, TOO_MANY_ARGS, "document_end"); + #else +- printf(op->body_end); +- printf(op->document_end); ++ printf(oc->personality->body_end); ++ printf(oc->personality->document_end); + #endif +- } ++ } ++} ++ ++/* public functions */ ++void unrtf_set_output_device (unRTFOptions *options, unrtf_output_device_func output_func, void *output_data) ++{ ++ options->device.print = output_func; ++ options->device.data = output_data; ++} ++ ++/*======================================================================== ++ * Name: main ++ * Purpose: Main control function. ++ * Args: Args. ++ * Returns: Exit code. ++ *=======================================================================*/ ++ ++static int stdout_print(void *null, const char *data, size_t data_len) ++{ ++ return printf ("%s", data); ++} ++ ++static char *format_path(const unRTFOptions *options) ++{ ++ size_t fullname_len; ++ char *fullname; ++ ++ if (!options->output_format || !options->config_directory) ++ return 0; ++ ++ fullname_len = strlen (options->output_format) + strlen (options->config_directory) + 6; ++ fullname = malloc(fullname_len + 1); ++ sprintf (fullname, "%s/%s.conf", options->config_directory, options->output_format); ++ ++ return fullname; ++} ++ ++/* TODO: make use of mmap */ ++int unrtf_convert_from_string (unRTFOptions *options, const char *input_str, size_t input_len) ++{ ++ Word *word; ++ char *path, *env_path_p; ++ ConversionContext cc; ++ OutputContext oc; ++ ++ if (!options) ++ return 0; ++ ++ if (!input_str || !input_len) ++ return 0; ++ ++ if (!options->output_format) ++ options->output_format = DEFAULT_OUTPUT; ++ if (!options->config_directory) ++ { ++ if ((env_path_p = getenv("UNRTF_SEARCH_PATH")) != NULL) ++ { ++ if (options->verbose_mode) ++ fprintf (stderr, "got environment path: %s\n", env_path_p); ++ options->config_directory = env_path_p; ++ } ++ else ++ options->config_directory = DEFAULT_UNRTF_SEARCH_PATH; ++ } ++ ++ path = format_path(options); ++ if (!path) ++ return 0; ++ ++ if (access(path, R_OK) != 0) ++ { ++ free (path); ++ return 0; ++ } ++ ++ if (!options->device.print) ++ unrtf_set_output_device (options, stdout_print, NULL); ++ ++ memset (&cc, 0, sizeof (struct ConversionContext)); ++ ++ hash_init (&cc); ++ ++ cc.read_buf = input_str; ++ cc.read_buf_end = input_len; ++ ++ cc.current_max_length = 1; ++ cc.ungot_char = -1; ++ cc.ungot_char2 = -1; ++ cc.ungot_char3 = -1; ++ ++ cc.picture_file_number=1; ++ cc.picture_bits_per_pixel=1; ++ cc.picture_type = PICT_UNKNOWN; ++ ++ cc.desc.desc = (iconv_t) -1; ++ cc.desc2.desc = (iconv_t) -1; ++ ++ cc.options = options; ++ ++ oc.personality = user_init(&cc, path); ++ oc.conversion = &cc; ++ ++ /* All the work starts here. word_read() should keep reading words until ++ * the end of the file. */ ++ word = word_read(&cc); ++ ++ if (options->dump_mode) { ++ word_dump(&cc, word); ++ printf("\n"); ++ } else { ++ /* Should we also optimize word before dump? - AF */ ++ /* word = optimize_word(oc.conversion, word); */ ++ word_print(&oc, word); ++ } ++ ++ /* marcossamaral - 0.19.9 */ ++ if (options->verbose_mode || options->debug_mode) { ++ unsigned long total=0; ++ total = hash_stats(&cc); ++ fprintf(stderr, "Done.\n"); ++ fprintf(stderr, "%lu words were hashed.\n", total); ++ } ++ ++ if (options->debug_mode) { ++ fprintf(stderr, "Total memory allocated %ld bytes.\n", ++ total_malloced()); ++ } ++ ++ hash_free(&cc); ++ word_free(word); ++ fonttable_free(oc.conversion); ++ if (my_iconv_is_valid(oc.conversion->desc)) ++ my_iconv_close(oc.conversion->desc); ++ op_free (oc.personality); ++ free (path); ++ ++ return 1; /* success */ ++} ++ ++int unrtf_convert_from_filename (unRTFOptions *options, const char *filename) ++{ ++ FILE *f; ++ size_t read_len, total_len, max_len; ++ char *content; ++ char buffer[4096]; ++ int is_stdin = 0, rc; ++ ++ if (!filename || strcmp(filename, "-") == 0) ++ { ++ is_stdin = 1; ++ f = stdin; ++ filename = ""; ++ } ++ else ++ { ++ f = fopen (filename, "r"); ++ if (!f) ++ return 0; ++ } ++ ++ if (options->verbose_mode || options->debug_mode) fprintf(stderr, "Processing %s...\n", filename); ++ ++ max_len = 4096; ++ total_len = 0; ++ content = malloc (max_len + 1); ++ do ++ { ++ read_len = fread (buffer, sizeof (char), 4096, f); ++ memcpy (content + total_len, buffer, read_len); ++ total_len += read_len; ++ if (total_len + 4096 > max_len) ++ { ++ max_len = total_len + 4096; ++ content = realloc (content, max_len + 1); ++ } ++ } ++ while (read_len == 4096); ++ ++ if (!is_stdin) ++ fclose (f); ++ ++ content[total_len] = 0; ++ rc = unrtf_convert_from_string (options, content, total_len); ++ ++ free (content); ++ ++ return rc; + } +diff -durpN unrtf-0.21.2.old/src/convert.h unrtf-0.21.2/src/convert.h +--- unrtf-0.21.2.old/src/convert.h 2010-07-03 22:30:58.000000000 -0400 ++++ unrtf-0.21.2/src/convert.h 2011-11-09 15:48:29.998798267 -0500 +@@ -36,18 +36,135 @@ + + #ifndef _CONVERT + ++#include "my_iconv.h" ++ + enum { +- CHARSET_ANSI=1, +- CHARSET_MAC, +- CHARSET_CP437, +- CHARSET_CP850, ++ CHARSET_ANSI=1, ++ CHARSET_MAC, ++ CHARSET_CP437, ++ CHARSET_CP850, + }; + + #ifndef _WORD + #include "word.h" + #endif + +-extern void word_print (Word*); ++typedef struct { ++ int num; ++ char *name; ++} FontEntry; ++ ++#define MAX_FONTS (8192) ++ ++/* RTF color table colors are RGB */ ++ ++typedef struct { ++ unsigned char r,g,b; ++} Color; ++ ++#define MAX_COLORS (1024) ++ ++/* For each RTF text block (the text within braces) we must keep ++ * an AttrStack which is a stack of attributes and their optional ++ * parameter. Since RTF text blocks are nested, these make up a ++ * stack of stacks. And, since RTF text blocks inherit attributes ++ * from parent blocks, all new AttrStacks do the same from ++ * their parent AttrStack. ++ */ ++#define MAX_ATTRS (10000) ++ ++typedef struct _stack { ++ unsigned char attr_stack[MAX_ATTRS]; ++ char *attr_stack_params[MAX_ATTRS]; ++ int tos; ++ struct _stack *next; ++} AttrStack; ++ ++typedef struct _hi { ++ struct _hi *next; ++ char *str; ++ unsigned long value; ++} HashItem; ++ ++typedef struct ConversionContext { ++ const struct unRTFOptions *options; ++ ++ HashItem *hash[256]; ++ unsigned long hash_length[256]; ++ unsigned long hash_value; ++ ++ int lineno; /* Used for error reporting and final line count. */ ++ ++ int banner_printed; ++ ++ int within_picture; ++ int picture_file_number; ++ char picture_path[256]; ++ int picture_width; ++ int picture_height; ++ int picture_bits_per_pixel; ++ int picture_type; ++ int picture_wmetafile_type; ++ char *picture_wmetafile_type_str; ++ ++ int have_printed_body; ++ int within_header; ++ ++ char *hyperlink_base; ++ ++ FontEntry font_table[MAX_FONTS]; ++ int total_fonts; ++ ++ Color color_table[MAX_COLORS]; ++ int total_colors; ++ ++ my_iconv_t desc; ++ my_iconv_t desc2; ++ ++ /* Previously in word_print_core function ++ */ ++ int total_chars_this_line; /* for simulating \tab */ ++ ++ /* This value is set by attr_push and attr_pop ++ */ ++ int simulate_smallcaps; ++ int simulate_allcaps; ++ ++ int coming_pars_that_are_tabular; ++ int within_table; ++ int have_printed_row_begin; ++ int have_printed_cell_begin; ++ int have_printed_row_end; ++ int have_printed_cell_end; ++ ++ /* attr.c */ ++ AttrStack *stack_of_stacks; ++ AttrStack *stack_of_stacks_top; ++ ++ /* word.c */ ++ int indent_level; ++ ++ /* parse.c */ ++ char *input_str; ++ unsigned long current_max_length; ++ int ungot_char; ++ int ungot_char2; ++ int ungot_char3; ++ int last_returned_ch; ++ int buffer_size; ++ ++ const char *read_buf; ++ int read_buf_end; ++ int read_buf_index; ++ ++} ConversionContext; ++ ++struct OutputContext; ++ ++extern void word_print (const struct OutputContext *, Word*); ++extern void starting_body(const struct OutputContext *); ++extern void starting_text(const struct OutputContext *); ++ + #define FONT_GREEK "cp1253" + #define FONT_SYMBOL "SYMBOL" + +diff -durpN unrtf-0.21.2.old/src/defs.h unrtf-0.21.2/src/defs.h +--- unrtf-0.21.2.old/src/defs.h 2010-07-03 22:30:58.000000000 -0400 ++++ unrtf-0.21.2/src/defs.h 2011-11-09 15:48:29.998798267 -0500 +@@ -64,9 +64,6 @@ + #define SKIP_ONE_WORD 2 + #endif + +-#define USAGE "unrtf [--version] [--verbose] [--help] [--nopict|-n] [--noremap] [--html] [--text] [--vt] [--latex] [--rtf] [-P config_search_path] [-t )] " +- +- + /* Default names for RTF's default fonts */ + #define FONTNIL_STR "Times,TimesRoman,TimesNewRoman" + #define FONTROMAN_STR "Times,Palatino" +@@ -76,3 +73,6 @@ + #define FONTDECOR_STR "ZapfChancery" + #define FONTTECH_STR "Symbol" + ++/* This one should be deduce from the configure script */ ++#define DEFAULT_UNRTF_SEARCH_PATH "/usr/local/lib/unrtf/" ++#define DEFAULT_OUTPUT "html" +diff -durpN unrtf-0.21.2.old/src/error.c unrtf-0.21.2/src/error.c +--- unrtf-0.21.2.old/src/error.c 2010-07-03 22:30:58.000000000 -0400 ++++ unrtf-0.21.2/src/error.c 2011-11-09 15:48:29.998798267 -0500 +@@ -51,27 +51,11 @@ + #include + #endif + ++#include "convert.h" + #include "defs.h" + #include "main.h" + + +- +-/*======================================================================== +- * Name: usage +- * Purpose: Prints usage information and exits with an error. +- * Args: None. +- * Returns: None. +- *=======================================================================*/ +- +-void +-usage () +-{ +- fprintf(stderr, "Usage: %s\n", USAGE); +- exit(-3); +-} +- +- +- + /*======================================================================== + * Name: error_handler + * Purpose: Prints error message and other useful info, then exits. +@@ -80,10 +64,10 @@ usage () + *=======================================================================*/ + + void +-error_handler (char* message) ++error_handler (const struct ConversionContext *cc, char* message) + { + #if 1 +- fprintf(stderr, "Error (line %d): %s\n", lineno, message); ++ fprintf(stderr, "Error (line %d): %s\n", cc->lineno, message); + #else + fprintf(stderr, "Error: %s\n", message); + #endif +diff -durpN unrtf-0.21.2.old/src/error.h unrtf-0.21.2/src/error.h +--- unrtf-0.21.2.old/src/error.h 2010-07-03 22:30:58.000000000 -0400 ++++ unrtf-0.21.2/src/error.h 2011-11-09 15:48:29.998798267 -0500 +@@ -37,9 +37,10 @@ + + #define CHECK_MALLOC_SUCCESS(XX) { if ((XX)==NULL) { fprintf (stderr, "internal error: cannot allocate memory in %s at %d\n", __FILE__, __LINE__); exit (1); }} + ++struct ConversionContext; + + extern void usage(void); +-extern void error_handler (char*); ++extern void error_handler (const struct ConversionContext *, char*); + extern void warning_handler (char*); + + +diff -durpN unrtf-0.21.2.old/src/hash.c unrtf-0.21.2/src/hash.c +--- unrtf-0.21.2.old/src/hash.c 2010-07-03 22:30:58.000000000 -0400 ++++ unrtf-0.21.2/src/hash.c 2011-11-09 15:48:29.998798267 -0500 +@@ -53,24 +53,16 @@ + #include + #endif + ++#ifdef HAVE_STDLIB_H ++#include ++#endif ++ ++#include "convert.h" + #include "error.h" + #include "main.h" + #include "malloc.h" + +- +-typedef struct _hi { +- struct _hi *next; +- char *str; +- unsigned long value; +-} HashItem; +- +- +-/* Index by first char of string */ +-static HashItem *hash[256]; +-static unsigned long hash_length[256]; +-static unsigned long hash_value=0; +- +- ++#include "hash.h" + + /*======================================================================== + * Name: hash_init +@@ -80,13 +72,13 @@ static unsigned long hash_value=0; + *=======================================================================*/ + + void +-hash_init () ++hash_init (struct ConversionContext *cc) + { +- int i; +- for (i=0; i<256; i++) { +- hash[i]=NULL; +- hash_length[i]=0; +- } ++ int i; ++ for (i=0; i<256; i++) { ++ cc->hash[i]=NULL; ++ cc->hash_length[i]=0; ++ } + } + + +@@ -101,14 +93,14 @@ hash_init () + *=======================================================================*/ + + unsigned long +-hash_stats () ++hash_stats (struct ConversionContext *cc) + { +- int i; +- unsigned long total=0; +- for (i=0; i<256; i++) { +- total += hash_length[i]; +- } +- return(total); ++ int i; ++ unsigned long total=0; ++ for (i=0; i<256; i++) { ++ total += cc->hash_length[i]; ++ } ++ return(total); + } + + +@@ -121,32 +113,32 @@ hash_stats () + *=======================================================================*/ + + static HashItem * +-hashitem_new (char *str) ++hashitem_new (struct ConversionContext *cc, char *str) + { +- HashItem *hi; +- unsigned long i; +- +- hi=(HashItem*) my_malloc(sizeof(HashItem)); +- if (!hi) +- error_handler("Out of memory"); +- memset ((void*)hi, 0, sizeof (HashItem)); +- +- hi->str = my_strdup(str); ++ HashItem *hi; ++ unsigned long i; + +- i = *str; +- if (i=='\\') i=str[1]; +- i <<= 24; +- hi->value = i | (hash_value++ & 0xffffff); +- hi->next = NULL; ++ hi=(HashItem*) my_malloc(sizeof(HashItem)); ++ if (!hi) ++ error_handler(cc, "Out of memory"); ++ memset ((void*)hi, 0, sizeof (HashItem)); ++ ++ hi->str = my_strdup(cc, str); ++ ++ i = *str; ++ if (i=='\\') i=str[1]; ++ i <<= 24; ++ hi->value = i | (cc->hash_value++ & 0xffffff); ++ hi->next = NULL; + + #if 0 +- if (debug_mode) { +- printf ("\n", +- hi->value, hi->str); +- } ++ if (debug_mode) { ++ printf ("\n", ++ hi->value, hi->str); ++ } + #endif + +- return hi; ++ return hi; + } + + +@@ -158,7 +150,7 @@ hashitem_new (char *str) + *=======================================================================*/ + + unsigned long +-hash_get_index (char *str) ++hash_get_index (struct ConversionContext *cc, char *str) + { + #if 1 /* daved - 0.19.1 */ + unsigned short index; +@@ -177,17 +169,17 @@ hash_get_index (char *str) + if (ch=='\\' && *(str+1)) + ch = *(str+1); + index = ch; +- hi = hash[index]; ++ hi = cc->hash[index]; + while (hi) { + if (!strcmp(hi->str,str)) + return hi->value; + hi=hi->next; + } + /* not in hash */ +- hi = hashitem_new (str); +- hi->next = hash[index]; +- hash [index] = hi; +- ++hash_length [index]; ++ hi = hashitem_new (cc, str); ++ hi->next = cc->hash[index]; ++ cc->hash [index] = hi; ++ ++cc->hash_length [index]; + return hi->value; + } + +@@ -201,13 +193,13 @@ hash_get_index (char *str) + *=======================================================================*/ + + char* +-hash_get_string (unsigned long value) ++hash_get_string (const struct ConversionContext *cc, unsigned long value) + { + int index; + HashItem *hi; + + index = value >> 24; +- hi = hash[index]; ++ hi = cc->hash[index]; + while (hi) { + if (hi->value == value) + return hi->str; +@@ -216,3 +208,27 @@ hash_get_string (unsigned long value) + warning_handler("Word not in hash"); + return NULL; + } ++ ++static void ++hashitem_free (HashItem *item) ++{ ++ HashItem *next = item->next; ++ ++ my_free (item->str); ++ free (item); ++ if (next) ++ hashitem_free(next); ++} ++ ++void ++hash_free (struct ConversionContext *cc) ++{ ++ int i; ++ for (i=0; i<256; i++) { ++ if (cc->hash[i]) { ++ hashitem_free(cc->hash[i]); ++ } ++ cc->hash[i]=NULL; ++ cc->hash_length[i]=0; ++ } ++} +diff -durpN unrtf-0.21.2.old/src/hash.h unrtf-0.21.2/src/hash.h +--- unrtf-0.21.2.old/src/hash.h 2010-07-03 22:30:58.000000000 -0400 ++++ unrtf-0.21.2/src/hash.h 2011-11-09 15:51:52.846788680 -0500 +@@ -32,11 +32,15 @@ + * 16 Dec 07, daved@physiol.usyd.edu.au: updated to GPL v3 + *--------------------------------------------------------------------*/ + ++#ifndef HASH_H ++#define HASH_H 1 + ++struct ConversionContext; + +-extern void hash_init (void); +-extern unsigned long hash_stats (void); +-extern unsigned long hash_get_index (char *); +-extern char* hash_get_string (unsigned long ); +- ++extern void hash_init (struct ConversionContext *); ++extern unsigned long hash_stats (struct ConversionContext *); ++extern unsigned long hash_get_index (struct ConversionContext *, char *); ++extern char* hash_get_string (const struct ConversionContext *, unsigned long); ++extern void hash_free (struct ConversionContext *); + ++#endif /* HASH_H */ +diff -durpN unrtf-0.21.2.old/src/main.c unrtf-0.21.2/src/main.c +--- unrtf-0.21.2.old/src/main.c 2010-07-03 22:30:58.000000000 -0400 ++++ unrtf-0.21.2/src/main.c 2011-11-09 15:48:29.998798267 -0500 +@@ -1,23 +1,23 @@ + /*============================================================================= +- GNU UnRTF, a command-line program to convert RTF documents to other formats. +- Copyright (C) 2000, 2001, 2004 by Zachary Smith ++ GNU UnRTF, a command-line program to convert RTF documents to other formats. ++ Copyright (C) 2000, 2001, 2004 by Zachary Smith + +- 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 3 of the License, or +- (at your option) any later version. ++ 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 3 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. ++ 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +- The maintainer is reachable by electronic mail at daved@physiol.usyd.edu.au +-=============================================================================*/ ++ The maintainer is reachable by electronic mail at daved@physiol.usyd.edu.au ++ =============================================================================*/ + + + /*---------------------------------------------------------------------- +@@ -45,7 +45,7 @@ + * 17 Dec 07, daved@physiol.usyd.edu.au: support for --noremap from + * David Santinoli + * 09 Nov 08, arkadiusz.firus@gmail.com: support for -t +- and read stdin if no input file provided ++ and read stdin if no input file provided + * 13 Dec 08, daved@physiol.usyd.edu.au: search path code + * 17 Jan 10, daved@physiol.usyd.edu.au: change search path to directory + * containing output conf and font charmap files +@@ -70,263 +70,136 @@ + #include + + #include "defs.h" +-#include "error.h" +-#include "word.h" +-#include "convert.h" +-#include "parse.h" +-#include "hash.h" +-#include "malloc.h" +-#include "path.h" ++#include "unrtf.h" + +-#include "output.h" +-#include "user.h" + #include "main.h" +-#include "util.h" +- +-int nopict_mode; /* TRUE => Do not write \pict's to files */ +-int dump_mode; /* TRUE => Output a dump of the RTF word tree */ +-int debug_mode; /* TRUE => Output debug comments within HTML */ +-int lineno; /* Used for error reporting and final line count. */ +-int simple_mode; /* TRUE => Output HTML without SPAN/DIV tags -- This would +- probably be more useful if we could pull out tags +- as well. */ +-int inline_mode; /* TRUE => Output HTML without HTML/BODY/HEAD -- This is +- buggy. I've seen it output pages of tags. */ +-/* marcossamaral - 0.19.9 */ +-int verbose_mode; /* TRUE => Output additional informations about unrtf */ +-int no_remap_mode; /* don't remap codepoints */ +- +- +-OutputPersonality *op = NULL; + + /*======================================================================== +- * Name: get_config +- * Purpose: Updates output acording to information found in file path. +- * Args: Path to configuration file, OutputPersonality, mode. +- If mode == 0 configuration file is defined by user. +- If mode == 1 configuration file is in CONFIG_DIR. +- * Returns: Updated OutputPersonality. ++ * Name: usage ++ * Purpose: Prints usage information and exits with an error. ++ * Args: None. ++ * Returns: None. + *=======================================================================*/ + +-OutputPersonality * +-get_config(char *path, OutputPersonality *op, int mode) ++void ++usage () + { +- char *absolute_path; +- char *user_path; +- char u_success=0; +- struct path_dir *path_dir_p; +- +- switch(mode) +- { +- case 0: +- if(n_path_dirs == 0) +- { +- fprintf(stderr,"no directories to search for %s\n", path); +- exit(1); +- } +- for(path_dir_p = &topdir; path_dir_p->dir_name; path_dir_p = path_dir_p->next) +- { +- char *p; +- p = path_dir_p->dir_name; +- if(*(p+strlen(p)-1) != '/') +- p = concatenate(p, "/"); +- p=concatenate(p, path); +- user_path=concatenate(p, ".conf"); +- if(access(user_path, F_OK|R_OK)) +- continue; +- op = user_init(op, user_path); +- u_success++; +- break; +- } +- if(!u_success) +- { +- fprintf(stderr, "failed to find %s.conf in search path dirs\n", path); +- exit(1); +- } +- break; +- case 1: +- path = concatenate(CONFIG_DIR, path); +- absolute_path = concatenate(path, ".conf"); +- op = user_init(op, absolute_path); +- my_free(absolute_path); +- break; +- default: +- error_handler("Error in function get_config (file main.c)."); +- } +- +- return op; ++ fprintf(stderr, "Usage: %s\n", USAGE); ++ exit(-3); + } + +-/*======================================================================== +- * Name: main +- * Purpose: Main control function. +- * Args: Args. +- * Returns: Exit code. +- *=======================================================================*/ +- + int + main (int argc, char **argv) + { +- FILE *f; +- Word * word; +- char *path = NULL; +- char *env_path_p = '\0'; +- +- int i; +- nopict_mode = debug_mode = dump_mode = inline_mode = no_remap_mode = FALSE; +- /* initialize search path to compiled-in value */ +- search_path = DEFAULT_UNRTF_SEARCH_PATH; ++ unRTFOptions unrtf_options; ++ int show_version = 0, i, free_path = 0; ++ char *path = NULL, *old_path; ++ size_t path_len; + +- if((env_path_p = getenv("UNRTF_SEARCH_PATH")) != NULL) +- { +- if(verbose_mode) +- fprintf(stderr, "got environment path: %s\n", env_path_p); +- search_path=env_path_p; +- } ++ memset (&unrtf_options, 0, sizeof (unRTFOptions)); + +- /* Handle arguments */ ++ /* Handle arguments */ + +- for (i = 1; i < argc; i++) { +- if (!strcmp("--dump", argv[i])) dump_mode = TRUE; +- else if (!strcmp("-d", argv[i])) dump_mode = TRUE; +- else if (!strcmp("--debug", argv[i])) debug_mode = TRUE; +- else if (!strcmp("--verbose", argv[i])) verbose_mode = TRUE; +- else if (!strcmp("--simple", argv[i])) simple_mode = TRUE; +- else if (!strcmp("--noremap", argv[i])) no_remap_mode = TRUE; +- else if (!strcmp("-t", argv[i])) +- { +- if ((i + 1) < argc && *argv[i + 1] != '-') +- { +- i++; +- if(!path_checked && check_dirs() == 0) +- { +- fprintf(stderr,"no config dirs for %s\n", argv[i]); +- exit(1); +- } +- op = get_config(argv[i], op, 0); +- } +- } +- else if (!strcmp("-P", argv[i])) +- { +- if(i+1 > argc) +- { +- fprintf(stderr,"-P needs a path argument\n"); +- exit(1); +- } +- search_path=argv[++i]; +- } +- else if (!strcmp("--inline", argv[i])) inline_mode = TRUE; +- else if (!strcmp("--help", argv[i])) { +- usage(); +- } +- else if (!strcmp("--version", argv[i])) { +- fprintf(stderr, "%s\n", PACKAGE_VERSION); +- fprintf(stderr, "search path is: %s\n", search_path); +- exit(0); +- } +- else if (!strcmp("--nopict", argv[i])) nopict_mode = TRUE; +- else if (!strcmp("-n", argv[i])) nopict_mode = TRUE; +- else if (!strncmp("--", argv[i], 2)) ++ for (i = 1; i < argc; i++) { ++ if (!strcmp("--dump", argv[i])) unrtf_options.dump_mode = TRUE; ++ else if (!strcmp("-d", argv[i])) unrtf_options.dump_mode = TRUE; ++ else if (!strcmp("--debug", argv[i])) unrtf_options.debug_mode = TRUE; ++ else if (!strcmp("--verbose", argv[i])) unrtf_options.verbose_mode = TRUE; ++ else if (!strcmp("--simple", argv[i])) unrtf_options.simple_mode = TRUE; ++ else if (!strcmp("--noremap", argv[i])) unrtf_options.no_remap_mode = TRUE; ++ else if (!strcmp("-t", argv[i])) ++ { ++ if ((i + 1) < argc && *argv[i + 1] != '-') ++ { ++ i++; ++ unrtf_options.output_format = argv[i]; ++ } ++ else ++ { ++ fprintf(stderr, "-t needs a path argument\n"); ++ exit(1); ++ } ++ } ++ else if (!strcmp("-P", argv[i])) ++ { ++ if ((i + 1) < argc && *argv[i + 1] != '-') ++ { ++ i++; ++ unrtf_options.config_directory = argv[i]; ++ } ++ else ++ { ++ fprintf(stderr,"-P needs a path argument\n"); ++ exit(1); ++ } ++ } ++ else if (!strcmp("--inline", argv[i])) unrtf_options.inline_mode = TRUE; ++ else if (!strcmp("--help", argv[i])) { ++ usage(); ++ } ++ else if (!strcmp("--version", argv[i])) { ++ show_version = 1; ++ } ++ else if (!strcmp("--nopict", argv[i])) unrtf_options.nopict_mode = TRUE; ++ else if (!strcmp("-n", argv[i])) unrtf_options.nopict_mode = TRUE; ++ else if (!strncmp("--", argv[i], 2)) + #if 0 /* daved 0.21.1 */ +- op = get_config(&argv[i][2], op, 1) ++ op = get_config(&cc, &argv[i][2], op, 1) + #else +- { +- if(!path_checked && check_dirs() == 0) +- { +- fprintf(stderr,"no config dirs for %s\n", argv[i]); +- exit(1); +- } +- op = get_config(&argv[i][2], op, 0); +- } ++ { ++ unrtf_options.output_format = argv[i] + 2; ++ } + #endif +- else { +- if (*argv[i] == '-') usage(); +- +- if (path) +- usage(); +- else +- path = argv[i]; +- } +- } +- +- +- +- if (op == NULL) +- op = get_config(DEFAULT_OUTPUT, op, 1); +- if(!path_checked && check_dirs() == 0) +- { +- fprintf(stderr,"no config directories\n"); +- exit(1); +- } +- +- +- hash_init(); +- +- /* Program information */ +- if (verbose_mode || debug_mode) { +- fprintf(stderr, "This is UnRTF "); +- fprintf(stderr, "version %s\n", PACKAGE_VERSION); +- fprintf(stderr, "By Dave Davey, Marcos Serrou do Amaral and Arkadiusz Firus\n"); +- fprintf(stderr, "Original Author: Zachary Smith\n"); +- show_dirs(); +- } +- +- if (debug_mode) fprintf(stderr, "Debug mode.\n"); +- if (dump_mode) fprintf(stderr, "Dump mode.\n"); +- +- /* Open file for reading. Append ".rtf" to file name if not supplied. */ +- if (path == NULL) +- f = stdin; +- else +- { +- f = fopen(path, "r"); +- if (!f) { +- char path2[200]; +- strcpy(path2, path); +- strcat(path2, ".rtf"); +- f = fopen(path2, "r"); +- if (!f) +- error_handler("Cannot open input file"); +- } +- } +- +- if (verbose_mode || debug_mode) fprintf(stderr, "Processing %s...\n", path); +- +- /* Keep track of lines processed. This is arbitrary to the user as +- * RTF ignores newlines. May be helpful in error tracking. */ +- lineno = 0; ++ else { ++ if (*argv[i] == '-') usage(); + +- /* All the work starts here. word_read() should keep reading words until +- * the end of the file. */ +- word = word_read(f); ++ if (path) ++ usage(); ++ else ++ path = argv[i]; ++ } ++ } + +- if (dump_mode) { +- word_dump(word); +- printf("\n"); +- } else { +-/* Should we also optimize word before dump? - AF */ +- word = optimize_word(word); +- word_print(word); +- } ++ if (show_version) { ++ fprintf(stderr, "%s\n", PACKAGE_VERSION); ++ fprintf(stderr, "search path is: %s\n", ++ (unrtf_options.config_directory ++ ? unrtf_options.config_directory : DEFAULT_UNRTF_SEARCH_PATH)); ++ exit(0); ++ } + +- fclose(f); ++ /* Program information */ ++ if (unrtf_options.verbose_mode || unrtf_options.debug_mode) { ++ fprintf(stderr, "This is UnRTF "); ++ fprintf(stderr, "version %s\n", PACKAGE_VERSION); ++ fprintf(stderr, "By Dave Davey, Marcos Serrou do Amaral and Arkadiusz Firus\n"); ++ fprintf(stderr, "Original Author: Zachary Smith\n"); ++ fprintf(stderr, "Configuration directory: %s\n", ++ (unrtf_options.config_directory ++ ? unrtf_options.config_directory ++ : DEFAULT_UNRTF_SEARCH_PATH)); ++ } + +- /* marcossamaral - 0.19.9 */ +- if(verbose_mode || debug_mode) { +- unsigned long total=0; +- total = hash_stats(); +- fprintf(stderr, "Done.\n"); +- fprintf(stderr, "%lu words were hashed.\n", total); +- } ++ if (unrtf_options.debug_mode) fprintf(stderr, "Debug mode.\n"); ++ if (unrtf_options.dump_mode) fprintf(stderr, "Dump mode.\n"); + +- if (debug_mode) { +- fprintf(stderr, "Total memory allocated %ld bytes.\n", +- total_malloced()); +- } ++ /* Check file access for reading. Append ".rtf" to file name if not supplied. */ ++ if (path && access(path, R_OK) != 0) { ++ path_len = strlen(path); ++ old_path = path; ++ path = malloc (path_len + 5); ++ sprintf (path, "%s.rtf", old_path); ++ if (access(path, R_OK) != 0) { ++ free (path); ++ fprintf (stderr, "Cannot access input file.\n"); ++ exit (10); ++ } ++ free_path = 1; ++ } + +- /* May as well */ +- word_free(word); ++ unrtf_convert_from_filename (&unrtf_options, path); ++ if (free_path) ++ free (path); + +- return 0; ++ return 0; + } +- +diff -durpN unrtf-0.21.2.old/src/main.h unrtf-0.21.2/src/main.h +--- unrtf-0.21.2.old/src/main.h 2010-07-03 22:30:58.000000000 -0400 ++++ unrtf-0.21.2/src/main.h 2011-11-09 15:48:29.998798267 -0500 +@@ -35,21 +35,8 @@ + * 17 Jan 10, daved@physiol.usyd.edu.au: change CONFIG_DIR to drop outputs/ + *--------------------------------------------------------------------*/ + +- +-extern int lineno; +-extern int debug_mode; +-extern int simple_mode; +-extern int inline_mode; +-extern int no_remap_mode; +- +- + #ifndef _OUTPUT + #include "output.h" + #endif + +-#define CONFIG_DIR "/usr/local/lib/unrtf/" +-#define DEFAULT_OUTPUT "html" +- +-extern OutputPersonality *op; +- +- ++#define USAGE "unrtf [--version] [--verbose] [--help] [--nopict|-n] [--noremap] [--html] [--text] [--vt] [--latex] [--rtf] [-P config_search_path] [-t )] " +diff -durpN unrtf-0.21.2.old/src/Makefile.am unrtf-0.21.2/src/Makefile.am +--- unrtf-0.21.2.old/src/Makefile.am 2010-07-03 22:30:58.000000000 -0400 ++++ unrtf-0.21.2/src/Makefile.am 2011-11-09 15:48:29.998798267 -0500 +@@ -13,7 +13,6 @@ unrtf_SOURCES = attr.c attr.h \ + malloc.c malloc.h \ + output.c output.h \ + parse.c parse.h \ +- path.c path.h \ + unicode.c unicode.h \ + user.c user.h \ + util.c util.h \ +diff -durpN unrtf-0.21.2.old/src/malloc.c unrtf-0.21.2/src/malloc.c +--- unrtf-0.21.2.old/src/malloc.c 2010-07-09 01:13:05.000000000 -0400 ++++ unrtf-0.21.2/src/malloc.c 2011-11-09 15:48:29.998798267 -0500 +@@ -135,19 +135,19 @@ total_malloced (void) { + *=======================================================================*/ + + char * +-my_strdup (char *src) { +- unsigned long len; +- char *ptr; ++my_strdup (struct ConversionContext *cc, char *src) { ++ unsigned long len; ++ char *ptr; + +- CHECK_PARAM_NOT_NULL(src); ++ CHECK_PARAM_NOT_NULL(src); + +- len = strlen(src); +- ptr = my_malloc (len+1); +- if (!ptr) +- error_handler ("out of memory in strdup()"); ++ len = strlen(src); ++ ptr = my_malloc (len+1); ++ if (!ptr) ++ error_handler (cc, "out of memory in strdup()"); + +- strcpy (ptr, src); +- return ptr; ++ sprintf (ptr, "%s", src); ++ return ptr; + } + /* added by daved */ + #include +@@ -163,5 +163,5 @@ rpl_malloc (size_t n) + { + if (n == 0) + n = 1; +-return malloc (n); ++ return malloc (n); + } +diff -durpN unrtf-0.21.2.old/src/malloc.h unrtf-0.21.2/src/malloc.h +--- unrtf-0.21.2.old/src/malloc.h 2010-07-03 22:30:58.000000000 -0400 ++++ unrtf-0.21.2/src/malloc.h 2011-11-09 15:48:29.998798267 -0500 +@@ -32,9 +32,10 @@ + * 09 Nov 08, arkadiusz.firus@gmail.com: added my_realloc + *--------------------------------------------------------------------*/ + ++struct ConversionContext; ++ + extern char * my_malloc (unsigned long); + extern void my_free (char*); + extern char * my_realloc(char*, unsigned long, unsigned long); + extern unsigned long total_malloced (void); +-extern char * my_strdup (char*); +- ++extern char * my_strdup (struct ConversionContext *, char*); +diff -durpN unrtf-0.21.2.old/src/my_iconv.c unrtf-0.21.2/src/my_iconv.c +--- unrtf-0.21.2.old/src/my_iconv.c 2010-08-16 00:12:43.000000000 -0400 ++++ unrtf-0.21.2/src/my_iconv.c 2011-11-09 15:48:29.998798267 -0500 +@@ -12,154 +12,133 @@ + #include + #include + +-#include "malloc.h" +-#include "my_iconv.h" +-#include "util.h" + #if 1 /* daved 0.21.1 */ + #include "unicode.h" +-#include "path.h" + #include + #include + #endif + +-extern int verbose_mode; ++#include "convert.h" ++#include "malloc.h" ++#include "my_iconv.h" ++#include "util.h" ++#include "unrtf.h" ++ ++#define MY_ICONV_T_CLEAR {(iconv_t) -1, NULL} + + my_iconv_t +-my_iconv_open(const char *tocode, const char *fromcode) ++my_iconv_open(const struct ConversionContext *cc, const char *tocode, const char *fromcode) + { +- char *path; +- FILE *f; +- my_iconv_t cd = MY_ICONV_T_CLEAR; +- int c, i; ++ char *path; ++ FILE *f; ++ my_iconv_t cd = MY_ICONV_T_CLEAR; ++ int c, i; + +- if ((cd.desc = iconv_open(tocode, fromcode)) == (iconv_t) -1) +- { +-#if 1 /* daved 0.21.1 */ +- struct path_dir *path_dir_p; +- char u_success=0; +- for(path_dir_p = &topdir; path_dir_p->dir_name; path_dir_p = path_dir_p->next) +- { +- char *p; +- p = path_dir_p->dir_name; +- if(*(p+strlen(p)-1) != '/') +- p = concatenate(p, "/"); +- p = concatenate(p, fromcode); +- path=concatenate(p, ".charmap"); +- if(access(path, F_OK|R_OK)) +- continue; +- u_success++; +- break; +- } +- if(!u_success) +- { +-#else +- path = concatenate(CHARMAP_DIR, fromcode); +-#endif +-#if 1 /* daved 0.21.1 */ +- } +- if((f = fopen(path, "r")) == NULL && verbose_mode) +- fprintf(stderr, "failed to open charmap file %s\n", path); +-#else +- f = fopen(path, "r"); +-#endif ++ if ((cd.desc = iconv_open(tocode, fromcode)) == (iconv_t) -1) ++ { ++ path = my_malloc((strlen(cc->options->config_directory) + strlen(fromcode) + 10) * sizeof(char)); ++ sprintf (path, "%s/%s.charmap", cc->options->config_directory, fromcode); + +- if (f != NULL) +- { +- cd.char_table = (char **)my_malloc(char_table_size * sizeof(char *)); +- c = fgetc(f); ++ if((f = fopen(path, "r")) == NULL && cc->options->verbose_mode) ++ fprintf(stderr, "failed to open charmap file %s\n", path); + +- for (i = 0; i < char_table_size && c != EOF; i++) +- { +- if (c == '<') +- cd.char_table[i] = get_unicode_char(f); +- leave_line(f); +- c = fgetc(f); +- } ++ if (f != NULL) ++ { ++ cd.char_table = (char **)my_malloc(char_table_size * sizeof(char *)); ++ c = fgetc(f); + +- fclose(f); +- } ++ for (i = 0; i < char_table_size && c != EOF; i++) ++ { ++ if (c == '<') ++ cd.char_table[i] = get_unicode_char(f); ++ leave_line(f); ++ c = fgetc(f); ++ } + +- my_free(path); +- } ++ fclose(f); ++ } + +- return cd; ++ my_free(path); ++ } ++ ++ return cd; + } + + size_t + my_iconv(my_iconv_t cd, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) + { +- int c, i; +- size_t result = 0; ++ int c, i; ++ size_t result = 0; + +- if (cd.desc == (iconv_t) -1) { +- if (cd.char_table != NULL) +- { +- while (*inbytesleft > 0 && *outbytesleft > 0) +- { +- c = (int) **inbuf; +- if (c < 0) +- c = 256 + c; ++ if (cd.desc == (iconv_t) -1) { ++ if (cd.char_table != NULL) ++ { ++ while (*inbytesleft > 0 && *outbytesleft > 0) ++ { ++ c = (int) **inbuf; ++ if (c < 0) ++ c = 256 + c; + +- if (cd.char_table[c] != NULL) +- { +- for (i = 0; cd.char_table[c][i] != '\0' && *outbytesleft > 0; i++) +- { +- **outbuf = cd.char_table[c][i]; +- (*outbytesleft)--; +- (*outbuf)++; +- } +- } ++ if (cd.char_table[c] != NULL) ++ { ++ for (i = 0; cd.char_table[c][i] != '\0' && *outbytesleft > 0; i++) ++ { ++ **outbuf = cd.char_table[c][i]; ++ (*outbytesleft)--; ++ (*outbuf)++; ++ } ++ } + +- (*inbuf)++; +- (*inbytesleft)--; +- result++; +- } +- } +- } +- else +- result = iconv(cd.desc, inbuf, inbytesleft, outbuf, outbytesleft); ++ (*inbuf)++; ++ (*inbytesleft)--; ++ result++; ++ } ++ } ++ } ++ else ++ result = iconv(cd.desc, inbuf, inbytesleft, outbuf, outbytesleft); + +- return result; ++ return result; + } + + my_iconv_t + my_iconv_close(my_iconv_t cd) + { +- int i; ++ int i; + +- if (cd.char_table != NULL) +- { +- for (i = 0; i < char_table_size; i++) +- { +- my_free(cd.char_table[i]); +- } ++ if (cd.char_table != NULL) ++ { ++ for (i = 0; i < char_table_size; i++) ++ { ++ my_free(cd.char_table[i]); ++ } + +- my_free((void *)cd.char_table); +- cd.char_table = NULL; +- } ++ my_free((void *)cd.char_table); ++ cd.char_table = NULL; ++ } + +- if (cd.desc != (iconv_t) -1) +- { +- iconv_close(cd.desc); +- cd.desc = (iconv_t) -1; +- } ++ if (cd.desc != (iconv_t) -1) ++ { ++ iconv_close(cd.desc); ++ cd.desc = (iconv_t) -1; ++ } + +- return cd; ++ return cd; + } + + int + my_iconv_is_valid (my_iconv_t cd) + { +- if (cd.desc != (iconv_t) -1 || cd.char_table != NULL) +- return 1; ++ if (cd.desc != (iconv_t) -1 || cd.char_table != NULL) ++ return 1; + +- return 0; ++ return 0; + } + + void + my_iconv_t_make_invalid(my_iconv_t *cd) + { +- cd->desc = (iconv_t) -1; +- cd->char_table = NULL; ++ cd->desc = (iconv_t) -1; ++ cd->char_table = NULL; + } + +diff -durpN unrtf-0.21.2.old/src/my_iconv.h unrtf-0.21.2/src/my_iconv.h +--- unrtf-0.21.2.old/src/my_iconv.h 2010-07-03 22:30:58.000000000 -0400 ++++ unrtf-0.21.2/src/my_iconv.h 2011-11-09 15:48:29.998798267 -0500 +@@ -5,6 +5,9 @@ + * Purpose: my_conv definitions + *--------------------------------------------------------------------*/ + ++#ifndef _MY_ICONV ++#define _MY_ICONV 1 ++ + #ifndef HAVE_ICONV_H + #include + #define HAVE_ICONV_H +@@ -19,9 +22,9 @@ typedef struct + char **char_table; + } my_iconv_t; + +-#define MY_ICONV_T_CLEAR {(iconv_t) -1, NULL} ++struct ConversionContext; + +-my_iconv_t my_iconv_open(const char *tocode, const char *fromcode); ++my_iconv_t my_iconv_open(const struct ConversionContext *cc, const char *tocode, const char *fromcode); + + size_t my_iconv(my_iconv_t cd, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft); + +@@ -31,3 +34,4 @@ int my_iconv_is_valid(my_iconv_t cd); + + void my_iconv_t_make_invalid(my_iconv_t *cd); + ++#endif /* _MY_ICONV */ +diff -durpN unrtf-0.21.2.old/src/output.c unrtf-0.21.2/src/output.c +--- unrtf-0.21.2.old/src/output.c 2011-06-07 08:04:38.000000000 -0400 ++++ unrtf-0.21.2/src/output.c 2011-11-09 15:50:35.126792073 -0500 +@@ -1,23 +1,23 @@ + /*============================================================================= +- GNU UnRTF, a command-line program to convert RTF documents to other formats. +- Copyright (C) 2000,2001,2004 by Zachary Smith ++ GNU UnRTF, a command-line program to convert RTF documents to other formats. ++ Copyright (C) 2000,2001,2004 by Zachary Smith + +- 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 3 of the License, or +- (at your option) any later version. ++ 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 3 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. ++ 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +- The maintainer is reachable by electronic mail at daved@physiol.usyd.edu.au +-=============================================================================*/ ++ The maintainer is reachable by electronic mail at daved@physiol.usyd.edu.au ++ =============================================================================*/ + + + /*---------------------------------------------------------------------- +@@ -38,7 +38,7 @@ + * David Santinoli + * 09 Nov 08, arkadiusz.firus@gmail.com: use iconv + * 21 Aug 10, daved@physiol.usyd.edu.au: add code to deal with character +- doublets (see convert.c) ++ doublets (see convert.c) + *--------------------------------------------------------------------*/ + + +@@ -64,7 +64,8 @@ + #include "output.h" + #include "main.h" + #include "convert.h" +- ++#include "unrtf.h" ++#include "user.h" + + #ifndef HAVE_ATTR_H + #include "attr.h" +@@ -79,16 +80,16 @@ + *=======================================================================*/ + + OutputPersonality* +-op_create () ++op_create (const struct ConversionContext *cc) + { +- OutputPersonality* new_op; ++ OutputPersonality* new_op; + +- new_op = (OutputPersonality*) my_malloc (sizeof(OutputPersonality)); +- if (!new_op) +- error_handler ("cannot allocate output personality"); ++ new_op = (OutputPersonality*) my_malloc (sizeof(OutputPersonality)); ++ if (!new_op) ++ error_handler (cc, "cannot allocate output personality"); + +- memset ((void*) new_op, 0, sizeof (OutputPersonality)); +- return new_op; ++ memset ((void*) new_op, 0, sizeof (OutputPersonality)); ++ return new_op; + } + + /*======================================================================== +@@ -102,13 +103,15 @@ op_create () + void + op_free (OutputPersonality *op) + { +- CHECK_PARAM_NOT_NULL(op); +- +- my_free ((void*) op); +-} ++ CHECK_PARAM_NOT_NULL(op); + ++ free_user_definitions(op); + ++ if (op->aliases) ++ free_collection(op->aliases); + ++ my_free ((void*) op); ++} + + /*======================================================================== + * Name: op_translate_char +@@ -119,102 +122,110 @@ op_free (OutputPersonality *op) + *=======================================================================*/ + + char * +-op_translate_char (OutputPersonality *op, my_iconv_t cd, int ch) ++op_translate_char (const struct ConversionContext *cc, const OutputPersonality *op, int ch) + { +- short start; +- char *result=NULL; +- static char output_buffer[2]={ 0, 0 }; +- char *inbuf, *outbuf; +- size_t inbytes = (ch / 256) + 1, outbytes = inbytes * 4, i; ++ char *result=NULL; ++ static char output_buffer[2]={ 0, 0 }; ++ char *inbuf, *outbuf, *originbuf, *origoutbuf; ++ size_t inbytes = (ch / 256) + 1, outbytes = inbytes * 4, i; ++ my_iconv_t cd; + +- CHECK_PARAM_NOT_NULL(op); ++ CHECK_PARAM_NOT_NULL(op); + +- if (no_remap_mode == TRUE && ch < 256) +- { +- output_buffer[0]=ch; +- result=output_buffer; +- } +- else +- if (result == NULL) +- { +- inbuf = my_malloc(inbytes + 1); +- outbuf = my_malloc(outbytes + 1); ++ if (cc->options->no_remap_mode == TRUE && ch < 256) ++ { ++ output_buffer[0]=ch; ++ result=strdup(output_buffer); ++ } ++ else ++ if (result == NULL) ++ { ++ originbuf = inbuf = my_malloc(inbytes + 1); ++ origoutbuf = outbuf = my_malloc(outbytes + 1); + +- for (i = inbytes - 1; ch > 255; i--) +- { +- inbuf[i] = ch % 256; +- ch /= 256; +- } ++ for (i = inbytes - 1; ch > 255; i--) ++ { ++ inbuf[i] = ch % 256; ++ ch /= 256; ++ } + +- inbuf[0] = ch; +- inbuf[inbytes] = '\0'; +- i = outbytes; +- if (!my_iconv_is_valid(cd)) +- { +- cd = my_iconv_open("UTF-8", "cp1252"); ++ inbuf[0] = ch; ++ inbuf[inbytes] = '\0'; ++ i = outbytes; ++ if (!my_iconv_is_valid(cc->desc)) ++ { ++ cd = my_iconv_open(cc, "UTF-8", "cp1252"); + +- if (my_iconv(cd, &inbuf, &inbytes, &outbuf, &outbytes) == -1) +- { ++ if (my_iconv(cd, &inbuf, &inbytes, &outbuf, &outbytes) == -1) ++ { + #if 1 /* daved */ +- fprintf(stderr, "unrtf: Error in executing iconv1\n"); ++ fprintf(stderr, "unrtf: Error in executing iconv1\n"); + #else +- fprintf(stderr, "unrtf: Error in executing iconv1\n"); ++ fprintf(stderr, "unrtf: Error in executing iconv1\n"); + #endif +- return NULL; +- } ++ free (originbuf); ++ free (origoutbuf); ++ return NULL; ++ } + +- my_iconv_close(cd); +- } +- else ++ my_iconv_close(cd); ++ } ++ else + +- if (my_iconv(cd, &inbuf, &inbytes, &outbuf, &outbytes) == -1) +- { +- fprintf(stderr, "unrtf: Error in executing iconv\n"); +- return NULL; +- } +- *outbuf = '\0'; +- outbuf -= i - outbytes; +-/* Conversion from string to utf8 code number */ +- inbytes = 0; ++ if (my_iconv(cc->desc, &inbuf, &inbytes, &outbuf, &outbytes) == -1) ++ { ++ fprintf(stderr, "unrtf: Error in executing iconv\n"); ++ free (originbuf); ++ free (origoutbuf); ++ return NULL; ++ } ++ *outbuf = '\0'; ++ outbuf -= i - outbytes; ++ /* Conversion from string to utf8 code number */ ++ inbytes = 0; + +- for (i = 0; outbuf[i] != '\0'; i++) +- inbytes++; ++ for (i = 0; outbuf[i] != '\0'; i++) ++ inbytes++; + +- ch = 0; ++ ch = 0; + +- for (i = 0; i < inbytes; i++) +- { +- if (i == 0) +- switch (inbytes) +- { +- case 1: +- ch = outbuf[0]; +- break; +- case 2: +- ch = (unsigned char) outbuf[0] - 192; +- break; +- case 3: +- ch = (unsigned char) outbuf[0] - 224; +- break; +- case 4: +- ch = (unsigned char) outbuf[0] - 240; +- break; +- } +- else +- ch = (ch * 64) + ((unsigned char) outbuf[i] - 128); +- } +-/* End of conversion*/ ++ for (i = 0; i < inbytes; i++) ++ { ++ if (i == 0) ++ switch (inbytes) ++ { ++ case 1: ++ ch = outbuf[0]; ++ break; ++ case 2: ++ ch = (unsigned char) outbuf[0] - 192; ++ break; ++ case 3: ++ ch = (unsigned char) outbuf[0] - 224; ++ break; ++ case 4: ++ ch = (unsigned char) outbuf[0] - 240; ++ break; ++ } ++ else ++ ch = (ch * 64) + ((unsigned char) outbuf[i] - 128); ++ } ++ /* End of conversion*/ + +- result = get_alias(op, ch); ++ result = get_alias(op, ch); + +- if (result == NULL) +- if (ch > 127 && op->unisymbol_print) +- result = assemble_string(op->unisymbol_print, ch); +- else +- result = outbuf; +- } ++ if (result == NULL) ++ { ++ if (ch > 127 && op->unisymbol_print) ++ result = assemble_string(op->unisymbol_print, ch); ++ else ++ result = outbuf; ++ } + +- return result; ++ free (originbuf); ++ } ++ ++ return result; + } + + #if 0 /* daved - 0.21.2 */ +@@ -227,123 +238,122 @@ op_translate_char (OutputPersonality *op + *=======================================================================*/ + + char * +-op_translate_str (OutputPersonality *op, my_iconv_t cd, int * doublet) ++op_translate_str (const struct ConversionContext *cc, OutputPersonality *op, my_iconv_t cd, int * doublet) + { +- short start; +- char *result=NULL; +- static char output_buffer[3]={ 0, 0, 0 }; +- unsigned char *inbuf; +- char *outbuf; +- int ch; ++ char *result=NULL; ++ static char output_buffer[3]={ 0, 0, 0 }; ++ unsigned char *inbuf; ++ char *outbuf; ++ int ch; + +- fprintf(stderr, "doublet = %o %o\n", *doublet, *(doublet+1)); ++ fprintf(stderr, "doublet = %o %o\n", *doublet, *(doublet+1)); + #if 0 +- size_t inbytes = (ch / 256) + 1, outbytes = inbytes * 4, i; ++ size_t inbytes = (ch / 256) + 1, outbytes = inbytes * 4, i; + #else +- size_t inbytes = 3, outbytes = inbytes * 4, i; ++ size_t inbytes = 3, outbytes = inbytes * 4, i; + #endif + +- CHECK_PARAM_NOT_NULL(op); ++ CHECK_PARAM_NOT_NULL(op); + + #if 0 +- if (no_remap_mode == TRUE && ch < 256) +- { +- output_buffer[0]=ch; +- result=output_buffer; +- } +- else +- if (result == NULL) +- { ++ if (cc->options->no_remap_mode == TRUE && ch < 256) ++ { ++ output_buffer[0]=ch; ++ result=output_buffer; ++ } ++ else ++ if (result == NULL) ++ { + #endif +- inbuf = (char *) my_malloc(inbytes + 1); +- *inbuf = *doublet; +- *(inbuf+1) = (unsigned char *) *(doublet+1); +- *(inbuf+2) = 0; +- fprintf(stderr, "inbuf = %o %o\n", *inbuf, *(inbuf+1)); +- outbuf = my_malloc(outbytes + 1); ++ inbuf = (char *) my_malloc(inbytes + 1); ++ *inbuf = *doublet; ++ *(inbuf+1) = (unsigned char *) *(doublet+1); ++ *(inbuf+2) = 0; ++ fprintf(stderr, "inbuf = %o %o\n", *inbuf, *(inbuf+1)); ++ outbuf = my_malloc(outbytes + 1); + + #if 0 + +- for (i = inbytes - 1; ch > 255; i--) +- { +- inbuf[i] = ch % 256; +- ch /= 256; +- } ++ for (i = inbytes - 1; ch > 255; i--) ++ { ++ inbuf[i] = ch % 256; ++ ch /= 256; ++ } + +- inbuf[0] = ch; +- inbuf[inbytes] = '\0'; ++ inbuf[0] = ch; ++ inbuf[inbytes] = '\0'; + #endif +- i = outbytes; +- if (!my_iconv_is_valid(cd)) +- { +- cd = my_iconv_open("UTF-8", "cp1252"); ++ i = outbytes; ++ if (!my_iconv_is_valid(cd)) ++ { ++ cd = my_iconv_open("UTF-8", "cp1252"); + +- if (my_iconv(cd, &inbuf, &inbytes, &outbuf, &outbytes) == -1) +- { +- fprintf(stderr, "unrtf: Error in executing iconv1\n"); +- return NULL; +- } ++ if (my_iconv(cd, &inbuf, &inbytes, &outbuf, &outbytes) == -1) ++ { ++ fprintf(stderr, "unrtf: Error in executing iconv1\n"); ++ return NULL; ++ } + +- my_iconv_close(cd); +- } +- else +- { ++ my_iconv_close(cd); ++ } ++ else ++ { + +- if (my_iconv(cd, &inbuf, &inbytes, &outbuf, &outbytes) == -1) +- { ++ if (my_iconv(cd, &inbuf, &inbytes, &outbuf, &outbytes) == -1) ++ { + #if 1 /* daved */ +- fprintf(stderr, "unrtf: Error in executing iconv - inbytes=%d inbuf[0]=%o inbuf[1]=%o\n", inbytes, inbuf[0], inbuf[1]); ++ fprintf(stderr, "unrtf: Error in executing iconv - inbytes=%d inbuf[0]=%o inbuf[1]=%o\n", inbytes, inbuf[0], inbuf[1]); + #else +- fprintf(stderr, "unrtf: Error in executing iconv\n"); ++ fprintf(stderr, "unrtf: Error in executing iconv\n"); + #endif +- return NULL; +- } +- } +- *outbuf = '\0'; +- outbuf -= i - outbytes; +-/* Conversion from string to utf8 code number */ +- inbytes = 0; ++ return NULL; ++ } ++ } ++ *outbuf = '\0'; ++ outbuf -= i - outbytes; ++ /* Conversion from string to utf8 code number */ ++ inbytes = 0; + +- for (i = 0; outbuf[i] != '\0'; i++) +- inbytes++; ++ for (i = 0; outbuf[i] != '\0'; i++) ++ inbytes++; + +- ch = 0; ++ ch = 0; + +- for (i = 0; i < inbytes; i++) +- { +- if (i == 0) +- switch (inbytes) +- { +- case 1: +- ch = outbuf[0]; +- break; +- case 2: +- ch = (unsigned char) outbuf[0] - 192; +- break; +- case 3: +- ch = (unsigned char) outbuf[0] - 224; +- break; +- case 4: +- ch = (unsigned char) outbuf[0] - 240; +- break; +- } +- else +- ch = (ch * 64) + ((unsigned char) outbuf[i] - 128); +- } +-/* End of conversion*/ ++ for (i = 0; i < inbytes; i++) ++ { ++ if (i == 0) ++ switch (inbytes) ++ { ++ case 1: ++ ch = outbuf[0]; ++ break; ++ case 2: ++ ch = (unsigned char) outbuf[0] - 192; ++ break; ++ case 3: ++ ch = (unsigned char) outbuf[0] - 224; ++ break; ++ case 4: ++ ch = (unsigned char) outbuf[0] - 240; ++ break; ++ } ++ else ++ ch = (ch * 64) + ((unsigned char) outbuf[i] - 128); ++ } ++ /* End of conversion*/ + +- result = get_alias(op, ch); ++ result = get_alias(op, ch); + +- if (result == NULL) +- if (ch > 127 && op->unisymbol_print) +- result = assemble_string(op->unisymbol_print, ch); +- else +- result = outbuf; ++ if (result == NULL) ++ if (ch > 127 && op->unisymbol_print) ++ result = assemble_string(op->unisymbol_print, ch); ++ else ++ result = outbuf; + #if 0 /* daved 0.21.2 */ +- } ++ } + #endif + +- return result; ++ return result; + } + #endif + +@@ -357,113 +367,115 @@ op_translate_str (OutputPersonality *op, + *=======================================================================*/ + + char * +-op_translate_doublet (OutputPersonality *op, my_iconv_t cd, int ch1, int ch2) ++op_translate_doublet (const struct ConversionContext *cc, const OutputPersonality *op, int ch1, int ch2) + { +- short start; +- char *result=NULL; +- static char output_buffer[3]={ 0, 0, 0 }; +- unsigned char *inbuf; +- char *outbuf; +- int ch; ++ char *result=NULL; ++ static char output_buffer[3]={ 0, 0, 0 }; ++ char *inbuf; ++ char *outbuf; ++ int ch; ++ my_iconv_t cd; + + #if 0 +- size_t inbytes = (ch / 256) + 1, outbytes = inbytes * 4, i; ++ size_t inbytes = (ch / 256) + 1, outbytes = inbytes * 4, i; + #else +- size_t inbytes = 3, outbytes = inbytes * 4, i; ++ size_t inbytes = 3, outbytes = inbytes * 4, i; + #if 0 +- fprintf(stderr, "doublet = %o %o\n", ch1, ch2); ++ fprintf(stderr, "doublet = %o %o\n", ch1, ch2); + #endif + #endif + +- CHECK_PARAM_NOT_NULL(op); ++ CHECK_PARAM_NOT_NULL(op); + +- if (no_remap_mode == TRUE && ch < 256) +- { +- output_buffer[0]=ch1; +- output_buffer[1]=ch2; +- result=output_buffer; +- } +- else +- if (result == NULL) +- { +- inbuf = (char *) my_malloc(inbytes + 1); +- *inbuf = ch1; +- *(inbuf+1) = ch2; +- *(inbuf+2) = 0; ++ if (cc->options->no_remap_mode == TRUE && ch < 256) ++ { ++ output_buffer[0]=ch1; ++ output_buffer[1]=ch2; ++ result=output_buffer; ++ } ++ else ++ if (result == NULL) ++ { ++ inbuf = (char *) my_malloc(inbytes + 1); ++ *inbuf = ch1; ++ *(inbuf+1) = ch2; ++ *(inbuf+2) = 0; + #if 0 +- fprintf(stderr, "inbuf = %o %o\n", *inbuf, *(inbuf+1)); ++ fprintf(stderr, "inbuf = %o %o\n", *inbuf, *(inbuf+1)); + #endif +- outbuf = my_malloc(outbytes + 1); ++ outbuf = my_malloc(outbytes + 1); + +- i = outbytes; +- if (!my_iconv_is_valid(cd)) +- { +- cd = my_iconv_open("UTF-8", "cp1252"); ++ i = outbytes; ++ if (!my_iconv_is_valid(cc->desc)) ++ { ++ cd = my_iconv_open(cc, "UTF-8", "cp1252"); + +- if (my_iconv(cd, (char **)&inbuf, (size_t *)&inbytes, (char **)&outbuf, &outbytes) == -1) +- { +- fprintf(stderr, "unrtf: Error in executing iconv1\n"); +- return NULL; +- } ++ if (my_iconv(cd, (char **)&inbuf, (size_t *)&inbytes, (char **)&outbuf, &outbytes) == -1) ++ { ++ fprintf(stderr, "unrtf: Error in executing iconv1\n"); ++ return NULL; ++ } + +- my_iconv_close(cd); +- } +- else +- { ++ my_iconv_close(cd); ++ } ++ else ++ { + +- if (my_iconv(cd, (char **)&inbuf, (size_t *)&inbytes, (char **)&outbuf, &outbytes) == -1) +- { ++ if (my_iconv(cc->desc, (char **)&inbuf, (size_t *)&inbytes, (char **)&outbuf, &outbytes) == -1) ++ { + #if 1 /* daved */ +- fprintf(stderr, "unrtf: Error in executing iconv - inbytes=%d inbuf[0]=%o inbuf[1]=%o\n", inbytes, inbuf[0], inbuf[1]); ++ fprintf(stderr, "unrtf: Error in executing iconv - inbytes=%d inbuf[0]=%o inbuf[1]=%o\n", inbytes, inbuf[0], inbuf[1]); + #else +- fprintf(stderr, "unrtf: Error in executing iconv\n"); ++ fprintf(stderr, "unrtf: Error in executing iconv\n"); + #endif +- return NULL; +- } +- } +- *outbuf = '\0'; +- outbuf -= i - outbytes; +-/* Conversion from string to utf8 code number */ +- inbytes = 0; ++ return NULL; ++ } ++ } ++ *outbuf = '\0'; ++ outbuf -= i - outbytes; ++ /* Conversion from string to utf8 code number */ ++ inbytes = 0; + +- for (i = 0; outbuf[i] != '\0'; i++) +- inbytes++; ++ for (i = 0; outbuf[i] != '\0'; i++) ++ inbytes++; + +- ch = 0; ++ ch = 0; + +- for (i = 0; i < inbytes; i++) +- { +- if (i == 0) +- switch (inbytes) +- { +- case 1: +- ch = outbuf[0]; +- break; +- case 2: +- ch = (unsigned char) outbuf[0] - 192; +- break; +- case 3: +- ch = (unsigned char) outbuf[0] - 224; +- break; +- case 4: +- ch = (unsigned char) outbuf[0] - 240; +- break; +- } +- else +- ch = (ch * 64) + ((unsigned char) outbuf[i] - 128); +- } +-/* End of conversion*/ ++ for (i = 0; i < inbytes; i++) ++ { ++ if (i == 0) ++ switch (inbytes) ++ { ++ case 1: ++ ch = outbuf[0]; ++ break; ++ case 2: ++ ch = (unsigned char) outbuf[0] - 192; ++ break; ++ case 3: ++ ch = (unsigned char) outbuf[0] - 224; ++ break; ++ case 4: ++ ch = (unsigned char) outbuf[0] - 240; ++ break; ++ } ++ else ++ ch = (ch * 64) + ((unsigned char) outbuf[i] - 128); ++ } ++ /* End of conversion*/ + +- result = get_alias(op, ch); ++ result = get_alias(op, ch); + +- if (result == NULL) +- if (ch > 127 && op->unisymbol_print) +- result = assemble_string(op->unisymbol_print, ch); +- else +- result = outbuf; +- } ++ if (result == NULL) ++ { ++ if (ch > 127 && op->unisymbol_print) ++ result = assemble_string(op->unisymbol_print, ch); ++ else ++ result = outbuf; ++ } ++ } + +- return result; ++ return result; + } + #endif + /*======================================================================== +@@ -475,123 +487,113 @@ op_translate_doublet (OutputPersonality + *=======================================================================*/ + + void +-op_begin_std_fontsize (OutputPersonality *op, int size) ++op_begin_std_fontsize (const OutputContext *oc, int size) + { +- int found_std_expr = FALSE; ++ int found_std_expr = FALSE; ++ const struct unRTFOutputDevice *device = &oc->conversion->options->device; + +- CHECK_PARAM_NOT_NULL(op); ++ CHECK_PARAM_NOT_NULL(oc); + +- /* Look for an exact match with a standard point size. +- */ +- switch (size) { +- case 8: +- if (op->fontsize8_begin) { +- if (safe_printf(0, op->fontsize8_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize8_begin"); +- found_std_expr = TRUE; +- } +- break; +- case 10: +- if (op->fontsize10_begin) { +- if (safe_printf(0, op->fontsize10_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize10_begin"); +- found_std_expr = TRUE; +- } +- break; +- case 12: +- if (op->fontsize12_begin) { +- if (safe_printf(0, op->fontsize12_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize12_begin"); +- found_std_expr = TRUE; +- } +- break; +- case 14: +- if (op->fontsize14_begin) { +- if (safe_printf(0, op->fontsize14_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize14_begin"); +- found_std_expr = TRUE; +- } +- break; +- case 18: +- if (op->fontsize18_begin) { +- if (safe_printf(0, op->fontsize18_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize18_begin"); +- found_std_expr = TRUE; +- } +- break; +- case 24: +- if (op->fontsize24_begin) { +- if (safe_printf(0, op->fontsize24_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize24_begin"); +- found_std_expr = TRUE; +- } +- break; +- case 36: +- if (op->fontsize36_begin) { +- if (safe_printf(0, op->fontsize36_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize36_begin"); +- found_std_expr = TRUE; +- } +- break; +- case 48: +- if (op->fontsize48_begin) { +- if (safe_printf(0, op->fontsize48_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize48_begin"); +- found_std_expr = TRUE; +- } +- break; +- } ++ /* Look for an exact match with a standard point size. ++ */ ++ switch (size) { ++ case 8: ++ if (oc->personality->fontsize8_begin) { ++ if (safe_printf(device, 0, oc->personality->fontsize8_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize8_begin"); ++ found_std_expr = TRUE; ++ } ++ break; ++ case 10: ++ if (oc->personality->fontsize10_begin) { ++ if (safe_printf(device, 0, oc->personality->fontsize10_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize10_begin"); ++ found_std_expr = TRUE; ++ } ++ break; ++ case 12: ++ if (oc->personality->fontsize12_begin) { ++ if (safe_printf(device, 0, oc->personality->fontsize12_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize12_begin"); ++ found_std_expr = TRUE; ++ } ++ break; ++ case 14: ++ if (oc->personality->fontsize14_begin) { ++ if (safe_printf(device, 0, oc->personality->fontsize14_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize14_begin"); ++ found_std_expr = TRUE; ++ } ++ break; ++ case 18: ++ if (oc->personality->fontsize18_begin) { ++ if (safe_printf(device, 0, oc->personality->fontsize18_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize18_begin"); ++ found_std_expr = TRUE; ++ } ++ break; ++ case 24: ++ if (oc->personality->fontsize24_begin) { ++ if (safe_printf(device, 0, oc->personality->fontsize24_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize24_begin"); ++ found_std_expr = TRUE; ++ } ++ break; ++ case 36: ++ if (oc->personality->fontsize36_begin) { ++ if (safe_printf(device, 0, oc->personality->fontsize36_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize36_begin"); ++ found_std_expr = TRUE; ++ } ++ break; ++ case 48: ++ if (oc->personality->fontsize48_begin) { ++ if (safe_printf(device, 0, oc->personality->fontsize48_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize48_begin"); ++ found_std_expr = TRUE; ++ } ++ break; ++ } + +- /* If no exact match, try to write out a change to the +- * exact point size. +- */ +- if (!found_std_expr) { +- if (op->fontsize_begin) { +- char expr[16]; +- sprintf (expr, "%d", size); +- if (safe_printf (1, op->fontsize_begin, expr)) fprintf(stderr, TOO_MANY_ARGS, "fontsize_begin"); +- } else { +- /* If we cannot write out a change for the exact +- * point size, we must approximate to a standard +- * size. +- */ +- if (size<9 && op->fontsize8_begin) { +- if (safe_printf(0, op->fontsize8_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize8_begin"); +- } else +- if (size<11 && op->fontsize10_begin) { +- if (safe_printf(0, op->fontsize10_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize10_begin"); +- } else +- if (size<13 && op->fontsize12_begin) { +- if (safe_printf(0, op->fontsize12_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize12_begin"); +- } else +- if (size<16 && op->fontsize14_begin) { +- if (safe_printf(0, op->fontsize14_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize14_begin"); +- } else +- if (size<21 && op->fontsize18_begin) { +- if (safe_printf(0, op->fontsize18_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize18_begin"); +- } else +- if (size<30 && op->fontsize24_begin) { +- if (safe_printf(0, op->fontsize24_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize24_begin"); +- } else +- if (size<42 && op->fontsize36_begin) { +- if (safe_printf(0, op->fontsize36_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize36_begin"); +- } else +- if (size>40 && op->fontsize48_begin) { +- if (safe_printf(0, op->fontsize48_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize48_begin"); +- } else +- /* If we can't even produce a good approximation, +- * just try to get a font size near 12 point. +- */ +- if (op->fontsize12_begin) +- if (safe_printf(0, op->fontsize12_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize12_begin"); +- else +- if (op->fontsize14_begin) +- if (safe_printf(0, op->fontsize14_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize14_begin"); +- else +- if (op->fontsize10_begin) +- if (safe_printf(0, op->fontsize10_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize10_begin"); +- else +- if (op->fontsize18_begin) +- if (safe_printf(0, op->fontsize18_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize18_begin"); +- else +- if (op->fontsize8_begin) +- if (safe_printf(0, op->fontsize8_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize8_begin"); +- else +- error_handler ("output personality lacks sufficient font size change capability"); +- } +- } ++ /* If no exact match, try to write out a change to the ++ * exact point size. ++ */ ++ if (!found_std_expr) { ++ if (oc->personality->fontsize_begin) { ++ char expr[16]; ++ sprintf (expr, "%d", size); ++ if (safe_printf(device, 1, oc->personality->fontsize_begin, expr)) fprintf(stderr, TOO_MANY_ARGS, "fontsize_begin"); ++ } else { ++ /* If we cannot write out a change for the exact ++ * point size, we must approximate to a standard ++ * size. ++ */ ++ if (size<9 && oc->personality->fontsize8_begin) { ++ if (safe_printf(device, 0, oc->personality->fontsize8_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize8_begin"); ++ } else if (size<11 && oc->personality->fontsize10_begin) { ++ if (safe_printf(device, 0, oc->personality->fontsize10_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize10_begin"); ++ } else if (size<13 && oc->personality->fontsize12_begin) { ++ if (safe_printf(device, 0, oc->personality->fontsize12_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize12_begin"); ++ } else if (size<16 && oc->personality->fontsize14_begin) { ++ if (safe_printf(device, 0, oc->personality->fontsize14_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize14_begin"); ++ } else if (size<21 && oc->personality->fontsize18_begin) { ++ if (safe_printf(device, 0, oc->personality->fontsize18_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize18_begin"); ++ } else if (size<30 && oc->personality->fontsize24_begin) { ++ if (safe_printf(device, 0, oc->personality->fontsize24_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize24_begin"); ++ } else if (size<42 && oc->personality->fontsize36_begin) { ++ if (safe_printf(device, 0, oc->personality->fontsize36_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize36_begin"); ++ } else if (size>40 && oc->personality->fontsize48_begin) { ++ if (safe_printf(device, 0, oc->personality->fontsize48_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize48_begin"); ++ } else if (oc->personality->fontsize12_begin) { ++ /* If we can't even produce a good approximation, ++ * just try to get a font size near 12 point. ++ */ ++ if (safe_printf(device, 0, oc->personality->fontsize12_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize12_begin"); ++ } else if (oc->personality->fontsize14_begin) { ++ if (safe_printf(device, 0, oc->personality->fontsize14_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize14_begin"); ++ } else if (oc->personality->fontsize10_begin) { ++ if (safe_printf(device, 0, oc->personality->fontsize10_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize10_begin"); ++ } else if (oc->personality->fontsize18_begin) { ++ if (safe_printf(device, 0, oc->personality->fontsize18_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize18_begin"); ++ } else if (oc->personality->fontsize8_begin) { ++ if (safe_printf(device, 0, oc->personality->fontsize8_begin)) fprintf(stderr, TOO_MANY_ARGS, "fontsize8_begin"); ++ } else { ++ error_handler (oc->conversion, "output personality lacks sufficient font size change capability"); ++ } ++ } ++ } + } + + +@@ -604,123 +606,113 @@ op_begin_std_fontsize (OutputPersonality + *=======================================================================*/ + + void +-op_end_std_fontsize (OutputPersonality *op, int size) ++op_end_std_fontsize (const OutputContext *oc, int size) + { +- int found_std_expr = FALSE; ++ int found_std_expr = FALSE; ++ const struct unRTFOutputDevice *device = &oc->conversion->options->device; + +- CHECK_PARAM_NOT_NULL(op); ++ CHECK_PARAM_NOT_NULL(oc); + +- /* Look for an exact match with a standard point size. +- */ +- switch (size) { +- case 8: +- if (op->fontsize8_end) { +- if (safe_printf(0, op->fontsize8_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize8_end"); +- found_std_expr = TRUE; +- } +- break; +- case 10: +- if (op->fontsize10_end) { +- if (safe_printf(0, op->fontsize10_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize10_end"); +- found_std_expr = TRUE; +- } +- break; +- case 12: +- if (op->fontsize12_end) { +- if (safe_printf(0, op->fontsize12_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize12_end"); +- found_std_expr = TRUE; +- } +- break; +- case 14: +- if (op->fontsize14_end) { +- if (safe_printf(0, op->fontsize14_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize14_end"); +- found_std_expr = TRUE; +- } +- break; +- case 18: +- if (op->fontsize18_end) { +- if (safe_printf(0, op->fontsize18_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize18_end"); +- found_std_expr = TRUE; +- } +- break; +- case 24: +- if (op->fontsize24_end) { +- if (safe_printf(0, op->fontsize24_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize24_end"); +- found_std_expr = TRUE; +- } +- break; +- case 36: +- if (op->fontsize36_end) { +- if (safe_printf(0, op->fontsize36_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize36_end"); +- found_std_expr = TRUE; +- } +- break; +- case 48: +- if (op->fontsize48_end) { +- if (safe_printf(0, op->fontsize48_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize48_end"); +- found_std_expr = TRUE; +- } +- break; +- } ++ /* Look for an exact match with a standard point size. ++ */ ++ switch (size) { ++ case 8: ++ if (oc->personality->fontsize8_end) { ++ if (safe_printf(device, 0, oc->personality->fontsize8_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize8_end"); ++ found_std_expr = TRUE; ++ } ++ break; ++ case 10: ++ if (oc->personality->fontsize10_end) { ++ if (safe_printf(device, 0, oc->personality->fontsize10_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize10_end"); ++ found_std_expr = TRUE; ++ } ++ break; ++ case 12: ++ if (oc->personality->fontsize12_end) { ++ if (safe_printf(device, 0, oc->personality->fontsize12_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize12_end"); ++ found_std_expr = TRUE; ++ } ++ break; ++ case 14: ++ if (oc->personality->fontsize14_end) { ++ if (safe_printf(device, 0, oc->personality->fontsize14_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize14_end"); ++ found_std_expr = TRUE; ++ } ++ break; ++ case 18: ++ if (oc->personality->fontsize18_end) { ++ if (safe_printf(device, 0, oc->personality->fontsize18_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize18_end"); ++ found_std_expr = TRUE; ++ } ++ break; ++ case 24: ++ if (oc->personality->fontsize24_end) { ++ if (safe_printf(device, 0, oc->personality->fontsize24_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize24_end"); ++ found_std_expr = TRUE; ++ } ++ break; ++ case 36: ++ if (oc->personality->fontsize36_end) { ++ if (safe_printf(device, 0, oc->personality->fontsize36_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize36_end"); ++ found_std_expr = TRUE; ++ } ++ break; ++ case 48: ++ if (oc->personality->fontsize48_end) { ++ if (safe_printf(device, 0, oc->personality->fontsize48_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize48_end"); ++ found_std_expr = TRUE; ++ } ++ break; ++ } + +- /* If no exact match, try to write out a change to the +- * exact point size. +- */ +- if (!found_std_expr) { +- if (op->fontsize_end) { +- char expr[16]; +- sprintf (expr, "%d", size); +- if (safe_printf(1, op->fontsize_end, expr)) fprintf(stderr, TOO_MANY_ARGS, "fontsize_end"); +- } else { +- /* If we cannot write out a change for the exact +- * point size, we must approximate to a standard +- * size. +- */ +- if (size<9 && op->fontsize8_end) { +- if (safe_printf(0, op->fontsize8_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize8_end"); +- } else +- if (size<11 && op->fontsize10_end) { +- if (safe_printf(0, op->fontsize10_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize10_end"); +- } else +- if (size<13 && op->fontsize12_end) { +- if (safe_printf(0, op->fontsize12_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize12_end"); +- } else +- if (size<16 && op->fontsize14_end) { +- if (safe_printf(0, op->fontsize14_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize14_end"); +- } else +- if (size<21 && op->fontsize18_end) { +- if (safe_printf(0, op->fontsize18_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize18_end"); +- } else +- if (size<30 && op->fontsize24_end) { +- if (safe_printf(0, op->fontsize24_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize24_end"); +- } else +- if (size<42 && op->fontsize36_end) { +- if (safe_printf(0, op->fontsize36_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize36_end"); +- } else +- if (size>40 && op->fontsize48_end) { +- if (safe_printf(0, op->fontsize48_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize48_end"); +- } else +- /* If we can't even produce a good approximation, +- * just try to get a font size near 12 point. +- */ +- if (op->fontsize12_end) +- if (safe_printf(0, op->fontsize12_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize12_end"); +- else +- if (op->fontsize14_end) +- if (safe_printf(0, op->fontsize14_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize14_end"); +- else +- if (op->fontsize10_end) +- if (safe_printf(0, op->fontsize10_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize10_end"); +- else +- if (op->fontsize18_end) +- if (safe_printf(0, op->fontsize18_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize18_end"); +- else +- if (op->fontsize8_end) +- if (safe_printf(0, op->fontsize8_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize8_end"); +- else +- error_handler ("output personality lacks sufficient font size change capability"); +- } +- } ++ /* If no exact match, try to write out a change to the ++ * exact point size. ++ */ ++ if (!found_std_expr) { ++ if (oc->personality->fontsize_end) { ++ char expr[16]; ++ sprintf (expr, "%d", size); ++ if (safe_printf(device, 1, oc->personality->fontsize_end, expr)) fprintf(stderr, TOO_MANY_ARGS, "fontsize_end"); ++ } else { ++ /* If we cannot write out a change for the exact ++ * point size, we must approximate to a standard ++ * size. ++ */ ++ if (size<9 && oc->personality->fontsize8_end) { ++ if (safe_printf(device, 0, oc->personality->fontsize8_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize8_end"); ++ } else if (size<11 && oc->personality->fontsize10_end) { ++ if (safe_printf(device, 0, oc->personality->fontsize10_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize10_end"); ++ } else if (size<13 && oc->personality->fontsize12_end) { ++ if (safe_printf(device, 0, oc->personality->fontsize12_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize12_end"); ++ } else if (size<16 && oc->personality->fontsize14_end) { ++ if (safe_printf(device, 0, oc->personality->fontsize14_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize14_end"); ++ } else if (size<21 && oc->personality->fontsize18_end) { ++ if (safe_printf(device, 0, oc->personality->fontsize18_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize18_end"); ++ } else if (size<30 && oc->personality->fontsize24_end) { ++ if (safe_printf(device, 0, oc->personality->fontsize24_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize24_end"); ++ } else if (size<42 && oc->personality->fontsize36_end) { ++ if (safe_printf(device, 0, oc->personality->fontsize36_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize36_end"); ++ } else if (size>40 && oc->personality->fontsize48_end) { ++ if (safe_printf(device, 0, oc->personality->fontsize48_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize48_end"); ++ } else if (oc->personality->fontsize12_end) { ++ /* If we can't even produce a good approximation, ++ * just try to get a font size near 12 point. ++ */ ++ if (safe_printf(device, 0, oc->personality->fontsize12_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize12_end"); ++ } else if (oc->personality->fontsize14_end) { ++ if (safe_printf(device, 0, oc->personality->fontsize14_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize14_end"); ++ } else if (oc->personality->fontsize10_end) { ++ if (safe_printf(device, 0, oc->personality->fontsize10_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize10_end"); ++ } else if (oc->personality->fontsize18_end) { ++ if (safe_printf(device, 0, oc->personality->fontsize18_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize18_end"); ++ } else if (oc->personality->fontsize8_end) { ++ if (safe_printf(device, 0, oc->personality->fontsize8_end)) fprintf(stderr, TOO_MANY_ARGS, "fontsize8_end"); ++ } else { ++ error_handler (oc->conversion, "output personality lacks sufficient font size change capability"); ++ } ++ } ++ } + } + + #if 1 /* AK3 - AF */ +@@ -734,7 +726,7 @@ op_end_std_fontsize (OutputPersonality * + void + add_alias(OutputPersonality *op, int nr, char *text) + { +- op->aliases = (Aliases *)add_to_collection((Collection *)op->aliases, nr, text); ++ op->aliases = (Aliases *)add_to_collection((Collection *)op->aliases, nr, text); + } + + /*======================================================================== +@@ -745,9 +737,8 @@ add_alias(OutputPersonality *op, int nr, + *=======================================================================*/ + + char * +-get_alias(OutputPersonality *op, int nr) ++get_alias(const OutputPersonality *op, int nr) + { +- return get_from_collection((Collection *)op->aliases, nr); ++ return get_from_collection((Collection *)op->aliases, nr); + } + #endif +- +diff -durpN unrtf-0.21.2.old/src/output.h unrtf-0.21.2/src/output.h +--- unrtf-0.21.2.old/src/output.h 2010-08-11 21:09:02.000000000 -0400 ++++ unrtf-0.21.2/src/output.h 2011-11-09 15:48:30.002798270 -0500 +@@ -44,227 +44,228 @@ + typedef Collection Aliases; + + typedef struct { +- int cp; +- unsigned short chars[128]; ++ int cp; ++ unsigned short chars[128]; + } CodepageInfo; + ++typedef struct OutputPersonality { ++ char *comment_begin; ++ char *comment_end; + +-typedef struct { +- char *comment_begin; +- char *comment_end; +- +- char *document_begin; +- char *document_end; ++ char *document_begin; ++ char *document_end; + +- char *header_begin; +- char *header_end; ++ char *header_begin; ++ char *header_end; + +- char *document_title_begin; +- char *document_title_end; ++ char *document_title_begin; ++ char *document_title_end; + +- char *document_keywords_begin; +- char *document_keywords_end; ++ char *document_keywords_begin; ++ char *document_keywords_end; + +- char *document_author_begin; +- char *document_author_end; ++ char *document_author_begin; ++ char *document_author_end; + +- char *document_changedate_begin; +- char *document_changedate_end; ++ char *document_changedate_begin; ++ char *document_changedate_end; + +- char *body_begin; +- char *body_end; ++ char *body_begin; ++ char *body_end; + +- char *word_begin; +- char *word_end; ++ char *word_begin; ++ char *word_end; + +- char *paragraph_begin; +- char *paragraph_end; ++ char *paragraph_begin; ++ char *paragraph_end; + +- char *center_begin; +- char *center_end; ++ char *center_begin; ++ char *center_end; + +- char *align_left_begin; +- char *align_left_end; ++ char *align_left_begin; ++ char *align_left_end; + +- char *align_right_begin; +- char *align_right_end; ++ char *align_right_begin; ++ char *align_right_end; + +- char *justify_begin; +- char *justify_end; ++ char *justify_begin; ++ char *justify_end; + +- char *forced_space; +- char *line_break; +- char *page_break; ++ char *forced_space; ++ char *line_break; ++ char *page_break; + +- char *hyperlink_begin; +- char *hyperlink_end; ++ char *hyperlink_begin; ++ char *hyperlink_end; + +- char *imagelink_begin; +- char *imagelink_end; ++ char *imagelink_begin; ++ char *imagelink_end; + +- char *table_begin; +- char *table_end; ++ char *table_begin; ++ char *table_end; + +- char *table_row_begin; +- char *table_row_end; ++ char *table_row_begin; ++ char *table_row_end; + +- char *table_cell_begin; +- char *table_cell_end; ++ char *table_cell_begin; ++ char *table_cell_end; + +- /* Character attributes */ +- char *font_begin; +- char *font_end; ++ /* Character attributes */ ++ char *font_begin; ++ char *font_end; + +- char *fontsize_begin; +- char *fontsize_end; ++ char *fontsize_begin; ++ char *fontsize_end; + +- /* standard font sizes are optional */ +- char *fontsize8_begin; +- char *fontsize8_end; ++ /* standard font sizes are optional */ ++ char *fontsize8_begin; ++ char *fontsize8_end; + +- char *fontsize10_begin; +- char *fontsize10_end; ++ char *fontsize10_begin; ++ char *fontsize10_end; + +- char *fontsize12_begin; +- char *fontsize12_end; ++ char *fontsize12_begin; ++ char *fontsize12_end; + +- char *fontsize14_begin; +- char *fontsize14_end; ++ char *fontsize14_begin; ++ char *fontsize14_end; + +- char *fontsize18_begin; +- char *fontsize18_end; ++ char *fontsize18_begin; ++ char *fontsize18_end; + +- char *fontsize24_begin; +- char *fontsize24_end; ++ char *fontsize24_begin; ++ char *fontsize24_end; + +- char *fontsize36_begin; +- char *fontsize36_end; ++ char *fontsize36_begin; ++ char *fontsize36_end; + +- char *fontsize48_begin; +- char *fontsize48_end; ++ char *fontsize48_begin; ++ char *fontsize48_end; + +- char *smaller_begin; +- char *smaller_end; ++ char *smaller_begin; ++ char *smaller_end; + +- char *bigger_begin; +- char *bigger_end; ++ char *bigger_begin; ++ char *bigger_end; + +- char *foreground_begin; +- char *foreground_end; ++ char *foreground_begin; ++ char *foreground_end; + +- char *background_begin; +- char *background_end; ++ char *background_begin; ++ char *background_end; + +- char *bold_begin; +- char *bold_end; ++ char *bold_begin; ++ char *bold_end; + +- char *italic_begin; +- char *italic_end; ++ char *italic_begin; ++ char *italic_end; + +- char *underline_begin; +- char *underline_end; ++ char *underline_begin; ++ char *underline_end; + +- char *dbl_underline_begin; +- char *dbl_underline_end; ++ char *dbl_underline_begin; ++ char *dbl_underline_end; + +- char *superscript_begin; +- char *superscript_end; ++ char *superscript_begin; ++ char *superscript_end; + +- char *subscript_begin; +- char *subscript_end; ++ char *subscript_begin; ++ char *subscript_end; + +- char *strikethru_begin; +- char *strikethru_end; ++ char *strikethru_begin; ++ char *strikethru_end; + +- char *dbl_strikethru_begin; +- char *dbl_strikethru_end; ++ char *dbl_strikethru_begin; ++ char *dbl_strikethru_end; + +- char *emboss_begin; +- char *emboss_end; ++ char *emboss_begin; ++ char *emboss_end; + +- char *engrave_begin; +- char *engrave_end; ++ char *engrave_begin; ++ char *engrave_end; + +- char *shadow_begin; +- char *shadow_end; ++ char *shadow_begin; ++ char *shadow_end; + +- char *outline_begin; +- char *outline_end; ++ char *outline_begin; ++ char *outline_end; + +- char *small_caps_begin; +- char *small_caps_end; ++ char *small_caps_begin; ++ char *small_caps_end; + +- char *pointlist_begin; +- char *pointlist_end; ++ char *pointlist_begin; ++ char *pointlist_end; + +- char *pointlist_item_begin; +- char *pointlist_item_end; ++ char *pointlist_item_begin; ++ char *pointlist_item_end; + +- char *numericlist_begin; +- char *numericlist_end; ++ char *numericlist_begin; ++ char *numericlist_end; + +- char *numericlist_item_begin; +- char *numericlist_item_end; ++ char *numericlist_item_begin; ++ char *numericlist_item_end; + +- char *expand_begin; +- char *expand_end; ++ char *expand_begin; ++ char *expand_end; + +- char *toc_entry_begin; +- char *toc_entry_end; ++ char *toc_entry_begin; ++ char *toc_entry_end; + +- char *index_entry_begin; +- char *index_entry_end; ++ char *index_entry_begin; ++ char *index_entry_end; + +- char *fonttable_begin; +- char *fonttable_end; +- char *fonttable_fontnr; +- char *fonttable_fontname; ++ char *fonttable_begin; ++ char *fonttable_end; ++ char *fonttable_fontnr; ++ char *fonttable_fontname; + +- /* XX These should really be replaced by references +- * to one of the charsets. +- */ +- struct { +- char *bullet; +- char *left_quote; +- char *right_quote; +- char *left_dbl_quote; +- char *right_dbl_quote; +- char *nonbreaking_space; +- char *emdash; +- char *endash; +- char *lessthan; +- char *greaterthan; +- char *amp; +- char *copyright; +- char *trademark; +- char *nonbreaking_hyphen; +- char *optional_hyphen; +- } chars; ++ /* XX These should really be replaced by references ++ * to one of the charsets. ++ */ ++ struct { ++ char *bullet; ++ char *left_quote; ++ char *right_quote; ++ char *left_dbl_quote; ++ char *right_dbl_quote; ++ char *nonbreaking_space; ++ char *emdash; ++ char *endash; ++ char *lessthan; ++ char *greaterthan; ++ char *amp; ++ char *copyright; ++ char *trademark; ++ char *nonbreaking_hyphen; ++ char *optional_hyphen; ++ } chars; + +- int simulate_small_caps : 1; +- int simulate_all_caps : 1; +- int simulate_word_underline : 1; +- char *unisymbol_print; +- char *utf8_encoding; +- Aliases *aliases; +-} +-OutputPersonality; ++ int simulate_small_caps : 1; ++ int simulate_all_caps : 1; ++ int simulate_word_underline : 1; ++ char *unisymbol_print; ++ char *utf8_encoding; ++ Aliases *aliases; ++} OutputPersonality; + ++typedef struct OutputContext { ++ struct ConversionContext *conversion; ++ struct OutputPersonality *personality; ++} OutputContext; + +-extern OutputPersonality* op_create(void); ++extern OutputPersonality* op_create(const struct ConversionContext *); + extern void op_free (OutputPersonality*); +-extern char* op_translate_char (OutputPersonality *op, my_iconv_t cd, int ch); ++extern char* op_translate_char (const struct ConversionContext *cc, const OutputPersonality *op, int ch); + #if 1 /* daved - 0.21.2 */ +-extern char* op_translate_str (OutputPersonality *op, my_iconv_t cd, int * doublet); +-extern char* op_translate_doublet (OutputPersonality *op, my_iconv_t cd, int ch1, int ch2); ++extern char* op_translate_str (const struct ConversionContext *cc, const OutputPersonality *op, int * doublet); ++extern char* op_translate_doublet (const struct ConversionContext *cc, const OutputPersonality *op, int ch1, int ch2); + #endif + +-extern void op_begin_std_fontsize (OutputPersonality*, int); +-extern void op_end_std_fontsize (OutputPersonality*, int); ++extern void op_begin_std_fontsize (const struct OutputContext *, int); ++extern void op_end_std_fontsize (const struct OutputContext *, int); + +-void add_alias(OutputPersonality *op, int nr, char *text); +-char *get_alias(OutputPersonality *op, int nr); ++void add_alias(struct OutputPersonality *op, int nr, char *text); ++char *get_alias(const struct OutputPersonality *op, int nr); + + #define _OUTPUT + #endif +- +diff -durpN unrtf-0.21.2.old/src/parse.c unrtf-0.21.2/src/parse.c +--- unrtf-0.21.2.old/src/parse.c 2010-07-03 22:30:58.000000000 -0400 ++++ unrtf-0.21.2/src/parse.c 2011-11-09 15:48:30.002798270 -0500 +@@ -1,23 +1,23 @@ + /*============================================================================= +- GNU UnRTF, a command-line program to convert RTF documents to other formats. +- Copyright (C) 2000,2001 Zachary Thayer Smith ++ GNU UnRTF, a command-line program to convert RTF documents to other formats. ++ Copyright (C) 2000,2001 Zachary Thayer Smith + +- 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 3 of the License, or +- (at your option) any later version. ++ 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 3 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. ++ 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +- The author is reachable by electronic mail at tuorfa@yahoo.com. +-=============================================================================*/ ++ The author is reachable by electronic mail at tuorfa@yahoo.com. ++ =============================================================================*/ + + + /*---------------------------------------------------------------------- +@@ -59,6 +59,7 @@ + #include + #endif + ++#include "convert.h" + #include "defs.h" + #include "parse.h" + #include "malloc.h" +@@ -67,14 +68,6 @@ + #include "word.h" + #include "hash.h" + +- +- +-/* local to getchar stuff */ +-static int ungot_char = -1; +-static int ungot_char2 = -1; +-static int ungot_char3 = -1; +- +- + /*======================================================================== + * Name: my_unget_char + * Purpose: My own unget routine, handling up to 3 ungot characters. +@@ -82,30 +75,16 @@ static int ungot_char3 = -1; + * Returns: None. + *=======================================================================*/ + +-static void my_unget_char (int ch) ++static void my_unget_char (struct ConversionContext *cc, int ch) + { +- if (ungot_char>=0 && ungot_char2>=0 && ungot_char3>=0) +- error_handler("More than 3 ungot chars"); ++ if (cc->ungot_char>=0 && cc->ungot_char2>=0 && cc->ungot_char3>=0) ++ error_handler(cc, "More than 3 ungot chars"); + +- ungot_char3 = ungot_char2; +- ungot_char2 = ungot_char; +- ungot_char = ch; ++ cc->ungot_char3 = cc->ungot_char2; ++ cc->ungot_char2 = cc->ungot_char; ++ cc->ungot_char = ch; + } + +- +-static int last_returned_ch=0; +- +- +-#define READ_BUF_LEN 2048 +-static int buffer_size = 0; +-static char *read_buf = NULL; +-static int read_buf_end = 0; +-static int read_buf_index = 0; +- +- +- +- +- + /*======================================================================== + * Name: my_getchar + * Purpose: Gets a character: either an ungot one, or a buffered one. +@@ -113,76 +92,54 @@ static int read_buf_index = 0; + * Returns: Character, or EOF. + *=======================================================================*/ + +-static int my_getchar (FILE* f) ++static int my_getchar (struct ConversionContext *cc) + { +- int ch; +- +- CHECK_PARAM_NOT_NULL(f); ++ int ch; + +- if (ungot_char>=0) { +- ch = ungot_char; +- ungot_char = ungot_char2; +- ungot_char2 = ungot_char3; +- ungot_char3 = -1; +- last_returned_ch = ch; +- if(ch > 255) +- { +- fprintf(stderr, "returning bad ch = '%c' (0%o)\n", +- ch, ch); +- } +- return ch; +- } +- do { +- if (read_buf_index >= read_buf_end) { +- if (!read_buf) { +- buffer_size = READ_BUF_LEN; +- read_buf = my_malloc (buffer_size); +- if (!read_buf) { +- buffer_size /= 4; +- read_buf = my_malloc (buffer_size); +- if (!read_buf) +- error_handler("Cannot allocate read buffer"); +- } +- } +- read_buf_end = fread (read_buf, 1, buffer_size, f); +- read_buf_index = 0; +- if (!read_buf_end) +- return EOF; +- } +- ch = read_buf [read_buf_index++]; ++ if (cc->ungot_char>=0) { ++ ch = cc->ungot_char; ++ cc->ungot_char = cc->ungot_char2; ++ cc->ungot_char2 = cc->ungot_char3; ++ cc->ungot_char3 = -1; ++ cc->last_returned_ch = ch; ++ if(ch > 255) ++ { ++ fprintf(stderr, "returning bad ch = '%c' (0%o)\n", ++ ch, ch); ++ } ++ return ch; ++ } ++ do { ++ if (cc->read_buf_index >= cc->read_buf_end) { ++ return EOF; ++ } ++ ch = cc->read_buf [cc->read_buf_index++]; + +- if (ch=='\n') { +- lineno++; +- /* Convert \(newline) into \par here */ +- if (last_returned_ch=='\\') { +- my_unget_char (' '); +- my_unget_char ('r'); +- my_unget_char ('a'); +- ch = 'p'; +- break; +- } +- } +- } +- while (ch=='\r' /* || ch=='\n' */ ); ++ if (ch=='\n') { ++ cc->lineno++; ++ /* Convert \(newline) into \par here */ ++ if (cc->last_returned_ch=='\\') { ++ my_unget_char (cc, ' '); ++ my_unget_char (cc, 'r'); ++ my_unget_char (cc, 'a'); ++ ch = 'p'; ++ break; ++ } ++ } ++ } ++ while (ch=='\r' /* || ch=='\n' */ ); + +- if (ch=='\t') ch = ' '; ++ if (ch=='\t') ch = ' '; + +- last_returned_ch = ch; +- if(ch > 255) +- { +- fprintf(stderr,"returning bad ch '%c' (0%o)\n", ch, ch); +- exit(1); +- } +- return ch; ++ cc->last_returned_ch = ch; ++ if(ch > 255) ++ { ++ fprintf(stderr,"returning bad ch '%c' (0%o)\n", ch, ch); ++ exit(1); ++ } ++ return ch; + } + +- +-/* local to read_word */ +-static char *input_str = NULL; +-static unsigned long current_max_length = 1; +- +- +- + /*======================================================================== + * Name: expand_word_buffer + * Purpose: Expands the buffer used to store an incoming word. +@@ -192,22 +149,22 @@ static unsigned long current_max_length + *=======================================================================*/ + + static int +-expand_word_buffer () ++expand_word_buffer (struct ConversionContext *cc) + { +- char *new_ptr; +- unsigned long old_length; +- if (!input_str) +- error_handler("No input buffer allocated"); +- old_length = current_max_length; +- current_max_length *= 2; +- new_ptr = my_malloc (current_max_length); +- if (!new_ptr) +- error_handler("Out of memory while resizing buffer"); ++ char *new_ptr; ++ unsigned long old_length; ++ if (!cc->input_str) ++ error_handler(cc, "No input buffer allocated"); ++ old_length = cc->current_max_length; ++ cc->current_max_length *= 2; ++ new_ptr = my_malloc (cc->current_max_length); ++ if (!new_ptr) ++ error_handler(cc, "Out of memory while resizing buffer"); + +- memcpy (new_ptr, input_str, old_length); +- my_free(input_str); +- input_str = new_ptr; +- return TRUE; ++ memcpy (new_ptr, cc->input_str, old_length); ++ my_free(cc->input_str); ++ cc->input_str = new_ptr; ++ return TRUE; + } + + +@@ -222,183 +179,181 @@ expand_word_buffer () + *=======================================================================*/ + + static int +-read_word (FILE *f) ++read_word (struct ConversionContext *cc) + { +- int ch, ch2; +- unsigned long ix=0; +- int have_whitespace=FALSE; +- int is_control_word=FALSE; +- int has_numeric_param=FALSE; /* if is_control_word==TRUE */ +- int need_unget=FALSE; +- +- CHECK_PARAM_NOT_NULL(f); ++ int ch, ch2; ++ unsigned long ix=0; ++ int have_whitespace=FALSE; ++ int is_control_word=FALSE; ++ int has_numeric_param=FALSE; /* if is_control_word==TRUE */ ++ int need_unget=FALSE; + +- current_max_length = 10; /* XX */ ++ cc->current_max_length = 10; /* XX */ + +- /* Get some storage for a word. +- */ +- input_str = my_malloc (current_max_length); +- if (!input_str) +- error_handler("Cannot allocate word storage"); ++ /* Get some storage for a word. ++ */ ++ cc->input_str = my_malloc (cc->current_max_length); ++ if (!cc->input_str) ++ error_handler(cc, "Cannot allocate word storage"); + +- do { +- ch = my_getchar(f); +- } +- while (ch=='\n'); ++ do { ++ ch = my_getchar(cc); ++ } ++ while (ch=='\n'); + +- if (ch==' ') +- { +- /* Compress multiple space chars down to one. +- */ +- while (ch == ' ') { +- ch = my_getchar(f); +- have_whitespace=TRUE; +- } +- if (have_whitespace) { +- my_unget_char (ch); +- input_str[0]=' '; +- input_str[1]=0; +- return 1; +- } +- } ++ if (ch==' ') ++ { ++ /* Compress multiple space chars down to one. ++ */ ++ while (ch == ' ') { ++ ch = my_getchar(cc); ++ have_whitespace=TRUE; ++ } ++ if (have_whitespace) { ++ my_unget_char (cc, ch); ++ cc->input_str[0]=' '; ++ cc->input_str[1]=0; ++ return 1; ++ } ++ } + +- switch(ch) +- { +- case EOF: +- return 0; ++ switch(ch) ++ { ++ case EOF: ++ return 0; + +- case '\\': +- ch2 = my_getchar(f); ++ case '\\': ++ ch2 = my_getchar(cc); + +- /* Look for two-character command words. +- */ +- switch (ch2) +- { +- case '\n': +- strcpy (input_str, "\\par"); +- return 4; +- case '~': +- case '{': +- case '}': +- case '\\': +- case '_': +- case '-': +- input_str[0] = '\\'; +- input_str[1] = ch2; +- input_str[2] = 0; +- return 2; +- case '\'': +- /* Preserve \'## expressions (hex char exprs) for later. +- */ +- input_str[0]='\\'; +- input_str[1]='\''; +- ix=2; +- if(ix==current_max_length) { +- if (!expand_word_buffer ()) +- error_handler("Word too long"); +- } +- ch = my_getchar(f); +- input_str[ix++]=ch; +- if(ix==current_max_length) { +- if (!expand_word_buffer ()) +- error_handler("Word too long"); +- } +- ch = my_getchar(f); +- input_str[ix++]=ch; +- if(ix==current_max_length) { +- if (!expand_word_buffer ()) +- error_handler("Word too long"); +- } +- input_str[ix]=0; +- return ix; +- } ++ /* Look for two-character command words. ++ */ ++ switch (ch2) ++ { ++ case '\n': ++ strcpy (cc->input_str, "\\par"); ++ return 4; ++ case '~': ++ case '{': ++ case '}': ++ case '\\': ++ case '_': ++ case '-': ++ cc->input_str[0] = '\\'; ++ cc->input_str[1] = ch2; ++ cc->input_str[2] = 0; ++ return 2; ++ case '\'': ++ /* Preserve \'## expressions (hex char exprs) for later. ++ */ ++ cc->input_str[0]='\\'; ++ cc->input_str[1]='\''; ++ ix=2; ++ if(ix==cc->current_max_length) { ++ if (!expand_word_buffer (cc)) ++ error_handler(cc, "Word too long"); ++ } ++ ch = my_getchar(cc); ++ cc->input_str[ix++]=ch; ++ if(ix==cc->current_max_length) { ++ if (!expand_word_buffer (cc)) ++ error_handler(cc, "Word too long"); ++ } ++ ch = my_getchar(cc); ++ cc->input_str[ix++]=ch; ++ if(ix==cc->current_max_length) { ++ if (!expand_word_buffer (cc)) ++ error_handler(cc, "Word too long"); ++ } ++ cc->input_str[ix]=0; ++ return ix; ++ } + +- is_control_word=TRUE; +- ix=1; +- input_str[0]=ch; +- ch=ch2; +- break; ++ is_control_word=TRUE; ++ ix=1; ++ cc->input_str[0]=ch; ++ ch=ch2; ++ break; + +- case '\t': +- /* In RTF, a tab char is the same as \tab. +- */ +- strcpy (input_str, "\\tab"); +- return 4; ++ case '\t': ++ /* In RTF, a tab char is the same as \tab. ++ */ ++ strcpy (cc->input_str, "\\tab"); ++ return 4; + +- case '{': +- case '}': +- case ';': +- input_str[0]=ch; +- input_str[1]=0; +- return 1; ++ case '{': ++ case '}': ++ case ';': ++ cc->input_str[0]=ch; ++ cc->input_str[1]=0; ++ return 1; + +- } ++ } + +- while (ch!=EOF) +- { +- /* Several chars always ends a word, and we need to save them. +- */ +- if (ch=='\t' || ch=='{' || ch=='}' || ch=='\\') { +- need_unget=TRUE; +- break; +- } ++ while (ch!=EOF) ++ { ++ /* Several chars always ends a word, and we need to save them. ++ */ ++ if (ch=='\t' || ch=='{' || ch=='}' || ch=='\\') { ++ need_unget=TRUE; ++ break; ++ } + +- /* A newline always ends a command word; we don't save it. +- * A newline is ignored if this is not a command word. +- */ +- if (ch=='\n') { +- if (is_control_word) +- break; +- ch = my_getchar(f); +- continue; +- } ++ /* A newline always ends a command word; we don't save it. ++ * A newline is ignored if this is not a command word. ++ */ ++ if (ch=='\n') { ++ if (is_control_word) ++ break; ++ ch = my_getchar(cc); ++ continue; ++ } + +- /* A semicolon always ends a command word; we do save it. +- * A semicolon never ends a regular word. +- */ +- if (ch==';') { +- if (is_control_word) { +- need_unget=TRUE; +- break; +- } +- } ++ /* A semicolon always ends a command word; we do save it. ++ * A semicolon never ends a regular word. ++ */ ++ if (ch==';') { ++ if (is_control_word) { ++ need_unget=TRUE; ++ break; ++ } ++ } + +- /* In this parser, a space character terminates +- * any word, and if it does not follow a command, +- * then it is a word in itself. +- */ +- if (ch==' ') { +- if (!is_control_word) +- need_unget=TRUE; +- break; +- } ++ /* In this parser, a space character terminates ++ * any word, and if it does not follow a command, ++ * then it is a word in itself. ++ */ ++ if (ch==' ') { ++ if (!is_control_word) ++ need_unget=TRUE; ++ break; ++ } + +- /* Identify a control word's numeric parameter. +- */ +- if (is_control_word) { +- if (!has_numeric_param && (isdigit(ch) || ch=='-')) +- has_numeric_param = TRUE; +- else +- if (has_numeric_param && !isdigit(ch)) { +- if (ch!=' ') +- need_unget=TRUE; +- break; +- } +- } ++ /* Identify a control word's numeric parameter. ++ */ ++ if (is_control_word) { ++ if (!has_numeric_param && (isdigit(ch) || ch=='-')) ++ has_numeric_param = TRUE; ++ else ++ if (has_numeric_param && !isdigit(ch)) { ++ if (ch!=' ') ++ need_unget=TRUE; ++ break; ++ } ++ } + +- input_str[ix++] = ch; +- if (ix==current_max_length) { +- if (!expand_word_buffer ()) +- error_handler("Word too long"); +- } +- ch = my_getchar (f); +- } ++ cc->input_str[ix++] = ch; ++ if (ix==cc->current_max_length) { ++ if (!expand_word_buffer (cc)) ++ error_handler(cc, "Word too long"); ++ } ++ ch = my_getchar (cc); ++ } + +- if (need_unget) +- my_unget_char(ch); ++ if (need_unget) ++ my_unget_char(cc, ch); + +- input_str[ix]=0; +- return ix; ++ cc->input_str[ix]=0; ++ return ix; + } + + +@@ -412,44 +367,42 @@ read_word (FILE *f) + *=======================================================================*/ + + Word * +-word_read (FILE* f) { +- Word * prev_word = NULL; +- Word * first_word = NULL; +- Word * new_word = NULL; /* temp */ +- +- CHECK_PARAM_NOT_NULL(f); +- +- do { +- if (!read_word(f)) +- return first_word; ++word_read (struct ConversionContext *cc) { ++ Word * prev_word = NULL; ++ Word * first_word = NULL; ++ Word * new_word = NULL; /* temp */ + +- if (input_str[0] == '{') { +- /* Process subwords */ ++ do { ++ if (!read_word(cc)) ++ return first_word; + +- /* Create a dummy word to point to a sublist */ +- new_word = word_new(NULL); +- if (!new_word) +- error_handler("Cannot allocate word"); ++ if (cc->input_str[0] == '{') { ++ /* Process subwords */ + +- /* Get the sublist */ +- new_word->child = word_read(f); ++ /* Create a dummy word to point to a sublist */ ++ new_word = word_new(cc, NULL); ++ if (!new_word) ++ error_handler(cc, "Cannot allocate word"); + +- } else if (input_str[0] == '}') { +- return first_word; +- } else { +- new_word = word_new(input_str); +- } ++ /* Get the sublist */ ++ new_word->child = word_read(cc); ++ ++ } else if (cc->input_str[0] == '}') { ++ return first_word; ++ } else { ++ new_word = word_new(cc, cc->input_str); ++ } + +- if (prev_word) +- prev_word->next = new_word; ++ if (prev_word) ++ prev_word->next = new_word; + +- if (!first_word) +- first_word = new_word; ++ if (!first_word) ++ first_word = new_word; + +- prev_word = new_word; ++ prev_word = new_word; + +- /* Free up the memory allocated by read_word. */ +- my_free(input_str); +- input_str = NULL; +- } while (1); ++ /* Free up the memory allocated by read_word. */ ++ my_free(cc->input_str); ++ cc->input_str = NULL; ++ } while (1); + } +diff -durpN unrtf-0.21.2.old/src/parse.h unrtf-0.21.2/src/parse.h +--- unrtf-0.21.2.old/src/parse.h 2010-07-03 22:30:58.000000000 -0400 ++++ unrtf-0.21.2/src/parse.h 2011-11-09 15:48:30.002798270 -0500 +@@ -38,8 +38,6 @@ + #include "word.h" + #endif + ++struct ConversionContext; + +-extern Word *word_read(FILE*); +- +- +- ++extern Word *word_read(struct ConversionContext *cc); +diff -durpN unrtf-0.21.2.old/src/path.c unrtf-0.21.2/src/path.c +--- unrtf-0.21.2.old/src/path.c 2010-07-03 22:30:58.000000000 -0400 ++++ unrtf-0.21.2/src/path.c 1969-12-31 19:00:00.000000000 -0500 +@@ -1,55 +0,0 @@ +-#include +-#include +-#include +-#include +- +-#include "path.h" +- +-struct path_dir *path_dir_p = &topdir; +- +-int check_dirs() +-{ +- char *p; +- char *colon; +- char *dir_name; +- int a; +- +- for(p = search_path; *p != '\0';) +- { +- dir_name = p; +- if((colon = strchr(p, ':')) != NULL) +- { +- p = colon; +- *p++ = '\0'; +- } +- else +- p += strlen(p); +- a = access(dir_name, R_OK|X_OK); +- if(a) +- continue; +- path_dir_p->dir_name = dir_name; +- if((path_dir_p->next = (struct path_dir *)malloc(sizeof (struct path_dir))) == NULL) +- { +- fprintf(stderr,"cannot malloc\n"); +- exit(1); +- } +- path_dir_p = path_dir_p->next; +- path_dir_p->dir_name = 0; +- n_path_dirs++; +- } +- path_checked = 1; +- return(n_path_dirs); +-} +- +-void show_dirs() +-{ +- if(n_path_dirs == 0) +- { +- fprintf(stderr,"no directories to show\n"); +- exit(1); +- } +- fprintf(stderr,"show_dirs: %d directories\n", n_path_dirs); +- for(path_dir_p = &topdir; path_dir_p->dir_name; path_dir_p = path_dir_p->next) +- fprintf(stderr,"directory = %s\n", path_dir_p->dir_name); +-} +- +diff -durpN unrtf-0.21.2.old/src/path.h unrtf-0.21.2/src/path.h +--- unrtf-0.21.2.old/src/path.h 2010-07-03 22:30:58.000000000 -0400 ++++ unrtf-0.21.2/src/path.h 1969-12-31 19:00:00.000000000 -0500 +@@ -1,16 +0,0 @@ +-#define DEFAULT_UNRTF_SEARCH_PATH "/usr/local/lib/unrtf/" +- +-char *search_path; +-int n_path_dirs; +-int path_checked; +- +-struct path_dir +-{ +- char *dir_name; +- struct path_dir *next; +-}; +- +-struct path_dir topdir; +- +-int check_dirs(); +-void show_dirs(); +diff -durpN unrtf-0.21.2.old/src/unrtf.h unrtf-0.21.2/src/unrtf.h +--- unrtf-0.21.2.old/src/unrtf.h 1969-12-31 19:00:00.000000000 -0500 ++++ unrtf-0.21.2/src/unrtf.h 2011-11-09 15:48:30.002798270 -0500 +@@ -0,0 +1,55 @@ ++/*=========================================================================== ++ GNU UnRTF, a command-line program to convert RTF documents to other formats. ++ Copyright (C) 2000,2001,2004 by Zachary Smith ++ Copyright (C) 2011 by Inverse ++ ++ 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ ++ The maintainer is reachable by electronic mail at daved@physiol.usyd.edu.au ++===========================================================================*/ ++ ++#ifndef UNRTF_H ++#define UNRTF_H ++ ++typedef int (*unrtf_output_device_func)(void *, const char *, size_t); ++ ++struct unRTFOutputDevice { ++ unrtf_output_device_func print; ++ void *data; ++}; ++ ++typedef struct unRTFOptions { ++ struct unRTFOutputDevice device; /* stdout if NULL */ ++ const char *config_directory; ++ const char *output_format; /* DEFAULT_OUTPUT if NULL */ ++ ++ int nopict_mode; /* TRUE => Do not write \pict's to files */ ++ int dump_mode; /* TRUE => Output a dump of the RTF word tree */ ++ int debug_mode; /* TRUE => Output debug comments within HTML */ ++ int simple_mode; /* TRUE => Output HTML without SPAN/DIV tags -- This would ++ probably be more useful if we could pull out tags ++ as well. */ ++ int inline_mode; /* TRUE => Output HTML without HTML/BODY/HEAD -- This is ++ buggy. I've seen it output pages of tags. */ ++ /* marcossamaral - 0.19.9 */ ++ int verbose_mode; /* TRUE => Output additional informations about unrtf */ ++ int no_remap_mode; /* don't remap codepoints */ ++} unRTFOptions; ++ ++void unrtf_set_output_device (unRTFOptions *, unrtf_output_device_func, void *); ++int unrtf_convert_from_filename (unRTFOptions *, const char *); ++int unrtf_convert_from_string (unRTFOptions *, const char *, size_t); ++ ++#endif /* UNRTF_H */ +diff -durpN unrtf-0.21.2.old/src/user.c unrtf-0.21.2/src/user.c +--- unrtf-0.21.2.old/src/user.c 2011-06-07 08:08:17.000000000 -0400 ++++ unrtf-0.21.2/src/user.c 2011-11-09 15:48:30.002798270 -0500 +@@ -7,7 +7,7 @@ + *---------------------------------------------------------------------- + * Changes: + * 21 Aug 10, daved@physiol.usyd.edu.au: test feof() rather than EOF for +- AIX support ++ AIX support + *--------------------------------------------------------------------*/ + + #ifndef HAVE_STDIO_H +@@ -38,9 +38,9 @@ + + typedef struct my_F + { +- FILE *file; +- int line_nr; +- char *name; ++ FILE *file; ++ int line_nr; ++ char *name; + } my_FILE; + + +@@ -54,15 +54,15 @@ typedef struct my_F + my_FILE * + my_fopen(char *file_name, char *mode) + { +- my_FILE *f = (my_FILE *) malloc(sizeof(my_FILE)); ++ my_FILE *f = (my_FILE *) malloc(sizeof(my_FILE)); + +- if ((f->file = fopen(file_name, "r")) == NULL || (f->name = my_malloc((strlen(file_name) + 1) * sizeof(char))) == NULL) +- return NULL; ++ if ((f->file = fopen(file_name, "r")) == NULL || (f->name = my_malloc((strlen(file_name) + 1) * sizeof(char))) == NULL) ++ return NULL; + +- f->line_nr = 1; +- strcpy(f->name, file_name); ++ f->line_nr = 1; ++ strcpy(f->name, file_name); + +- return f; ++ return f; + } + + /*======================================================================== +@@ -75,8 +75,8 @@ my_fopen(char *file_name, char *mode) + void + my_fclose(my_FILE *f) + { +- fclose(f->file); +- my_free(f->name); ++ fclose(f->file); ++ my_free(f->name); + } + + /*======================================================================== +@@ -86,103 +86,103 @@ my_fclose(my_FILE *f) + * Returns: Definition or NULL on error. + *=======================================================================*/ + +-#define ADD_CHAR(char)\ +- if (def_buffer_length == chars_nr)\ +- {\ +- if ((def = my_realloc(def, def_buffer_length, def_buffer_length * 2)) == NULL)\ +- {\ +- perror("Cannot allocate memory.");\ +- return NULL;\ +- }\ +- def_buffer_length *= 2;\ +- }\ +- def[chars_nr] = char;\ +- chars_nr++; ++#define ADD_CHAR(char) \ ++ if (def_buffer_length == chars_nr) \ ++ { \ ++ if ((def = my_realloc(def, def_buffer_length, def_buffer_length * 2)) == NULL) \ ++ { \ ++ perror("Cannot allocate memory."); \ ++ return NULL; \ ++ } \ ++ def_buffer_length *= 2; \ ++ } \ ++ def[chars_nr] = char; \ ++ chars_nr++; + + char * + give_definition(my_FILE *file) + { +- char c, c2 = 0, c3 = 0, c4 = 0, *def, *unicode_char; +- int i; +- unsigned long def_buffer_length = STANDARD_BUFFER_LENGTH, chars_nr = 0; ++ char c, c2 = 0, c3 = 0, c4 = 0, *def, *unicode_char; ++ int i; ++ unsigned long def_buffer_length = STANDARD_BUFFER_LENGTH, chars_nr = 0; + +- if ((def = my_malloc(def_buffer_length)) == NULL) +- return NULL; ++ if ((def = my_malloc(def_buffer_length)) == NULL) ++ return NULL; + +- c = fgetc(file->file); ++ c = fgetc(file->file); + +- while (c == '\t' || c == '#') +- { +- if (c == '#') +- leave_line(file->file); +- else +- { +- c = fgetc(file->file); ++ while (c == '\t' || c == '#') ++ { ++ if (c == '#') ++ leave_line(file->file); ++ else ++ { ++ c = fgetc(file->file); + + #if 1 /* daved 0.21.2 */ +- while (c != '\n' && !feof(file->file)) ++ while (c != '\n' && !feof(file->file)) + #else +- while (c != '\n' && c != EOF) ++ while (c != '\n' && c != EOF) + #endif +- { +- if (c == 'U' && c2 == '<' && (c3 != '\\' || (c3 == '\\' && c4 == '\\'))) +- { +- unicode_char = get_unicode_char(file->file); ++ { ++ if (c == 'U' && c2 == '<' && (c3 != '\\' || (c3 == '\\' && c4 == '\\'))) ++ { ++ unicode_char = get_unicode_char(file->file); + +- for (i = 0; unicode_char[i] != '\0'; i++) +- ADD_CHAR(unicode_char[i]) +- c = fgetc(file->file); +- c2 = 0; +- c3 = 0; +- c4 = 0; +- } +- else +- { +- if (c2 == '<') +- { +- ADD_CHAR('<'); +- } ++ for (i = 0; unicode_char[i] != '\0'; i++) ++ ADD_CHAR(unicode_char[i]) ++ c = fgetc(file->file); ++ c2 = 0; ++ c3 = 0; ++ c4 = 0; ++ } ++ else ++ { ++ if (c2 == '<') ++ { ++ ADD_CHAR('<'); ++ } + +- /* daved - support \n in definitions */ +- if (c == 'n' && c2 == '\\') +- { +- ADD_CHAR('\n'); +- } +- else +- if (c != '<' && c != '\\' || (c == '\\' && c2 == '\\')) +- { +- ADD_CHAR(c) +- } ++ /* daved - support \n in definitions */ ++ if (c == 'n' && c2 == '\\') ++ { ++ ADD_CHAR('\n'); ++ } ++ else ++ if (c != '<' && c != '\\' || (c == '\\' && c2 == '\\')) ++ { ++ ADD_CHAR(c); ++ } + +- c4 = c3; +- c3 = c2; +- c2 = c; +- c = fgetc(file->file); +- } +- } ++ c4 = c3; ++ c3 = c2; ++ c2 = c; ++ c = fgetc(file->file); ++ } ++ } + +- file->line_nr++; +- ADD_CHAR('\n'); +- } ++ file->line_nr++; ++ ADD_CHAR('\n'); ++ } + +- c = fgetc(file->file); +- } ++ c = fgetc(file->file); ++ } + + #if 1 /* daved 0.21.2 */ +- if (!feof(file->file)) ++ if (!feof(file->file)) + #else +- if (c != EOF) ++ if (c != EOF) + #endif +- { +- ungetc(c, file->file); +- } ++ { ++ ungetc(c, file->file); ++ } + +- if (chars_nr > 0) +- def[chars_nr - 1] = '\0'; +- else +- def[0] = '\0'; ++ if (chars_nr > 0) ++ def[chars_nr - 1] = '\0'; ++ else ++ def[0] = '\0'; + +- return def; ++ return def; + } + + /*======================================================================== +@@ -190,49 +190,71 @@ give_definition(my_FILE *file) + * Purpose: Tries to match known tag names with first argument + * Args: Tag name, Output Personality, file to read from + * Returns: -1 on error, +- 0 on success, +- 1 when tag name "name" is unknown ++ 0 on success, ++ 1 when tag name "name" is unknown + *=======================================================================*/ + + int + match_name (char *name, OutputPersonality *op, my_FILE *file) + { +- struct definition +- { +- char *name; +- char **variable; +- } defs[] = DEFS_ARRAY(op); +- +- char *endptr; +- int i; ++ struct definition ++ { ++ char *name; ++ char **variable; ++ } defs[] = DEFS_ARRAY(op); ++ char *def, *endptr; ++ int i; + + #if 1 /* daved 0.21.0-rc2 */ +- for (i = 0; defs[i].name && strcmp(defs[i].name, name); i++); ++ for (i = 0; defs[i].name && strcmp(defs[i].name, name); i++); + +- if (!defs[i].name) ++ if (!defs[i].name) + #else +- for (i = 0; defs[i].name[0] != '\0' && strcmp(defs[i].name, name); i++); ++ for (i = 0; defs[i].name[0] != '\0' && strcmp(defs[i].name, name); i++); + +- if (defs[i].name[0] == '\0') ++ if (defs[i].name[0] == '\0') + #endif +- { +- i = strtol(name, &endptr, 10); ++ { ++ i = strtol(name, &endptr, 10); + +- if (*endptr == '\0') +- add_alias(op, i, give_definition(file)); +- else if (name[0] == '<' && name[1] == 'U') +- add_alias(op, get_unicode(&name[2]), give_definition(file)); +- else +- { +- fprintf(stderr, "unrtf: unknown name \"%s\" in line %d of \"%s\"\n", name, file->line_nr, file->name); +- return 1; +- } +- } +- else +- if ((*defs[i].variable = give_definition(file)) == NULL) +- return -1; ++ def = give_definition(file); ++ if (*endptr == '\0') ++ add_alias(op, i, def); ++ else if (name[0] == '<' && name[1] == 'U') ++ add_alias(op, get_unicode(&name[2]), def); ++ else ++ { ++ my_free (def); ++ fprintf(stderr, "unrtf: unknown name \"%s\" in line %d of \"%s\"\n", name, file->line_nr, file->name); ++ return 1; ++ } ++ my_free (def); ++ } ++ else ++ if ((*defs[i].variable = give_definition(file)) == NULL) ++ return -1; + +- return 0; ++ return 0; ++} ++ ++void ++free_user_definitions (OutputPersonality *op) ++{ ++ struct definition ++ { ++ char *name; ++ char **variable; ++ } defs[] = DEFS_ARRAY(op); ++ char *variable; ++ int i; ++ ++ for (i = 0; defs[i].name; i++) ++ { ++ variable = *defs[i].variable; ++ if (variable) ++ free(variable); ++ *defs[i].variable = NULL; ++ } + } + + /*======================================================================== +@@ -243,52 +265,55 @@ match_name (char *name, OutputPersonalit + *=======================================================================*/ + + OutputPersonality * +-user_init (OutputPersonality *op, char *definitions_file_path) ++user_init (const struct ConversionContext *cc, char *definitions_file_path) + { +- my_FILE *f; +- char name_buffer[BUFFER_SIZE]; ++ my_FILE *f; ++ char name_buffer[BUFFER_SIZE]; ++ OutputPersonality *op; + +- if (op == NULL) +- op = op_create(); ++ op = op_create(cc); + +- if ((f = my_fopen(definitions_file_path, "r")) == NULL) +- { +- perror(definitions_file_path); +- return op; +- } ++ if ((f = my_fopen(definitions_file_path, "r")) == NULL) ++ { ++ perror(definitions_file_path); ++ op_free (op); ++ op = NULL; ++ return op; ++ } + + #if 1 /* daved 0.21.2 */ +- while +- ( +- fgets(name_buffer, BUFFER_SIZE - 1, f->file) != NULL +- && +- !feof(f->file) +- ) ++ while ++ ( ++ fgets(name_buffer, BUFFER_SIZE - 1, f->file) != NULL ++ && ++ !feof(f->file) ++ ) + #else +- while (fgets(name_buffer, BUFFER_SIZE - 1, f->file) != NULL) ++ while (fgets(name_buffer, BUFFER_SIZE - 1, f->file) != NULL) + #endif +- { +- if (name_buffer[strlen(name_buffer) - 1] != '\n') +- leave_line(f->file); ++ { ++ if (name_buffer[strlen(name_buffer) - 1] != '\n') ++ leave_line(f->file); + +- f->line_nr++; ++ f->line_nr++; + +- if (name_buffer[0] != '#' && name_buffer[0] != '\n') +- { +- name_buffer[strlen(name_buffer) - 1] = '\0'; ++ if (name_buffer[0] != '#' && name_buffer[0] != '\n') ++ { ++ name_buffer[strlen(name_buffer) - 1] = '\0'; + +- if (match_name(name_buffer, op, f) == -1) +- { +- my_fclose(f); +- free(f); +- return NULL; +- } +- } +- } ++ if (match_name(name_buffer, op, f) == -1) ++ { ++ my_fclose(f); ++ free(f); ++ op_free (op); ++ return NULL; ++ } ++ } ++ } + +- my_fclose(f); +- free(f); ++ my_fclose(f); ++ free(f); + +- return op; ++ return op; + } + +diff -durpN unrtf-0.21.2.old/src/user.h unrtf-0.21.2/src/user.h +--- unrtf-0.21.2.old/src/user.h 2010-07-03 22:30:58.000000000 -0400 ++++ unrtf-0.21.2/src/user.h 2011-11-09 15:48:30.002798270 -0500 +@@ -151,9 +151,10 @@ + + #ifndef _USER + ++struct ConversionContext; + +-extern OutputPersonality* user_init(OutputPersonality *, char *tags_file_path); +- ++extern OutputPersonality* user_init(const struct ConversionContext *cc, char *tags_file_path); ++extern void free_user_definitions (OutputPersonality *op); + + #define _USER + #endif +diff -durpN unrtf-0.21.2.old/src/word.c unrtf-0.21.2/src/word.c +--- unrtf-0.21.2.old/src/word.c 2010-07-03 22:30:58.000000000 -0400 ++++ unrtf-0.21.2/src/word.c 2011-11-09 15:48:30.002798270 -0500 +@@ -1,23 +1,23 @@ + /*============================================================================= +- GNU UnRTF, a command-line program to convert RTF documents to other formats. +- Copyright (C) 2000,2001,2004 by Zachary Smith ++ GNU UnRTF, a command-line program to convert RTF documents to other formats. ++ Copyright (C) 2000,2001,2004 by Zachary Smith + +- 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 3 of the License, or +- (at your option) any later version. ++ 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 3 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. ++ 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +- The maintainer is reachable by electronic mail at daved@physiol.usyd.edu.au +-=============================================================================*/ ++ The maintainer is reachable by electronic mail at daved@physiol.usyd.edu.au ++ =============================================================================*/ + + + /*---------------------------------------------------------------------- +@@ -69,6 +69,7 @@ + #endif + + #include "defs.h" ++#include "convert.h" + #include "parse.h" + #include "malloc.h" + #include "main.h" +@@ -77,10 +78,6 @@ + #include "hash.h" + + +-/* For word_dump */ +-static int indent_level=0; +- +- + /*======================================================================== + * Name: word_string + * Purpose: Obtains the string of a Word object. This involves accessing +@@ -90,12 +87,12 @@ static int indent_level=0; + *=======================================================================*/ + + char * +-word_string (Word *w) { +- char *str; +- CHECK_PARAM_NOT_NULL(w); +- if (w->hash_index) str = hash_get_string (w->hash_index); +- else str = NULL; +- return str; ++word_string (const struct ConversionContext *cc, Word *w) { ++ char *str; ++ CHECK_PARAM_NOT_NULL(w); ++ if (w->hash_index) str = hash_get_string (cc, w->hash_index); ++ else str = NULL; ++ return str; + } + + +@@ -108,24 +105,22 @@ word_string (Word *w) { + *=======================================================================*/ + + Word * +-word_new (char *str) { +- Word * w; ++word_new (struct ConversionContext *cc, char *str) { ++ Word * w; + +- w = (Word *) my_malloc(sizeof(Word)); +- if (!w) +- error_handler ("out of memory"); +- memset ((void*) w, 0, sizeof(Word)); +- if (!w) error_handler ("cannot allocate a Word"); ++ w = (Word *) my_malloc(sizeof(Word)); ++ if (!w) ++ error_handler (cc, "out of memory"); ++ memset ((void*) w, 0, sizeof(Word)); ++ if (!w) error_handler (cc, "cannot allocate a Word"); + +- if (str) w->hash_index = hash_get_index (str); +- else w->hash_index = 0; ++ if (str) w->hash_index = hash_get_index (cc, str); ++ else w->hash_index = 0; + +- return w; ++ return w; + } + + +- +- + /*======================================================================== + * Name: word_free + * Purpose: Deallocates a Word object. This is only called at the end of +@@ -135,20 +130,20 @@ word_new (char *str) { + *=======================================================================*/ + + void word_free (Word *w) { +- Word *prev; +- Word *w2; ++ Word *prev; ++ Word *w2; + +- CHECK_PARAM_NOT_NULL(w); ++ CHECK_PARAM_NOT_NULL(w); + +- while (w) { +- w2 = w->child; +- if (w2) +- word_free(w2); ++ while (w) { ++ w2 = w->child; ++ if (w2) ++ word_free(w2); + +- prev = w; +- w = w->next; +- my_free((char*) prev); +- } ++ prev = w; ++ w = w->next; ++ my_free((char*) prev); ++ } + } + + +@@ -165,14 +160,14 @@ void word_free (Word *w) { + static void + print_indentation (int level) + { +- int i; ++ int i; + +- if (level) { +- for (i=0;iindent_level += 2; ++ print_indentation (cc->indent_level); + +- while (w) { +- s = word_string (w); +- if (s) { +- printf ("\"%s\" ", s); +- } else { +- if (w->child) { +- word_dump (w->child); +- printf ("\n"); +- print_indentation (indent_level); +- } +- else +- warning_handler ("Word object has no string and no children"); +- } +- w = w->next; +- } ++ while (w) { ++ s = word_string (cc, w); ++ if (s) { ++ printf ("\"%s\" ", s); ++ } else { ++ if (w->child) { ++ word_dump (cc, w->child); ++ printf ("\n"); ++ print_indentation (cc->indent_level); ++ } ++ else ++ warning_handler ("Word object has no string and no children"); ++ } ++ w = w->next; ++ } + +- indent_level -= 2; ++ cc->indent_level -= 2; + } + + #if 1 /* AK6 - AF */ +@@ -223,56 +218,56 @@ word_dump (Word *w) + * Returns: Optimized word. + *=======================================================================*/ + Word * +-optimize_word(Word *w) ++optimize_word(const struct ConversionContext *cc, Word *w) + { +- char *s, *s1; +- int i = 0, len; +- Collection *c = NULL; +- Tag tags_to_opt[] = OPT_ARRAY; +- Word *root = w, *w2; ++ char *s, *s1; ++ int i = 0, len; ++ Collection *c = NULL; ++ Tag tags_to_opt[] = OPT_ARRAY; ++ Word *root = w, *w2; + +- for (; w != NULL; w = w->next) +- { ++ for (; w != NULL; w = w->next) ++ { + +- if (s = word_string(w)) +- { +- for (i = 0; tags_to_opt[i].name[0] != '\0'; i++) +- { +- if (tags_to_opt[i].has_param) +- { +- len = strlen(tags_to_opt[i].name); +- if (!strncmp(tags_to_opt[i].name, s, len) && (isdigit(s[len]) || s[len] == '-')) +- break; +- } +- else +- if (!strcmp(tags_to_opt[i].name, s)) +- break; +- } ++ if (s = word_string(cc, w)) ++ { ++ for (i = 0; tags_to_opt[i].name[0] != '\0'; i++) ++ { ++ if (tags_to_opt[i].has_param) ++ { ++ len = strlen(tags_to_opt[i].name); ++ if (!strncmp(tags_to_opt[i].name, s, len) && (isdigit(s[len]) || s[len] == '-')) ++ break; ++ } ++ else ++ if (!strcmp(tags_to_opt[i].name, s)) ++ break; ++ } + +- if (tags_to_opt[i].name[0] != '\0') +- { +- s1 = get_from_collection(c, i); ++ if (tags_to_opt[i].name[0] != '\0') ++ { ++ s1 = get_from_collection(c, i); + +- if (s != NULL && s1 != NULL && !strcmp(s1, s)) +- { +- w2->next = w->next; +- my_free((char *)w); +- w = w2; +- } +- else +- c = add_to_collection(c, i, s); +- } +- } ++ if (s != NULL && s1 != NULL && !strcmp(s1, s)) ++ { ++ w2->next = w->next; ++ my_free((char *)w); ++ w = w2; ++ } ++ else ++ c = add_to_collection(c, i, s); ++ } ++ } + +- if (w->child != NULL) +- w->child = optimize_word(w->child); ++ if (w->child != NULL) ++ w->child = optimize_word(cc, w->child); + +- w2 = w; +- } ++ w2 = w; ++ } + +-// free_collection(c); ++ free_collection(c); + +- return root; ++ return root; + } + #endif + +diff -durpN unrtf-0.21.2.old/src/word.h unrtf-0.21.2/src/word.h +--- unrtf-0.21.2.old/src/word.h 2010-07-03 22:30:58.000000000 -0400 ++++ unrtf-0.21.2/src/word.h 2011-11-09 15:48:30.002798270 -0500 +@@ -41,14 +41,15 @@ typedef struct _w { + struct _w * child; + } Word; + +-extern Word* word_new (char*); ++struct ConversionContext; ++ ++extern Word* word_new (struct ConversionContext *, char*); + extern void word_free (Word*); +-extern Word* word_read (FILE*); +-extern char* word_string (Word*); +-extern void word_dump (Word*); ++extern char* word_string (const struct ConversionContext *, Word*); ++extern void word_dump (struct ConversionContext *, Word*); + extern void word_print_html (Word*); + +-extern Word* optimize_word(Word*); ++extern Word* optimize_word(const struct ConversionContext *, Word*); + + typedef struct _t { + char *name; diff --git a/OpenChange/unrtf-0.21.2.tar.gz b/OpenChange/unrtf-0.21.2.tar.gz new file mode 100644 index 000000000..421ba59f0 Binary files /dev/null and b/OpenChange/unrtf-0.21.2.tar.gz differ diff --git a/OpenChange/unrtf_config_h b/OpenChange/unrtf_config_h new file mode 100644 index 000000000..193142ba9 --- /dev/null +++ b/OpenChange/unrtf_config_h @@ -0,0 +1,75 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the header file. */ +#define HAVE_CTYPE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if your system has a GNU libc compatible `malloc' function, and + to 0 otherwise. */ +#define HAVE_MALLOC 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `memset' function. */ +#define HAVE_MEMSET 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strchr' function. */ +#define HAVE_STRCHR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strstr' function. */ +#define HAVE_STRSTR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Name of package */ +#define PACKAGE "unrtf" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "bug-unrtf@gnu.org" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "unrtf" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "unrtf 0.21.2" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "unrtf" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "0.21.2" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION "0.21.2" + +/* Define to rpl_malloc if the replacement function should be used. */ +/* #undef malloc */ diff --git a/SoObjects/SOGo/SOGoGCSFolder.m b/SoObjects/SOGo/SOGoGCSFolder.m index 96bb3890f..59a8fd16b 100644 --- a/SoObjects/SOGo/SOGoGCSFolder.m +++ b/SoObjects/SOGo/SOGoGCSFolder.m @@ -1986,7 +1986,7 @@ static NSArray *childRecordFields = nil; [r appendFormat: @""]; [r appendString: baseURL]; - [r appendString: [object objectForKey: @"c_name"]]; + [r appendString: [[object objectForKey: @"c_name"] stringByEscapingURL]]; [r appendString: @""]; // NSLog (@"(appendPropstats...): %@", [NSDate date]); @@ -2032,7 +2032,7 @@ static NSArray *childRecordFields = nil; for (count = 0; count < max; count++) { element = [refs objectAtIndex: count]; - currentURL = [[element firstChild] nodeValue]; + currentURL = [[[element firstChild] nodeValue] stringByUnescapingURL]; [urls addObject: currentURL]; } diff --git a/SoObjects/SOGo/SOGoSieveManager.m b/SoObjects/SOGo/SOGoSieveManager.m index 62c91f980..4f32f969e 100644 --- a/SoObjects/SOGo/SOGoSieveManager.m +++ b/SoObjects/SOGo/SOGoSieveManager.m @@ -629,7 +629,7 @@ static NSString *sieveScriptName = @"sogo"; NGSieveClient *client; NSString *filterScript, *v, *sieveServer; int sievePort; - BOOL b; + BOOL b, connected; dd = [user domainDefaults]; if (!([dd sieveScriptsEnabled] || [dd vacationEnabled] || [dd forwardEnabled])) @@ -637,6 +637,8 @@ static NSString *sieveScriptName = @"sogo"; req = [NSMutableArray arrayWithCapacity: 15]; ud = [user userDefaults]; + + connected = YES; b = NO; script = [NSMutableString string]; @@ -793,7 +795,23 @@ static NSString *sieveScriptName = @"sogo"; [client closeConnection]; return NO; } - result = [client login: theLogin authname: theAuthName password: thePassword]; + + NS_DURING + { + result = [client login: theLogin authname: theAuthName password: thePassword]; + } + NS_HANDLER + { + connected = NO; + } + NS_ENDHANDLER + + if (!connected) + { + NSLog(@"Sieve connection failed on %@", [address description]); + return NO; + } + if (![[result valueForKey:@"result"] boolValue]) { NSLog(@"failure. Attempting with a renewed password (no authname supported)"); thePassword = [theAccount imap4PasswordRenewed: YES]; diff --git a/UI/PreferencesUI/BrazilianPortuguese.lproj/Localizable.strings b/UI/PreferencesUI/BrazilianPortuguese.lproj/Localizable.strings index aeb0e2716..0c2f533b4 100644 --- a/UI/PreferencesUI/BrazilianPortuguese.lproj/Localizable.strings +++ b/UI/PreferencesUI/BrazilianPortuguese.lproj/Localizable.strings @@ -282,4 +282,4 @@ "Password change is not supported." = "Changement de mot de passe non-supporté."; "Unhandled HTTP error code: %{0}" = "Code HTTP non-géré: %{0}"; "New password:" = "Nova senha:"; -"Confirmation:" = "Confirmação:"; \ No newline at end of file +"Confirmation:" = "Confirmação:"; diff --git a/UI/PreferencesUI/Hungarian.lproj/Localizable.strings b/UI/PreferencesUI/Hungarian.lproj/Localizable.strings index a8d292d25..ff000de12 100644 --- a/UI/PreferencesUI/Hungarian.lproj/Localizable.strings +++ b/UI/PreferencesUI/Hungarian.lproj/Localizable.strings @@ -282,4 +282,4 @@ "Password change is not supported." = "Changement de mot de passe non-supporté."; "Unhandled HTTP error code: %{0}" = "Code HTTP non-géré: %{0}"; "New password:" = "Új jelszó:"; -"Confirmation:" = "Megerősítés:"; \ No newline at end of file +"Confirmation:" = "Megerősítés:"; diff --git a/UI/PreferencesUI/NorwegianBokmal.lproj/Localizable.strings b/UI/PreferencesUI/NorwegianBokmal.lproj/Localizable.strings index 37d0aabfb..ab8766748 100644 --- a/UI/PreferencesUI/NorwegianBokmal.lproj/Localizable.strings +++ b/UI/PreferencesUI/NorwegianBokmal.lproj/Localizable.strings @@ -282,4 +282,4 @@ "Password change is not supported." = "Changement de mot de passe non-supporté."; "Unhandled HTTP error code: %{0}" = "Code HTTP non-géré: %{0}"; "New password:" = "Nytt passord:"; -"Confirmation:" = "Bekreft:"; \ No newline at end of file +"Confirmation:" = "Bekreft:"; diff --git a/UI/PreferencesUI/Swedish.lproj/Localizable.strings b/UI/PreferencesUI/Swedish.lproj/Localizable.strings index ff7958bcc..e5211934a 100644 --- a/UI/PreferencesUI/Swedish.lproj/Localizable.strings +++ b/UI/PreferencesUI/Swedish.lproj/Localizable.strings @@ -284,4 +284,4 @@ Servernamn:"; "Password change is not supported." = "Changement de mot de passe non-supporté."; "Unhandled HTTP error code: %{0}" = "Code HTTP non-géré: %{0}"; "New password:" = "Nytt lösenord:"; -"Confirmation:" = "Bekräfta:"; \ No newline at end of file +"Confirmation:" = "Bekräfta:"; diff --git a/UI/PreferencesUI/Welsh.lproj/Localizable.strings b/UI/PreferencesUI/Welsh.lproj/Localizable.strings index 2062338fc..5919aef6c 100644 --- a/UI/PreferencesUI/Welsh.lproj/Localizable.strings +++ b/UI/PreferencesUI/Welsh.lproj/Localizable.strings @@ -282,4 +282,4 @@ "Password change is not supported." = "Changement de mot de passe non-supporté."; "Unhandled HTTP error code: %{0}" = "Code HTTP non-géré: %{0}"; "New password:" = "New password:"; -"Confirmation:" = "Confirmation:"; \ No newline at end of file +"Confirmation:" = "Confirmation:";