/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  backend-html.c defines the screen output backend of refdbd
  markus@mhoenicka.de 9-5-00

   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, see <http://www.gnu.org/licenses/>

  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

#include <string.h>
#include <syslog.h> /* for definitions of log message priorities */
#include <stdio.h>
#include <dbi/dbi.h>

#include "refdb.h"
#include "linklist.h"
#include "backend.h"
#include "backend-html.h"
#include "writenote.h"
#include "strfncs.h"
#include "refdbd.h"
#include "cgi.h"
#include "dbfncs.h"
#include "connect.h"

extern char refdblib[]; /* location of shareable files */
extern int n_log_level; /* numeric version of log_level */

/* forward declaration of local functions */
static char* print_field_html(const char* item, struct renderinfo* ptr_rendinfo, const char* start_string);
static int add_partdata_html(char** ptr_buffer, size_t* ptr_buffer_len, struct renderinfo* ptr_rendinfo, int n_istemp, unsigned long long refcount);
static int add_setdata_html(char** ptr_buffer, size_t* ptr_buffer_len, struct renderinfo* ptr_rendinfo, int n_istemp, unsigned long long refcount);
static int add_author_info_html(char** ptr_buffer, size_t* ptr_buffer_len, int type, struct renderinfo* ptr_rendinfo, int n_istemp, unsigned long long refcount);

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  prepare_render_html(): writes a header for the html output of a
                         query

  int prepare_render_html returns 0 if successful, >0 if failed

  struct renderinfo* ptr_rendinfo ptr to a structure with the info
                             how the reference should be rendered

 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
int prepare_render_html(struct renderinfo* ptr_rendinfo) {
  char* new_ref;
  char* header;

  if ((header = assemble_header(ptr_rendinfo)) == NULL) {
    return 801;
  }

  if ((new_ref = mstrcpy(*(ptr_rendinfo->ptr_ref), header, ptr_rendinfo->ptr_ref_len)) == NULL) {
    free(header);
    return 801;
  }
  else {
    *(ptr_rendinfo->ptr_ref) = new_ref;
    free(header);
  }

  return 0;
}

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  finish_render_html(): writes a footer for the html output of a query

  int finish_render_html returns 0 if successful, >0 if failed

  struct renderinfo* ptr_rendinfo ptr to a structure with the info
                             how the reference should be rendered

 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
int finish_render_html(struct renderinfo* ptr_rendinfo) {
  int n_cgi;
  char* new_ref;
  char* html_foot;

  n_cgi = (ptr_rendinfo->ref_format == 6) ? 1:0;

  if (n_cgi) {
    html_foot = load_html("refdbq_foot", refdblib);
    if (!html_foot) {
      LOG_PRINT(LOG_ERR, get_status_msg(802));
      return 802;
    }
    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), html_foot, ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
      free(html_foot);
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }
    free(html_foot);
  }
  else {
    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "</body>\n</html>\n", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }
  }

  return 0;
}

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  render_html() renders a RIS dataset for html output

  int render_html returns 0 if successful, >0 if failed

  struct renderinfo* ptr_rendinfo ptr to a structure with the info
                             how the reference should be rendered

  int n_istemp if 0, retrieve data from permanent tables
               if 1, retrieve data from temporary tables
	       if 2, retrieve data from temporary tables, but compute
                     frequency data from the permanent tables

  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
