/****************************************************************************
 * NCSA Mosaic for the X Window System                                      *
 * Software Development Group                                               *
 * National Center for Supercomputing Applications                          *
 * University of Illinois at Urbana-Champaign                               *
 * 605 E. Springfield, Champaign IL 61820                                   *
 * mosaic@ncsa.uiuc.edu                                                     *
 *                                                                          *
 * Copyright (C) 1993, Board of Trustees of the University of Illinois      *
 *                                                                          *
 * NCSA Mosaic software, both binary and source (hereafter, Software) is    *
 * copyrighted by The Board of Trustees of the University of Illinois       *
 * (UI), and ownership remains with the UI.                                 *
 *                                                                          *
 * The UI grants you (hereafter, Licensee) a license to use the Software    *
 * for academic, research and internal business purposes only, without a    *
 * fee.  Licensee may distribute the binary and source code (if released)   *
 * to third parties provided that the copyright notice and this statement   *
 * appears on all copies and that no charge is associated with such         *
 * copies.                                                                  *
 *                                                                          *
 * Licensee may make derivative works.  However, if Licensee distributes    *
 * any derivative work based on or derived from the Software, then          *
 * Licensee will (1) notify NCSA regarding its distribution of the          *
 * derivative work, and (2) clearly notify users that such derivative       *
 * work is a modified version and not the original NCSA Mosaic              *
 * distributed by the UI.                                                   *
 *                                                                          *
 * Any Licensee wishing to make commercial use of the Software should       *
 * contact the UI, c/o NCSA, to negotiate an appropriate license for such   *
 * commercial use.  Commercial use includes (1) integration of all or       *
 * part of the source code into a product for sale or license by or on      *
 * behalf of Licensee to third parties, or (2) distribution of the binary   *
 * code or source code to third parties that need it to utilize a           *
 * commercial product sold or licensed by or on behalf of Licensee.         *
 *                                                                          *
 * UI MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR   *
 * ANY PURPOSE.  IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED          *
 * WARRANTY.  THE UI SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY THE    *
 * USERS OF THIS SOFTWARE.                                                  *
 *                                                                          *
 * By using or copying this Software, Licensee agrees to abide by the       *
 * copyright law and all other applicable laws of the U.S. including, but   *
 * not limited to, export control laws, and the terms of this license.      *
 * UI shall have the right to terminate this license immediately by         *
 * written notice upon Licensee's breach of, or non-compliance with, any    *
 * of its terms.  Licensee may be held legally responsible for any          *
 * copyright infringement that is caused or encouraged by Licensee's        *
 * failure to abide by the terms of this license.                           *
 *                                                                          *
 * Comments and questions are welcome and can be sent to                    *
 * mosaic-x@ncsa.uiuc.edu.                                                  *
 ****************************************************************************/
#include "../config.h"

#include <stdio.h>
#include <stdlib.h>

#include "HTMLparse.h"
#include "HTML.h"
#include "HTMLP.h"
#include "HTMLPutil.h"

/* Code to free a linked list of parsed HTML objects generated from a
 * raw text file.  Also code to free a linked list of formatted elements
 * taht make up a page of a formatted document.
 */

/* Free up the passed linked list of parsed HTML objects, freeing
 * all memory associated with each object.
 */
void FreeMarkUpList(MarkInfo *List)
{
	MarkInfo *current;
	MarkInfo *mptr;

	current = List;
	while (current) {
		mptr = current;
		current = current->next;
		if (mptr->start)
			free((char *)mptr->start);
		if (mptr->text)
			free((char *)mptr->text);
		if (mptr->end)
			free((char *)mptr->end);
		if ((!mptr->is_end) && (mptr->type == M_ANCHOR)) {
			if (mptr->anc_name) {
				free(mptr->anc_name);
			}
			if (mptr->anc_href) {
				free(mptr->anc_href);
			}
			if (mptr->anc_title) {
				free(mptr->anc_title);
			}
		}

		if (mptr->s_aps) {	/* aprog */
			_FreeAprogStruct(mptr->s_aps);
		}
		if (mptr->s_ats) {	/* applet */
			_FreeAppletStruct(mptr->s_ats);
		}
		if (mptr->t_p1) {	/* table */
			_FreeTableStruct(mptr->t_p1);
		}
		free((char *)mptr);
	}
}
/* Free up the passed linked list of parsed HTML usemaps, freeing
 * all memory associated with each map.
 */
void FreeMapList(MapInfo *map)
{
	MapInfo *nextmap;
	AreaInfo *area, *nextarea;
	CoordInfo *coords, *nextcoords;

	while (map) {
		nextmap = map->next;
		area = map->areaList;
		while (area) {
			nextarea = area->next;
			coords = area->coordList;			
			while (coords) {
				nextcoords = coords->next;
				free(coords);
				coords = nextcoords;
			}
			if (area->href)
				free(area->href);
			if (area->alt)
				free(area->alt);
			free(area);
			area = nextarea;
		}
		if (map->name)
			free(map->name);
		free(map);
		map = nextmap;
	}
}

/* Used to find the longest line (in characters) in a collection of text blocks.
 * cnt is the running count of characters, and txt is the pointer to the current
 * text block.  Since we are finding line widths, a newline resets the width
 * count.
 */
