//
// XTHtmlLinebreakHandler2.m
// TadsTerp
//
// Created by Rune Berg on 11/05/14.
// Copyright (c) 2014 Rune Berg. All rights reserved.
//
#import "XTHtmlLinebreakHandler2.h"
#import "XTHtmlTagBr.h"
#import "XTHtmlTagP.h"
#import "XTHtmlTagTab.h"
#import "XTStringUtils.h"
#import "XTLogger.h"
#import "XTAllocDeallocCounter.h"
@interface XTHtmlLinebreakHandler2 ()
@property NSUInteger divDepth;
//TODO hackish - consider proper "tag stack handling"
@end
@implementation XTHtmlLinebreakHandler2
static XTLogger* logger;
static NSArray *newlinesStringsCache;
+ (void)initialize
{
logger = [XTLogger loggerForClass:[XTHtmlLinebreakHandler2 class]];
newlinesStringsCache = @[@"", @"\n", @"\n\n", @"\n\n\n", @"\n\n\n\n"];
}
OVERRIDE_ALLOC_FOR_COUNTER
OVERRIDE_DEALLOC_FOR_COUNTER
- (id)init
{
self = [super init];
if (self) {
_state = XT_LINEBREAKHANDLER2_AT_START_OF_LINE;
_divDepth = 0;
}
return self;
}
- (void)resetForNextCommand
{
_state = XT_LINEBREAKHANDLER2_AT_START_OF_LINE;
_divDepth = 0;
}
- (NSString *)handleTagBr:(NSInteger)height
{
[logger trace:@"handleTagBr (state %ld): %ld", self.state, height];
if (height < 0) {
//
==
height = 1;
}
NSUInteger numberOfNewlines;
switch (self.state) {
case XT_LINEBREAKHANDLER2_AT_START_OF_LINE:
//TODO simplify:
if (height == 0) {
numberOfNewlines = 0;
} else if (height == 1) {
numberOfNewlines = 1;
} else {
numberOfNewlines = height;
}
break;
case XT_LINEBREAKHANDLER2_AFTER_TAB_START_OF_LINE:
if (height <= 1) {
numberOfNewlines = 0;
} else {
numberOfNewlines = height + 1;
}
break;
case XT_LINEBREAKHANDLER2_IN_TEXT:
if (height == 0) {
numberOfNewlines = 1;
} else if (height == 1) {
numberOfNewlines = 1;
} else {
numberOfNewlines = height + 1;
}
break;
default:
[logger error:@"handleTagBr unexpected state %d", self.state];
//TODO handle error
break;
}
_state = XT_LINEBREAKHANDLER2_AT_START_OF_LINE;
return [self stringOfNewlines:numberOfNewlines];
}
//TODO rm if not used
/*
- (NSString *)handleTagP
{
[logger trace:@"handleTagP (state %ld)", self.state];
NSUInteger numberOfNewlines;
switch (self.state) {
case XT_LINEBREAKHANDLER2_AT_START_OF_LINE:
numberOfNewlines = 1;
break;
case XT_LINEBREAKHANDLER2_IN_TEXT:
numberOfNewlines = 2;
break;
case XT_LINEBREAKHANDLER2_AFTER_TAB_START_OF_LINE:
numberOfNewlines = 1;
break;
default:
numberOfNewlines = 1;
[logger error:@"handleTagP unexpected state %d", self.state];
//TODO handle error
}
_state = XT_LINEBREAKHANDLER2_AT_START_OF_LINE;
return [self stringOfNewlines:numberOfNewlines];
}*/
- (NSString *)handleTagTab
{
switch (self.state) {
case XT_LINEBREAKHANDLER2_AT_START_OF_LINE:
_state = XT_LINEBREAKHANDLER2_AFTER_TAB_START_OF_LINE;
break;
case XT_LINEBREAKHANDLER2_IN_TEXT:
// stay in current state
break;
case XT_LINEBREAKHANDLER2_AFTER_TAB_START_OF_LINE:
// stay in current state
break;
default:
[logger error:@"handleTagTab unexpected state %d", self.state];
//TODO handle error
}
//TODO rm return type? no - defer space for tabs... see gold.gam initial loc
return @"";
}
//TODO unit test
- (NSString *)handleEndLi
{
_state = XT_LINEBREAKHANDLER2_AT_START_OF_LINE;
return @"\n";
}
- (void)handleText:(NSString *)text
{
if (text != nil && text.length >= 1) {
BOOL endsWithNewline = [text hasSuffix:@"\n"];
if (endsWithNewline) {
_state = XT_LINEBREAKHANDLER2_AT_START_OF_LINE;
} else {
BOOL endsWithZwsp = [text hasSuffix:ZERO_WIDTH_SPACE];
if (! endsWithZwsp) {
_state = XT_LINEBREAKHANDLER2_IN_TEXT;
} else {
int brkpt = 1;
}
}
}
}
//TODO missing from diagram
//TODO better name
//TODO distinguish between open and close?
- (NSString *)handleBlockLevelNewline:(XTHtmlTag *)tag
{
NSString *res = nil;
if ([tag isBlockLevel]) {
if (self.state == XT_LINEBREAKHANDLER2_IN_TEXT) {
res = @"\n";
}
_state = XT_LINEBREAKHANDLER2_AT_START_OF_LINE;
} else {
//TODO log error
}
return res;
}
//-------------------------------
- (NSString *)stringOfNewlines:(NSUInteger)numberOfNewlines
{
NSString *res;
if (numberOfNewlines < newlinesStringsCache.count) {
res = newlinesStringsCache[numberOfNewlines];
} else {
NSMutableString *tempRes = [NSMutableString string];
while (numberOfNewlines-- > 0) {
[tempRes appendString:@"\n"];
}
res = tempRes;
}
return res;
}
@end