int render_html(struct renderinfo* ptr_rendinfo, int n_istemp) {
  int n_cgi;
  int errcode; /* receives error code for periodical requests */
  int nhave_booktitle = 0;
  int nhave_para = 0;
  int render_res;
  int retval = 0;
  unsigned long long refcount;
  unsigned long long frequency;
  size_t buffer_len = 4096;
  char have_page = 0;
  const char* item;
  char id[32] = "";
  char* new_ref;
  const char* type;
  char* avail;
  char *entitize_buf;
  char date_buffer[256];
  char href_buffer[20];
  char hr_buffer[10];
  char* buffer;
  dbi_result dbires;
  dbi_conn conn;
  struct REPRINT reprint;

  n_cgi = (ptr_rendinfo->ref_format == REFCGIHTML) ? 1:0;

  if (ptr_rendinfo->ref_format == REFXHTML) {
    strcpy(hr_buffer, "<hr />\n");
  }
  else {
    strcpy(hr_buffer, "<hr>\n");
  }

  if ((buffer = malloc(buffer_len)) == NULL) {
    LOG_PRINT(LOG_CRIT, get_status_msg(801));
    retval = 801;
    goto cleanup;
  }
  *buffer = '\0';

  if ((type = get_refdb_type(ptr_rendinfo->dbires)) == NULL) {
    LOG_PRINT(LOG_WARNING, get_status_msg(234));
    retval = 234;
    goto cleanup;
  }

  conn = dbi_result_get_conn(ptr_rendinfo->dbires);

  if (n_cgi) {
    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "<tr><td class=\"result\">", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      retval = 801;
      goto cleanup;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }
  }

  /* get reference count for later use */
  refcount = get_reference_count(dbi_result_get_conn(ptr_rendinfo->dbires), NULL, 0 /* istemp */);

  /*----------------------------------------------------------------*/
  /* ID */
  get_refdb_id(ptr_rendinfo->dbires, id);

  if (*id) {
    if (n_cgi) {
      /* misuse date_buffer */
      sprintf(date_buffer, "<input type=\"checkbox\" name=\"pickid%s\" value=\"1\">&nbsp;<input type=\"submit\" value=\"Edit\" name=\"editid%s\">", id, id);
      if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), date_buffer, ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	retval = 801;
	goto cleanup;
      }
      else {
	*(ptr_rendinfo->ptr_ref) = new_ref;
      }
    }
    /* else: do nothing */
  }
  else {
    LOG_PRINT(LOG_WARNING, get_status_msg(234));
    retval = 234;
    goto cleanup;
  }

  /* each reference is wrapped in a div element */
  if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "<div class=\"record\">\n", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
    LOG_PRINT(LOG_CRIT, get_status_msg(801));
    retval = 801;
    goto cleanup;
  }
  else {
    *(ptr_rendinfo->ptr_ref) = new_ref;
  }

  /* misuse date_buffer */
  if (is_in_list(ptr_rendinfo->dbires, ptr_rendinfo->username) == 1) {
    strcpy(date_buffer, "<h2 class='IDpersonal'>ID:");
  }
  else {
    strcpy(date_buffer, "<h2 class='ID'>ID:");
  }

  if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), date_buffer, ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
    LOG_PRINT(LOG_CRIT, get_status_msg(801));
    retval = 801;
    goto cleanup;
  }
  else {
    *(ptr_rendinfo->ptr_ref) = new_ref;
  }

  /* ID */
  if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), id, ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
    LOG_PRINT(LOG_CRIT, get_status_msg(801));
    retval = 801;
    goto cleanup;
  }
  else {
    *(ptr_rendinfo->ptr_ref) = new_ref;
  }

  if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "</h2>\n", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
    LOG_PRINT(LOG_CRIT, get_status_msg(801));
    retval = 801;
    goto cleanup;
  }
  else {
    *(ptr_rendinfo->ptr_ref) = new_ref;
  }


  /*----------------------------------------------------------------*/
  /* citation key */
  item = get_refdb_citekey(ptr_rendinfo->dbires);

  /* citation key is preprocessed and cannot contain offending xml chars */
  if (item && *item) {
    if (print_field_html(item, ptr_rendinfo, "<p class='citekey'>CITEKEY:") == NULL) {
      return 234;
    }
  }

  /*----------------------------------------------------------------*/
  /* the part apparatus (analytic) */

  if (has_part_data(type)) {
    if ((retval = add_partdata_html(&buffer, &buffer_len, ptr_rendinfo, n_istemp, refcount)) != 0) {
      goto cleanup;
    }
    else if (*buffer) {
      if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "<div class=\"part\">\n", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	retval = 801;
	goto cleanup;
      }
      else {
	*(ptr_rendinfo->ptr_ref) = new_ref;
      }

      if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), buffer, ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	retval = 801;
	goto cleanup;
      }
      else {
	*(ptr_rendinfo->ptr_ref) = new_ref;
      }

      if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "</div>\n", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	retval = 801;
	goto cleanup;
      }
      else {
	*(ptr_rendinfo->ptr_ref) = new_ref;
      }
    }
    *buffer = '\0';
  }

  /*----------------------------------------------------------------*/
  /* the publication apparatus (monographic) */

  if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "<div class=\"publication\">\n", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
    LOG_PRINT(LOG_CRIT, get_status_msg(801));
    return 801;
  }
  else {
    *(ptr_rendinfo->ptr_ref) = new_ref;
  }

  if (has_chapter_data(type)) {
    /* use a verbal separator to start the monographic data */
    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "in:\n", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }
  }

  /*----------------------------------------------------------------*/
  /* authors */
  if ((retval = add_author_info_html(&buffer, &buffer_len, 2 /* publication */, ptr_rendinfo, n_istemp, refcount)) != 0) {
    goto cleanup;
  }
  
  if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), buffer, ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
    LOG_PRINT(LOG_CRIT, get_status_msg(801));
    retval = 801;
    goto cleanup;
  }
  else {
    *(ptr_rendinfo->ptr_ref) = new_ref;
  }

  *buffer = '\0';

  if (has_periodical_data(type)) {
    /*----------------------------------------------------------------*/
    /* periodical */
    int rel_frequency;
    char buffer[64];

    nhave_para = 1;
    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "<p>", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }

    /* fetch journal of this article */
    if ((item = get_periodical(dbi_result_get_conn(ptr_rendinfo->dbires), date_buffer, NULL, 4, &errcode, n_istemp, my_dbi_result_get_idval(ptr_rendinfo->dbires, "refdb_id"), &frequency)) != NULL) {

      rel_frequency = calculate_relative_frequency(frequency, refcount);

      sprintf(buffer, "<span class='periodical relfreq%d'>", rel_frequency);
      if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), buffer, ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
      else {
	*(ptr_rendinfo->ptr_ref) = new_ref;
      }

      if ((entitize_buf = strdup(item)) != NULL
	  && sgml_entitize(&entitize_buf, ptr_rendinfo->ref_format) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
      
      if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), entitize_buf, ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	free(entitize_buf);
	return 801;
      }
      else {
	*(ptr_rendinfo->ptr_ref) = new_ref;
      }

      free(entitize_buf);

      if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "</span> ", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
      else {
	*(ptr_rendinfo->ptr_ref) = new_ref;
      }
    }
  }

  /*----------------------------------------------------------------*/
  /* publication title */
  item = get_refdb_booktitle_copy(ptr_rendinfo->dbires);
  if (item != NULL) {
    nhave_booktitle++;

    if (sgml_entitize((char**)&item, ptr_rendinfo->ref_format) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
      
    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "<span class='title'>", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }

    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), (char*)item, ptr_rendinfo->ptr_ref_len, 0)) == NULL) { /* book title */
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      free((char*)item);
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }
    free((char*)item);

    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "</span>", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }
  }


  /*----------------------------------------------------------------*/
  /* edition */
  item = get_refdb_edition(ptr_rendinfo->dbires);
  if (item != NULL) {
    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), " <span class='edition'>(", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }

    if ((entitize_buf = strdup(item)) != NULL
	&& sgml_entitize(&entitize_buf, ptr_rendinfo->ref_format) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
      
    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), entitize_buf, ptr_rendinfo->ptr_ref_len, 0)) == NULL) { /* volume */
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      free(entitize_buf);
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }
    
    free(entitize_buf);

    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), ".edition)</span> ", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }
  }
  
  /*----------------------------------------------------------------*/
  /* volume */
  item = get_refdb_volume(ptr_rendinfo->dbires);
  if (item != NULL) {
    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "<span class='volume'>", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }

    if ((entitize_buf = strdup(item)) != NULL
	&& sgml_entitize(&entitize_buf, ptr_rendinfo->ref_format) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
      
    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), entitize_buf, ptr_rendinfo->ptr_ref_len, 0)) == NULL) { /* volume */
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      free(entitize_buf);
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }
    
    free(entitize_buf);

    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "</span>", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }
  }
  
  /*----------------------------------------------------------------*/
  /* issue */
  item = get_refdb_issue(ptr_rendinfo->dbires);  
  if (item != NULL) {
    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "<span class='issue'>(", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }

    if ((entitize_buf = strdup(item)) != NULL
	&& sgml_entitize(&entitize_buf, ptr_rendinfo->ref_format) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
      
    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), entitize_buf, ptr_rendinfo->ptr_ref_len, 0)) == NULL) { /* issue */
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      free(entitize_buf);
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }

    free(entitize_buf);
    
    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), ")</span>", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }
  }

  /*----------------------------------------------------------------*/
  /* startpage */
  item = get_refdb_startpage(ptr_rendinfo->dbires);
  if (item != NULL) {
    have_page++;
    if (strcmp(type, "BOOK") == 0 || strcmp(type, "SER") == 0 ||
	strcmp(type, "THES") == 0 || strcmp(type, "RPRT") == 0 ||
	strcmp(type, "CHAP") == 0) {
      if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "<span class='page'>pp. ", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
      else {
	*(ptr_rendinfo->ptr_ref) = new_ref;
      }
    }
    else {
      if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), ":<span class='page'>", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
      else {
	*(ptr_rendinfo->ptr_ref) = new_ref;
      }
    }

    if ((entitize_buf = strdup(item)) != NULL
	&& sgml_entitize(&entitize_buf, ptr_rendinfo->ref_format) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
      
    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), entitize_buf, ptr_rendinfo->ptr_ref_len, 0)) == NULL) { /* start page */
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      free(entitize_buf);
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }

    free(entitize_buf);
  }
  
  /*----------------------------------------------------------------*/
  /* endpage */
  item = get_refdb_endpage(ptr_rendinfo->dbires);
  if (item != NULL) {
    have_page++;
    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "-", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }

    if ((entitize_buf = strdup(item)) != NULL
	&& sgml_entitize(&entitize_buf, ptr_rendinfo->ref_format) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
      
    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), entitize_buf, ptr_rendinfo->ptr_ref_len, 0)) == NULL) { /* end page */
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      free(entitize_buf);
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }

    free(entitize_buf);
  }

  if (have_page) {
    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "</span>", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }
  }

  /*----------------------------------------------------------------*/
  /* pubyear */
  item = get_refdb_pubyear(ptr_rendinfo->dbires, date_buffer);
  if (item != NULL) {
    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), " (", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }

    /* year */
    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), date_buffer, ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }

    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), ")", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }

  }

  if (nhave_para) {
    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "</p>\n", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }
  }
  
  if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "\n</div>\n", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
    LOG_PRINT(LOG_CRIT, get_status_msg(801));
    return 801;
  }
  else {
    *(ptr_rendinfo->ptr_ref) = new_ref;
  }

  /*----------------------------------------------------------------*/
  /* the set apparatus (series) */

  if (has_set_data(type)) {
    if ((retval = add_setdata_html(&buffer, &buffer_len, ptr_rendinfo, n_istemp, refcount)) != 0) {
      goto cleanup;
    }
    else if (*buffer) {
      if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "<div class=\"set\">\npart of: ", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	retval = 801;
	goto cleanup;
      }
      else {
	*(ptr_rendinfo->ptr_ref) = new_ref;
      }

      if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), buffer, ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	retval = 801;
	goto cleanup;
      }
      else {
	*(ptr_rendinfo->ptr_ref) = new_ref;
      }

      if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "</div>\n", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	retval = 801;
	goto cleanup;
      }
      else {
	*(ptr_rendinfo->ptr_ref) = new_ref;
      }
    }
    *buffer = '\0';
  }

  /*----------------------------------------------------------------*/
  /* abstract */
 if (strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "N2") != NULL
     || strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "AB") != NULL
     || strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "ALL") != NULL) {
    item = get_refdb_abstract_copy(ptr_rendinfo->dbires);
    if (item != NULL) {
      if (sgml_entitize((char**)&item, ptr_rendinfo->ref_format) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	free((char*)item);
	return 801;
      }
      
      if (print_field_html(item, ptr_rendinfo, "<p class='abstract'>ABSTRACT: ") == NULL) {
	free((char*)item);
	return 801;
      }
      free((char*)item);
    }
  }

  /*----------------------------------------------------------------*/
  /* address */
 if (strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "AD") != NULL
     || strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "ALL") != NULL) {
    item = get_refdb_address_copy(ptr_rendinfo->dbires);
    if (item != NULL) {
      if (sgml_entitize((char**)&item, ptr_rendinfo->ref_format) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	free((char*)item);
	return 801;
      }
      
      if (print_field_html(item, ptr_rendinfo, "<p class='address'>ADDRESS: ") == NULL) {
	free((char*)item);
	return 801;
      }
      free((char*)item);
    }
  }

  /*----------------------------------------------------------------*/
  /* reprint, availability  */
  if (strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "RP") != NULL
      || strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "ALL") != NULL) {
    if (get_reprint(ptr_rendinfo->dbires, &reprint, ptr_rendinfo->username, 4) != NULL && reprint.reprint != NULL && *(reprint.reprint)) {
      if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "<p class='rp'>REPRINT: ", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
      else {
	*(ptr_rendinfo->ptr_ref) = new_ref;
      }

      if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), reprint.reprint, ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
      else {
	*(ptr_rendinfo->ptr_ref) = new_ref;
      }

      if (reprint.date != NULL && *(reprint.date)) {
	if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), " (", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	  LOG_PRINT(LOG_CRIT, get_status_msg(801));
	  return 801;
	}
	else {
	  *(ptr_rendinfo->ptr_ref) = new_ref;
	}
	if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), reprint.date, ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	  LOG_PRINT(LOG_CRIT, get_status_msg(801));
	  return 801;
	}
	else {
	  *(ptr_rendinfo->ptr_ref) = new_ref;
	}
	if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), ")", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	  LOG_PRINT(LOG_CRIT, get_status_msg(801));
	  return 801;
	}
	else {
	  *(ptr_rendinfo->ptr_ref) = new_ref;
	}
      }
    }
    if (reprint.date != NULL && *(reprint.date)) {
      if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), ": ", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
      else {
	*(ptr_rendinfo->ptr_ref) = new_ref;
      }
      if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), reprint.date, ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
      else {
	*(ptr_rendinfo->ptr_ref) = new_ref;
      }
    }
    if (reprint.avail != NULL && *(reprint.avail)) {
      if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), ": ", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
      else {
	*(ptr_rendinfo->ptr_ref) = new_ref;
      }

      avail = mstrdup(reprint.avail);
      if (avail == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
      if (strncmp(strup(avail), "PATH:", 5) == 0) {
	free(avail);
	/* if pdfroot specifies a protocol, use it as a prefix for
	   the href attribute. If not, add file:// as a pseudo
	   protocol */
	if (strncmp(ptr_rendinfo->pdfroot, "http://", 7) == 0
	    || strncmp(ptr_rendinfo->pdfroot, "HTTP://", 7) == 0
	    || strncmp(ptr_rendinfo->pdfroot, "ftp://", 6) == 0
	    || strncmp(ptr_rendinfo->pdfroot, "FTP://", 6) == 0
	    || strncmp(ptr_rendinfo->pdfroot, "file://", 7) == 0
	    || strncmp(ptr_rendinfo->pdfroot, "FILE://", 7) == 0) {
	  strcpy(href_buffer, "<a href=\"");
	}
	else {
	  strcpy(href_buffer, "<a href=\"file://");
	}

	if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), href_buffer, ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	  LOG_PRINT(LOG_CRIT, get_status_msg(801));
	  return 801;
	}
	else {
	  *(ptr_rendinfo->ptr_ref) = new_ref;
	}
	if (*(ptr_rendinfo->pdfroot)) {
	  if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), ptr_rendinfo->pdfroot, ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	    LOG_PRINT(LOG_CRIT, get_status_msg(801));
	    return 801;
	  }
	  else {
	    *(ptr_rendinfo->ptr_ref) = new_ref;
	  }
	}

	if ((entitize_buf = strdup(reprint.avail+5)) != NULL
	    && sgml_entitize(&entitize_buf, ptr_rendinfo->ref_format) == NULL) {
	  LOG_PRINT(LOG_CRIT, get_status_msg(801));
	  return 801;
	}
      
	if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), entitize_buf, ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	  LOG_PRINT(LOG_CRIT, get_status_msg(801));
	  free(entitize_buf);
	  return 801;
	}
	else {
	  *(ptr_rendinfo->ptr_ref) = new_ref;
	}

	if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "\">", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	  LOG_PRINT(LOG_CRIT, get_status_msg(801));
	  free(entitize_buf);
	  return 801;
	}
	else {
	  *(ptr_rendinfo->ptr_ref) = new_ref;
	}

	if (*(ptr_rendinfo->pdfroot)) {
	  if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), ptr_rendinfo->pdfroot, ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	    LOG_PRINT(LOG_CRIT, get_status_msg(801));
	    return 801;
	  }
	  else {
	    *(ptr_rendinfo->ptr_ref) = new_ref;
	  }
	}

	if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), entitize_buf, ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	  LOG_PRINT(LOG_CRIT, get_status_msg(801));
	  free(entitize_buf);
	  return 801;
	}
	else {
	  *(ptr_rendinfo->ptr_ref) = new_ref;
	}

	free(entitize_buf);

	if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "</a>", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	  LOG_PRINT(LOG_CRIT, get_status_msg(801));
	  return 801;
	}
	else {
	  *(ptr_rendinfo->ptr_ref) = new_ref;
	}
      }
      else {
	int n_renderaslink = 0;

	free(avail);
	/* if the availability string starts with a protocol
	   specifier, render the string as a link */
	if (strncmp(reprint.avail, "http://", 7) == 0
	    || strncmp(reprint.avail, "HTTP://", 7) == 0
	    || strncmp(reprint.avail, "ftp://", 6) == 0
	    || strncmp(reprint.avail, "FTP://", 6) == 0
	    || strncmp(reprint.avail, "file://", 7) == 0
	    || strncmp(reprint.avail, "FILE://", 7) == 0) {
	  n_renderaslink++;
	  if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "<a href=\"", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	    LOG_PRINT(LOG_CRIT, get_status_msg(801));
	    return 801;
	  }
	  else {
	    *(ptr_rendinfo->ptr_ref) = new_ref;
	  }

	  if ((entitize_buf = strdup(reprint.avail)) != NULL
	      && sgml_entitize(&entitize_buf, ptr_rendinfo->ref_format) == NULL) {
	    LOG_PRINT(LOG_CRIT, get_status_msg(801));
	    return 801;
	  }
      
	  if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), entitize_buf, ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	    LOG_PRINT(LOG_CRIT, get_status_msg(801));
	    free(entitize_buf);
	    return 801;
	  }
	  else {
	    *(ptr_rendinfo->ptr_ref) = new_ref;
	  }

	  if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "\">", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	    LOG_PRINT(LOG_CRIT, get_status_msg(801));
	    free(entitize_buf);
	    return 801;
	  }
	  else {
	    *(ptr_rendinfo->ptr_ref) = new_ref;
	  }
	}

	if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), entitize_buf, ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	  LOG_PRINT(LOG_CRIT, get_status_msg(801));
	  free(entitize_buf);
	  return 801;
	}
	else {
	  *(ptr_rendinfo->ptr_ref) = new_ref;
	}

	free(entitize_buf);

	if (n_renderaslink) {
	  if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "</a>", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	    LOG_PRINT(LOG_CRIT, get_status_msg(801));
	    return 801;
	  }
	  else {
	    *(ptr_rendinfo->ptr_ref) = new_ref;
	  }
	}
      }
    }

    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "</p>\n", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }
  }

  /*----------------------------------------------------------------*/
  /* ISBN/ISSN */
 if (strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "SN") != NULL
     || strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "ALL") != NULL) {
    item = get_refdb_issn(ptr_rendinfo->dbires);

    if (item) {
      if ((entitize_buf = strdup(item)) != NULL
	  && sgml_entitize(&entitize_buf, ptr_rendinfo->ref_format) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
      
      if (print_field_html(entitize_buf, ptr_rendinfo, "<p class='issn'>ISSN: ") == NULL) {
	free(entitize_buf);
	return 801;
      }

      free(entitize_buf);
    }
  }

  /*----------------------------------------------------------------*/
  /* publisher */
 if (strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "PB") != NULL
     || strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "ALL") != NULL) {
    item = get_refdb_publisher(ptr_rendinfo->dbires);

    if (item) {
      if ((entitize_buf = strdup(item)) != NULL
	  && sgml_entitize(&entitize_buf, ptr_rendinfo->ref_format) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
      
      if (print_field_html(entitize_buf, ptr_rendinfo, "<p class='publisher'>PUBLISHER: ") == NULL) {
	free(entitize_buf);
	return 801;
      }

      free(entitize_buf);
    }
  }

  /*----------------------------------------------------------------*/
  /* city */
 if (strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "CY") != NULL
     || strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "ALL") != NULL) {
    item = get_refdb_city(ptr_rendinfo->dbires);

    if (item) {
      if ((entitize_buf = strdup(item)) != NULL
	  && sgml_entitize(&entitize_buf, ptr_rendinfo->ref_format) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
      
      if (print_field_html(entitize_buf, ptr_rendinfo, "<p class='city'>CITY: ") == NULL) {
	free(entitize_buf);
	return 801;
      }

      free(entitize_buf);
    }
  }

  /*----------------------------------------------------------------*/
  /* keywords */
  if (strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "KW") != NULL
      || strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "ALL") != NULL) {
    int rel_frequency;
    int have_keyword = 0;
    char buffer[64];

    dbires = request_keywords(conn, my_dbi_result_get_idval(ptr_rendinfo->dbires, "refdb_id"), 0, n_istemp);

    if (dbires == NULL) {
      return 234;
    }

    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "<p class='keywords'>KEYWORDS: ", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
      clean_request(dbires);
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }

    /* fetch all keywords of this article */
    while ((item = get_extended_keyword(dbires, n_istemp, &frequency)) != NULL) {
      have_keyword = 1;
      rel_frequency = calculate_relative_frequency(frequency, refcount);
      
      if ((entitize_buf = strdup(item)) == NULL
	  || sgml_entitize(&entitize_buf, ptr_rendinfo->ref_format) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
    
      /* todo: use relative frequency instead of absolute, e.g. an integer between 1 and 10 */
      sprintf(buffer, "<span class='keyword relfreq%d'>", rel_frequency);

      if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), buffer, ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	clean_request(dbires);
	free(entitize_buf);
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
      else {
	*(ptr_rendinfo->ptr_ref) = new_ref;
      }
      
      if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), entitize_buf, ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	clean_request(dbires);
	free(entitize_buf);
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
      else {
	*(ptr_rendinfo->ptr_ref) = new_ref;
      }
      
      free(entitize_buf);
      
      if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "</span>; ", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	clean_request(dbires);
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
      else {
	*(ptr_rendinfo->ptr_ref) = new_ref;
      }
    }
    clean_request(dbires);

    if (have_keyword) { /* eliminate the trailing comma after the last author */
      new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "</p>\n", ptr_rendinfo->ptr_ref_len, 2);
    }
    else {
      new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "</p>\n", ptr_rendinfo->ptr_ref_len, 0);
    }
    
    if (new_ref == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }
  }

  /*----------------------------------------------------------------*/
  /* user fields */
  if (strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "U1") != NULL
      || strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "ALL") != NULL) {
    item = get_refdb_user1(ptr_rendinfo->dbires);

    if (item) {
      if ((entitize_buf = strdup(item)) != NULL
	  && sgml_entitize(&entitize_buf, ptr_rendinfo->ref_format) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
      
      if (print_field_html(entitize_buf, ptr_rendinfo, "<p class='u1'>USER1: ") == NULL) {
	free(entitize_buf);
	return 801;
      }
      
      free(entitize_buf);
    }
  }

  if (strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "U2") != NULL
      || strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "ALL") != NULL) {
    item = get_refdb_user2(ptr_rendinfo->dbires);
    
    if (item) {
      if ((entitize_buf = strdup(item)) != NULL
	  && sgml_entitize(&entitize_buf, ptr_rendinfo->ref_format) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
      
      if (print_field_html(entitize_buf, ptr_rendinfo, "<p class='u2'>USER2: ") == NULL) {
	free(entitize_buf);
	return 801;
      }

      free(entitize_buf);
    }
  }

  if (strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "U3") != NULL
      || strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "ALL") != NULL) {
    item = get_refdb_user3(ptr_rendinfo->dbires);

    if (item) {
      if ((entitize_buf = strdup(item)) != NULL
	  && sgml_entitize(&entitize_buf, ptr_rendinfo->ref_format) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
      
      if (print_field_html(entitize_buf, ptr_rendinfo, "<p class='u3'>USER3: ") == NULL) {
	free(entitize_buf);
	return 801;
      }

      free(entitize_buf);
    }
  }

  if (strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "U4") != NULL
      || strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "ALL") != NULL) {
    item = get_refdb_user4(ptr_rendinfo->dbires);

    if (item) {
      if ((entitize_buf = strdup(item)) != NULL
	  && sgml_entitize(&entitize_buf, ptr_rendinfo->ref_format) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
      
      if (print_field_html(entitize_buf, ptr_rendinfo, "<p class='u4'>USER4: ") == NULL) {
	free(entitize_buf);
	return 801;
      }

      free(entitize_buf);
    }
  }

  if (strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "U5") != NULL
      || strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "ALL") != NULL) {
    item = get_refdb_user5(ptr_rendinfo->dbires);

    if (item) {
      if ((entitize_buf = strdup(item)) != NULL
	  && sgml_entitize(&entitize_buf, ptr_rendinfo->ref_format) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
      
      if (print_field_html(entitize_buf, ptr_rendinfo, "<p class='u5'>USER5: ") == NULL) {
	free(entitize_buf);
	return 801;
      }

      free(entitize_buf);
    }
  }

  /*----------------------------------------------------------------*/
  /* misc fields */
  if (strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "MX") != NULL
      || strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "ALL") != NULL) {
    item = get_refdb_typeofwork(ptr_rendinfo->dbires);

    if (item && *item) {
      if ((entitize_buf = strdup(item)) != NULL
	  && sgml_entitize(&entitize_buf, ptr_rendinfo->ref_format) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
      
      if (print_field_html(entitize_buf, ptr_rendinfo, "<p class='typeofwork'>TYPE OF WORK: ") == NULL) {
	free(entitize_buf);
	return 801;
      }

      free(entitize_buf);
    }

    item = get_refdb_area(ptr_rendinfo->dbires);

    if (item && *item) {
      if ((entitize_buf = strdup(item)) != NULL
	  && sgml_entitize(&entitize_buf, ptr_rendinfo->ref_format) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
      
      if (print_field_html(entitize_buf, ptr_rendinfo, "<p class='area'>AREA: ") == NULL) {
	free(entitize_buf);
	return 801;
      }

      free(entitize_buf);
    }

    item = get_refdb_ostype(ptr_rendinfo->dbires);

    if (item && *item) {
      if ((entitize_buf = strdup(item)) != NULL
	  && sgml_entitize(&entitize_buf, ptr_rendinfo->ref_format) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
      
      if (print_field_html(entitize_buf, ptr_rendinfo, "<p class='ostype'>OS TYPE: ") == NULL) {
	free(entitize_buf);
	return 801;
      }

      free(entitize_buf);
    }

    item = get_refdb_degree(ptr_rendinfo->dbires);

    if (item && *item) {
      if ((entitize_buf = strdup(item)) != NULL
	  && sgml_entitize(&entitize_buf, ptr_rendinfo->ref_format) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
      
      if (print_field_html(entitize_buf, ptr_rendinfo, "<p class='degree'>DEGREE: ") == NULL) {
	free(entitize_buf);
	return 801;
      }

      free(entitize_buf);
    }

    item = get_refdb_runningtime(ptr_rendinfo->dbires);

    if (item && *item) {
      if ((entitize_buf = strdup(item)) != NULL
	  && sgml_entitize(&entitize_buf, ptr_rendinfo->ref_format) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
      
      if (print_field_html(entitize_buf, ptr_rendinfo, "<p class='runningtime'>RUNNING TIME: ") == NULL) {
	free(entitize_buf);
	return 801;
      }

      free(entitize_buf);
    }

    item = get_refdb_classcodeintl(ptr_rendinfo->dbires);

    if (item && *item) {
      if ((entitize_buf = strdup(item)) != NULL
	  && sgml_entitize(&entitize_buf, ptr_rendinfo->ref_format) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
      
      if (print_field_html(entitize_buf, ptr_rendinfo, "<p class='classcodeintl'>CLASS CODE (INTL): ") == NULL) {
	free(entitize_buf);
	return 801;
      }

      free(entitize_buf);
    }

    item = get_refdb_classcodeus(ptr_rendinfo->dbires);

    if (item && *item) {
      if ((entitize_buf = strdup(item)) != NULL
	  && sgml_entitize(&entitize_buf, ptr_rendinfo->ref_format) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
      
      if (print_field_html(entitize_buf, ptr_rendinfo, "<p class='classcodeus'>CLASS CODE (US): ") == NULL) {
	free(entitize_buf);
	return 801;
      }

      free(entitize_buf);
    }

    item = get_refdb_senderemail(ptr_rendinfo->dbires);

    if (item && *item) {
      if ((entitize_buf = strdup(item)) != NULL
	  && sgml_entitize(&entitize_buf, ptr_rendinfo->ref_format) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
      
      if (print_field_html(entitize_buf, ptr_rendinfo, "<p class='senderemail'>EMAIL (SENDER): ") == NULL) {
	free(entitize_buf);
	return 801;
      }

      free(entitize_buf);
    }

    item = get_refdb_recipientemail(ptr_rendinfo->dbires);

    if (item && *item) {
      if ((entitize_buf = strdup(item)) != NULL
	  && sgml_entitize(&entitize_buf, ptr_rendinfo->ref_format) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
      
      if (print_field_html(entitize_buf, ptr_rendinfo, "<p class='recipientemail'>EMAIL (RECIPIENT): ") == NULL) {
	free(entitize_buf);
	return 801;
      }

      free(entitize_buf);
    }

    item = get_refdb_mediatype(ptr_rendinfo->dbires);

    if (item && *item) {
      if ((entitize_buf = strdup(item)) != NULL
	  && sgml_entitize(&entitize_buf, ptr_rendinfo->ref_format) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
      
      if (print_field_html(entitize_buf, ptr_rendinfo, "<p class='mediatype'>MEDIA TYPE: ") == NULL) {
	free(entitize_buf);
	return 801;
      }

      free(entitize_buf);
    }

    item = get_refdb_numvolumes(ptr_rendinfo->dbires);

    if (item && *item) {
      if ((entitize_buf = strdup(item)) != NULL
	  && sgml_entitize(&entitize_buf, ptr_rendinfo->ref_format) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
      
      if (print_field_html(entitize_buf, ptr_rendinfo, "<p class='numvolumes'>NUMBER OF VOLUMES: ") == NULL) {
	free(entitize_buf);
	return 801;
      }

      free(entitize_buf);
    }

    item = get_refdb_computer(ptr_rendinfo->dbires);

    if (item && *item) {
      if ((entitize_buf = strdup(item)) != NULL
	  && sgml_entitize(&entitize_buf, ptr_rendinfo->ref_format) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
      
      if (print_field_html(entitize_buf, ptr_rendinfo, "<p class='computer'>COMPUTER: ") == NULL) {
	free(entitize_buf);
	return 801;
      }

      free(entitize_buf);
    }

    item = get_refdb_conferencelocation(ptr_rendinfo->dbires);

    if (item && *item) {
      if ((entitize_buf = strdup(item)) != NULL
	  && sgml_entitize(&entitize_buf, ptr_rendinfo->ref_format) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
      
      if (print_field_html(entitize_buf, ptr_rendinfo, "<p class='conferencelocation'>CONFERENCE LOCATION: ") == NULL) {
	free(entitize_buf);
	return 801;
      }

      free(entitize_buf);
    }

    item = get_refdb_registrynum(ptr_rendinfo->dbires);

    if (item && *item) {
      if ((entitize_buf = strdup(item)) != NULL
	  && sgml_entitize(&entitize_buf, ptr_rendinfo->ref_format) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
      
      if (print_field_html(entitize_buf, ptr_rendinfo, "<p class='registrynum'>REGISTRY NUMBER: ") == NULL) {
	free(entitize_buf);
	return 801;
      }

      free(entitize_buf);
    }

    item = get_refdb_classification(ptr_rendinfo->dbires);

    if (item && *item) {
      if ((entitize_buf = strdup(item)) != NULL
	  && sgml_entitize(&entitize_buf, ptr_rendinfo->ref_format) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
      
      if (print_field_html(entitize_buf, ptr_rendinfo, "<p class='classification'>CLASSIFICATION: ") == NULL) {
	free(entitize_buf);
	return 801;
      }

      free(entitize_buf);
    }

    item = get_refdb_section(ptr_rendinfo->dbires);

    if (item && *item) {
      if ((entitize_buf = strdup(item)) != NULL
	  && sgml_entitize(&entitize_buf, ptr_rendinfo->ref_format) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
      
      if (print_field_html(entitize_buf, ptr_rendinfo, "<p class='section'>SECTION: ") == NULL) {
	free(entitize_buf);
	return 801;
      }

      free(entitize_buf);
    }

    item = get_refdb_pamphletnum(ptr_rendinfo->dbires);

    if (item && *item) {
      if ((entitize_buf = strdup(item)) != NULL
	  && sgml_entitize(&entitize_buf, ptr_rendinfo->ref_format) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
      
      if (print_field_html(entitize_buf, ptr_rendinfo, "<p class='pamphletnum'>PAMPHLET NUMBER: ") == NULL) {
	free(entitize_buf);
	return 801;
      }

      free(entitize_buf);
    }

    item = get_refdb_chapternum(ptr_rendinfo->dbires);

    if (item && *item) {
      if ((entitize_buf = strdup(item)) != NULL
	  && sgml_entitize(&entitize_buf, ptr_rendinfo->ref_format) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	return 801;
      }
      
      if (print_field_html(entitize_buf, ptr_rendinfo, "<p class='chapternum'>CHAPTER NUMBER: ") == NULL) {
	free(entitize_buf);
	return 801;
      }

      free(entitize_buf);
    }
  }


  /*----------------------------------------------------------------*/
  /* URL, L1-L4, DOI */
  if (strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "UR") != NULL
      || strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "DOI") != NULL
      || strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "LX") != NULL
      || strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "ALL") != NULL) {
    int i;
    char *entitize_string;
    char keytype[6][10] = {"URL", "PDF", "FULLTEXT", "RELATED", "IMAGE", "DOI"};
    char buffer[64];

    /* loop over all link types */
    for (i=0; i<6;i++) {
      dbires = request_ulinks(conn, my_dbi_result_get_idval(ptr_rendinfo->dbires, "refdb_id"), 0 /* ref entry */, i /* link type */, n_istemp, ptr_rendinfo->username);
      if (dbires == NULL) {
	return 234;
      }

      while ((item = get_ulink(dbires)) != NULL) {
	if (i != 5) {
	  /* render link as is */
	  sprintf(buffer, "<p class='ur'>%s: <a href=\"", keytype[i]);
	}
	else {
	  /* dx.doi.org resolves the identifier DOI to a web resource */
	  sprintf(buffer, "<p class='ur'>%s: <a href=\"http://dx.doi.org/", keytype[i]);
	}

	if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), buffer, ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	  LOG_PRINT(LOG_CRIT, get_status_msg(801));
	  clean_request(dbires);
	  return 801;
	}
	else {
	  *(ptr_rendinfo->ptr_ref) = new_ref;
	}

	if (i>0 && i<5) {
	  entitize_string = add_root_to_link(item, ptr_rendinfo->pdfroot);
	}
	else {
	  entitize_string = strdup(item);
	}

	if (entitize_string == NULL) {
	  LOG_PRINT(LOG_CRIT, get_status_msg(801));
	  clean_request(dbires);
	  return 801;
	}

	if (sgml_entitize(&entitize_string, ptr_rendinfo->ref_format) == NULL) {
	  LOG_PRINT(LOG_CRIT, get_status_msg(801));
	  clean_request(dbires);
	  free(entitize_string);
	  return 801;
	}
      
	if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), entitize_string, ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	  LOG_PRINT(LOG_CRIT, get_status_msg(801));
	  clean_request(dbires);
	  free(entitize_string);
	  return 801;
	}
	else {
	  *(ptr_rendinfo->ptr_ref) = new_ref;
	}

	if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "\">", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	  LOG_PRINT(LOG_CRIT, get_status_msg(801));
	  clean_request(dbires);
	  free(entitize_string);
	  return 801;
	}
	else {
	  *(ptr_rendinfo->ptr_ref) = new_ref;
	}

	if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), entitize_string, ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	  LOG_PRINT(LOG_CRIT, get_status_msg(801));
	  clean_request(dbires);
	  free(entitize_string);
	  return 801;
	}
	else {
	  *(ptr_rendinfo->ptr_ref) = new_ref;
	}

	free(entitize_string);

	if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "</a></p>\n", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
	  LOG_PRINT(LOG_CRIT, get_status_msg(801));
	  return 801;
	}
	else {
	  *(ptr_rendinfo->ptr_ref) = new_ref;
	}
      } /* end while */
      clean_request(dbires);
    } /* end for */
  }

  /*----------------------------------------------------------------*/
  /* notes */
  if (strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "N1") != NULL
      || strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "ALL") != NULL) {
    item = get_notes_copy(ptr_rendinfo->dbires, ptr_rendinfo->username);

    if (item != NULL) {
      if (sgml_entitize((char**)&item, ptr_rendinfo->ref_format) == NULL) {
	LOG_PRINT(LOG_CRIT, get_status_msg(801));
	free((char*)item);
	return 801;
      }
      
      if (print_field_html(item, ptr_rendinfo, "<p class='note'>NOTES:") == NULL) {
	free((char*)item);
	return 801;
      }
      free((char*)item);
    }
  }

  /*----------------------------------------------------------------*/
  /* extended notes */
  if (strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "NX") != NULL
      || strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "ALL") != NULL) {
    dbi_result orig_dbires;

    /* look for additional notes linked with the record,
       keywords, authors, or periodicals */
    /* see whether to include reference lists */
    if (strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "NL") != NULL
	|| strstr((ptr_rendinfo->ptr_biblio_info)->format_string, "ALL") != NULL) {
      if ((dbires = request_notes_by_ref(dbi_result_get_conn(ptr_rendinfo->dbires), atoll(id), REFERENCE|KEYWORD|AUTHOR|PERIODICAL, ptr_rendinfo->username, ptr_rendinfo->ptr_clrequest->share_default, 1/* include lists */)) == NULL) {
	/*       printf("request_notes_by_ref() failed\n"); */
	free_request_notes_by_ref(dbi_result_get_conn(ptr_rendinfo->dbires));
	return 234;
      }
    }
    else {
      if ((dbires = request_notes_by_ref(dbi_result_get_conn(ptr_rendinfo->dbires), atoll(id), REFERENCE|KEYWORD|AUTHOR|PERIODICAL, ptr_rendinfo->username, ptr_rendinfo->ptr_clrequest->share_default, 0/* exclude lists */)) == NULL) {
	/*       printf("request_notes_by_ref() failed\n"); */
	free_request_notes_by_ref(dbi_result_get_conn(ptr_rendinfo->dbires));
	return 234;
      }
    }
    
    /* save original query result. This is legal as dbi_result is a
       pointer in disguise */
    orig_dbires = ptr_rendinfo->dbires;
    ptr_rendinfo->dbires = dbires;

    while (dbi_result_next_row(ptr_rendinfo->dbires) != 0) {
      if ((render_res = render_note(ptr_rendinfo)) != 0) {
	ptr_rendinfo->dbires = orig_dbires;
	clean_request(dbires);
	free_request_notes_by_ref(dbi_result_get_conn(ptr_rendinfo->dbires));
	return render_res;
      }
    }
    clean_request(dbires);
    free_request_notes_by_ref(dbi_result_get_conn(orig_dbires));
    ptr_rendinfo->dbires = orig_dbires;
  }

  if (n_cgi) {
    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "</td></tr>\n", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }
  }
  else {
    /* finish div */
    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "</div>\n", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }
  }

