Adopt use of gnulib for portability.
[pspp-builds.git] / src / html.c
index 42d818b519f908004e0eb876cdfc089ffd53a67b..f902520d0e1a2580530e7ba633211d9c7db8e2ed 100644 (file)
 
    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. */
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA. */
 
 /* This #if encloses the rest of the file. */
 #if !NO_HTML
 
 #include <config.h>
-#include <assert.h>
+#include "htmlP.h"
+#include "error.h"
 #include <errno.h>
 #include <stdlib.h>
 #include <ctype.h>
 #include "alloc.h"
 #include "error.h"
 #include "filename.h"
+#include "getl.h"
 #include "getline.h"
-#include "htmlP.h"
+#include "getlogin_r.h"
 #include "output.h"
 #include "som.h"
 #include "tab.h"
 #include "version.h"
+#include "mkfile.h"
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
 
 /* Prototypes. */
 static int postopen (struct file_ext *);
 static int preclose (struct file_ext *);
 
-int
-html_open_global (struct outp_class *this unused)
+static int
+html_open_global (struct outp_class *this UNUSED)
 {
   return 1;
 }
 
-int
-html_close_global (struct outp_class *this unused)
+static int
+html_close_global (struct outp_class *this UNUSED)
 {
   return 1;
 }
 
-int
+static int
 html_preopen_driver (struct outp_driver *this)
 {
   struct html_driver_ext *x;
@@ -87,7 +93,7 @@ html_preopen_driver (struct outp_driver *this)
   return 1;
 }
 
-int
+static int
 html_postopen_driver (struct outp_driver *this)
 {
   struct html_driver_ext *x = this->ext;
@@ -105,7 +111,7 @@ html_postopen_driver (struct outp_driver *this)
   return 1;
 }
 
-int
+static int
 html_close_driver (struct outp_driver *this)
 {
   struct html_driver_ext *x = this->ext;
@@ -122,6 +128,22 @@ html_close_driver (struct outp_driver *this)
   return 1;
 }
 
+
+/* Link the image contained in FILENAME to the 
+   HTML stream in file F. */
+static int
+link_image (struct file_ext *f, char *filename)
+{
+  fprintf (f->file,
+          "<IMG SRC=\"%s\"/>", filename);
+
+  if (ferror (f->file))
+    return 0;
+
+  return 1;
+}
+
+
 /* Generic option types. */
 enum
 {
@@ -141,7 +163,7 @@ static struct outp_option option_tab[] =
 };
 static struct outp_option_info option_info;
 
-void
+static void
 html_option (struct outp_driver *this, const char *key, const struct string *val)
 {
   struct html_driver_ext *x = this->ext;
@@ -156,7 +178,7 @@ html_option (struct outp_driver *this, const char *key, const struct string *val
       break;
     case 1:
       free (x->file.filename);
-      x->file.filename = xstrdup (ds_value (val));
+      x->file.filename = xstrdup (ds_c_str (val));
       break;
     case string_arg:
       {
@@ -168,10 +190,11 @@ html_option (struct outp_driver *this, const char *key, const struct string *val
            break;
          default:
            assert (0);
+            abort ();
          }
        if (*dest)
          free (*dest);
-       *dest = xstrdup (ds_value (val));
+       *dest = xstrdup (ds_c_str (val));
       }
       break;
     default:
@@ -216,9 +239,7 @@ postopen (struct file_ext *f)
       {"source-file", 0},
       {0, 0},
     };
-#if HAVE_UNISTD_H
-  char host[128];
-#endif
+  char login[128], host[128];
   time_t curtime;
   struct tm *loctime;
 
@@ -259,14 +280,13 @@ postopen (struct file_ext *f)
       *cp = 0;
   }
 
-  /* PORTME: Determine username, net address. */
-#if HAVE_UNISTD_H
-  dict[2].value = getenv ("LOGNAME");
-  if (!dict[2].value)
-    dict[2].value = getlogin ();
-  if (!dict[2].value)
-    dict[2].value = _("nobody");
+  if (getenv ("LOGNAME") != NULL)
+    str_copy_rpad (login, sizeof login, getenv ("LOGNAME"));
+  else if (getlogin_r (login, sizeof login))
+    strcpy (login, _("nobody"));
+  dict[2].value = login;
 
