//-----------------------------------------------------------------------------
// Copyright © 2006 - Philip Howard - All rights reserved
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//-----------------------------------------------------------------------------
// package	libh/arith
// homepage	http://libh.slashusr.org/
//-----------------------------------------------------------------------------
// author	Philip Howard
// email	libh at ipal dot org
// homepage	http://phil.ipal.org/
//-----------------------------------------------------------------------------
// This file is best viewed using a fixed spaced font such as Courier
// and in a display at least 120 columns wide.
//-----------------------------------------------------------------------------

#include "arith_lib.h"

__PROTO_BEGIN__
//-----------------------------------------------------------------------------
// function	zoom_scan_d
//
// purpose	Scan a string of zooming command characters and produce a set
//		of values to multiply and add to transform 2D coordinates to
//		given a zoomed and positioned view.
//
// arguments	1 (const char *) zooming/positioning command string
//		2 (double *) where to store X multiplier
//		3 (double *) where to store Y multiplier
//		4 (double *) where to store X adder
//		5 (double *) where to store Y adder
//
// returns	(int) == -1 : general failure
//		(int) >=  0 : number of successful commands
//
// note		If an unrecognized command is found, command interpretation
//		stops and the returned number represents an index into the
//		command sequence string to the unrecognized character.  The
//		stored results only apply to the last successful command.
//
// commands	0 o O	- zoom out (unzoom) by 2x
//		1	- zoom in by 2x to the upper left quadrant
//		2	- zoom in by 2x to the upper center quadrant
//		3	- zoom in by 2x to the upper fright quadrant
//		4	- zoom in by 2x to the middle left quadrant
//		5 i I	- zoom in by 2x to the middle center quadrant
//		6	- zoom in by 2x to the middle right quadrant
//		7	- zoom in by 2x to the lower left quadrant
//		8	- zoom in by 2x to the lower center quadrant
//		9	- zoom in by 2x to the lower right quadrant
//		x X	- zoom only X axis by 2x
//		y Y	- zoom only Y axis by 2x
//		l L	- shift by 1/2 width leftward
//		u U	- shift by 1/2 height upward
//		r R	- shift by 1/2 width rightward
//		d D	- shift by 1/2 height downward
//-----------------------------------------------------------------------------
int
zoom_scan_d (
    const char *	arg_cmd_str
    ,
    double *		arg_mul_x_p
    ,
    double *		arg_mul_y_p
    ,
    double *		arg_add_x_p
    ,
    double *		arg_add_y_p
    )
__PROTO_END__
{
    double		mul_x		;
    double		mul_y		;
    double		add_x		;
    double		add_y		;
    const char *	cmd_p		;
    int			bad		;


    mul_x = 1.0;
    mul_y = 1.0;
    add_x = 0.0;
    add_y = 0.0;
    cmd_p = arg_cmd_str;
    bad = 0;

    for (;;) {

	//---------------------------
	// Store current zoom values.
	//---------------------------
	if ( arg_mul_x_p ) * arg_mul_x_p = mul_x;
	if ( arg_mul_y_p ) * arg_mul_y_p = mul_y;
	if ( arg_add_x_p ) * arg_add_x_p = add_x;
	if ( arg_add_y_p ) * arg_add_y_p = add_y;

	//-----------------------------------------
	// If no (more) characters remain, end now.
	//-----------------------------------------
	if ( ! * cmd_p ) break;

	//---------------------
	// Select X multiplier.
	//---------------------
	switch ( * cmd_p ) {

	case '0': case 'o': case 'O':
	    mul_x += mul_x;
	    break;

	case '1':
	case '4':
	case '7':
	case '2':
	case '5': case 'i': case 'I': case 'z': case 'Z':
	case '8':
	case '3':
	case '6':
	case '9':
	case 'x': case 'X':
	    mul_x /= 2.0;
	    break;

	case 'l': case 'L':
	case 'u': case 'U':
	case 'r': case 'R':
	case 'd': case 'D':
	case 'y': case 'Y':
	    break;

	default:
	    bad = 1;
	    break;
	}

	//----------------
	// Select X adder.
	//----------------
	switch ( * cmd_p ) {

	case '1':
	case '4':
	case '7':
	    add_x -= mul_x;
	    break;

	case '3':
	case '6':
	case '9':
	    add_x += mul_x;
	    break;

	case 'l': case 'L':
	    add_x -= mul_x / 2.0;
	    break;

	case 'r': case 'R':
	    add_x += mul_x / 2.0;
	    break;

	case 'u': case 'U':
	case 'd': case 'D':
	    break;

	case '0': case 'o': case 'O':
	case '2':
	case '5': case 'i': case 'I': case 'z': case 'Z':
	case '8':
	case 'x': case 'X':
	case 'y': case 'Y':
	    break;

	default:
	    bad = 1;
	    break;
	}

	//---------------------
	// Select Y multiplier.
	//---------------------
	switch ( * cmd_p ) {

	case '0': case 'o': case 'O':
	    mul_y += mul_y;
	    break;

	case '1':
	case '4':
	case '7':
	case '2':
	case '5': case 'i': case 'I': case 'z': case 'Z':
	case '8':
	case '3':
	case '6':
	case '9':
	case 'y': case 'Y':
	    mul_y /= 2.0;
	    break;

	case 'l': case 'L':
	case 'u': case 'U':
	case 'r': case 'R':
	case 'd': case 'D':
	case 'x': case 'X':
	    break;

	default:
	    bad = 1;
	    break;
	}

	//----------------
	// Select Y adder.
	//----------------
	switch ( * cmd_p ) {

	case '1':
	case '2':
	case '3':
	    add_y -= mul_y;
	    break;

	case '7':
	case '8':
	case '9':
	    add_y += mul_y;
	    break;

	case 'd': case 'D':
	    add_y -= mul_y / 2.0;
	    break;

	case 'u': case 'U':
	    add_y += mul_y / 2.0;
	    break;

	case '0': case 'o': case 'O':
	case '4':
	case '5': case 'i': case 'I': case 'z': case 'Z':
	case '6':
	case 'l': case 'L':
	case 'r': case 'R':
	case 'x': case 'X':
	case 'y': case 'Y':
	    break;

	default:
	    bad = 1;
	    break;
	}

	//-----------------------------------------
	// If a bad character encountered, end now.
	//-----------------------------------------
	if ( bad ) break;

	//----------------
	// Next character.
	//----------------
	++ cmd_p;
    }

    //-----------------------------------------
    // Return the number of characters scanned.
    //-----------------------------------------
    return ( cmd_p - arg_cmd_str );
}