/*      printf("%s\n", *(ptr_rendinfo->ptr_ref)); */

 cleanup:
  free(buffer);

  return 0;
}

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  add_partdata_html(): writes part data into a buffer

  static int add_partdata_scrn returns 0 if ok or an error code > 0

  char** ptr_buffer ptr to a buffer that will receive the output. The
                buffer will be reallocated as needed

  size_t* ptr_buffer_len ptr to the length of buffer. Will be updated
                if buffer is reallocated

  struct renderinfo* ptr_rendinfo ptr to a structure with the info
                             how the reference should be rendered

  int n_istemp if 0, retrieve data from permanent tables
               if 1, retrieve data from temporary tables
	       if 2, retrieve data from temporary tables, but compute
                     frequency data from the permanent tables

  unsigned long long refcount total number of refs in the database

 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
static int add_partdata_html(char** ptr_buffer, size_t* ptr_buffer_len, struct renderinfo* ptr_rendinfo, int n_istemp, unsigned long long refcount) {
  char* item;
  char* new_buffer;
  int result;

  /*----------------------------------------------------------------*/
  /* authors */
  if ((result = add_author_info_html(ptr_buffer, ptr_buffer_len, 1 /* part */, ptr_rendinfo, n_istemp, refcount)) != 0) {
    return result;
  }

  /*----------------------------------------------------------------*/
  /* title */
  item = get_refdb_title_copy(ptr_rendinfo->dbires);
  if (item != NULL) {
    if ((new_buffer = mstrcat(*ptr_buffer, "<span class='title'>", ptr_buffer_len, 0)) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *ptr_buffer = new_buffer;
    }

    if ((new_buffer = mstrcat(*ptr_buffer, item, ptr_buffer_len, 0)) == NULL) { /* title */
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      free(item);
      return 801;
    }
    else {
      *ptr_buffer = new_buffer;
    }
    
    free(item);
    
    if ((new_buffer = mstrcat(*ptr_buffer, "</span>\n", ptr_buffer_len, 0)) == NULL) {
      free(item);
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *ptr_buffer = new_buffer;
    }
  }

  return 0;
}

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  add_setdata_html(): writes set data into a buffer

  static int add_setdata_html returns 0 if ok or an error code > 0

  char** ptr_buffer ptr to a buffer that will receive the output. The
                buffer will be reallocated as needed

  size_t* ptr_buffer_len ptr to the length of buffer. Will be updated
                if buffer is reallocated

  struct renderinfo* ptr_rendinfo ptr to a structure with the info
                             how the reference should be rendered

  int n_istemp if 0, retrieve data from permanent tables
               if 1, retrieve data from temporary tables
	       if 2, retrieve data from temporary tables, but compute
                     frequency data from the permanent tables

  unsigned long long refcount total number of refs in the database

 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