char * MaxTextWidth(char *txt, int *cnt)
{
	char *start;
	char *end;
	int width;

	if (!txt)
		return(NULL);
	width = *cnt;
	start = txt;
	/* If this blocks starts with a newline, reset the width
	 * count, and skip the newline.
	 */
	while ((*start == '\n') || (*start == '\r')) {
		width = 0;
		start++;
	}
	end = start;
	/* count characters, stoping either at a newline, or at the
	 * end of this text block.  Expand tabs.
	 */
	while (*end && (*end != '\n') && (*end != '\r')) {
		if (*end == '\t') {
			width = ((width / 8) + 1) * 8;
		} else {
			width++;
		}
		end++;
	}
	*cnt = width;
	return(end);
}

/* Free up the passed linked list of formatted elements, freeing
 * all memory associated with each element.
 */
void FreeLineList( struct ele_rec *list, HTMLWidget hw)
{
	struct ele_rec *current;
	struct ele_rec *eptr;
	ImageInfo *picd;
	ImageInfo *next;
	ImageInfo *tmp;

	current = list;
	while (current) {
		eptr = current;
		current = current->next;
		if (eptr->edata) {
			free((char *)eptr->edata);
		}
		if ((eptr->type == E_IMAGE) && eptr->pic_data) {
			picd = eptr->pic_data;
                         /*
                          * Don't free internal image pixmaps or data
                          */
			if ((picd->image != (Pixmap)NULL) && picd->fetched) {
				XFreePixmap(XtDisplay(hw), picd->image);
				if (picd->clip != (Pixmap)NULL) {
					XFreePixmap(XtDisplay(hw), picd->clip);
				}
			}
			/* Free any animation ImageInfo and Pixmaps */
			if (picd->anim_info && picd->next) {
				next = picd->next;
				while (next) {
					tmp = next;
					next = tmp->next;
					if (tmp->image != (Pixmap)NULL) {
						XFreePixmap(XtDisplay(hw),
							tmp->image);
						tmp->image = (Pixmap)NULL;
					}
					if (tmp->clip != (Pixmap)NULL) {
						XFreePixmap(XtDisplay(hw),
							tmp->clip);
						tmp->clip = (Pixmap)NULL;
					}
					/* Free rescaled animation data */
					if (picd->fetched && !picd->cached) {
						if (tmp->image_data)
							free(tmp->image_data);
						if (tmp->clip_data)
							free(tmp->clip_data);
					}
					free(tmp);
				}
				if (picd->has_anim_image &&
				    (picd->anim_image != (Pixmap)NULL))
					XFreePixmap(XtDisplay(hw),
						picd->anim_image);
				if (picd->has_anim_image &&
				    (picd->bg_image != (Pixmap)NULL))
					XFreePixmap(XtDisplay(hw),
						picd->bg_image);
			}
			/* Private copy if it was rescaled */
			if (picd->fetched && !picd->cached) {
				if (picd->image_data)
					free(picd->image_data);
				if (picd->clip_data)
					free(picd->clip_data);
			}
			/* Internal images can have these */
			if (picd->src)
				free(picd->src);
			if (picd->text)
				free(picd->text);
			if (picd->alt_text)
				free(picd->alt_text);
			if (picd->usemap)
				free(picd->usemap);
			free(picd);
		}
		free((char *)eptr);
	}
}

/*
 * Passed in 2 element pointers, and element positions.
 * Function should return 1 if if start occurs before end.
 * Otherwise return 0.
 */
int ElementLessThan( struct ele_rec *start, struct ele_rec *end,
	int start_pos, int end_pos)
{
	struct ele_rec *current;

	/*
	 * Deal with start or end being NULL
	 */
	if ((start == NULL) && (end == NULL))
		return(0);
	if ((start == NULL) && end)
		return(1);
	if (start && (end == NULL))
		return(0);
	/*
	 * Deal with easy identical case
	 */
	if (start == end) {
		if (start_pos < end_pos)
			return(1);
		return(0);
	}
	/* We know element Ids are always equal or increasing within a list.*/
	if (start->ele_id < end->ele_id)
		return(1);
	if (start->ele_id == end->ele_id) {
		current = start;
		while (current) {
			if (current->ele_id != start->ele_id)
				break;
			if (current == end)
				break;
			current = current->next;
		}
		if (current == end)
			return(1);
		return(0);
	}
	return(0);
}

/*
 * Passed in 2 element pointers, and element positions.
 * Function should return 1 if they need to be swapped in order for then
 * to proceed left to right and top to bottom in the text.
 * Otherwise return 0.
 */
int SwapElements( struct ele_rec *start, struct ele_rec *end, 
		int start_pos, int end_pos)
{
	struct ele_rec *current;

	/* Deal with start or end being NULL */
	if ((start == NULL) && (end == NULL))
		return(0);
	if ((start == NULL) && end)
		return(1);
	if (start && (end == NULL))
		return(0);
	/* Deal with easy identical case */
	if (start == end) {
		if (start_pos > end_pos)
			return(1);
		return(0);
	}

	/* We know element Ids are always equal or increasing within a list. */
	if (start->ele_id < end->ele_id)
		return(0);
	if (start->ele_id == end->ele_id) {
		current = start;
		while (current) {
			if (current->ele_id != start->ele_id)
				break;
			if (current == end)
				break;
			current = current->next;
		}
		if (current == end)
			return(0);
		return(1);
	}
	return(1);
}
