//====START_GENERATED_PROLOG======================================
//
//
//   COMPONENT_NAME: odother
//
//   CLASSES: none
//
//   ORIGINS: 27
//
//
//   (C) COPYRIGHT International Business Machines Corp. 1995,1996
//   All Rights Reserved
//   Licensed Materials - Property of IBM
//   US Government Users Restricted Rights - Use, duplication or
//   disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
//
//   IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
//   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//   PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
//   CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
//   USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
//   OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
//   OR PERFORMANCE OF THIS SOFTWARE.
//
//====END_GENERATED_PROLOG========================================
//
// @(#) 1.1 nt/src/samples/JavaPart/jemppars.cpp, odjavapart, od96nt, odnt9712d 10/23/96 03:06:52 [ 3/21/97 17:41:07 ]

#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#include "JEmpPars.h"

static AppletAttribute *newAppletAttribute(void)
{
	AppletAttribute *attrib = (AppletAttribute *)malloc(sizeof(AppletAttribute));
	if (attrib) {
		attrib->name = 0;
		attrib->value = 0;
		attrib->next = 0;
	}

	return attrib;
}

static void deleteAppletAttribute(AppletAttribute *aa)
{
	if (aa) {
		free(aa->name);
		free(aa->value);
		free(aa);
	}
}

static void deleteAppletAttributeList(AppletAttribute *first)
{
	AppletAttribute *cur = 0;
	while (first) {
		cur = first;
		first = first->next;
		deleteAppletAttribute(cur);
	}
}

static AppletAttribute* addOrReplaceAttribute(AppletAttribute *first,
                                              AppletAttribute *newAttrib)
{
	AppletAttribute *cur = first;
	AppletAttribute *prev = 0;
	int found = 0;

	while (cur) {
		if (strcmp(cur->name, newAttrib->name) == 0) {
			char *tmpVal = cur->value;
			cur->value = newAttrib->value;
			newAttrib->value = tmpVal;
			deleteAppletAttribute(newAttrib);
			found = 1;
			break;
		}
		prev = cur;
		cur = cur->next;
	}

	if (!found) {
		if (prev) {
			prev->next = newAttrib;
		} else {
			first = newAttrib;
		}

		newAttrib->next = 0;
	}
	return first;
}

static AppletAttribute* findAppletAttribute(AppletAttribute *aa, char *name)
{
	while (aa) {
		if (strcmp(aa->name, name) == 0) {
			return aa;
		} else {
			aa = aa->next;
		}
	}
	return 0;
}

AppletTagStructEx* newAppletTag(void)
{
	AppletTagStructEx *appTag = (AppletTagStructEx *)malloc(sizeof(AppletTagStructEx));
	if (appTag) {
		appTag->sourceURL = 0;
		appTag->codebase = 0;
		appTag->code = 0;
		appTag->alt = 0;
		appTag->name = 0;
		appTag->width = -1;
		appTag->height = -1;
		appTag->align = 0;
		appTag->vspace = -1;
		appTag->hspace = -1;
		appTag->attributes = 0;
		appTag->next = 0;
	}
	return appTag;
}

void jeAppletTagDelete(AppletTagStructEx *appTag)
{
	if (appTag) {
		free(appTag->sourceURL);
		free(appTag->codebase);
		free(appTag->code);
		free(appTag->alt);
		free(appTag->name);
		free(appTag->align);
		deleteAppletAttributeList(appTag->attributes);
		free(appTag);
	}
}

static char* appendChar(char ch, char *ptr, int *posn, int *size)
{
	if (!ptr || *posn == *size) {
		char *newBuf = (char *)malloc(*size * 2 + 1);
		*size *= 2;
		if (ptr) {
			ptr[*posn] = '\0';
			strcpy(newBuf, ptr);
			free(ptr);
		}
		ptr = newBuf;
	}

	ptr[*posn] = ch;
	(*posn)++;

	return ptr;
}

static char* scanIdentifier(const char **buffer)
{
	int   size = 32;
	char *tmpBuf = (char *)malloc(size + 1);
	int   posn = 0;
	const char *ptr = *buffer;
	char *retBuf = 0;

	while (*ptr && (isalnum(*ptr) || (*ptr == '.') || (*ptr == '-'))) {
		tmpBuf = appendChar((char)tolower(*ptr), tmpBuf, &posn, &size);
		ptr++;
	}

	if (posn > 0) {
		tmpBuf[posn] = '\0';
		retBuf = strdup(tmpBuf);
	}
	free(tmpBuf);

	*buffer = ptr;
	return retBuf;
}

static void skipSpace(const char **buffer)
{
	const char *ptr = *buffer;
	while (*ptr && isspace(*ptr)) {
		ptr++;
	}

	*buffer = ptr;
}

static AppletAttribute* scanTag(const char **buffer)
{
	const char *ptr = *buffer;
	AppletAttribute *firstAttr = 0;
	skipSpace(&ptr);

	while (*ptr && *ptr != '>') {
		char *att = scanIdentifier(&ptr);
		char *val = 0;

		if (att) {
		skipSpace(&ptr);
		if (*ptr == '=') {
			int quote = -1;
			char *buf = 0;
			int   size = 16;
			int   posn = 0;

			ptr++;
			skipSpace(&ptr);
			if (*ptr == '\'' || *ptr == '\"') {
				quote = *ptr;
				ptr++;
			}
			while (*ptr &&
			    (((quote < 0) && !isspace(*ptr) && (*ptr != '>')) ||
			    ((quote >= 0) && (*ptr != quote)))) {
				buf = appendChar(*ptr, buf, &posn, &size);
				ptr++;
			}

			if (*ptr == quote) {
				ptr++;
			}

			val = 0;
			if (buf && posn > 0) {
				buf[posn] = '\0';
				val = strdup(buf);
			}
			free(buf);

			if (att) {
				AppletAttribute *curAttr = newAppletAttribute();
				curAttr->name = att;
				curAttr->value = val;

				if (!firstAttr) {
					firstAttr = curAttr;
				} else {
					addOrReplaceAttribute(firstAttr, curAttr);
				}
			} else {
				free(att);
				free(val);
			}

			skipSpace(&ptr);
		}
		} else {
		    ptr++;
		}
	}

	*buffer = ptr;
	return firstAttr;
}