static int add_setdata_html(char** ptr_buffer, size_t* ptr_buffer_len, struct renderinfo* ptr_rendinfo, int n_istemp, unsigned long long refcount) {
  char* item;
  char* new_buffer;
  int result;

  /*----------------------------------------------------------------*/
  /* authors */
  if ((result = add_author_info_html(ptr_buffer, ptr_buffer_len, 3 /* set */, ptr_rendinfo, n_istemp, refcount)) != 0) {
    return result;
  }

  /*----------------------------------------------------------------*/
  /* title */
  item = get_refdb_title_series_copy(ptr_rendinfo->dbires);
  if (item != NULL) {
    if ((new_buffer = mstrcat(*ptr_buffer, "<span class='title'>", ptr_buffer_len, 0)) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *ptr_buffer = new_buffer;
    }

    if ((new_buffer = mstrcat(*ptr_buffer, item, ptr_buffer_len, 0)) == NULL) { /* title */
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      free(item);
      return 801;
    }
    else {
      *ptr_buffer = new_buffer;
    }
    
    free(item);
    
    if ((new_buffer = mstrcat(*ptr_buffer, "</span>\n", ptr_buffer_len, 0)) == NULL) {
      free(item);
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *ptr_buffer = new_buffer;
    }
  }

  return 0;
}

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  add_author_info_html(): writes author data into a buffer

  static int add_author_info_html returns 0 if ok or an error code > 0

  char** ptr_buffer ptr to a buffer that will receive the output. The
                buffer will be reallocated as needed

  size_t* ptr_buffer_len ptr to the length of buffer. Will be updated
                if buffer is reallocated

  int type 1=part authors, 2=publication authors, 3=set authors

  struct renderinfo* ptr_rendinfo ptr to a structure with the info
                             how the reference should be rendered

  int n_istemp if 0, retrieve data from permanent tables
               if 1, retrieve data from temporary tables
	       if 2, retrieve data from temporary tables, but compute
                     frequency data from the permanent tables

  unsigned long long refcount total number of refs in the database

 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
