/* elsewhen.c: -*- C -*-  Provide a <when> ... <elsewhen> </when> tag. */

/*  Copyright (c) 1997 Brian J. Fox
    Author: Brian J. Fox (bfox@ai.mit.edu) Wed Jun 18 18:44:04 1997.

    This file is part of <Meta-HTML>(tm), a system for the rapid
    deployment of Internet and Intranet applications via the use of
    the Meta-HTML language.

    Copyright (c) 1995, 1996, Brian J. Fox (bfox@ai.mit.edu).
    Copyright (c) 1996, Universal Access Inc. (http://www.ua.com).

    Meta-HTML is free software; you can redistribute it and/or modify
    it under the terms of the UAI Free Software License as published
    by Universal Access Inc.; either version 1, 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
    UAI Free Software License for more details.

    You should have received a copy of the UAI Free Software License
    along with this program; if you have not, you may obtain one by
    writing to:

    Universal Access Inc.
    129 El Paseo Court
    Santa Barbara, CA
    93101  */

#include "language.h"

static void pf_when (PFunArgs);
#define COMPLEX_ELSE_IF 1

#if defined (COMPLEX_ELSE_IF)
static void pf_complex_if (PFunArgs);
#endif

/* 2) Create a static table which associates function name, type, debug-flags,
      and address of code for each function. */
static PFunDesc functab[] = {
  /*   tag	     complex? debug_level	   code    */
  { "WHEN",		1,	 0,		pf_when },
#if defined (COMPLEX_ELSE_IF)
  { "IF",		1,	 0,		pf_complex_if },
#endif
  { (char *)NULL,	0,	 0,		(PFunHandler *)NULL }
};

void
module_initialize (void)
{
  register int i;
  Symbol *sym;

  /* Install the names and pointers. */
  for (i = 0; functab[i].tag != (char *)NULL; i++)
    {
      sym = symbol_intern_in_package (mhtml_function_package, functab[i].tag);
      sym->type = symtype_FUNCTION;
      sym->values = (char **)(&functab[i]);
    }
}

void _init (void) { module_initialize (); }

/* Just like <when> ... </when> but allow <elsewhen> to appear in the body. */
static void
pf_when (PFunArgs)
{
  char *test = mhtml_evaluate_string (get_positional_arg (vars, 0));
  char *else_text = (char *)NULL;
  int e_start = 0, else_start = 0;

  /* Find *all* occurences of <elsewhen> until there are none left, or
     until we found one that belongs to us. */
  while (1)
    {
      int e_end, ours_p;

      /* Is it within our <when> body? */
      ours_p = page_indicator_owned_by
	(body, "elsewhen", "when", &e_start, &e_end, else_start);

      if (ours_p == 1)
	{
	  body->buffer[e_start] = '\0';
	  while ((e_end < body->bindex) && (whitespace (body->buffer[e_end])))
	    e_end++;
	  else_text = body->buffer + e_end;
	  break;
	}
      else if (ours_p == 0)
	{
	  /* Not found at all. Quit looking. */
	  break;
	}
      else
	{
	  /* Not within our body.  Try finding the next one. */
	  else_start = e_end;
	  e_start = 0;
	}
    }

  if (!empty_string_p (test))
    bprintf_insert (page, start, "%s", body->buffer);
  else if (else_text)
    bprintf_insert (page, start, "%s", else_text);

  xfree (test);
}

#if defined (COMPLEX_ELSE_IF)
/* A non-lisp friendly <if> <else> </if> tag. */
static void
pf_complex_if (PFunArgs)
{
  char *test = mhtml_evaluate_string (get_positional_arg (vars, 0));
  char *else_text = (char *)NULL;
  int e_start = 0, else_start = 0;

  /* Find *all* occurences of <else> until there are none left, or
     until we found one that belongs to us. */
  while (1)
    {
      int e_end, ours_p;

      /* Is it within our <when> body? */
      ours_p = page_indicator_owned_by
	(body, "else", "if", &e_start, &e_end, else_start);

      if (ours_p == 1)
	{
	  body->buffer[e_start] = '\0';
	  while ((e_end < body->bindex) && (whitespace (body->buffer[e_end])))
	    e_end++;
	  else_text = body->buffer + e_end;
	  break;
	}
      else if (ours_p == 0)
	{
	  /* Not found at all. Quit looking. */
	  break;
	}
      else
	{
	  /* Not within our body.  Try finding the next one. */
	  else_start = e_end;
	  e_start = 0;
	}
    }

  if (!empty_string_p (test))
    bprintf_insert (page, start, "%s", body->buffer);
  else if (else_text)
    bprintf_insert (page, start, "%s", else_text);

  xfree (test);
}
#endif /* COMPLEX_ELSE_IF */
