﻿//------------------------------------------------------------------------------
//
// ADOBE SYSTEMS INCORPORATED
// Copyright 2003 Adobe Systems Incorporated 
// All Rights Reserved
//
// NOTICE: Adobe permits you to use, modify, and distribute 
// this file in accordance with the terms of the Adobe license 
// agreement accompanying it. If you have received this file 
// from a source other than Adobe, then your use, modification, 
// or distribution of it requires the prior written permission 
// of Adobe.
//
//------------------------------------------------------------------------------

///////////////////////////////////////////////////////////////////////////
//
// PUBLIC
//

function RTFScanner()
{
	this.source		= null;
	this.error		= '';
	this.rtf		= null;
	this.progress	= null;
	
	this.curGroup	= null;
	this.state		= 'stop';
	
	this.sourceBuffer	= '';
	this.bufferIndex	= 0;
	this.BUFFER_MAX		= 1000000;
	this.readChars		= 0;
}

RTFScanner.prototype.processSource = function()
{
	var ret = false;
	
	var startDate = new Date();
	
	if( this.source != null )
	{
		this.state = 'run';
		
		this.sourceBuffer	= '';
		this.bufferIndex	= 0;
		this.readChars		= 0;

		switch( this.source.constructor.name )
		{
			case 'JSXFile':
				ret = this.processFile();
				break;
				
			default:
				this.error = 'No handler for source type';
		}
		
		this.state = 'stop';
	}
	else
		this.error = 'No Source';
		
	var endDate = new Date();
	
	if( module.debug )
	{
		var hour = endDate.getHours() - startDate.getHours();
		var min  = endDate.getMinutes() - startDate.getMinutes();
		var sec  = endDate.getSeconds() - startDate.getSeconds();
		var ms   = endDate.getMilliseconds() - startDate.getMilliseconds();
		
		writeln( 'RTF Scanner, procceed ' + hour + ' hours, ' + min + ' minutes, ' + sec + ' seconds, ' + ms + ' milliseconds' );
	}
		
	return ret;
}

RTFScanner.prototype.stop = function()
{
	this.state = 'userbreak';
}

///////////////////////////////////////////////////////////////////////////
//
// PRIVATE
//

RTFScanner.prototype.processFile = function()
{
	var ret = false;
	
	app.currentFolder = this.source.parent;
	
	var max = this.source.size;
	
	if( this.source.open( 'r', 'BINARY' ) )
	{
		while( this.state == 'run' )
		{
			// progress
			if( this.progress != null )
			{
				this.progress( this.readChars, max );
			}
			
			var skip = false;
			
			var ch = this.getNext();
			var cC = ch.charCodeAt(0);
			
			//
			// skip win lineending character
			//
			if( cC == 13 )
			{
				var ncC = this.lookUp().charCodeAt(0);
				
				if( ncC == 10 )
					skip = true;
			}
			
			if( !skip )
			{
				switch( ch )
				{
					case '\n':
					case '\t':
						// skip linebreak characters
						break;

					case '{':
					{
						var group = new RTFGroup( this.curGroup );
						
						if( this.rtf == null )
						{
							this.rtf = group;
							this.curGroup = group;
						}
						else
						{
							this.curGroup.addGroup( group );
							this.curGroup = group;
						}
					}
					break;
		
					case '}':
						this.curGroup.close();
						this.curGroup = this.curGroup.parentGroup;
						break;
						
					case '\\':
					{
						var lu = this.lookUp();
						
						switch( lu )
						{
							case '\\':
							{
								ch = this.getNext();
								this.processCharacter( ch );
							}
							break;
							
							case '\'':
							{
								this.getNext();
								var hex = this.getNext(2);
								var value = parseInt( hex, 16 );
								ch = String.fromCharCode( value );
								this.processCharacter( ch );
							}
							break;
							
							default:
								this.processControl();
						}
					}
					break;
					
					default:
						this.processCharacter( ch );
				}
			}
		}
		
		if( this.state == 'userbreak' )
		{
			this.state = 'stop';
			this.error = 'userbreak';
		}
		
		ret = this.error == '';
	}
	
	this.source.close();
	
	return ret;
}

RTFScanner.prototype.processControl = function()
{
	var ch = this.lookUp();
	
	var ctrlSymbol = this.isCtrlWordChar( ch );
	
	if( !ctrlSymbol )
	{
		this.curGroup.addCtrlSymbol( this.getNext() );
	}
	else
	{
		var ctrlWord = '';
		var complete = false;
		
		do
		{
			if( ch == ' ' )/*|| ch == ';' )*/
			{
				complete = true;
				ctrlWord += this.getNext();
			}
			else
			{
				if( this.isCtrlWordChar( ch ) || ch == '-' )
				{
					ctrlWord += this.getNext();
					ch = this.lookUp();
				}
				else
					complete = true;
			}
			
		} while( !complete );
		
		if( ctrlWord.length > 0 )
			this.curGroup.addCtrlWord( ctrlWord );
	}
}

RTFScanner.prototype.processCharacter = function( ch )
{
	if( this.curGroup != null )
	{
		this.curGroup.addCharacter( ch );
	}
}

RTFScanner.prototype.isCtrlWordChar = function( ch )
{
	var ret = false;
	var cCode = ch.charCodeAt(0);
	
	ret = ( ( cCode > 47 ) && ( cCode < 58 ) ) || ( ( cCode > 64 ) && ( cCode < 91 ) ) || ( ( cCode > 96 ) && ( cCode < 123 ) );
	
	return ret;
}

RTFScanner.prototype.updateBufferFor = function( count )
{
	if( this.sourceBuffer.length - this.bufferIndex < count + 1 )
	{
		var tmp = this.source.read( this.BUFFER_MAX );
		
		this.sourceBuffer = this.sourceBuffer.substr( this.bufferIndex, this.BUFFER_MAX-1 );
		this.sourceBuffer += tmp;
		
		this.bufferIndex = 0;
	}
}

RTFScanner.prototype.getNext = function( count )
{
	if( count == null || count == undefined )
		count = 1;
		
	this.updateBufferFor( count );

	var ch = this.sourceBuffer.substr( this.bufferIndex, count );
	
	this.bufferIndex += ch.length;
	this.readChars += ch.length;

	if( ch.length < count )
		this.state = 'eof';
	
	return ch;
}

RTFScanner.prototype.lookUp = function( count )
{
	if( count == null || count == undefined )
		count = 1;
		
	this.updateBufferFor( count );
	
	var ch = this.sourceBuffer.substr( this.bufferIndex, count );
	
	return ch;
}