+#ifdef HAVE_UNISTD_H
   if (gethostname (host, 128) == -1)
     {
       if (errno == ENAMETOOLONG)
@@ -274,11 +294,10 @@ postopen (struct file_ext *f)
       else
        strcpy (host, _("nowhere"));
     }
+#else
+  strcpy (host, _("nowhere"));
+#endif
   dict[3].value = host;
-#else /* !HAVE_UNISTD_H */
-  dict[2].value = _("nobody");
-  dict[3].value = _("nowhere");
-#endif /* !HAVE_UNISTD_H */
 
   dict[4].value = outp_title ? outp_title : "";
   dict[5].value = outp_subtitle ? outp_subtitle : "";
@@ -358,7 +377,7 @@ preclose (struct file_ext *f)
   return 1;
 }
 
-int
+static int
 html_open_page (struct outp_driver *this)
 {
   struct html_driver_ext *x = this->ext;
@@ -378,7 +397,7 @@ html_open_page (struct outp_driver *this)
   return !ferror (x->file.file);
 }
 
-int
+static int
 html_close_page (struct outp_driver *this)
 {
   struct html_driver_ext *x = this->ext;
@@ -390,8 +409,8 @@ html_close_page (struct outp_driver *this)
 
 static void output_tab_table (struct outp_driver *, struct tab_table *);
 
-void
-html_submit (struct outp_driver *this, struct som_table *s)
+static void
+html_submit (struct outp_driver *this, struct som_entity *s)
 {
   extern struct som_table_class tab_table_class;
   struct html_driver_ext *x = this->ext;
@@ -403,30 +422,21 @@ html_submit (struct outp_driver *this, struct som_table *s)
       return;
     }
 
-  if (s->class == &tab_table_class)
-    output_tab_table (this, (struct tab_table *) s->ext);
-  else
-    assert (0);
-}
+  assert ( s->class == &tab_table_class ) ;
+
+  switch (s->type) 
+    {
+    case SOM_TABLE:
+      output_tab_table ( this, (struct tab_table *) s->ext);
+      break;
+    case SOM_CHART:
+      link_image( &x->file, ((struct chart *)s->ext)->filename);
+      break;
+    default:
+      assert(0);
+      break;
+    }
 
-/* Emit HTML to FILE to change from *OLD_ATTR attributes to NEW_ATTR.
-   Sets *OLD_ATTR to NEW_ATTR when done. */
-static void
-change_attributes (FILE *f, int *old_attr, int new_attr)
-{
-  if (*old_attr == new_attr)
-    return;
-
-  if (*old_attr & OUTP_F_B)
-    fputs ("</B>", f);
-  if (*old_attr & OUTP_F_I)
-    fputs ("</I>", f);
-  if (new_attr & OUTP_F_I)
-    fputs ("<I>", f);
-  if (new_attr & OUTP_F_B)
-    fputs ("<B>", f);
-
-  *old_attr = new_attr;
 }
 
 /* Write string S of length LEN to file F, escaping characters as
@@ -436,7 +446,6 @@ escape_string (FILE *f, char *s, int len)
 {
   char *ep = &s[len];
   char *bp, *cp;
-  int attr = 0;
 
   for (bp = cp = s; bp < ep; bp = cp)
     {
@@ -462,9 +471,6 @@ escape_string (FILE *f, char *s, int len)
            assert (0);
          }
     }
-
-  if (attr)
-    change_attributes (f, &attr, 0);
 }
   
 /* Write table T to THIS output driver. */