AppletTagStructEx* jeAppletTagParse(char *buffer)
{
	const char *ptr = buffer;
	AppletTagStructEx *firstApplet = 0;
	AppletTagStructEx *lastApplet = 0;
	AppletTagStructEx *curApplet = 0;

	if (!buffer) {
		return 0;
	}

	while (*ptr) {
		// Find the opening <
		if (*ptr == '<') {
			ptr++;
			if (*ptr == '/') {
				char *nm = 0;
				ptr++;
				nm = scanIdentifier(&ptr);
				if (nm && strcmpi(nm, "applet") == 0) {
					// closing applet tag </applet>
					if (curApplet) {
						if (!firstApplet)
							firstApplet = lastApplet = curApplet;
						else {
							lastApplet->next = curApplet;
							lastApplet = curApplet;
						}
						curApplet = 0;
					}
					free(nm);
				} else {
					ptr++;
				}
			} else if (*ptr == '!') {
				// Look for comment
				ptr++;
				if (*ptr == '-') {
					ptr++;
					if (*ptr == '-') {
						AppletAttribute *aa = 0;
						AppletAttribute *tAttrib = 0;
						ptr++;
						// A comment lets see if its a "source" comment
						aa = scanTag(&ptr);
						tAttrib = findAppletAttribute(aa, "source");
						if (curApplet && tAttrib) {
							// Lets remove -- from the value
							int idx = strlen(tAttrib->value);
							if (idx >= 2 &&
							tAttrib->value[idx - 1] == '-' &&
							tAttrib->value[idx - 2] == '-') {
								tAttrib->value[idx-2] = '\0';
								idx = idx - 2;
							}
							if (idx == 0) {
								free(tAttrib->value);
								tAttrib->value = 0;
							}

							free(curApplet->sourceURL);
							curApplet->sourceURL = tAttrib->value;
							tAttrib->value = 0;
						}
						deleteAppletAttributeList(aa);
					}
				}
			} else {
				char *nm = scanIdentifier(&ptr);
				if (nm) {
					if (strcmpi(nm, "param") == 0) {
						AppletAttribute *aa = scanTag(&ptr);
						AppletAttribute *name = findAppletAttribute(aa, "name");
						AppletAttribute *value = findAppletAttribute(aa, "value");

						if (curApplet && aa && name && value) {
							char *tmpStr = name->name;
							name->name = name->value;
							name->value = value->value;
							value->value = tmpStr;

							//            strlwr(name->name);
							curApplet->attributes = addOrReplaceAttribute(curApplet->attributes,
											    name);
							deleteAppletAttribute(value);
						} else {
							deleteAppletAttributeList(aa);
						}
					} else if (strcmpi(nm, "applet") == 0) {
						AppletAttribute *aa = scanTag(&ptr);
						// Create AppletTagStructEx
						curApplet = newAppletTag();
						if (curApplet) {
							// Find the required tags first
							AppletAttribute *tAttrib = findAppletAttribute(aa, "code");
							if (tAttrib) {
								curApplet->code = tAttrib->value;
								tAttrib->value = 0;
							}
							tAttrib = findAppletAttribute(aa, "width");
							if (tAttrib) {
								curApplet->width = atol(tAttrib->value);
							}
							tAttrib = findAppletAttribute(aa, "height");
							if (tAttrib) {
								curApplet->height = atol(tAttrib->value);
							}

							if (curApplet->code &&
							curApplet->height != -1 && curApplet->width != -1) {
								tAttrib = findAppletAttribute(aa, "codebase");
								if (tAttrib) {
									curApplet->codebase = tAttrib->value;
									tAttrib->value = 0;
								}
								tAttrib = findAppletAttribute(aa, "alt");
								if (tAttrib) {
									curApplet->alt = tAttrib->value;
									tAttrib->value = 0;
								}
								tAttrib = findAppletAttribute(aa, "name");
								if (tAttrib) {
									curApplet->name = tAttrib->value;
									tAttrib->value = 0;
								}
								tAttrib = findAppletAttribute(aa, "align");
								if (tAttrib) {
									curApplet->align = tAttrib->value;
									tAttrib->value = 0;
								}
								tAttrib = findAppletAttribute(aa, "hspace");
								if (tAttrib) {
									curApplet->hspace = atol(tAttrib->value);
								}
								tAttrib = findAppletAttribute(aa, "vspace");
								if (tAttrib) {
									curApplet->vspace = atol(tAttrib->value);
								}

								// Free up aa
								deleteAppletAttributeList(aa);
							}
						}
					}
					free(nm);
					} else {
				ptr++;
				}
			}
		} else {
			ptr++;
		}
	}

	jeAppletTagDelete(curApplet);  // If we hit don't hit </Applet>
	return firstApplet;
}