static int add_author_info_html(char** ptr_buffer, size_t* ptr_buffer_len, int type, struct renderinfo* ptr_rendinfo, int n_istemp, unsigned long long refcount) {
  int n_have_author = 0;
  unsigned long long frequency;
  char* new_buffer;
  char* entitize_buf;
  struct AUTHOR_INFO ainfo;
  dbi_conn conn;
  dbi_result dbires;

  conn = dbi_result_get_conn(ptr_rendinfo->dbires);

  /* request authors */
  dbires = request_authors(conn, type , NULL /* all roles */, NULL, 0, my_dbi_result_get_idval(ptr_rendinfo->dbires, "refdb_id"));
  if (dbires == NULL) {
    LOG_PRINT(LOG_WARNING, get_status_msg(234));
    return 234;
  }

  if (dbi_result_get_numrows(dbires)) {
    if ((new_buffer = mstrcat(*ptr_buffer, "<p class='authors'>", ptr_buffer_len, 0)) == NULL) {
      clean_request(dbires);
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *ptr_buffer = new_buffer;
    }
  }

  /* fetch all authors */
  while (get_extended_author_parts(dbires, &ainfo, n_istemp, &frequency) != NULL) {
    n_have_author = 1;
    int rel_frequency;
    char buffer[64];

    rel_frequency = calculate_relative_frequency(frequency, refcount);

    sprintf(buffer, "<span class='%s relfreq%d'>", (*(ainfo.role)) ? ainfo.role:"author", rel_frequency);

    if ((entitize_buf = strdup(ainfo.name)) == NULL
	|| sgml_entitize(&entitize_buf, ptr_rendinfo->ref_format) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
      
    if ((new_buffer = mstrcat(*ptr_buffer, buffer, ptr_buffer_len, 0)) == NULL) {
      clean_request(dbires);
      free(entitize_buf);
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *ptr_buffer = new_buffer;
    }

    if ((new_buffer = mstrcat(*ptr_buffer, entitize_buf, ptr_buffer_len, 0)) == NULL) {
      clean_request(dbires);
      free(entitize_buf);
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *ptr_buffer = new_buffer;
    }

    free(entitize_buf);

    if ((new_buffer = mstrcat(*ptr_buffer, "</span>; ", ptr_buffer_len, 0)) == NULL) {
      clean_request(dbires);
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *ptr_buffer = new_buffer;
    }
  }
  clean_request(dbires);

  if (n_have_author) { /* eliminate the trailing comma after the last author */
    new_buffer = mstrcat(*ptr_buffer, "</p>\n", ptr_buffer_len, 2);
    if (new_buffer == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return 801;
    }
    else {
      *ptr_buffer = new_buffer;
    }
  }

  return 0;
}

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  print_field_html(): writes simple field contents to HTML output

  char* print_field_html returns a ptr to the modified string. Due to
                         reallocation this may be different from the
			 ptr passed to this function in the ptr_rendinfo
			 structure which is also updated accordingly

  const char* item ptr to the contents of the field to write

  struct renderinfo* ptr_rendinfo ptr to a structure with the info
                             how the reference should be rendered

  const char* start_string ptr to a string to be printed before the 
                         field contents

 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
static char* print_field_html(const char* item, struct renderinfo* ptr_rendinfo, const char* start_string) {
  char* new_ref;

  if (item != NULL) {
    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), (char*)start_string, ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return NULL;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }
    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), (char*)item, ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return NULL;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
    }
    if ((new_ref = mstrcat(*(ptr_rendinfo->ptr_ref), "</p>\n", ptr_rendinfo->ptr_ref_len, 0)) == NULL) {
      LOG_PRINT(LOG_CRIT, get_status_msg(801));
      return NULL;
    }
    else {
      *(ptr_rendinfo->ptr_ref) = new_ref;
      }
  }
  return *(ptr_rendinfo->ptr_ref);
}