@@ -473,13 +479,11 @@ output_tab_table (struct outp_driver *this, struct tab_table *t)
 {
   struct html_driver_ext *x = this->ext;
   
-  tab_hit++;
-
   if (t->nr == 1 && t->nc == 1)
     {
       fputs ("<P>", x->file.file);
       if (!ls_empty_p (t->cc))
-       escape_string (x->file.file, ls_value (t->cc), ls_length (t->cc));
+       escape_string (x->file.file, ls_c_str (t->cc), ls_length (t->cc));
       fputs ("</P>\n", x->file.file);
       
       return;
@@ -490,14 +494,13 @@ output_tab_table (struct outp_driver *this, struct tab_table *t)
   if (!ls_empty_p (&t->title))
     {
       fprintf (x->file.file, "  <TR>\n    <TH COLSPAN=%d>", t->nc);
-      escape_string (x->file.file, ls_value (&t->title),
+      escape_string (x->file.file, ls_c_str (&t->title),
                     ls_length (&t->title));
       fputs ("</TH>\n  </TR>\n", x->file.file);
     }
   
   {
     int r;
-    struct len_string *cc = t->cc;
     unsigned char *ct = t->ct;
 
     for (r = 0; r < t->nr; r++)
@@ -505,15 +508,22 @@ output_tab_table (struct outp_driver *this, struct tab_table *t)
        int c;
        
        fputs ("  <TR>\n", x->file.file);
-       for (c = 0; c < t->nc; c++, cc++, ct++)
+       for (c = 0; c < t->nc; c++, ct++)
          {
+            struct fixed_string *cc;
            int tag;
            char header[128];
            char *cp;
+            struct tab_joined_cell *j = NULL;
 
-           if ((*ct & TAB_JOIN)
-               && ((struct tab_joined_cell *) ls_value (cc))->hit == tab_hit)
-             continue;
+            cc = t->cc + c + r * t->nc;
+           if (*ct & TAB_JOIN) 
+              {
+                j = (struct tab_joined_cell *) ls_c_str (cc);
+                cc = &j->contents;
+                if (j->x1 != c || j->y1 != r)
+                  continue; 
+              }
 
            if (r < t->t || r >= t->nr - t->b
                || c < t->l || c >= t->nc - t->r)
@@ -539,14 +549,12 @@ output_tab_table (struct outp_driver *this, struct tab_table *t)
 
            if (*ct & TAB_JOIN)
              {
-               struct tab_joined_cell *j =
-                 (struct tab_joined_cell *) ls_value (cc);
-               j->hit = tab_hit;
-               
                if (j->x2 - j->x1 > 1)
                  cp = spprintf (cp, " COLSPAN=%d", j->x2 - j->x1);
                if (j->y2 - j->y1 > 1)
                  cp = spprintf (cp, " ROWSPAN=%d", j->y2 - j->y1);
+
+                cc = &j->contents;
              }
            
            strcpy (cp, ">");
@@ -554,7 +562,7 @@ output_tab_table (struct outp_driver *this, struct tab_table *t)
            
            if ( ! (*ct & TAB_EMPTY)  ) 
              {
-               char *s = ls_value (cc);
+               char *s = ls_c_str (cc);
                size_t l = ls_length (cc);
 
                while (l && isspace ((unsigned char) *s))
@@ -575,6 +583,31 @@ output_tab_table (struct outp_driver *this, struct tab_table *t)
   fputs ("</TABLE>\n\n", x->file.file);
 }
 
+static void
+html_initialise_chart(struct outp_driver *d UNUSED, struct chart *ch)
+{
+
+  FILE  *fp;
+
+  make_unique_file_stream(&fp, &ch->filename);
+
+#ifdef NO_CHARTS
+  ch->lp = 0;
+#else
+  ch->pl_params = pl_newplparams();
+  ch->lp = pl_newpl_r ("png", 0, fp, stderr, ch->pl_params);
+#endif
+
+}
+
+static void 
+html_finalise_chart(struct outp_driver *d UNUSED, struct chart *ch)
+{
+  free(ch->filename);
+}
+
+
+
 /* HTML driver class. */
 struct outp_class html_class =
 {
@@ -614,6 +647,10 @@ struct outp_class html_class =
   NULL,
   NULL,
   NULL,
+
+  html_initialise_chart,
+  html_finalise_chart
+
 };
 
 #endif /* !NO_HTML */