Initial commit of pristine erwise source
authorToni Nikkanen <toni@tuug.fi>
Sat, 7 Mar 2009 16:16:01 +0000 (18:16 +0200)
committerToni Nikkanen <toni@tuug.fi>
Sat, 7 Mar 2009 16:16:01 +0000 (18:16 +0200)
112 files changed:
Cl/Cl.c [new file with mode: 0644]
Cl/Cl.h [new file with mode: 0644]
Cl/ClConnection.c [new file with mode: 0644]
Cl/ClFTP.c [new file with mode: 0644]
Cl/ClHTTP.c [new file with mode: 0644]
Cl/ClMisc.c [new file with mode: 0644]
Cl/Imakefile [new file with mode: 0644]
Cl/Makefile [new file with mode: 0644]
Cl/WWWLibrary/HTAccess.c [new file with mode: 0644]
Cl/WWWLibrary/HTAccess.h [new file with mode: 0644]
Cl/WWWLibrary/HTAnchor.c [new file with mode: 0644]
Cl/WWWLibrary/HTAnchor.h [new file with mode: 0644]
Cl/WWWLibrary/HTAtom.c [new file with mode: 0644]
Cl/WWWLibrary/HTAtom.h [new file with mode: 0644]
Cl/WWWLibrary/HTBrowse.h [new file with mode: 0644]
Cl/WWWLibrary/HTChunk.c [new file with mode: 0644]
Cl/WWWLibrary/HTChunk.h [new file with mode: 0644]
Cl/WWWLibrary/HTFTP.c [new file with mode: 0644]
Cl/WWWLibrary/HTFTP.h [new file with mode: 0644]
Cl/WWWLibrary/HTFile.c [new file with mode: 0644]
Cl/WWWLibrary/HTFile.h [new file with mode: 0644]
Cl/WWWLibrary/HTFont.h [new file with mode: 0644]
Cl/WWWLibrary/HTFormat.c [new file with mode: 0644]
Cl/WWWLibrary/HTFormat.h [new file with mode: 0644]
Cl/WWWLibrary/HTGopher.c [new file with mode: 0644]
Cl/WWWLibrary/HTGopher.h [new file with mode: 0644]
Cl/WWWLibrary/HTHistory.c [new file with mode: 0644]
Cl/WWWLibrary/HTHistory.h [new file with mode: 0644]
Cl/WWWLibrary/HTList.c [new file with mode: 0644]
Cl/WWWLibrary/HTList.h [new file with mode: 0644]
Cl/WWWLibrary/HTML.c [new file with mode: 0644]
Cl/WWWLibrary/HTML.h [new file with mode: 0644]
Cl/WWWLibrary/HTNews.c [new file with mode: 0644]
Cl/WWWLibrary/HTNews.h [new file with mode: 0644]
Cl/WWWLibrary/HTParse.c [new file with mode: 0644]
Cl/WWWLibrary/HTParse.h [new file with mode: 0644]
Cl/WWWLibrary/HTString.c [new file with mode: 0644]
Cl/WWWLibrary/HTString.h [new file with mode: 0644]
Cl/WWWLibrary/HTStyle.c [new file with mode: 0644]
Cl/WWWLibrary/HTStyle.h [new file with mode: 0644]
Cl/WWWLibrary/HTTCP.c [new file with mode: 0644]
Cl/WWWLibrary/HTTCP.h [new file with mode: 0644]
Cl/WWWLibrary/HTTP.c [new file with mode: 0644]
Cl/WWWLibrary/HTTP.h [new file with mode: 0644]
Cl/WWWLibrary/HTUtils.h [new file with mode: 0644]
Cl/WWWLibrary/HText.h [new file with mode: 0644]
Cl/WWWLibrary/Imakefile [new file with mode: 0644]
Cl/WWWLibrary/Makefile [new file with mode: 0644]
Cl/WWWLibrary/Makefile.bak [new file with mode: 0644]
Cl/WWWLibrary/README [new file with mode: 0644]
Cl/WWWLibrary/SGML.c [new file with mode: 0644]
Cl/WWWLibrary/SGML.h [new file with mode: 0644]
Cl/WWWLibrary/WWW.h [new file with mode: 0644]
Cl/WWWLibrary/tcp.h [new file with mode: 0644]
HText/DefaultStyles.c [new file with mode: 0644]
HText/HText.c [new file with mode: 0644]
HText/HText.h [new file with mode: 0644]
HText/Imakefile [new file with mode: 0644]
HText/Makefile [new file with mode: 0644]
HText/dummy.c [new file with mode: 0644]
Imakefile [new file with mode: 0644]
Makefile [new file with mode: 0644]
Ui/Imakefile [new file with mode: 0644]
Ui/Makefile [new file with mode: 0644]
Ui/RCS/.uidemo.c,v [new file with mode: 0644]
Ui/Ui.h [new file with mode: 0644]
Ui/UiConnections.c [new file with mode: 0644]
Ui/UiControlPanel.c [new file with mode: 0644]
Ui/UiDefaults.c [new file with mode: 0644]
Ui/UiDefs.h [new file with mode: 0644]
Ui/UiFileSelection.c [new file with mode: 0644]
Ui/UiIncludes.h [new file with mode: 0644]
Ui/UiInfo.c [new file with mode: 0644]
Ui/UiInit.c [new file with mode: 0644]
Ui/UiList.c [new file with mode: 0644]
Ui/UiMisc.c [new file with mode: 0644]
Ui/UiPage.c [new file with mode: 0644]
Ui/UiPageSettings.c [new file with mode: 0644]
Ui/UiPrint.c [new file with mode: 0644]
Ui/UiProtos.h [new file with mode: 0644]
Ui/UiRecall.c [new file with mode: 0644]
Ui/UiSearch.c [new file with mode: 0644]
Ui/UiSelectionBox.c [new file with mode: 0644]
Ui/UiTypes.h [new file with mode: 0644]
Ui/UiUtil.c [new file with mode: 0644]
Xl/Imakefile [new file with mode: 0644]
Xl/Makefile [new file with mode: 0644]
Xl/Xl.h [new file with mode: 0644]
Xl/XlConfig.h [new file with mode: 0644]
Xl/XlDefaultFonts.h [new file with mode: 0644]
Xl/XlFormatText.c [new file with mode: 0644]
Xl/XlFormatText.h [new file with mode: 0644]
Xl/XlSetup.c [new file with mode: 0644]
Xl/XlStyle.c [new file with mode: 0644]
Xl/XlStyle.h [new file with mode: 0644]
Xl/XlTypes.h [new file with mode: 0644]
Xl/XlUtil.c [new file with mode: 0644]
Xl/XlWindow.c [new file with mode: 0644]
erwise/Config.c [new file with mode: 0644]
erwise/Defs.h [new file with mode: 0644]
erwise/Help.c [new file with mode: 0644]
erwise/Imakefile [new file with mode: 0644]
erwise/Includes.h [new file with mode: 0644]
erwise/Makefile [new file with mode: 0644]
erwise/Misc.c [new file with mode: 0644]
erwise/Page.c [new file with mode: 0644]
erwise/Print.c [new file with mode: 0644]
erwise/Protos.h [new file with mode: 0644]
erwise/Setup.c [new file with mode: 0644]
erwise/TopLevel.c [new file with mode: 0644]
erwise/Types.h [new file with mode: 0644]
erwise/main.c [new file with mode: 0644]

diff --git a/Cl/Cl.c b/Cl/Cl.c
new file mode 100644 (file)
index 0000000..77b80ce
--- /dev/null
+++ b/Cl/Cl.c
@@ -0,0 +1,413 @@
+/*
+ * Cl.c --
+ *
+ * Author: Teemu Rantanen <tvr@cs.hut.fi>
+ * Copyright (c) 1992 Teemu Rantanen
+ *                    All rights reserved
+ *
+ * Created: Thu Apr 16 22:08:27 1992 tvr
+ * Last modified: Wed May 13 13:27:58 1992 tvr
+ *
+ */
+
+#include <stdio.h>
+
+#include "Cl.h"
+
+#include "HTStyle.h"
+#include "HTParse.h"
+#include "HText.h"
+#include "tcp.h"
+
+#include "../HText/HText.h"
+
+extern HText_t *HtLocalText;
+
+int WWWErwiseStatus;
+ClConnection_t *WWWErwiseConnection;
+
+void cl_free_connection ();
+
+/*
+ * Where to load this file ?
+ */
+
+char *WWWErwiseFileLoadName = 0;
+
+/*
+ * Open connection. Allocate strutures.
+ */
+
+ClConnection_t *
+ClOpenConnection (address)
+     char *address;
+{
+  int status;
+  ClConnection_t *p = (ClConnection_t *) malloc (sizeof (*p));
+
+  /*
+   * Some validation checks
+   */
+
+  if (!p)
+    return p;
+
+  if (!address)
+    return NULL;
+
+  memset (p, 0, sizeof (*p));
+
+  p->address = (char *) strdup (address);
+
+  /*
+   * If we wish to load to file, open fd here
+   */
+
+  if (WWWErwiseFileLoadName)
+    {
+
+      p->load_to_file_fd =
+       open (WWWErwiseFileLoadName, O_WRONLY | O_CREAT, 0666);
+
+      free (WWWErwiseFileLoadName);
+
+      WWWErwiseFileLoadName = 0;
+
+      if (p->load_to_file_fd < 0)
+       {
+
+         printf ("ClOpenConnection: Cannot load to file '%s'\n",
+                 WWWErwiseFileLoadName);
+
+         ClCloseConnection (p);
+
+         return 0;
+       }
+
+      p->load_to_file = 1;
+    }
+
+
+  /*
+   * Kludge #1:
+   * Call common code to get socket fd. Also set state to some value so
+   * that ReadData calls some function that makes sense.
+   */
+
+  WWWErwiseConnection = p;
+
+  WWWErwiseStatus = CL_CONTINUES;
+
+  p->status = HTLoadAbsolute (address, 0);
+
+  if ((WWWErwiseStatus == CL_FAILED) ||
+      (WWWErwiseStatus == CL_ALREADY_LOADED))
+    {
+
+      ClCloseConnection (p);
+
+      return NULL;
+    }
+
+  return p;
+}
+
+
+/*
+ * Read data or poll connection opening
+ */
+struct HText *
+ClReadData (connection, how_done, fd)
+     ClConnection_t *connection;
+     int *how_done;
+     int *fd;
+{
+  int continues;
+
+  void (*tmpf) ();
+
+  WWWErwiseStatus = CL_CONTINUES;
+
+  WWWErwiseConnection = connection;
+
+  /*
+   * If loading was on non-blocking mode ?
+   */
+  if (!connection->function)
+    {
+
+      *fd = connection->fd;
+
+      if (connection->status)
+       {
+
+         *how_done = CL_COMPLETED;
+
+         ClCloseConnection (connection);
+
+         return HtLocalText;
+
+       }
+      else
+       {
+
+         *how_done = CL_FAILED;
+
+         ClCloseConnection (connection);
+
+         return 0;
+
+       }
+    }
+
+  /*
+   * Try max 3 pollings at one call. This makes loading faster but does not
+   * get too much cpu
+   */
+  for (continues = 3; continues > 0; continues--)
+    {
+
+      tmpf = *connection->function;
+
+      if (*connection->function)
+       (void) (*connection->function) ();
+
+      /*
+       * If mode is going to change to poll, set it now
+       */
+      if (*connection->function == WWWErwiseSetPoll)
+       (void) WWWErwiseSetPoll ();
+
+      /*
+       * Can we try next polling?
+       */
+      if ((*connection->function == tmpf) || (*how_done != CL_CONTINUES) ||
+         (connection->select_fd))
+       {
+
+         continues = 0;
+       }
+    }
+
+  *how_done = WWWErwiseStatus;
+
+  *fd = connection->select_fd;
+
+  if (*how_done == CL_FAILED)
+    {
+
+      ClCloseConnection (connection);
+
+      return NULL;
+    }
+
+  if (*how_done == CL_COMPLETED)
+    {
+
+      ClCloseConnection (connection);
+
+      return HtLocalText;      /* global variable because @#$#$ <censored> */
+    }
+
+  return NULL;
+}
+
+
+/*
+ * User wants to terminate a connection
+ */
+
+void
+ClCloseConnection (connection)
+     ClConnection_t *connection;
+{
+  if (connection->load_to_file)
+    {
+
+      close (connection->load_to_file_fd);
+    }
+
+  if (connection->fd)
+    {
+
+      shutdown (connection->fd, 2);
+
+      close (connection->fd);
+    }
+
+  if (connection->secondary_fd)
+    {
+
+      shutdown (connection->secondary_fd, 2);
+
+      close (connection->secondary_fd);
+    }
+
+  cl_free_connection (connection);
+}
+
+
+
+/*
+ * read data from local buffer. If no data on buffer, make normal read
+ */
+int
+cl_read_data (fd, data, length)
+     int fd;
+     char *data;
+     int length;
+{
+  ClConnection_t *p = WWWErwiseConnection;
+
+  cl_data_t *b = p->buffer_first;
+
+  int howmuch = 0;
+
+  if (p->buffer_last)
+    {
+      if (!b)
+       return 0;
+
+      if (length < b->size)
+       {
+
+         memcpy (data, b->data, length);
+
+         howmuch = length;
+
+         b->size -= length;
+
+         b->data += length;
+       }
+      else
+       {
+
+         memcpy (data, b->data, b->size);
+
+         howmuch = b->size;
+
+         free (b->freeptr);
+
+         if (b->next)
+           {
+             b->next->prev = 0;
+             p->buffer_first = b->next;
+           }
+         else
+           {
+             p->buffer_first = 0;
+           }
+         free (b);
+       }
+    }
+  else
+    {
+      return NETREAD (fd, data, length);
+    }
+  return howmuch;
+}
+
+
+
+/*
+ * Free everything connection structure has malloced (and not yet freed)
+ */
+
+void
+cl_free_connection (connection)
+     ClConnection_t *connection;
+{
+  if (connection->address)
+    free (connection->address);
+
+  if (connection->addr)
+    free (connection->addr);
+
+  if (connection->command)
+    free (connection->command);
+
+  if (connection->buffer_first)
+    {
+      cl_data_t *p = connection->buffer_first;
+
+      while (p)
+       {
+
+         cl_data_t *p2 = p;
+
+         free (p->freeptr);
+
+         free (p);
+
+         p = p2->next;
+       }
+    }
+
+  /*
+   * NOTE!
+   * anAnchor or diag should not be freed (at least they are not on
+   * original common code.
+   */
+}
+
+
+/*
+ * Return true if loading to file is supported with this address
+ */
+int
+ClCanLoadToFile (address)
+     char *address;
+{
+  char *access;
+
+  if (!address)
+    {
+      return 0;
+    }
+
+  access = HTParse (address, "", PARSE_ACCESS);
+
+  if (!strcmp (access, "html"))
+    {
+
+      free (access);
+
+      return 1;
+    }
+
+  if (!strcmp (access, "file"))
+    {
+
+      free (access);
+
+      return 1;
+    }
+
+  free (access);
+
+  return 0;
+}
+
+
+/*
+ * Are we loading this connection to file ?
+ */
+int
+ClConnectionOnLoadToFileMode (connection)
+     ClConnection_t *connection;
+{
+  if (!connection)
+    return 0;
+
+  return connection->load_to_file;
+}
+
+
+void
+ClSetFileNameForLoadingToFile (char *filename)
+{
+  if (filename)
+    WWWErwiseFileLoadName = (char *) strdup (filename);
+  else
+    WWWErwiseFileLoadName = NULL;
+}
diff --git a/Cl/Cl.h b/Cl/Cl.h
new file mode 100644 (file)
index 0000000..f502d13
--- /dev/null
+++ b/Cl/Cl.h
@@ -0,0 +1,180 @@
+/*
+ * Cl.h --
+ *
+ * Author: Teemu Rantanen <tvr@cs.hut.fi>
+ * Copyright (c) 1992 Teemu Rantanen
+ *                    All rights reserved
+ *
+ * Created: Thu Apr 16 21:40:39 1992 tvr
+ * Last modified: Wed May 13 00:11:13 1992 tvr
+ *
+ */
+
+#include "HTAnchor.h"
+#include "HTStyle.h"
+#include "HText.h"
+
+/*
+ * Data is store on linked list
+ */
+typedef struct cl_data_s
+{
+  struct cl_data_s *next;
+  struct cl_data_s *prev;
+  void *data;
+  void *freeptr;
+  int size;
+}         cl_data_t;
+
+
+/*
+ * This structure contains all information needed to accomplish this
+ * connection.
+ */
+typedef struct ClConnection_s
+{
+  /*
+   * address of this connection
+   */
+  char *address;
+
+  /*
+   * Fd of the connection. Also ftp connection data channel.
+   */
+  int fd;
+  int secondary_fd;
+
+  /*
+   * If this fd is not set connection has to be polled. If it is NOT
+   * set, connection has to be selected (must not poll!)
+   */
+  int select_fd;
+
+  /*
+   * Function of this state machine
+   */
+  void (**function) ();
+
+  /*
+   * Store junk here (address of data on connect() )
+   */
+  void *addr;
+  int addr_size;
+
+  /*
+   * Store command to write to the net here
+   */
+  char *command;
+
+  /*
+   * Data Buffer
+   */
+  cl_data_t *buffer_first;
+  cl_data_t *buffer_last;
+
+  /*
+   * stuff given to HTLoadHTTP()
+   */
+  int diag;
+  struct HTAnchor *anAnchor;
+
+  /*
+   * How happened with load if on nonblocking mode
+   */
+  int status;
+
+  /*
+   * Hostname on ftp connections
+   */
+  char *ftphost;
+
+  /*
+   * Data port on ftp connections
+   */
+  int port;
+
+
+  /*
+   * Load to file ?
+   */
+  int load_to_file;
+  int load_to_file_fd;
+
+}              ClConnection_t;
+
+
+/*
+ * More data is to be read
+ */
+#define CL_CONTINUES           0
+
+/*
+ * Connection completed
+ */
+#define CL_COMPLETED           1
+
+/*
+ * Connection failed
+ */
+#define CL_FAILED              2
+
+/*
+ * Document already loaded (error)
+ */
+#define CL_ALREADY_LOADED      3
+
+
+/*
+ * Prototypes
+ */
+ClConnection_t *ClOpenConnection (char *address);
+
+struct HText *ClReadData (ClConnection_t * connection, int *how_done, int *fd);
+
+void ClSetOptions (ClConnection_t * connection, int argc, char *argv[]);
+
+void ClCloseConnection (ClConnection_t * connection);
+
+int ClCanLoadToFile (char *address);
+
+void ClSetFileNameForLoadingToFile (char *filename);
+
+int ClConnectionOnLoadToFileMode (ClConnection_t * connection);
+
+/*
+ * Globals
+ */
+
+extern int WWWErwiseStatus;
+extern ClConnection_t *WWWErwiseConnection;
+
+void WWWErwiseConnect ();
+void WWWErwiseSendCommand ();
+void WWWErwiseReadData ();
+void WWWErwiseParse ();
+
+
+/*
+ * Internals
+ */
+
+void WWWErwiseFtpUser ();
+void WWWErwiseFtpPass ();
+void WWWErwiseFtpPassive ();
+void WWWErwiseFtpGetPassive ();
+void WWWErwiseFtpGetCommand ();
+void WWWErwiseFtpDataChannel ();
+void WWWErwiseFtpCheckForError ();
+void WWWErwiseFtpBinary ();
+void WWWErwiseCheckParse ();
+void WWWErwiseSetPoll ();
+void WWWErwiseSetSelect ();
+void WWWErwiseTerminateIfLoadToFile ();
+
+int cl_start_connection ();
+
+/*
+ * Debug ...
+ */
+
+#define CL_DEBUG(a)    printf a
diff --git a/Cl/ClConnection.c b/Cl/ClConnection.c
new file mode 100644 (file)
index 0000000..12e2688
--- /dev/null
@@ -0,0 +1,324 @@
+/*
+ * ClConnection.c --
+ *
+ * Author: Teemu Rantanen <tvr@cs.hut.fi>
+ * Copyright (c) 1992 Teemu Rantanen
+ *                    All rights reserved
+ *
+ * Created: Mon Apr 20 19:29:14 1992 tvr
+ * Last modified: Wed May 13 00:53:24 1992 tvr
+ *
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <errno.h>
+
+#include "Cl.h"
+
+#include "HTParse.h"
+#include "HTFormat.h"
+#include "HTAnchor.h"
+#include "tcp.h"
+
+#include "../HText/HText.h"
+
+extern HText_t *HtLocalText;
+
+
+/*
+ * Poll connecting until connection completes.
+ */
+void
+WWWErwiseConnect ()
+{
+  int status;
+
+  CL_DEBUG (("Poll connect\n"));
+
+  status = connect (WWWErwiseConnection->fd,
+                   (struct sockaddr *) WWWErwiseConnection->addr,
+                   WWWErwiseConnection->addr_size);
+  if (status < 0 && (errno != EISCONN))
+    {
+      if ((errno == EALREADY) || (errno == EINPROGRESS))
+       {
+         /*
+           * Would block
+           */
+         return;
+       }
+
+      CL_DEBUG (("Cannot connect(%d)\n", errno));
+
+      /*
+       * Cannot connect
+       */
+      WWWErwiseStatus = CL_FAILED;
+
+      return;
+    }
+
+  /*
+   * Connected. Get next function from the list of things to do.
+   * Also, stop polling.
+   */
+
+  free (WWWErwiseConnection->addr);
+
+  WWWErwiseConnection->addr = NULL;
+
+  WWWErwiseConnection->function++;
+}
+
+
+
+/*
+ * Instead of connect, this function is called. Store needed data to
+ * poll connecting later.
+ */
+int
+erwise_connect (fd, addr, size)
+     int fd;
+     struct sockaddr *addr;
+     int size;
+{
+  int status;
+
+  CL_DEBUG (("Try to Connect\n"));
+
+  status = connect (fd, addr, size);
+
+  if (status < 0)
+    {
+      switch (errno)
+       {
+       case EINPROGRESS:
+       case EISCONN:
+       case EALREADY:
+         break;
+
+       default:
+         CL_DEBUG (("Cannot connect (first try %d)\n", errno));
+         return -1;
+       }
+    }
+
+  /*
+   * Duplicate what to connect
+   */
+  WWWErwiseConnection->addr = (void *) malloc (size);
+
+  memcpy (WWWErwiseConnection->addr, addr, size);
+
+  WWWErwiseConnection->addr_size = size;
+
+  /*
+   * OK
+   */
+  return 0;
+}
+
+
+
+
+
+/*
+ * Send command to net
+ */
+
+void
+WWWErwiseSendCommand ()
+{
+  int status;
+
+  CL_DEBUG (("Send Command\n"));
+
+  status = NETWRITE (WWWErwiseConnection->fd,
+                    WWWErwiseConnection->command,
+                    (int) strlen (WWWErwiseConnection->command));
+
+  if (status == strlen (WWWErwiseConnection->command))
+    {
+      /*
+       * Succeeded
+       */
+      free (WWWErwiseConnection->command);
+      WWWErwiseConnection->command = 0;
+
+      WWWErwiseConnection->function++;
+
+    }
+  else if (status < 0)
+    {
+      /*
+       * Failed
+       */
+      CL_DEBUG (("SendCommand failed\n"));
+
+      WWWErwiseStatus = CL_FAILED;
+      return;
+    }
+  else
+    {
+      /*
+       * Partial read
+       */
+      char *tmp = WWWErwiseConnection->command;
+
+      WWWErwiseConnection->command = (char *) strdup (tmp + status);
+      free (tmp);
+    }
+}
+
+
+#define ERWISE_BLOCK 8192
+
+/*
+ * Read data until all data is read
+ */
+
+void
+WWWErwiseReadData ()
+{
+  char tmp[ERWISE_BLOCK];
+
+  int i;
+
+  i = read (WWWErwiseConnection->fd,
+           tmp,
+           ERWISE_BLOCK);
+
+  CL_DEBUG (("got %d bytes\n", i));
+
+  /*
+   * Append data to (memory) buffer or to file.
+   */
+  if (i > 0)
+    {
+
+      /*
+       * Load directly to file ?
+       */
+
+      if (WWWErwiseConnection->load_to_file)
+       {
+         int st;
+
+         st = write (WWWErwiseConnection->load_to_file_fd,
+                     tmp,
+                     i);
+
+         if (st != i)
+           {
+             WWWErwiseStatus = CL_FAILED;
+           }
+
+         return;
+       }
+
+      if (!WWWErwiseConnection->buffer_first)
+       {
+
+         WWWErwiseConnection->buffer_first =
+           WWWErwiseConnection->buffer_last =
+           (cl_data_t *) malloc (sizeof (cl_data_t));
+
+         memset (WWWErwiseConnection->buffer_first, 0, sizeof (cl_data_t));
+
+         WWWErwiseConnection->buffer_first->data =
+           WWWErwiseConnection->buffer_first->freeptr =
+           (void *) malloc (i);
+
+         WWWErwiseConnection->buffer_first->size = i;
+
+         memcpy (WWWErwiseConnection->buffer_first->data, tmp, i);
+
+       }
+      else
+       {
+
+         cl_data_t *p = (cl_data_t *) malloc (sizeof (cl_data_t));
+
+         memset (p, 0, sizeof (cl_data_t));
+
+         p->data = p->freeptr = (void *) malloc (i);
+
+         p->size = i;
+
+         memcpy (p->data, tmp, i);
+
+         p->prev = WWWErwiseConnection->buffer_last;
+
+         WWWErwiseConnection->buffer_last->next = p;
+
+         WWWErwiseConnection->buffer_last = p;
+       }
+
+      return;
+    }
+
+  if (i < 0 && (errno != EWOULDBLOCK))
+    {
+      CL_DEBUG (("ReadData failed\n"));
+      WWWErwiseStatus = CL_FAILED;
+    }
+
+  if (i == 0)
+    {
+      WWWErwiseConnection->function++;
+      return;
+    }
+}
+
+
+
+/*
+ * Parse data that has been read
+ */
+
+void
+WWWErwiseParse ()
+{
+  /*
+   * XXXXXX If saving to file, don't parse
+   */
+
+  HTParseFormat (WWWErwiseConnection->diag ? WWW_PLAINTEXT : WWW_HTML,
+                WWWErwiseConnection->anAnchor,
+                WWWErwiseConnection->fd);
+
+  (void) HTClose (WWWErwiseConnection->fd);
+
+  /*
+   * XXXXX free connection structure
+   */
+  WWWErwiseStatus = CL_COMPLETED;
+  WWWErwiseConnection->function++;
+}
+
+
+
+/*
+ * If we are loading to file, nothing else needs to be done ...
+ */
+void
+WWWErwiseTerminateIfLoadToFile ()
+{
+  if (WWWErwiseConnection->load_to_file)
+    {
+      HtLocalText = 0;
+
+      while (*WWWErwiseConnection->function)
+       {
+         WWWErwiseConnection->function++;
+       }
+
+      WWWErwiseStatus = CL_COMPLETED;
+
+    }
+  else
+    {
+      WWWErwiseConnection->function++;
+    }
+}
diff --git a/Cl/ClFTP.c b/Cl/ClFTP.c
new file mode 100644 (file)
index 0000000..7b859c7
--- /dev/null
@@ -0,0 +1,496 @@
+/*
+ * ClFTP.c --
+ *
+ * Author: Teemu Rantanen <tvr@cs.hut.fi>
+ * Copyright (c) 1992 Teemu Rantanen
+ *                    All rights reserved
+ *
+ * Created: Sun Apr 19 22:42:51 1992 tvr
+ * Last modified: Mon May 11 23:30:15 1992 tvr
+ *
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include "Cl.h"
+
+#include "HTParse.h"
+#include "HTUtils.h"
+#include "tcp.h"
+#include "HTAnchor.h"
+
+#define IPPORT_FTP 21
+
+/*
+ * Erwise's own ftp load function. Setup all things to be done
+ */
+
+PUBLIC int HTFTP_open_file_read
+ARGS2 (
+       char *, name,
+       HTParentAnchor *, anchor
+)
+{
+  int status;
+
+  /*
+   * Set up a list of things to do
+   */
+
+  {
+    static void (*functions[]) () =
+    {
+      WWWErwiseConnect,
+      WWWErwiseSetSelect,
+      WWWErwiseFtpGetCommand,  /* get junk */
+
+      WWWErwiseSetPoll,
+      WWWErwiseFtpUser,                /* Send user */
+      WWWErwiseSendCommand,
+      WWWErwiseSetSelect,
+      WWWErwiseFtpGetCommand,
+
+      WWWErwiseSetPoll,
+      WWWErwiseFtpPass,                /* send pass */
+      WWWErwiseSendCommand,
+      WWWErwiseSetSelect,
+      WWWErwiseFtpGetCommand,
+
+      WWWErwiseSetPoll,
+      WWWErwiseFtpBinary,      /* set binary mode */
+      WWWErwiseSendCommand,
+      WWWErwiseSetSelect,
+      WWWErwiseFtpGetCommand,
+
+      WWWErwiseSetPoll,
+      WWWErwiseFtpPassive,     /* set passive mode */
+      WWWErwiseSendCommand,
+      WWWErwiseSetSelect,
+
+      WWWErwiseFtpGetPassive,  /* Get reply and request a file */
+      WWWErwiseSetPoll,
+      WWWErwiseSendCommand,
+
+      WWWErwiseFtpDataChannel, /* make connection */
+      WWWErwiseConnect,
+
+      WWWErwiseFtpCheckForError,/* check for file not found etc ... */
+
+      WWWErwiseSetSelect,      /* read data */
+      WWWErwiseReadData,
+
+      WWWErwiseSetPoll,                /* parse stuff */
+      WWWErwiseTerminateIfLoadToFile,
+      WWWErwiseParse,
+      NULL,
+    };
+    WWWErwiseConnection->function = functions;
+  }
+
+  /*
+   * Set up information needed later
+   */
+
+  WWWErwiseConnection->ftphost = HTParse (name, "", PARSE_HOST);
+
+  WWWErwiseConnection->anAnchor = anchor;
+
+  /*
+   * Start connecting to data port
+   */
+
+  status = cl_start_connection (WWWErwiseConnection->ftphost,
+                               WWWErwiseConnection,
+                               IPPORT_FTP);
+
+  /*
+   * FTP mode on formatting is PLAINTEXT
+   */
+
+  WWWErwiseConnection->diag = 1;
+
+  return status;
+}
+
+
+/*
+ * Send misc commands to data flow
+ */
+
+void
+WWWErwiseFtpUser ()
+{
+  CL_DEBUG (("FTP: send user\n"));
+
+  WWWErwiseConnection->command = strdup ("USER ftp\r\n");
+
+  WWWErwiseConnection->function++;
+}
+
+void
+WWWErwiseFtpPass ()
+{
+  char tmp[8192], hostname[1024];
+
+  CL_DEBUG (("FTP: send pass\n"));
+
+  if (!gethostname (hostname, 1024))
+    {
+      strcpy (hostname, "noname.rupu");
+    }
+
+  sprintf (tmp, "PASS erwise@%s\r\n", hostname);
+
+  WWWErwiseConnection->command = strdup (tmp);
+
+  WWWErwiseConnection->function++;
+}
+
+void
+WWWErwiseFtpPassive ()
+{
+  CL_DEBUG (("FTP: send pasv\n"));
+
+  WWWErwiseConnection->command = strdup ("PASV\r\n");
+
+  WWWErwiseConnection->function++;
+}
+
+void
+WWWErwiseFtpBinary ()
+{
+  CL_DEBUG (("FTP: set binary\n"));
+
+  WWWErwiseConnection->command = strdup ("TYPE I\r\n");
+
+  WWWErwiseConnection->function++;
+}
+
+
+/*
+ * Get junk commands return when the are accomplished
+ */
+
+#define ERWISE_BL_SIZE   8192
+
+void
+WWWErwiseFtpGetCommand ()
+{
+  char tmp[ERWISE_BL_SIZE];
+
+  int i;
+
+  i = NETREAD (WWWErwiseConnection->fd, tmp, ERWISE_BL_SIZE);
+
+  if ((i == -1) && (errno == EWOULDBLOCK))
+    {
+      return;
+    }
+
+  CL_DEBUG (("FTP: got %s\n", tmp));
+
+  if ((tmp[0] < '2') || (tmp[0] > '3'))
+    {
+
+      WWWErwiseStatus = CL_FAILED;
+
+      return;
+
+    }
+
+  WWWErwiseConnection->function++;
+
+}
+/*
+ * Get return code from passive command
+ */
+
+void
+WWWErwiseFtpGetPassive ()
+{
+  char tmp[1024], *p;
+  int a1, a2, a3, a4;
+  int p1, p2, port;
+
+  int i;
+
+  i = NETREAD (WWWErwiseConnection->fd, tmp, 1024);
+
+  if ((i == -1) && (errno == EWOULDBLOCK))
+    {
+      return;
+    }
+
+  tmp[i] = 0;
+
+  CL_DEBUG (("FTP: got passive %s\n", tmp));
+
+  /*
+   * Get to the line which is reply from PASV command.
+   * Check for errors on the way.
+   */
+
+  p = tmp;
+
+  i = 1;
+
+  while (i)
+    {
+      if ((*p >= '0') && (*p <= '9'))
+       {
+         if (!strncmp ("227", p, 3))
+           {
+             i = 0;
+             continue;
+           }
+
+         if ((p[0] < '2') || (tmp[0] > '3'))
+           {
+             WWWErwiseStatus = CL_FAILED;
+             return;
+           }
+       }
+
+      /*
+       * Get next line
+       */
+      while (*p && (*p != '\n'))
+       p++;
+
+      p++;
+
+      if (!*p)
+       {
+         /*
+           * no line but no errors yet
+           */
+         return;
+       }
+    }
+
+  /*
+   * Correct line, get port
+   */
+
+  while (*p && (*p != '('))
+    p++;
+
+  if (!*p)
+    {
+      /*
+       * 227 but no address / port ??
+       */
+
+      WWWErwiseStatus = CL_FAILED;
+
+      return;
+    }
+
+  sscanf (p, "(%d,%d,%d,%d,%d,%d)", &a1, &a2, &a3, &a4, &p1, &p2);
+
+  port = p1 * 256 + p2;
+
+  printf ("ErwiseFTP: got connection to %d.%d.%d.%d on port %d\n",
+         a1, a2, a3, a4, port);
+
+  /*
+   * send receive command too
+   */
+
+  {
+    char *filename = HTParse (WWWErwiseConnection->address, "",
+                             PARSE_PATH + PARSE_PUNCTUATION);
+
+    sprintf (tmp, "RETR %s\r\n", filename);
+
+    WWWErwiseConnection->command = strdup (tmp);
+  }
+
+  WWWErwiseConnection->port = port;
+
+  WWWErwiseConnection->function++;
+}
+
+
+/*
+ * Make data channel connection
+ */
+void
+WWWErwiseFtpDataChannel ()
+{
+  /*
+   * Set data flow port to secondary so that it can be closed properly
+   */
+
+  WWWErwiseConnection->secondary_fd = WWWErwiseConnection->fd;
+
+  cl_start_connection (WWWErwiseConnection->ftphost,
+                      WWWErwiseConnection,
+                      WWWErwiseConnection->port);
+
+  WWWErwiseConnection->function++;
+}
+
+
+
+/*
+ * Start connection. Make sure it is nonblocking one.
+ */
+
+int
+cl_start_connection (host, connection, port)
+     char *host;
+     ClConnection_t *connection;
+     int port;
+{
+  /*
+   * Code partly from get_connection()
+   */
+
+  int s;
+
+  struct hostent *phost;       /* Pointer to host -- See netdb.h */
+  struct sockaddr_in soc_address;      /* Binary network address */
+  struct sockaddr_in *sin = &soc_address;
+
+/*  Set up defaults:
+*/
+  sin->sin_family = AF_INET;   /* Family, host order  */
+  sin->sin_port = htons (port);
+
+/* Get node name:
+*/
+  {
+    if (*host >= '0' && *host <= '9')
+      {                                /* Numeric node address: */
+       sin->sin_addr.s_addr = inet_addr (host);        /* See arpa/inet.h */
+
+      }
+    else
+      {                                /* Alphanumeric node name: */
+       phost = gethostbyname (host);   /* See netdb.h */
+       if (!phost)
+         {
+           if (TRACE)
+             printf (
+                      "FTP: Can't find internet node name `%s'.\n",
+                      host);
+
+           WWWErwiseStatus = CL_FAILED;
+
+           return -1;
+         }
+       memcpy (&sin->sin_addr, phost->h_addr, phost->h_length);
+      }
+
+    if (TRACE)
+      printf (
+              "FTP: Parsed remote address as port %d, inet %d.%d.%d.%d\n",
+              (unsigned int) ntohs (sin->sin_port),
+              (int) *((unsigned char *) (&sin->sin_addr) + 0),
+              (int) *((unsigned char *) (&sin->sin_addr) + 1),
+              (int) *((unsigned char *) (&sin->sin_addr) + 2),
+              (int) *((unsigned char *) (&sin->sin_addr) + 3));
+  }                            /* scope of p1 */
+
+
+  {
+    int status;
+
+    s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
+
+    if (s < 0)
+      {
+       WWWErwiseStatus = CL_FAILED;
+
+       return -1;
+      }
+
+    connection->fd = s;
+
+    /*
+     * Must NOT select connection now. Must poll.
+     */
+    connection->select_fd = 0;
+
+    (void) fcntl (s, F_SETFL, O_NONBLOCK);
+    (void) fcntl (s, F_SETFL, FNDELAY);
+
+    status = erwise_connect (s,
+                            (struct sockaddr *) & soc_address,
+                            sizeof (soc_address));
+  }
+
+  /*
+   * everything done
+   */
+
+  return s;
+}
+
+
+
+/*
+ * Check for errors when retr is sent
+ */
+
+void
+WWWErwiseFtpCheckForError ()
+{
+  fd_set readfds;
+  fd_set exceptionfds;
+
+  struct timeval tv;
+
+  int fd, fd2;
+
+  fd = WWWErwiseConnection->fd;
+  fd2 = WWWErwiseConnection->secondary_fd;
+
+  tv.tv_sec = tv.tv_usec = 0;
+
+  FD_ZERO (&readfds);
+  FD_SET (fd, &readfds);
+  FD_SET (fd2, &readfds);
+
+  FD_ZERO (&exceptionfds);
+  FD_SET (fd, &exceptionfds);
+  FD_SET (fd2, &exceptionfds);
+
+  select ((fd > fd2 ? fd : fd2) + 1, &readfds, NULL, &exceptionfds, &tv);
+
+  /*
+   * Error on either data or command channel
+   */
+  if (FD_ISSET (fd, &exceptionfds) || FD_ISSET (fd2, &exceptionfds))
+    {
+
+      WWWErwiseStatus = CL_FAILED;
+
+      return;
+    }
+
+  /*
+   * Data is flowing (OK)
+   */
+  if (FD_ISSET (fd, &readfds))
+    {
+
+      WWWErwiseConnection->function++;
+
+      return;
+    }
+
+  /*
+   * Anything here is considered an error
+   */
+  if (FD_ISSET (fd2, &readfds))
+    {
+
+      WWWErwiseStatus = CL_FAILED;
+
+      return;
+    }
+}
diff --git a/Cl/ClHTTP.c b/Cl/ClHTTP.c
new file mode 100644 (file)
index 0000000..15c0dfe
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * ClHTTP.c --
+ *
+ * Author: Teemu Rantanen <tvr@cs.hut.fi>
+ * Copyright (c) 1992 Teemu Rantanen
+ *                    All rights reserved
+ *
+ * Created: Fri Apr 17 23:43:01 1992 tvr
+ * Last modified: Mon May 11 23:29:10 1992 tvr
+ *
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include "Cl.h"
+
+#include "HTParse.h"
+#include "HTFormat.h"
+#include "HTAnchor.h"
+#include "tcp.h"
+
+
+
+/*
+ * We want that loading won't kill the whole f*king client.
+ *
+ * This is a kludge ;)
+ */
+
+PUBLIC int HTLoadHTTP
+ARGS4 (CONST char *, arg,
+       CONST char *, gate,
+       HTAnchor *, anAnchor,
+       int, diag)
+{
+  /*
+   * Most code from old loading function
+   */
+
+  int s;
+  int status;
+  char *command;
+
+  struct sockaddr_in soc_address;      /* Binary network address */
+  struct sockaddr_in *sin = &soc_address;
+
+  if (!arg)
+    return -3;                 /* Bad if no name sepcified     */
+  if (!*arg)
+    return -2;                 /* Bad if name had zero length  */
+
+/*  Set up defaults:
+*/
+  sin->sin_family = AF_INET;   /* Family, host order  */
+  sin->sin_port = htons (TCP_PORT);    /* Default: new port,    */
+
+  if (TRACE)
+    {
+      if (gate)
+       fprintf (stderr,
+                "HTTPAccess: Using gateway %s for %s\n", gate, arg);
+      else
+       fprintf (stderr, "HTTPAccess: Direct access for %s\n", arg);
+    }
+
+/* Get node name and optional port number:
+*/
+  {
+    char *p1 = HTParse (gate ? gate : arg, "", PARSE_HOST);
+    HTParseInet (sin, p1);
+    free (p1);
+  }
+
+
+/*     Now, let's get a socket set up from the server for the sgml data:
+*/
+  s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
+  (void) fcntl (s, F_SETFL, O_NONBLOCK);
+  (void) fcntl (s, F_SETFL, FNDELAY);
+
+  /*
+   * Now. Do first attempt to connect.
+   */
+  status = erwise_connect (s,
+                          (struct sockaddr *) & soc_address,
+                          sizeof (soc_address));
+
+  if (s < 0)
+    {
+      /*
+       * Fail
+       */
+      /*free(command);*/
+      return -1;
+    }
+
+  if (TRACE)
+    printf ("HTTP connected, socket %d\n", s);
+
+/*     Ask that node for the document,
+**     omitting the host name & anchor if not gatewayed.
+*/
+  if (gate)
+    {
+      command = malloc (4 + strlen (arg) + 1 + 1);
+      strcpy (command, "GET ");
+      strcat (command, arg);
+    }
+  else
+    {                          /* not gatewayed */
+      char *p1 = HTParse (arg, "", PARSE_PATH | PARSE_PUNCTUATION);
+      command = malloc (4 + strlen (p1) + 1 + 1);
+      strcpy (command, "GET ");
+      strcat (command, p1);
+      free (p1);
+    }
+  strcat (command, "\r\n");    /* Include CR for telnet compat. */
+
+
+  if (TRACE)
+    printf ("HTTP writing command `%s' to socket %d\n", command, s);
+
+#ifdef NOT_ASCII
+  {
+    char *p;
+    for (p = command; *p; p++)
+      {
+       *p = TOASCII (*p);
+      }
+  }
+#endif
+
+  /*
+   * Ok. Everything is now set up. Set functionpointers so that
+   * the rest of loading works ok.
+   */
+
+  {
+    static void (*functions[]) () =
+    {
+      WWWErwiseConnect,
+      WWWErwiseSendCommand,
+      WWWErwiseSetSelect,
+      WWWErwiseReadData,
+      WWWErwiseSetPoll,
+      WWWErwiseTerminateIfLoadToFile,
+      WWWErwiseParse,
+      NULL,
+    };
+    WWWErwiseConnection->function = functions;
+  }
+
+  WWWErwiseConnection->command = command;
+
+  WWWErwiseConnection->diag = diag;
+
+  WWWErwiseConnection->anAnchor = anAnchor;
+
+  /*
+   * Cheat HTOpen()
+   */
+  return s;
+}
diff --git a/Cl/ClMisc.c b/Cl/ClMisc.c
new file mode 100644 (file)
index 0000000..932131f
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * ClMisc.c --
+ *
+ * Author: Teemu Rantanen <tvr@cs.hut.fi>
+ * Copyright (c) 1992 Teemu Rantanen
+ *                    All rights reserved
+ *
+ * Created: Mon Apr 20 19:27:04 1992 tvr
+ * Last modified: Mon Apr 20 19:48:47 1992 tvr
+ *
+ */
+
+#include "Cl.h"
+
+
+/*
+ * Set mode to poll or to select connection
+ */
+
+void
+WWWErwiseSetPoll ()
+{
+  CL_DEBUG (("SetPoll\n"));
+
+  WWWErwiseConnection->select_fd = 0;
+
+  WWWErwiseConnection->function++;
+}
+
+void
+WWWErwiseSetSelect ()
+{
+  CL_DEBUG (("SetSelect\n"));
+
+  WWWErwiseConnection->select_fd = WWWErwiseConnection->fd;
+
+  WWWErwiseConnection->function++;
+}
diff --git a/Cl/Imakefile b/Cl/Imakefile
new file mode 100644 (file)
index 0000000..9379405
--- /dev/null
@@ -0,0 +1,20 @@
+#
+#
+#
+
+#define IHavesubdirs
+#define PassCDebugFlags
+
+          OBJS = Cl.o ClHTTP.o ClFTP.o ClMisc.o ClConnection.o
+          SRCS = Cl.c ClHTTP.c ClFTP.c ClMisc.c ClConnection.c
+       SUBDIRS = WWWLibrary
+       DEFINES = -I$(SUBDIRS)
+
+NormalLibraryTarget(Cl, $(OBJS))
+
+MakeSubdirs($(SUBDIRS))
+MakefileSubdirs($(SUBDIRS))
+DependTarget()
+DependSubdirs($(SUBDIRS))
+
+
diff --git a/Cl/Makefile b/Cl/Makefile
new file mode 100644 (file)
index 0000000..631a7de
--- /dev/null
@@ -0,0 +1,405 @@
+# Makefile generated by imake - do not edit!
+# $XConsortium: imake.c,v 1.65 91/07/25 17:50:17 rws Exp $
+#
+# The cpp used on this machine replaces all newlines and multiple tabs and
+# spaces in a macro expansion with a single space.  Imake tries to compensate
+# for this, but is not always successful.
+#
+
+# -------------------------------------------------------------------------
+# Makefile generated from "Imake.tmpl" and </tmp/IIf.a10826>
+# $XConsortium: Imake.tmpl,v 1.139 91/09/16 08:52:48 rws Exp $
+#
+# Platform-specific parameters may be set in the appropriate <vendor>.cf
+# configuration files.  Site-specific parameters should be set in the file
+# site.def.  Full rebuilds are recommended if any parameters are changed.
+#
+# If your C preprocessor does not define any unique symbols, you will need
+# to set BOOTSTRAPCFLAGS when rebuilding imake (usually when doing
+# "make World" the first time).
+#
+
+# -------------------------------------------------------------------------
+# site-specific configuration parameters that need to come before
+# the platform-specific parameters - edit site.def to change
+
+# site:  $XConsortium: site.def,v 1.2 91/07/30 20:26:44 rws Exp $
+
+# -------------------------------------------------------------------------
+# platform-specific configuration parameters - edit sun.cf to change
+
+# platform:  $XConsortium: sun.cf,v 1.72.1.1 92/03/18 13:13:37 rws Exp $
+
+# operating system:  SunOS 4.1.2
+
+# $XConsortium: sunLib.rules,v 1.7 91/12/20 11:19:47 rws Exp $
+
+.c.o:
+       $(CC) -c $(CFLAGS) $*.c
+
+# -------------------------------------------------------------------------
+# site-specific configuration parameters that go after
+# the platform-specific parameters - edit site.def to change
+
+# site:  $XConsortium: site.def,v 1.2 91/07/30 20:26:44 rws Exp $
+
+            SHELL = /bin/sh
+
+              TOP = ../.
+      CURRENT_DIR = ./Cl
+
+               AR = ar clq
+  BOOTSTRAPCFLAGS =
+               CC = gcc2 -pipe -fstrength-reduce -fpcc-struct-return
+               AS = as
+
+         COMPRESS = compress
+              CPP = /lib/cpp $(STD_CPP_DEFINES)
+    PREPROCESSCMD = gcc2 -pipe -fstrength-reduce -fpcc-struct-return -E $(STD_CPP_DEFINES)
+          INSTALL = install
+               LD = ld
+             LINT = lint
+      LINTLIBFLAG = -C
+         LINTOPTS = -axz
+               LN = ln -s
+             MAKE = make
+               MV = mv
+               CP = cp
+
+           RANLIB = ranlib
+  RANLIBINSTFLAGS =
+
+               RM = rm -f
+            TROFF = psroff
+         MSMACROS = -ms
+              TBL = tbl
+              EQN = eqn
+     STD_INCLUDES =
+  STD_CPP_DEFINES =
+      STD_DEFINES =
+ EXTRA_LOAD_FLAGS = -B/usr/bin/
+  EXTRA_LIBRARIES =
+             TAGS = ctags
+
+    SHAREDCODEDEF = -DSHAREDCODE
+         SHLIBDEF = -DSUNSHLIB
+
+    PROTO_DEFINES =
+
+     INSTPGMFLAGS =
+
+     INSTBINFLAGS = -m 0755
+     INSTUIDFLAGS = -m 4755
+     INSTLIBFLAGS = -m 0644
+     INSTINCFLAGS = -m 0444
+     INSTMANFLAGS = -m 0444
+     INSTDATFLAGS = -m 0444
+    INSTKMEMFLAGS = -g kmem -m 2755
+
+      PROJECTROOT = /v/X11R5
+
+     TOP_INCLUDES = -I$(INCROOT)
+
+      CDEBUGFLAGS = -O
+        CCOPTIONS =
+
+      ALLINCLUDES = $(INCLUDES) $(EXTRA_INCLUDES) $(TOP_INCLUDES) $(STD_INCLUDES)
+       ALLDEFINES = $(ALLINCLUDES) $(STD_DEFINES) $(EXTRA_DEFINES) $(PROTO_DEFINES) $(DEFINES)
+           CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLDEFINES)
+        LINTFLAGS = $(LINTOPTS) -DLINT $(ALLDEFINES)
+
+           LDLIBS = $(SYS_LIBRARIES) $(EXTRA_LIBRARIES)
+
+        LDOPTIONS = $(CDEBUGFLAGS) $(CCOPTIONS) $(LOCAL_LDFLAGS) -L$(USRLIBDIR)
+
+   LDCOMBINEFLAGS = -X -r
+      DEPENDFLAGS =
+
+        MACROFILE = sun.cf
+           RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *~ *.a .emacs_* tags TAGS make.log MakeOut
+
+    IMAKE_DEFINES =
+
+         IRULESRC = $(CONFIGDIR)
+        IMAKE_CMD = $(IMAKE) -DUseInstalled -I$(IRULESRC) $(IMAKE_DEFINES)
+
+     ICONFIGFILES = $(IRULESRC)/Imake.tmpl $(IRULESRC)/Imake.rules \
+                       $(IRULESRC)/Project.tmpl $(IRULESRC)/site.def \
+                       $(IRULESRC)/$(MACROFILE) $(EXTRA_ICONFIGFILES)
+
+# -------------------------------------------------------------------------
+# X Window System Build Parameters
+# $XConsortium: Project.tmpl,v 1.138 91/09/10 09:02:12 rws Exp $
+
+# -------------------------------------------------------------------------
+# X Window System make variables; this need to be coordinated with rules
+
+          PATHSEP = /
+        USRLIBDIR = /v/X11R5/lib
+           BINDIR = /v/X11R5/bin
+          INCROOT = /v/X11R5/include
+     BUILDINCROOT = $(TOP)
+      BUILDINCDIR = $(BUILDINCROOT)/X11
+      BUILDINCTOP = ..
+           INCDIR = $(INCROOT)/X11
+           ADMDIR = /usr/adm
+           LIBDIR = $(USRLIBDIR)/X11
+        CONFIGDIR = $(LIBDIR)/config
+       LINTLIBDIR = $(USRLIBDIR)/lint
+
+          FONTDIR = $(LIBDIR)/fonts
+         XINITDIR = $(LIBDIR)/xinit
+           XDMDIR = $(LIBDIR)/xdm
+           TWMDIR = $(LIBDIR)/twm
+          MANPATH = /v/X11R5/man
+    MANSOURCEPATH = $(MANPATH)/man
+        MANSUFFIX = n
+     LIBMANSUFFIX = 3
+           MANDIR = $(MANSOURCEPATH)$(MANSUFFIX)
+        LIBMANDIR = $(MANSOURCEPATH)$(LIBMANSUFFIX)
+           NLSDIR = $(LIBDIR)/nls
+        PEXAPIDIR = $(LIBDIR)/PEX
+      XAPPLOADDIR = $(LIBDIR)/app-defaults
+       FONTCFLAGS = -t
+
+     INSTAPPFLAGS = $(INSTDATFLAGS)
+
+            IMAKE = imake
+           DEPEND = makedepend
+              RGB = rgb
+
+            FONTC = bdftopcf
+
+        MKFONTDIR = mkfontdir
+        MKDIRHIER = /bin/sh $(BINDIR)/mkdirhier
+
+        CONFIGSRC = $(TOP)/config
+       DOCUTILSRC = $(TOP)/doc/util
+        CLIENTSRC = $(TOP)/clients
+          DEMOSRC = $(TOP)/demos
+           LIBSRC = $(TOP)/lib
+          FONTSRC = $(TOP)/fonts
+       INCLUDESRC = $(TOP)/X11
+        SERVERSRC = $(TOP)/server
+          UTILSRC = $(TOP)/util
+        SCRIPTSRC = $(UTILSRC)/scripts
+       EXAMPLESRC = $(TOP)/examples
+       CONTRIBSRC = $(TOP)/../contrib
+           DOCSRC = $(TOP)/doc
+           RGBSRC = $(TOP)/rgb
+        DEPENDSRC = $(UTILSRC)/makedepend
+         IMAKESRC = $(CONFIGSRC)
+         XAUTHSRC = $(LIBSRC)/Xau
+          XLIBSRC = $(LIBSRC)/X
+           XMUSRC = $(LIBSRC)/Xmu
+       TOOLKITSRC = $(LIBSRC)/Xt
+       AWIDGETSRC = $(LIBSRC)/Xaw
+       OLDXLIBSRC = $(LIBSRC)/oldX
+      XDMCPLIBSRC = $(LIBSRC)/Xdmcp
+      BDFTOSNFSRC = $(FONTSRC)/bdftosnf
+      BDFTOSNFSRC = $(FONTSRC)/clients/bdftosnf
+      BDFTOPCFSRC = $(FONTSRC)/clients/bdftopcf
+     MKFONTDIRSRC = $(FONTSRC)/clients/mkfontdir
+         FSLIBSRC = $(FONTSRC)/lib/fs
+    FONTSERVERSRC = $(FONTSRC)/server
+     EXTENSIONSRC = $(TOP)/extensions
+         XILIBSRC = $(EXTENSIONSRC)/lib/xinput
+      PHIGSLIBSRC = $(EXTENSIONSRC)/lib/PEX
+
+# $XConsortium: sunLib.tmpl,v 1.14.1.1 92/03/17 14:58:46 rws Exp $
+
+SHLIBLDFLAGS = -assert pure-text
+PICFLAGS = -fPIC
+
+  DEPEXTENSIONLIB =
+     EXTENSIONLIB = -lXext
+
+          DEPXLIB = $(DEPEXTENSIONLIB)
+             XLIB = $(EXTENSIONLIB) -lX11
+
+        DEPXMULIB = $(USRLIBDIR)/libXmu.sa.$(SOXMUREV)
+       XMULIBONLY = -lXmu
+           XMULIB = -lXmu
+
+       DEPOLDXLIB =
+          OLDXLIB = -loldX
+
+      DEPXTOOLLIB = $(USRLIBDIR)/libXt.sa.$(SOXTREV)
+         XTOOLLIB = -lXt
+
+        DEPXAWLIB = $(USRLIBDIR)/libXaw.sa.$(SOXAWREV)
+           XAWLIB = -lXaw
+
+        DEPXILIB =
+           XILIB = -lXi
+
+        SOXLIBREV = 4.10
+          SOXTREV = 4.10
+         SOXAWREV = 5.0
+        SOOLDXREV = 4.10
+         SOXMUREV = 4.10
+        SOXEXTREV = 4.10
+      SOXINPUTREV = 4.10
+
+      DEPXAUTHLIB = $(USRLIBDIR)/libXau.a
+         XAUTHLIB =  -lXau
+      DEPXDMCPLIB = $(USRLIBDIR)/libXdmcp.a
+         XDMCPLIB =  -lXdmcp
+
+        DEPPHIGSLIB = $(USRLIBDIR)/libphigs.a
+           PHIGSLIB =  -lphigs
+
+       DEPXBSDLIB = $(USRLIBDIR)/libXbsd.a
+          XBSDLIB =  -lXbsd
+
+ LINTEXTENSIONLIB = $(LINTLIBDIR)/llib-lXext.ln
+         LINTXLIB = $(LINTLIBDIR)/llib-lX11.ln
+          LINTXMU = $(LINTLIBDIR)/llib-lXmu.ln
+        LINTXTOOL = $(LINTLIBDIR)/llib-lXt.ln
+          LINTXAW = $(LINTLIBDIR)/llib-lXaw.ln
+           LINTXI = $(LINTLIBDIR)/llib-lXi.ln
+        LINTPHIGS = $(LINTLIBDIR)/llib-lphigs.ln
+
+          DEPLIBS = $(DEPXAWLIB) $(DEPXMULIB) $(DEPXTOOLLIB) $(DEPXLIB)
+
+         DEPLIBS1 = $(DEPLIBS)
+         DEPLIBS2 = $(DEPLIBS)
+         DEPLIBS3 = $(DEPLIBS)
+
+# -------------------------------------------------------------------------
+# Imake rules for building libraries, programs, scripts, and data files
+# rules:  $XConsortium: Imake.rules,v 1.123 91/09/16 20:12:16 rws Exp $
+
+# -------------------------------------------------------------------------
+# start of Imakefile
+
+#
+#
+#
+
+          OBJS = Cl.o ClHTTP.o ClFTP.o ClMisc.o ClConnection.o
+          SRCS = Cl.c ClHTTP.c ClFTP.c ClMisc.c ClConnection.c
+       SUBDIRS = WWWLibrary
+       DEFINES = -I$(SUBDIRS)
+
+all:: libCl.a
+
+libCl.a:  $(OBJS)
+       $(RM) $@
+       $(AR) $@  $(OBJS)
+       $(RANLIB) $@
+
+all::
+       @case '${MFLAGS}' in *[ik]*) set +e;; esac; \
+       for i in $(SUBDIRS) ;\
+       do \
+       (cd $$i ; echo "making" all "in $(CURRENT_DIR)/$$i..."; \
+       $(MAKE) $(MFLAGS)  all); \
+       done
+
+Makefiles::
+       @case '${MFLAGS}' in *[ik]*) set +e;; esac; \
+       for i in $(SUBDIRS) ;\
+       do \
+       echo "making Makefiles in $(CURRENT_DIR)/$$i..."; \
+       case "$$i" in \
+       ./?*/?*/?*/?*) newtop=../../../../ sub=subsubsubsub;; \
+       ./?*/?*/?*) newtop=../../../ sub=subsubsub;; \
+       ./?*/?*) newtop=../../ sub=subsub;; \
+       ./?*) newtop=../ sub=sub;; \
+       */?*/?*/?*) newtop=../../../../ sub=subsubsubsub;; \
+       */?*/?*) newtop=../../../ sub=subsubsub;; \
+       */?*) newtop=../../ sub=subsub;; \
+       *) newtop=../ sub=sub;; \
+       esac; \
+       case "$(TOP)" in \
+       /?*) newtop= upprefix= ;; \
+       *) upprefix=../ ;; \
+       esac; \
+       $(MAKE) $${sub}dirMakefiles UPPREFIX=$$upprefix NEWTOP=$$newtop \
+       MAKEFILE_SUBDIR=$$i NEW_CURRENT_DIR=$(CURRENT_DIR)/$$i;\
+       done
+
+subdirMakefiles:
+       $(RM) $(MAKEFILE_SUBDIR)/Makefile.bak
+       -@if [ -f $(MAKEFILE_SUBDIR)/Makefile ]; then set -x; \
+       $(MV) $(MAKEFILE_SUBDIR)/Makefile $(MAKEFILE_SUBDIR)/Makefile.bak; \
+       else exit 0; fi
+       cd $(MAKEFILE_SUBDIR); $(IMAKE_CMD) -DTOPDIR=$(UPPREFIX)$(TOP) -DCURDIR=$(NEW_CURRENT_DIR); \
+       $(MAKE) $(MFLAGS) Makefiles
+
+subsubdirMakefiles:
+       $(RM) $(MAKEFILE_SUBDIR)/Makefile.bak
+       -@if [ -f $(MAKEFILE_SUBDIR)/Makefile ]; then set -x; \
+       $(MV) $(MAKEFILE_SUBDIR)/Makefile $(MAKEFILE_SUBDIR)/Makefile.bak; \
+       else exit 0; fi
+       cd $(MAKEFILE_SUBDIR); $(IMAKE_CMD) -DTOPDIR=$(UPPREFIX)$(UPPREFIX)$(TOP) -DCURDIR=$(NEW_CURRENT_DIR); \
+       $(MAKE) $(MFLAGS) Makefiles
+
+subsubsubdirMakefiles:
+       $(RM) $(MAKEFILE_SUBDIR)/Makefile.bak
+       -@if [ -f $(MAKEFILE_SUBDIR)/Makefile ]; then set -x; \
+       $(MV) $(MAKEFILE_SUBDIR)/Makefile $(MAKEFILE_SUBDIR)/Makefile.bak; \
+       else exit 0; fi
+       cd $(MAKEFILE_SUBDIR); $(IMAKE_CMD) -DTOPDIR=$(UPPREFIX)$(UPPREFIX)$(UPPREFIX)$(TOP) -DCURDIR=$(NEW_CURRENT_DIR); \
+       $(MAKE) $(MFLAGS) Makefiles
+
+subsubsubsubdirMakefiles:
+       $(RM) $(MAKEFILE_SUBDIR)/Makefile.bak
+       -@if [ -f $(MAKEFILE_SUBDIR)/Makefile ]; then set -x; \
+       $(MV) $(MAKEFILE_SUBDIR)/Makefile $(MAKEFILE_SUBDIR)/Makefile.bak; \
+       else exit 0; fi
+       cd $(MAKEFILE_SUBDIR); $(IMAKE_CMD) -DTOPDIR=$(UPPREFIX)$(UPPREFIX)$(UPPREFIX)$(UPPREFIX)$(TOP) -DCURDIR=$(NEW_CURRENT_DIR); \
+       $(MAKE) $(MFLAGS) Makefiles
+
+depend::
+       $(DEPEND) $(DEPENDFLAGS) -s "# DO NOT DELETE" -- $(ALLDEFINES) -- $(SRCS)
+
+depend::
+       @case '${MFLAGS}' in *[ik]*) set +e;; esac; \
+       for i in $(SUBDIRS) ;\
+       do \
+       (cd $$i ; echo "depending" "in $(CURRENT_DIR)/$$i..."; \
+       $(MAKE) $(MFLAGS)  depend); \
+       done
+
+# -------------------------------------------------------------------------
+# common rules for all Makefiles - do not edit
+
+emptyrule::
+
+clean::
+       $(RM_CMD) "#"*
+
+Makefile::
+       -@if [ -f Makefile ]; then set -x; \
+       $(RM) Makefile.bak; $(MV) Makefile Makefile.bak; \
+       else exit 0; fi
+       $(IMAKE_CMD) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT_DIR)
+
+tags::
+       $(TAGS) -w *.[ch]
+       $(TAGS) -xw *.[ch] > TAGS
+
+saber:
+       # load $(ALLDEFINES) $(SRCS)
+
+osaber:
+       # load $(ALLDEFINES) $(OBJS)
+
+# -------------------------------------------------------------------------
+# empty rules for directories that do not have SUBDIRS - do not edit
+
+install::
+       @echo "install in $(CURRENT_DIR) done"
+
+install.man::
+       @echo "install.man in $(CURRENT_DIR) done"
+
+Makefiles::
+
+includes::
+
+# -------------------------------------------------------------------------
+# dependencies generated by makedepend
+
diff --git a/Cl/WWWLibrary/HTAccess.c b/Cl/WWWLibrary/HTAccess.c
new file mode 100644 (file)
index 0000000..3f7af2c
--- /dev/null
@@ -0,0 +1,520 @@
+/*             Access Manager                                  HTAccess.c
+**             ==============
+*/
+
+
+#include "HTParse.h"
+#include "HTUtils.h"
+#include "WWW.h"
+#include "HTAnchor.h"
+#include "HTFTP.h"
+#include "HTTP.h"
+#include "HTFile.h"
+#include <errno.h>
+#include <stdio.h>
+
+#include "tcp.h"
+#include "HText.h"
+#include "HTNews.h"
+#include "HTGopher.h"
+#include "HTBrowse.h"          /* Need global HTClientHost */
+
+#include "HTAccess.h"
+
+#ifdef ERWISE
+#include "Cl.h"
+#endif
+
+#define HT_NO_DATA -9999
+
+PUBLIC int HTDiag = 0;         /* Diagnostics: load source as text */
+
+/*     Telnet or "rlogin" access
+**     -------------------------
+*/
+PRIVATE int remote_session ARGS2(char *, access, char *, host)
+{
+       char * user = host;
+       char * hostname = strchr(host, '@');
+       char * port = strchr(host, ':');
+       char   command[256];
+       BOOL rlogin = strcmp(access, "rlogin");
+       
+       if (hostname) {
+           *hostname++ = 0;    /* Split */
+       } else {
+           hostname = host;
+           user = 0;           /* No user specified */
+       }
+       if (port) *port++ = 0;  /* Split */
+
+#ifdef unix
+       sprintf(command, "%s%s%s %s %s", access,
+               user ? " -l " : "",
+               user ? user : "",
+               hostname,
+               port ? port : "");
+       if (TRACE) fprintf(stderr, "HTaccess: Command is: %s\n", command);
+       system(command);
+       return HT_NO_DATA;              /* Ok - it was done but no data */
+#define TELNET_DONE
+#endif
+
+#ifdef MULTINET                                /* VMS varieties */
+       if (!rlogin) {                  /* telnet */
+           if (user) printf("When you are connected, log in as %s\n", user);
+           sprintf(command, "TELNET %s%s %s",
+               port ? "/PORT=" : "",
+               port ? port : "",
+               hostname);
+       } else {
+           sprintf(command, "RLOGIN%s%s%s%s %s", access,
+               user ? "/USERNAME=" : "",
+               user ? user : "",
+               port ? "/PORT=" : "",
+               port ? port : "",
+               hostname);
+       }
+       if (TRACE) fprintf(stderr, "HTaccess: Command is: %s\n", command);
+       system(command);
+       return HT_NO_DATA;              /* Ok - it was done but no data */
+#define TELNET_DONE
+#endif
+
+#ifdef UCX
+#define SIMPLE_TELNET
+#endif
+#ifdef VM
+#define SIMPLE_TELNET
+#endif
+#ifdef SIMPLE_TELNET
+       if (!rlogin) {                  /* telnet only */
+           if (user) printf("When you are connected, log in as %s\n", user);
+           sprintf(command, "TELNET  %s",      /* @@ Bug: port ignored */
+               hostname);
+           if (TRACE) fprintf(stderr, "HTaccess: Command is: %s\n", command);
+           system(command);
+           return HT_NO_DATA;          /* Ok - it was done but no data */
+       }
+#endif
+
+#ifndef TELNET_DONE
+       fprintf(stderr,
+       "Sorry, this browser was compiled without the %s access option.\n",
+               access);
+       fprintf(stderr,
+       "\nTo access the information you must %s to %s", access, hostname);
+       if (port) fprintf(stderr," (port %s)", port);
+       if (user) fprintf(stderr," logging in with username %s", user);
+       fprintf(stderr, ".\n");
+       return -1;
+#endif
+}
+
+/*     Open a file descriptor for a document
+**     -------------------------------------
+**
+** On entry,
+**     addr            must point to the fully qualified hypertext reference.
+**
+** On exit,
+**     returns         <0      Error has occured.
+**                     >=0     Value of file descriptor or socket to be used
+**                              to read data.
+**     *pFormat        Set to the format of the file, if known.
+**                     (See WWW.h)
+**
+*/
+PRIVATE int HTOpen ARGS3(
+       CONST char *,addr1,
+       HTFormat *,pFormat,
+       HTParentAnchor *,anchor)
+{
+    char * access=0;   /* Name of access method */
+    int status;
+    char * gateway;
+    char * gateway_parameter;
+    char * addr = (char *)malloc(strlen(addr1)+1);
+    
+    if (addr == NULL) outofmem(__FILE__, "HTOpen");
+    strcpy(addr, addr1);                       /* Copy to play with */
+    
+    access =  HTParse(addr, "file:", PARSE_ACCESS);
+    
+    gateway_parameter = (char *)malloc(strlen(access)+20);
+    if (gateway_parameter == NULL) outofmem(__FILE__, "HTOpen");
+    strcpy(gateway_parameter, "WWW_");
+    strcat(gateway_parameter, access);
+    strcat(gateway_parameter, "_GATEWAY");
+    gateway = getenv(gateway_parameter);
+    free(gateway_parameter);
+
+    if (gateway) {
+       status = HTLoadHTTP(addr, gateway, anchor, HTDiag);
+#ifndef CURSES
+       if (status<0) fprintf(stderr,   /* For simple users */
+           "Cannot connect to information gateway %s\n", gateway);
+#endif 
+    } else if (0==strcmp(access, "http")) {
+        status = HTLoadHTTP(addr, 0, anchor, HTDiag);
+#ifndef CURSES
+       if (status<0) fprintf(stderr,   /* For simple users */
+               "Cannot connect to information server.\n");
+#endif
+    } else if (0==strcmp(access, "file")) {
+        status = HTOpenFile(addr, pFormat, anchor);
+
+    } else if (0==strcmp(access, "news")) {
+        status = HTLoadNews(addr, anchor, HTDiag);
+       if (status>0) status = HT_LOADED;
+
+    } else if (0==strcmp(access, "gopher")) {
+        status = HTLoadGopher(addr, anchor, HTDiag);
+       if (status>0) status = HT_LOADED;
+
+    } else if (!strcmp(access, "telnet") ||            /* TELNET */
+       !strcmp(access, "rlogin")) {                    /* RLOGIN */
+        char * host = HTParse(addr, "", PARSE_HOST);
+       remote_session(access, host);
+       free(host);
+       
+    } else if (0==strcmp(access, "wais")) {
+        user_message(
+"HTAccess: For WAIS access set WWW_wais_GATEWAY to gateway address.\n");
+    } else {
+
+        user_message(
+       "HTAccess: name scheme `%s' unknown by this browser version.\n",
+                access);
+        status = -1;
+    }
+    free(access);
+    free(addr);
+    return status;
+}
+
+
+/*     Close socket opened for reading a file
+**     --------------------------------------
+**
+*/
+#ifdef ERWISE
+PUBLIC int HTClose ARGS1(int,soc)
+#else
+PRIVATE int HTClose ARGS1(int,soc)
+#endif
+{
+    return HTFTP_close_file(soc);
+}
+
+
+/*             Load a document
+**             ---------------
+**
+**    On Entry,
+**       anchor            is the node_anchor for the document
+**        full_address      The address of the file to be accessed.
+**
+**    On Exit,
+**        returns    YES     Success in opening file
+**                   NO      Failure 
+**
+*/
+
+PUBLIC BOOL HTLoadDocument ARGS3(HTParentAnchor *,anchor,
+       CONST char *,full_address,
+       BOOL,   filter)
+
+{
+    int                new_file_number;
+    HTFormat    format;
+    HText *    text;
+
+    if (text=(HText *)HTAnchor_document(anchor)) {     /* Already loaded */
+#ifdef ERWISE
+        /*
+         * do NOT do this
+         */
+        fprintf(stderr, "HTBrowse: Document already in memory.\n");
+
+        WWWErwiseStatus = CL_ALREADY_LOADED;
+
+        return YES;
+#else
+        if (TRACE) fprintf(stderr, "HTBrowse: Document already in memory.\n");
+        HText_select(text);
+       return YES;
+#endif
+    }
+    
+#ifdef CURSES
+      prompt_set("Retrieving document...");
+#endif
+    if (filter) {
+        new_file_number = 0;
+       format = WWW_HTML;
+    } else {
+       new_file_number = HTOpen(full_address, &format, anchor);
+    }
+/*     Log the access if necessary
+*/
+    if (logfile) {
+       time_t theTime;
+       time(&theTime);
+       fprintf(logfile, "%24.24s %s %s %s\n",
+           ctime(&theTime),
+           HTClientHost ? HTClientHost : "local",
+           new_file_number<0 ? "FAIL" : "GET",
+           full_address);
+       fflush(logfile);        /* Actually update it on disk */
+       if (TRACE) fprintf(stderr, "Log: %24.24s %s %s %s\n",
+           ctime(&theTime),
+           HTClientHost ? HTClientHost : "local",
+           new_file_number<0 ? "FAIL" : "GET",
+           full_address);
+    }
+    
+
+    if (new_file_number == HT_LOADED) {
+       if (TRACE) {
+           printf("HTAccess: `%s' has been accessed.\n",
+           full_address);
+       }
+#ifdef ERWISE
+        WWWErwiseStatus = CL_COMPLETED;
+        WWWErwiseConnection->fd = -1;
+#endif
+       return YES;
+    }
+    
+    if (new_file_number == HT_NO_DATA) {
+       if (TRACE) {
+           printf("HTAccess: `%s' has been accessed, No data left.\n",
+           full_address);
+       }
+#ifdef ERWISE
+        WWWErwiseStatus = CL_FAILED;
+#endif
+       return NO;
+    }
+    
+    if (new_file_number<0) {                 /* Failure in accessing a file */
+
+#ifdef CURSES
+        user_message("Can't access `%s'", full_address);
+#else
+       printf("\nWWW: Can't access `%s'\n", full_address);
+#endif
+#ifdef ERWISE
+        WWWErwiseStatus = CL_FAILED;
+        return NO;
+#endif
+       if (!HTMainText){
+            exit(2);                           /* Can't get first page */
+        } else {
+            return NO;
+        }
+    }
+    
+    if (TRACE) {
+       printf("WWW: Opened `%s' as fd %d\n",
+       full_address, new_file_number);
+    }
+
+#ifdef ERWISE
+    /*
+     * Do the rest elsewhere (if this connection can be loaded
+     * using non blocking transfer)
+     */
+
+    if(WWWErwiseConnection->function) {
+        WWWErwiseConnection->fd = new_file_number;
+
+        return YES;
+    }
+#endif
+
+    HTParseFormat(HTDiag ? WWW_PLAINTEXT : format, anchor, new_file_number);
+    
+    HTClose(new_file_number);
+    
+    return YES;
+    
+} /* HTLoadDocument */
+
+
+/*             Load a document from absolute name
+**             ---------------
+**
+**    On Entry,
+**        relative_name     The relative address of the file to be accessed.
+**
+**    On Exit,
+**        returns    YES     Success in opening file
+**                   NO      Failure 
+**
+**
+*/
+
+PUBLIC BOOL HTLoadAbsolute ARGS2(CONST char *,addr, BOOL, filter)
+{
+   return HTLoadDocument(
+                       HTAnchor_parent(HTAnchor_findAddress(addr)),
+                       addr, filter);
+}
+
+
+/*             Load a document from relative name
+**             ---------------
+**
+**    On Entry,
+**        relative_name     The relative address of the file to be accessed.
+**
+**    On Exit,
+**        returns    YES     Success in opening file
+**                   NO      Failure 
+**
+**
+*/
+
+PUBLIC BOOL HTLoadRelative ARGS1(CONST char *,relative_name)
+{
+    char *             full_address = 0;
+    BOOL                       result;
+    char *             mycopy = 0;
+    char *             stripped = 0;
+    char *             current_address =
+                               HTAnchor_address((HTAnchor*)HTMainAnchor);
+
+    StrAllocCopy(mycopy, relative_name);
+
+    stripped = HTStrip(mycopy);
+    full_address = HTParse(stripped,
+                  current_address,
+                  PARSE_ACCESS|PARSE_HOST|PARSE_PATH|PARSE_PUNCTUATION);
+    result = HTLoadAbsolute(full_address, NO);
+    free(full_address);
+    free(current_address);
+    return result;
+}
+
+
+/*             Load if necessary, and select an anchor
+**             --------------------------------------
+**
+**    On Entry,
+**        destination              The child or parenet anchor to be loaded.
+**
+**    On Exit,
+**        returns    YES     Success
+**                   NO      Failure 
+**
+*/
+
+PUBLIC BOOL HTLoadAnchor ARGS1(HTAnchor *,destination)
+{
+    HTParentAnchor * parent;
+
+    if (!destination) return NO;       /* No link */
+    
+    parent  = HTAnchor_parent(destination);
+    
+    if ( /* HTAnchor_document (parent) == NULL) { */ parent != HTMainAnchor)   {       /* If not already loaded */
+        BOOL result;
+        char * address = HTAnchor_address((HTAnchor*) parent);
+       result = HTLoadDocument(parent, address, NO);
+       free(address);
+       if (!result) return NO;
+    }
+    
+    if (destination != (HTAnchor *)parent)     /* If child anchor */
+        HText_selectAnchor(HTMainText, 
+               (HTChildAnchor*)destination); /* Double display? @@ */
+               
+    return YES;
+       
+} /* HTLoadAnchor */
+
+
+#ifndef ERWISE
+/*             Search
+**             ------
+**  Performs a keyword search on word given by the user. Adds the keyword to 
+**  the end of the current address and attempts to open the new address.
+**
+**  On Entry,
+**       *keywords     space-separated keyword list or similar search list
+**     HTMainAnchor    global must be valid.
+*/
+
+PUBLIC BOOL HTSearch ARGS1(char *,keywords)
+
+{
+    char * p;            /* pointer to first non-blank */
+    char * q, *s;
+    char * address = HTAnchor_address((HTAnchor*)HTMainAnchor);
+    BOOL result;
+    
+    p = HTStrip(keywords);
+    for (q=p; *q; q++)
+        if (WHITE(*q)) {
+           *q = '+';
+       }
+
+    s=strchr(address, '?');            /* Find old search string */
+    if (s) *s = 0;                             /* Chop old search off */
+
+    StrAllocCat(address, "?");
+    StrAllocCat(address, p);
+
+    result = HTLoadRelative(address);
+    free(address);
+    return result;
+    
+}
+#else /* ERWISE */
+
+/*
+ * Why everything is so hardcoded ???? 
+ */
+
+PUBLIC char *HTSearchAddress ARGS1(char *,keywords)
+{
+    char * p;             /* pointer to first non-blank */
+    char * q, *s;
+    char * address = HTAnchor_address((HTAnchor*)HTMainAnchor);
+    char * current_address;
+    char * mycopy;
+    char * stripped;
+    char * full_address;
+
+    
+    p = HTStrip(keywords);
+    for (q=p; *q; q++)
+        if (WHITE(*q)) {
+            *q = '+';
+        }
+
+    s=strchr(address, '?');             /* Find old search string */
+    if (s) *s = 0;                              /* Chop old search off */
+
+    StrAllocCat(address, "?");
+    StrAllocCat(address, p);
+
+    StrAllocCopy(mycopy, address);
+    
+    current_address = HTAnchor_address((HTAnchor*)HTMainAnchor);
+
+    stripped = HTStrip(mycopy);
+
+    full_address = HTParse(stripped,
+                   current_address,
+                   PARSE_ACCESS|PARSE_HOST|PARSE_PATH|PARSE_PUNCTUATION);
+
+    free(address);
+    
+    return full_address;
+}
+
+#endif /* ERWISE */
+
diff --git a/Cl/WWWLibrary/HTAccess.h b/Cl/WWWLibrary/HTAccess.h
new file mode 100644 (file)
index 0000000..ecbc165
--- /dev/null
@@ -0,0 +1,114 @@
+/*             Access Manager                                  HTAccess.h
+**             ==============
+*/
+
+#ifndef HTACCESS_H
+#define HTACCESS_H
+
+/*     Flag to allow source to be loaded as text
+*/
+extern int HTDiag;
+
+/*     Open a file descriptor for a document
+**     -------------------------------------
+**
+** On entry,
+**     addr            must point to the fully qualified hypertext reference.
+**
+** On exit,
+**     returns         <0      Error has occured.
+**                     >=0     Value of file descriptor or socket to be used
+**                              to read data.
+**     *pFormat        Set to the format of the file, if known.
+**                     (See WWW.h)
+**
+** No longer public -- only used internally.
+*/
+/* extern int HTOpen PARAMS((CONST char * addr, HTFormat * format)); */
+
+
+/*     Close socket opened for reading a file
+**     --------------------------------------
+**
+*/
+extern int HTClose PARAMS((int soc));
+
+
+/*             Load a document
+**             ---------------
+**
+**    On Entry,
+**       anchor            is the node_anchor for the document
+**        full_address      The address of the file to be accessed.
+**
+**    On Exit,
+**        returns    YES     Success in opening file
+**                   NO      Failure 
+**
+*/
+
+extern BOOL HTLoadDocument PARAMS((HTParentAnchor * anchor,
+       CONST char * full_address,
+       BOOL    filter));
+
+
+
+/*             Load a document from relative name
+**             ---------------
+**
+**    On Entry,
+**        relative_name     The relative address of the file to be accessed.
+**
+**    On Exit,
+**        returns    YES     Success in opening file
+**                   NO      Failure 
+**
+**
+*/
+
+extern  BOOL HTLoadRelative PARAMS((CONST char * relative_name));
+
+/*             Load a document from relative name
+**             ---------------
+**
+**    On Entry,
+**        relative_name     The relative address of the file to be accessed.
+**
+**    On Exit,
+**        returns    YES     Success in opening file
+**                   NO      Failure 
+**
+**
+*/
+
+extern BOOL HTLoadAbsolute PARAMS((CONST char * addr, BOOL filter));
+
+
+/*             Load if necessary, and select an anchor
+**             --------------------------------------
+**
+**    On Entry,
+**        destination              The child or parenet anchor to be loaded.
+**
+**    On Exit,
+**        returns    YES     Success
+**                   NO      Failure 
+**
+*/
+
+extern BOOL HTLoadAnchor PARAMS((HTAnchor * destination));
+
+/*             Search
+**             ------
+**  Performs a keyword search on word given by the user. Adds the keyword to 
+**  the end of the current address and attempts to open the new address.
+**
+**  On Entry,
+**       *keywords     space-separated keyword list or similar search list
+**     HTMainAnchor    global must be valid.
+*/
+
+extern BOOL HTSearch PARAMS((char * keywords));
+
+
+#endif /* HTACCESS_H */
diff --git a/Cl/WWWLibrary/HTAnchor.c b/Cl/WWWLibrary/HTAnchor.c
new file mode 100644 (file)
index 0000000..d5a0053
--- /dev/null
@@ -0,0 +1,487 @@
+/*     Hypertext "Anchor" Object                               HTAnchor.c
+**     ==========================
+**
+** An anchor represents a region of a hypertext document which is linked to
+** another anchor in the same or a different document.
+**
+** History
+**
+**         Nov 1990  Written in Objective-C for the NeXT browser (TBL)
+**     24-Oct-1991 (JFG), written in C, browser-independant 
+**     21-Nov-1991 (JFG), first complete version
+**
+**     (c) Copyright CERN 1991 - See Copyright.html
+*/
+
+#define HASH_SIZE 101          /* Arbitrary prime. Memory/speed tradeoff */
+
+#include <ctype.h>
+#include "tcp.h"
+#include "HTAnchor.h"
+#include "HTUtils.h"
+#include "HTParse.h"
+
+typedef struct _HyperDoc Hyperdoc;
+#ifdef vms
+struct _HyperDoc {
+       int junk;       /* VMS cannot handle pointers to undefined structs */
+};
+#endif
+
+PRIVATE HTList **adult_table=0;  /* Point to table of lists of all parents */
+
+/*                             Creation Methods
+**                             ================
+**
+**     Do not use "new" by itself outside this module. In order to enforce
+**     consistency, we insist that you furnish more information about the
+**     anchor you are creating : use newWithParent or newWithAddress.
+*/
+
+PRIVATE HTParentAnchor * HTParentAnchor_new
+  NOARGS
+{
+  HTParentAnchor *newAnchor = 
+    (HTParentAnchor *) calloc (1, sizeof (HTParentAnchor));  /* zero-filled */
+  newAnchor->parent = newAnchor;
+  return newAnchor;
+}
+
+PRIVATE HTChildAnchor * HTChildAnchor_new
+  NOARGS
+{
+  return (HTChildAnchor *) calloc (1, sizeof (HTChildAnchor));  /* zero-filled */
+}
+
+
+/*     Case insensitive string comparison
+**     ----------------------------------
+** On entry,
+**     s       Points to one string, null terminated
+**     t       points to the other.
+** On exit,
+**     returns YES if the strings are equivalent ignoring case
+**             NO if they differ in more than  their case.
+*/
+
+PRIVATE BOOL equivalent
+  ARGS2 (CONST char *,s, CONST char *,t)
+{
+  if (s && t) {  /* Make sure they point to something */
+    for ( ; *s && *t ; s++, t++) {
+        if (TOUPPER(*s) != TOUPPER(*t))
+         return NO;
+    }
+    return TOUPPER(*s) == TOUPPER(*t);
+  } else
+    return s == t;  /* Two NULLs are equivalent, aren't they ? */
+}
+
+
+/*     Create new or find old sub-anchor
+**     ---------------------------------
+**
+**     This one is for a new anchor being edited into an existing
+**     document. The parent anchor must already exist.
+*/
+
+PRIVATE HTChildAnchor * HTAnchor_findChild
+  ARGS2 (HTParentAnchor *,parent, CONST char *,tag)
+{
+  HTChildAnchor *child;
+  HTList *kids;
+
+  if (! parent) {
+    if (TRACE) printf ("HTAnchor_findChild called with NULL parent.\n");
+    return NULL;
+  }
+  if (kids = parent->children) {  /* parent has children : search them */
+    if (tag && *tag) {         /* TBL */
+       while (child = HTList_nextObject (kids)) {
+           if (equivalent(child->tag, tag)) { /* Case sensitive 920226 */
+               if (TRACE) printf (
+              "Child anchor %p of parent %p with name `%s' already exists.\n",
+                   child, parent, tag);
+               return child;
+           }
+       }
+     }  /*  end if tag is void */
+  } else  /* parent doesn't have any children yet : create family */
+    parent->children = HTList_new ();
+
+  child = HTChildAnchor_new ();
+  if (TRACE) printf("new Anchor %p named `%s' is child of %p\n",
+                  child, (int)tag ? tag : (CONST char *)"" , parent); /* int for apollo */
+  HTList_addObject (parent->children, child);
+  child->parent = parent;
+  StrAllocCopy(child->tag, tag);
+  return child;
+}
+
+
+/*     Create or find a child anchor with a possible link
+**     --------------------------------------------------
+**
+**     Create new anchor with a given parent and possibly
+**     a name, and possibly a link to a _relatively_ named anchor.
+**     (Code originally in ParseHTML.h)
+*/
+PUBLIC HTChildAnchor * HTAnchor_findChildAndLink
+  ARGS4(
+       HTParentAnchor *,parent,        /* May not be 0 */
+       CONST char *,tag,       /* May be "" or 0 */
+       CONST char *,href,      /* May be "" or 0 */
+       HTLinkType *,ltype      /* May be 0 */
+       )
+{
+  HTChildAnchor * child = HTAnchor_findChild(parent, tag);
+  if (href && *href) {
+    char * parsed_address;
+    HTAnchor * dest;
+    parsed_address = HTParse(href, HTAnchor_address((HTAnchor *) parent),
+                            PARSE_ALL);
+    dest = HTAnchor_findAddress(parsed_address);
+    HTAnchor_link((HTAnchor *) child, dest, ltype);
+    free(parsed_address);
+  }
+  return child;
+}
+
+
+/*     Create new or find old named anchor
+**     -----------------------------------
+**
+**     This one is for a reference which is found in a document, and might
+**     not be already loaded.
+**     Note: You are not guaranteed a new anchor -- you might get an old one,
+**     like with fonts.
+*/
+
+HTAnchor * HTAnchor_findAddress
+  ARGS1 (CONST char *,address)
+{
+  char *tag = HTParse (address, "", PARSE_ANCHOR);  /* Anchor tag specified ? */
+
+  /* If the address represents a sub-anchor, we recursively load its parent,
+     then we create a child anchor within that document. */
+  if (*tag) {
+    char *docAddress = HTParse(address, "", PARSE_ACCESS | PARSE_HOST |
+                                           PARSE_PATH | PARSE_PUNCTUATION);
+    HTParentAnchor * foundParent =
+      (HTParentAnchor *) HTAnchor_findAddress (docAddress);
+    HTChildAnchor * foundAnchor = HTAnchor_findChild (foundParent, tag);
+    free (docAddress);
+    free (tag);
+    return (HTAnchor *) foundAnchor;
+  }
+  
+  else { /* If the address has no anchor tag, check whether we have this node */
+    int hash;
+    CONST char *p;
+    HTList * adults;
+    HTList *grownups;
+    HTParentAnchor * foundAnchor;
+
+    free (tag);
+    
+    /* Select list from hash table */
+    for(p=address, hash=0; *p; p++) hash = (hash * 3 + *p) % HASH_SIZE;
+    if (!adult_table)
+        adult_table = (HTList**) calloc(HASH_SIZE, sizeof(HTList*));
+    if (!adult_table[hash]) adult_table[hash] = HTList_new();
+    adults = adult_table[hash];
+
+    /* Search list for anchor */
+    grownups = adults;
+    while (foundAnchor = HTList_nextObject (grownups)) {
+      if (equivalent(foundAnchor->address, address)) {
+       if (TRACE) printf("Anchor %p with address `%s' already exists.\n",
+                         foundAnchor, address);
+       return (HTAnchor *) foundAnchor;
+      }
+    }
+    
+    /* Node not found : create new anchor */
+    foundAnchor = HTParentAnchor_new ();
+    if (TRACE) printf("New anchor %p has hash %d and address `%s'\n",
+       foundAnchor, hash, address);
+    StrAllocCopy(foundAnchor->address, address);
+    HTList_addObject (adults, foundAnchor);
+    return (HTAnchor *) foundAnchor;
+  }
+}
+
+
+/*     Delete an anchor and possibly related things (auto garbage collection)
+**     --------------------------------------------
+**
+**     The anchor is only deleted if the corresponding document is not loaded.
+**     All outgoing links from parent and children are deleted, and this anchor
+**     is removed from the sources list of all its targets.
+**     We also try to delete the targets whose documents are not loaded.
+**     If this anchor's source list is empty, we delete it and its children.
+*/
+
+PRIVATE void deleteLinks
+  ARGS1 (HTAnchor *,this)
+{
+  if (! this)
+    return;
+
+  /* Recursively try to delete target anchors */
+  if (this->mainLink.dest) {
+    HTParentAnchor *parent = this->mainLink.dest->parent;
+    HTList_removeObject (parent->sources, this);
+    if (! parent->document)  /* Test here to avoid calling overhead */
+      HTAnchor_delete (parent);
+  }
+  if (this->links) {  /* Extra destinations */
+    HTLink *target;
+    while (target = HTList_removeLastObject (this->links)) {
+      HTParentAnchor *parent = target->dest->parent;
+      HTList_removeObject (parent->sources, this);
+      if (! parent->document)  /* Test here to avoid calling overhead */
+       HTAnchor_delete (parent);
+    }
+  }
+}
+
+PUBLIC BOOL HTAnchor_delete
+  ARGS1 (HTParentAnchor *,this)
+{
+  HTChildAnchor *child;
+
+  /* Don't delete if document is loaded */
+  if (this->document)
+    return NO;
+
+  /* Recursively try to delete target anchors */
+  deleteLinks ((HTAnchor *) this);
+
+  if (! HTList_isEmpty (this->sources)) {  /* There are still incoming links */
+    /* Delete all outgoing links from children, if any */
+    HTList *kids = this->children;
+    while (child = HTList_nextObject (kids))
+      deleteLinks ((HTAnchor *) child);
+    return NO;  /* Parent not deleted */
+  }
+
+  /* No more incoming links : kill everything */
+  /* First, recursively delete children */
+  while (child = HTList_removeLastObject (this->children)) {
+    deleteLinks ((HTAnchor *) child);
+    free (child->tag);
+    free (child);
+  }
+
+  /* Now kill myself */
+  HTList_delete (this->children);
+  HTList_delete (this->sources);
+  free (this->address);
+  /* Devise a way to clean out the HTFormat if no longer needed (ref count?) */
+  free (this);
+  return YES;  /* Parent deleted */
+}
+
+
+/*             Move an anchor to the head of the list of its siblings
+**             ------------------------------------------------------
+**
+**     This is to ensure that an anchor which might have already existed
+**     is put in the correct order as we load the document.
+*/
+
+void HTAnchor_makeLastChild
+  ARGS1(HTChildAnchor *,this)
+{
+  if (this->parent != (HTParentAnchor *) this) {  /* Make sure it's a child */
+    HTList * siblings = this->parent->children;
+    HTList_removeObject (siblings, this);
+    HTList_addObject (siblings, this);
+  }
+}
+
+/*     Data access functions
+**     ---------------------
+*/
+
+extern HTParentAnchor * HTAnchor_parent
+  ARGS1 (HTAnchor *,this)
+{
+  return this ? this->parent : NULL;
+}
+
+void HTAnchor_setDocument
+  ARGS2 (HTParentAnchor *,this, HyperDoc *,doc)
+{
+  if (this)
+    this->document = doc;
+}
+
+HyperDoc * HTAnchor_document
+  ARGS1 (HTParentAnchor *,this)
+{
+  return this ? this->document : NULL;
+}
+
+
+/* We don't want code to change an address after anchor creation... yet ?
+void HTAnchor_setAddress
+  ARGS2 (HTAnchor *,this, char *,addr)
+{
+  if (this)
+    StrAllocCopy (this->parent->address, addr);
+}
+*/
+
+char * HTAnchor_address
+  ARGS1 (HTAnchor *,this)
+{
+  char *addr = NULL;
+  if (this) {
+    if (((HTParentAnchor *) this == this->parent) ||
+       !((HTChildAnchor *) this)->tag) {  /* it's an adult or no tag */
+      StrAllocCopy (addr, this->parent->address);
+    }
+    else {  /* it's a named child */
+      addr = malloc (2 + strlen (this->parent->address)
+                    + strlen (((HTChildAnchor *) this)->tag));
+      if (addr == NULL) outofmem(__FILE__, "HTAnchor_address");
+      sprintf (addr, "%s#%s", this->parent->address,
+              ((HTChildAnchor *) this)->tag);
+    }
+  }
+  return addr;
+}
+
+
+
+void HTAnchor_setFormat
+  ARGS2 (HTParentAnchor *,this, HTFormat *,form)
+{
+  if (this)
+    this->format = form;
+}
+
+HTFormat * HTAnchor_format
+  ARGS1 (HTParentAnchor *,this)
+{
+  return this ? this->format : NULL;
+}
+
+
+
+void HTAnchor_setIndex
+  ARGS1 (HTParentAnchor *,this)
+{
+  if (this)
+    this->isIndex = YES;
+}
+
+BOOL HTAnchor_isIndex
+  ARGS1 (HTParentAnchor *,this)
+{
+  return this ? this->isIndex : NO;
+}
+
+
+
+BOOL HTAnchor_hasChildren
+  ARGS1 (HTParentAnchor *,this)
+{
+  return this ? ! HTList_isEmpty(this->children) : NO;
+}
+
+/*     Title handling
+*/
+CONST char * HTAnchor_title
+  ARGS1 (HTParentAnchor *,this)
+{
+  return this ? this->title : 0;
+}
+
+void HTAnchor_setTitle
+  ARGS2(HTParentAnchor *,this, CONST char *,title)
+{
+  StrAllocCopy(this->title, title);
+}
+
+void HTAnchor_appendTitle
+  ARGS2(HTParentAnchor *,this, CONST char *,title)
+{
+  StrAllocCat(this->title, title);
+}
+
+/*     Link this Anchor to another given one
+**     -------------------------------------
+*/
+
+BOOL HTAnchor_link
+  ARGS3(HTAnchor *,source, HTAnchor *,destination, HTLinkType *,type)
+{
+  if (! (source && destination))
+    return NO;  /* Can't link to/from non-existing anchor */
+  if (TRACE) printf ("Linking anchor %p to anchor %p\n", source, destination);
+  if (! source->mainLink.dest) {
+    source->mainLink.dest = destination;
+    source->mainLink.type = type;
+  } else {
+    HTLink * newLink = (HTLink *) malloc (sizeof (HTLink));
+    if (newLink == NULL) outofmem(__FILE__, "HTAnchor_link");
+    newLink->dest = destination;
+    newLink->type = type;
+    if (! source->links)
+      source->links = HTList_new ();
+    HTList_addObject (source->links, newLink);
+  }
+  if (!destination->parent->sources)
+    destination->parent->sources = HTList_new ();
+  HTList_addObject (destination->parent->sources, source);
+  return YES;  /* Success */
+}
+
+
+/*     Manipulation of links
+**     ---------------------
+*/
+
+HTAnchor * HTAnchor_followMainLink
+  ARGS1 (HTAnchor *,this)
+{
+  return this->mainLink.dest;
+}
+
+HTAnchor * HTAnchor_followTypedLink
+  ARGS2 (HTAnchor *,this, HTLinkType *,type)
+{
+  if (this->mainLink.type == type)
+    return this->mainLink.dest;
+  if (this->links) {
+    HTList *links = this->links;
+    HTLink *link;
+    while (link = HTList_nextObject (links))
+      if (link->type == type)
+       return link->dest;
+  }
+  return NULL;  /* No link of this type */
+}
+
+BOOL HTAnchor_makeMainLink
+  ARGS2 (HTAnchor *,this, HTLink *,movingLink)
+{
+  /* Check that everything's OK */
+  if (! (this && HTList_removeObject (this->links, movingLink)))
+    return NO;  /* link not found or NULL anchor */
+  else {
+    /* First push current main link onto top of links list */
+    HTLink *newLink = (HTLink*) malloc (sizeof (HTLink));
+    if (newLink == NULL) outofmem(__FILE__, "HTAnchor_makeMainLink");
+    memcpy (newLink, & this->mainLink, sizeof (HTLink));
+    HTList_addObject (this->links, newLink);
+
+    /* Now make movingLink the new main link, and free it */
+    memcpy (& this->mainLink, movingLink, sizeof (HTLink));
+    free (movingLink);
+    return YES;
+  }
+}
diff --git a/Cl/WWWLibrary/HTAnchor.h b/Cl/WWWLibrary/HTAnchor.h
new file mode 100644 (file)
index 0000000..63f2f97
--- /dev/null
@@ -0,0 +1,265 @@
+/*     Hypertext "Anchor" Object                                    HTAnchor.h
+**     ==========================
+**
+**     An anchor represents a region of a hypertext document which is linked
+**     to another anchor in the same or a different document.
+*/
+
+#ifndef HTANCHOR_H
+#define HTANCHOR_H
+
+/* Version 0 (TBL) written in Objective-C for the NeXT browser */
+/* Version 1 of 24-Oct-1991 (JFG), written in C, browser-independant */
+
+#include "HTList.h"
+#include "HTAtom.h"
+
+#ifdef SHORT_NAMES
+#define HTAnchor_findChild                     HTAnFiCh
+#define HTAnchor_findChildAndLink              HTAnFiLi
+#define HTAnchor_findAddress                   HTAnFiAd
+#define HTAnchor_delete                                HTAnDele
+#define HTAnchor_makeLastChild                 HTAnMaLa
+#define HTAnchor_parent                                HTAnPare
+#define HTAnchor_setDocument                   HTAnSeDo
+#define HTAnchor_document                      HTAnDocu
+#define HTAnchor_setFormat                     HTAnSeFo
+#define HTAnchor_format                                HTAnForm
+#define HTAnchor_setIndex                      HTAnSeIn
+#define HTAnchor_isIndex                       HTAnIsIn
+#define HTAnchor_address                       HTAnAddr
+#define HTAnchor_hasChildren                   HTAnHaCh
+#define HTAnchor_title                         HTAnTitl
+#define HTAnchor_setTitle                      HTAnSeTi
+#define HTAnchor_appendTitle                   HTAnApTi
+#define HTAnchor_link                          HTAnLink
+#define HTAnchor_followMainLink                        HTAnFoMa
+#define HTAnchor_followTypedLink               HTAnFoTy
+#define HTAnchor_makeMainLink                  HTAnMaMa
+#endif
+
+/*                     Main definition of anchor
+**                     =========================
+*/
+
+typedef struct _HyperDoc HyperDoc;  /* Ready for forward references */
+typedef struct _HTAnchor HTAnchor;
+typedef struct _HTParentAnchor HTParentAnchor;
+
+#include "HTFormat.h"
+
+typedef HTAtom HTLinkType;
+
+typedef struct {
+  HTAnchor *   dest;           /* The anchor to which this leads */
+  HTLinkType * type;           /* Semantics of this link */
+} HTLink;
+
+struct _HTAnchor {             /* Generic anchor : just links */
+  HTLink       mainLink;       /* Main (or default) destination of this */
+  HTList *     links;          /* List of extra links from this, if any */
+  /* We separate the first link from the others to avoid too many small mallocs
+     involved by a list creation. Most anchors only point to one place. */
+  HTParentAnchor * parent;     /* Parent of this anchor (self for adults) */
+};
+
+struct _HTParentAnchor {
+  /* Common part from the generic anchor structure */
+  HTLink       mainLink;       /* Main (or default) destination of this */
+  HTList *     links;          /* List of extra links from this, if any */
+  HTParentAnchor * parent;     /* Parent of this anchor (self) */
+
+  /* ParentAnchor-specific information */
+  HTList *     children;       /* Subanchors of this, if any */
+  HTList *     sources;        /* List of anchors pointing to this, if any */
+  HyperDoc *   document;       /* The document within which this is an anchor */
+  char *       address;        /* Absolute address of this node */
+  HTFormat *   format;         /* Pointer to node format descriptor */
+  BOOL         isIndex;        /* Acceptance of a keyword search */
+  char *       title;          /* Title of document */
+};
+
+typedef struct {
+  /* Common part from the generic anchor structure */
+  HTLink       mainLink;       /* Main (or default) destination of this */
+  HTList *     links;          /* List of extra links from this, if any */
+  HTParentAnchor * parent;     /* Parent of this anchor */
+
+  /* ChildAnchor-specific information */
+  char *       tag;            /* Address of this anchor relative to parent */
+} HTChildAnchor;
+
+
+/*     Create new or find old sub-anchor
+**     ---------------------------------
+**
+**     This one is for a new anchor being edited into an existing
+**     document. The parent anchor must already exist.
+*/
+
+extern HTChildAnchor * HTAnchor_findChild
+  PARAMS(
+     (HTParentAnchor *parent,
+      CONST char *tag)
+  );
+
+/*     Create or find a child anchor with a possible link
+**     --------------------------------------------------
+**
+**     Create new anchor with a given parent and possibly
+**     a name, and possibly a link to a _relatively_ named anchor.
+**     (Code originally in ParseHTML.h)
+*/
+extern HTChildAnchor * HTAnchor_findChildAndLink
+  PARAMS((
+      HTParentAnchor * parent, /* May not be 0 */
+      CONST char * tag,         /* May be "" or 0 */
+      CONST char * href,       /* May be "" or 0 */
+      HTLinkType * ltype       /* May be 0 */
+  ));
+
+
+/*     Create new or find old named anchor
+**     -----------------------------------
+**
+**     This one is for a reference which is found in a document, and might
+**     not be already loaded.
+**     Note: You are not guaranteed a new anchor -- you might get an old one,
+**     like with fonts.
+*/
+
+extern HTAnchor * HTAnchor_findAddress
+  PARAMS(
+     (CONST char * address)
+     );
+
+
+/*     Delete an anchor and possibly related things (auto garbage collection)
+**     --------------------------------------------
+**
+**     The anchor is only deleted if the corresponding document is not loaded.
+**     All outgoing links from parent and children are deleted, and this anchor
+**     is removed from the sources list of all its targets.
+**     We also try to delete the targets whose documents are not loaded.
+**     If this anchor's source list is empty, we delete it and its children.
+*/
+
+extern BOOL HTAnchor_delete
+  PARAMS(
+     (HTParentAnchor *this)
+     );
+
+
+/*             Move an anchor to the head of the list of its siblings
+**             ------------------------------------------------------
+**
+**     This is to ensure that an anchor which might have already existed
+**     is put in the correct order as we load the document.
+*/
+
+extern void HTAnchor_makeLastChild
+  PARAMS(
+     (HTChildAnchor *this)
+     );
+
+/*     Data access functions
+**     ---------------------
+*/
+
+extern HTParentAnchor * HTAnchor_parent
+  PARAMS(
+     (HTAnchor *this)
+     );
+
+extern void HTAnchor_setDocument
+  PARAMS(
+     (HTParentAnchor *this, HyperDoc *doc)
+     );
+
+extern HyperDoc * HTAnchor_document
+  PARAMS(
+     (HTParentAnchor *this)
+     );
+/* We don't want code to change an address after anchor creation... yet ?
+extern void HTAnchor_setAddress
+  PARAMS(
+     (HTAnchor *this, char *addr)
+     );
+*/
+
+extern char * HTAnchor_address
+  PARAMS(
+     (HTAnchor *this)
+     );
+
+extern void HTAnchor_setFormat
+  PARAMS(
+     (HTParentAnchor *this, HTFormat *form)
+     );
+
+extern HTFormat * HTAnchor_format
+  PARAMS(
+     (HTParentAnchor *this)
+     );
+
+extern void HTAnchor_setIndex
+  PARAMS(
+     (HTParentAnchor *this)
+     );
+
+extern BOOL HTAnchor_isIndex
+  PARAMS(
+     (HTParentAnchor *this)
+     );
+
+extern BOOL HTAnchor_hasChildren
+  PARAMS(
+     (HTParentAnchor *this)
+     );
+
+/*     Title handling
+*/
+extern CONST char * HTAnchor_title
+  PARAMS(
+     (HTParentAnchor *this)
+     );
+
+extern void HTAnchor_setTitle
+  PARAMS(
+     (HTParentAnchor *this, CONST char * title)
+     );
+
+extern void HTAnchor_appendTitle
+  PARAMS(
+     (HTParentAnchor *this, CONST char * title)
+     );
+
+/*     Link this Anchor to another given one
+**     -------------------------------------
+*/
+
+extern BOOL HTAnchor_link
+  PARAMS(
+     (HTAnchor *source, HTAnchor *destination, HTLinkType *type)
+     );
+
+/*     Manipulation of links
+**     ---------------------
+*/
+
+extern HTAnchor * HTAnchor_followMainLink
+  PARAMS(
+     (HTAnchor *this)
+     );
+
+extern HTAnchor * HTAnchor_followTypedLink
+  PARAMS(
+     (HTAnchor *this, HTLinkType *type)
+     );
+
+extern BOOL HTAnchor_makeMainLink
+  PARAMS(
+     (HTAnchor *this, HTLink *movingLink)
+     );
+
+#endif /* HTANCHOR_H */
diff --git a/Cl/WWWLibrary/HTAtom.c b/Cl/WWWLibrary/HTAtom.c
new file mode 100644 (file)
index 0000000..44a099f
--- /dev/null
@@ -0,0 +1,74 @@
+/*                     Atoms: Names to numbers                 HTAtom.c
+**                     =======================
+**
+**     Atoms are names which are given representative pointer values
+**     so that they can be stored more efficiently, and comparisons
+**     for equality done more efficiently.
+**
+**     Atoms are kept in a hash table consisting of an array of linked lists.
+**
+** Authors:
+**     TBL     Tim Berners-Lee, WorldWideWeb project, CERN
+**     (c) Copyright CERN 1991 - See Copyright.html
+**
+*/
+#define HASH_SIZE      101             /* Tunable */
+#include "HTUtils.h"
+#include "HTAtom.h"
+
+#ifdef ERWISE
+#include <stdio.h>
+#endif
+
+PRIVATE HTAtom * hash_table[HASH_SIZE];
+PRIVATE BOOL initialised = NO;
+
+#ifdef __STDC__
+PUBLIC HTAtom * HTAtom_for(const char * string)
+#else
+PUBLIC HTAtom * HTAtom_for(string)
+    char * string;
+#endif
+{
+    int hash;
+    CONST char * p;
+    HTAtom * a;
+    
+    /*         First time around, clear hash table
+    */
+    if (!initialised) {
+        int i;
+       for (i=0; i<HASH_SIZE; i++)
+           hash_table[i] = (HTAtom *) 0;
+       initialised = YES;
+    }
+    
+    /*         Generate hash function
+    */
+    for(p=string, hash=0; *p; p++) {
+        hash = (hash * 3 + *p) % HASH_SIZE;
+    }
+    
+    /*         Search for the string in the list
+    */
+    for (a=hash_table[hash]; a; a=a->next) {
+       if (0==strcmp(a->name, string)) {
+           if (TRACE) printf("HTAtom: Old atom %d for `&s'\n", a, string);
+           return a;                           /* Found: return it */
+       }
+    }
+    
+    /*         Generate a new entry
+    */
+    a = (HTAtom *)malloc(sizeof(*a));
+    if (a == NULL) outofmem(__FILE__, "HTAtom_for");
+    a->name = (char *)malloc(strlen(string)+1);
+    if (a->name == NULL) outofmem(__FILE__, "HTAtom_for");
+    strcpy(a->name, string);
+    a->next = hash_table[hash];                /* Put onto the head of list */
+    hash_table[hash] = a;
+    if (TRACE) printf("HTAtom: New atom %d for `&s'\n", a, string);
+    return a;
+}
+
+
diff --git a/Cl/WWWLibrary/HTAtom.h b/Cl/WWWLibrary/HTAtom.h
new file mode 100644 (file)
index 0000000..2ebef26
--- /dev/null
@@ -0,0 +1,36 @@
+/*                     Atoms: Names to numbers                 HTAtom.h
+**                     =======================
+**
+**     Atoms are names which are given representative pointer values
+**     so that they can be stored more efficiently, and compaisons
+**     for equality done more efficiently.
+**
+**     HTAtom_for(string) returns a representative value such that it
+**     will always (within one run of the program) return the same
+**     value for the same given string.
+**
+** Authors:
+**     TBL     Tim Berners-Lee, WorldWideWeb project, CERN
+**
+**     (c) Copyright CERN 1991 - See Copyright.html
+**
+*/
+
+#ifndef HTATOM_H
+#define HTATOM_H
+
+typedef struct _HTAtom HTAtom;
+struct _HTAtom {
+       HTAtom *        next;
+       char *          name;
+}; /* struct _HTAtom */
+
+#ifdef __STDC__
+extern HTAtom * HTAtom_for(const char * string);
+#else
+extern HTAtom * HTAtom_for();
+#endif
+
+#define HTAtom_name(a) ((a)->name)
+
+#endif /* HTATOM_H */
diff --git a/Cl/WWWLibrary/HTBrowse.h b/Cl/WWWLibrary/HTBrowse.h
new file mode 100644 (file)
index 0000000..781015e
--- /dev/null
@@ -0,0 +1,36 @@
+/*             Declarations of things available from HTBrowse.c
+**             ------------------------------------------------
+**
+**     HTBrowse.c, the main program of a line mode browser,  leaves various
+**     public variables atteh disposal of its submodules.
+*/
+
+#ifndef HTBROWSE_H
+#define HTBROWSE_H
+
+#include "tcp.h"
+
+#ifdef SHORT_NAMES
+#define HTScreenHeight                 HTScHeig
+#define HTScreenWidth                  HTScWidt
+#define HTClientHost                   HTClHost
+#define display_anchors                        HTDiAnch
+#define interactive                    HTIntera
+#define reference_mark                 HTReMark
+#endif
+
+extern  int  WWW_TraceFlag;            /* Off unless -v option given */
+extern  int  HTScreenWidth;            /* By default */
+extern  int  HTScreenHeight;           /* Undefined */
+extern BOOL  display_anchors;          /* anchor will be shown in text? */
+extern  BOOL interactive;              /*  e.g. shows prompts etc */
+
+                                          
+extern FILE * logfile;                 /* File to output one-liners to */
+
+extern char * HTClientHost;            /* Name or number of telnetting host */
+extern char * reference_mark;          /* Format string for  [1] &c */
+extern char * end_mark;                /* Format string for  [End] */
+
+#endif /* HTBROWSE_H */
diff --git a/Cl/WWWLibrary/HTChunk.c b/Cl/WWWLibrary/HTChunk.c
new file mode 100644 (file)
index 0000000..320ab9b
--- /dev/null
@@ -0,0 +1,84 @@
+/*             Chunk handling: Flexible arrays
+**             ===============================
+**
+*/
+
+#include "HTUtils.h"
+#include "HTChunk.h"
+#include <stdio.h>
+/*     Create a chunk with a certain allocation unit
+**     --------------
+*/
+PUBLIC HTChunk * HTChunkCreate ARGS1 (int,grow)
+{
+    HTChunk * ch = (HTChunk *) malloc(sizeof(HTChunk));
+    if (!ch) return 0;
+    ch->data = 0;
+    ch->growby = grow;
+    ch->size = 0;
+    ch->allocated = 0;
+    return ch;
+}
+
+
+/*     Clear a chunk of all data
+**     --------------------------
+*/
+PUBLIC void HTChunkClear ARGS1 (HTChunk *,ch)
+{
+    if (ch->data) {
+       free(ch->data);
+       ch->data = 0;
+    }
+    ch->size = 0;
+    ch->allocated = 0;
+}
+
+
+/*     Append a character
+**     ------------------
+*/
+PUBLIC void HTChunkPutc ARGS2 (HTChunk *,ch, char,c)
+{
+    if (ch->size >= ch->allocated) {
+       ch->allocated = ch->allocated + ch->growby;
+        ch->data = ch->data ? (char *)realloc(ch->data, ch->allocated)
+                           : (char *)malloc(ch->allocated);
+      if (!ch->data) outofmem(__FILE__, "HTChunkPutc");
+    }
+    ch->data[ch->size++] = c;
+}
+
+
+/*     Ensure a certain size
+**     ---------------------
+*/
+PUBLIC void HTChunkEnsure ARGS2 (HTChunk *,ch, int,needed)
+{
+    if (needed <= ch->allocated) return;
+    ch->allocated = needed-1 - ((needed-1) % ch->growby)
+                            + ch->growby; /* Round up */
+    ch->data = ch->data ? (char *)realloc(ch->data, ch->allocated)
+                       : (char *)malloc(ch->allocated);
+    if (ch->data == NULL) outofmem(__FILE__, "HTChunkEnsure");
+}
+
+
+/*     Terminate a chunk
+**     -----------------
+*/
+PUBLIC void HTChunkTerminate ARGS1 (HTChunk *,ch)
+{
+    HTChunkPutc(ch, (char)0);
+}
+
+
+/*     Append a string
+**     ---------------
+*/
+PUBLIC void HTChunkPuts ARGS2 (HTChunk *,ch, CONST char *,s)
+{
+    CONST char * p;
+    for (p=s; *p; p++)
+        HTChunkPutc(ch, *p);
+}
diff --git a/Cl/WWWLibrary/HTChunk.h b/Cl/WWWLibrary/HTChunk.h
new file mode 100644 (file)
index 0000000..a1da188
--- /dev/null
@@ -0,0 +1,97 @@
+/*             Chunk handling: Flexible arrays
+**             ===============================
+**
+** This module implements a flexible array. It is a general utility module.
+** A chunk is a structure which may be extended.  These routines create
+** and append data to chnuks, automatically reallocating them as necessary.
+**
+*/
+
+
+typedef struct {
+       int     size;           /* In bytes                     */
+       int     growby;         /* Allocation unit in bytes     */
+       int     allocated;      /* Current size of *data        */
+       char *  data;           /* Pointer to malloced area or 0 */
+} HTChunk;
+
+
+#ifdef SHORT_NAMES
+#define HTChunkClear           HTChClea
+#define HTChunkPutc            HTChPutc
+#define HTChunkPuts            HTChPuts
+#define HTChunkCreate          HTChCrea
+#define HTChunkTerminate       HTChTerm
+#define HTChunkEnsure          HtChEnsu
+#endif
+
+
+/*     Create new chunk
+**
+** On entry,
+**
+**     growby          The number of bytes to allocate at a time
+**                     when the chunk is later extended. Arbitrary but
+**                     normally a trade-off time vs. memory
+**
+** On exit,
+**     returns         A chunk pointer to the new chunk,
+*/
+extern HTChunk * HTChunkCreate PARAMS((int growby));
+
+
+/*     Clear a chunk
+**
+** On entry,
+**     ch      A valid chunk pointer made by HTChunkCreate()
+**
+** On exit,
+**     *ch     The size of the chunk is zero.
+*/
+extern void HTChunkClear PARAMS((HTChunk * ch));
+
+
+/*     Ensure a chunk has a certain space in
+**
+** On entry,
+**     ch      A valid chunk pointer made by HTChunkCreate()
+**     s       The size required
+**
+** On exit,
+**     *ch     Has size at least s
+*/
+extern void HTChunkEnsure PARAMS((HTChunk * ch, int s));
+
+
+/*     Append a character to a  chunk
+**
+** On entry,
+**     ch      A valid chunk pointer made by HTChunkCreate()
+**     c       The character to be appended
+** On exit,
+**     *ch     Is one character bigger
+*/
+
+extern void HTChunkPutc PARAMS((HTChunk * ch, char c));
+
+/*     Append a string to a  chunk
+**
+** On entry,
+**     ch      A valid chunk pointer made by HTChunkCreate()
+**     s       Tpoints to a zero-terminated string to be appended
+** On exit,
+**     *ch     Is bigger by strlen(s)
+*/
+
+extern void HTChunkPuts PARAMS((HTChunk * ch, const char *s));
+
+
+/*     Append a zero character to a  chunk
+**
+** On entry,
+**     ch      A valid chunk pointer made by HTChunkCreate()
+** On exit,
+**     *ch     Is one character bigger
+*/
+
+extern void HTChunkTerminate PARAMS((HTChunk * ch));
diff --git a/Cl/WWWLibrary/HTFTP.c b/Cl/WWWLibrary/HTFTP.c
new file mode 100644 (file)
index 0000000..7280bb4
--- /dev/null
@@ -0,0 +1,960 @@
+/*                     File Transfer Protocol (FTP) Client
+**                     for a WorldWideWeb browser
+**                     ===================================
+**
+**     A cache of control connections is kept.
+**
+** Note: Port allocation
+**
+**     It is essential that the port is allocated by the system, rather
+**     than chosen in rotation by us (POLL_PORTS), or the following
+**     problem occurs.
+**
+**     It seems that an attempt by the server to connect to a port which has
+**     been used recently by a listen on the same socket, or by another
+**     socket this or another process causes a hangup of (almost exactly)
+**     one minute. Therefore, we have to use a rotating port number.
+**     The problem remains that if the application is run twice in quick
+**     succession, it will hang for what remains of a minute.
+**
+** History:
+**      2 May 91       Written TBL, as a part of the WorldWideWeb project.
+**     15 Jan 92       Bug fix: close() was used for NETCLOSE for control soc
+**     10 Feb 92       Retry if cached connection times out or breaks
+**
+** Options:
+**     LISTEN          We listen, the other guy connects for data.
+**                     Otherwise, other way round, but problem finding our
+**                     internet address!
+*/
+
+#define LISTEN         /* @@@@ Test */
+
+/*
+BUGS:  @@@     Limit connection cache size!
+               Error reporting to user.
+               400 & 500 errors are acked by user with windows.
+               Use configuration file for user names
+               Prompt user for password
+               
+**             Note for portablility this version does not use select() and
+**             so does not watch the control and data channels at the
+**             same time.
+*/             
+
+#define REPEAT_PORT    /* Give the port number for each file */
+#define REPEAT_LISTEN  /* Close each listen socket and open a new one */
+
+/* define POLL_PORTS            If allocation does not work, poll ourselves.*/
+#define LISTEN_BACKLOG 2       /* Number of pending connect requests (TCP)*/
+
+#define FIRST_TCP_PORT 1024    /* Region to try for a listening port */
+#define LAST_TCP_PORT  5999    
+
+#define LINE_LENGTH 256
+#define COMMAND_LENGTH 256
+
+#include "HTParse.h"
+#include "HTUtils.h"
+#include "tcp.h"
+#include "HTTCP.h"
+#include "HTAnchor.h"
+#include "HText.h"
+#include "HTStyle.h"
+
+#include "HTFTP.h"
+
+#ifndef IPPORT_FTP
+#define IPPORT_FTP     21
+#endif
+
+extern HTStyleSheet * styleSheet;
+PRIVATE HTStyle *h1Style;                      /* For heading level 1 */
+PRIVATE HTStyle *h2Style;                      /* For heading level 2 */
+PRIVATE HTStyle *textStyle;                    /* Text style */
+PRIVATE HTStyle *dirStyle;                     /* Compact List style */
+
+#ifdef REMOVED_CODE
+extern char *malloc();
+extern void free();
+extern char *strncpy();
+#endif
+
+typedef struct _connection {
+    struct _connection *       next;   /* Link on list         */
+    u_long                     addr;   /* IP address           */
+    int                                socket; /* Socket number for communication */
+} connection;
+
+#ifndef NIL
+#define NIL 0
+#endif
+
+
+/*     Module-Wide Variables
+**     ---------------------
+*/
+PRIVATE connection * connections =0;   /* Linked list of connections */
+PRIVATE char    response_text[LINE_LENGTH+1];/* Last response from NewsHost */
+PRIVATE connection * control;          /* Current connection */
+PRIVATE int    data_soc = -1;          /* Socket for data transfer =invalid */
+
+#ifdef POLL_PORTS
+PRIVATE        unsigned short  port_number = FIRST_TCP_PORT;
+#endif
+
+#ifdef LISTEN
+PRIVATE int     master_socket = -1;    /* Listening socket = invalid   */
+PRIVATE char   port_command[255];      /* Command for setting the port */
+PRIVATE fd_set open_sockets;           /* Mask of active channels */
+PRIVATE int    num_sockets;            /* Number of sockets to scan */
+#else
+PRIVATE        unsigned short  passive_port;   /* Port server specified for data */
+#endif
+
+
+#define NEXT_CHAR HTGetChararcter()    /* Use function in HTFormat.c */
+
+#define DATA_BUFFER_SIZE 2048
+PRIVATE char data_buffer[DATA_BUFFER_SIZE];            /* Input data buffer */
+PRIVATE char * data_read_pointer;
+PRIVATE char * data_write_pointer;
+#define NEXT_DATA_CHAR next_data_char()
+
+
+/*     Procedure: Read a character from the data connection
+**     ----------------------------------------------------
+*/
+PRIVATE char next_data_char
+NOARGS
+{
+    int status;
+    if (data_read_pointer >= data_write_pointer) {
+       status = NETREAD(data_soc, data_buffer, DATA_BUFFER_SIZE);
+       /* Get some more data */
+       if (status <= 0) return (char)-1;
+       data_write_pointer = data_buffer + status;
+       data_read_pointer = data_buffer;
+    }
+#ifdef NOT_ASCII
+    {
+        char c = *data_read_pointer++;
+       return FROMASCII(c);
+    }
+#else
+    return *data_read_pointer++;
+#endif
+}
+
+
+/*     Close an individual connection
+**
+*/
+#ifdef __STDC__
+PRIVATE int close_connection(connection * con)
+#else
+PRIVATE int close_connection(con)
+    connection *con;
+#endif
+{
+    connection * scan;
+    int status = NETCLOSE(con->socket);
+    if (TRACE) printf("FTP: Closing control socket %d\n", con->socket);
+    if (connections==con) {
+        connections = con->next;
+       return status;
+    }
+    for(scan=connections; scan; scan=scan->next) {
+        if (scan->next == con) {
+           scan->next = con->next;     /* Unlink */
+           if (control==con) control = (connection*)0;
+           return status;
+       } /*if */
+    } /* for */
+    return -1;         /* very strange -- was not on list. */
+}
+
+
+/*     Execute Command and get Response
+**     --------------------------------
+**
+**     See the state machine illustrated in RFC959, p57. This implements
+**     one command/reply sequence.  It also interprets lines which are to
+**     be continued, which are marked with a "-" immediately after the
+**     status code.
+**
+** On entry,
+**     con     points to the connection which is established.
+**     cmd     points to a command, or is NIL to just get the response.
+**
+**     The command is terminated with the CRLF pair.
+**
+** On exit,
+**     returns:  The first digit of the reply type,
+**               or negative for communication failure.
+*/
+#ifdef __STDC__
+PRIVATE int response(char * cmd)
+#else
+PRIVATE int response(cmd)
+    char * cmd;
+#endif
+{
+    int result;                                /* Three-digit decimal code */
+    char       continuation;
+    int status;
+    
+    if (!control) {
+          if(TRACE) printf("FTP: No control connection set up!!\n");
+         return -99;
+    }
+    
+    if (cmd) {
+    
+       if (TRACE) printf("  Tx: %s", cmd);
+
+#ifdef NOT_ASCII
+       {
+           char * p;
+           for(p=cmd; *p; p++) {
+               *p = TOASCII(*p);
+           }
+       }
+#endif 
+       status = NETWRITE(control->socket, cmd, (int)strlen(cmd));
+       if (status<0) {
+           if (TRACE) printf(
+               "FTP: Error %d sending command: closing socket %d\n",
+               status, control->socket);
+           close_connection(control);
+           return status;
+       }
+    }
+
+    do {
+       char *p = response_text;
+       for(;;) {  
+           if (((*p++=NEXT_CHAR) == '\n')
+                       || (p == &response_text[LINE_LENGTH])) {
+               *p++=0;                 /* Terminate the string */
+               if (TRACE) printf("    Rx: %s", response_text);
+               sscanf(response_text, "%d%c", &result, &continuation);
+               break;      
+           } /* if end of line */
+           
+           if (*(p-1) < 0) {
+               if(TRACE) fprintf(stderr, "Error on rx: closing socket %d\n",
+                   control->socket);
+               strcpy(response_text, "000 *** TCP read error on response\n");
+               close_connection(control);
+               return -1;      /* End of file on response */
+           }
+       } /* Loop over characters */
+
+    } while (continuation == '-');
+    
+    if (result==421) {
+       if(TRACE) fprintf(stderr, "FTP: They close so we close socket %d\n",
+           control->socket);
+       close_connection(control);
+       return -1;
+    }
+    return result/100;
+}
+
+
+/*     Get a valid connection to the host
+**     ----------------------------------
+**
+** On entry,
+**     arg     points to the name of the host in a hypertext address
+** On exit,
+**     returns <0 if error
+**             socket number if success
+**
+**     This routine takes care of managing timed-out connections, and
+**     limiting the number of connections in use at any one time.
+**
+**     It ensures that all connections are logged in if they exist.
+**     It ensures they have the port number transferred.
+*/
+PRIVATE int get_connection ARGS1 (CONST char *,arg)
+{
+    struct hostent * phost;            /* Pointer to host -- See netdb.h */
+    struct sockaddr_in soc_address;    /* Binary network address */
+    struct sockaddr_in* sin = &soc_address;
+
+    char * username=0;
+    char * password=0;
+    
+    if (!arg) return -1;               /* Bad if no name sepcified     */
+    if (!*arg) return -1;              /* Bad if name had zero length  */
+
+/*  Set up defaults:
+*/
+    sin->sin_family = AF_INET;                 /* Family, host order  */
+    sin->sin_port = htons(IPPORT_FTP);         /* Well Known Number    */
+
+    if (TRACE) printf("FTP: Looking for %s\n", arg);
+
+/* Get node name:
+*/
+    {
+       char *p1 = HTParse(arg, "", PARSE_HOST);
+       char *p2 = strchr(p1, '@');     /* user? */
+       char * pw;
+       if (p2) {
+           username = p1;
+           *p2=0;                      /* terminate */
+           p1 = p2+1;                  /* point to host */
+           pw = strchr(username, ':');
+           if (pw) {
+               *pw++ = 0;
+               password = pw;
+           }
+       }
+       HTParseInet(sin, p1);
+        if (!username) free(p1);
+    } /* scope of p1 */
+
+        
+/*     Now we check whether we already have a connection to that port.
+*/
+
+    {
+       connection * scan;
+       for (scan=connections; scan; scan=scan->next) {
+           if (sin->sin_addr.s_addr == scan->addr) {
+               if (TRACE) printf(
+               "FTP: Already have connection for %d.%d.%d.%d.\n",
+                   (int)*((unsigned char *)(&scan->addr)+0),
+                   (int)*((unsigned char *)(&scan->addr)+1),
+                   (int)*((unsigned char *)(&scan->addr)+2),
+                   (int)*((unsigned char *)(&scan->addr)+3));
+               if (username) free(username);
+               return scan->socket;            /* Good return */
+           } else {
+               if (TRACE) printf(
+               "FTP: Existing connection is %d.%d.%d.%d\n",
+                   (int)*((unsigned char *)(&scan->addr)+0),
+                   (int)*((unsigned char *)(&scan->addr)+1),
+                   (int)*((unsigned char *)(&scan->addr)+2),
+                   (int)*((unsigned char *)(&scan->addr)+3));
+           }
+       }
+    }
+
+   
+/*     Now, let's get a socket set up from the server:
+*/      
+    {
+        int status;
+       connection * con = (connection *)malloc(sizeof(*con));
+       if (con == NULL) outofmem(__FILE__, "get_connection");
+       con->addr = sin->sin_addr.s_addr;       /* save it */
+       status = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+       if (status<0) {
+           (void) HTInetStatus("socket");
+           free(con);
+           if (username) free(username);
+           return status;
+       }
+       con->socket = status;
+
+       status = connect(con->socket, (struct sockaddr*)&soc_address,
+        sizeof(soc_address));
+        if (status<0){
+           (void) HTInetStatus("connect");
+           if (TRACE) printf(
+               "FTP: Unable to connect to remote host for `%s'.\n",
+               arg);
+           NETCLOSE(con->socket);
+           free(con);
+           if (username) free(username);
+           return status;                      /* Bad return */
+       }
+       
+       if (TRACE) printf("FTP connected, socket %d\n", con->socket);
+       control = con;                  /* Current control connection */
+       con->next = connections;        /* Link onto list of good ones */
+       connections = con;
+        HTInitInput(con->socket);/* Initialise buffering for contron connection */
+
+
+/*     Now we log in           Look up username, prompt for pw.
+*/
+       {
+           int status = response(NIL); /* Get greeting */
+           
+           if (status == 2) {          /* Send username */
+               char * command;
+               if (username) {
+                   command = (char*)malloc(10+strlen(username)+2+1);
+                   if (command == NULL) outofmem(__FILE__, "get_connection");
+                   sprintf(command, "USER %s\r\n", username);
+               } else {
+                   command = (char*)malloc(25);
+                   if (command == NULL) outofmem(__FILE__, "get_connection");
+                   sprintf(command, "USER anonymous\r\n");
+               }
+               status = response(command);
+               free(command);
+           }
+           if (status == 3) {          /* Send password */
+               char * command;
+               if (password) {
+                   command = (char*)malloc(10+strlen(password)+2+1);
+                   if (command == NULL) outofmem(__FILE__, "get_connection");
+                   sprintf(command, "PASS %s\r\n", password);
+               } else {
+                   command = (char*)malloc(10+strlen(HTHostName())+2+1);
+                   if (command == NULL) outofmem(__FILE__, "get_connection");
+                   sprintf(command,
+                   "PASS user@%s\r\n", HTHostName()); /*@@*/
+               }
+               status = response(command);
+               free(command);
+           }
+            if (username) free(username);
+
+           if (status == 3) status = response("ACCT noaccount\r\n");
+           
+           if (status !=2) {
+               if (TRACE) printf("FTP: Login fail: %s", response_text);
+               if (control) close_connection(control);
+               return -1;              /* Bad return */
+           }
+           if (TRACE) printf("FTP: Logged in.\n");
+       }
+
+/*     Now we inform the server of the port number we will listen on
+*/
+#ifndef REPEAT_PORT
+       {
+           int status = response(port_command);
+           if (status !=2) {
+               if (control) close_connection(control);
+               return -status;         /* Bad return */
+           }
+           if (TRACE) printf("FTP: Port defined.\n");
+       }
+#endif
+       return con->socket;                     /* Good return */
+    } /* Scope of con */
+}
+
+
+#ifdef LISTEN
+
+/*     Close Master (listening) socket
+**     -------------------------------
+**
+**
+*/
+#ifdef __STDC__
+PRIVATE int close_master_socket(void)
+#else
+PRIVATE int close_master_socket()
+#endif
+{
+    int status;
+    FD_CLR(master_socket, &open_sockets);
+    status = NETCLOSE(master_socket);
+    if (TRACE) printf("FTP: Closed master socket %d\n", master_socket);
+    master_socket = -1;
+    if (status<0) return HTInetStatus("close master socket");
+    else return status;
+}
+
+
+/*     Open a master socket for listening on
+**     -------------------------------------
+**
+**     When data is transferred, we open a port, and wait for the server to
+**     connect with the data.
+**
+** On entry,
+**     master_socket   Must be negative if not set up already.
+** On exit,
+**     Returns         socket number if good
+**                     less than zero if error.
+**     master_socket   is socket number if good, else negative.
+**     port_number     is valid if good.
+*/
+#ifdef __STDC__
+PRIVATE int get_listen_socket(void)
+#else
+PRIVATE int get_listen_socket()
+#endif
+{
+    struct sockaddr_in soc_address;    /* Binary network address */
+    struct sockaddr_in* sin = &soc_address;
+    int new_socket;                    /* Will be master_socket */
+    
+    
+    FD_ZERO(&open_sockets);    /* Clear our record of open sockets */
+    num_sockets = 0;
+    
+#ifndef REPEAT_LISTEN
+    if (master_socket>=0) return master_socket;  /* Done already */
+#endif
+
+/*  Create internet socket
+*/
+    new_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+       
+    if (new_socket<0)
+       return HTInetStatus("socket for master socket");
+    
+    if (TRACE) printf("FTP: Opened master socket number %d\n", new_socket);
+    
+/*  Search for a free port.
+*/
+    sin->sin_family = AF_INET;     /* Family = internet, host order  */
+    sin->sin_addr.s_addr = INADDR_ANY; /* Any peer address */
+#ifdef POLL_PORTS
+    {
+        unsigned short old_port_number = port_number;
+       for(port_number=old_port_number+1;;port_number++){ 
+           int status;
+           if (port_number > LAST_TCP_PORT)
+               port_number = FIRST_TCP_PORT;
+           if (port_number == old_port_number) {
+               return HTInetStatus("bind");
+           }
+           soc_address.sin_port = htons(port_number);
+           if ((status=bind(new_socket,
+                   (struct sockaddr*)&soc_address,
+                           /* Cast to generic sockaddr */
+                   sizeof(soc_address))) == 0)
+               break;
+           if (TRACE) printf(
+               "TCP bind attempt to port %d yields %d, errno=%d\n",
+               port_number, status, errno);
+       } /* for */
+    }
+#else
+    {
+        int status;
+       int address_length = sizeof(soc_address);
+       status = getsockname(control->socket,
+                       (struct sockaddr *)&soc_address,
+                        &address_length);
+       if (status<0) return HTInetStatus("getsockname");
+       CTRACE(tfp, "FTP: This host is %s\n",
+           HTInetString(sin));
+       
+       soc_address.sin_port = 0;       /* Unspecified: please allocate */
+       status=bind(new_socket,
+               (struct sockaddr*)&soc_address,
+                       /* Cast to generic sockaddr */
+               sizeof(soc_address));
+       if (status<0) return HTInetStatus("bind");
+       
+       address_length = sizeof(soc_address);
+       status = getsockname(new_socket,
+                       (struct sockaddr*)&soc_address,
+                       &address_length);
+       if (status<0) return HTInetStatus("getsockname");
+    }
+#endif    
+
+    CTRACE(tfp, "FTP: bound to port %d on %s\n",
+       (unsigned int)ntohs(sin->sin_port),
+       HTInetString(sin));
+
+#ifdef REPEAT_LISTEN
+    if (master_socket>=0)
+        (void) close_master_socket();
+#endif    
+    
+    master_socket = new_socket;
+    
+/*     Now we must find out who we are to tell the other guy
+*/
+    (void)HTHostName();        /* Make address valid - doesn't work*/
+    sprintf(port_command, "PORT %d,%d,%d,%d,%d,%d\r\n",
+                   (int)*((unsigned char *)(&sin->sin_addr)+0),
+                   (int)*((unsigned char *)(&sin->sin_addr)+1),
+                   (int)*((unsigned char *)(&sin->sin_addr)+2),
+                   (int)*((unsigned char *)(&sin->sin_addr)+3),
+                   (int)*((unsigned char *)(&sin->sin_port)+0),
+                   (int)*((unsigned char *)(&sin->sin_port)+1));
+
+
+/*     Inform TCP that we will accept connections
+*/
+    if (listen(master_socket, 1)<0) {
+       master_socket = -1;
+       return HTInetStatus("listen");
+    }
+    CTRACE(tfp, "TCP: Master socket(), bind() and listen() all OK\n");
+    FD_SET(master_socket, &open_sockets);
+    if ((master_socket+1) > num_sockets) num_sockets=master_socket+1;
+
+    return master_socket;              /* Good */
+
+} /* get_listen_socket */
+#endif
+
+
+/*     Get Styles from stylesheet
+**     --------------------------
+*/
+PRIVATE void get_styles NOARGS
+{
+    if (!h1Style) h1Style = HTStyleNamed(styleSheet, "Heading1");
+    if (!h2Style) h2Style = HTStyleNamed(styleSheet, "Heading2");
+    if (!textStyle) textStyle = HTStyleNamed(styleSheet, "Example");
+    if (!dirStyle) dirStyle = HTStyleNamed(styleSheet, "Dir");
+}
+
+
+/*     Read a directory into an hypertext object from the data socket
+**     --------------------------------------------------------------
+**
+** On entry,
+**     anchor          Parent anchor to link the HText to
+**     address         Address of the directory
+** On exit,
+**     returns         HT_LOADED if OK
+**                     <0 if error.
+*/
+PRIVATE int read_directory
+ARGS2 (
+  HTParentAnchor *,    parent,
+  CONST char *,                        address
+)
+{
+  HText * HT = HText_new (parent);
+  char *filename = HTParse(address, "", PARSE_PATH + PARSE_PUNCTUATION);
+  HTChildAnchor * child;  /* corresponds to an entry of the directory */
+  char c = 0;
+#define LASTPATH_LENGTH 150  /* @@@@ Horrible limit on the entry size */
+  char lastpath[LASTPATH_LENGTH + 1];
+  char *p, *entry;
+
+  HText_beginAppend (HT);
+  get_styles();
+
+  HTAnchor_setTitle (parent, "FTP Directory of ");
+  HTAnchor_appendTitle (parent, address + 5);  /* +5 gets rid of "file:" */
+  HText_setStyle (HT, h1Style);
+  HText_appendText (HT, filename);
+
+  HText_setStyle (HT, dirStyle);
+  data_read_pointer = data_write_pointer = data_buffer;
+
+  if (*filename == 0)  /* Empty filename : use root */
+    strcpy (lastpath, "/");
+  else {
+    p = filename + strlen (filename) - 2;
+    while (p >= filename && *p != '/')
+      p--;
+    strcpy (lastpath, p + 1);  /* relative path */
+  }
+  free (filename);
+  entry = lastpath + strlen (lastpath);
+  if (*(entry-1) != '/')
+    *entry++ = '/';  /* ready to append entries */
+
+  if (strlen (lastpath) > 1) {  /* Current file is not the FTP root */
+    strcpy (entry, "..");
+    child = HTAnchor_findChildAndLink (parent, 0, lastpath, 0);
+    HText_beginAnchor (HT, child);
+    HText_appendText (HT, "Parent Directory");
+    HText_endAnchor (HT);
+    HText_appendCharacter (HT, '\t');
+  }
+  for (;;) {
+    p = entry;
+    while (p - lastpath < LASTPATH_LENGTH) {
+      c = NEXT_DATA_CHAR;
+      if (c == '\r') {
+       c = NEXT_DATA_CHAR;
+       if (c != '\n') {
+         if (TRACE)
+           printf ("Warning: No newline but %d after carriage return.\n", c);
+         break;
+       }
+      }
+      if (c == '\n' || c == (char) EOF)
+       break;
+      *p++ = c;
+    }
+    if (c == (char) EOF && p == entry)
+      break;
+    *p = 0;
+    child = HTAnchor_findChildAndLink (parent, 0, lastpath, 0);
+    HText_beginAnchor (HT, child);
+    HText_appendText (HT, entry);
+    HText_endAnchor (HT);
+    HText_appendCharacter (HT, '\t');
+  }
+
+  HText_appendParagraph (HT);
+  HText_endAppend (HT);
+  return response(NIL) == 2 ? HT_LOADED : -1;
+}
+
+
+#ifndef ERWISE
+/*     Retrieve File from Server
+**     -------------------------
+**
+** On entry,
+**     name            WWW address of a file: document, including hostname
+** On exit,
+**     returns         Socket number for file if good.
+**                     <0 if bad.
+*/
+PUBLIC int HTFTP_open_file_read
+ARGS2 (
+  CONST char *,                        name,
+  HTParentAnchor *,    anchor
+)
+{
+    BOOL isDirectory = NO;
+    int status;
+    int retry;                 /* How many times tried? */
+    
+    for (retry=0; retry<2; retry++) {  /* For timed out/broken connections */
+    
+       status = get_connection(name);
+       if (status<0) return status;
+
+#ifdef LISTEN
+       status = get_listen_socket();
+       if (status<0) return status;
+    
+#ifdef REPEAT_PORT
+/*     Inform the server of the port number we will listen on
+*/
+       {
+           status = response(port_command);
+           if (status !=2) {           /* Could have timed out */
+               if (status<0) continue;         /* try again - net error*/
+               return -status;                 /* bad reply */
+           }
+           if (TRACE) printf("FTP: Port defined.\n");
+       }
+#endif
+#else  /* Use PASV */
+/*     Tell the server to be passive
+*/
+       {
+           char *p;
+           int reply, h0, h1, h2, h3, p0, p1;  /* Parts of reply */
+           status = response("PASV\r\n");
+           if (status !=2) {
+               if (status<0) continue;         /* retry or Bad return */
+               return -status;                 /* bad reply */
+           }
+           for(p=response_text; *p; p++)
+               if ((*p<'0')||(*p>'9')) *p = ' ';       /* Keep only digits */
+           status = sscanf(response_text, "%d%d%d%d%d%d%d",
+                   &reply, &h0, &h1, &h2, &h3, &p0, &p1);
+           if (status<5) {
+               if (TRACE) printf("FTP: PASV reply has no inet address!\n");
+               return -99;
+           }
+           passive_port = (p0<<8) + p1;
+           if (TRACE) printf("FTP: Server is listening on port %d\n",
+                   passive_port);
+       }
+
+/*     Open connection for data:
+*/
+       {
+           struct sockaddr_in soc_address;
+           int status = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+           if (status<0) {
+               (void) HTInetStatus("socket for data socket");
+               return status;
+           }
+           data_soc = status;
+           
+           soc_address.sin_addr.s_addr = control->addr;
+           soc_address.sin_port = htons(passive_port);
+           soc_address.sin_family = AF_INET;       /* Family, host order  */
+           if (TRACE) printf( 
+               "FTP: Data remote address is port %d, inet %d.%d.%d.%d\n",
+                       (unsigned int)ntohs(soc_address.sin_port),
+                       (int)*((unsigned char *)(&soc_address.sin_addr)+0),
+                       (int)*((unsigned char *)(&soc_address.sin_addr)+1),
+                       (int)*((unsigned char *)(&soc_address.sin_addr)+2),
+                       (int)*((unsigned char *)(&soc_address.sin_addr)+3));
+    
+           status = connect(data_soc, (struct sockaddr*)&soc_address,
+                   sizeof(soc_address));
+           if (status<0){
+               (void) HTInetStatus("connect for data");
+               NETCLOSE(data_soc);
+               return status;                  /* Bad return */
+           }
+           
+           if (TRACE) printf("FTP data connected, socket %d\n", data_soc);
+       }
+#endif /* use PASV */
+       status = 0;
+        break; /* No more retries */
+
+    } /* for retries */
+    if (status<0) return status;       /* Failed with this code */
+    
+/*     Ask for the file:
+*/    
+    {
+        char *filename = HTParse(name, "", PARSE_PATH + PARSE_PUNCTUATION);
+       char command[LINE_LENGTH+1];
+       if (!*filename) StrAllocCopy(filename, "/");
+       sprintf(command, "RETR %s\r\n", filename);
+       status = response(command);
+       if (status != 1) {  /* Failed : try to CWD to it */
+         sprintf(command, "CWD %s\r\n", filename);
+         status = response(command);
+         if (status == 2) {  /* Successed : let's NAME LIST it */
+           isDirectory = YES;
+           sprintf(command, "NLST\r\n");
+           status = response (command);
+         }
+       }
+       free(filename);
+       if (status != 1) return -status;                /* Action not started */
+    }
+
+#ifdef LISTEN
+/*     Wait for the connection
+*/
+    {
+       struct sockaddr_in soc_address;
+        int    soc_addrlen=sizeof(soc_address);
+       status = accept(master_socket,
+                       (struct sockaddr *)&soc_address,
+                       &soc_addrlen);
+       if (status<0)
+           return HTInetStatus("accept");
+       CTRACE(tfp, "TCP: Accepted new socket %d\n", status);
+       data_soc = status;
+    }
+#else
+/* @@ */
+#endif
+    if (isDirectory)
+      return read_directory (anchor, name);
+      /* returns HT_LOADED or error */
+    else
+      return data_soc;
+       
+} /* open_file_read */
+#endif /* ERWISE */
+
+/*     Close socket opened for reading a file, and get final message
+**     -------------------------------------------------------------
+**
+*/
+PUBLIC int HTFTP_close_file
+ARGS1 (int,soc)
+{
+    int status;
+
+    if (soc!=data_soc) {
+        if (TRACE) printf("HTFTP: close socket %d: (not FTP data socket).\n",
+               soc);
+       return NETCLOSE(soc);
+    }
+    status = NETCLOSE(data_soc);
+    if (TRACE) printf("FTP: Closing data socket %d\n", data_soc);
+    if (status<0) (void) HTInetStatus("close");        /* Comment only */
+    data_soc = -1;     /* invalidate it */
+    
+    status = response(NIL);
+    if (status!=2) return -status;
+    
+    return status;     /* Good */
+}
+
+
+/*___________________________________________________________________________
+*/
+/*     Test program only
+**     -----------------
+**
+**     Compiling this with -DTEST produces a test program.  Unix only
+**
+** Syntax:
+**     test <file or option> ...
+**
+**     options:        -v      Verbose: Turn trace on at this point
+*/
+#ifdef TEST
+
+PUBLIC int WWW_TraceFlag;
+
+#ifdef __STDC__
+int main(int argc, char*argv[])
+#else
+int main(argc, argv)
+       int argc;
+       char *argv[];
+#endif
+{
+    
+    int arg;                   /* Argument number */
+    int status;
+    connection * con;
+    WWW_TraceFlag = (0==strcmp(argv[1], "-v"));        /* diagnostics ? */
+
+#ifdef SUPRESS    
+    status = get_listen_socket();
+    if (TRACE) printf("get_listen_socket returns %d\n\n", status);
+    if (status<0) exit(status);
+
+    status = get_connection(argv[1]);  /* test double use */
+    if (TRACE) printf("get_connection(`%s') returned %d\n\n", argv[1], status);
+    if (status<0) exit(status);
+#endif
+
+    for(arg=1; arg<argc; arg++) {              /* For each argument */
+         if (0==strcmp(argv[arg], "-v")) {
+             WWW_TraceFlag = 1;                        /* -v => Trace on */
+
+        } else {                               /* Filename: */
+       
+           status = HTTP_open_file_read(argv[arg]);
+           if (TRACE) printf("open_file_read returned %d\n\n", status);
+           if (status<0) exit(status);
+               
+       /*      Copy the file to std out:
+       */   
+           {
+               char buffer[INPUT_BUFFER_SIZE];
+               for(;;) {
+                   int status = NETREAD(data_soc, buffer, INPUT_BUFFER_SIZE);
+                   if (status<=0) {
+                       if (status<0) (void) HTInetStatus("read");
+                       break;
+                   }
+                   status = write(1, buffer, status);
+                   if (status<0) {
+                       printf("Write failure!\n");
+                       break;
+                   }
+               }
+           }
+       
+           status = HTTP_close_file(data_soc);
+           if (TRACE) printf("Close_file returned %d\n\n", status);
+
+        } /* if */
+    } /* for */
+    status = response("QUIT\r\n");             /* Be good */
+    if (TRACE) printf("Quit returned %d\n", status);
+
+    while(connections) close_connection(connections);
+    
+    close_master_socket();
+         
+} /* main */
+#endif  /* TEST */
+
diff --git a/Cl/WWWLibrary/HTFTP.h b/Cl/WWWLibrary/HTFTP.h
new file mode 100644 (file)
index 0000000..bd0ffcd
--- /dev/null
@@ -0,0 +1,31 @@
+/*                     FTP access functions            HTFTP.h
+**                     ====================
+*/
+
+/*     Retrieve File from Server
+**     -------------------------
+**
+** On exit,
+**     returns         Socket number for file if good.
+**                     <0 if bad.
+*/
+extern int HTFTP_open_file_read
+PARAMS
+((
+  CONST char * name,
+  HTParentAnchor * anchor
+));
+
+/*     Close socket opened for reading a file, and get final message
+**     -------------------------------------------------------------
+**
+*/
+extern int HTFTP_close_file
+PARAMS ((int soc));
+
+
+/*     Return Host Name
+**     ----------------
+*/
+extern CONST char * HTHostName
+NOPARAMS;
diff --git a/Cl/WWWLibrary/HTFile.c b/Cl/WWWLibrary/HTFile.c
new file mode 100644 (file)
index 0000000..3bef015
--- /dev/null
@@ -0,0 +1,554 @@
+/*                     File Access                             HTFile.c
+**                     ===========
+**
+**     This is unix-specific code in general, with some VMS bits.
+**     These are routines for file access used by WWW browsers.
+**
+** History:
+**        Feb 91       Written Tim Berners-Lee CERN/CN
+**        Apr 91       vms-vms access included using DECnet syntax
+**
+** Bugs:
+**     Cannot access VMS files from a unix machine. How can we know that the
+**     target machine runs VMS?
+*/
+
+#define INFINITY 512           /* file name length @@ FIXME */
+
+
+
+#ifdef unix                    /* if this is to compile on a UNIX machine */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/dir.h>
+#include "HText.h"
+#define GOT_READ_DIR 1    /* if directory reading functions are available */
+#endif
+
+#include "HTUtils.h"
+#include "HTFile.h"
+
+#include "WWW.h"
+#include "HTParse.h"
+#include "tcp.h"
+#include "HTTCP.h"
+#include "HTFTP.h"
+#include "HTAnchor.h"
+
+PRIVATE char *HTMountRoot = "/Net/";           /* Where to find mounts */
+#ifdef vms
+PRIVATE char *HTCacheRoot = "/WWW$SCRATCH/";   /* Where to cache things */
+#else
+PRIVATE char *HTCacheRoot = "/tmp/W3_Cache_";   /* Where to cache things */
+#endif
+
+/* PRIVATE char *HTSaveRoot  = "$(HOME)/WWW/";*/    /* Where to save things */
+
+#ifdef vms
+/*     Convert unix-style name into VMS name
+**     -------------------------------------
+**
+** Bug:        Returns pointer to static -- non-reentrant
+*/
+PRIVATE char * vms_name(CONST char * nn, CONST char * fn)
+{
+
+/*     We try converting the filename into Files-11 syntax. That is, we assume
+**     first that the file is, like us, on a VMS node. We try remote
+**     (or local) DECnet access. Files-11, VMS, VAX and DECnet
+**     are trademarks of Digital Equipment Corporation. 
+**     The node is assumed to be local if the hostname WITHOUT DOMAIN
+**     matches the local one. @@@
+*/
+    static char vmsname[INFINITY];     /* returned */
+    char * filename = (char*)malloc(strlen(fn)+1);
+    char * nodename = (char*)malloc(strlen(nn)+2+1);   /* Copies to hack */
+    char *second;              /* 2nd slash */
+    char *last;                        /* last slash */
+    
+    char * hostname = HTHostName();
+
+    strcpy(filename, fn);
+    strcpy(nodename, "");      /* On same node? Yes if node names match */
+    {
+        char *p, *q;
+        for (p=hostname, q=nn; *p && *p!='.' && *q && *q!='.'; p++, q++){
+           if (TOUPPER(*p)!=TOUPPER(*q)) {
+               strcpy(nodename, nn);
+               q = strchr(nodename, '.');      /* Mismatch */
+               if (q) *q=0;                    /* Chop domain */
+               strcat(nodename, "::");         /* Try decnet anyway */
+               break;
+           }
+       }
+    }
+
+    second = strchr(filename+1, '/');          /* 2nd slash */
+    last = strrchr(filename, '/');     /* last slash */
+        
+    if (!second) {                             /* Only one slash */
+       sprintf(vmsname, "%s%s", nodename, filename);
+    } else if(second==last) {          /* Exactly two slashes */
+       *second = 0;            /* Split filename from disk */
+       sprintf(vmsname, "%s%s:%s", nodename, filename+1, second+1);
+       *second = '/';  /* restore */
+    } else {                           /* More than two slashes */
+       char * p;
+       *second = 0;            /* Split disk from directories */
+       *last = 0;              /* Split dir from filename */
+       sprintf(vmsname, "%s%s:[%s]%s",
+               nodename, filename+1, second+1, last+1);
+       *second = *last = '/';  /* restore filename */
+       for (p=strchr(vmsname, '['); *p!=']'; p++)
+           if (*p=='/') *p='.';        /* Convert dir sep.  to dots */
+    }
+    free(nodename);
+    free(filename);
+    return vmsname;
+}
+
+
+#endif /* vms */
+
+/*     Make the cache file name for a W3 document
+**     ------------------------------------------
+**     Make up a suitable name for saving the node in
+**
+**     E.g.    /tmp/WWW_Cache_news/1234@cernvax.cern.ch
+**             /tmp/WWW_Cache_http/crnvmc/FIND/xx.xxx.xx
+**
+** On exit,
+**     returns a malloc'ed string which must be freed by the caller.
+*/
+PUBLIC char * HTCacheFileName ARGS1(CONST char *,name)
+{
+    char * access = HTParse(name, "", PARSE_ACCESS);
+    char * host = HTParse(name, "", PARSE_HOST);
+    char * path = HTParse(name, "", PARSE_PATH+PARSE_PUNCTUATION);
+    
+    char * result;
+    result = (char *)malloc(
+           strlen(HTCacheRoot)+strlen(access)
+           +strlen(host)+strlen(path)+6+1);
+    if (result == NULL) outofmem(__FILE__, "HTCacheFileName");
+    sprintf(result, "%s/WWW/%s/%s%s", HTCacheRoot, access, host, path);
+    free(path);
+    free(access);
+    free(host);
+    return result;
+}
+
+/*     Open a file for write, creating the path
+**     ----------------------------------------
+*/
+#ifdef NOT_IMPLEMENTED
+PRIVATE int HTCreatePath ARGS1(CONST char *,path)
+{
+    return -1;
+}
+#endif
+
+/*     Convert filenames between local and WWW formats
+**     -----------------------------------------------
+**     Make up a suitable name for saving the node in
+**
+**     E.g.    $(HOME)/WWW/news/1234@cernvax.cern.ch
+**             $(HOME)/WWW/http/crnvmc/FIND/xx.xxx.xx
+**
+** On exit,
+**     returns a malloc'ed string which must be freed by the caller.
+*/
+PUBLIC char * HTLocalName ARGS1(CONST char *,name)
+{
+    char * access = HTParse(name, "", PARSE_ACCESS);
+    char * host = HTParse(name, "", PARSE_HOST);
+    char * path = HTParse(name, "", PARSE_PATH+PARSE_PUNCTUATION);
+    
+    if (0==strcmp(access, "file")) {
+        free(access);  
+       if ((0==strcmp(host, HTHostName())) || !*host) {
+           free(host);
+           if (TRACE) printf("Node `%s' means path `%s'\n", name, path);
+           return(path);
+       } else {
+           char * result = (char *)malloc(
+                               strlen("/Net/")+strlen(host)+strlen(path)+1);
+              if (result == NULL) outofmem(__FILE__, "HTLocalName");
+           sprintf(result, "%s%s%s", "/Net/", host, path);
+           free(host);
+           free(path);
+           if (TRACE) printf("Node `%s' means file `%s'\n", name, result);
+           return result;
+       }
+    } else {  /* other access */
+       char * result;
+        CONST char * home =  (CONST char*)getenv("HOME");
+       if (!home) home = "/tmp"; 
+       result = (char *)malloc(
+               strlen(home)+strlen(access)+strlen(host)+strlen(path)+6+1);
+      if (result == NULL) outofmem(__FILE__, "HTLocalName");
+       sprintf(result, "%s/WWW/%s/%s%s", home, access, host, path);
+       free(path);
+       free(access);
+       free(host);
+       return result;
+    }
+}
+
+
+/*     Make a WWW name from a full local path name
+**
+** Bugs:
+**     At present, only the names of two network root nodes are hand-coded
+**     in and valid for the NeXT only. This should be configurable in
+**     the general case.
+*/
+
+PUBLIC char * WWW_nameOfFile ARGS1 (CONST char *,name)
+{
+    char * result;
+#ifdef NeXT
+    if (0==strncmp("/private/Net/", name, 13)) {
+       result = (char *)malloc(7+strlen(name+13)+1);
+       if (result == NULL) outofmem(__FILE__, "WWW_nameOfFile");
+       sprintf(result, "file://%s", name+13);
+    } else
+#endif
+    if (0==strncmp(HTMountRoot, name, 5)) {
+       result = (char *)malloc(7+strlen(name+5)+1);
+       if (result == NULL) outofmem(__FILE__, "WWW_nameOfFile");
+       sprintf(result, "file://%s", name+5);
+    } else {
+        result = (char *)malloc(7+strlen(HTHostName())+strlen(name)+1);
+       if (result == NULL) outofmem(__FILE__, "WWW_nameOfFile");
+       sprintf(result, "file://%s%s", HTHostName(), name);
+    }
+    if (TRACE) printf("File `%s'\n\tmeans node `%s'\n", name, result);
+    return result;
+}
+
+
+/*     Determine file format from file name
+**     ------------------------------------
+**
+** Note: This function is also in the server file HTRetrieve.c
+** If it gets complicated, it should be shared.
+**
+*/
+
+PUBLIC HTFormat HTFileFormat ARGS1 (CONST char *,filename)
+{
+    CONST char * extension;
+    for (extension=filename+strlen(filename);
+       (extension>filename) &&
+               (*extension != '.') &&
+               (*extension!='/');
+       extension--) /* search */ ;
+
+    if (*extension == '.') {
+       return    0==strcmp(".html", extension) ? WWW_HTML
+               : 0==strcmp(".rtf",  extension) ? WWW_RICHTEXT
+               : 0==strcmp(".txt",  extension) ? WWW_PLAINTEXT
+               : WWW_PLAINTEXT;        /* Unrecognised, try plain text */
+    } else {
+       return WWW_PLAINTEXT;
+    } 
+}
+
+
+/*     Determine write access to a file
+//     --------------------------------
+//
+// On exit,
+//     return value    YES if file can be accessed and can be written to.
+//
+// Bugs:
+//     1.      No code for non-unix systems.
+//     2.      Isn't there a quicker way?
+*/
+
+#ifdef vms
+#define NO_GROUPS
+#endif
+#ifdef NO_UNIX_IO
+#define NO_GROUPS
+#endif
+#ifdef PCNFS
+#define NO_GROUPS
+#endif
+
+PUBLIC BOOL HTEditable ARGS1 (CONST char *,filename)
+{
+#ifdef NO_GROUPS
+    return NO;         /* Safe answer till we find the correct algorithm */
+#else
+    int        groups[NGROUPS];        
+    uid_t      myUid;
+    int                ngroups;                        /* The number of groups  */
+    struct stat        fileStatus;
+    int                i;
+        
+    if (stat(filename, &fileStatus))           /* Get details of filename */
+       return NO;                              /* Can't even access file! */
+
+    ngroups = getgroups(NGROUPS, groups);      /* Groups to which I belong  */
+    myUid = geteuid();                         /* Get my user identifier */
+
+    if (TRACE) {
+        int i;
+       printf("File mode is 0%o, uid=%d, gid=%d. My uid=%d, %d groups (",
+           fileStatus.st_mode, fileStatus.st_uid, fileStatus.st_gid,
+           myUid, ngroups);
+       for (i=0; i<ngroups; i++) printf(" %d", groups[i]);
+       printf(")\n");
+    }
+    
+    if (fileStatus.st_mode & 0002)             /* I can write anyway? */
+       return YES;
+       
+    if ((fileStatus.st_mode & 0200)            /* I can write my own file? */
+     && (fileStatus.st_uid == myUid))
+       return YES;
+
+    if (fileStatus.st_mode & 0020)             /* Group I am in can write? */
+    {
+       for (i=0; i<ngroups; i++) {
+            if (groups[i] == fileStatus.st_gid)
+               return YES;
+       }
+    }
+    if (TRACE) printf("\tFile is not editable.\n");
+    return NO;                                 /* If no excuse, can't do */
+#endif
+}
+
+
+/*     Open a file descriptor for a document
+**     -------------------------------------
+**
+** On entry,
+**     addr            must point to the fully qualified hypertext reference.
+**
+** On exit,
+**     returns         <0      Error has occured.
+**                     >=0     Value of file descriptor or socket to be used
+**                              to read data.
+**     *pFormat        Set to the format of the file, if known.
+**                     (See WWW.h)
+**
+*/
+int HTOpenFile
+ARGS3
+(
+ CONST char *,addr,
+ HTFormat *,pFormat,
+ HTParentAnchor *,anchor
+)
+{
+    char * filename;
+    int fd = -1;               /* Unix file descriptor number = INVALID */
+    char * nodename = 0;
+    char * newname=0;  /* Simplified name of file */
+
+/*     Reduce the filename to a basic form (hopefully unique!)
+*/
+    StrAllocCopy(newname, addr);
+    filename=HTParse(newname, "", PARSE_PATH|PARSE_PUNCTUATION);
+    nodename=HTParse(newname, "", PARSE_HOST);
+    free(newname);
+    
+    *pFormat = HTFileFormat(filename);
+
+    
+#ifdef vms
+/* Assume that the file is remote vms or ultrix if no domain name @@ */
+    if (!strchr(nodename, '.')) {
+        char * vmsname = vms_name(nodename, filename);
+       fd = open(vmsname, O_RDONLY, 0);
+
+/*     If the file wasn't VMS syntax, then perhaps it is ultrix
+*/
+       if (fd<0) {
+           char ultrixname[INFINITY];
+           if (TRACE) fprintf(stderr, "HTFile: Can't open as %s\n", vmsname);
+           sprintf(ultrixname, "%s::\"%s\"", nodename, filename);
+           fd = open(ultrixname, O_RDONLY, 0);
+           if (fd<0) {
+               if (TRACE) fprintf(stderr, 
+                       "HTFile: Can't open as %s\n", ultrixname);
+           }
+       }
+    }
+#else
+
+/*     For unix, we try to translate the name into the name of a transparently
+**     mounted file.
+*/
+#ifndef NO_UNIX_IO
+    {
+       char * localname = HTLocalName(addr);
+       
+       
+#ifdef GOT_READ_DIR
+/*
+**     Check to see if the 'localname' is in fact a directory.  If it is
+**     create a new hypertext object containing a list of files and 
+**     subdirectories contained in the directory.  All of these are links
+**      to the directories or files listed.
+**      NB This assumes the existance of a type 'struct direct', which will
+**      hold the directory entry, and a type 'DIR' which is used to point to
+**      the current directory being read.
+*/
+       
+       struct stat dir_info;
+       
+       if (stat(localname,&dir_info) == -1) {     /* get file information */
+                                      /* if can't read file information */
+           if (TRACE) fprintf(stderr, "HTFile: can't stat %s\n", localname);
+
+       }  else {               /* Stat was OK */
+               
+
+           if (((dir_info.st_mode) & S_IFMT) == S_IFDIR) {
+               /* if localname is a directory */       
+               HTChildAnchor * child;
+               HText * HT;
+               extern HTStyleSheet * styleSheet;
+               static HTStyle * DirectoryStyle = 0;
+               static HTStyle * H1Style = 0;
+               DIR *dp;
+               struct direct * dirbuf;
+                   
+               char * tmpfilename = NULL;
+               char * shortfilename = NULL;
+               struct stat *file_info = malloc(sizeof(struct stat));
+               
+               if (TRACE)
+                   fprintf(stderr,"%s is a directory\n",localname);
+                       
+               if (!H1Style)
+                   H1Style = HTStyleNamed(styleSheet, "Heading1");
+               
+               if (!DirectoryStyle)
+                   DirectoryStyle = HTStyleNamed(styleSheet, "Dir");
+               
+               HTAnchor_setTitle(anchor, filename);
+                   
+               HT = HText_new(anchor);
+               HText_beginAppend(HT);
+                   
+               HText_setStyle(HT,H1Style);
+               shortfilename=strrchr(localname,'/');
+               /* put the last part of the path in shortfilename */
+               shortfilename++;               /* get rid of leading '/' */
+               if (*shortfilename=='\0')
+                   shortfilename--;
+                   
+               HText_appendText(HT,shortfilename);
+               HText_setStyle(HT,DirectoryStyle);
+               
+               dp = opendir(localname);
+               if (dp) {                   
+                  /* if the directory file is readable */
+                   while (dirbuf = readdir(dp)) {
+                               /* while there are directory entries to be read */
+                       if (dirbuf->d_ino == 0)
+                                       /* if the entry is not being used, skip it */
+                           continue;
+                       
+                       if (!strcmp(dirbuf->d_name,"."))
+                           continue;      /* skip the entry for this directory */
+                           
+                       if (strcmp(dirbuf->d_name,".."))
+                                   /* if the current entry is parent directory */
+                           if ((*(dirbuf->d_name)=='.') ||
+                               (*(dirbuf->d_name)==','))
+                               continue;    /* skip those files whose name begins
+                                               with '.' or ',' */
+    
+                       StrAllocCopy(tmpfilename,localname);
+                       if (strcmp(localname,"/")) 
+                                           /* if filename is not root directory */
+                           StrAllocCat(tmpfilename,"/"); 
+                       else
+                           if (!strcmp(dirbuf->d_name,".."))
+                               continue;
+               /* if root directory and current entry is parent
+                                       directory, skip the current entry */
+                       
+                       StrAllocCat(tmpfilename,dirbuf->d_name);
+                       /* append the current entry's filename to the path */
+                       HTSimplify(tmpfilename);
+               
+                       child = HTAnchor_findChildAndLink(
+                               anchor, 0, tmpfilename, 0);
+                       HText_beginAnchor(HT, child); 
+                       stat(tmpfilename,file_info);
+                       
+                       if (strcmp(dirbuf->d_name,"..")) {
+/* if the current entry is not the parent directory then use the file name */
+                           HText_appendText(HT,dirbuf->d_name);
+                           if (((file_info->st_mode) & S_IFMT) == S_IFDIR) 
+                               HText_appendCharacter(HT, '/'); 
+                       }                       
+                       else {
+                       /* use name of parent directory */
+                           char * endbit = strrchr(tmpfilename, '/');
+                           HText_appendText(HT,"Up to ");
+                           HText_appendText(HT, endbit?endbit+1:tmpfilename);
+                       }       
+                       HText_endAnchor(HT);
+                           
+                       HText_appendCharacter(HT, '\t');
+                   } /* end while directory entries left to read */
+                   
+                   closedir(dp);
+                   free(tmpfilename);
+                   
+               }  else {   /* Directory is not readable */
+                   if (TRACE)
+                       fprintf(stderr,"HTFile.c: directory %s unreadable\n",
+                               localname);
+                   HText_appendText(HT,
+                          "Sorry, can't read the contents of this directory - probably read protected\n");
+                           
+               } /* end if directory not readable */    
+               
+               HText_endAppend(HT);
+                   
+               free(file_info);
+               free(filename);  
+               free(localname);
+               return HT_LOADED;       /* fd not valid, but document loaded anyway */
+               
+           } /* end if localname is directory */
+       
+       } /* end if file stat worked */
+       
+/* End of directory reading section
+*/
+#endif
+
+       fd = open(localname, O_RDONLY, 0);
+       if(TRACE) printf ("HTAccess: Opening `%s' gives %d\n",
+                           localname, fd);
+       free(localname);
+    }
+#endif
+#endif
+
+/*     Now, as transparently mounted access has failed, we try FTP.
+*/
+    if (fd<0)
+       if (strcmp(nodename, HTHostName())!=0) {
+           free(filename);
+           return HTFTP_open_file_read(addr, anchor);
+    }
+
+/*     All attempts have failed if fd<0.
+*/
+    if (fd<0) printf("Can't open `%s', errno=%d\n", filename, errno);
+    free(filename);
+    return fd;
+
+}
diff --git a/Cl/WWWLibrary/HTFile.h b/Cl/WWWLibrary/HTFile.h
new file mode 100644 (file)
index 0000000..473275a
--- /dev/null
@@ -0,0 +1,83 @@
+/*                     File Access                             HTFile.h
+**                     ===========
+**
+**     These are routines for file access used by WWW browsers.
+**
+*/
+
+#include "HTFormat.h"
+
+/*     Convert filenames between local and WWW formats
+**     -----------------------------------------------
+**     Make up a suitable name for saving the node in
+**
+**     E.g.    $(HOME)/WWW/news/1234@cernvax.cern.ch
+**             $(HOME)/WWW/http/crnvmc/FIND/xx.xxx.xx
+*/
+#ifdef __STDC__
+extern char * HTLocalName(const char * name);
+#else
+extern char * HTLocalName();
+#endif
+
+/*     Make a WWW name from a full local path name
+**
+*/
+extern char * WWW_nameOfFile PARAMS((const char * name));
+
+
+/*     Generate the name of a cache file
+*/
+
+extern char * HTCacheFileName PARAMS((CONST char * name));
+
+
+/*     Determine file format from file name
+**     ------------------------------------
+*/
+
+#ifdef __STDC__
+extern int HTFileFormat(const char * filename);
+#else
+extern int HTFileFormat();
+#endif 
+
+
+/*     Determine write access to a file
+//     --------------------------------
+//
+// On exit,
+//     return value    YES if file can be accessed and can be written to.
+//
+//     Isn't there a quicker way?
+*/
+
+#ifdef __STDC__
+extern BOOL HTEditable(const char * filename);
+#else
+extern BOOL HTEditable();
+#endif
+
+
+/*     Open a file descriptor for a document
+**     -------------------------------------
+**
+** On entry,
+**     addr            must point to the fully qualified hypertext reference.
+**
+** On exit,
+**     returns         <0      Error has occured.
+**                     >=0     Value of file descriptor or socket to be used
+**                              to read data.
+**     *pFormat        Set to the format of the file, if known.
+**                     (See WWW.h)
+**
+*/
+extern int HTOpenFile
+PARAMS
+((
+  const char * addr,
+  HTFormat * pFormat,
+  HTParentAnchor * anchor
+));
+
diff --git a/Cl/WWWLibrary/HTFont.h b/Cl/WWWLibrary/HTFont.h
new file mode 100644 (file)
index 0000000..914d33e
--- /dev/null
@@ -0,0 +1,19 @@
+/*             The portable font concept (!?*)
+*/
+
+/*     Line mode browser version:
+*/
+
+typedef int HTFont;    /* For now */
+
+#define HT_NON_BREAK_SPACE ((char)1)   /* For now */
+
+#define HT_FONT                0
+#define HT_CAPITALS    1
+#define HT_BOLD                2
+#define HT_UNDERLINE   4
+#define HT_INVERSE     8
+#define HT_DOUBLE      0x10
+
+#define HT_BLACK       0
+#define HT_WHITE       1
diff --git a/Cl/WWWLibrary/HTFormat.c b/Cl/WWWLibrary/HTFormat.c
new file mode 100644 (file)
index 0000000..ab2a9dd
--- /dev/null
@@ -0,0 +1,133 @@
+/*             Manage different file formats                   HTFormat.c
+**             =============================
+**
+** Bugs:
+**     Not reentrant.
+**
+**     Assumes the incoming stream is ASCII, rather than a local file
+**     format, and so ALWAYS converts from ASCII on non-ASCII machines.
+**     Therefore, non-ASCII machines can't read local files.
+*/
+
+#include "HTUtils.h"
+#include "tcp.h"
+#include "HTFormat.h"
+
+#include "HTML.h"
+#include "HText.h"
+#include "HTStyle.h"
+
+extern HTStyleSheet * styleSheet;
+
+/*     File buffering
+**     --------------
+**
+**     The input file is read using the macro which can read from
+**     a socket or a file.
+**     The input buffer size, if large will give greater efficiency and
+**     release the server faster, and if small will save space on PCs etc.
+*/
+#define INPUT_BUFFER_SIZE 4096         /* Tradeoff */
+PRIVATE char input_buffer[INPUT_BUFFER_SIZE];
+PRIVATE char * input_pointer;
+PRIVATE char * input_limit;
+PRIVATE int input_file_number;
+
+
+/*     Set up the buffering
+**
+**     These routines are public because they are in fact needed by
+**     many parsers, and on PCs and Macs we should not duplicate
+**     the static buffer area.
+*/
+PUBLIC void HTInitInput ARGS1 (int,file_number)
+{
+    input_file_number = file_number;
+    input_pointer = input_limit = input_buffer;
+}
+
+
+PUBLIC char HTGetChararcter NOARGS
+{
+    char ch;
+    do {
+       if (input_pointer >= input_limit) {
+#ifdef ERWISE
+            int status = cl_read_data(
+                   input_file_number, input_buffer, INPUT_BUFFER_SIZE);
+#else
+           int status = NETREAD(
+                   input_file_number, input_buffer, INPUT_BUFFER_SIZE);
+#endif
+           if (status <= 0) {
+               if (status == 0) return (char)EOF;
+               if (TRACE) fprintf(stderr,
+                   "HTFormat: File read error %d\n", status);
+               return (char)EOF; /* -1 is returned by UCX at end of HTTP link */
+           }
+           input_pointer = input_buffer;
+           input_limit = input_buffer + status;
+       }
+       ch = *input_pointer++;
+    } while (ch == (char) 13); /* Ignore ASCII carriage return */
+    
+    return FROMASCII(ch);
+}
+
+
+/*     Parse a file given format and file number
+**     ------------
+*/
+PUBLIC void HTParseFormat ARGS3(
+       HTFormat,format,
+       HTParentAnchor *,anchor,
+       int,file_number)
+{
+/*     Parse the file
+*/
+#ifdef CURSES
+      long    bytecount = 0;
+#endif
+    HTInitInput(file_number);
+
+    switch (format) {
+
+    case WWW_HTML:             /* Parse HTML */
+      {
+        HTML_begin(anchor);
+       SGML_begin(&HTML_dtd);
+       for(;;) {
+           char character;
+           character = HTGetChararcter();
+           if (character == (char)EOF) break;
+#ifdef CURSES
+              if (++bytecount % 1024 == 0) prompt_count(bytecount / 1024);
+#endif
+    
+           SGML_character(&HTML_dtd, character);           
+         }
+       SGML_end(&HTML_dtd);
+      }
+       break;
+
+    default :                  /* unknown format -- Parse plain text */
+      {
+        HText * text = HText_new(anchor);
+       HText_setStyle(text, HTStyleNamed(styleSheet, "Example"));
+       HText_beginAppend(text);
+       for(;;) {
+           char character;
+           character = HTGetChararcter();
+           if (character == (char)EOF) break;
+#ifdef CURSES
+              if (++bytecount % 1024 == 0) prompt_count(bytecount / 1024);
+#endif
+           HText_appendCharacter(text, character);           
+       }
+        HText_endAppend(text);
+      }
+       break;
+       
+    } /* end of switch (format) */
+    
+}
diff --git a/Cl/WWWLibrary/HTFormat.h b/Cl/WWWLibrary/HTFormat.h
new file mode 100644 (file)
index 0000000..70d3fee
--- /dev/null
@@ -0,0 +1,39 @@
+/*             Manage different file formats                   HTFormat.c
+**             =============================
+**
+*/
+#ifndef HTFORMAT_H
+#define HTFORMAT_H
+
+#include "HTUtils.h"
+
+typedef int HTFormat;
+                               /* Can take the following values: */
+#define WWW_INVALID   (-1)
+#define WWW_SOURCE     0       /* Whatever it was                      */
+#define WWW_PLAINTEXT  1       /* plain ISO latin (ASCII)              */
+#define WWW_POSTSCRIPT 2       /* Postscript - encapsulated?           */
+#define        WWW_RICHTEXT    3       /* Microsoft RTF transfer format        */
+#define WWW_HTML       4       /* WWW HyperText Markup Language        */
+#define WWW_BINARY     5       /* Otherwise Unknown binary format */
+
+#include "HTAnchor.h"
+
+
+/*     Clear input buffer and set file number
+*/
+extern void HTInitInput PARAMS((int file_number));
+
+/*     Get next character from buffer
+*/
+extern char HTGetChararcter NOPARAMS;
+
+
+/*     Parse a file given its format
+*/
+extern void HTParseFormat PARAMS((
+       HTFormat        format,
+       HTParentAnchor  *anchor,
+       int             file_number));
+
+#endif
diff --git a/Cl/WWWLibrary/HTGopher.c b/Cl/WWWLibrary/HTGopher.c
new file mode 100644 (file)
index 0000000..5ef66ca
--- /dev/null
@@ -0,0 +1,415 @@
+/*                     GOPHER ACCESS                           HTGopher.c
+**                     =============
+**
+** History:
+**     26 Sep 90       Adapted from other accesses (News, HTTP) TBL
+**     29 Nov 91       Downgraded to C, for portable implementation.
+*/
+
+#define GOPHER_PORT 70         /* See protocol spec */
+#define BIG 1024               /* Bug */
+#define LINE_LENGTH 256                /* Bug */
+
+/*     Gopher entity types:
+*/
+#define GOPHER_TEXT            '0'
+#define GOPHER_MENU            '1'
+#define GOPHER_CSO             '2'
+#define GOPHER_ERROR           '3'
+#define GOPHER_MACBINHEX       '4'
+#define GOPHER_PCBINHEX                '5'
+#define GOPHER_UUENCODED       '6'
+#define GOPHER_INDEX           '7'
+#define GOPHER_TELNET          '8'
+#define GOPHER_HTML            'h'             /* HTML */
+#define GOPHER_DUPLICATE       '+'
+#define GOPHER_WWW             'w'             /* W3 address */
+
+#include <ctype.h>
+#include "HTUtils.h"           /* Coding convention macros */
+#include "tcp.h"
+
+#include "HTGopher.h"
+
+#include "HText.h"
+#include "HTParse.h"
+#include "HTFormat.h"
+#include "HTTCP.h"
+
+#ifdef NeXTStep
+#include <appkit/defaults.h>
+#define GOPHER_PROGRESS(foo)
+#else
+#define GOPHER_PROGRESS(foo) printf("%s\n", (foo))
+#endif
+
+extern HTStyleSheet * styleSheet;
+
+#define NEXT_CHAR HTGetChararcter()
+
+
+
+/*     Module-wide variables
+*/
+PRIVATE int s;                                 /* Socket for GopherHost */
+PRIVATE HText *        HT;                             /* the new hypertext */
+PRIVATE HTParentAnchor *node_anchor;           /* Its anchor */
+PRIVATE int    diagnostic;                     /* level: 0=none 2=source */
+
+PRIVATE HTStyle *addressStyle;                 /* For address etc */
+PRIVATE HTStyle *heading1Style;                        /* For heading level 1 */
+PRIVATE HTStyle *textStyle;                    /* Text style */
+
+
+/*     Matrix of allowed characters in filenames
+**     -----------------------------------------
+*/
+
+PRIVATE BOOL acceptable[256];
+PRIVATE BOOL acceptable_inited = NO;
+
+PRIVATE void init_acceptable NOARGS
+{
+    unsigned int i;
+    char * good = 
+      "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./-_$";
+    for(i=0; i<256; i++) acceptable[i] = NO;
+    for(;*good; good++) acceptable[(unsigned int)*good] = YES;
+    acceptable_inited = YES;
+}
+
+PRIVATE CONST char hex[17] = "0123456789abcdef";
+
+/*     Decdoe one hex character
+*/
+
+PRIVATE char from_hex ARGS1(char, c)
+{
+    return               (c>='0')&&(c<='9') ? c-'0'
+                       : (c>='A')&&(c<='F') ? c-'A'+10
+                       : (c>='a')&&(c<='f') ? c-'a'+10
+                       :                      0;
+}
+
+
+
+/*     Get Styles from stylesheet
+**     --------------------------
+*/
+PRIVATE void get_styles NOARGS
+{
+    if (!heading1Style) heading1Style = HTStyleNamed(styleSheet, "Heading1");
+    if (!addressStyle) addressStyle = HTStyleNamed(styleSheet, "Address");
+    if (!textStyle) textStyle = HTStyleNamed(styleSheet, "Example");
+}
+
+
+/*     Paste in an Anchor
+**     ------------------
+**
+**     The title of the destination is set, as there is no way
+**     of knowing what the title is when we arrive.
+**
+** On entry,
+**     HT      is in append mode.
+**     text    points to the text to be put into the file, 0 terminated.
+**     addr    points to the hypertext refernce address 0 terminated.
+*/
+PRIVATE void write_anchor ARGS2(CONST char *,text, CONST char *,addr)
+{
+    HTChildAnchor      *anchor;
+    HTParentAnchor     *dest;
+    
+    HText_beginAnchor(HT,
+               anchor = HTAnchor_findChildAndLink(node_anchor, "",  addr, 0));
+    dest = HTAnchor_parent(
+           HTAnchor_followMainLink((HTAnchor *)anchor));
+           
+    if (!HTAnchor_title(dest)) HTAnchor_setTitle(dest, text);
+           
+    HText_appendText(HT, text);
+    HText_endAnchor(HT);
+}
+
+
+/*     Parse a Gopher Menu document
+**     ============================
+**
+*/
+
+PRIVATE void parse_menu ARGS2 (
+       CONST char *,   arg,
+       HTParentAnchor *,anAnchor)
+{
+    char gtype;
+    char ch;
+    char line[BIG];
+    char address[BIG];
+    char *name, *selector;             /* Gopher menu fields */
+    char *host;
+    char *port;
+    char *p = line;
+    
+
+#define TAB            '\t'
+#define HEX_ESCAPE     '%'
+
+    if (!HTAnchor_title(anAnchor))
+       HTAnchor_setTitle(anAnchor, arg);/* Tell user something's happening */
+    
+    node_anchor = anAnchor;
+    HT = HText_new(anAnchor);
+    
+    HText_beginAppend(HT);
+    HText_appendText(HT, "Select one of:\n");
+    
+    while ((ch=NEXT_CHAR) != (char)EOF) {
+    
+        if (ch != '\n') {
+           *p = ch;            /* Put character in line */
+           if (p< &line[BIG-1]) p++;
+           
+       } else {
+           *p++ = 0;           /* Terminate line */
+           p = line;           /* Scan it to parse it */
+           port = 0;           /* Flag "not parsed" */
+           if (TRACE) fprintf(stderr, "HTGopher: Menu item: %s\n", line);
+           gtype = *p++;
+           
+           /* Break on line with a dot by itself */
+           if ((gtype=='.') && ((*p=='\r') || (*p==0))) break;
+
+           if (gtype && *p) {
+               name = p;
+               selector = strchr(name, TAB);
+               if (selector) {
+                   *selector++ = 0;    /* Terminate name */
+                   host = strchr(selector, TAB);
+                   if (host) {
+                       *host++ = 0;    /* Terminate selector */
+                       port = strchr(host, TAB);
+                       if (port) {
+                           char *junk;
+                           port[0] = ':';      /* delimit host a la W3 */
+                           junk = strchr(port, TAB);
+                           if (junk) *junk++ = 0;      /* Chop port */
+                           if ((port[1]=='0') && (!port[2]))
+                               port[0] = 0;    /* 0 means none */
+                       } /* no port */
+                   } /* host ok */
+               } /* selector ok */
+           } /* gtype and name ok */
+           
+           if (gtype == GOPHER_WWW) {  /* Gopher pointer to W3 */
+               write_anchor(name, selector);
+               HText_appendParagraph(HT);
+
+           } else if (port) {          /* Other types need port */
+               if (gtype == GOPHER_TELNET) {
+                   if (*selector) sprintf(address, "telnet://%s@%s/",
+                       selector, host);
+                   else sprintf(address, "telnet://%s/", host);
+                   
+               } else {                        /* If parsed ok */
+                   char *q;
+                   char *p;
+                   sprintf(address, "//%s/%c", host, gtype);
+                   q = address+ strlen(address);
+                   for(p=selector; *p; p++) {  /* Encode selector string */
+                       if (acceptable[*p]) *q++ = *p;
+                       else {
+                           *q++ = HEX_ESCAPE;  /* Means hex coming */
+                           *q++ = hex[(*p) >> 4];
+                           *q++ = hex[(*p) & 15];
+                       }
+                   }
+                   *q++ = 0;                   /* terminate address */
+               }
+               write_anchor(name, address);
+               HText_appendParagraph(HT);
+           } else { /* parse error */
+               if (TRACE) fprintf(stderr,
+                       "HTGopher: Bad menu item.\n");
+               HText_appendText(HT, line);
+               HText_appendParagraph(HT);
+           } /* parse error */
+           
+           p = line;   /* Start again at beginning of line */
+           
+       } /* if end of line */
+       
+    } /* Loop over characters */
+       
+    HText_endAppend(HT);
+    return;
+}
+
+/*     Display a Gopher Index document
+**     -------------------------------
+*/
+
+PRIVATE void display_index ARGS2 (
+       CONST char *,   arg,
+       HTParentAnchor *,anAnchor)
+{
+    node_anchor = anAnchor;
+    HT = HText_new(anAnchor);
+    HText_beginAppend(HT);
+    HText_setStyle(HT, heading1Style);
+    HText_appendText(HT, arg);
+    HText_setStyle(HT, textStyle);
+    HText_appendText(HT, "\nThis is a searchable index.\n");
+       
+    if (!HTAnchor_title(anAnchor))
+       HTAnchor_setTitle(anAnchor, arg);/* Tell user something's happening */
+    
+    HText_endAppend(HT);
+    return;
+}
+
+
+/*             Load by name                                    HTLoadGopher
+**             ============
+**
+**      Bug:   No decoding of strange data types as yet.
+**
+*/
+PUBLIC int HTLoadGopher ARGS3(
+       CONST char *,arg,
+       HTParentAnchor *,anAnchor,
+       int,diag)
+{
+    char *command;                     /* The whole command */
+    int status;                                /* tcp return */
+    char gtype;                                /* Gopher Node type */
+    char * selector;                   /* Selector string */
+    struct sockaddr_in soc_address;    /* Binary network address */
+    struct sockaddr_in* sin = &soc_address;
+
+    diagnostic = diag;                 /* set global flag */
+    
+    if (!acceptable_inited) init_acceptable();
+    
+    if (!arg) return -3;               /* Bad if no name sepcified     */
+    if (!*arg) return -2;              /* Bad if name had zero length  */
+    
+    if (TRACE) printf("HTGopher: Looking for %s\n", arg);
+    get_styles();
+    
+    
+/*  Set up defaults:
+*/
+    sin->sin_family = AF_INET;                 /* Family, host order  */
+    sin->sin_port = htons(GOPHER_PORT);                /* Default: new port,  */
+
+    if (TRACE) printf("HTTPAccess: Looking for %s\n", arg);
+
+/* Get node name and optional port number:
+*/
+    {
+       char *p1 = HTParse(arg, "", PARSE_HOST);
+       HTParseInet(sin, p1);
+        free(p1);
+    }
+    
+/* Get entity type, and selector string.
+*/        
+    {
+       char * p1 = HTParse(arg, "", PARSE_PATH|PARSE_PUNCTUATION);
+        gtype = '1';           /* Default = menu */
+       selector = p1;
+       if ((*selector++=='/') && (*selector)) {        /* Skip first slash */
+           gtype = *selector++;                        /* Pick up gtype */
+       }
+       if (gtype == GOPHER_INDEX) {
+            HTAnchor_setIndex(anAnchor);       /* Search is allowed */
+           selector = strchr(selector, '?');   /* Look for search string */
+           if (!selector || !*selector) {      /* No search required */
+               display_index(arg, anAnchor);   /* Display "cover page" */
+               return 1;                       /* Local function only */
+           }
+           command = malloc(strlen(selector)+ 2 + 1);
+              if (command == NULL) outofmem(__FILE__, "HTLoadGopher");
+           strcpy(command, selector);
+           
+       } else {                                /* Not index */
+           char * p = selector;
+           char * q = command = malloc(strlen(selector)+2+1);
+              if (command == NULL) outofmem(__FILE__, "HTLoadGopher");
+           while (*p) {                /* Decode hex */
+               if (*p == HEX_ESCAPE) {
+                   char c;
+                   unsigned int b;
+                   p++;
+                   c = *p++;
+                   b =   from_hex(c);
+                   c = *p++;
+                   if (!c) break;      /* Odd number of chars! */
+                   *q++ = (b<<4) + from_hex(c);
+               } else {
+                   *q++ = *p++;        /* Record */
+               }
+           }
+           *q++ = 0;   /* Terminate command */
+       }
+       free(p1);
+    }
+    
+    strcat(command, "\r\n");           /* Include CR for telnet compat. */
+    
+
+/*     Set up a socket to the server for the data:
+*/      
+    s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+    status = connect(s, (struct sockaddr*)&soc_address, sizeof(soc_address));
+    if (status<0){
+       if (TRACE) printf("HTTPAccess: Unable to connect to remote host for `%s'.\n",
+           arg);
+       free(command);
+       return HTInetStatus("connect");
+    }
+    
+    HTInitInput(s);            /* Set up input buffereing */
+    
+    if (TRACE) printf("HTGopher: Connected, writing command `%s' to socket %d\n", command, s);
+    
+#ifdef NOT_ASCII
+    {
+       char * p;
+       for(p = command; *p; p++) {
+           *p = TOASCII(*p);
+       }
+    }
+#endif
+
+    status = NETWRITE(s, command, (int)strlen(command));
+    free(command);
+    if (status<0){
+       if (TRACE) printf("HTGopher: Unable to send command.\n");
+           return HTInetStatus("send");
+    }
+
+/*     Now read the data from the socket:
+*/    
+    if (diagnostic==2) gtype = GOPHER_TEXT;    /* Read as plain text anyway */
+    
+    switch (gtype) {
+    
+    case GOPHER_HTML :
+       HTParseFormat(WWW_HTML, anAnchor, s);
+       return 1;
+
+    case GOPHER_MENU :
+    case GOPHER_INDEX :
+        parse_menu(arg, anAnchor);
+       return 1;
+       
+    case GOPHER_TEXT :
+    default:                   /* @@ parse as plain text */
+       HTParseFormat(WWW_PLAINTEXT, anAnchor, s);
+       return 1;
+    } /* switch(gtype) */
+    /*NOTREACHED*/
+}
+
diff --git a/Cl/WWWLibrary/HTGopher.h b/Cl/WWWLibrary/HTGopher.h
new file mode 100644 (file)
index 0000000..83abf2e
--- /dev/null
@@ -0,0 +1,16 @@
+/*                     GOPHER ACCESS                           HTGopher.h
+**                     =============
+**
+** History:
+**      8 Jan 92       Adapted from HTTP TBL
+*/
+
+#ifndef HTGOPHER_H
+#define HTGOPHER_H
+
+#include "HTAnchor.h"
+extern int HTLoadGopher PARAMS((const char *arg,
+       HTParentAnchor * anAnchor,
+       int diag));
+
+#endif /* HTGOPHER_H */
diff --git a/Cl/WWWLibrary/HTHistory.c b/Cl/WWWLibrary/HTHistory.c
new file mode 100644 (file)
index 0000000..ca5bcb0
--- /dev/null
@@ -0,0 +1,154 @@
+#include "HTHistory.h"
+
+#include "tcp.h"               /* for standard io */
+
+static HTList * history;       /* List of visited anchors */
+
+
+/*                             Navigation
+**                             ==========
+*/
+
+/*             Record the jump to an anchor
+**             ----------------------------
+*/
+
+void HTHistory_record
+  ARGS1 (HTAnchor *,destination)
+{
+  if (destination) {
+    if (! history)
+      history = HTList_new();
+    HTList_addObject (history, destination);
+  }
+}
+
+/*             Go back in history (find the last visited node)
+**             ------------------
+*/
+
+HTAnchor * HTHistory_backtrack
+  NOARGS  /* FIXME: Should we add a `sticky' option ? */
+{
+  if (HTHistory_canBacktrack())
+    HTList_removeLastObject (history);
+  return HTList_lastObject (history);  /* is Home if can't backtrack */
+}
+
+BOOL HTHistory_canBacktrack
+  NOARGS
+{
+  return (HTList_objectAt (history, 1) != NULL);
+}
+
+/*             Browse through references in the same parent node
+**             -------------------------------------------------
+**
+**     Take the n-th child's link after or before the one we took to get here.
+**     Positive offset means go towards most recently added children.
+*/
+
+HTAnchor * HTHistory_moveBy
+ ARGS1 (int,offset)
+{
+  HTAnchor * last = HTList_objectAt (history, 1);
+  if (! last)
+    return NULL;  /* No last visited node */
+  if (last != (HTAnchor *) last->parent) {  /* Was a child */
+    HTList * kids = last->parent->children;
+    int i = HTList_indexOf (kids, last); 
+    HTAnchor * nextOne = HTList_objectAt (kids, i - offset);
+    if (nextOne) {
+      HTAnchor * destination = HTAnchor_followMainLink (nextOne);
+      if (destination) {
+       HTList_removeLastObject (history);
+       HTList_removeLastObject (history);
+       HTList_addObject (history, nextOne);
+       HTList_addObject (history, destination);
+      }
+      return destination;
+    } else {
+      if (TRACE) printf(
+               "HTHistory_moveBy: offset by %+d goes out of list %p.\n",
+               offset, kids);
+      return NULL;
+    }
+  } else {  /* Was a parent */
+    return NULL;  /* FIXME we could possibly follow the next link... */
+  }
+}
+
+BOOL HTHistory_canMoveBy
+ ARGS1 (int,offset)
+{
+  HTAnchor * last = HTList_objectAt (history, 1);
+  if (! last)
+    return NO;  /* No last visited node */
+  if (last != (HTAnchor *) last->parent) {  /* Was a child */
+    HTList * kids = last->parent->children;
+    int i = HTList_indexOf (kids, last); 
+    return (HTList_objectAt (kids, i - offset) != NULL);
+  } else {  /* Was a parent */
+    return NO;  /* FIXME we could possibly follow the next link... */
+  }
+}
+
+
+/*                             Retrieval
+**                             =========
+*/
+
+/*             Read numbered visited anchor (1 is the oldest)
+**             ----------------------------
+*/
+
+HTAnchor * HTHistory_read
+  ARGS1 (int,number)
+{
+  return HTList_objectAt (history, HTList_count (history) - number);
+}
+
+
+/*             Recall numbered visited anchor (1 is the oldest)
+**             ------------------------------
+**     This reads the anchor and stores it again in the list, except if last.
+*/
+
+HTAnchor * HTHistory_recall
+  ARGS1 (int,number)
+{
+  HTAnchor * destination =
+    HTList_objectAt (history, HTList_count (history) - number);
+  if (destination && destination != HTList_lastObject (history))
+    HTList_addObject (history, destination);
+  return destination;
+}
+
+/*             Number of Anchors stored
+**             ------------------------
+**
+**     This is needed in order to check the validity of certain commands
+**     for menus, etc.
+(not needed for now. Use canBacktrack, etc.)
+int HTHistory_count
+  NOARGS
+{
+  return HTList_count (history);
+}
+*/
+
+/*             Change last history entry
+**             -------------------------
+**
+**     Sometimes we load a node by one anchor but leave by a different
+**     one, and it is the one we left from which we want to remember.
+*/
+
+void HTHistory_leavingFrom
+  ARGS1 (HTAnchor *,anchor)
+{
+  if (HTList_removeLastObject (history))
+    HTList_addObject (history, anchor);
+  else
+    if (TRACE) fprintf(stderr, "HTHistory_leavingFrom: empty history !\n");
+}
diff --git a/Cl/WWWLibrary/HTHistory.h b/Cl/WWWLibrary/HTHistory.h
new file mode 100644 (file)
index 0000000..bb1bab0
--- /dev/null
@@ -0,0 +1,107 @@
+#ifndef HTHISTORY_H
+#define HTHISTORY_H
+
+#include "HTAnchor.h"
+
+#ifdef SHORT_NAMES
+#define HTHistory_record               HTHiReco
+#define HTHistory_backtrack            HTHiBack
+#define HTHistory_canBacktrack         HTHiCaBa
+#define HTHistory_moveBy               HTHiMoBy
+#define HTHistory_canMoveBy            HTHiCaMo
+#define HTHistory_read                 HTHiRead
+#define HTHistory_recall               HTHiReca
+#define HTHistory_count                        HTHiCoun
+#define HTHistory_leavingFrom          HTHiLeFr
+#endif
+
+/*                             Navigation
+**                             ==========
+*/
+
+/*             Record the jump to an anchor
+**             ----------------------------
+*/
+
+extern void HTHistory_record
+  PARAMS(
+    (HTAnchor * destination)
+  );
+
+/*             Go back in history (find the last visited node)
+**             ------------------
+*/
+
+extern HTAnchor * HTHistory_backtrack
+  NOPARAMS;  /* FIXME: Should we add a `sticky' option ? */
+
+extern BOOL HTHistory_canBacktrack
+  NOPARAMS;
+
+/*             Browse through references in the same parent node
+**             -------------------------------------------------
+**
+**     Take the n-th child's link after or before the one we took to get here.
+**     Positive offset means go towards most recently added children.
+*/
+
+extern HTAnchor * HTHistory_moveBy
+  PARAMS(
+     (int offset)
+     );
+
+extern BOOL HTHistory_canMoveBy
+  PARAMS(
+     (int offset)
+     );
+
+#define HTHistory_next (HTHistory_moveBy (+1))
+#define HTHistory_canNext (HTHistory_canMoveBy (+1))
+#define HTHistory_previous (HTHistory_moveBy (-1))
+#define HTHistory_canPrevious (HTHistory_canMoveBy (-1))
+
+
+/*                             Retrieval
+**                             =========
+*/
+
+/*             Read numbered visited anchor (1 is the oldest)
+**             ----------------------------
+*/
+
+extern HTAnchor * HTHistory_read
+  PARAMS(
+    (int number)
+  );
+
+/*             Recall numbered visited anchor (1 is the oldest)
+**             ------------------------------
+**     This reads the anchor and stores it again in the list, except if last.
+*/
+
+extern HTAnchor * HTHistory_recall
+  PARAMS(
+    (int number)
+  );
+
+/*             Number of Anchors stored
+**             ------------------------
+**
+**     This is needed in order to check the validity of certain commands
+**     for menus, etc.
+(not needed for now. Use canBacktrack, etc.)
+extern int HTHistory_count NOPARAMS;
+*/
+
+/*             Change last history entry
+**             -------------------------
+**
+**     Sometimes we load a node by one anchor but leave by a different
+**     one, and it is the one we left from which we want to remember.
+*/
+extern void HTHistory_leavingFrom
+  PARAMS(
+    (HTAnchor * anchor)
+  );
+
+#endif /* HTHISTORY_H */
diff --git a/Cl/WWWLibrary/HTList.c b/Cl/WWWLibrary/HTList.c
new file mode 100644 (file)
index 0000000..7d40f3e
--- /dev/null
@@ -0,0 +1,127 @@
+/*     A small List class                                            HTList.c
+**     ==================
+**
+**     A list is represented as a sequence of linked nodes of type HTList.
+**     The first node is a header which contains no object.
+**     New nodes are inserted between the header and the rest of the list.
+*/
+
+#include "HTList.h"
+
+#ifdef ERWISE
+#include <stdio.h>
+#endif
+
+HTList * HTList_new NOARGS
+{
+  HTList *newList = (HTList *)malloc (sizeof (HTList));
+  if (newList == NULL) outofmem(__FILE__, "HTList_new");
+  newList->object = NULL;
+  newList->next = NULL;
+  return newList;
+}
+
+void HTList_delete ARGS1(HTList *,this)
+{
+  HTList *current;
+  while (current = this) {
+    this = this->next;
+    free (current);
+  }
+}
+
+void HTList_addObject ARGS2(HTList *,this, void *,newObject)
+{
+  if (this) {
+    HTList *newNode = (HTList *)malloc (sizeof (HTList));
+    if (newNode == NULL) outofmem(__FILE__, "HTList_addObject");
+    newNode->object = newObject;
+    newNode->next = this->next;
+    this->next = newNode;
+  }
+  else
+    if (TRACE) printf ("HTList: Trying to add object %p to a nonexisting list\n",
+                      newObject);
+}
+
+BOOL HTList_removeObject ARGS2(HTList *,this, void *,oldObject)
+{
+  if (this) {
+    HTList *previous;
+    while (this->next) {
+      previous = this;
+      this = this->next;
+      if (this->object == oldObject) {
+       previous->next = this->next;
+       free (this);
+       return YES;  /* Success */
+      }
+    }
+  }
+  return NO;  /* object not found or NULL list */
+}
+
+void * HTList_removeLastObject ARGS1 (HTList *,this)
+{
+  if (this && this->next) {
+    HTList *lastNode = this->next;
+    void * lastObject = lastNode->object;
+    this->next = lastNode->next;
+    free (lastNode);
+    return lastObject;
+  } else  /* Empty list */
+    return NULL;
+}
+
+void * HTList_removeFirstObject ARGS1 (HTList *,this)
+{
+  if (this && this->next) {
+    HTList * prevNode;
+    void *firstObject;
+    while (this->next) {
+      prevNode = this;
+      this = this->next;
+    }
+    firstObject = this->object;
+    prevNode->next = NULL;
+    free (this);
+    return firstObject;
+  } else  /* Empty list */
+    return NULL;
+}
+
+int HTList_count ARGS1 (HTList *,this)
+{
+  int count = 0;
+  if (this)
+    while (this = this->next)
+      count++;
+  return count;
+}
+
+int HTList_indexOf ARGS2(HTList *,this, void *,object)
+{
+  if (this) {
+    int position = 0;
+    while (this = this->next) {
+      if (this->object == object)
+       return position;
+      position++;
+    }
+  }
+  return -1;  /* Object not in the list */
+}
+
+void * HTList_objectAt ARGS2 (HTList *,this, int,position)
+{
+  if (position < 0)
+    return NULL;
+  if (this) {
+    while (this = this->next) {
+      if (position == 0)
+       return this->object;
+      position--;
+    }
+  }
+  return NULL;  /* Reached the end of the list */
+}
diff --git a/Cl/WWWLibrary/HTList.h b/Cl/WWWLibrary/HTList.h
new file mode 100644 (file)
index 0000000..4aed995
--- /dev/null
@@ -0,0 +1,49 @@
+/*             List object
+**
+**     The list object is a generic container for storing collections
+**     of things in order.
+*/
+#ifndef HTLIST_H
+#define HTLIST_H
+
+#include "HTUtils.h"  /* for BOOL type and PARAMS and ARGS*/
+
+typedef struct _HTList HTList;
+
+struct _HTList {
+  void * object;
+  HTList * next;
+};
+
+#ifdef SHORT_NAMES
+#define HTList_new                     HTLiNew
+#define HTList_delete                  HTLiDele
+#define HTList_addObject               HTLiAdOb
+#define HTList_removeObject            HTLiReOb
+#define HTList_removeLastObject                HTLiReLa
+#define HTList_removeFirstObject       HTLiReFi
+#define HTList_count                   HTLiCoun
+#define HTList_indexOf                 HTLiInOf
+#define HTList_objectAt                        HTLiObAt
+#endif
+
+extern HTList *        HTList_new NOPARAMS;
+extern void    HTList_delete PARAMS((HTList *this));
+extern void    HTList_addObject PARAMS((HTList *this, void *newObject));
+extern BOOL    HTList_removeObject PARAMS((HTList *this, void *oldObject));
+extern void *  HTList_removeLastObject PARAMS((HTList *this));
+extern void *  HTList_removeFirstObject PARAMS((HTList *this));
+#define        HTList_isEmpty(this) (this ? this->next == NULL : YES)
+extern int     HTList_count PARAMS((HTList *this));
+extern int     HTList_indexOf PARAMS((HTList *this, void *object));
+#define        HTList_lastObject(this) \
+  (this && this->next ? this->next->object : NULL)
+extern void *  HTList_objectAt PARAMS((HTList *this, int position));
+
+/* Fast macro to traverse the list. Call it first with copy of list header :
+   it returns the first object and increments the passed list pointer.
+   Call it with the same variable until it returns NULL. */
+#define HTList_nextObject(this) \
+  (this && (this = this->next) ? this->object : NULL)
+
+#endif /* HTLIST_H */
diff --git a/Cl/WWWLibrary/HTML.c b/Cl/WWWLibrary/HTML.c
new file mode 100644 (file)
index 0000000..ec1471d
--- /dev/null
@@ -0,0 +1,429 @@
+/*             HTML Parser
+**             ===========
+*/
+#include <ctype.h>
+#include <stdio.h>
+
+#include "HTUtils.h"
+#include "SGML.h"
+#include "HTAtom.h"
+#include "HTChunk.h"
+#include "HText.h"
+#include "HTStyle.h"
+#include "HTML.h"
+
+
+/*                             SPECIAL HTML CODE
+**                             =================
+*/
+
+extern HTStyleSheet * styleSheet;      /* Application-wide */
+
+PRIVATE HTParentAnchor * node_anchor;
+PRIVATE HText * text;
+
+PRIVATE HTStyle * glossary_style;
+PRIVATE HTStyle * list_compact_style;
+PRIVATE HTStyle * glossary_compact_style;
+
+PRIVATE HTChunk title = { 0, 128, 0, 0 };      /* Grow by 128 */
+
+
+/*     Forward declarations of routines for DTD
+*/
+PRIVATE void no_change PARAMS((HTTag * t, HTElement * e));
+PRIVATE void begin_litteral PARAMS((HTTag * t, HTElement * e));
+PRIVATE void begin_element PARAMS((HTTag * t, HTElement * e));
+PRIVATE void end_element PARAMS((HTTag * t, HTElement * e));
+PRIVATE void begin_document PARAMS((HTTag * t, HTElement * e));
+PRIVATE void end_document PARAMS((HTTag * t, HTElement * e));
+PRIVATE void begin_anchor PARAMS((HTTag * t, HTElement * e));
+PRIVATE void end_anchor PARAMS((HTTag * t, HTElement * e));
+PRIVATE void begin_list PARAMS((HTTag * t, HTElement * e));
+PRIVATE void list_element PARAMS((HTTag * t, HTElement * e));
+PRIVATE void end_list PARAMS((HTTag * t, HTElement * e));
+PRIVATE void begin_glossary PARAMS((HTTag * t, HTElement * e));
+PRIVATE void end_glossary PARAMS((HTTag * t, HTElement * e));
+
+PRIVATE int got_styles = 0;
+PRIVATE void get_styles NOPARAMS;
+
+PRIVATE        BOOL            style_change;
+PRIVATE HTStyle *      new_style;
+PRIVATE HTStyle *      old_style;
+PRIVATE BOOL           in_word;  /* Have just had a non-white character */
+
+/*     Style buffering avoids dummy paragraph begin/ends.
+*/
+#define UPDATE_STYLE if (style_change) { \
+       HText_setStyle(text, new_style); \
+       old_style = new_style; \
+       style_change = NO; }
+
+PRIVATE void change_style ARGS1(HTStyle *,style)
+{
+    if (new_style!=style) {
+       style_change = YES /* was old_style == new_style */ ;
+       new_style = style;
+    }
+}
+
+
+/*             TITLE
+*/
+
+/*     Accumulate a character of title
+*/
+#ifdef __STDC__
+static void accumulate_string(char c)
+#else
+static void accumulate_string(c)
+    char c;
+#endif
+{
+    HTChunkPutc(&title, c);
+}
+
+
+/*             Clear the title
+*/
+PRIVATE  void clear_string ARGS2(HTTag *,t, HTElement *,e)
+{
+    HTChunkClear(&title);
+}
+
+PRIVATE void set_title ARGS2(HTTag *,t, HTElement *,e)
+{
+    HTChunkTerminate(&title);
+    HTAnchor_setTitle(node_anchor, title.data);
+}
+
+/*             Character handling
+*/
+PRIVATE void set_index ARGS2(HTTag *,t, HTElement *,e)
+{
+    HTAnchor_setIndex(node_anchor);
+}
+
+PRIVATE void pass_character ARGS1(char, c)
+{
+    if (style_change) {
+        if ((c=='\n') || (c==' ')) return;     /* Ignore it */
+        UPDATE_STYLE;
+    }
+    if (c=='\n') {
+        if (in_word) {
+           HText_appendCharacter(text, ' ');
+           in_word = NO;
+       }
+    } else {
+        HText_appendCharacter(text, c);
+       in_word = YES;
+    }
+}
+
+PRIVATE void litteral_text ARGS1(char, c)
+{
+/*     We guarrantee that the style is up-to-date in begin_litteral
+*/
+    HText_appendCharacter(text, c);            /* @@@@@ */
+}
+
+PRIVATE void ignore_text ARGS1(char, c)
+{
+    /* Do nothing */
+}
+
+PRIVATE void set_next_id  ARGS2(HTTag *,t, HTElement *,e)
+{
+    /* @@@@@  Bad SGML anyway */
+}
+
+PRIVATE void new_paragraph  ARGS2(HTTag *,t, HTElement *,e)
+{
+    UPDATE_STYLE;
+    HText_appendParagraph(text);
+    in_word = NO;
+}
+
+PRIVATE void term ARGS2(HTTag *,t, HTElement *,e)
+{
+    if (!style_change) {
+        HText_appendParagraph(text);
+       in_word = NO;
+    }
+}
+
+PRIVATE void definition ARGS2(HTTag *,t, HTElement *,e)
+{
+    UPDATE_STYLE;
+    pass_character('\t');      /* Just tab out one stop */
+    in_word = NO;
+}
+
+/*             Our Static DTD for HTML
+**             -----------------------
+*/
+
+static entity entities[] = {
+       { "lt", "<" },
+       { "gt", ">" },
+       { "amp", "&" },
+       { "bullet" , "\267" },                  /* @@@ NeXT only */
+       { 0,    0 }  /* Terminate list */
+};
+
+static attr no_attr[] = {{ 0, 0 , 0}};
+
+static attr a_attr[] = {                               /* Anchor attributes */
+#define A_ID 0
+       { "NAME", 0, 0 },                               /* Should be ID */
+#define A_TYPE 1
+       { "TYPE", 0, 0 },
+#define A_HREF 2
+       { "HREF", 0, 0 },
+       { 0, 0 , 0}     /* Terminate list */
+};     
+static attr list_attr[] = {
+#define LIST_COMPACT 0
+       { "COMPACT", 0, 0 },
+       { 0, 0, 0 }     /* Terminate list */
+};
+
+static attr glossary_attr[] = {
+#define GLOSSARY_COMPACT 0
+       { "COMPACT", 0, 0 },
+       { 0, 0, 0 }     /* Terminate list */
+};
+
+static HTTag default_tag =
+    { "DOCUMENT", no_attr , 0, 0, begin_document, pass_character, end_document };
+/*     NAME ATTR  STYLE LITERAL?  ON_BEGIN   ON__CHARACTER     ON_END
+*/
+static HTTag tags[] = {
+#define TITLE_TAG 0
+    { "TITLE", no_attr, 0, 0, clear_string, accumulate_string, set_title },
+#define ISINDEX_TAG 1
+    { "ISINDEX", no_attr, 0, 0, set_index, 0 , 0 },
+#define NEXTID_TAG 2
+    { "NEXTID", no_attr, 0, 0, set_next_id, 0, 0 },
+#define ADDRESS_TAG 3
+    { "ADDRESS"        , no_attr, 0, 0, begin_element, pass_character, end_element },
+#define H1_TAG 4
+    { "H1"     , no_attr, 0, 0, begin_element, pass_character, end_element },
+    { "H2"     , no_attr, 0, 0, begin_element, pass_character, end_element },
+    { "H3"     , no_attr, 0, 0, begin_element, pass_character, end_element },
+    { "H4"     , no_attr, 0, 0, begin_element, pass_character, end_element },
+    { "H5"     , no_attr, 0, 0, begin_element, pass_character, end_element },
+    { "H6"     , no_attr, 0, 0, begin_element, pass_character, end_element },
+    { "H7"     , no_attr, 0, 0, begin_element, pass_character, end_element },
+#define UL_TAG 11
+    { "UL"     , list_attr, 0, 0, begin_list, pass_character, end_list },
+#define OL_TAG 12
+    { "OL"     , list_attr, 0, 0, begin_list, pass_character, end_list },
+#define MENU_TAG 13
+    { "MENU"   , list_attr, 0, 0, begin_list, pass_character, end_list },
+#define DIR_TAG 14
+    { "DIR"    , list_attr, 0, 0, begin_list, pass_character, end_list },
+#define LI_TAG 15
+    { "LI"     , no_attr, 0, 0, list_element, pass_character, 0 },
+#define DL_TAG 16
+    { "DL"     , list_attr, 0, 0, begin_glossary, pass_character, end_glossary },
+    { "DT"     , no_attr, 0, 0, term, pass_character, 0 },
+    { "DD"     , no_attr, 0, 0, definition, pass_character, 0 },
+    { "A"      , a_attr,  0, 0, begin_anchor, pass_character, end_anchor },
+#define P_TAG 20
+    { "P"      , no_attr, 0, 0, new_paragraph, pass_character, 0 },
+#define XMP_TAG 21
+  { "XMP"      , no_attr, 0, YES, begin_litteral, litteral_text, end_element },
+#define LISTING_TAG 22
+  { "LISTING"  , no_attr, 0, YES,begin_litteral, litteral_text, end_element },
+#define PLAINTEXT_TAG 23
+  { "PLAINTEXT", no_attr, 0, YES, begin_litteral, litteral_text, end_element },
+#define COMMENT_TAG 24
+    { "COMMENT", no_attr, 0, YES, no_change, ignore_text, no_change },
+    { 0, 0, 0, 0,  0, 0 , 0}   /* Terminate list */
+};
+
+PUBLIC SGML_dtd HTML_dtd = { tags, &default_tag, entities };
+
+
+/*             Flattening the style structure
+**             ------------------------------
+**
+On the NeXT, and on any read-only browser, it is simpler for the text to have
+a sequence of styles, rather than a nested tree of styles. In this
+case we have to flatten the structure as it arrives from SGML tags into
+a sequence of styles.
+*/
+
+/*     Anchor handling
+**     ---------------
+*/
+PRIVATE void begin_anchor ARGS2(HTTag *,t, HTElement *,e)
+{
+    HTChildAnchor * source = HTAnchor_findChildAndLink(
+       node_anchor,                                            /* parent */
+       a_attr[A_ID].present    ? a_attr[A_ID].value : 0,       /* Tag */
+       a_attr[A_HREF].present  ? a_attr[A_HREF].value : 0,     /* Addresss */
+       a_attr[A_TYPE].present  ? 
+               (HTLinkType*)HTAtom_for(a_attr[A_TYPE].value)
+                : 0);
+    
+    UPDATE_STYLE;
+    HText_beginAnchor(text, source);
+}
+
+PRIVATE void end_anchor ARGS2(HTTag *,  t,
+                       HTElement *,    e)
+{
+    UPDATE_STYLE;
+    HText_endAnchor(text);
+}
+
+
+/*     General SGML Element Handling
+**     -----------------------------
+*/
+PRIVATE void begin_element ARGS2(HTTag *,t, HTElement *,e)
+{
+    change_style((HTStyle*)(t->style));
+}
+PRIVATE void no_change ARGS2(HTTag *,t, HTElement *,e)
+{
+    /* Do nothing */;
+}
+PRIVATE void begin_litteral ARGS2(HTTag *,t, HTElement *,e)
+{
+    change_style(t->style);
+    UPDATE_STYLE;
+}
+PRIVATE void end_element ARGS2(HTTag *,t, HTElement *,e)
+{
+    if (e) change_style(e->tag->style);
+}
+
+/*                     Lists
+*/
+PRIVATE void begin_list ARGS2(HTTag *,t, HTElement *,e)
+{
+    change_style(list_attr[LIST_COMPACT].present
+               ? list_compact_style
+               : (HTStyle*)(t->style));
+    in_word = NO;
+}
+
+PRIVATE void end_list ARGS2(HTTag *,t, HTElement *,e)
+{
+    change_style(e->tag->style);
+    in_word = NO;
+}
+
+PRIVATE void list_element  ARGS2(HTTag *,t, HTElement *,e)
+{
+    if (e->tag != &tags[DIR_TAG])
+       HText_appendParagraph(text);
+    else
+        HText_appendCharacter(text, '\t');     /* Tab @@ nl for UL? */
+    in_word = NO;
+}
+
+
+PRIVATE void begin_glossary ARGS2(HTTag *,t, HTElement *,e)
+{
+    change_style(glossary_attr[GLOSSARY_COMPACT].present
+               ? glossary_compact_style
+               : glossary_style);
+    in_word = NO;
+}
+
+PRIVATE void end_glossary ARGS2(HTTag *,t, HTElement *,e)
+{
+    change_style(e->tag->style);
+    in_word = NO;
+}
+
+
+/*     Begin and End document
+**     ----------------------
+*/
+PUBLIC void HTML_begin ARGS1(HTParentAnchor *,anchor)
+{
+    node_anchor = anchor;
+}
+
+PRIVATE void begin_document ARGS2(HTTag *, t, HTElement *, e)
+{
+    if (!got_styles) get_styles();
+    text = HText_new(node_anchor);
+    HText_beginAppend(text);
+    HText_setStyle(text, default_tag.style);
+    old_style = 0;
+    style_change = NO;
+    in_word = NO;
+}
+
+PRIVATE void end_document ARGS2(HTTag *, t, HTElement *, e)
+{
+    HText_endAppend(text);
+
+}
+
+/*     Get Styles from style sheet
+**     ---------------------------
+*/
+PRIVATE void get_styles NOARGS
+{
+    got_styles = YES;
+    
+    tags[P_TAG].style =
+    default_tag.style =                HTStyleNamed(styleSheet, "Normal");
+    tags[H1_TAG].style =       HTStyleNamed(styleSheet, "Heading1");
+    tags[H1_TAG+1].style =     HTStyleNamed(styleSheet, "Heading2");
+    tags[H1_TAG+2].style =     HTStyleNamed(styleSheet, "Heading3");
+    tags[H1_TAG+3].style =     HTStyleNamed(styleSheet, "Heading4");
+    tags[H1_TAG+4].style =     HTStyleNamed(styleSheet, "Heading5");
+    tags[H1_TAG+5].style =     HTStyleNamed(styleSheet, "Heading6");
+    tags[H1_TAG+6].style =     HTStyleNamed(styleSheet, "Heading7");
+    tags[DL_TAG].style =       HTStyleNamed(styleSheet, "Glossary");
+    tags[UL_TAG].style =       HTStyleNamed(styleSheet, "List");
+    tags[OL_TAG].style =       HTStyleNamed(styleSheet, "List");
+    tags[MENU_TAG].style =     HTStyleNamed(styleSheet, "Menu");
+    list_compact_style =
+    tags[DIR_TAG].style =      HTStyleNamed(styleSheet, "Dir");    
+    glossary_style =           HTStyleNamed(styleSheet, "Glossary");
+    glossary_compact_style =   HTStyleNamed(styleSheet, "GlossaryCompact");
+    tags[ADDRESS_TAG].style=   HTStyleNamed(styleSheet, "Address");
+    tags[PLAINTEXT_TAG].style =
+    tags[XMP_TAG].style =      HTStyleNamed(styleSheet, "Example");
+    tags[LISTING_TAG].style =  HTStyleNamed(styleSheet, "Listing");
+}
+
+
+/*     Parse an HTML file
+**     ------------------
+**
+**     This version takes a pointer to the routine to call
+**     to get each character.
+*/
+BOOL HTML_Parse
+#ifdef __STDC__
+  (HTParentAnchor * anchor, char (*next_char)() )
+#else
+  (anchor, next_char)
+    HTParentAnchor * anchor;
+    char (*next_char)();
+#endif
+{
+        HTML_begin(anchor);
+       SGML_begin(&HTML_dtd);
+       for(;;) {
+           char character;
+           character = (*next_char)();
+           if (character == (char)EOF) break;
+    
+           SGML_character(&HTML_dtd, character);           
+         }
+       SGML_end(&HTML_dtd);
+       return YES;
+}
diff --git a/Cl/WWWLibrary/HTML.h b/Cl/WWWLibrary/HTML.h
new file mode 100644 (file)
index 0000000..acbe240
--- /dev/null
@@ -0,0 +1,17 @@
+/*             The HTML Parser                                 HTML.h
+**             ---------------
+*/
+
+#ifndef HTML_H
+#define HTML_H
+
+#include "HTUtils.h"
+#include "HTAnchor.h"
+#include "SGML.h"
+
+extern SGML_dtd HTML_dtd;      /* The DTD */
+extern void HTML_begin PARAMS((HTParentAnchor * anchor));
+extern BOOL HTML_Parse PARAMS((
+       HTParentAnchor * anchor,
+       char (*next_char)() ));
+#endif
diff --git a/Cl/WWWLibrary/HTNews.c b/Cl/WWWLibrary/HTNews.c
new file mode 100644 (file)
index 0000000..94b827d
--- /dev/null
@@ -0,0 +1,943 @@
+/*                     NEWS ACCESS                             HTNews.c
+**                     ===========
+**
+** History:
+**     26 Sep 90       Written TBL
+**     29 Nov 91       Downgraded to C, for portable implementation.
+*/
+
+#define NEWS_PORT 119          /* See rfc977 */
+#define APPEND                 /* Use append methods */
+#define MAX_CHUNK      40      /* Largest number of articles in one window */
+#define CHUNK_SIZE     20      /* Number of articles for quick display */
+
+#ifndef DEFAULT_NEWS_HOST
+#define DEFAULT_NEWS_HOST "news"
+#endif
+#ifndef SERVER_FILE
+#define SERVER_FILE "/usr/local/lib/rn/server"
+#endif
+
+#include <ctype.h>
+#include "HTUtils.h"           /* Coding convention macros */
+#include "tcp.h"
+
+#include "HTNews.h"
+
+#include "HText.h"
+#include "HTParse.h"
+#include "HTFormat.h"
+
+#ifdef NeXTStep
+#include <appkit/defaults.h>
+#define NEWS_PROGRESS(foo)
+#else
+#define NEWS_PROGRESS(foo) fprintf(stderr, "%s\n", (foo))
+#endif
+
+extern HTStyleSheet * styleSheet;
+
+#define NEXT_CHAR HTGetChararcter()
+#define LINE_LENGTH 512                        /* Maximum length of line of ARTICLE etc */
+#define GROUP_NAME_LENGTH      256     /* Maximum length of group name */
+
+
+/*     Module-wide variables
+*/
+PRIVATE char * NewsHost;
+PRIVATE struct sockaddr_in soc_address;                /* Binary network address */
+PRIVATE int s;                                 /* Socket for NewsHost */
+PRIVATE char response_text[LINE_LENGTH+1];     /* Last response */
+PRIVATE HText *        HT;                             /* the new hypertext */
+PRIVATE HTParentAnchor *node_anchor;           /* Its anchor */
+PRIVATE int    diagnostic;                     /* level: 0=none 2=source */
+
+PRIVATE HTStyle *addressStyle;                 /* For address etc */
+PRIVATE HTStyle *heading1Style;                        /* For heading level 1 */
+PRIVATE HTStyle *textStyle;                    /* Text style */
+
+
+/*     Initialisation for this module
+**     ------------------------------
+**
+**     Except on the NeXT, we pick up the NewsHost name from
+**
+**     1.      Environment variable NNTPSERVER
+**     2.      File SERVER_FILE
+**     3.      Compilation time macro DEFAULT_NEWS_HOST
+**     4.      Default to "news"
+**
+**     On the NeXT, we pick up the NewsHost name from, in order:
+**
+**     1.      WorldWideWeb default "NewsHost"
+**     2.      Global default "NewsHost"
+**     3.      News default "NewsHost"
+**     4.      Compilation time macro DEFAULT_NEWS_HOST
+**     5.      Defualt to "news"
+*/
+PRIVATE BOOL initialized = NO;
+PRIVATE BOOL initialize NOARGS
+{
+    CONST struct hostent  *phost;        /* Pointer to host - See netdb.h */
+    struct sockaddr_in* sin = &soc_address;
+
+        
+/*  Set up defaults:
+*/
+    sin->sin_family = AF_INET;         /* Family = internet, host order  */
+    sin->sin_port = htons(NEWS_PORT);   /* Default: new port,    */
+
+/*   Get name of Host
+*/
+#ifdef NeXTStep
+    if ((NewsHost = NXGetDefaultValue("WorldWideWeb","NewsHost"))==0)
+        if ((NewsHost = NXGetDefaultValue("News","NewsHost")) == 0)
+           NewsHost = "cernvax.cern.ch";
+#else
+    if (getenv("NNTPSERVER")) {
+        StrAllocCopy(NewsHost, (char *)getenv("NNTPSERVER"));
+       if (TRACE) fprintf(stderr, "HTNews: NNTPSERVER defined as `%s'\n",
+               NewsHost);
+    } else {
+        char server_name[256];
+        FILE* fp = fopen(SERVER_FILE, "r");
+        if (fp) {
+           if (fscanf(fp, "%s", server_name)==1) {
+               StrAllocCopy(NewsHost, server_name);
+               if (TRACE) fprintf(stderr,
+               "HTNews: File %s defines news host as `%s'\n",
+                       SERVER_FILE, NewsHost);
+           }
+           fclose(fp);
+       }
+    }
+    if (!NewsHost) NewsHost = DEFAULT_NEWS_HOST;
+#endif
+
+    if (*NewsHost>='0' && *NewsHost<='9') {   /* Numeric node address: */
+       sin->sin_addr.s_addr = inet_addr((char *)NewsHost); /* See arpa/inet.h */
+
+    } else {               /* Alphanumeric node name: */
+       phost=gethostbyname((char*)NewsHost);   /* See netdb.h */
+       if (!phost) {
+#ifdef NeXTStep
+           NXRunAlertPanel(NULL, "Can't find internet node name `%s'.",
+               NULL,NULL,NULL,
+               NewsHost);
+#else
+           fprintf(stderr,
+             "HTNews: Can't find internet node name `%s'.\n",NewsHost);
+#endif
+           CTRACE(tfp,
+             "HTNews: Can't find internet node name `%s'.\n",NewsHost);
+           return NO;  /* Fail */
+       }
+       memcpy(&sin->sin_addr, phost->h_addr, phost->h_length);
+    }
+
+    if (TRACE) printf( 
+       "HTNews: Parsed address as port %4x, inet %d.%d.%d.%d\n",
+               (unsigned int)ntohs(sin->sin_port),
+               (int)*((unsigned char *)(&sin->sin_addr)+0),
+               (int)*((unsigned char *)(&sin->sin_addr)+1),
+               (int)*((unsigned char *)(&sin->sin_addr)+2),
+               (int)*((unsigned char *)(&sin->sin_addr)+3));
+
+    s = -1;            /* Disconnected */
+    
+    return YES;
+}
+
+
+
+/*     Get Styles from stylesheet
+**     --------------------------
+*/
+PRIVATE void get_styles NOARGS
+{
+    if (!heading1Style) heading1Style = HTStyleNamed(styleSheet, "Heading1");
+    if (!addressStyle) addressStyle = HTStyleNamed(styleSheet, "Address");
+    if (!textStyle) textStyle = HTStyleNamed(styleSheet, "Example");
+}
+
+
+/*     Send NNTP Command line to remote host & Check Response
+**     ------------------------------------------------------
+**
+** On entry,
+**     command points to the command to be sent, including CRLF, or is null
+**             pointer if no command to be sent.
+** On exit,
+**     Negative status indicates transmission error, socket closed.
+**     Positive status is an NNTP status.
+*/
+
+
+PRIVATE int response ARGS1(CONST char *,command)
+{
+    int result;    
+    char * p = response_text;
+    if (command) {
+        int status = NETWRITE(s, command, (int)strlen(command));
+       if (status<0){
+           if (TRACE) fprintf(stderr,
+               "HTNews: Unable to send `%s'. Disconnecting.\n");
+           NETCLOSE(s);
+           s = -1;
+           return status;
+       } /* if bad status */
+       if (TRACE) printf("NNTP command sent: %s", command);
+    } /* if command to be sent */
+    
+    for(;;) {  
+       if (((*p++=NEXT_CHAR) == '\n') || (p == &response_text[LINE_LENGTH])) {
+           *p++=0;                             /* Terminate the string */
+           if (TRACE) printf("NNTP Response: %s\n", response_text);
+           sscanf(response_text, "%d", &result);
+           return result;          
+       } /* if end of line */
+       
+       if (*(p-1) < 0) {
+           if (TRACE) fprintf(stderr,
+               "HTNews: EOF on read, closing socket %d\n", s);
+           NETCLOSE(s);        /* End of file, close socket */
+           return s = -1;      /* End of file on response */
+       }
+    } /* Loop over characters */
+}
+
+
+/*     Case insensitive string comparisons
+**     -----------------------------------
+**
+** On entry,
+**     template must be already un upper case.
+**     unknown may be in upper or lower or mixed case to match.
+*/
+PRIVATE BOOL match ARGS2 (CONST char *,unknown, CONST char *,template)
+{
+    CONST char * u = unknown;
+    CONST char * t = template;
+    for (;*u && *t && (TOUPPER(*u)==*t); u++, t++) /* Find mismatch or end */ ;
+    return (BOOL)(*t==0);              /* OK if end of template */
+}
+
+/*     Find Author's name in mail address
+**     ----------------------------------
+**
+** On exit,
+**     THE EMAIL ADDRESS IS CORRUPTED
+**
+** For example, returns "Tim Berners-Lee" if given any of
+**     " Tim Berners-Lee <tim@online.cern.ch> "
+**  or " tim@online.cern.ch ( Tim Berners-Lee ) "
+*/
+PRIVATE char * author_name ARGS1 (char *,email)
+{
+    char *s, *e;
+    
+    if ((s=strchr(email,'(')) && (e=strchr(email, ')')))
+        if (e>s) {
+           *e=0;                       /* Chop off everything after the ')'  */
+           return HTStrip(s+1);        /* Remove leading and trailing spaces */
+       }
+       
+    if ((s=strchr(email,'<')) && (e=strchr(email, '>')))
+        if (e>s) {
+           strcpy(s, e+1);             /* Remove <...> */
+           return HTStrip(email);      /* Remove leading and trailing spaces */
+       }
+       
+    return HTStrip(email);             /* Default to the whole thing */
+
+}
+
+
+/*     Paste in an Anchor
+**     ------------------
+**
+**
+** On entry,
+**     HT      has a selection of zero length at the end.
+**     text    points to the text to be put into the file, 0 terminated.
+**     addr    points to the hypertext refernce address,
+**             terminated by white space, comma, NULL or '>' 
+*/
+PRIVATE void write_anchor ARGS2(CONST char *,text, CONST char *,addr)
+{
+    char href[LINE_LENGTH+1];
+               
+    {
+       CONST char * p;
+       strcpy(href,"news:");
+       for(p=addr; *p && (*p!='>') && !WHITE(*p) && (*p!=','); p++);
+        strncat(href, addr, p-addr);   /* Make complete hypertext reference */
+    }
+    
+    HText_beginAnchor(HT,
+               HTAnchor_findChildAndLink(node_anchor, "",  href, 0));
+    HText_appendText(HT, text);
+    HText_endAnchor(HT);
+}
+
+
+/*     Write list of anchors
+**     ---------------------
+**
+**     We take a pointer to a list of objects, and write out each,
+**     generating an anchor for each.
+**
+** On entry,
+**     HT      has a selection of zero length at the end.
+**     text    points to a comma or space separated list of addresses.
+** On exit,
+**     *text   is NOT any more chopped up into substrings.
+*/
+PRIVATE void write_anchors ARGS1 (char *,text)
+{
+    char * start = text;
+    char * end;
+    char c;
+    for (;;) {
+        for(;*start && (WHITE(*start)); start++);  /* Find start */
+       if (!*start) return;                    /* (Done) */
+        for(end=start; *end && (*end!=' ') && (*end!=','); end++);/* Find end */
+       if (*end) end++;        /* Include comma or space but not NULL */
+       c = *end;
+       *end = 0;
+       write_anchor(start, start);
+       *end = c;
+       start = end;                    /* Point to next one */
+    }
+}
+
+/*     Abort the connection                                    abort_socket
+**     --------------------
+*/
+PRIVATE void abort_socket NOARGS
+{
+    if (TRACE) fprintf(stderr,
+           "HTNews: EOF on read, closing socket %d\n", s);
+    NETCLOSE(s);       /* End of file, close socket */
+    HText_appendText(HT, "Network Error: connection lost");
+    HText_appendParagraph(HT);
+    s = -1;            /* End of file on response */
+    return;
+}
+
+/*     Read in an Article                                      read_article
+**     ------------------
+**
+**
+**     Note the termination condition of a single dot on a line by itself.
+**     RFC 977 specifies that the line "folding" of RFC850 is not used, so we
+**     do not handle it here.
+**
+** On entry,
+**     s       Global socket number is OK
+**     HT      Global hypertext object is ready for appending text
+*/       
+PRIVATE void read_article NOARGS
+{
+
+    char line[LINE_LENGTH+1];
+    char *references=NULL;                     /* Hrefs for other articles */
+    char *newsgroups=NULL;                     /* Newsgroups list */
+    char *p = line;
+    BOOL done = NO;
+    
+/*     Read in the HEADer of the article:
+**
+**     The header fields are either ignored, or formatted and put into the
+**      Text.
+*/
+    if (!diagnostic) {
+        HText_setStyle(HT, addressStyle);
+       while(!done){
+           char ch = *p++ = NEXT_CHAR;
+           if (ch==(char)EOF) {
+               abort_socket(); /* End of file, close socket */
+               return;         /* End of file on response */
+           }
+           if ((ch == '\n') || (p == &line[LINE_LENGTH])) {
+               *--p=0;                         /* Terminate the string */
+               if (TRACE) printf("H %s\n", line);
+
+               if (line[0]=='.') {     
+                   if (line[1]<' ') {          /* End of article? */
+                       done = YES;
+                       break;
+                   }
+               
+               } else if (line[0]<' ') {
+                   break;              /* End of Header? */
+               } else if (match(line, "SUBJECT:")) {
+                   HTAnchor_setTitle(node_anchor, line+8);
+                   HText_setStyle(HT, heading1Style);
+                   HText_appendText(HT, line+8);
+                   HText_setStyle(HT, addressStyle);
+               } else if (match(line, "DATE:")
+                       || match(line, "FROM:")
+                       || match(line, "ORGANIZATION:")) {
+                   strcat(line, "\n");
+                   HText_appendText(HT, strchr(line,':')+1);
+               } else if (match(line, "NEWSGROUPS:")) {
+                   StrAllocCopy(newsgroups, HTStrip(strchr(line,':')+1));
+                   
+               } else if (match(line, "REFERENCES:")) {
+                   StrAllocCopy(references, HTStrip(strchr(line,':')+1));
+                   
+               } /* end if match */
+               p = line;                       /* Restart at beginning */
+           } /* if end of line */
+       } /* Loop over characters */
+    
+       HText_appendCharacter(HT, '\n');
+       HText_setStyle(HT, textStyle);
+       if (newsgroups) {
+           HText_appendText(HT, "\nNewsgroups: ");
+           write_anchors(newsgroups);
+           free(newsgroups);
+       }
+       
+       if (references) {
+           HText_appendText(HT, "\nReferences: ");
+           write_anchors(references);
+           free(references);
+       }
+    
+       HText_appendText(HT, "\n\n\n");
+       
+    } else { /* diagnostic */
+        HText_setStyle(HT, textStyle);
+    }
+    
+/*     Read in the BODY of the Article:
+*/
+    p = line;
+    while(!done){
+       char ch = *p++ = NEXT_CHAR;
+       if (ch==(char)EOF) {
+           abort_socket();     /* End of file, close socket */
+           return;             /* End of file on response */
+       }
+       if ((ch == '\n') || (p == &line[LINE_LENGTH])) {
+           *p++=0;                             /* Terminate the string */
+           if (TRACE) printf("B %s", line);
+           if (line[0]=='.') {
+               if (line[1]<' ') {              /* End of article? */
+                   done = YES;
+                   break;
+               } else {                        /* Line starts with dot */
+                   HText_appendText(HT, &line[1]);     /* Ignore first dot */
+               }
+           } else {
+
+/*     Normal lines are scanned for buried references to other articles.
+**     Unfortunately, it will pick up mail addresses as well!
+*/
+               char *l = line;
+               char * p;
+               while (p=strchr(l, '<')) {
+                   char *q  = strchr(p,'>');
+                   char *at = strchr(p, '@');
+                   if (q && at && at<q) {
+                       char c = q[1];
+                       q[1] = 0;               /* chop up */
+                       *p = 0;
+                       HText_appendText(HT, l);
+                       *p = '<';               /* again */
+                       *q = 0;
+                       HText_beginAnchor(HT,
+                           HTAnchor_findChildAndLink(
+                               node_anchor, "", p+1, 0));
+                       *q = '>';               /* again */
+                       HText_appendText(HT, p);
+                       HText_endAnchor(HT);
+                       q[1] = c;               /* again */
+                       l=q+1;
+                   } else break;               /* line has unmatched <> */
+               } 
+               HText_appendText(HT,  l);       /* Last bit of the line */
+           } /* if not dot */
+           p = line;                           /* Restart at beginning */
+       } /* if end of line */
+    } /* Loop over characters */
+}
+
+
+/*     Read in a List of Newsgroups
+**     ----------------------------
+*/
+/*
+**     Note the termination condition of a single dot on a line by itself.
+**     RFC 977 specifies that the line "folding" of RFC850 is not used, so we
+**     do not handle it here.
+*/        
+PRIVATE void read_list NOARGS
+{
+
+    char line[LINE_LENGTH+1];
+    char *p;
+    BOOL done = NO;
+    
+/*     Read in the HEADer of the article:
+**
+**     The header fields are either ignored, or formatted and put into the
+**     Text.
+*/
+    HText_appendText(HT,  "\nNewsgroups:\n\n");        /* Should be haeding style */
+    p = line;
+    while(!done){
+       char ch = *p++ = NEXT_CHAR;
+       if (ch==(char)EOF) {
+           abort_socket();     /* End of file, close socket */
+           return;             /* End of file on response */
+       }
+       if ((ch == '\n') || (p == &line[LINE_LENGTH])) {
+           *p++=0;                             /* Terminate the string */
+           if (TRACE) printf("B %s", line);
+           if (line[0]=='.') {
+               if (line[1]<' ') {              /* End of article? */
+                   done = YES;
+                   break;
+               } else {                        /* Line starts with dot */
+                   HText_appendText(HT,  &line[1]);
+               }
+           } else {
+
+/*     Normal lines are scanned for references to newsgroups.
+*/
+               char group[LINE_LENGTH];
+               int first, last;
+               char postable;
+               if (sscanf(line, "%s %d %d %c", group, &first, &last, &postable)==4)
+                   write_anchor(line, group);
+               else
+                   HText_appendText(HT, line);
+           } /* if not dot */
+           p = line;                   /* Restart at beginning */
+       } /* if end of line */
+    } /* Loop over characters */
+}
+
+
+/*     Read in a Newsgroup
+**     -------------------
+**     Unfortunately, we have to ask for each article one by one if we
+**     want more than one field.
+**
+*/
+PRIVATE void read_group ARGS3(
+  CONST char *,groupName,
+  int,first_required,
+  int,last_required
+)
+{
+    char line[LINE_LENGTH+1];
+    char author[LINE_LENGTH+1];
+    char subject[LINE_LENGTH+1];
+    char *p;
+    BOOL done;
+
+    char buffer[LINE_LENGTH];
+    char *reference=0;                 /* Href for article */
+    int art;                           /* Article number WITHIN GROUP */
+    int status, count, first, last;    /* Response fields */
+                                       /* count is only an upper limit */
+
+    sscanf(response_text, " %d %d %d %d", &status, &count, &first, &last);
+    if(TRACE) printf("Newsgroup status=%d, count=%d, (%d-%d) required:(%d-%d)\n",
+                       status, count, first, last, first_required, last_required);
+    if (last==0) {
+        HText_appendText(HT,  "\nNo articles in this group.\n");
+       return;
+    }
+    
+#define FAST_THRESHOLD 100     /* Above this, read IDs fast */
+#define CHOP_THRESHOLD 50      /* Above this, chop off the rest */
+
+    if (first_required<first) first_required = first;          /* clip */
+    if ((last_required==0) || (last_required > last)) last_required = last;
+    
+    if (last_required<=first_required) {
+        HText_appendText(HT,  "\nNo articles in this range.\n");
+       return;
+    }
+
+    if (last_required-first_required+1 > MAX_CHUNK) {  /* Trim this block */
+        first_required = last_required-CHUNK_SIZE+1;
+    }
+    if (TRACE) printf (
+    "    Chunk will be (%d-%d)\n", first_required, last_required);
+
+/*     Link to earlier articles
+*/
+    if (first_required>first) {
+       int before;                     /* Start of one before */
+       if (first_required-MAX_CHUNK <= first) before = first;
+       else before = first_required-CHUNK_SIZE;
+       sprintf(buffer, "%s/%d-%d", groupName, before, first_required-1);
+       if (TRACE) printf("    Block before is %s\n", buffer);
+       HText_appendText(HT,  " (");
+       HText_beginAnchor(HT,
+           HTAnchor_findChildAndLink(node_anchor, "", buffer, 0));
+       HText_appendText(HT,  "Earlier articles");
+       HText_endAnchor(HT);
+       HText_appendText(HT,  "...)\n");
+    }
+    
+    done = NO;
+
+/*#define USE_XHDR*/
+#ifdef USE_XHDR
+    if (count>FAST_THRESHOLD)  {
+        sprintf(buffer,
+       "\nThere are about %d articles currently available in %s, IDs as follows:\n\n",
+               count, groupName); 
+        HText_appendText(HT, buffer);
+        sprintf(buffer, "XHDR Message-ID %d-%d\n", first, last);
+       status = response(buffer);
+       if (status==221) {
+
+           p = line;
+           while(!done){
+               char ch = *p++ = NEXT_CHAR;
+               if (ch==(char)EOF) {
+                   abort_socket();     /* End of file, close socket */
+                   return;             /* End of file on response */
+               }
+               if ((ch == '\n') || (p == &line[LINE_LENGTH])) {
+                   *p++=0;                             /* Terminate the string */
+                   if (TRACE) printf("X %s", line);
+                   if (line[0]=='.') {
+                       if (line[1]<' ') {              /* End of article? */
+                           done = YES;
+                           break;
+                       } else {                        /* Line starts with dot */
+                               /* Ignore strange line */
+                       }
+                   } else {
+       
+       /*      Normal lines are scanned for references to articles.
+       */
+                       char * space = strchr(line, ' ');
+                       if (space++)
+                           write_anchor(space, space);
+                   } /* if not dot */
+                   p = line;                   /* Restart at beginning */
+               } /* if end of line */
+           } /* Loop over characters */
+
+           /* leaving loop with "done" set */
+       } /* Good status */
+    };
+#endif
+
+/*     Read newsgroup using individual fields:
+*/
+    if (!done) {
+        if (first==first_required && last==last_required)
+               HText_appendText(HT, "\nAll available articles in ");
+        else HText_appendText(HT,  "\nArticles in ");
+       HText_appendText(HT, groupName);
+       HText_appendText(HT, "\n\n");
+       for(art=first_required; art<=last_required; art++) {
+    
+/*#define OVERLAP*/
+#ifdef OVERLAP
+/* With this code we try to keep the server running flat out by queuing just
+** one extra command ahead of time. We assume (1) that the server won't abort
+** if it get input during output, and (2) that TCP buffering is enough for the
+** two commands. Both these assumptions seem very reasonable. However, we HAVE
+** had a hangup with a loaded server.
+*/
+           if (art==first_required) {
+               if (art==last_required) {
+                       sprintf(buffer, "HEAD %d\n", art);      /* Only one */
+                       status = response(buffer);
+                   } else {                                    /* First of many */
+                       sprintf(buffer, "HEAD %d\nHEAD %d\n", art, art+1);
+                       status = response(buffer);
+                   }
+           } else if (art==last_required) {                    /* Last of many */
+                   status = response(NULL);
+           } else {                                            /* Middle of many */
+                   sprintf(buffer, "HEAD %d\n", art+1);
+                   status = response(buffer);
+           }
+           
+#else  /* NOT OVERLAP */
+           sprintf(buffer, "HEAD %d\n", art);
+           status = response(buffer);
+#endif /* NOT OVERLAP */
+
+           if (status == 221) {        /* Head follows - parse it:*/
+    
+               p = line;                               /* Write pointer */
+               done = NO;
+               while(!done){
+                   char ch = *p++ = NEXT_CHAR;
+                   if (ch==(char)EOF) {
+                       abort_socket(); /* End of file, close socket */
+                       return;         /* End of file on response */
+                   }
+                   if ((ch == '\n')
+                       || (p == &line[LINE_LENGTH]) ) {
+                   
+                       *--p=0;         /* Terminate  & chop LF*/
+                       p = line;               /* Restart at beginning */
+                       if (TRACE) printf("G %s\n", line);
+                       switch(line[0]) {
+    
+                       case '.':
+                           done = (line[1]<' ');       /* End of article? */
+                           break;
+    
+                       case 'S':
+                       case 's':
+                           if (match(line, "SUBJECT:"))
+                               strcpy(subject, line+9);/* Save subject */
+                           break;
+    
+                       case 'M':
+                       case 'm':
+                           if (match(line, "MESSAGE-ID:")) {
+                               char * addr = HTStrip(line+11) +1; /* Chop < */
+                               addr[strlen(addr)-1]=0;         /* Chop > */
+                               StrAllocCopy(reference, addr);
+                           }
+                           break;
+    
+                       case 'f':
+                       case 'F':
+                           if (match(line, "FROM:")) {
+                               char * p;
+                               strcpy(author,
+                                       author_name(strchr(line,':')+1));
+                               p = author + strlen(author) - 1;
+                               if (*p=='\n') *p = 0;   /* Chop off newline */
+                           }
+                           break;
+                                   
+                       } /* end switch on first character */
+                   } /* if end of line */
+               } /* Loop over characters */
+    
+               sprintf(buffer, "\"%s\" - %s", subject, author);
+               if (reference) {
+                   write_anchor(buffer, reference);
+                   free(reference);
+                   reference=0;
+               } else {
+                   HText_appendText(HT, buffer);
+               }
+               HText_appendParagraph(HT);
+               
+    
+/*     Change the title bar to indicate progress!
+*/
+               if (art%10 == 0) {
+                   sprintf(buffer, "Reading newsgroup %s,  Article %d (of %d-%d) ...",
+                           groupName, art, first, last);
+                   HTAnchor_setTitle(node_anchor, buffer);
+               }
+    
+           } /* If good response */
+       } /* Loop over article */           
+    } /* If read headers */
+    
+/*     Link to later articles
+*/
+    if (last_required<last) {
+       int after;                      /* End of article after */
+       after = last_required+CHUNK_SIZE;
+       if (after==last) sprintf(buffer, "news:%s", groupName); /* original group */
+       else sprintf(buffer, "news:%s/%d-%d", groupName, last_required+1, after);
+       if (TRACE) printf("    Block after is %s\n", buffer);
+       HText_appendText(HT,  "(");
+       HText_beginAnchor(HT, HTAnchor_findChildAndLink(
+               node_anchor, "", buffer, 0));
+       HText_appendText(HT,  "Later articles");
+       HText_endAnchor(HT);
+       HText_appendText(HT,  "...)\n");
+    }
+    
+/*     Set window title
+*/
+    sprintf(buffer, "Newsgroup %s,  Articles %d-%d",
+               groupName, first_required, last_required);
+    HTAnchor_setTitle(node_anchor, buffer);
+
+}
+
+
+/*             Load by name                                    HTLoadNews
+**             ============
+*/
+PUBLIC int HTLoadNews ARGS3(
+       CONST char *,arg,
+       HTParentAnchor *,anAnchor,
+       int,diag)
+{
+    char command[257];                 /* The whole command */
+    char groupName[GROUP_NAME_LENGTH]; /* Just the group name */
+    int status;                                /* tcp return */
+    int retries;                       /* A count of how hard we have tried */ 
+    BOOL group_wanted;                 /* Flag: group was asked for, not article */
+    BOOL list_wanted;                  /* Flag: group was asked for, not article */
+    int first, last;                   /* First and last articles asked for */
+
+    diagnostic = diag;                 /* set global flag */
+    
+    if (TRACE) printf("HTNews: Looking for %s\n", arg);
+    get_styles();
+    
+    if (!initialized) initialized = initialize();
+    if (!initialized) return -1;       /* FAIL */
+    
+    {
+        char * p1;
+
+/*     We will ask for the document, omitting the host name & anchor.
+**
+**     Syntax of address is
+**             xxx@yyy                 Article
+**             <xxx@yyy>               Same article
+**             xxxxx                   News group (no "@")
+*/        
+       group_wanted = (strchr(arg, '@')==0) && (strchr(arg, '*')==0);
+       list_wanted  = (strchr(arg, '@')==0) && (strchr(arg, '*')!=0);
+       
+       p1 = HTParse(arg, "", PARSE_PATH|PARSE_PUNCTUATION);
+       if (list_wanted) {
+           strcpy(command, "LIST ");
+       } else if (group_wanted) {
+           char * slash = strchr(p1, '/');
+           strcpy(command, "GROUP ");
+           first = 0;
+           last = 0;
+           if (slash) {
+               *slash = 0;
+               strcpy(groupName, p1);
+               *slash = '/';
+               (void) sscanf(slash+1, "%d-%d", &first, &last);
+           } else {
+               strcpy(groupName, p1);
+           }
+           strcat(command, groupName);
+       } else {
+           strcpy(command, "ARTICLE ");
+           if (strchr(p1, '<')==0) strcat(command,"<");
+           strcat(command, p1);
+           if (strchr(p1, '>')==0) strcat(command,">");
+       }
+       free(p1);
+
+        strcat(command, "\r\n");               /* CR LF, as in rfc 977 */
+       
+    } /* scope of p1 */
+    
+    if (!*arg) return NO;                      /* Ignore if no name */
+
+    
+/*     Make a hypertext object with an anchor list.
+*/       
+    node_anchor = anAnchor;
+    HT = HText_new(anAnchor);
+    HText_beginAppend(HT);
+       
+/*     Now, let's get a stream setup up from the NewsHost:
+*/       
+    for(retries=0;retries<2; retries++){
+    
+        if (s<0) {
+           HTAnchor_setTitle(node_anchor, "Connecting to NewsHost ...");/* Tell user  */
+            NEWS_PROGRESS("Connecting to NewsHost ...");
+           s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+           status = connect(s, (struct sockaddr*)&soc_address, sizeof(soc_address));
+           if (status<0){
+               char message[256];
+               NETCLOSE(s);
+               s = -1;
+               if (TRACE) printf("HTNews: Unable to connect to news host.\n");
+/*             if (retries<=1) continue;   WHY TRY AGAIN ?     */
+#ifdef NeXTStep
+               NXRunAlertPanel(NULL,
+                   "Could not access newshost %s.",
+                   NULL,NULL,NULL,
+                   NewsHost);
+#else
+               fprintf(stderr, "Could not access newshost %s\n",
+                   NewsHost);
+#endif
+               sprintf(message,
+"\nCould not access %s.\n\n (Check default WorldWideWeb NewsHost ?)\n",
+                   NewsHost);
+               HText_beginAppend(HT);
+               HText_appendText(HT, message);
+               HText_endAppend(HT);
+               return YES;
+           } else {
+               if (TRACE) printf("HTNews: Connected to news host %s.\n",
+                               NewsHost);
+               HTInitInput(s);         /* set up buffering */
+               if ((response(NULL) / 100) !=2) {
+                       NETCLOSE(s);
+                       s = -1;
+#ifdef NeXTStep
+                       NXRunAlertPanel("News access",
+                           "Could not retrieve information:\n   %s.",
+                           NULL,NULL,NULL,
+                           response_text);
+#endif
+                       HTAnchor_setTitle(node_anchor, "News host response");
+                       HText_beginAppend(HT);
+                       HText_appendText(HT,
+                            "Sorry, could not retrieve information: ");
+                       HText_appendText(HT, response_text);
+                       HText_endAppend(HT);
+                       return YES;
+               }
+           }
+       } /* If needed opening */
+       
+       HTAnchor_setTitle(node_anchor, arg);/* Tell user something's happening */
+       status = response(command);
+       if (status<0) break;
+       if ((status/ 100) !=2) {
+/*         NXRunAlertPanel("News access", response_text,
+               NULL,NULL,NULL);
+*/
+           HText_beginAppend(HT);
+           HText_appendText(HT, response_text);
+           HText_endAppend(HT);
+           NETCLOSE(s);
+           s = -1;
+/* return HT; -- no:the message might be "Timeout-disconnected" left over */
+           continue;   /*      Try again */
+       }
+  
+/*     Load a group, article, etc
+*/
+        HText_beginAppend(HT);
+       
+       if (list_wanted) read_list();
+       else if (group_wanted) read_group(groupName, first, last);
+        else read_article();
+
+       HText_endAppend(HT);
+       return YES;
+       
+    } /* Retry loop */
+    
+    HText_beginAppend(HT);
+    HText_appendText(HT, "Sorry, could not load requested news.\n");
+    HText_endAppend(HT);
+    
+/*    NXRunAlertPanel(NULL, "Sorry, could not load `%s'.",
+           NULL,NULL,NULL, arg);No -- message earlier wil have covered it */
+
+    return YES;
+}
+
diff --git a/Cl/WWWLibrary/HTNews.h b/Cl/WWWLibrary/HTNews.h
new file mode 100644 (file)
index 0000000..2883464
--- /dev/null
@@ -0,0 +1,17 @@
+/*                     NEWS ACCESS                             HTNews.h
+**                     ===========
+**
+** History:
+**     26 Sep 90       Written TBL
+**     29 Nov 91       Downgraded to C, for portable implementation.
+*/
+
+#ifndef HTNEWS_H
+#define HTNEWS_H
+
+#include "HTAnchor.h"
+extern int HTLoadNews PARAMS((const char *arg,
+       HTParentAnchor * anAnchor,
+       int diag));
+
+#endif /* HTNEWS_H */
diff --git a/Cl/WWWLibrary/HTParse.c b/Cl/WWWLibrary/HTParse.c
new file mode 100644 (file)
index 0000000..09b8aa0
--- /dev/null
@@ -0,0 +1,333 @@
+/*             Parse HyperText Document Address                HTParse.c
+**             ================================
+*/
+
+#include "HTUtils.h"
+#include "HTParse.h"
+#include "tcp.h"
+
+struct struct_parts {
+       char * access;
+       char * host;
+       char * absolute;
+       char * relative;
+/*     char * search;          no - treated as part of path */
+       char * anchor;
+};
+
+
+/*     Strip white space off a string
+**     ------------------------------
+**
+** On exit,
+**     Return value points to first non-white character, or to 0 if none.
+**     All trailing white space is OVERWRITTEN with zero.
+*/
+
+#ifdef __STDC__
+char * HTStrip(char * s)
+#else
+char * HTStrip(s)
+       char *s;
+#endif
+{
+#define SPACE(c) ((c==' ')||(c=='\t')||(c=='\n')) 
+    char * p=s;
+    for(p=s;*p;p++);                   /* Find end of string */
+    for(p--;p>=s;p--) {
+       if(SPACE(*p)) *p=0;     /* Zap trailing blanks */
+       else break;
+    }
+    while(SPACE(*s))s++;       /* Strip leading blanks */
+    return s;
+}
+
+
+/*     Scan a filename for its consituents
+**     -----------------------------------
+**
+** On entry,
+**     name    points to a document name which may be incomplete.
+** On exit,
+**      absolute or relative may be nonzero (but not both).
+**     host, anchor and access may be nonzero if they were specified.
+**     Any which are nonzero point to zero terminated strings.
+*/
+#ifdef __STDC__
+PRIVATE void scan(char * name, struct struct_parts *parts)
+#else
+PRIVATE void scan(name, parts)
+    char * name;
+    struct struct_parts *parts;
+#endif
+{
+    char * after_access;
+    char * p;
+    int length = strlen(name);
+    
+    parts->access = 0;
+    parts->host = 0;
+    parts->absolute = 0;
+    parts->relative = 0;
+    parts->anchor = 0;
+    
+    after_access = name;
+    for(p=name; *p; p++) {
+       if (*p==':') {
+               *p = 0;
+               parts->access = name;   /* Access name has been specified */
+               after_access = p+1;
+       }
+       if (*p=='/') break;
+       if (*p=='#') break;
+    }
+    
+    for(p=name+length-1; p>=name; p--) {
+       if (*p =='#') {
+           parts->anchor=p+1;
+           *p=0;                               /* terminate the rest */
+       }
+    }
+    p = after_access;
+    if (*p=='/'){
+       if (p[1]=='/') {
+           parts->host = p+2;          /* host has been specified      */
+           *p=0;                       /* Terminate access             */
+           p=strchr(parts->host,'/');  /* look for end of host name if any */
+           if(p) {
+               *p=0;                   /* Terminate host */
+               parts->absolute = p+1;          /* Root has been found */
+           }
+       } else {
+           parts->absolute = p+1;              /* Root found but no host */
+       }           
+    } else {
+        parts->relative = (*after_access) ? after_access : 0;  /* zero for "" */
+    }
+#ifdef NOT_DEFINED     /* search is just treated as part of path */
+    {
+        char *p = relative ? relative : absolute;
+       if (p) {
+           char * q = strchr(p, '?');  /* Any search string? */
+           if (q) {
+               *q = 0;                 /* If so, chop that off. */
+               parts->search = q+1;
+           }
+       }
+    }
+#endif
+} /*scan */    
+
+
+/*     Parse a Name relative to another name
+**     -------------------------------------
+**
+**     This returns those parts of a name which are given (and requested)
+**     substituting bits from the related name where necessary.
+**
+** On entry,
+**     aName           A filename given
+**      relatedName     A name relative to which aName is to be parsed
+**      wanted          A mask for the bits which are wanted.
+**
+** On exit,
+**     returns         A pointer to a malloc'd string which MUST BE FREED
+*/
+#ifdef __STDC__
+char * HTParse(const char * aName, const char * relatedName, int wanted)
+#else
+char * HTParse(aName, relatedName, wanted)
+    char * aName;
+    char * relatedName;
+    int wanted;
+#endif
+
+{
+    char * result = 0;
+    char * return_value = 0;
+    int len;
+    char * name = 0;
+    char * rel = 0;
+    char * p;
+    struct struct_parts given, related;
+    
+    /* Make working copies of input strings to cut up:
+    */
+    len = strlen(aName)+strlen(relatedName)+10;
+    result=(char *)malloc(len);                /* Lots of space: more than enough */
+    if (result == NULL) outofmem(__FILE__, "HTParse");
+    
+    StrAllocCopy(name, aName);
+    StrAllocCopy(rel, relatedName);
+    
+    scan(name, &given);
+    scan(rel,  &related); 
+    result[0]=0;               /* Clear string  */
+    if (wanted & PARSE_ACCESS)
+        if (given.access|| related.access) {
+           strcat(result, given.access ? given.access : related.access);
+           if(wanted & PARSE_PUNCTUATION) strcat(result, ":");
+       }
+       
+    if (given.access && related.access)        /* If different, inherit nothing. */
+        if (strcmp(given.access, related.access)!=0) {
+           related.host=0;
+           related.absolute=0;
+           related.relative=0;
+           related.anchor=0;
+       }
+       
+    if (wanted & PARSE_HOST)
+        if(given.host || related.host) {
+           if(wanted & PARSE_PUNCTUATION) strcat(result, "//");
+           strcat(result, given.host ? given.host : related.host);
+       }
+       
+    if (given.host && related.host)  /* If different hosts, inherit no path. */
+        if (strcmp(given.host, related.host)!=0) {
+           related.absolute=0;
+           related.relative=0;
+           related.anchor=0;
+       }
+       
+    if (wanted & PARSE_PATH) {
+        if(given.absolute) {                           /* All is given */
+           if(wanted & PARSE_PUNCTUATION) strcat(result, "/");
+           strcat(result, given.absolute);
+       } else if(related.absolute) {   /* Adopt path not name */
+           strcat(result, "/");
+           strcat(result, related.absolute);
+           if (given.relative) {
+               p = strchr(result, '?');        /* Search part? */
+               if (!p) p=result+strlen(result)-1;
+               for (; *p!='/'; p--);   /* last / */
+               p[1]=0;                                 /* Remove filename */
+               strcat(result, given.relative);         /* Add given one */
+               HTSimplify (result);
+           }
+       } else if(given.relative) {
+           strcat(result, given.relative);             /* what we've got */
+       } else if(related.relative) {
+           strcat(result, related.relative);
+       } else {  /* No inheritance */
+           strcat(result, "/");
+       }
+    }
+               
+    if (wanted & PARSE_ANCHOR)
+        if(given.anchor || related.anchor) {
+           if(wanted & PARSE_PUNCTUATION) strcat(result, "#");
+           strcat(result, given.anchor ? given.anchor : related.anchor);
+       }
+    free(rel);
+    free(name);
+    
+    StrAllocCopy(return_value, result);
+    free(result);
+    return return_value;               /* exactly the right length */
+}
+
+/*             Simplify a filename
+//             -------------------
+//
+// A unix-style file is allowed to contain the seqeunce xxx/../ which may be
+// replaced by "" , and the seqeunce "/./" which may be replaced by "/".
+// Simplification helps us recognize duplicate filenames.
+//
+//     Thus,   /etc/junk/../fred       becomes /etc/fred
+//             /etc/junk/./fred        becomes /etc/junk/fred
+*/
+#ifdef __STDC__
+void HTSimplify(char * filename)
+#else
+void HTSimplify(filename)
+    char * filename;
+#endif
+
+{
+    char * p;
+    char * q;
+    for(p=filename+2; *p; p++) {
+        if (*p=='/') {
+           if ((p[1]=='.') && (p[2]=='.') && (p[3]=='/' || !p[3] )) {
+               for (q=p-1; (q>filename) && (*q!='/'); q--); /* prev slash */
+               if (*q=='/') {
+                   strcpy(q, p+3);     /* Remove  /xxx/..      */
+                   if (!*filename) strcpy(filename, "/");
+                   p = q-1;            /* Start again with prev slash  */
+               } else {                        /*   xxx/..     error?  */
+                   strcpy(filename, p[3] ? p+4 : p+3); /* rm  xxx/../  */
+                   p = filename;               /* Start again */
+               }
+           } else if ((p[1]=='.') && (p[2]=='/' || !p[2])) {
+               strcpy(p, p+2);                 /* Remove a slash and a dot */
+           }
+       }
+    }
+}
+
+
+/*             Make Relative Name
+**             ------------------
+**
+** This function creates and returns a string which gives an expression of
+** one address as related to another. Where there is no relation, an absolute
+** address is retured.
+**
+**  On entry,
+**     Both names must be absolute, fully qualified names of nodes
+**     (no anchor bits)
+**
+**  On exit,
+**     The return result points to a newly allocated name which, if
+**     parsed by HTParse relative to relatedName, will yield aName.
+**     The caller is responsible for freeing the resulting name later.
+**
+*/
+#ifdef __STDC__
+char * HTRelative(const char * aName, const char *relatedName)
+#else
+char * HTRelative(aName, relatedName)
+   char * aName;
+   char * relatedName;
+#endif
+{
+    char * result = 0;
+    CONST char *p = aName;
+    CONST char *q = relatedName;
+    CONST char * after_access = 0;
+    CONST char * path = 0;
+    CONST char * last_slash = 0;
+    int slashes = 0;
+    
+    for(;*p; p++, q++) {       /* Find extent of match */
+       if (*p!=*q) break;
+       if (*p==':') after_access = p+1;
+       if (*p=='/') {
+           last_slash = p;
+           slashes++;
+           if (slashes==3) path=p;
+       }
+    }
+    
+    /* q, p point to the first non-matching character or zero */
+    
+    if (!after_access) {                       /* Different access */
+        StrAllocCopy(result, aName);
+    } else if (slashes<3){                     /* Different nodes */
+       StrAllocCopy(result, after_access);
+    } else if (slashes==3){                    /* Same node, different path */
+        StrAllocCopy(result, path);
+    } else {                                   /* Some path in common */
+        int levels= 0;
+        for(; *q && (*q!='#'); q++)  if (*q=='/') levels++;
+       result = (char *)malloc(3*levels + strlen(last_slash) + 1);
+      if (result == NULL) outofmem(__FILE__, "HTRelative");
+       result[0]=0;
+       for(;levels; levels--)strcat(result, "../");
+       strcat(result, last_slash+1);
+    }
+    if (TRACE) printf("HT: `%s' expressed relative to\n    `%s' is\n   `%s'.",
+               aName, relatedName, result);
+    return result;
+}
diff --git a/Cl/WWWLibrary/HTParse.h b/Cl/WWWLibrary/HTParse.h
new file mode 100644 (file)
index 0000000..0bd6d92
--- /dev/null
@@ -0,0 +1,87 @@
+/*             Parse HyperText Document Address                HTParse.h
+**             ================================
+*/
+/*     These are flag bits which may be ORed together to form a number to give
+**     the 'wanted' argument to HTParse.
+*/
+#define PARSE_ACCESS           16
+#define PARSE_HOST              8
+#define PARSE_PATH              4
+#define PARSE_ANCHOR            2
+#define PARSE_PUNCTUATION       1
+#define PARSE_ALL              31
+
+/*     Parse a Name relative to another name
+**     -------------------------------------
+**
+**     This returns those parts of a name which are given (and requested)
+**     substituting bits from the related name where necessary.
+**
+** On entry,
+**     aName           A filename given
+**     relatedName     A name relative to ehich aName is to be parsed
+**      wanted          A mask for the bits which are wanted.
+**
+** On exit,
+**     returns         A pointer to a malloc'd string which MUST BE FREED
+*/
+#ifdef __STDC__
+extern char * HTParse(const char * aName, const char * relatedName, int wanted);
+#else
+extern char * HTParse();
+#endif
+
+/*     Strip white space off a string
+**     ------------------------------
+**
+** On exit,
+**     Return value points to first non-white character, or to 0 if none.
+**     All trailing white space is OVERWRITTEN with zero.
+*/
+#ifdef __STDC__
+extern char * HTStrip(char * s);
+#else
+extern char * HTStrip();
+#endif
+
+/*             Simplify a filename
+**             -------------------
+**
+**     A unix-style file is allowed to contain the seqeunce xxx/../ which
+**     may be replaced by "" , and the seqeunce "/./" which may be replaced
+**     by "/".
+**     Simplification helps us recognize duplicate filenames. It doesn't deal
+**     with soft links, though.
+**     The new (shorter) filename overwrites the old.
+**
+**     Thus,   /etc/junk/../fred       becomes /etc/fred
+**             /etc/junk/./fred        becomes /etc/junk/fred
+*/
+#ifdef __STDC__
+extern void HTSimplify(char * filename);
+#else
+extern void HTSimplify();
+#endif
+
+/*             Make Relative Name
+**             ------------------
+**
+**     This function creates and returns a string which gives an expression of
+**     one address as related to another. Where there is no relation, an
+**     absolute address is retured.
+**
+**  On entry,
+**     Both names must be absolute, fully qualified names of nodes
+**     (no anchor bits)
+**
+**  On exit,
+**     The return result points to a newly allocated name which, if parsed
+**     by HTParse relative to relatedName, will yield aName. The caller is
+**     responsible for freeing the resulting name later.
+**
+*/
+#ifdef __STDC__
+extern char * HTRelative(const char * aName, const char *relatedName);
+#else
+extern char * HTRelative();
+#endif
diff --git a/Cl/WWWLibrary/HTString.c b/Cl/WWWLibrary/HTString.c
new file mode 100644 (file)
index 0000000..e997423
--- /dev/null
@@ -0,0 +1,82 @@
+/*             Case-independent string comparison              HTString.c
+**
+**     Original version came with listserv implementation.
+**     Version TBL Oct 91 replaces one which modified the strings.
+**     02-Dec-91 (JFG) Added stralloccopy and stralloccat
+**     23 Jan 92 (TBL) Changed strallocc* to 8 char HTSAC* for VM and suchlike
+*/
+#include <ctype.h>
+#include "HTUtils.h"
+#include "tcp.h"
+
+#ifndef VM             /* VM has these already it seems */
+       
+/*     Strings of any length
+**     ---------------------
+*/
+PUBLIC int strcasecomp ARGS2 (CONST char*,a, CONST char *,b)
+{
+       CONST char *p =a;
+       CONST char *q =b;
+       for(p=a, q=b; *p && *q; p++, q++) {
+           int diff = TOLOWER(*p) - TOLOWER(*q);
+           if (diff) return diff;
+       }
+       if (*p) return 1;       /* p was longer than q */
+       if (*q) return -1;      /* p was shorter than q */
+       return 0;               /* Exact match */
+}
+
+
+/*     With count limit
+**     ----------------
+*/
+PUBLIC int strncasecomp ARGS3(CONST char*,a, CONST char *,b, int,n)
+{
+       CONST char *p =a;
+       CONST char *q =b;
+       
+       for(p=a, q=b;; p++, q++) {
+           int diff;
+           if (p == a+n) return 0;     /*   Match up to n characters */
+           if (!(*p && *q)) return *p - *q;
+           diff = TOLOWER(*p) - TOLOWER(*q);
+           if (diff) return diff;
+       }
+       /*NOTREACHED*/
+}
+#endif
+
+/*     Allocate a new copy of a string, and returns it
+*/
+PUBLIC char * HTSACopy
+  ARGS2 (char **,dest, CONST char *,src)
+{
+  if (*dest) free(*dest);
+  if (! src)
+    *dest = NULL;
+  else {
+    *dest = (char *) malloc (strlen(src) + 1);
+    if (*dest == NULL) outofmem(__FILE__, "HTSACopy");
+    strcpy (*dest, src);
+  }
+  return *dest;
+}
+
+PUBLIC char * HTSACat
+  ARGS2 (char **,dest, CONST char *,src)
+{
+  if (src && *src) {
+    if (*dest) {
+      int length = strlen (*dest);
+      *dest = (char *) realloc (*dest, length + strlen(src) + 1);
+      if (*dest == NULL) outofmem(__FILE__, "HTSACat");
+      strcpy (*dest + length, src);
+    } else {
+      *dest = (char *) malloc (strlen(src) + 1);
+      if (*dest == NULL) outofmem(__FILE__, "HTSACat");
+      strcpy (*dest, src);
+    }
+  }
+  return *dest;
+}
diff --git a/Cl/WWWLibrary/HTString.h b/Cl/WWWLibrary/HTString.h
new file mode 100644 (file)
index 0000000..1b3c6f2
--- /dev/null
@@ -0,0 +1,19 @@
+/*             Case-independent string comparison              HTString.h
+**             and allocations with copies
+*/
+#ifndef HTSTRING_H
+#define HTSTRING_H
+
+#include "HTUtils.h"
+
+extern int strcasecomp  PARAMS((CONST char *a, CONST char *b));
+extern int strncasecomp PARAMS((CONST char *a, CONST char *b, int n));
+
+extern char * HTSACopy PARAMS ((char **dest, CONST char *src));
+extern char * HTSACat  PARAMS ((char **dest, CONST char *src));
+
+/* Enable the old macro-like calling methods */
+#define StrAllocCopy(dest, src) HTSACopy (&(dest), src)
+#define StrAllocCat(dest, src)  HTSACat  (&(dest), src)
+
+#endif
diff --git a/Cl/WWWLibrary/HTStyle.c b/Cl/WWWLibrary/HTStyle.c
new file mode 100644 (file)
index 0000000..b15801c
--- /dev/null
@@ -0,0 +1,363 @@
+/*     Style Implementation for Hypertext                      HTStyle.c
+**     ==================================
+**
+**     Styles allow the translation between a logical property
+**     of a piece of text and its physical representation.
+**
+**     A StyleSheet is a collection of styles, defining the
+**     translation necessary to
+**     represent a document. It is a linked list of styles.
+*/
+#include "HTStyle.h"
+#include "HTUtils.h"
+
+/*     Create a new style
+*/
+PUBLIC HTStyle* HTStyleNew NOARGS
+{
+    HTStyle * self = (HTStyle *)malloc(sizeof(*self));
+    memset(self, 0, sizeof(*self));
+    self->font = HT_FONT;
+    self->color = HT_BLACK;
+    return self;
+}
+
+/*     Create a new style with a name
+*/
+PUBLIC HTStyle* HTStyleNewNamed ARGS1 (CONST char *,name)
+{
+    HTStyle * self = HTStyleNew();
+    StrAllocCopy(self->name, name);
+    return self;
+}
+
+
+/*     Free a style
+*/
+PUBLIC HTStyle * HTStyleFree ARGS1 (HTStyle *,self)
+{
+    if (self->name) free(self->name);
+    if (self->SGMLTag) free(self->SGMLTag);
+    free(self);
+    return 0;
+}
+
+
+#ifdef SUPPRESS  /* Only on the NeXT */
+/*     Read a style from a stream      (without its name)
+**     --------------------------
+**
+**     Reads a style with paragraph information from a stream.
+**     The style name is not read or written by these routines.
+*/
+#define NONE_STRING "(None)"
+#define HTStream NXStream
+
+HTStyle * HTStyleRead (HTStyle * style, HTStream * stream)
+{
+    char myTag[STYLE_NAME_LENGTH];
+    char fontName[STYLE_NAME_LENGTH];
+    NXTextStyle *p;
+    int        tab;
+    int gotpara;               /* flag: have we got a paragraph definition? */
+       
+    NXScanf(stream, "%s%s%f%d",
+       myTag,
+       fontName,
+       &style->fontSize,
+       &gotpara);
+    if (gotpara) {
+       if (!style->paragraph) {
+           style->paragraph = malloc(sizeof(*(style->paragraph)));
+           style->paragraph->tabs = 0;
+       }
+       p = style->paragraph;
+       NXScanf(stream, "%f%f%f%f%hd%f%f%hd",
+           &p->indent1st,
+           &p->indent2nd,
+           &p->lineHt,
+           &p->descentLine,
+           &p->alignment,
+           &style->spaceBefore,
+           &style->spaceAfter,
+           &p->numTabs);
+       if (p->tabs) free(p->tabs);
+       p->tabs = malloc(p->numTabs * sizeof(p->tabs[0]));
+       for (tab=0; tab < p->numTabs; tab++) {
+           NXScanf(stream, "%hd%f",
+                   &p->tabs[tab].kind,
+                   &p->tabs[tab].x);
+       }
+    } else { /* No paragraph */
+        if (style->paragraph) {
+           free(style->paragraph);
+           style->paragraph = 0;
+       }
+    } /* if no paragraph */
+    StrAllocCopy(style->SGMLTag, myTag);
+    if (strcmp(fontName, NONE_STRING)==0)
+        style->font = 0;
+    else
+        style->font = [Font newFont:fontName size:style->fontSize];
+    return 0;
+
+}
+
+
+/*     Write a style to a stream in a compatible way
+*/
+HTStyle * HTStyleWrite (HTStyle * style, NXStream * stream)
+{
+    int tab;
+    NXTextStyle *p = style->paragraph;
+    NXPrintf(stream, "%s %s %f %d\n",
+       style->SGMLTag,
+       style->font ? [style->font name] : NONE_STRING,
+       style->fontSize,
+       p!=0);
+
+    if (p) {
+       NXPrintf(stream, "\t%f %f %f %f %d %f %f\t%d\n",
+           p->indent1st,
+           p->indent2nd,
+           p->lineHt,
+           p->descentLine,
+           p->alignment,
+           style->spaceBefore,
+           style->spaceAfter,
+           p->numTabs);
+           
+       for (tab=0; tab < p->numTabs; tab++)
+           NXPrintf(stream, "\t%d %f\n",
+                   p->tabs[tab].kind,
+                   p->tabs[tab].x);
+       }
+    return style;
+}
+
+
+/*     Write a style to stdout for diagnostics
+*/
+HTStyle * HTStyleDump (HTStyle * style)
+{
+    int tab;
+    NXTextStyle *p = style->paragraph;
+    printf("Style %d `%s' SGML:%s. Font %s %.1f point.\n",
+       style,
+       style->name,
+       style->SGMLTag,
+       [style->font name],
+       style->fontSize);
+    if (p) {
+        printf(
+       "\tIndents: first=%.0f others=%.0f, Height=%.1f Desc=%.1f\n"
+       "\tAlign=%d, %d tabs. (%.0f before, %.0f after)\n",
+           p->indent1st,
+           p->indent2nd,
+           p->lineHt,
+           p->descentLine,
+           p->alignment,
+           p->numTabs,
+           style->spaceBefore,
+           style->spaceAfter);
+           
+       for (tab=0; tab < p->numTabs; tab++) {
+           printf("\t\tTab kind=%d at %.0f\n",
+                   p->tabs[tab].kind,
+                   p->tabs[tab].x);
+       }
+       printf("\n");
+    } /* if paragraph */
+    return style;
+}
+#endif
+
+
+/*                     StyleSheet Functions
+**                     ====================
+*/
+
+/*     Searching for styles:
+*/
+HTStyle * HTStyleNamed ARGS2 (HTStyleSheet *,self, CONST char *,name)
+{
+    HTStyle * scan;
+    for (scan=self->styles; scan; scan=scan->next)
+        if (0==strcmp(scan->name, name)) return scan;
+    if (TRACE) printf("StyleSheet: No style named `%s'\n", name);
+    return 0;
+}
+
+#ifdef NEXT_SUPRESS            /* Not in general common code */
+
+HTStyle * HTStyleMatching (HTStyleSheet * self, HTStyle *style)
+{
+    HTStyle * scan;
+    for (scan=self->styles; scan; scan=scan->next)
+        if (scan->paragraph == para) return scan;
+    return 0;
+}
+
+/*     Find the style which best fits a given run
+**     ------------------------------------------
+**
+**     This heuristic is used for guessing the style for a run of
+**     text which has been pasted in. In order, we try:
+**
+**     A style whose paragraph structure is actually used by the run.
+**     A style matching in font
+**     A style matching in paragraph style exactly
+**     A style matching in paragraph to a degree
+*/
+
+HTStyle * HTStyleForRun (HTStyleSheet *self, NXRun *run)
+{
+    HTStyle * scan;
+    HTStyle * best = 0;
+    int        bestMatch = 0;
+    NXTextStyle * rp = run->paraStyle;
+    for (scan=self->styles; scan; scan=scan->next)
+        if (scan->paragraph == run->paraStyle) return scan;    /* Exact */
+
+    for (scan=self->styles; scan; scan=scan->next){
+       NXTextStyle * sp = scan->paragraph;
+       if (sp) {
+           int match = 0;
+           if (sp->indent1st ==        rp->indent1st)  match = match+1;
+           if (sp->indent2nd ==        rp->indent2nd)  match = match+2;
+           if (sp->lineHt ==           rp->lineHt)     match = match+1;
+           if (sp->numTabs ==          rp->numTabs)    match = match+1;
+           if (sp->alignment ==        rp->alignment)  match = match+3;
+           if (scan->font ==           run->font)      match = match+10;
+           if (match>bestMatch) {
+                   best=scan;
+                   bestMatch=match;
+           }
+       }
+    }
+    if (TRACE) printf("HTStyleForRun: Best match for style is %d out of 18\n",
+                        bestMatch);
+    return best;
+}
+#endif
+
+
+/*     Add a style to a sheet
+**     ----------------------
+*/
+HTStyleSheet * HTStyleSheetAddStyle ARGS2
+  (HTStyleSheet *,self, HTStyle *,style)
+{
+    style->next = 0;           /* The style will go on the end */
+    if (!self->styles) {
+       self->styles = style;
+    } else {
+       HTStyle * scan;
+        for(scan=self->styles; scan->next; scan=scan->next); /* Find end */
+       scan->next=style;
+    }
+    return self;
+}
+
+
+/*     Remove the given object from a style sheet if it exists
+*/
+HTStyleSheet * HTStyleSheetRemoveStyle ARGS2
+  (HTStyleSheet *,self, HTStyle *,style)
+{
+    if (self->styles = style) {
+       self->styles = style->next;
+       return self;
+    } else {
+       HTStyle * scan;
+       for(scan = self->styles; scan; scan = scan->next) {
+           if (scan->next = style) {
+               scan->next = style->next;
+               return self;
+           }
+       }
+    }
+    return 0;
+}
+
+/*     Create new style sheet
+*/
+
+HTStyleSheet * HTStyleSheetNew NOARGS
+{
+    HTStyleSheet * self = (HTStyleSheet *)malloc(sizeof(*self));
+
+    memset((void*)self, 0, sizeof(*self));     /* ANSI */
+/* Harbison c ref man says (char*)self
+   but k&r ansii and abc books and Think_C say (void*) */
+    
+/*    bzero(self, sizeof(*self)); */           /* BSD */
+    return self;
+}
+
+
+/*     Free off a style sheet pointer
+*/
+HTStyleSheet * HTStyleSheetFree ARGS1 (HTStyleSheet *,self)
+{
+    HTStyle * style;
+    while((style=self->styles)!=0) {
+        self->styles = style->next;
+       HTStyleFree(style);
+    }
+    free(self);
+    return 0;
+}
+
+
+/*     Read a stylesheet from a typed stream
+**     -------------------------------------
+**
+**     Reads a style sheet from a stream.  If new styles have the same names
+**     as existing styles, they replace the old ones without changing the ids.
+*/
+
+#ifdef NEXT_SUPRESS  /* Only on the NeXT */
+HTStyleSheet * HTStyleSheetRead(HTStyleSheet * self, NXStream * stream)
+{
+    int numStyles;
+    int i;
+    HTStyle * style;
+    char styleName[80];
+    NXScanf(stream, " %d ", &numStyles);
+    if (TRACE) printf("Stylesheet: Reading %d styles\n", numStyles);
+    for (i=0; i<numStyles; i++) {
+        NXScanf(stream, "%s", styleName);
+        style = HTStyleNamed(self, styleName);
+       if (!style) {
+           style = HTStyleNewNamed(styleName);
+           (void) HTStyleSheetAddStyle(self, style);
+       }
+       (void) HTStyleRead(style, stream);
+       if (TRACE) HTStyleDump(style);
+    }
+    return self;
+}
+
+/*     Write a stylesheet to a typed stream
+**     ------------------------------------
+**
+**     Writes a style sheet to a stream.
+*/
+
+HTStyleSheet * HTStyleSheetWrite(HTStyleSheet * self, NXStream * stream)
+{
+    int numStyles = 0;
+    HTStyle * style;
+    
+    for(style=self->styles; style; style=style->next) numStyles++;
+    NXPrintf(stream, "%d\n", numStyles);
+    
+    if (TRACE) printf("StyleSheet: Writing %d styles\n", numStyles);
+    for (style=self->styles; style; style=style->next) {
+        NXPrintf(stream, "%s ", style->name);
+       (void) HTStyleWrite(style, stream);
+    }
+    return self;
+}
+#endif
diff --git a/Cl/WWWLibrary/HTStyle.h b/Cl/WWWLibrary/HTStyle.h
new file mode 100644 (file)
index 0000000..cfcc788
--- /dev/null
@@ -0,0 +1,154 @@
+/*     Style Definition for Hypertext                          HTStyle.h
+**     ==============================
+**
+**     Styles allow the translation between a logical property of a piece of
+**     text and its physical representation.
+**
+**     A StyleSheet is a collection of styles, defining the
+**     translation necessary to represent a document.
+**     It is a linked list of styles.
+*/
+#ifndef HTStyle_H
+#define HTStyle_H
+
+#include "HTUtils.h"
+#include "HTAnchor.h"
+#include "HTFont.h"
+
+#ifdef SHORT_NAMES
+#define HTStyleNew                     HTStNew
+#define HTStyleFree                    HTStFree
+#define HTStyleRead                    HTStRead
+#define HTStyleWrite                   HTStWrite
+#define HTStyleSheetNew                        HTStShNe
+#define HTStyleSheetFree               HTStShFr
+#define HTStyleNamed                   HTStName
+#define HTStyleForParagraph            HTStFoPa
+#define HTStyleMatching                        HTStMatc
+#define HTStyleForRun                  HTStFoRu
+#define HTStyleSheetAddStyle           HTStShAd
+#define HTStyleSheetRemoveStyle                HTStShRm
+#define HTStyleSheetRead               HTStShRe
+#define HTStyleSheetWrite              HTStShWr
+#endif
+
+#ifdef NeXT_suppressed
+#include <appkit/appkit.h>
+typedef NXCoord HTCoord;
+#define HTParagraphStyle NXTextStyle
+#define HTCoord NXCoord
+typedef struct _color {
+       float   grey;
+       int     RGBColor;
+} HTColor;
+#else
+
+typedef float HTCoord;
+
+typedef struct _HTParagraphStyle {
+    HTCoord    left_indent;            /* @@@@ junk! etc etc*/
+} HTParagraphStyle;
+
+typedef int HTColor;           /* Sorry about the US spelling! */
+
+#endif
+
+
+
+#define STYLE_NAME_LENGTH      80      /* @@@@@@@@@@@ */
+        
+typedef struct {
+    short              kind;           /* only NX_LEFTTAB implemented*/
+    HTCoord            position;       /* x coordinate for stop */
+} HTTabStop;
+
+
+/*     The Style Structure
+**     -------------------
+*/
+
+typedef struct _HTStyle {
+
+/*     Style management information
+*/
+    struct _HTStyle    *next;          /* Link for putting into stylesheet */
+    char *             name;           /* Style name */
+    char *             SGMLTag;        /* Tag name to start */
+
+
+/*     Character attributes    (a la NXRun)
+*/
+    HTFont             font;           /* Font id */
+    HTCoord            fontSize;       /* The size of font, not independent */
+    HTColor            color;  /* text gray of current run */
+    int                superscript;    /* superscript (-sub) in points */
+
+    HTAnchor           *anchor;        /* Anchor id if any, else zero */
+
+/*     Paragraph Attribtes     (a la NXTextStyle)
+*/
+    HTCoord            indent1st;      /* how far first line in paragraph is
+                                * indented */
+    HTCoord            leftIndent;     /* how far second line is indented */
+    HTCoord            rightIndent;    /* (Missing from NeXT version */
+    short              alignment;      /* quad justification */
+    HTCoord            lineHt;         /* line height */
+    HTCoord            descentLine;    /* descender bottom from baseline */
+    HTTabStop          *tabs;          /* array of tab stops, 0 terminated */
+
+    BOOL               wordWrap;       /* Yes means wrap at space not char */
+    BOOL               freeFormat;     /* Yes means \n is just white space */
+    HTCoord            spaceBefore;    /* Omissions from NXTextStyle */
+    HTCoord            spaceAfter;
+    int                        paraFlags;      /* Paragraph flags, bits as follows: */
+
+#define PARA_KEEP      1       /* Do not break page within this paragraph */
+#define        PARA_WITH_NEXT  2       /* Do not break page after this paragraph */
+
+#define HT_JUSTIFY 0           /* For alignment */
+#define HT_LEFT        1
+#define HT_RIGHT 2
+#define HT_CENTER 3
+  
+} HTStyle;
+
+
+/*     Style functions:
+*/
+extern HTStyle * HTStyleNew NOPARAMS;
+extern HTStyle* HTStyleNewNamed PARAMS ((CONST char * name));
+extern HTStyle * HTStyleFree PARAMS((HTStyle * self));
+#ifdef SUPRESS
+extern HTStyle * HTStyleRead PARAMS((HTStyle * self, HTStream * stream));
+extern HTStyle * HTStyleWrite PARAMS((HTStyle * self, HTStream * stream));
+#endif
+/*             Style Sheet
+**             -----------
+*/
+typedef struct _HTStyleSheet {
+       char *          name;
+       HTStyle *       styles;
+} HTStyleSheet;
+
+
+/*     Stylesheet functions:
+*/
+extern HTStyleSheet * HTStyleSheetNew NOPARAMS;
+extern HTStyleSheet * HTStyleSheetFree PARAMS((HTStyleSheet * self));
+extern HTStyle * HTStyleNamed PARAMS((HTStyleSheet * self, CONST char * name));
+extern HTStyle * HTStyleForParagraph PARAMS((HTStyleSheet * self,
+       HTParagraphStyle * paraStyle));
+extern HTStyle * HTStyleMatching PARAMS((HTStyleSheet *self, HTStyle * style));
+/* extern HTStyle * HTStyleForRun PARAMS((HTStyleSheet *self, NXRun * run)); */
+extern HTStyleSheet * HTStyleSheetAddStyle PARAMS((HTStyleSheet * self,
+       HTStyle * style));
+extern HTStyleSheet * HTStyleSheetRemoveStyle PARAMS((HTStyleSheet * self,
+       HTStyle * style));
+#ifdef SUPPRESS
+extern HTStyleSheet * HTStyleSheetRead PARAMS((HTStyleSheet * self,
+                                               HTStream * stream));
+extern HTStyleSheet * HTStyleSheetWrite PARAMS((HTStyleSheet * self,
+                                               HTStream * stream));
+#endif
+#define CLEAR_POINTER ((void *)-1)     /* Pointer value means "clear me" */
+#endif /* HTStyle_H */
diff --git a/Cl/WWWLibrary/HTTCP.c b/Cl/WWWLibrary/HTTCP.c
new file mode 100644 (file)
index 0000000..3da790b
--- /dev/null
@@ -0,0 +1,301 @@
+/*                     Generic Communication Code              HTTCP.c
+**                     ==========================
+**
+**     This code is in common between client and server sides.
+**
+**     16 Jan 92       Fix strtol() undefined on CMU Mach. - TBL
+*/
+
+
+#include "HTUtils.h"
+#include "tcp.h"               /* Defines SHORT_NAMES if necessary */
+#ifdef SHORT_NAMES
+#define HTInetStatus           HTInStat
+#define HTInetString           HTInStri
+#define HTParseInet            HTPaInet
+#endif
+
+/*     Module-Wide variables
+*/
+
+PRIVATE char *hostname=0;              /* The name of this host */
+
+
+/*     PUBLIC VARIABLES
+*/
+
+/* PUBLIC struct sockaddr_in HTHostAddress; */ /* The internet address of the host */
+                                       /* Valid after call to HTHostName() */
+
+/*     Encode INET status (as in sys/errno.h)                    inet_status()
+**     ------------------
+**
+** On entry,
+**     where           gives a description of what caused the error
+**     global errno    gives the error number in the unix way.
+**
+** On return,
+**     returns         a negative status in the unix way.
+*/
+#ifndef PCNFS
+#ifdef vms
+extern int uerrno;     /* Deposit of error info (as perr errno.h) */
+extern int vmserrno;   /* Deposit of VMS error info */
+extern volatile noshare int errno;  /* noshare to avoid PSECT conflict */
+#else
+#ifndef errno
+extern int errno;
+#endif
+#endif
+
+#ifndef VM
+#ifndef vms
+#ifndef NeXT
+#ifndef THINK_C
+extern char *sys_errlist[];            /* see man perror on cernvax */
+extern int sys_nerr;
+#endif  /* think c */
+#endif /* NeXT */
+#endif  /* vms */
+#endif /* VM */
+#endif /* PCNFS */
+
+/*     Report Internet Error
+**     ---------------------
+*/
+#ifdef __STDC__
+PUBLIC int HTInetStatus(char *where)
+#else
+PUBLIC int HTInetStatus(where)
+    char    *where;
+#endif
+{
+    CTRACE(tfp, "TCP: Error %d in `errno' after call to %s() failed.\n\t%s\n",
+           errno,  where,
+#ifdef VM
+           "(Error number not translated)");   /* What Is the VM equiv? */
+#define ER_NO_TRANS_DONE
+#endif
+#ifdef vms
+           "(Error number not translated)");
+#define ER_NO_TRANS_DONE
+#endif
+#ifdef NeXT
+           strerror(errno));
+#define ER_NO_TRANS_DONE
+#endif
+#ifdef THINK_C
+           strerror(errno));
+#define ER_NO_TRANS_DONE
+#endif
+
+#ifndef ER_NO_TRANS_DONE
+           errno < sys_nerr ? sys_errlist[errno] : "Unknown error" );
+#endif
+
+
+#ifdef vms
+    CTRACE(tfp, "         Unix error number (uerrno) = %ld dec\n", uerrno);
+    CTRACE(tfp, "         VMS error (vmserrno)       = %lx hex\n", vmserrno);
+#endif
+    return -errno;
+}
+
+
+/*     Parse a cardinal value                                 parse_cardinal()
+**     ----------------------
+**
+** On entry,
+**     *pp         points to first character to be interpreted, terminated by
+**                 non 0:9 character.
+**     *pstatus    points to status already valid
+**     maxvalue    gives the largest allowable value.
+**
+** On exit,
+**     *pp         points to first unread character
+**     *pstatus    points to status updated iff bad
+*/
+#ifdef __STDC__
+PUBLIC unsigned int HTCardinal(int *pstatus,
+       char            **pp,
+       unsigned int    max_value)
+#else
+PUBLIC unsigned int HTCardinal(pstatus, pp, max_value)
+   int                 *pstatus;
+   char                        **pp;
+   unsigned int                max_value;
+#endif
+{
+    int   n;
+    if ( (**pp<'0') || (**pp>'9')) {       /* Null string is error */
+       *pstatus = -3;  /* No number where one expeceted */
+       return 0;
+    }
+
+    n=0;
+    while ((**pp>='0') && (**pp<='9')) n = n*10 + *((*pp)++) - '0';
+
+    if (n>max_value) {
+       *pstatus = -4;  /* Cardinal outside range */
+       return 0;
+    }
+
+    return n;
+}
+
+
+/*     Produce a string for an inernet address
+**     ---------------------------------------
+**
+** On exit,
+**     returns a pointer to a static string which must be copied if
+**             it is to be kept.
+*/
+#ifdef __STDC__
+PUBLIC const char * HTInetString(struct sockaddr_in* sin)
+#else
+PUBLIC char * HTInetString(sin)
+    struct sockaddr_in *sin;
+#endif
+{
+    static char string[16];
+    sprintf(string, "%d.%d.%d.%d",
+           (int)*((unsigned char *)(&sin->sin_addr)+0),
+           (int)*((unsigned char *)(&sin->sin_addr)+1),
+           (int)*((unsigned char *)(&sin->sin_addr)+2),
+           (int)*((unsigned char *)(&sin->sin_addr)+3));
+    return string;
+}
+
+
+/*     Parse an internet node address and port
+**     ---------------------------------------
+**
+** On entry,
+**     str     points to a string with a node name or number,
+**             with optional trailing colon and port number.
+**     sin     points to the binary internet address field.
+**
+** On exit,
+**     *sin    is filled in. If no port is specified in str, that
+**             field is left unchanged in *sin.
+*/
+#ifdef __STDC__
+PUBLIC int HTParseInet(struct sockaddr_in* sin, const char *str)
+#else
+PUBLIC int HTParseInet(sin, str)
+    struct sockaddr_in *sin;
+    char *str;
+#endif
+{
+    char *port;
+    char host[256];
+    struct hostent  *phost;    /* Pointer to host - See netdb.h */
+    strcpy(host, str);         /* Take a copy we can mutilate */
+
+
+
+/*     Parse port number if present
+*/    
+    if (port=strchr(host, ':')) {
+       *port++ = 0;            /* Chop off port */
+        if (port[0]>='0' && port[0]<='9') {
+#ifdef unix
+           sin->sin_port = htons(atol(port));
+#else
+           sin->sin_port = htons(strtol(port, (char**)0 , 10));
+#endif
+       } else {
+#ifdef SUPPRESS                /* 1. crashes!?!.  2. Not recommended */
+           struct servent * serv = getservbyname(port, (char*)0);
+           if (serv) sin->sin_port = serv->s_port;
+           else if (TRACE) printf("TCP: Unknown service %s\n", port);
+#endif
+       }
+    }
+
+/*     Parse host number if present
+*/  
+    if (*host>='0' && *host<='9') {   /* Numeric node address: */
+       sin->sin_addr.s_addr = inet_addr(host); /* See arpa/inet.h */
+
+    } else {               /* Alphanumeric node name: */
+#ifdef MVS     /* Oustanding problem with crsh in MVS gethostbyname */
+       if(TRACE)printf("HTTCP: Calling gethostbyname(%s)\n", host);
+#endif
+       phost=gethostbyname(host);      /* See netdb.h */
+#ifdef MVS
+       if(TRACE)printf("HTTCP: gethostbyname() returned %d\n", phost);
+#endif
+       if (!phost) {
+           if (TRACE) printf(
+                   "HTTPAccess: Can't find internet node name `%s'.\n",host);
+           return -1;  /* Fail? */
+       }
+       memcpy(&sin->sin_addr, phost->h_addr, phost->h_length);
+    }
+
+    if (TRACE) printf( 
+       "TCP: Parsed address as port %d, IP address %d.%d.%d.%d\n",
+               (unsigned int)ntohs(sin->sin_port),
+               (int)*((unsigned char *)(&sin->sin_addr)+0),
+               (int)*((unsigned char *)(&sin->sin_addr)+1),
+               (int)*((unsigned char *)(&sin->sin_addr)+2),
+               (int)*((unsigned char *)(&sin->sin_addr)+3));
+
+    return 0;  /* OK */
+}
+
+
+
+/*     Derive the name of the host on which we are
+**     -------------------------------------------
+**
+*/
+#ifdef __STDC__
+PRIVATE void get_host_details(void)
+#else
+PRIVATE void get_host_details()
+#endif
+
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 64              /* Arbitrary limit */
+#endif
+
+{
+    char name[MAXHOSTNAMELEN+1];       /* The name of this host */
+#ifdef NEED_HOST_ADDRESS               /* no -- needs name server! */
+    struct hostent * phost;            /* Pointer to host -- See netdb.h */
+#endif
+    int namelength = sizeof(name);
+    
+    if (hostname) return;              /* Already done */
+    gethostname(name, namelength);     /* Without domain */
+    CTRACE(tfp, "TCP: Local host name is %s\n", name);
+    StrAllocCopy(hostname, name);
+
+#ifdef NEED_HOST_ADDRESS               /* no -- needs name server! */
+    phost=gethostbyname(name);         /* See netdb.h */
+    if (!phost) {
+       if (TRACE) printf(
+               "TCP: Can't find my own internet node address for `%s'!!\n",
+               name);
+       return;  /* Fail! */
+    }
+    StrAllocCopy(hostname, phost->h_name);
+    memcpy(&HTHostAddress, &phost->h_addr, phost->h_length);
+    if (TRACE) printf("     Name server says that is `%s' = %s\n",
+           hostname, HTInetString(&HTHostAddress));
+#endif
+}
+
+#ifdef __STDC__
+PUBLIC const char * HTHostName(void)
+#else
+PUBLIC char * HTHostName()
+#endif
+{
+    get_host_details();
+    return hostname;
+}
+
diff --git a/Cl/WWWLibrary/HTTCP.h b/Cl/WWWLibrary/HTTCP.h
new file mode 100644 (file)
index 0000000..3e9a04a
--- /dev/null
@@ -0,0 +1,98 @@
+/*                     Generic Communication Code              HTTCP.h
+**                     ==========================
+**
+*/
+#include "tcp.h"
+
+#ifdef SHORT_NAMES
+#define HTInetStatus            HTInStat
+#define HTInetString           HTInStri
+#define HTParseInet            HTPaInet
+#endif
+
+
+/*     Produce a string for an internet address
+**     ---------------------------------------
+**
+** On exit,
+**     returns a pointer to a static string which must be copied if
+**             it is to be kept.
+*/
+#ifdef __STDC__
+extern const char * HTInetString(struct sockaddr_in* sin);
+#else
+extern char * HTInetString();
+#endif
+
+
+/*     Encode INET status (as in sys/errno.h)                    inet_status()
+**     ------------------
+**
+** On entry,
+**     where           gives a description of what caused the error
+**     global errno    gives the error number in the unix way.
+**
+** On return,
+**     returns         a negative status in the unix way.
+*/
+#ifdef __STDC__
+extern int HTInetStatus(char *where);
+#else
+extern int HTInetStatus();
+#endif
+
+/*     Publicly accesible variables
+*/
+/* extern struct sockaddr_in HTHostAddress; */
+                       /* The internet address of the host */
+                       /* Valid after call to HTHostName() */
+
+
+/*     Parse a cardinal value                                 parse_cardinal()
+**     ----------------------
+**
+** On entry,
+**     *pp         points to first character to be interpreted, terminated by
+**                 non 0:9 character.
+**     *pstatus    points to status already valid
+**     maxvalue    gives the largest allowable value.
+**
+** On exit,
+**     *pp         points to first unread character
+**     *pstatus    points to status updated iff bad
+*/
+#ifdef __STDC__
+extern unsigned int HTCardinal(int *pstatus,
+       char            **pp,
+       unsigned int    max_value);
+#else
+extern unsigned int HTCardinal();
+#endif
+
+/*     Parse an internet node address and port
+**     ---------------------------------------
+**
+** On entry,
+**     str     points to a string with a node name or number,
+**             with optional trailing colon and port number.
+**     sin     points to the binary internet address field.
+**
+** On exit,
+**     *sin    is filled in. If no port is specified in str, that
+**             field is left unchanged in *sin.
+*/
+#ifdef __STDC__
+extern int HTParseInet(struct sockaddr_in* sin, const char *str);
+#else
+extern int HTParseInet();
+#endif
+
+/*     Get Name of This Machine
+**     ------------------------
+**
+*/
+#ifdef __STDC__
+extern const char * HTHostName(void);
+#else
+extern char * HTHostName();
+#endif
diff --git a/Cl/WWWLibrary/HTTP.c b/Cl/WWWLibrary/HTTP.c
new file mode 100644 (file)
index 0000000..69c6006
--- /dev/null
@@ -0,0 +1,132 @@
+/*     HyperText Tranfer Protocol      - Client implementation         HTTP.c
+**     ==========================
+*/
+
+/*     Module parameters:
+**     -----------------
+**
+**  These may be undefined and redefined by syspec.h
+*/
+#include "HTParse.h"
+#include "HTUtils.h"
+#include "tcp.h"
+#include "HTTCP.h"
+#include "HTFormat.h"
+
+
+#ifndef ERWISE
+/*             Load Dcoument from HTTP Server                  HTLoadHTTP()
+**             ==============================
+**
+**     Given a hypertext address, this routine loads a document.
+**
+**
+** On entry,
+**     arg     is the hypertext reference of the article to be loaded.
+**     gate    is nill if no gateway, else the gateway address.
+**
+** On exit,
+**     returns >=0     If no error, a good socket number
+**             <0      Error.
+**
+**     The socket must be closed by the caller after the document has been
+**     read.
+**
+*/
+PUBLIC int HTLoadHTTP ARGS4 (CONST char *, arg,
+       CONST char *,   gate, 
+       HTAnchor *,     anAnchor,
+       int,            diag)
+{
+    int s;                             /* Socket number for returned data */
+    char *command;                     /* The whole command */
+    int status;                                /* tcp return */
+    struct sockaddr_in soc_address;    /* Binary network address */
+    struct sockaddr_in* sin = &soc_address;
+
+    if (!arg) return -3;                       /* Bad if no name sepcified     */
+    if (!*arg) return -2;                      /* Bad if name had zero length  */
+
+/*  Set up defaults:
+*/
+    sin->sin_family = AF_INET;                 /* Family, host order  */
+    sin->sin_port = htons(TCP_PORT);           /* Default: new port,    */
+
+    if (TRACE) {
+        if (gate) fprintf(stderr,
+               "HTTPAccess: Using gateway %s for %s\n", gate, arg);
+        else fprintf(stderr, "HTTPAccess: Direct access for %s\n", arg);
+    }
+    
+/* Get node name and optional port number:
+*/
+    {
+       char *p1 = HTParse(gate ? gate : arg, "", PARSE_HOST);
+       HTParseInet(sin, p1);
+        free(p1);
+    }
+    
+   
+/*     Now, let's get a socket set up from the server for the sgml data:
+*/      
+    s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+    status = connect(s, (struct sockaddr*)&soc_address, sizeof(soc_address));
+    if (status<0){
+       if (TRACE) printf(
+           "HTTP: Unable to connect to remote host for `%s'.\n",
+           arg);
+       free(command);
+       return HTInetStatus("connect");
+    }
+    
+    if (TRACE) printf("HTTP connected, socket %d\n", s);
+
+/*     Ask that node for the document,
+**     omitting the host name & anchor if not gatewayed.
+*/        
+    if (gate) {
+        command = malloc(4 + strlen(arg)+ 2 + 1);
+        if (command == NULL) outofmem(__FILE__, "HTLoadHTTP");
+        strcpy(command, "GET ");
+       strcat(command, arg);
+    } else { /* not gatewayed */
+       char * p1 = HTParse(arg, "", PARSE_PATH|PARSE_PUNCTUATION);
+        command = malloc(4 + strlen(p1)+ 2 + 1);
+      if (command == NULL) outofmem(__FILE__, "HTLoadHTTP");
+        strcpy(command, "GET ");
+       strcat(command, p1);
+       free(p1);
+    }
+    strcat(command, "\r\n");           /* Include CR for telnet compat. */
+           
+
+    if (TRACE) printf("HTTP writing command `%s' to socket %d\n", command, s);
+    
+#ifdef NOT_ASCII
+    {
+       char * p;
+       for(p = command; *p; p++) {
+           *p = TOASCII(*p);
+       }
+    }
+#endif
+
+    status = NETWRITE(s, command, (int)strlen(command));
+    free(command);
+    if (status<0){
+       if (TRACE) printf("HTTPAccess: Unable to send command.\n");
+           return HTInetStatus("send");
+    }
+
+/*     Now load the  date
+*/
+    HTParseFormat(diag ? WWW_PLAINTEXT : WWW_HTML,
+                (HTParentAnchor *) anAnchor, s);
+    
+    if (TRACE) printf("HTTP: close socket %d.\n", s);
+    status = NETCLOSE(s);
+
+    return HT_LOADED;                  /* Good return */
+}
+#endif /* ERWISE */
diff --git a/Cl/WWWLibrary/HTTP.h b/Cl/WWWLibrary/HTTP.h
new file mode 100644 (file)
index 0000000..be72957
--- /dev/null
@@ -0,0 +1,39 @@
+/*     HyperText Tranfer Protocol                                      HTTP.h
+**     ==========================
+*/
+
+#ifndef HTTP_H
+#define HTTP_H
+
+#include "HTAnchor.h"
+
+/*             Open Socket for reading from HTTP Server        HTTP_get()
+**             ========================================
+**
+**     Given a hypertext address, this routine opens a socket to the server,
+**     sends the "get" command to ask for the node, and then returns the
+**     socket to the caller. The socket must later be closed by the caller.
+**
+** On entry,
+**     arg     is the hypertext reference of the article to be loaded.
+** On exit,
+**     returns >=0     If no error, a good socket number
+**             <0      Error.
+**
+*/
+#ifdef __STDC__
+extern int HTTP_Get(const char * arg);
+#else
+extern int HTTP_Get();
+#endif
+
+/*     Load Document using HTTP
+**     ------------------------
+*/
+
+extern int HTLoadHTTP PARAMS((CONST char *arg,
+       CONST char * gateway,
+       HTParentAnchor * anAnchor,
+       int diag));
+
+#endif /* HTTP_H */
diff --git a/Cl/WWWLibrary/HTUtils.h b/Cl/WWWLibrary/HTUtils.h
new file mode 100644 (file)
index 0000000..b911690
--- /dev/null
@@ -0,0 +1,197 @@
+/*     Macros for general use                                  HTUtils.h
+**
+**     See also: the system dependent file "tcp.h"
+*/
+
+/* extern void *malloc(size_t size); */
+
+#ifndef HTUTILS_H
+#define HTUTILS_H
+
+#ifdef SHORT_NAMES
+#define WWW_TraceFlag HTTrFlag
+#endif
+
+/*     Debug message control.
+*/
+#ifdef DEBUG
+
+#ifndef STDIO_H
+#include <stdio.h>
+#define STDIO_H
+#endif
+
+#define TRACE (WWW_TraceFlag)
+#define PROGRESS(str) printf(str)
+extern int WWW_TraceFlag;
+#else
+#define TRACE 0
+#define PROGRESS(str) /* nothing for now */
+#endif
+#define CTRACE if(TRACE)fprintf
+#define tfp stdout
+
+/*     Standard C library for malloc() etc
+*/
+#ifdef vax
+#ifdef unix
+#define ultrix /* Assume vax+unix=ultrix */
+#endif
+#endif
+
+#ifndef VMS
+#ifndef ultrix
+#ifdef NeXT
+#include <libc.h>      /* NeXT */
+#endif
+#ifndef MACH           /* Vincent.Cate@furmint.nectar.cs.cmu.edu */
+#include <stdlib.h>    /* ANSI */
+#endif
+#else
+#include <malloc.h>    /* ultrix */
+#include <memory.h>
+#include <stdio.h>
+#endif
+
+#else                          /* VMS */
+#include <stdio.h>
+#include <ctype.h>
+#endif
+
+#define PUBLIC                 /* Accessible outside this module     */
+#define PRIVATE static         /* Accessible only within this module */
+
+#ifdef __STDC__
+#define CONST const            /* "const" only exists in STDC */
+#define NOPARAMS (void)
+#define PARAMS(parameter_list) parameter_list
+#define NOARGS (void)
+#define ARGS1(t,a) \
+  (t a)
+#define ARGS2(t,a,u,b) \
+  (t a, u b)
+#define ARGS3(t,a,u,b,v,c) \
+  (t a, u b, v c)
+#define ARGS4(t,a,u,b,v,c,w,d) \
+  (t a, u b, v c, w d)
+#define ARGS5(t,a,u,b,v,c,w,d,x,e) \
+  (t a, u b, v c, w d, x e)
+#define ARGS6(t,a,u,b,v,c,w,d,x,e,y,f) \
+  (t a, u b, v c, w d, x e, y f)
+#define ARGS7(t,a,u,b,v,c,w,d,x,e,y,f,z,g) \
+  (t a, u b, v c, w d, x e, y f, z g)
+#define ARGS8(t,a,u,b,v,c,w,d,x,e,y,f,z,g,s,h) \
+  (t a, u b, v c, w d, x e, y f, z g, s h)
+#define ARGS9(t,a,u,b,v,c,w,d,x,e,y,f,z,g,s,h,r,i) \
+  (t a, u b, v c, w d, x e, y f, z g, s h, r i)
+
+#else  /* not ANSI */
+
+#define CONST
+#define NOPARAMS ()
+#define PARAMS(parameter_list) ()
+#define NOARGS ()
+#define ARGS1(t,a) (a) \
+  t a;
+#define ARGS2(t,a,u,b) (a,b) \
+  t a; u b;
+#define ARGS3(t,a,u,b,v,c) (a,b,c) \
+  t a; u b; v c;
+#define ARGS4(t,a,u,b,v,c,w,d) (a,b,c,d) \
+  t a; u b; v c; w d;
+#define ARGS5(t,a,u,b,v,c,w,d,x,e) (a,b,c,d,e) \
+  t a; u b; v c; w d; x e;
+#define ARGS6(t,a,u,b,v,c,w,d,x,e,y,f) (a,b,c,d,e,f) \
+  t a; u b; v c; w d; x e; y f;
+#define ARGS7(t,a,u,b,v,c,w,d,x,e,y,f,z,g) (a,b,c,d,e,f,g) \
+  t a; u b; v c; w d; x e; y f; z g;
+#define ARGS8(t,a,u,b,v,c,w,d,x,e,y,f,z,g,s,h) (a,b,c,d,e,f,g,h) \
+  t a; u b; v c; w d; x e; y f; z g; s h;
+#define ARGS9(t,a,u,b,v,c,w,d,x,e,y,f,z,g,s,h,r,i) (a,b,c,d,e,f,g,h,i) \
+  t a; u b; v c; w d; x e; y f; z g; s h; r i;
+
+#endif /* __STDC__ (ANSI) */
+
+#ifndef NULL
+#define NULL ((void *)0)
+#endif
+
+
+/* Note: GOOD and BAD are already defined (differently) on RS6000 aix */
+/* #define GOOD(status) ((status)&1)    VMS style status: test bit 0         */
+/* #define BAD(status)  (!GOOD(status))         Bit 0 set if OK, otherwise clear   */
+
+#ifndef BOOLEAN_DEFINED
+typedef char   BOOLEAN;                /* Logical value */
+#ifndef CURSES
+#ifndef TRUE
+#define TRUE   (BOOLEAN)1
+#define        FALSE   (BOOLEAN)0
+#endif
+#endif
+#define BOOLEAN_DEFINED
+#endif
+
+#ifndef BOOL
+#define BOOL BOOLEAN
+#endif
+#ifndef YES
+#define YES (BOOLEAN)1
+#define NO (BOOLEAN)0
+#endif
+
+#define TCP_PORT 2784          /* 80 Allocated by Jon Postel/ISI 24-Jan-92 */
+
+/*     Is character c white space? */
+
+#ifndef NOT_ASCII
+#define WHITE(c) (((unsigned char)(c))<=' ')   /* Assumes ASCII but faster */
+#else
+#define WHITE(c) ( ((c)==' ') || ((c)=='\t') || ((c)=='\n') || ((c)=='\r') )
+#endif
+
+#define HT_LOADED (29999)              /* Instead of a socket */
+
+#include "HTString.h"  /* String utilities */
+
+#ifndef ERWISE_UI
+#ifdef __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#else
+#include <varargs.h>
+#endif /* ERWISE */
+
+#ifdef CURSES
+/* htbrowse.c; */
+#include <curses.h>
+
+extern        WINDOW  *w_top, *w_text, *w_prompt;
+extern        void    user_message PARAMS((const char *fmt, ...));
+extern        void    prompt_set PARAMS((CONST char * msg));
+extern        void    prompt_count PARAMS((long kb));
+#else
+#define user_message printf
+#endif
+
+/*     Out Of Memory checking for malloc() return:
+*/
+#ifndef __FILE__
+#define __FILE__ ""
+#define __LINE__ ""
+#endif
+
+#define outofmem(file, func) \
+ { fprintf(stderr, "%s %s: out of memory.\nProgram aborted.\n", file, func); \
+  exit(1);}
+/* extern void outofmem PARAMS((const char *fname, const char *func)); */
+
+
+extern        void    msg_init PARAMS((int height));
+extern        void    msg_printf PARAMS((int y, const char *fmt, ...));
+extern        void    msg_exit PARAMS((int wait_for_key));
+
+#endif /* HTUTILS_H */
+
diff --git a/Cl/WWWLibrary/HText.h b/Cl/WWWLibrary/HText.h
new file mode 100644 (file)
index 0000000..c060180
--- /dev/null
@@ -0,0 +1,166 @@
+/*                     HyperText Object                        HText.h
+**                     ================
+**     This is the C intreface to the Objective-C HyperText class.
+*/
+
+#ifndef HTEXT_H
+#define HTEXT_H
+#include "HTAnchor.h"
+#include "HTStyle.h"
+
+#ifdef SHORT_NAMES
+#define HTMainText                     HTMaText
+#define HTMainAnchor                   HtMaAnch
+#define HText_new                      HTHTNew
+#define HText_free                     HTHTFree
+#define HText_beginAppend              HTHTBeAp
+#define HText_endAppend                        HTHTEnAp
+#define HText_setStyle                 HTHTSeSt
+#define HText_appendCharacter          HTHTApCh
+#define HText_appendText               HTHTApTe
+#define HText_appendParagraph          HTHTApPa
+#define HText_beginAnchor              HTHTBeAn
+#define HText_endAnchor                        HTHTEnAn
+#define HText_dump                     HTHTDump
+#define HText_nodeAnchor               HTHTNoAn
+#define HText_select                   HTHTSele
+#define HText_selectAnchor             HTHTSeAn
+#define HText_applyStyle               HTHTApSt
+#define HText_updateStyle              HTHTUpSt
+#define HText_selectionStyle           HTHTStyl
+#define HText_replaceSel               HTHTRepl
+#define HText_applyToSimilar           HTHTApTo
+#define HText_selectUnstyled           HTHTSeUn
+#define HText_unlinkSelection          HTHTUnSe
+#define HText_linkSelTo                        HTHTLiSe
+#define HText_referenceSelected                HTHTRefS
+#endif
+
+#ifndef THINK_C
+typedef struct _HText HText;
+#else
+class CHyperText;              /* Part of the Mac browser */
+typedef CHyperText HText
+#endif
+
+extern HText * HTMainText;             /* Pointer to current main text */
+extern HTParentAnchor * HTMainAnchor;  /* Pointer to current text's anchor */
+
+/*                     Creation and deletion
+**
+**     Create hypertext object                                 HText_new
+*/
+ extern HText *        HText_new PARAMS((HTParentAnchor * anchor));
+
+/*     Free hypertext object                                   HText_free
+*/
+extern void    HText_free PARAMS((HText * me));
+
+
+/*                     Object Building methods
+**                     -----------------------
+**
+**     These are used by a parser to build the text in an object
+**     HText_beginAppend must be called, then any combination of other
+**     append calls, then HText_endAppend. This allows optimised
+**     handling using buffers and caches which are flushed at the end.
+*/
+extern void HText_beginAppend PARAMS((HText * text));
+
+extern void HText_endAppend PARAMS((HText * text));
+
+/*     Set the style for future text
+*/
+extern void HText_setStyle PARAMS((HText * text, HTStyle * style));
+
+/*     Add one character
+*/
+extern void HText_appendCharacter PARAMS((HText * text, char ch));
+
+/*     Add a zero-terminated string
+*/
+extern void HText_appendText PARAMS((HText * text, CONST char * str));
+
+/*     New Paragraph
+*/
+extern void HText_appendParagraph PARAMS((HText * text));
+
+/*     Start/end sensitive text
+**
+** The anchor object is created and passed to HText_beginAnchor.
+** The senstive text is added to the text object, and then HText_endAnchor
+** is called. Anchors may not be nested.
+*/
+
+extern void HText_beginAnchor PARAMS((HText * text, HTChildAnchor * anc));
+extern void HText_endAnchor PARAMS((HText * text));
+
+
+/*     Dump diagnostics to stderr
+*/
+extern void HText_dump PARAMS((HText * me));   
+
+/*     Return the anchor associated with this node
+*/
+extern HTParentAnchor * HText_nodeAnchor PARAMS((HText * me));
+
+
+/*             Browsing functions
+**             ------------------
+*/
+
+/*     Bring to front and highlight it
+*/
+
+extern BOOL HText_select PARAMS((HText * text)); 
+extern BOOL HText_selectAnchor PARAMS((HText * text, HTChildAnchor* anchor)); 
+
+/*             Editing functions
+**             -----------------
+**
+**     These are called from the application. There are many more functions
+**     not included here from the orginal text object. These functions
+**     NEED NOT BE IMPLEMENTED in a browser which cannot edit.
+*/
+
+/*     Style handling:
+*/
+/*     Apply this style to the selection
+*/
+extern void HText_applyStyle PARAMS((HText * me, HTStyle *style));
+
+/*     Update all text with changed style.
+*/
+extern void HText_updateStyle PARAMS((HText * me, HTStyle *style));
+
+/*     Return style of  selection
+*/
+extern HTStyle * HText_selectionStyle PARAMS((
+       HText * me,
+       HTStyleSheet* sheet));
+
+/*     Paste in styled text
+*/
+extern void HText_replaceSel PARAMS((HText * me,
+       CONST char *aString, 
+       HTStyle* aStyle));
+
+/*     Apply this style to the selection and all similarly formatted text
+**     (style recovery only)
+*/
+extern void HTextApplyToSimilar PARAMS((HText * me, HTStyle *style));
+/*     Select the first unstyled run.
+**     (style recovery only)
+*/
+extern void HTextSelectUnstyled PARAMS((HText * me, HTStyleSheet *sheet));
+
+
+/*     Anchor handling:
+*/
+extern void            HText_unlinkSelection PARAMS((HText * me));
+extern HTAnchor *      HText_referenceSelected PARAMS((HText * me));
+extern HTAnchor *      HText_linkSelTo PARAMS((HText * me, HTAnchor* anchor));
+
+
+#endif /* HTEXT_H */
diff --git a/Cl/WWWLibrary/Imakefile b/Cl/WWWLibrary/Imakefile
new file mode 100644 (file)
index 0000000..7b02026
--- /dev/null
@@ -0,0 +1,19 @@
+#
+#
+#
+           OBJS        = HTAccess.o HTFTP.o HTHistory.o HTParse.o HTTP.o       \
+                 HTAnchor.o HTFile.o HTList.o HTString.o SGML.o        \
+                 HTAtom.o HTFormat.o HTML.o HTStyle.o HTChunk.o        \
+                 HTGopher.o HTNews.o HTTCP.o
+
+          SRCS = HTAccess.c HTFTP.c HTHistory.c HTParse.c HTTP.c       \
+                 HTAnchor.c HTFile.c HTList.c HTString.c SGML.c        \
+                 HTAtom.c HTFormat.c HTML.c HTStyle.c HTChunk.c        \
+                 HTGopher.c HTNews.c HTTCP.c
+
+       DEFINES = -DERWISE -I.. -I. -I../../HText
+
+
+NormalLibraryTarget(WWW, $(OBJS))
+
+DependTarget()
diff --git a/Cl/WWWLibrary/Makefile b/Cl/WWWLibrary/Makefile
new file mode 100644 (file)
index 0000000..05a4ccd
--- /dev/null
@@ -0,0 +1,340 @@
+# Makefile generated by imake - do not edit!
+# $XConsortium: imake.c,v 1.65 91/07/25 17:50:17 rws Exp $
+#
+# The cpp used on this machine replaces all newlines and multiple tabs and
+# spaces in a macro expansion with a single space.  Imake tries to compensate
+# for this, but is not always successful.
+#
+
+# -------------------------------------------------------------------------
+# Makefile generated from "Imake.tmpl" and </tmp/IIf.a11091>
+# $XConsortium: Imake.tmpl,v 1.139 91/09/16 08:52:48 rws Exp $
+#
+# Platform-specific parameters may be set in the appropriate <vendor>.cf
+# configuration files.  Site-specific parameters should be set in the file
+# site.def.  Full rebuilds are recommended if any parameters are changed.
+#
+# If your C preprocessor does not define any unique symbols, you will need
+# to set BOOTSTRAPCFLAGS when rebuilding imake (usually when doing
+# "make World" the first time).
+#
+
+# -------------------------------------------------------------------------
+# site-specific configuration parameters that need to come before
+# the platform-specific parameters - edit site.def to change
+
+# site:  $XConsortium: site.def,v 1.2 91/07/30 20:26:44 rws Exp $
+
+# -------------------------------------------------------------------------
+# platform-specific configuration parameters - edit sun.cf to change
+
+# platform:  $XConsortium: sun.cf,v 1.72.1.1 92/03/18 13:13:37 rws Exp $
+
+# operating system:  SunOS 4.1.2
+
+# $XConsortium: sunLib.rules,v 1.7 91/12/20 11:19:47 rws Exp $
+
+.c.o:
+       $(CC) -c $(CFLAGS) $*.c
+
+# -------------------------------------------------------------------------
+# site-specific configuration parameters that go after
+# the platform-specific parameters - edit site.def to change
+
+# site:  $XConsortium: site.def,v 1.2 91/07/30 20:26:44 rws Exp $
+
+            SHELL = /bin/sh
+
+              TOP = ../../.
+      CURRENT_DIR = ./Cl/WWWLibrary
+
+               AR = ar clq
+  BOOTSTRAPCFLAGS =
+               CC = gcc2 -pipe -fstrength-reduce -fpcc-struct-return
+               AS = as
+
+         COMPRESS = compress
+              CPP = /lib/cpp $(STD_CPP_DEFINES)
+    PREPROCESSCMD = gcc2 -pipe -fstrength-reduce -fpcc-struct-return -E $(STD_CPP_DEFINES)
+          INSTALL = install
+               LD = ld
+             LINT = lint
+      LINTLIBFLAG = -C
+         LINTOPTS = -axz
+               LN = ln -s
+             MAKE = make
+               MV = mv
+               CP = cp
+
+           RANLIB = ranlib
+  RANLIBINSTFLAGS =
+
+               RM = rm -f
+            TROFF = psroff
+         MSMACROS = -ms
+              TBL = tbl
+              EQN = eqn
+     STD_INCLUDES =
+  STD_CPP_DEFINES =
+      STD_DEFINES =
+ EXTRA_LOAD_FLAGS = -B/usr/bin/
+  EXTRA_LIBRARIES =
+             TAGS = ctags
+
+    SHAREDCODEDEF = -DSHAREDCODE
+         SHLIBDEF = -DSUNSHLIB
+
+    PROTO_DEFINES =
+
+     INSTPGMFLAGS =
+
+     INSTBINFLAGS = -m 0755
+     INSTUIDFLAGS = -m 4755
+     INSTLIBFLAGS = -m 0644
+     INSTINCFLAGS = -m 0444
+     INSTMANFLAGS = -m 0444
+     INSTDATFLAGS = -m 0444
+    INSTKMEMFLAGS = -g kmem -m 2755
+
+      PROJECTROOT = /v/X11R5
+
+     TOP_INCLUDES = -I$(INCROOT)
+
+      CDEBUGFLAGS = -O
+        CCOPTIONS =
+
+      ALLINCLUDES = $(INCLUDES) $(EXTRA_INCLUDES) $(TOP_INCLUDES) $(STD_INCLUDES)
+       ALLDEFINES = $(ALLINCLUDES) $(STD_DEFINES) $(EXTRA_DEFINES) $(PROTO_DEFINES) $(DEFINES)
+           CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLDEFINES)
+        LINTFLAGS = $(LINTOPTS) -DLINT $(ALLDEFINES)
+
+           LDLIBS = $(SYS_LIBRARIES) $(EXTRA_LIBRARIES)
+
+        LDOPTIONS = $(CDEBUGFLAGS) $(CCOPTIONS) $(LOCAL_LDFLAGS) -L$(USRLIBDIR)
+
+   LDCOMBINEFLAGS = -X -r
+      DEPENDFLAGS =
+
+        MACROFILE = sun.cf
+           RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *~ *.a .emacs_* tags TAGS make.log MakeOut
+
+    IMAKE_DEFINES =
+
+         IRULESRC = $(CONFIGDIR)
+        IMAKE_CMD = $(IMAKE) -DUseInstalled -I$(IRULESRC) $(IMAKE_DEFINES)
+
+     ICONFIGFILES = $(IRULESRC)/Imake.tmpl $(IRULESRC)/Imake.rules \
+                       $(IRULESRC)/Project.tmpl $(IRULESRC)/site.def \
+                       $(IRULESRC)/$(MACROFILE) $(EXTRA_ICONFIGFILES)
+
+# -------------------------------------------------------------------------
+# X Window System Build Parameters
+# $XConsortium: Project.tmpl,v 1.138 91/09/10 09:02:12 rws Exp $
+
+# -------------------------------------------------------------------------
+# X Window System make variables; this need to be coordinated with rules
+
+          PATHSEP = /
+        USRLIBDIR = /v/X11R5/lib
+           BINDIR = /v/X11R5/bin
+          INCROOT = /v/X11R5/include
+     BUILDINCROOT = $(TOP)
+      BUILDINCDIR = $(BUILDINCROOT)/X11
+      BUILDINCTOP = ..
+           INCDIR = $(INCROOT)/X11
+           ADMDIR = /usr/adm
+           LIBDIR = $(USRLIBDIR)/X11
+        CONFIGDIR = $(LIBDIR)/config
+       LINTLIBDIR = $(USRLIBDIR)/lint
+
+          FONTDIR = $(LIBDIR)/fonts
+         XINITDIR = $(LIBDIR)/xinit
+           XDMDIR = $(LIBDIR)/xdm
+           TWMDIR = $(LIBDIR)/twm
+          MANPATH = /v/X11R5/man
+    MANSOURCEPATH = $(MANPATH)/man
+        MANSUFFIX = n
+     LIBMANSUFFIX = 3
+           MANDIR = $(MANSOURCEPATH)$(MANSUFFIX)
+        LIBMANDIR = $(MANSOURCEPATH)$(LIBMANSUFFIX)
+           NLSDIR = $(LIBDIR)/nls
+        PEXAPIDIR = $(LIBDIR)/PEX
+      XAPPLOADDIR = $(LIBDIR)/app-defaults
+       FONTCFLAGS = -t
+
+     INSTAPPFLAGS = $(INSTDATFLAGS)
+
+            IMAKE = imake
+           DEPEND = makedepend
+              RGB = rgb
+
+            FONTC = bdftopcf
+
+        MKFONTDIR = mkfontdir
+        MKDIRHIER = /bin/sh $(BINDIR)/mkdirhier
+
+        CONFIGSRC = $(TOP)/config
+       DOCUTILSRC = $(TOP)/doc/util
+        CLIENTSRC = $(TOP)/clients
+          DEMOSRC = $(TOP)/demos
+           LIBSRC = $(TOP)/lib
+          FONTSRC = $(TOP)/fonts
+       INCLUDESRC = $(TOP)/X11
+        SERVERSRC = $(TOP)/server
+          UTILSRC = $(TOP)/util
+        SCRIPTSRC = $(UTILSRC)/scripts
+       EXAMPLESRC = $(TOP)/examples
+       CONTRIBSRC = $(TOP)/../contrib
+           DOCSRC = $(TOP)/doc
+           RGBSRC = $(TOP)/rgb
+        DEPENDSRC = $(UTILSRC)/makedepend
+         IMAKESRC = $(CONFIGSRC)
+         XAUTHSRC = $(LIBSRC)/Xau
+          XLIBSRC = $(LIBSRC)/X
+           XMUSRC = $(LIBSRC)/Xmu
+       TOOLKITSRC = $(LIBSRC)/Xt
+       AWIDGETSRC = $(LIBSRC)/Xaw
+       OLDXLIBSRC = $(LIBSRC)/oldX
+      XDMCPLIBSRC = $(LIBSRC)/Xdmcp
+      BDFTOSNFSRC = $(FONTSRC)/bdftosnf
+      BDFTOSNFSRC = $(FONTSRC)/clients/bdftosnf
+      BDFTOPCFSRC = $(FONTSRC)/clients/bdftopcf
+     MKFONTDIRSRC = $(FONTSRC)/clients/mkfontdir
+         FSLIBSRC = $(FONTSRC)/lib/fs
+    FONTSERVERSRC = $(FONTSRC)/server
+     EXTENSIONSRC = $(TOP)/extensions
+         XILIBSRC = $(EXTENSIONSRC)/lib/xinput
+      PHIGSLIBSRC = $(EXTENSIONSRC)/lib/PEX
+
+# $XConsortium: sunLib.tmpl,v 1.14.1.1 92/03/17 14:58:46 rws Exp $
+
+SHLIBLDFLAGS = -assert pure-text
+PICFLAGS = -fPIC
+
+  DEPEXTENSIONLIB =
+     EXTENSIONLIB = -lXext
+
+          DEPXLIB = $(DEPEXTENSIONLIB)
+             XLIB = $(EXTENSIONLIB) -lX11
+
+        DEPXMULIB = $(USRLIBDIR)/libXmu.sa.$(SOXMUREV)
+       XMULIBONLY = -lXmu
+           XMULIB = -lXmu
+
+       DEPOLDXLIB =
+          OLDXLIB = -loldX
+
+      DEPXTOOLLIB = $(USRLIBDIR)/libXt.sa.$(SOXTREV)
+         XTOOLLIB = -lXt
+
+        DEPXAWLIB = $(USRLIBDIR)/libXaw.sa.$(SOXAWREV)
+           XAWLIB = -lXaw
+
+        DEPXILIB =
+           XILIB = -lXi
+
+        SOXLIBREV = 4.10
+          SOXTREV = 4.10
+         SOXAWREV = 5.0
+        SOOLDXREV = 4.10
+         SOXMUREV = 4.10
+        SOXEXTREV = 4.10
+      SOXINPUTREV = 4.10
+
+      DEPXAUTHLIB = $(USRLIBDIR)/libXau.a
+         XAUTHLIB =  -lXau
+      DEPXDMCPLIB = $(USRLIBDIR)/libXdmcp.a
+         XDMCPLIB =  -lXdmcp
+
+        DEPPHIGSLIB = $(USRLIBDIR)/libphigs.a
+           PHIGSLIB =  -lphigs
+
+       DEPXBSDLIB = $(USRLIBDIR)/libXbsd.a
+          XBSDLIB =  -lXbsd
+
+ LINTEXTENSIONLIB = $(LINTLIBDIR)/llib-lXext.ln
+         LINTXLIB = $(LINTLIBDIR)/llib-lX11.ln
+          LINTXMU = $(LINTLIBDIR)/llib-lXmu.ln
+        LINTXTOOL = $(LINTLIBDIR)/llib-lXt.ln
+          LINTXAW = $(LINTLIBDIR)/llib-lXaw.ln
+           LINTXI = $(LINTLIBDIR)/llib-lXi.ln
+        LINTPHIGS = $(LINTLIBDIR)/llib-lphigs.ln
+
+          DEPLIBS = $(DEPXAWLIB) $(DEPXMULIB) $(DEPXTOOLLIB) $(DEPXLIB)
+
+         DEPLIBS1 = $(DEPLIBS)
+         DEPLIBS2 = $(DEPLIBS)
+         DEPLIBS3 = $(DEPLIBS)
+
+# -------------------------------------------------------------------------
+# Imake rules for building libraries, programs, scripts, and data files
+# rules:  $XConsortium: Imake.rules,v 1.123 91/09/16 20:12:16 rws Exp $
+
+# -------------------------------------------------------------------------
+# start of Imakefile
+
+#
+#
+#
+           OBJS        = HTAccess.o HTFTP.o HTHistory.o HTParse.o HTTP.o       \
+                 HTAnchor.o HTFile.o HTList.o HTString.o SGML.o        \
+                 HTAtom.o HTFormat.o HTML.o HTStyle.o HTChunk.o        \
+                 HTGopher.o HTNews.o HTTCP.o
+
+          SRCS = HTAccess.c HTFTP.c HTHistory.c HTParse.c HTTP.c       \
+                 HTAnchor.c HTFile.c HTList.c HTString.c SGML.c        \
+                 HTAtom.c HTFormat.c HTML.c HTStyle.c HTChunk.c        \
+                 HTGopher.c HTNews.c HTTCP.c
+
+       DEFINES = -DERWISE -I.. -I. -I../../HText
+
+all:: libWWW.a
+
+libWWW.a:  $(OBJS)
+       $(RM) $@
+       $(AR) $@  $(OBJS)
+       $(RANLIB) $@
+
+depend::
+       $(DEPEND) $(DEPENDFLAGS) -s "# DO NOT DELETE" -- $(ALLDEFINES) -- $(SRCS)
+
+# -------------------------------------------------------------------------
+# common rules for all Makefiles - do not edit
+
+emptyrule::
+
+clean::
+       $(RM_CMD) "#"*
+
+Makefile::
+       -@if [ -f Makefile ]; then set -x; \
+       $(RM) Makefile.bak; $(MV) Makefile Makefile.bak; \
+       else exit 0; fi
+       $(IMAKE_CMD) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT_DIR)
+
+tags::
+       $(TAGS) -w *.[ch]
+       $(TAGS) -xw *.[ch] > TAGS
+
+saber:
+       # load $(ALLDEFINES) $(SRCS)
+
+osaber:
+       # load $(ALLDEFINES) $(OBJS)
+
+# -------------------------------------------------------------------------
+# empty rules for directories that do not have SUBDIRS - do not edit
+
+install::
+       @echo "install in $(CURRENT_DIR) done"
+
+install.man::
+       @echo "install.man in $(CURRENT_DIR) done"
+
+Makefiles::
+
+includes::
+
+# -------------------------------------------------------------------------
+# dependencies generated by makedepend
+
diff --git a/Cl/WWWLibrary/Makefile.bak b/Cl/WWWLibrary/Makefile.bak
new file mode 100644 (file)
index 0000000..1d499b2
--- /dev/null
@@ -0,0 +1,340 @@
+# Makefile generated by imake - do not edit!
+# $XConsortium: imake.c,v 1.65 91/07/25 17:50:17 rws Exp $
+#
+# The cpp used on this machine replaces all newlines and multiple tabs and
+# spaces in a macro expansion with a single space.  Imake tries to compensate
+# for this, but is not always successful.
+#
+
+# -------------------------------------------------------------------------
+# Makefile generated from "Imake.tmpl" and </tmp/IIf.a10847>
+# $XConsortium: Imake.tmpl,v 1.139 91/09/16 08:52:48 rws Exp $
+#
+# Platform-specific parameters may be set in the appropriate <vendor>.cf
+# configuration files.  Site-specific parameters should be set in the file
+# site.def.  Full rebuilds are recommended if any parameters are changed.
+#
+# If your C preprocessor does not define any unique symbols, you will need
+# to set BOOTSTRAPCFLAGS when rebuilding imake (usually when doing
+# "make World" the first time).
+#
+
+# -------------------------------------------------------------------------
+# site-specific configuration parameters that need to come before
+# the platform-specific parameters - edit site.def to change
+
+# site:  $XConsortium: site.def,v 1.2 91/07/30 20:26:44 rws Exp $
+
+# -------------------------------------------------------------------------
+# platform-specific configuration parameters - edit sun.cf to change
+
+# platform:  $XConsortium: sun.cf,v 1.72.1.1 92/03/18 13:13:37 rws Exp $
+
+# operating system:  SunOS 4.1.2
+
+# $XConsortium: sunLib.rules,v 1.7 91/12/20 11:19:47 rws Exp $
+
+.c.o:
+       $(CC) -c $(CFLAGS) $*.c
+
+# -------------------------------------------------------------------------
+# site-specific configuration parameters that go after
+# the platform-specific parameters - edit site.def to change
+
+# site:  $XConsortium: site.def,v 1.2 91/07/30 20:26:44 rws Exp $
+
+            SHELL = /bin/sh
+
+              TOP = ../../.
+      CURRENT_DIR = ./Cl/WWWLibrary
+
+               AR = ar clq
+  BOOTSTRAPCFLAGS =
+               CC = gcc2 -pipe -fstrength-reduce -fpcc-struct-return
+               AS = as
+
+         COMPRESS = compress
+              CPP = /lib/cpp $(STD_CPP_DEFINES)
+    PREPROCESSCMD = gcc2 -pipe -fstrength-reduce -fpcc-struct-return -E $(STD_CPP_DEFINES)
+          INSTALL = install
+               LD = ld
+             LINT = lint
+      LINTLIBFLAG = -C
+         LINTOPTS = -axz
+               LN = ln -s
+             MAKE = make
+               MV = mv
+               CP = cp
+
+           RANLIB = ranlib
+  RANLIBINSTFLAGS =
+
+               RM = rm -f
+            TROFF = psroff
+         MSMACROS = -ms
+              TBL = tbl
+              EQN = eqn
+     STD_INCLUDES =
+  STD_CPP_DEFINES =
+      STD_DEFINES =
+ EXTRA_LOAD_FLAGS = -B/usr/bin/
+  EXTRA_LIBRARIES =
+             TAGS = ctags
+
+    SHAREDCODEDEF = -DSHAREDCODE
+         SHLIBDEF = -DSUNSHLIB
+
+    PROTO_DEFINES =
+
+     INSTPGMFLAGS =
+
+     INSTBINFLAGS = -m 0755
+     INSTUIDFLAGS = -m 4755
+     INSTLIBFLAGS = -m 0644
+     INSTINCFLAGS = -m 0444
+     INSTMANFLAGS = -m 0444
+     INSTDATFLAGS = -m 0444
+    INSTKMEMFLAGS = -g kmem -m 2755
+
+      PROJECTROOT = /v/X11R5
+
+     TOP_INCLUDES = -I$(INCROOT)
+
+      CDEBUGFLAGS = -O
+        CCOPTIONS =
+
+      ALLINCLUDES = $(INCLUDES) $(EXTRA_INCLUDES) $(TOP_INCLUDES) $(STD_INCLUDES)
+       ALLDEFINES = $(ALLINCLUDES) $(STD_DEFINES) $(EXTRA_DEFINES) $(PROTO_DEFINES) $(DEFINES)
+           CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLDEFINES)
+        LINTFLAGS = $(LINTOPTS) -DLINT $(ALLDEFINES)
+
+           LDLIBS = $(SYS_LIBRARIES) $(EXTRA_LIBRARIES)
+
+        LDOPTIONS = $(CDEBUGFLAGS) $(CCOPTIONS) $(LOCAL_LDFLAGS) -L$(USRLIBDIR)
+
+   LDCOMBINEFLAGS = -X -r
+      DEPENDFLAGS =
+
+        MACROFILE = sun.cf
+           RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *~ *.a .emacs_* tags TAGS make.log MakeOut
+
+    IMAKE_DEFINES =
+
+         IRULESRC = $(CONFIGDIR)
+        IMAKE_CMD = $(IMAKE) -DUseInstalled -I$(IRULESRC) $(IMAKE_DEFINES)
+
+     ICONFIGFILES = $(IRULESRC)/Imake.tmpl $(IRULESRC)/Imake.rules \
+                       $(IRULESRC)/Project.tmpl $(IRULESRC)/site.def \
+                       $(IRULESRC)/$(MACROFILE) $(EXTRA_ICONFIGFILES)
+
+# -------------------------------------------------------------------------
+# X Window System Build Parameters
+# $XConsortium: Project.tmpl,v 1.138 91/09/10 09:02:12 rws Exp $
+
+# -------------------------------------------------------------------------
+# X Window System make variables; this need to be coordinated with rules
+
+          PATHSEP = /
+        USRLIBDIR = /v/X11R5/lib
+           BINDIR = /v/X11R5/bin
+          INCROOT = /v/X11R5/include
+     BUILDINCROOT = $(TOP)
+      BUILDINCDIR = $(BUILDINCROOT)/X11
+      BUILDINCTOP = ..
+           INCDIR = $(INCROOT)/X11
+           ADMDIR = /usr/adm
+           LIBDIR = $(USRLIBDIR)/X11
+        CONFIGDIR = $(LIBDIR)/config
+       LINTLIBDIR = $(USRLIBDIR)/lint
+
+          FONTDIR = $(LIBDIR)/fonts
+         XINITDIR = $(LIBDIR)/xinit
+           XDMDIR = $(LIBDIR)/xdm
+           TWMDIR = $(LIBDIR)/twm
+          MANPATH = /v/X11R5/man
+    MANSOURCEPATH = $(MANPATH)/man
+        MANSUFFIX = n
+     LIBMANSUFFIX = 3
+           MANDIR = $(MANSOURCEPATH)$(MANSUFFIX)
+        LIBMANDIR = $(MANSOURCEPATH)$(LIBMANSUFFIX)
+           NLSDIR = $(LIBDIR)/nls
+        PEXAPIDIR = $(LIBDIR)/PEX
+      XAPPLOADDIR = $(LIBDIR)/app-defaults
+       FONTCFLAGS = -t
+
+     INSTAPPFLAGS = $(INSTDATFLAGS)
+
+            IMAKE = imake
+           DEPEND = makedepend
+              RGB = rgb
+
+            FONTC = bdftopcf
+
+        MKFONTDIR = mkfontdir
+        MKDIRHIER = /bin/sh $(BINDIR)/mkdirhier
+
+        CONFIGSRC = $(TOP)/config
+       DOCUTILSRC = $(TOP)/doc/util
+        CLIENTSRC = $(TOP)/clients
+          DEMOSRC = $(TOP)/demos
+           LIBSRC = $(TOP)/lib
+          FONTSRC = $(TOP)/fonts
+       INCLUDESRC = $(TOP)/X11
+        SERVERSRC = $(TOP)/server
+          UTILSRC = $(TOP)/util
+        SCRIPTSRC = $(UTILSRC)/scripts
+       EXAMPLESRC = $(TOP)/examples
+       CONTRIBSRC = $(TOP)/../contrib
+           DOCSRC = $(TOP)/doc
+           RGBSRC = $(TOP)/rgb
+        DEPENDSRC = $(UTILSRC)/makedepend
+         IMAKESRC = $(CONFIGSRC)
+         XAUTHSRC = $(LIBSRC)/Xau
+          XLIBSRC = $(LIBSRC)/X
+           XMUSRC = $(LIBSRC)/Xmu
+       TOOLKITSRC = $(LIBSRC)/Xt
+       AWIDGETSRC = $(LIBSRC)/Xaw
+       OLDXLIBSRC = $(LIBSRC)/oldX
+      XDMCPLIBSRC = $(LIBSRC)/Xdmcp
+      BDFTOSNFSRC = $(FONTSRC)/bdftosnf
+      BDFTOSNFSRC = $(FONTSRC)/clients/bdftosnf
+      BDFTOPCFSRC = $(FONTSRC)/clients/bdftopcf
+     MKFONTDIRSRC = $(FONTSRC)/clients/mkfontdir
+         FSLIBSRC = $(FONTSRC)/lib/fs
+    FONTSERVERSRC = $(FONTSRC)/server
+     EXTENSIONSRC = $(TOP)/extensions
+         XILIBSRC = $(EXTENSIONSRC)/lib/xinput
+      PHIGSLIBSRC = $(EXTENSIONSRC)/lib/PEX
+
+# $XConsortium: sunLib.tmpl,v 1.14.1.1 92/03/17 14:58:46 rws Exp $
+
+SHLIBLDFLAGS = -assert pure-text
+PICFLAGS = -fPIC
+
+  DEPEXTENSIONLIB =
+     EXTENSIONLIB = -lXext
+
+          DEPXLIB = $(DEPEXTENSIONLIB)
+             XLIB = $(EXTENSIONLIB) -lX11
+
+        DEPXMULIB = $(USRLIBDIR)/libXmu.sa.$(SOXMUREV)
+       XMULIBONLY = -lXmu
+           XMULIB = -lXmu
+
+       DEPOLDXLIB =
+          OLDXLIB = -loldX
+
+      DEPXTOOLLIB = $(USRLIBDIR)/libXt.sa.$(SOXTREV)
+         XTOOLLIB = -lXt
+
+        DEPXAWLIB = $(USRLIBDIR)/libXaw.sa.$(SOXAWREV)
+           XAWLIB = -lXaw
+
+        DEPXILIB =
+           XILIB = -lXi
+
+        SOXLIBREV = 4.10
+          SOXTREV = 4.10
+         SOXAWREV = 5.0
+        SOOLDXREV = 4.10
+         SOXMUREV = 4.10
+        SOXEXTREV = 4.10
+      SOXINPUTREV = 4.10
+
+      DEPXAUTHLIB = $(USRLIBDIR)/libXau.a
+         XAUTHLIB =  -lXau
+      DEPXDMCPLIB = $(USRLIBDIR)/libXdmcp.a
+         XDMCPLIB =  -lXdmcp
+
+        DEPPHIGSLIB = $(USRLIBDIR)/libphigs.a
+           PHIGSLIB =  -lphigs
+
+       DEPXBSDLIB = $(USRLIBDIR)/libXbsd.a
+          XBSDLIB =  -lXbsd
+
+ LINTEXTENSIONLIB = $(LINTLIBDIR)/llib-lXext.ln
+         LINTXLIB = $(LINTLIBDIR)/llib-lX11.ln
+          LINTXMU = $(LINTLIBDIR)/llib-lXmu.ln
+        LINTXTOOL = $(LINTLIBDIR)/llib-lXt.ln
+          LINTXAW = $(LINTLIBDIR)/llib-lXaw.ln
+           LINTXI = $(LINTLIBDIR)/llib-lXi.ln
+        LINTPHIGS = $(LINTLIBDIR)/llib-lphigs.ln
+
+          DEPLIBS = $(DEPXAWLIB) $(DEPXMULIB) $(DEPXTOOLLIB) $(DEPXLIB)
+
+         DEPLIBS1 = $(DEPLIBS)
+         DEPLIBS2 = $(DEPLIBS)
+         DEPLIBS3 = $(DEPLIBS)
+
+# -------------------------------------------------------------------------
+# Imake rules for building libraries, programs, scripts, and data files
+# rules:  $XConsortium: Imake.rules,v 1.123 91/09/16 20:12:16 rws Exp $
+
+# -------------------------------------------------------------------------
+# start of Imakefile
+
+#
+#
+#
+           OBJS        = HTAccess.o HTFTP.o HTHistory.o HTParse.o HTTP.o       \
+                 HTAnchor.o HTFile.o HTList.o HTString.o SGML.o        \
+                 HTAtom.o HTFormat.o HTML.o HTStyle.o HTChunk.o        \
+                 HTGopher.o HTNews.o HTTCP.o
+
+          SRCS = HTAccess.c HTFTP.c HTHistory.c HTParse.c HTTP.c       \
+                 HTAnchor.c HTFile.c HTList.c HTString.c SGML.c        \
+                 HTAtom.c HTFormat.c HTML.c HTStyle.c HTChunk.c        \
+                 HTGopher.c HTNews.c HTTCP.c
+
+       DEFINES = -DERWISE -I..
+
+all:: libWWW.a
+
+libWWW.a:  $(OBJS)
+       $(RM) $@
+       $(AR) $@  $(OBJS)
+       $(RANLIB) $@
+
+depend::
+       $(DEPEND) $(DEPENDFLAGS) -s "# DO NOT DELETE" -- $(ALLDEFINES) -- $(SRCS)
+
+# -------------------------------------------------------------------------
+# common rules for all Makefiles - do not edit
+
+emptyrule::
+
+clean::
+       $(RM_CMD) "#"*
+
+Makefile::
+       -@if [ -f Makefile ]; then set -x; \
+       $(RM) Makefile.bak; $(MV) Makefile Makefile.bak; \
+       else exit 0; fi
+       $(IMAKE_CMD) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT_DIR)
+
+tags::
+       $(TAGS) -w *.[ch]
+       $(TAGS) -xw *.[ch] > TAGS
+
+saber:
+       # load $(ALLDEFINES) $(SRCS)
+
+osaber:
+       # load $(ALLDEFINES) $(OBJS)
+
+# -------------------------------------------------------------------------
+# empty rules for directories that do not have SUBDIRS - do not edit
+
+install::
+       @echo "install in $(CURRENT_DIR) done"
+
+install.man::
+       @echo "install.man in $(CURRENT_DIR) done"
+
+Makefiles::
+
+includes::
+
+# -------------------------------------------------------------------------
+# dependencies generated by makedepend
+
diff --git a/Cl/WWWLibrary/README b/Cl/WWWLibrary/README
new file mode 100644 (file)
index 0000000..5e3aa6b
--- /dev/null
@@ -0,0 +1,9 @@
+Copyright WorldWideWeb project CERN 1990, 1991 -- See Copyright.html
+____________________________________________________________________
+
+
+
+This is the common code shared by various WWW products.
+See other /Implementation/ directories for the specific parts.
+
+TBL
diff --git a/Cl/WWWLibrary/SGML.c b/Cl/WWWLibrary/SGML.c
new file mode 100644 (file)
index 0000000..ede5fd9
--- /dev/null
@@ -0,0 +1,426 @@
+/*                     General SGML Parser code                SGML.c
+**                     ========================
+*/
+#include <ctype.h>
+#include <stdio.h>
+#include "HTUtils.h"
+#include "HTChunk.h"
+#include "SGML.h"
+
+#include "tcp.h"       /* For TOUPPER  ! */
+
+static void            (*contents_treatment) PARAMS((char c));
+static HTTag           *current_tag;
+static attr            *current_attribute;
+static HTChunk         *string =0;
+static HTElement       *element_stack;
+
+/*     Handle Attribute
+**     ----------------
+*/
+PUBLIC CONST char * SGML_default = "";
+
+#ifdef __STDC__
+PRIVATE void handle_attribute_name(const char * s)
+#else
+PRIVATE void handle_attribute_name(s)
+    char *s;
+#endif
+{
+    for(    current_attribute = current_tag->attributes;
+           current_attribute->name;
+           current_attribute++) {
+       if (0==strcasecomp(current_attribute->name, s))
+           break;
+    }
+    if (!current_attribute->name) {
+       if (TRACE)
+           fprintf(stderr, "SGML: Unknown attribute %s for tag %s\n",
+               s, current_tag->name);
+        current_attribute = 0; /* Invalid */
+       return;
+    }
+    current_attribute->present = YES;
+    if (current_attribute->value) {
+        free(current_attribute->value);
+       current_attribute->value = 0;
+    }
+}
+
+/*     Handle attribute value
+**     ----------------------
+*/
+#ifdef __STDC__
+PRIVATE void handle_attribute_value(const char * s)
+#else
+PRIVATE void handle_attribute_value(s)
+    char *s;
+#endif
+{
+    if (current_attribute) {
+       StrAllocCopy(current_attribute->value, s);
+    } else {
+        if (TRACE) fprintf(stderr, "SGML: Attribute value %s ignored\n", s);
+    }
+    current_attribute = 0;     /* can't have two assignments! */
+}
+
+/*     Handle entity
+**     -------------
+**
+** On entry,
+**     s       contains the entity name zero terminated
+** Bugs:
+**     If the entity name is unknown, the terminator is treated as
+**     a printable non-special character in all cases, even if it is '<'
+*/
+#ifdef __STDC__
+PRIVATE void handle_entity(const char * s, entity * entities, char term)
+#else
+PRIVATE void handle_entity(s,entities, term)
+    char * s;
+    entity * entities;
+    char term;
+#endif
+{
+    entity * e;
+    for(e = entities; e->name; e++) {
+       if (0==strcmp(e->name, s)) {
+           char * p;
+           for (p=e->representation; *p; p++) {
+               (*contents_treatment)(*p);
+           }
+           return;     /* Good */
+       }
+    }
+    /* If entity string not found, display as text */
+    if (TRACE)
+       fprintf(stderr, "SGML: Unknown entity %s\n", s); 
+    (*contents_treatment)('&');
+    {
+       CONST char *p;
+       for (p=s; *p; p++) {
+           (*contents_treatment)(*p);
+       }
+    }
+    (*contents_treatment)(term);
+}
+
+/*     End element
+*/
+#ifdef __STDC__
+PRIVATE void end_element(HTTag * old_tag)
+#else
+PRIVATE void end_element(old_tag)
+    HTTag * old_tag;
+#endif
+{
+    if (TRACE) fprintf(stderr, "SGML: End   </%s>\n", old_tag->name);
+    if (!old_tag->end) {
+        if (TRACE) fprintf(stderr,"SGML: Illegal end tag </%s> found.\n",
+               old_tag->name);
+       return;
+    }
+    while (element_stack)      {/* Loop is error path only */
+       HTElement * N = element_stack;
+       HTTag * t = element_stack->tag;
+       
+       if (old_tag != t) {             /* Mismatch: syntax error */
+           if (element_stack->next) {  /* This is not the last level */
+               if (TRACE) fprintf(stderr,
+               "SGML: Found </%s> when expecting </%s>. </%s> assumed.\n",
+                   old_tag->name, t->name, t->name);
+           } else {                    /* last level */
+               if (TRACE) fprintf(stderr,
+                   "SGML: Found </%s> when expecting </%s>. </%s> Ignored.\n",
+                   old_tag->name, t->name, old_tag->name);
+               return;                 /* Ignore */
+           }
+       }
+       
+       element_stack = N->next;                /* Remove from stack */
+       free(N);
+       (t->end)(t, element_stack);             /* Assume tag end */
+       if (element_stack)                      /* not end of document */
+           contents_treatment = element_stack->tag->treat;
+       if (old_tag == t) return;  /* Correct sequence */
+       
+       /* Syntax error path only */
+       
+    }
+    fprintf(stderr,
+       "SGML: Extra end tag </%s> found and ignored.\n", old_tag->name);
+}
+
+
+/*     Start a element
+*/
+#ifdef __STDC__
+PRIVATE void start_element(HTTag * new_tag)
+#else
+PRIVATE void start_element(new_tag)
+    HTTag * new_tag;
+#endif
+{
+    if (TRACE) fprintf(stderr, "SGML: Start <%s>\n", new_tag->name);
+    (*new_tag->begin)(new_tag, element_stack);
+    if (new_tag->end) {                /* i.e. tag not empty */
+       HTElement * N = (HTElement *)malloc(sizeof(HTElement));
+        if (N == NULL) outofmem(__FILE__, "start_element");
+       N->next = element_stack;
+       N->tag = new_tag;
+       element_stack = N;
+       contents_treatment = new_tag->treat;
+    }
+}
+
+
+
+/*     SGML Engine
+**     -----------
+**
+** On entry,
+**     dtd->tags               represents the DTD, along with
+**     dtd->entities
+**
+**     default_tag     represents the initial and final actions,
+**                     and the character processing, for data outside
+**                     any tags. May not be empty.
+*/
+
+PRIVATE enum sgml_state { S_text, S_litteral, S_tag, S_tag_gap, 
+               S_attr, S_attr_gap, S_equals, S_value,
+                 S_quoted, S_end, S_entity, S_junk_tag} state;
+
+PUBLIC void SGML_begin  ARGS1(SGML_dtd *,dtd)
+{
+    if (!string) string = HTChunkCreate(128);  /* Grow by this much */
+    
+    state = S_text;
+    start_element(dtd->default_tag);   /* Start document */
+}
+
+PUBLIC void SGML_end  ARGS1(SGML_dtd *,dtd)
+{
+    end_element(dtd->default_tag);     /* End document */
+}
+
+PUBLIC void SGML_character ARGS2(SGML_dtd *,dtd, char,c)
+
+{
+    switch(state) {
+    case S_text:
+       if (c=='&' && !(element_stack &&
+                       element_stack->tag  &&
+                       element_stack->tag->litteral)) {
+           string->size = 0;
+           state = S_entity;
+           
+       } else if (c=='<') {
+           string->size = 0;
+           state = (element_stack &&
+                       element_stack->tag  &&
+                       element_stack->tag->litteral) ?
+                               S_litteral : S_tag;
+       } else (*contents_treatment)(c);
+       break;
+
+/*     In litteral mode, waits only for specific end tag!
+*/
+    case S_litteral :
+       HTChunkPutc(string, c);
+       if ( TOUPPER(c) != ((string->size ==1) ? '/'
+               : element_stack->tag->name[string->size-2])) {
+           int i;
+           
+           /*  If complete match, end litteral */
+           if ((c=='>') && (!element_stack->tag->name[string->size-2])) {
+               end_element(element_stack->tag);
+               string->size = 0;
+               current_attribute = (attr *) 0;
+               state = S_text;
+               break;
+           }           /* If Mismatch: recover string. */
+           (*contents_treatment)('<');
+           for (i=0; i<string->size; i++)      /* recover */
+              (*contents_treatment)(string->data[i]);
+           state = S_text;     
+       }
+       
+        break;
+       
+/*     Handle Entities
+*/
+    case S_entity:
+       if (isalnum(c))
+           HTChunkPutc(string, c);
+       else {
+           HTChunkTerminate(string);
+           handle_entity(string->data, dtd->entities, c);
+           state = S_text;
+       }
+       break;
+       
+/*             Tag
+*/         
+    case S_tag:                                /* new tag */
+       if (isalnum(c))
+           HTChunkPutc(string, c);
+       else {                          /* End of tag name */
+           attr * a;
+           if (c=='/') {
+               if (TRACE) if (string->size!=0)
+                   fprintf(stderr,"SGML:  `<%s/' found!\n", string->data);
+               state = S_end;
+               break;
+           }
+           HTChunkTerminate(string) ;
+           for(current_tag = dtd->tags; current_tag->name; current_tag++) {
+               if (0==strcasecomp(current_tag->name, string->data)) {
+                   break;
+               }
+           }
+           if (!current_tag->name) {
+               if(TRACE) fprintf(stderr, "Unknown tag %s\n",
+                       string->data);
+               state = (c=='>') ? S_text : S_junk_tag;
+               break;
+           }
+           
+           for (a = current_tag->attributes; a->name; a++ ) {
+               a->present = NO;
+           }
+           string->size = 0;
+           current_attribute = (attr *) 0;
+           
+           if (c=='>') {
+               if (current_tag->name) start_element(current_tag);
+               state = S_text;
+           } else {
+               state = S_tag_gap;
+           }
+       }
+       break;
+
+               
+    case S_tag_gap:            /* Expecting attribute or > */
+       if (WHITE(c)) break;    /* Gap between attributes */
+       if (c=='>') {           /* End of tag */
+           if (current_tag->name) start_element(current_tag);
+           state = S_text;
+           break;
+       }
+       HTChunkPutc(string, c);
+       state = S_attr;         /* Get attribute */
+       break;
+       
+                               /* accumulating value */
+    case S_attr:
+       if (WHITE(c) || (c=='>') || (c=='=')) {         /* End of word */
+           HTChunkTerminate(string) ;
+           handle_attribute_name(string->data);
+           string->size = 0;
+           if (c=='>') {               /* End of tag */
+               if (current_tag->name) start_element(current_tag);
+               state = S_text;
+               break;
+           }
+           state = (c=='=' ?  S_equals: S_attr_gap);
+       } else {
+           HTChunkPutc(string, c);
+       }
+       break;
+               
+    case S_attr_gap:           /* Expecting attribute or = or > */
+       if (WHITE(c)) break;    /* Gap after attribute */
+       if (c=='>') {           /* End of tag */
+           if (current_tag->name) start_element(current_tag);
+           state = S_text;
+           break;
+       } else if (c=='=') {
+           state = S_equals;
+           break;
+       }
+       HTChunkPutc(string, c);
+       state = S_attr;         /* Get next attribute */
+       break;
+       
+    case S_equals:                     /* After attr = */ 
+       if (WHITE(c)) break;    /* Before attribute value */
+       if (c=='>') {           /* End of tag */
+           fprintf(stderr, "SGML: found = but no value\n");
+           if (current_tag->name) start_element(current_tag);
+           state = S_text;
+           break;
+           
+       } else if (c=='"') {
+           state = S_quoted;
+           break;
+       }
+       HTChunkPutc(string, c);
+       state = S_value;
+       break;
+       
+    case S_value:
+       if (WHITE(c) || (c=='>')) {             /* End of word */
+           HTChunkTerminate(string) ;
+           handle_attribute_value(string->data);
+           string->size = 0;
+           if (c=='>') {               /* End of tag */
+               if (current_tag->name) start_element(current_tag);
+               state = S_text;
+               break;
+           }
+           else state = S_tag_gap;
+       } else {
+           HTChunkPutc(string, c);
+       }
+       break;
+               
+    case S_quoted:                     /* Quoted attribute value */
+       if (c=='"') {           /* End of attribute value */
+           HTChunkTerminate(string) ;
+           handle_attribute_value(string->data);
+           string->size = 0;
+           state = S_tag_gap;
+       } else {
+           HTChunkPutc(string, c);
+       }
+       break;
+       
+    case S_end:                                        /* </ */
+       if (isalnum(c))
+           HTChunkPutc(string, c);
+       else {                          /* End of end tag name */
+           HTChunkTerminate(string) ;
+           if (c!='>') {
+               if (TRACE) fprintf(stderr,"SGML:  `</%s%c' found!\n",
+                   string->data, c);
+               state = S_junk_tag;
+               break;
+           }
+           for(current_tag = dtd->tags; current_tag->name; current_tag++) {
+               if (0==strcasecomp(current_tag->name, string->data)) {
+                   end_element(current_tag);
+                   break;
+               }
+           }
+           if (!current_tag->name) {
+               if(TRACE) fprintf(stderr,
+                   "Unknown end tag </%s>\n", string->data); 
+           }
+           string->size = 0;
+           current_attribute = (attr *) 0;
+           state = S_text;
+       }
+       break;
+
+               
+    case S_junk_tag:
+       if (c=='>') {
+           state = S_text;
+       }
+       
+    } /* switch on state */
+
+}
diff --git a/Cl/WWWLibrary/SGML.h b/Cl/WWWLibrary/SGML.h
new file mode 100644 (file)
index 0000000..a1bd043
--- /dev/null
@@ -0,0 +1,129 @@
+/*             SGML Parser definitions                         SGML.h
+**             =======================
+**
+**     The SGML parser is a state machine. It is called for every character
+**     of the input stream. The DTD data structure contains pointers
+**     to functions which are called to implement the actual effect of the
+**     text read. When these functions are called, the attribute structures
+**     pointed to by the DTD are valid, and the function is passed
+**     a pointer to the curent tag structure, and an
+**     "element stack" which represents the state of nesting within SGML
+**     elements.
+*/
+/*     (c) Copyright CERN 1991 - See Copyright.html
+*/
+
+#ifndef SGML_H
+#define SGML_H
+
+typedef struct {
+    char *     name;           /* The (constant) name of the attribute */
+    BOOL       present;        /* Was attribute specified for this tag? */
+    char *     value;          /* Malloced. Valid only if present is YES. */
+} attr;
+
+
+/*             A tag structure describes an SGML element.
+**             -----------------------------------------
+**
+**     If the tag has an end tag, then treat and end must be non-zero.
+**     If the tag does not, they must be zero.
+**
+**     name            is the string which comes after the tag opener "<".
+**
+**     attributes      points to a zero-terminated array
+**                     of attribute structures filled in by the parser.
+**
+**     style           is a pointer left for use by oter modules (typically
+**                     for storing the style used with this element)
+**
+**     litteral        determines how the SGML engine parses the charaters
+**                     within the element. If set, tag openers are ignored
+**                     except for that which opens a matching closing tag.
+**
+**     begin           is called when the tag has been parsed, and the
+**                     attribute values set. The element pointer points
+**                     to the top of the new element stack.
+**
+**     treat           is a pointer to a function which is called for
+**                     each text character within the element.
+**
+**     end             is called when the end tag has been parsed.
+**                     The element pointer points to the top of the
+**                     new element stack.
+*/
+typedef struct _tag HTTag;
+typedef struct _HTElement HTElement;
+struct _tag{
+    char * name;               /* The name of the tag */
+    attr * attributes;         /* The list of acceptable attributes */
+    void * style;              /* Not used by the SGML engine */
+    BOOL  litteral;            /* End only on end tag @@ */            
+    void (*begin) PARAMS((HTTag * t, HTElement * e));  /* Action on begin tag */
+    void (*treat) PARAMS((char c));    /* Action when character is parsed */
+    void (*end) PARAMS((HTTag * t, HTElement * e));    /* Action on </tag> or 0 if empty */
+};
+
+/*     Stack of previous tags:
+**
+**     This allows us to return down the stack reselcting styles.
+**     As we return, attribute values will be garbage in general.
+*/
+struct _HTElement {
+       HTElement *     next;   /* Previously nested element or 0 */
+       HTTag   *       tag;    /* The tag at this level */
+       void *          info;   /* Free to be used by caller only */
+};
+
+
+typedef struct _entity {
+    char * name;
+    char * representation;
+} entity;
+
+typedef struct {
+    HTTag *    tags;
+    HTTag *    default_tag;
+    entity *   entities;
+} SGML_dtd;
+
+
+/*     Initialise the SGML parser
+**
+** On entry,
+**     dtd     must point to a DTD structure as defined above
+** On exit,
+**             The default tag starter has been processed.
+*/
+
+extern void  SGML_begin PARAMS((SGML_dtd * dtd));
+
+
+/*     Crank the SGML parser
+**
+** On entry,
+**     dtd     must point to a DTD structure as defined above.
+**             SGML_begin must have been called on it.
+**
+**     c       is the next character of the input stream
+*/
+
+extern void  SGML_character PARAMS((SGML_dtd * dtd, char c));
+
+
+/*     Finish the SGML parser
+**
+** On entry,
+**     dtd     must point to a DTD structure as defined above
+**             SGML_begin must have been called on it.
+** On exit,
+**             The document will be completed.
+**             SGML_begin must be called again before any
+**             more parsing is done.
+*/
+
+extern void  SGML_end PARAMS((SGML_dtd * dtd));
+
+
+
+#endif /* SGML_H */
diff --git a/Cl/WWWLibrary/WWW.h b/Cl/WWWLibrary/WWW.h
new file mode 100644 (file)
index 0000000..246cd83
--- /dev/null
@@ -0,0 +1,20 @@
+/*     Include file for WorldWideWeb project-wide definitions
+*/
+
+/*     Formats:
+*/
+
+#ifndef WWW_H
+#define WWW_H
+
+/*     Bit fields describing the capabilities for a node:
+*/
+#define WWW_READ               1
+#define WWW_WRITE              2
+#define WWW_LINK_TO_NODE       4
+#define WWW_LINK_TO_PART       8
+#define WWW_LINK_FROM_NODE     16
+#define WWW_LINK_FROM_PART     32
+#define WWW_DO_ANYTHING                63
+
+#endif /* WWW_H */
diff --git a/Cl/WWWLibrary/tcp.h b/Cl/WWWLibrary/tcp.h
new file mode 100644 (file)
index 0000000..969e9c8
--- /dev/null
@@ -0,0 +1,326 @@
+/*     System-system differences for TCP include files and macros     tcp.h
+**     ===========================================================
+**
+**
+**     This file includes for each system, the files necessary for
+**     network and file I/O
+**
+** Authors
+**     TBL     Tim Berners-Lee, W3 project, CERN, <timbl@info.cern.ch>
+**     EvA     Eelco van Asperen <evas@cs.few.eur.nl>
+**
+**  History:
+**     22 Feb 91       Written (TBL) as part of the WWW project.
+**     16 Jan 92       PC code from EvA
+*/
+#ifndef TCP_H
+#define TCP_H
+
+#define NETCLOSE close     /* Routine to close a TCP-IP socket         */
+#define NETREAD  read      /* Routine to read from a TCP-IP socket     */
+#define NETWRITE write     /* Routine to write to a TCP-IP socket      */
+
+
+/*     Macintosh - Think-C
+**     -------------------
+**
+**     Think-C is one development environment on the Mac.
+**
+**     We recommend that you compile with 4-byte ints to be compatible
+**     with MPW C.  We used Tom Milligan's s_socket library which was
+**     written for 4 byte int, and the MacTCP library assumes 4-byte int.
+*/
+#ifdef THINK_C
+#define DEBUG                  /* Can't put it on the CC command line  */
+#define NO_UNIX_IO             /* getuid() missing                     */
+#define NO_GETPID              /* getpid() does not exist              */
+#define NO_GETWD               /* getwd() does not exist               */
+
+#undef NETCLOSE                    /* Routine to close a TCP-IP socket         */
+#undef NETREAD             /* Routine to read from a TCP-IP socket     */
+#undef NETWRITE            /* Routine to write to a TCP-IP socket      */
+#define NETCLOSE s_close    /* Routine to close a TCP-IP socket                */
+#define NETREAD  s_read            /* Routine to read from a TCP-IP socket     */
+#define NETWRITE s_write    /* Routine to write to a TCP-IP socket     */
+
+#define bind s_bind        /* Funny names presumably to prevent clashes */
+#define connect s_connect
+#define accept s_accept
+#define listen s_listen
+#define socket s_socket
+#define getsockname s_getsockname
+
+/* The function prototype checking is better than the include files
+*/
+
+extern s_close(int s);
+extern s_read(int s, char *buffer, int buflen);
+extern s_write(int s, const char *buffer, int buflen);
+
+extern bind(int s, struct sockaddr *name, int namelen);
+extern accept(int s, struct sockaddr *addr, int *addrlen);
+extern listen(int s, int qlen);
+extern connect(int s, struct sockaddr *addr, int addrlen);
+
+extern s_socket(int domain, int type, int protocol);
+extern s_getsockname(int s, struct sockaddr *name, int *namelen);
+extern struct hostent *gethostent(const char * name);
+extern unsigned long inet_addr(const char * name);
+
+#endif
+
+
+/*     On the NeXT, there's a little package of include files.
+*/
+#ifdef NeXT
+#include <libc.h>              /* NeXT has all this packaged up */
+#define ntohs(x) (x)
+#define htons(x) (x)
+#include <sys/errno.h>         /* Get ECONNRESET etc */
+#define SELECT                 /* Is supported ok */
+#define INCLUDES_DONE
+
+#else                          /* Not NeXT */
+#ifndef STDIO_H
+#include <stdio.h>
+#define STDIO_H
+#endif
+
+
+/*     On the IBM RS-6000, AIX is almost Unix.
+**     But AIX must be defined in the makefile.
+*/
+#ifdef AIX
+#define unix
+#endif
+
+/*     MVS is compiled as for VM. MVS has no unix-style I/O
+**     The command line compile options seem to come across in
+**     lower case.
+**
+**     See aslo lots of VM stuff lower down.
+*/
+#ifdef mvs
+#define MVS
+#endif
+
+#ifdef MVS
+#define VM
+#endif
+
+#ifdef NEWLIB
+#pragma linkage(newlib,OS)     /* Enables recursive NEWLIB */
+#endif
+
+/*     VM doesn't have a built-in predefined token, so we cheat: */
+#ifdef __STDIO__
+#define VM
+#else
+#include <string.h>            /* For bzero etc - not NeXT or VM */
+#endif
+#define SELECT                 /* Handle >1 channel if we can.         */
+#endif                         /* Not NeXT */
+
+
+/*     Under VMS, there are many versions of TCP-IP. Define one if you
+**     do not use Digital's UCX product:
+**
+**             UCX             DEC's "Ultrix connection" (default)
+**             WIN_TCP         From Wollongong, now GEC software.
+**             MULTINET        From SRI, now from TGV Inv.
+**
+**     The second two do not interfere with the unix i/o library, and so they
+**     need special calls to read, write and close sockets. In these cases the
+**     socket number is a VMS channel number, so we make the HORRIBLE
+**     assumption that a channel number will be greater than 10 but a
+**     unix file descriptor less than 10.
+*/
+#ifdef vms
+#ifdef WIN_TCP
+#undef NETREAD
+#undef NETWRITE
+#undef NETCLOSE
+#define NETREAD(s,b,l) ((s)>10 ? netread((s),(b),(l)) : read((s),(b),(l)))
+#define NETWRITE(s,b,l)        ((s)>10 ? netwrite((s),(b),(l)) : write((s),(b),(l)))
+#define NETCLOSE(s)    ((s)>10 ? netclose(s) : close(s))
+#endif
+
+#ifdef MULTINET
+#undef NETCLOSE
+#undef NETREAD
+#undef NETWRITE
+#define NETREAD(s,b,l) ((s)>10 ? socket_read((s),(b),(l)) : read((s),(b),(l)))
+#define NETWRITE(s,b,l)        ((s)>10 ? socket_write((s),(b),(l)) : \
+                               write((s),(b),(l)))
+#define NETCLOSE(s)    ((s)>10 ? socket_close(s) : close(s))
+#endif
+
+/*     Certainly this works for UCX and Multinet; not tried for Wollongong
+*/
+#ifdef MULTINET
+#include "multinet_root:[multinet.include.sys]types.h"
+#include "multinet_root:[multinet.include]errno.h"
+#include "multinet_root:[multinet.include.sys]time.h"
+#else
+#include types
+#include errno
+#include time
+#endif
+#include string
+#ifndef STDIO_H
+#include stdio
+#define STDIO_H
+#endif
+
+#include file
+#include unixio
+
+#define INCLUDES_DONE
+
+#ifdef MULTINET  /* Include from standard Multinet directories */
+#include "multinet_root:[multinet.include.sys]socket.h"
+#ifdef __TIME_LOADED  /* defined by sys$library:time.h */
+#define __TIME  /* to avoid double definitions in next file */
+#endif
+#include "multinet_root:[multinet.include.netinet]in.h"
+#include "multinet_root:[multinet.include.arpa]inet.h"
+#include "multinet_root:[multinet.include]netdb.h"
+#else
+#include socket
+#include in
+#include inet
+#include netdb
+#endif
+#define TCP_INCLUDES_DONE
+
+#endif /* vms */
+
+
+/*     IBM VM/CMS or MVS
+**     -----------------
+**
+**     Note:   All files must have lines <= 80 characters
+**             All include file names must have 8 chars max (+".h")
+**
+**     Under VM, compile with "DEF=VM"
+**
+**     Under MVS, compile with "NOMAR DEF(MVS)" to get rid of 72 char margin
+**       System include files TCPIP and COMMMAC neeed line number removal(!)
+*/
+
+#ifdef VM                      /* or MVS -- see above. */
+#define NOT_ASCII              /* char type is not ASCII */
+#define NO_UNIX_IO             /* Unix I/O routines are not supported */
+#define NO_GETPID              /* getpid() does not exist */
+#define NO_GETWD               /* getwd() does not exist */
+#ifndef SHORT_NAMES
+#define SHORT_NAMES            /* 8 character uniqueness for globals */
+#endif
+#include <manifest.h>                                                           
+#include <bsdtypes.h>                                                           
+#include <stdefs.h>                                                             
+#include <socket.h>                                                             
+#include <in.h>
+#include <inet.h>
+#include <netdb.h>                                                                 
+#include <errno.h>         /* independent */
+extern char asciitoebcdic[], ebcdictoascii[];
+#define TOASCII(c)   (c=='\n' ?  10  : ebcdictoascii[c])
+#define FROMASCII(c) (c== 10  ? '\n' : asciitoebcdic[c])                                   
+#include <bsdtime.h>
+#include <time.h>
+#include <string.h>                                                            
+#define INCLUDES_DONE
+#define TCP_INCLUDES_DONE
+#endif
+
+
+/*     IBM-PC running MS-DOS with SunNFS for TCP/IP
+**     ---------------------
+**
+**     This code thanks to Eelco van Asperen <evas@cs.few.eur.nl>
+*/
+
+#ifdef PCNFS
+#include <sys/types.h>
+#include <string.h>
+#ifndef STDIO_H
+#include <stdio.h>
+#define STDIO_H
+#endif
+
+#include <errno.h>         /* independent */
+#include <sys/time.h>      /* independent */
+#include <sys/stat.h>
+#include <fcntl.h>         /* In place of sys/param and sys/file */
+#define INCLUDES_DONE
+
+#define FD_SET(fd,pmask) (*(unsigned*)(pmask)) |=  (1<<(fd))
+#define FD_CLR(fd,pmask) (*(unsigned*)(pmask)) &= ~(1<<(fd))
+#define FD_ZERO(pmask)   (*(unsigned*)(pmask))=0
+#define FD_ISSET(fd,pmask) (*(unsigned*)(pmask) & (1<<(fd)))
+#endif
+
+
+/*     Regular BSD unix versions:      (default)
+**     -------------------------
+*/
+
+#ifndef INCLUDES_DONE
+#include <sys/types.h>
+/* #include <streams/streams.h>                        not ultrix */
+#include <string.h>
+#ifndef STDIO_H
+#include <stdio.h>
+#define STDIO_H
+#endif
+
+#include <errno.h>         /* independent */
+#include <sys/time.h>      /* independent */
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <sys/file.h>      /* For open() etc */
+#define INCLUDES_DONE
+#endif /* Normal includes */
+
+
+/*     Default include files for TCP
+*/
+#ifndef TCP_INCLUDES_DONE
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>     /* Must be after netinet/in.h */
+#include <netdb.h>
+#endif /* TCP includes */
+
+
+/*     Default macros for manipulating masks for select()
+*/
+#ifndef FD_SET
+typedef unsigned int fd_set;
+#define FD_SET(fd,pmask) (*(pmask)) |=  (1<<(fd))
+#define FD_CLR(fd,pmask) (*(pmask)) &= ~(1<<(fd))
+#define FD_ZERO(pmask)   (*(pmask))=0
+#define FD_ISSET(fd,pmask) (*(pmask) & (1<<(fd)))
+#endif
+
+
+/*     Default macros for converting characters
+**
+*/
+#ifndef TOASCII
+#define TOASCII(c) (c)
+#define FROMASCII(c) (c)                                   
+#endif
+
+#ifndef TOLOWER
+#ifdef pyr                     /* Pyramid can't uppercase non-alpha */
+#define TOLOWER(c) (isupper(c) ? tolower(c) : (c))
+#define TOUPPER(c) (islower(c) ? toupper(c) : (c))
+#else
+#define TOLOWER(c) tolower(c)
+#define TOUPPER(c) toupper(c)
+#endif /* pyr */
+#endif /* ndef TOUPPER */
+
+#endif /* TCP_H */
diff --git a/HText/DefaultStyles.c b/HText/DefaultStyles.c
new file mode 100644 (file)
index 0000000..5a251f6
--- /dev/null
@@ -0,0 +1,132 @@
+/*     A real style sheet for the Character Grid browser
+**
+**     The dimensions are all in characters!
+*/
+
+#include "HTStyle.h"
+
+/* Template:
+**     link to next, name, tag, tagtype,
+**     font, size, colour,             superscript, anchor id,
+**     indents: 1st, left, right,      lineheight, descent,    tabs,
+**     word wrap, free format, space: before, after, flags.
+*/
+
+PRIVATE HTStyle HTStyleNormal =
+{0, "Normal", "P",
+ HT_FONT, 1.0, HT_BLACK, 0, 0,
+ 3, 3, 0, HT_LEFT, 1, 0, 0,
+ YES, YES, 1, 1, 0};
+
+PRIVATE HTStyle HTStyleList =
+{&HTStyleNormal, "List", "UL",
+ HT_FONT, 1.0, HT_BLACK, 0, 0,
+ 7, 10, 0, HT_LEFT, 1, 0, 0,
+ YES, YES, 1, 1, 0};
+
+PRIVATE HTStyle HTStyleListCompact =
+{
+  &HTStyleList, "ListCompact", "ULC",
+  HT_FONT, 1.0, HT_BLACK, 0, 0,
+  1, 4, 0, HT_LEFT, 1, 0, 0,
+  YES, YES, 0, 0, 0
+};
+PRIVATE HTTabStop tabs_16[] =
+{
+  {0, 16},
+  {0, 32},
+  {0, 48},
+  {0, 64},
+  {0, 80},
+  {0, 96},
+  {0, 112}
+};
+
+PRIVATE HTStyle HTStyleColumns16 =
+{
+  &HTStyleListCompact, "Columns16", "ULC",
+  HT_FONT, 1.0, HT_BLACK, 0, 0,
+  1, 4, 0, HT_LEFT, 1, 0, tabs_16,
+  YES, YES, 0, 0, 0
+};
+
+PRIVATE HTStyle HTStyleGlossary =
+{
+  &HTStyleColumns16, "Glossary", "DL",
+  HT_FONT, 1.0, HT_BLACK, 0, 0,
+  2, 25, 0, HT_LEFT, 1, 0, 0,
+  YES, YES, 1, 1, 0
+};
+PRIVATE HTStyle HTStyleGlossaryCompact =
+{
+  &HTStyleGlossary, "GlossaryCompact", "DLC",
+  HT_FONT, 1.0, HT_BLACK, 0, 0,
+  0, 24, 0, HT_LEFT, 1, 0, 0,
+  YES, YES, 0, 0, 0
+};
+PRIVATE HTStyle HTStyleExample =
+{&HTStyleGlossaryCompact, "Example", "XMP",
+ HT_FONT, 1.0, HT_BLACK, 0, 0,
+ 0, 0, 0, HT_LEFT, 1, 0, 0,
+ NO, NO, 1, 1, 0};
+
+PRIVATE HTStyle HTStyleListing =
+{&HTStyleExample, "Listing", "LISTING",
+ HT_FONT, 1.0, HT_BLACK, 0, 0,
+ 0, 0, 0, HT_LEFT, 1, 0, 0,
+ NO, NO, 1, 1, 0};
+
+PRIVATE HTStyle HTStyleAddress =
+{&HTStyleListing, "Address", "ADDRESS",
+ HT_FONT, 1.0, HT_BLACK, 0, 0,
+ 0, 0, 0, HT_RIGHT, 1, 0, 0,
+ NO, NO, 1, 1, 0};
+
+PRIVATE HTStyle HTStyleHeading1 =
+{&HTStyleAddress, "Heading1", "H1",
+ HT_FONT + HT_CAPITALS + HT_BOLD, 1.0, HT_BLACK, 0, 0,
+ 0, 0, 0, HT_CENTER, 1, 0, 0,
+ YES, YES, 1, 1, 0};
+
+PRIVATE HTStyle HTStyleHeading2 =
+{&HTStyleHeading1, "Heading2", "H2",
+ HT_FONT + HT_BOLD, 1.0, HT_BLACK, 0, 0,
+ 0, 0, 0, HT_LEFT, 1, 0, 0,
+ YES, YES, 1, 1, 0};
+
+PRIVATE HTStyle HTStyleHeading3 =
+{&HTStyleHeading2, "Heading3", "H3",
+ HT_FONT + HT_CAPITALS, 1.0, HT_BLACK, 0, 0,
+ 2, 2, 0, HT_LEFT, 1, 0, 0,
+ YES, YES, 1, 0, 0};
+
+PRIVATE HTStyle HTStyleHeading4 =
+{&HTStyleHeading3, "Heading4", "H4",
+ HT_FONT, 1.0, HT_BLACK, 0, 0,
+ 4, 4, 0, HT_LEFT, 1, 0, 0,
+ YES, YES, 1, 0, 0};
+
+PRIVATE HTStyle HTStyleHeading5 =
+{&HTStyleHeading4, "Heading5", "H5",
+ HT_FONT, 1.0, HT_BLACK, 0, 0,
+ 6, 6, 0, HT_LEFT, 1, 0, 0,
+ YES, YES, 1, 0, 0};
+
+PRIVATE HTStyle HTStyleHeading6 =
+{&HTStyleHeading5, "Heading6", "H6",
+ HT_FONT, 1.0, HT_BLACK, 0, 0,
+ 8, 8, 0, HT_LEFT, 1, 0, 0,
+ YES, YES, 1, 0, 0};
+
+PRIVATE HTStyle HTStyleHeading7 =
+{&HTStyleHeading6, "Heading7", "H7",
+ HT_FONT, 1.0, HT_BLACK, 0, 0,
+ 10, 10, 0, HT_LEFT, 1, 0, 0,
+ YES, YES, 1, 0, 0};
+
+/* Style sheet points to the last in the list:
+*/
+PRIVATE HTStyleSheet sheet =
+{"default.style", &HTStyleHeading7};   /* sheet */
+
+PUBLIC HTStyleSheet *styleSheet = &sheet;
diff --git a/HText/HText.c b/HText/HText.c
new file mode 100644 (file)
index 0000000..c9f4a5a
--- /dev/null
@@ -0,0 +1,797 @@
+/*
+ * HText.c --
+ *
+ * Author: Teemu Rantanen <tvr@cs.hut.fi>
+ * Copyright (c) 1992 Teemu Rantanen
+ *                    All rights reserved
+ *
+ * Created: Wed Feb 26 15:59:04 1992 tvr
+ * Last modified: Mon Apr 27 00:41:22 1992 tvr
+ *
+ */
+
+#include <stdio.h>
+
+#include "HTStyle.h"
+#include "HText.h"
+
+
+/*
+ * This file interacts with WWWLibrary and builds one hypertext page.
+ * For every hypertext object on this page will be set
+ *  - data, length
+ *  - anchor information
+ *  - style
+ * Empty object will be generated for paragraph endings, newlines and
+ * tabulators.
+ */
+
+
+/*
+ * Debug module (temporary)
+ */
+
+#define HT_DEBUG(a)            /*printf a*/
+
+
+/*
+ * Local prototype
+ */
+
+void new_htext_object ();
+void make_paragraph_object ();
+void HText_setStyle ();
+
+
+/*
+ * Local text (temporary)
+ */
+
+struct HText *HtLocalText;
+
+
+/*
+ * When constructing data, save it first here. Then malloc needed space
+ * and copy it
+ */
+
+char localdata[HTEXT_MAX_OBJECT_SIZE];
+
+
+/*
+ * Set same anchor information to all objects belonging to same
+ * anchor.
+ */
+
+HTChildAnchor *local_anchor = 0;
+
+/*
+ * Default style
+ */
+extern HTStyleSheet *styleSheet;
+
+
+/*
+ * This file has functions that WWWLibrary uses to construct an hypertext
+ * object.
+ */
+
+/*                      Creation Method
+**                      ---------------
+*/
+struct HText *
+HText_new (anchor)
+     HTParentAnchor *anchor;
+{
+  struct HText *self;
+
+  /*
+   * Create hypertext object.
+   */
+
+  self = (struct HText *) malloc (sizeof (struct HText));
+
+  if (!self)
+    return self;
+
+  HTAnchor_setDocument (anchor, (HyperDoc *) self);
+
+  /*
+   * Initialize object.
+   */
+
+  memset (self, 0, sizeof (struct HText));
+
+  /*
+   * Set some WWWLibrary stuff ...
+   */
+  self->node_anchor = anchor;
+
+  /*
+   * Setup hashing code
+   */
+
+  HtLocalText = self;
+
+  return self;
+}
+
+
+/*      Free Entire Text
+**      ----------------
+*/
+void 
+HText_free (self)
+     struct HText *self;
+{
+  struct HTextObject *p, *p2;
+  struct HTextAnchor *a, *a2;
+
+  if (!self)
+    return;
+
+  p = self->first;
+
+  /*
+   * Set some WWWLibrary stuff ...
+   */
+  if (self->node_anchor)
+    HTAnchor_setDocument (self->node_anchor, (HyperDoc *) 0);
+
+
+  /*
+   * Free all data allocated on this file.
+   */
+  while (p)
+    {
+      p2 = p;
+      p = p->next;
+
+      /*
+       * Avoid loop if something goes wrong
+       */
+      p2->next = p2->prev = NULL;
+
+      if (p2->data)
+       free (p2->data);
+
+      free (p2);
+
+    }
+
+  a = self->anchorlist;
+
+  while (a)
+    {
+      a2 = a;
+      a = a->next;
+
+      free (a2);
+    }
+
+  free (self);
+}
+
+/*
+ * Get default style
+ */
+HTStyle *
+ht_get_default_style ()
+{
+  HTStyle *p = styleSheet->styles;
+
+  while (p && p->next)
+    {
+      if (!strcmp (p->SGMLTag, "XMP"))
+       return p;
+      p = p->next;
+    }
+
+  /*
+   * Return last if xmp not found
+   */
+  return p;
+}
+
+
+
+/*                      Object Building methods
+**                      -----------------------
+**
+**      These are used by a parser to build the text in an object
+*/
+void 
+HText_beginAppend (text)
+     struct HText *text;
+{
+  /*
+   * Set object to accept text
+   */
+
+  new_htext_object (text);
+
+  if (!text->first)
+    {
+      HT_DEBUG ((stderr, "htext begin append failed?\n"));
+    }
+
+  /*
+   * Set default style. Some pages cause no setStyle.
+   */
+  HText_setStyle (text, ht_get_default_style ());
+}
+
+
+/*      New paragraph in current style
+**      ------------------------------
+** See also: setStyle.
+*/
+
+void 
+HText_appendParagraph (text)
+     struct HText *text;
+{
+  HT_DEBUG (("\nHText_appendParagraph\n"));
+
+  /*
+   * Create paragraph object
+   */
+
+  make_paragraph_object (text, HTEXT_PARAGRAPH);
+}
+
+
+
+
+/*      Append a character to the text object
+**      -------------------------------------
+*/
+void 
+HText_appendCharacter (text, ch)
+     struct HText *text;
+     char ch;
+{
+  struct HTextObject *p;
+  int l;
+  static char lastchar = 0;
+
+  HT_DEBUG (("%c", ch));
+
+  /*
+   * safety
+   */
+
+  if (!text)
+    return;
+
+  /*
+   * Parse special characters
+   */
+  if (ch == '\n')
+    {
+
+      make_paragraph_object (text, HTEXT_NEWLINE);
+
+      return;
+
+    }
+
+  if (ch == '\t')
+    {
+
+      make_paragraph_object (text, HTEXT_TAB);
+
+      return;
+
+    }
+
+  /*
+   * Append space(s) at the end of objects
+   */
+  if (lastchar == ' ' && ch != ' ')
+    {
+
+      new_htext_object (text);
+
+      /*
+       * Don't loose this character
+       */
+      lastchar = ch;
+
+      HText_appendCharacter (text, ch);
+
+      return;
+    }
+
+  lastchar = ch;
+
+  p = text->last;
+
+  /*
+   * If local buffer is full, make continued hypertext object.
+   * This should not happen (is extreamely rare).
+   */
+
+  if (p->length >= HTEXT_MAX_OBJECT_SIZE)
+    {
+
+      p->paragraph = HTEXT_CONTINUE;
+
+      new_htext_object (text);
+
+      HText_appendCharacter (p, ch);
+
+      /* return */
+
+    }
+  else
+    {
+
+      localdata[p->length++] = ch;
+    }
+}
+
+
+HTextAnchor_t *
+htext_new_anchor ()
+{
+  HTextAnchor_t *p;
+
+  p = (HTextAnchor_t *) malloc (sizeof (HTextAnchor_t));
+
+  if (!p)
+    {
+      HT_DEBUG (("cannot malloc on htext_new_anchor(). tough.\n"));
+
+      exit (-1);
+    }
+
+  memset (p, 0, sizeof (HTextAnchor_t));
+
+  return p;
+}
+
+
+/*              Anchor handling
+**              ---------------
+*/
+/*      Start an anchor field
+*/
+void 
+HText_beginAnchor (text, anc)
+     struct HText *text;
+     HTChildAnchor *anc;
+{
+  HT_DEBUG (("\nHText_beginAnchor [%s]\n", anc->tag));
+
+  /*
+   * Set up anchor
+   */
+
+  if (!anc)
+    return;
+
+  if (HTAnchor_followMainLink ((HTAnchor *) anc))
+    {
+      /*
+       * Anchor is to be shown on the screen
+       */
+      new_htext_object (text);
+
+      local_anchor = anc;
+    }
+  /*
+   * Anchor is HREF anchor only
+   */
+  if (!text->anchorlist)
+    {
+
+      text->anchorlist = htext_new_anchor ();
+
+      text->anchorlist->object = text->last;
+
+      text->anchorlist->anchor = anc;
+
+    }
+  else
+    {
+
+      HTextAnchor_t *p = text->anchorlist;
+
+      for (; p->next; p = p->next) ;
+
+      p->next = htext_new_anchor ();
+
+      p->next->anchor = anc;
+
+      p->next->object = text->last;
+    }
+}
+
+
+
+/*
+ * End anchor creation
+ */
+
+void 
+HText_endAnchor (text)
+     struct HText *text;
+{
+  HT_DEBUG (("\nHText_endAnchor\n"));
+
+  /*
+   * Create this anchor an object and create new
+   */
+
+  new_htext_object (text);
+
+  local_anchor = NULL;
+
+}
+
+
+
+void 
+HText_appendText (text, str)
+     struct HText *text;
+     char *str;
+{
+  register char *p;
+
+  HT_DEBUG (("HText_appendText by characters\n"));
+
+  /*
+   * Append characters (or better, words)
+   */
+
+  for (p = str; *p; p++)
+    HText_appendCharacter (text, *p);
+
+}
+
+/*
+ * End text appending
+ */
+
+void 
+HText_endAppend (text)
+     struct HText *text;
+{
+  HT_DEBUG (("HText_endAppend"));
+
+  new_htext_object (text);
+}
+
+
+void 
+HText_setStyle (text, style)
+     struct HText *text;
+     HTStyle *style;
+{
+  HT_DEBUG (("HText_setStyle %s\n", style->name));
+
+  if (!style)
+    {
+      HT_DEBUG (("HText bug on HText_setStyle ... not changing style\n"));
+      return;
+    }
+
+  /*
+   * Begin style
+   */
+  new_htext_object (text);
+
+  /*
+   * If many headers in a row, append paragraph
+   */
+  if (text->last->style == style)
+    {
+      HText_appendParagraph (text);
+    }
+
+  text->last->style = style;
+}
+
+
+
+BOOL 
+HText_select (text)
+     struct HText *text;
+{
+  HT_DEBUG (("\nHText_select ??????\n"));
+  /*
+   * Do what ???
+   */
+
+  HtLocalText = text;
+}
+
+
+
+BOOL 
+HText_selectAnchor (text, anchor)
+     struct HText *text;
+     struct HTChildAnchor *anchor;
+{
+  HT_DEBUG (("\nHText_selectAnchor\n"));
+
+  /*
+   * Something stupid ?
+   */
+}
+
+
+
+/*
+ * Allocate new object. Set up modes from previous. Set up data -area.
+ */
+
+struct HTextObject *
+malloc_ht_object (prev)
+     struct HTextObject *prev;
+{
+  struct HTextObject *p;
+
+  /*
+   * New object
+   */
+
+  p = (struct HTextObject *) malloc (sizeof (struct HTextObject));
+
+  if (!p)
+    {
+      HT_DEBUG (("cannot malloc hypertextobject\n"));
+      exit (-1);
+    }
+
+  if (prev)
+    {
+
+      memcpy (p, prev, sizeof (struct HTextObject));
+
+      p->data = 0;
+
+      p->length = 0;
+
+      p->anchor = 0;
+
+      p->paragraph = 0;
+
+    }
+  else
+    {
+
+      memset (p, 0, sizeof (struct HTextObject));
+
+    }
+
+
+  return p;
+}
+
+
+
+
+/*
+ * Create new hypertext object.
+ */
+
+void 
+new_htext_object (text)
+     struct HText *text;
+{
+  struct HTextObject *p;
+
+  /*
+   * First object ?
+   */
+  if (text->first == 0)
+    {
+      text->first = text->last = malloc_ht_object (NULL);
+
+      return;
+    }
+
+  /*
+   * Temporary assignment
+   */
+
+  p = text->last;
+
+  /*
+   * Strip all null objects exept paragraph marks
+   */
+  if ((p->length == 0) && !(p->paragraph))
+    return;
+
+  /*
+   * Check paragraph objects
+   */
+  if (p->paragraph && (p->paragraph != HTEXT_CONTINUE) && p->length)
+    {
+      HT_DEBUG (("non null paragraph object ?\n"));
+      exit (-1);
+    }
+
+  /*
+   * If constructing object, malloc and copy local data
+   */
+
+  if (p->length)
+    {
+
+      p->data = (char *) malloc (p->length + 1);
+
+      if (!p->data)
+       {
+         HT_DEBUG (("cannot malloc data on new_htext_object()\n"));
+         exit (-1);
+       }
+
+      memcpy (p->data, localdata, p->length);
+
+      p->data[p->length] = 0;
+    }
+
+  /*
+   * Set anchorinformation to object
+   */
+
+  p->anchor = local_anchor;
+
+  /*
+   * Create new object
+   */
+
+  p = malloc_ht_object (text->last);
+
+  /*
+   * Set it last
+   */
+
+  p->prev = text->last;
+
+  text->last->next = p;
+
+  text->last = p;
+}
+
+
+
+/*
+ * Make empty object only stating paragraph, tab or newline
+ */
+
+void 
+make_paragraph_object (text, type)
+     struct HText *text;
+     int type;
+{
+  new_htext_object (text);
+
+  text->last->paragraph = type;
+
+  new_htext_object (text);
+
+}
+
+
+/*
+ * Malloc and copy data
+ */
+char *
+ht_memdup (data, len)
+     char *data;
+     int len;
+{
+  char *p;
+
+  p = (char *) malloc (len);
+
+  if (!p)
+    return 0;
+
+  memcpy (p, data, len);
+
+  return p;
+}
+
+
+/*
+ * Duplicate object information of this hypertext-page
+ */
+
+HText_t *
+HtDuplicate (text)
+     HText_t *text;
+{
+  HText_t *newtext;
+  HTextObject_t *o, *p;
+  HTextObject_t *p_old = 0;
+
+  newtext = (HText_t *) malloc (sizeof (*newtext));
+
+  if (!newtext)
+    return 0;
+
+  memset (newtext, 0, sizeof (*newtext));
+
+  o = text->first;
+
+  /*
+   * Allocate new htext -page info
+   */
+  if (o)
+    {
+      p = newtext->first = (HTextObject_t *) malloc (sizeof (*p));
+
+      if (!p)
+       {
+
+         free (newtext);
+
+         return 0;
+       }
+    }
+
+  while (o)
+    {
+      memset (p, 0, sizeof (*p));
+
+      p->paragraph = o->paragraph;
+
+      p->length = o->length;
+
+      p->style = o->style;
+
+      p->data = (char *) ht_memdup (o->data, o->length);
+
+      if (!p->data)
+       {
+
+         goto free_allocated_error;
+       }
+
+      p->prev = p_old;
+
+      if (o->next)
+       {
+
+         p_old = p;
+
+         p = (HTextObject_t *) malloc (sizeof (*p));
+
+         if (!p)
+           {
+
+             goto free_allocated_error;
+           }
+
+         p_old->next = p;
+       }
+
+      o = o->next;
+    }
+
+  newtext->last = p;
+
+  return newtext;
+
+free_allocated_error:
+
+  o = newtext->first;
+
+  while (o)
+    {
+
+      if (o->data)
+       free (o->data);
+
+      free (o);
+    }
+
+  free (newtext);
+
+  return 0;
+}
diff --git a/HText/HText.h b/HText/HText.h
new file mode 100644 (file)
index 0000000..a96082b
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * HText.h --
+ *
+ * Author: Teemu Rantanen <tvr@cs.hut.fi>
+ * Copyright (c) 1992 Teemu Rantanen
+ *                    All rights reserved
+ *
+ * Created: Wed Feb 26 15:57:03 1992 tvr
+ * Last modified: Mon Apr 27 23:55:47 1992 tvr
+ *
+ */
+
+
+/*
+ * Maximum Htext object data size
+ */
+
+#define HTEXT_MAX_OBJECT_SIZE  1024
+
+/*
+ * Region changes on hypertext
+ */
+#define HTEXT_PARAGRAPH                1
+#define        HTEXT_TAB               2
+#define        HTEXT_NEWLINE           3
+#define        HTEXT_CONTINUE          4
+
+
+/*
+ * Hypertext object structure.
+ */
+
+typedef struct HTextObject
+{
+  /*
+   * Pointers to next and previous objects
+   */
+
+  struct HTextObject *prev;
+  struct HTextObject *next;
+
+  /*
+   * All Hypertext specific fields here
+   */
+
+  /*
+   * If object is an anchor, have anchordata here
+   */
+  HTChildAnchor *anchor;
+
+  /*
+   * Style of this object.
+   */
+  HTStyle *style;
+
+  /*
+   * what data on this object
+   */
+  char *data;
+
+  /*
+   * How many bytes data
+   */
+  int length;
+
+  /*
+   * Marks paragraph change at the end of this object
+   */
+  int paragraph;
+
+  /*
+   * All Xl specific data here
+   */
+
+  /*
+   * Position of an object on a virtual screen. These will be set when
+   * object is being positioned.
+   */
+  long x;
+  long y;
+
+  /*
+   * Size of an object. These are calculated once (as these does
+   * not change).
+   */
+  long width;
+  long height;
+
+  /*
+   * Xl specific data of this object
+   */
+  struct XlObjectData *xl_data;
+} HTextObject_t;
+
+
+/*
+ * Hypertext structure of a page
+ */
+
+typedef struct HText
+{
+  /*
+   * First and last hypertext objects
+   */
+
+  struct HTextObject *first;
+  struct HTextObject *last;
+
+  /*
+   * Node anchor of this page
+   */
+  HTParentAnchor *node_anchor;
+
+  /*
+   * Xl specific global data for a page
+   */
+  struct XlGlobalData *xl_global;
+
+  /*
+   * HREF pointer list
+   */
+  struct HTextAnchor *anchorlist;
+
+  /*
+   * Cursor object of this page
+   */
+  struct HTextObject *cursor;
+
+} HText_t;
+
+
+/*
+ * HREF pointer list on a page
+ */
+typedef struct HTextAnchor
+{
+  /*
+   * Pointer to next
+   */
+  struct HTextAnchor *next;
+
+  /*
+   * Anchor data
+   */
+  HTChildAnchor *anchor;
+
+  /*
+   * To which hypertextobject is this connected to
+   */
+  struct HTextObject *object;
+} HTextAnchor_t;
+
+
+
+/*
+ * Prototype
+ */
+
+HText_t *HtDuplicate (HText_t * text);
diff --git a/HText/Imakefile b/HText/Imakefile
new file mode 100644 (file)
index 0000000..8622d9a
--- /dev/null
@@ -0,0 +1,12 @@
+#
+#
+#
+
+          OBJS = DefaultStyles.o HText.o dummy.o
+          SRCS = DefaultStyles.c HText.c dummy.c
+
+       DEFINES = -I../Cl/WWWLibrary
+
+NormalLibraryTarget(Ht, $(OBJS))
+
+DependTarget()
diff --git a/HText/Makefile b/HText/Makefile
new file mode 100644 (file)
index 0000000..d480967
--- /dev/null
@@ -0,0 +1,334 @@
+# Makefile generated by imake - do not edit!
+# $XConsortium: imake.c,v 1.65 91/07/25 17:50:17 rws Exp $
+#
+# The cpp used on this machine replaces all newlines and multiple tabs and
+# spaces in a macro expansion with a single space.  Imake tries to compensate
+# for this, but is not always successful.
+#
+
+# -------------------------------------------------------------------------
+# Makefile generated from "Imake.tmpl" and </tmp/IIf.a10867>
+# $XConsortium: Imake.tmpl,v 1.139 91/09/16 08:52:48 rws Exp $
+#
+# Platform-specific parameters may be set in the appropriate <vendor>.cf
+# configuration files.  Site-specific parameters should be set in the file
+# site.def.  Full rebuilds are recommended if any parameters are changed.
+#
+# If your C preprocessor does not define any unique symbols, you will need
+# to set BOOTSTRAPCFLAGS when rebuilding imake (usually when doing
+# "make World" the first time).
+#
+
+# -------------------------------------------------------------------------
+# site-specific configuration parameters that need to come before
+# the platform-specific parameters - edit site.def to change
+
+# site:  $XConsortium: site.def,v 1.2 91/07/30 20:26:44 rws Exp $
+
+# -------------------------------------------------------------------------
+# platform-specific configuration parameters - edit sun.cf to change
+
+# platform:  $XConsortium: sun.cf,v 1.72.1.1 92/03/18 13:13:37 rws Exp $
+
+# operating system:  SunOS 4.1.2
+
+# $XConsortium: sunLib.rules,v 1.7 91/12/20 11:19:47 rws Exp $
+
+.c.o:
+       $(CC) -c $(CFLAGS) $*.c
+
+# -------------------------------------------------------------------------
+# site-specific configuration parameters that go after
+# the platform-specific parameters - edit site.def to change
+
+# site:  $XConsortium: site.def,v 1.2 91/07/30 20:26:44 rws Exp $
+
+            SHELL = /bin/sh
+
+              TOP = ../.
+      CURRENT_DIR = ./HText
+
+               AR = ar clq
+  BOOTSTRAPCFLAGS =
+               CC = gcc2 -pipe -fstrength-reduce -fpcc-struct-return
+               AS = as
+
+         COMPRESS = compress
+              CPP = /lib/cpp $(STD_CPP_DEFINES)
+    PREPROCESSCMD = gcc2 -pipe -fstrength-reduce -fpcc-struct-return -E $(STD_CPP_DEFINES)
+          INSTALL = install
+               LD = ld
+             LINT = lint
+      LINTLIBFLAG = -C
+         LINTOPTS = -axz
+               LN = ln -s
+             MAKE = make
+               MV = mv
+               CP = cp
+
+           RANLIB = ranlib
+  RANLIBINSTFLAGS =
+
+               RM = rm -f
+            TROFF = psroff
+         MSMACROS = -ms
+              TBL = tbl
+              EQN = eqn
+     STD_INCLUDES =
+  STD_CPP_DEFINES =
+      STD_DEFINES =
+ EXTRA_LOAD_FLAGS = -B/usr/bin/
+  EXTRA_LIBRARIES =
+             TAGS = ctags
+
+    SHAREDCODEDEF = -DSHAREDCODE
+         SHLIBDEF = -DSUNSHLIB
+
+    PROTO_DEFINES =
+
+     INSTPGMFLAGS =
+
+     INSTBINFLAGS = -m 0755
+     INSTUIDFLAGS = -m 4755
+     INSTLIBFLAGS = -m 0644
+     INSTINCFLAGS = -m 0444
+     INSTMANFLAGS = -m 0444
+     INSTDATFLAGS = -m 0444
+    INSTKMEMFLAGS = -g kmem -m 2755
+
+      PROJECTROOT = /v/X11R5
+
+     TOP_INCLUDES = -I$(INCROOT)
+
+      CDEBUGFLAGS = -O
+        CCOPTIONS =
+
+      ALLINCLUDES = $(INCLUDES) $(EXTRA_INCLUDES) $(TOP_INCLUDES) $(STD_INCLUDES)
+       ALLDEFINES = $(ALLINCLUDES) $(STD_DEFINES) $(EXTRA_DEFINES) $(PROTO_DEFINES) $(DEFINES)
+           CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLDEFINES)
+        LINTFLAGS = $(LINTOPTS) -DLINT $(ALLDEFINES)
+
+           LDLIBS = $(SYS_LIBRARIES) $(EXTRA_LIBRARIES)
+
+        LDOPTIONS = $(CDEBUGFLAGS) $(CCOPTIONS) $(LOCAL_LDFLAGS) -L$(USRLIBDIR)
+
+   LDCOMBINEFLAGS = -X -r
+      DEPENDFLAGS =
+
+        MACROFILE = sun.cf
+           RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *~ *.a .emacs_* tags TAGS make.log MakeOut
+
+    IMAKE_DEFINES =
+
+         IRULESRC = $(CONFIGDIR)
+        IMAKE_CMD = $(IMAKE) -DUseInstalled -I$(IRULESRC) $(IMAKE_DEFINES)
+
+     ICONFIGFILES = $(IRULESRC)/Imake.tmpl $(IRULESRC)/Imake.rules \
+                       $(IRULESRC)/Project.tmpl $(IRULESRC)/site.def \
+                       $(IRULESRC)/$(MACROFILE) $(EXTRA_ICONFIGFILES)
+
+# -------------------------------------------------------------------------
+# X Window System Build Parameters
+# $XConsortium: Project.tmpl,v 1.138 91/09/10 09:02:12 rws Exp $
+
+# -------------------------------------------------------------------------
+# X Window System make variables; this need to be coordinated with rules
+
+          PATHSEP = /
+        USRLIBDIR = /v/X11R5/lib
+           BINDIR = /v/X11R5/bin
+          INCROOT = /v/X11R5/include
+     BUILDINCROOT = $(TOP)
+      BUILDINCDIR = $(BUILDINCROOT)/X11
+      BUILDINCTOP = ..
+           INCDIR = $(INCROOT)/X11
+           ADMDIR = /usr/adm
+           LIBDIR = $(USRLIBDIR)/X11
+        CONFIGDIR = $(LIBDIR)/config
+       LINTLIBDIR = $(USRLIBDIR)/lint
+
+          FONTDIR = $(LIBDIR)/fonts
+         XINITDIR = $(LIBDIR)/xinit
+           XDMDIR = $(LIBDIR)/xdm
+           TWMDIR = $(LIBDIR)/twm
+          MANPATH = /v/X11R5/man
+    MANSOURCEPATH = $(MANPATH)/man
+        MANSUFFIX = n
+     LIBMANSUFFIX = 3
+           MANDIR = $(MANSOURCEPATH)$(MANSUFFIX)
+        LIBMANDIR = $(MANSOURCEPATH)$(LIBMANSUFFIX)
+           NLSDIR = $(LIBDIR)/nls
+        PEXAPIDIR = $(LIBDIR)/PEX
+      XAPPLOADDIR = $(LIBDIR)/app-defaults
+       FONTCFLAGS = -t
+
+     INSTAPPFLAGS = $(INSTDATFLAGS)
+
+            IMAKE = imake
+           DEPEND = makedepend
+              RGB = rgb
+
+            FONTC = bdftopcf
+
+        MKFONTDIR = mkfontdir
+        MKDIRHIER = /bin/sh $(BINDIR)/mkdirhier
+
+        CONFIGSRC = $(TOP)/config
+       DOCUTILSRC = $(TOP)/doc/util
+        CLIENTSRC = $(TOP)/clients
+          DEMOSRC = $(TOP)/demos
+           LIBSRC = $(TOP)/lib
+          FONTSRC = $(TOP)/fonts
+       INCLUDESRC = $(TOP)/X11
+        SERVERSRC = $(TOP)/server
+          UTILSRC = $(TOP)/util
+        SCRIPTSRC = $(UTILSRC)/scripts
+       EXAMPLESRC = $(TOP)/examples
+       CONTRIBSRC = $(TOP)/../contrib
+           DOCSRC = $(TOP)/doc
+           RGBSRC = $(TOP)/rgb
+        DEPENDSRC = $(UTILSRC)/makedepend
+         IMAKESRC = $(CONFIGSRC)
+         XAUTHSRC = $(LIBSRC)/Xau
+          XLIBSRC = $(LIBSRC)/X
+           XMUSRC = $(LIBSRC)/Xmu
+       TOOLKITSRC = $(LIBSRC)/Xt
+       AWIDGETSRC = $(LIBSRC)/Xaw
+       OLDXLIBSRC = $(LIBSRC)/oldX
+      XDMCPLIBSRC = $(LIBSRC)/Xdmcp
+      BDFTOSNFSRC = $(FONTSRC)/bdftosnf
+      BDFTOSNFSRC = $(FONTSRC)/clients/bdftosnf
+      BDFTOPCFSRC = $(FONTSRC)/clients/bdftopcf
+     MKFONTDIRSRC = $(FONTSRC)/clients/mkfontdir
+         FSLIBSRC = $(FONTSRC)/lib/fs
+    FONTSERVERSRC = $(FONTSRC)/server
+     EXTENSIONSRC = $(TOP)/extensions
+         XILIBSRC = $(EXTENSIONSRC)/lib/xinput
+      PHIGSLIBSRC = $(EXTENSIONSRC)/lib/PEX
+
+# $XConsortium: sunLib.tmpl,v 1.14.1.1 92/03/17 14:58:46 rws Exp $
+
+SHLIBLDFLAGS = -assert pure-text
+PICFLAGS = -fPIC
+
+  DEPEXTENSIONLIB =
+     EXTENSIONLIB = -lXext
+
+          DEPXLIB = $(DEPEXTENSIONLIB)
+             XLIB = $(EXTENSIONLIB) -lX11
+
+        DEPXMULIB = $(USRLIBDIR)/libXmu.sa.$(SOXMUREV)
+       XMULIBONLY = -lXmu
+           XMULIB = -lXmu
+
+       DEPOLDXLIB =
+          OLDXLIB = -loldX
+
+      DEPXTOOLLIB = $(USRLIBDIR)/libXt.sa.$(SOXTREV)
+         XTOOLLIB = -lXt
+
+        DEPXAWLIB = $(USRLIBDIR)/libXaw.sa.$(SOXAWREV)
+           XAWLIB = -lXaw
+
+        DEPXILIB =
+           XILIB = -lXi
+
+        SOXLIBREV = 4.10
+          SOXTREV = 4.10
+         SOXAWREV = 5.0
+        SOOLDXREV = 4.10
+         SOXMUREV = 4.10
+        SOXEXTREV = 4.10
+      SOXINPUTREV = 4.10
+
+      DEPXAUTHLIB = $(USRLIBDIR)/libXau.a
+         XAUTHLIB =  -lXau
+      DEPXDMCPLIB = $(USRLIBDIR)/libXdmcp.a
+         XDMCPLIB =  -lXdmcp
+
+        DEPPHIGSLIB = $(USRLIBDIR)/libphigs.a
+           PHIGSLIB =  -lphigs
+
+       DEPXBSDLIB = $(USRLIBDIR)/libXbsd.a
+          XBSDLIB =  -lXbsd
+
+ LINTEXTENSIONLIB = $(LINTLIBDIR)/llib-lXext.ln
+         LINTXLIB = $(LINTLIBDIR)/llib-lX11.ln
+          LINTXMU = $(LINTLIBDIR)/llib-lXmu.ln
+        LINTXTOOL = $(LINTLIBDIR)/llib-lXt.ln
+          LINTXAW = $(LINTLIBDIR)/llib-lXaw.ln
+           LINTXI = $(LINTLIBDIR)/llib-lXi.ln
+        LINTPHIGS = $(LINTLIBDIR)/llib-lphigs.ln
+
+          DEPLIBS = $(DEPXAWLIB) $(DEPXMULIB) $(DEPXTOOLLIB) $(DEPXLIB)
+
+         DEPLIBS1 = $(DEPLIBS)
+         DEPLIBS2 = $(DEPLIBS)
+         DEPLIBS3 = $(DEPLIBS)
+
+# -------------------------------------------------------------------------
+# Imake rules for building libraries, programs, scripts, and data files
+# rules:  $XConsortium: Imake.rules,v 1.123 91/09/16 20:12:16 rws Exp $
+
+# -------------------------------------------------------------------------
+# start of Imakefile
+
+#
+#
+#
+
+          OBJS = DefaultStyles.o HText.o dummy.o
+          SRCS = DefaultStyles.c HText.c dummy.c
+
+       DEFINES = -I../Cl/WWWLibrary
+
+all:: libHt.a
+
+libHt.a:  $(OBJS)
+       $(RM) $@
+       $(AR) $@  $(OBJS)
+       $(RANLIB) $@
+
+depend::
+       $(DEPEND) $(DEPENDFLAGS) -s "# DO NOT DELETE" -- $(ALLDEFINES) -- $(SRCS)
+
+# -------------------------------------------------------------------------
+# common rules for all Makefiles - do not edit
+
+emptyrule::
+
+clean::
+       $(RM_CMD) "#"*
+
+Makefile::
+       -@if [ -f Makefile ]; then set -x; \
+       $(RM) Makefile.bak; $(MV) Makefile Makefile.bak; \
+       else exit 0; fi
+       $(IMAKE_CMD) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT_DIR)
+
+tags::
+       $(TAGS) -w *.[ch]
+       $(TAGS) -xw *.[ch] > TAGS
+
+saber:
+       # load $(ALLDEFINES) $(SRCS)
+
+osaber:
+       # load $(ALLDEFINES) $(OBJS)
+
+# -------------------------------------------------------------------------
+# empty rules for directories that do not have SUBDIRS - do not edit
+
+install::
+       @echo "install in $(CURRENT_DIR) done"
+
+install.man::
+       @echo "install.man in $(CURRENT_DIR) done"
+
+Makefiles::
+
+includes::
+
+# -------------------------------------------------------------------------
+# dependencies generated by makedepend
+
diff --git a/HText/dummy.c b/HText/dummy.c
new file mode 100644 (file)
index 0000000..0f5a3c7
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * dummy.c --
+ *
+ * Author: Teemu Rantanen <tvr@cs.hut.fi>
+ * Copyright (c) 1992 Teemu Rantanen
+ *                    All rights reserved
+ *
+ * Created: Wed Feb 26 16:30:17 1992 tvr
+ * Last modified: Wed Feb 26 23:12:57 1992 tvr
+ *
+ */
+
+#include <stdio.h>
+#include "HTStyle.h"
+#include "HText.h"
+
+/*
+ * something needed here to compile, but not to HText ..
+ */
+
+FILE *logfile = NULL;
+
+char *HTClientHost = NULL;
+
+struct HText *HTMainText = NULL;
+
+struct HTParentAnchor *HTMainAnchor = NULL;
diff --git a/Imakefile b/Imakefile
new file mode 100644 (file)
index 0000000..c7c73d3
--- /dev/null
+++ b/Imakefile
@@ -0,0 +1,29 @@
+#
+#
+#
+
+#define PassCDebugFlags 'CC=$(CC)' 'CDEBUGFLAGS=$(CDEBUGFLAGS)'
+#define IHaveSubdirs
+
+all::
+
+world::
+       make ${MFLAGS} mastermakefiles
+       make ${MFLAGS} depend
+       make ${MFLAGS} all
+
+        SUBDIRS        = Cl HText Xl Ui erwise
+
+MakeSubdirs($(SUBDIRS))
+
+DependSubdirs($(SUBDIRS))
+
+install::
+       $(MAKE) $(MFLAGS) install
+
+/**/# rebuild the makefiles at the master source tree
+mastermakefiles::
+       -$(MV)  Makefile Makefile.bak
+       $(MAKE) -f Makefile.bak Makefile
+       $(MAKE) Makefiles
+
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..9165f86
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,438 @@
+# Makefile generated by imake - do not edit!
+# $XConsortium: imake.c,v 1.65 91/07/25 17:50:17 rws Exp $
+#
+# The cpp used on this machine replaces all newlines and multiple tabs and
+# spaces in a macro expansion with a single space.  Imake tries to compensate
+# for this, but is not always successful.
+#
+
+# -------------------------------------------------------------------------
+# Makefile generated from "Imake.tmpl" and </tmp/IIf.a07565>
+# $XConsortium: Imake.tmpl,v 1.139 91/09/16 08:52:48 rws Exp $
+#
+# Platform-specific parameters may be set in the appropriate <vendor>.cf
+# configuration files.  Site-specific parameters should be set in the file
+# site.def.  Full rebuilds are recommended if any parameters are changed.
+#
+# If your C preprocessor does not define any unique symbols, you will need
+# to set BOOTSTRAPCFLAGS when rebuilding imake (usually when doing
+# "make World" the first time).
+#
+
+# -------------------------------------------------------------------------
+# site-specific configuration parameters that need to come before
+# the platform-specific parameters - edit site.def to change
+
+# site:  $XConsortium: site.def,v 1.2 91/07/30 20:26:44 rws Exp $
+
+# -------------------------------------------------------------------------
+# platform-specific configuration parameters - edit sun.cf to change
+
+# platform:  $XConsortium: sun.cf,v 1.72.1.1 92/03/18 13:13:37 rws Exp $
+
+# operating system:  SunOS 4.1.2
+
+# $XConsortium: sunLib.rules,v 1.7 91/12/20 11:19:47 rws Exp $
+
+.c.o:
+       $(CC) -c $(CFLAGS) $*.c
+
+# -------------------------------------------------------------------------
+# site-specific configuration parameters that go after
+# the platform-specific parameters - edit site.def to change
+
+# site:  $XConsortium: site.def,v 1.2 91/07/30 20:26:44 rws Exp $
+
+            SHELL = /bin/sh
+
+              TOP = .
+      CURRENT_DIR = .
+
+               AR = ar clq
+  BOOTSTRAPCFLAGS =
+               CC = gcc2 -pipe -fstrength-reduce -fpcc-struct-return
+               AS = as
+
+         COMPRESS = compress
+              CPP = /lib/cpp $(STD_CPP_DEFINES)
+    PREPROCESSCMD = gcc2 -pipe -fstrength-reduce -fpcc-struct-return -E $(STD_CPP_DEFINES)
+          INSTALL = install
+               LD = ld
+             LINT = lint
+      LINTLIBFLAG = -C
+         LINTOPTS = -axz
+               LN = ln -s
+             MAKE = make
+               MV = mv
+               CP = cp
+
+           RANLIB = ranlib
+  RANLIBINSTFLAGS =
+
+               RM = rm -f
+            TROFF = psroff
+         MSMACROS = -ms
+              TBL = tbl
+              EQN = eqn
+     STD_INCLUDES =
+  STD_CPP_DEFINES =
+      STD_DEFINES =
+ EXTRA_LOAD_FLAGS = -B/usr/bin/
+  EXTRA_LIBRARIES =
+             TAGS = ctags
+
+    SHAREDCODEDEF = -DSHAREDCODE
+         SHLIBDEF = -DSUNSHLIB
+
+    PROTO_DEFINES =
+
+     INSTPGMFLAGS =
+
+     INSTBINFLAGS = -m 0755
+     INSTUIDFLAGS = -m 4755
+     INSTLIBFLAGS = -m 0644
+     INSTINCFLAGS = -m 0444
+     INSTMANFLAGS = -m 0444
+     INSTDATFLAGS = -m 0444
+    INSTKMEMFLAGS = -g kmem -m 2755
+
+      PROJECTROOT = /v/X11R5
+
+     TOP_INCLUDES = -I$(INCROOT)
+
+      CDEBUGFLAGS = -O
+        CCOPTIONS =
+
+      ALLINCLUDES = $(INCLUDES) $(EXTRA_INCLUDES) $(TOP_INCLUDES) $(STD_INCLUDES)
+       ALLDEFINES = $(ALLINCLUDES) $(STD_DEFINES) $(EXTRA_DEFINES) $(PROTO_DEFINES) $(DEFINES)
+           CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLDEFINES)
+        LINTFLAGS = $(LINTOPTS) -DLINT $(ALLDEFINES)
+
+           LDLIBS = $(SYS_LIBRARIES) $(EXTRA_LIBRARIES)
+
+        LDOPTIONS = $(CDEBUGFLAGS) $(CCOPTIONS) $(LOCAL_LDFLAGS) -L$(USRLIBDIR)
+
+   LDCOMBINEFLAGS = -X -r
+      DEPENDFLAGS =
+
+        MACROFILE = sun.cf
+           RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *~ *.a .emacs_* tags TAGS make.log MakeOut
+
+    IMAKE_DEFINES =
+
+         IRULESRC = $(CONFIGDIR)
+        IMAKE_CMD = $(IMAKE) -DUseInstalled -I$(IRULESRC) $(IMAKE_DEFINES)
+
+     ICONFIGFILES = $(IRULESRC)/Imake.tmpl $(IRULESRC)/Imake.rules \
+                       $(IRULESRC)/Project.tmpl $(IRULESRC)/site.def \
+                       $(IRULESRC)/$(MACROFILE) $(EXTRA_ICONFIGFILES)
+
+# -------------------------------------------------------------------------
+# X Window System Build Parameters
+# $XConsortium: Project.tmpl,v 1.138 91/09/10 09:02:12 rws Exp $
+
+# -------------------------------------------------------------------------
+# X Window System make variables; this need to be coordinated with rules
+
+          PATHSEP = /
+        USRLIBDIR = /v/X11R5/lib
+           BINDIR = /v/X11R5/bin
+          INCROOT = /v/X11R5/include
+     BUILDINCROOT = $(TOP)
+      BUILDINCDIR = $(BUILDINCROOT)/X11
+      BUILDINCTOP = ..
+           INCDIR = $(INCROOT)/X11
+           ADMDIR = /usr/adm
+           LIBDIR = $(USRLIBDIR)/X11
+        CONFIGDIR = $(LIBDIR)/config
+       LINTLIBDIR = $(USRLIBDIR)/lint
+
+          FONTDIR = $(LIBDIR)/fonts
+         XINITDIR = $(LIBDIR)/xinit
+           XDMDIR = $(LIBDIR)/xdm
+           TWMDIR = $(LIBDIR)/twm
+          MANPATH = /v/X11R5/man
+    MANSOURCEPATH = $(MANPATH)/man
+        MANSUFFIX = n
+     LIBMANSUFFIX = 3
+           MANDIR = $(MANSOURCEPATH)$(MANSUFFIX)
+        LIBMANDIR = $(MANSOURCEPATH)$(LIBMANSUFFIX)
+           NLSDIR = $(LIBDIR)/nls
+        PEXAPIDIR = $(LIBDIR)/PEX
+      XAPPLOADDIR = $(LIBDIR)/app-defaults
+       FONTCFLAGS = -t
+
+     INSTAPPFLAGS = $(INSTDATFLAGS)
+
+            IMAKE = imake
+           DEPEND = makedepend
+              RGB = rgb
+
+            FONTC = bdftopcf
+
+        MKFONTDIR = mkfontdir
+        MKDIRHIER = /bin/sh $(BINDIR)/mkdirhier
+
+        CONFIGSRC = $(TOP)/config
+       DOCUTILSRC = $(TOP)/doc/util
+        CLIENTSRC = $(TOP)/clients
+          DEMOSRC = $(TOP)/demos
+           LIBSRC = $(TOP)/lib
+          FONTSRC = $(TOP)/fonts
+       INCLUDESRC = $(TOP)/X11
+        SERVERSRC = $(TOP)/server
+          UTILSRC = $(TOP)/util
+        SCRIPTSRC = $(UTILSRC)/scripts
+       EXAMPLESRC = $(TOP)/examples
+       CONTRIBSRC = $(TOP)/../contrib
+           DOCSRC = $(TOP)/doc
+           RGBSRC = $(TOP)/rgb
+        DEPENDSRC = $(UTILSRC)/makedepend
+         IMAKESRC = $(CONFIGSRC)
+         XAUTHSRC = $(LIBSRC)/Xau
+          XLIBSRC = $(LIBSRC)/X
+           XMUSRC = $(LIBSRC)/Xmu
+       TOOLKITSRC = $(LIBSRC)/Xt
+       AWIDGETSRC = $(LIBSRC)/Xaw
+       OLDXLIBSRC = $(LIBSRC)/oldX
+      XDMCPLIBSRC = $(LIBSRC)/Xdmcp
+      BDFTOSNFSRC = $(FONTSRC)/bdftosnf
+      BDFTOSNFSRC = $(FONTSRC)/clients/bdftosnf
+      BDFTOPCFSRC = $(FONTSRC)/clients/bdftopcf
+     MKFONTDIRSRC = $(FONTSRC)/clients/mkfontdir
+         FSLIBSRC = $(FONTSRC)/lib/fs
+    FONTSERVERSRC = $(FONTSRC)/server
+     EXTENSIONSRC = $(TOP)/extensions
+         XILIBSRC = $(EXTENSIONSRC)/lib/xinput
+      PHIGSLIBSRC = $(EXTENSIONSRC)/lib/PEX
+
+# $XConsortium: sunLib.tmpl,v 1.14.1.1 92/03/17 14:58:46 rws Exp $
+
+SHLIBLDFLAGS = -assert pure-text
+PICFLAGS = -fPIC
+
+  DEPEXTENSIONLIB =
+     EXTENSIONLIB = -lXext
+
+          DEPXLIB = $(DEPEXTENSIONLIB)
+             XLIB = $(EXTENSIONLIB) -lX11
+
+        DEPXMULIB = $(USRLIBDIR)/libXmu.sa.$(SOXMUREV)
+       XMULIBONLY = -lXmu
+           XMULIB = -lXmu
+
+       DEPOLDXLIB =
+          OLDXLIB = -loldX
+
+      DEPXTOOLLIB = $(USRLIBDIR)/libXt.sa.$(SOXTREV)
+         XTOOLLIB = -lXt
+
+        DEPXAWLIB = $(USRLIBDIR)/libXaw.sa.$(SOXAWREV)
+           XAWLIB = -lXaw
+
+        DEPXILIB =
+           XILIB = -lXi
+
+        SOXLIBREV = 4.10
+          SOXTREV = 4.10
+         SOXAWREV = 5.0
+        SOOLDXREV = 4.10
+         SOXMUREV = 4.10
+        SOXEXTREV = 4.10
+      SOXINPUTREV = 4.10
+
+      DEPXAUTHLIB = $(USRLIBDIR)/libXau.a
+         XAUTHLIB =  -lXau
+      DEPXDMCPLIB = $(USRLIBDIR)/libXdmcp.a
+         XDMCPLIB =  -lXdmcp
+
+        DEPPHIGSLIB = $(USRLIBDIR)/libphigs.a
+           PHIGSLIB =  -lphigs
+
+       DEPXBSDLIB = $(USRLIBDIR)/libXbsd.a
+          XBSDLIB =  -lXbsd
+
+ LINTEXTENSIONLIB = $(LINTLIBDIR)/llib-lXext.ln
+         LINTXLIB = $(LINTLIBDIR)/llib-lX11.ln
+          LINTXMU = $(LINTLIBDIR)/llib-lXmu.ln
+        LINTXTOOL = $(LINTLIBDIR)/llib-lXt.ln
+          LINTXAW = $(LINTLIBDIR)/llib-lXaw.ln
+           LINTXI = $(LINTLIBDIR)/llib-lXi.ln
+        LINTPHIGS = $(LINTLIBDIR)/llib-lphigs.ln
+
+          DEPLIBS = $(DEPXAWLIB) $(DEPXMULIB) $(DEPXTOOLLIB) $(DEPXLIB)
+
+         DEPLIBS1 = $(DEPLIBS)
+         DEPLIBS2 = $(DEPLIBS)
+         DEPLIBS3 = $(DEPLIBS)
+
+# -------------------------------------------------------------------------
+# Imake rules for building libraries, programs, scripts, and data files
+# rules:  $XConsortium: Imake.rules,v 1.123 91/09/16 20:12:16 rws Exp $
+
+# -------------------------------------------------------------------------
+# start of Imakefile
+
+#
+#
+#
+
+all::
+
+world::
+       make ${MFLAGS} mastermakefiles
+       make ${MFLAGS} depend
+       make ${MFLAGS} all
+
+        SUBDIRS        = Cl HText Xl Ui erwise
+
+all::
+       @case '${MFLAGS}' in *[ik]*) set +e;; esac; \
+       for i in $(SUBDIRS) ;\
+       do \
+       (cd $$i ; echo "making" all "in $(CURRENT_DIR)/$$i..."; \
+       $(MAKE) $(MFLAGS) 'CC=$(CC)' 'CDEBUGFLAGS=$(CDEBUGFLAGS)' all); \
+       done
+
+depend::
+       @case '${MFLAGS}' in *[ik]*) set +e;; esac; \
+       for i in $(SUBDIRS) ;\
+       do \
+       (cd $$i ; echo "depending" "in $(CURRENT_DIR)/$$i..."; \
+       $(MAKE) $(MFLAGS)  depend); \
+       done
+
+install::
+       $(MAKE) $(MFLAGS) install
+
+# rebuild the makefiles at the master source tree
+mastermakefiles::
+       -$(MV)  Makefile Makefile.bak
+       $(MAKE) -f Makefile.bak Makefile
+       $(MAKE) Makefiles
+
+# -------------------------------------------------------------------------
+# common rules for all Makefiles - do not edit
+
+emptyrule::
+
+clean::
+       $(RM_CMD) "#"*
+
+Makefile::
+       -@if [ -f Makefile ]; then set -x; \
+       $(RM) Makefile.bak; $(MV) Makefile Makefile.bak; \
+       else exit 0; fi
+       $(IMAKE_CMD) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT_DIR)
+
+tags::
+       $(TAGS) -w *.[ch]
+       $(TAGS) -xw *.[ch] > TAGS
+
+saber:
+       # load $(ALLDEFINES) $(SRCS)
+
+osaber:
+       # load $(ALLDEFINES) $(OBJS)
+
+# -------------------------------------------------------------------------
+# rules for building in SUBDIRS - do not edit
+
+install::
+       @case '${MFLAGS}' in *[ik]*) set +e;; esac; \
+       for i in $(SUBDIRS) ;\
+       do \
+       (cd $$i ; echo "installing" "in $(CURRENT_DIR)/$$i..."; \
+       $(MAKE) $(MFLAGS) DESTDIR='$(DESTDIR)' install); \
+       done
+
+install.man::
+       @case '${MFLAGS}' in *[ik]*) set +e;; esac; \
+       for i in $(SUBDIRS) ;\
+       do \
+       (cd $$i ; echo "installing man pages" "in $(CURRENT_DIR)/$$i..."; \
+       $(MAKE) $(MFLAGS) DESTDIR='$(DESTDIR)' install.man); \
+       done
+
+clean::
+       @case '${MFLAGS}' in *[ik]*) set +e;; esac; \
+       for i in $(SUBDIRS) ;\
+       do \
+       (cd $$i ; echo "cleaning" "in $(CURRENT_DIR)/$$i..."; \
+       $(MAKE) $(MFLAGS) RM_CMD='$(RM_CMD)' clean); \
+       done
+
+tags::
+       @case '${MFLAGS}' in *[ik]*) set +e;; esac; \
+       for i in $(SUBDIRS) ;\
+       do \
+       (cd $$i ; echo "tagging" "in $(CURRENT_DIR)/$$i..."; \
+       $(MAKE) $(MFLAGS) TAGS='$(TAGS)' tags); \
+       done
+
+Makefiles::
+       @case '${MFLAGS}' in *[ik]*) set +e;; esac; \
+       for i in $(SUBDIRS) ;\
+       do \
+       echo "making Makefiles in $(CURRENT_DIR)/$$i..."; \
+       case "$$i" in \
+       ./?*/?*/?*/?*) newtop=../../../../ sub=subsubsubsub;; \
+       ./?*/?*/?*) newtop=../../../ sub=subsubsub;; \
+       ./?*/?*) newtop=../../ sub=subsub;; \
+       ./?*) newtop=../ sub=sub;; \
+       */?*/?*/?*) newtop=../../../../ sub=subsubsubsub;; \
+       */?*/?*) newtop=../../../ sub=subsubsub;; \
+       */?*) newtop=../../ sub=subsub;; \
+       *) newtop=../ sub=sub;; \
+       esac; \
+       case "$(TOP)" in \
+       /?*) newtop= upprefix= ;; \
+       *) upprefix=../ ;; \
+       esac; \
+       $(MAKE) $${sub}dirMakefiles UPPREFIX=$$upprefix NEWTOP=$$newtop \
+       MAKEFILE_SUBDIR=$$i NEW_CURRENT_DIR=$(CURRENT_DIR)/$$i;\
+       done
+
+subdirMakefiles:
+       $(RM) $(MAKEFILE_SUBDIR)/Makefile.bak
+       -@if [ -f $(MAKEFILE_SUBDIR)/Makefile ]; then set -x; \
+       $(MV) $(MAKEFILE_SUBDIR)/Makefile $(MAKEFILE_SUBDIR)/Makefile.bak; \
+       else exit 0; fi
+       cd $(MAKEFILE_SUBDIR); $(IMAKE_CMD) -DTOPDIR=$(UPPREFIX)$(TOP) -DCURDIR=$(NEW_CURRENT_DIR); \
+       $(MAKE) $(MFLAGS) Makefiles
+
+subsubdirMakefiles:
+       $(RM) $(MAKEFILE_SUBDIR)/Makefile.bak
+       -@if [ -f $(MAKEFILE_SUBDIR)/Makefile ]; then set -x; \
+       $(MV) $(MAKEFILE_SUBDIR)/Makefile $(MAKEFILE_SUBDIR)/Makefile.bak; \
+       else exit 0; fi
+       cd $(MAKEFILE_SUBDIR); $(IMAKE_CMD) -DTOPDIR=$(UPPREFIX)$(UPPREFIX)$(TOP) -DCURDIR=$(NEW_CURRENT_DIR); \
+       $(MAKE) $(MFLAGS) Makefiles
+
+subsubsubdirMakefiles:
+       $(RM) $(MAKEFILE_SUBDIR)/Makefile.bak
+       -@if [ -f $(MAKEFILE_SUBDIR)/Makefile ]; then set -x; \
+       $(MV) $(MAKEFILE_SUBDIR)/Makefile $(MAKEFILE_SUBDIR)/Makefile.bak; \
+       else exit 0; fi
+       cd $(MAKEFILE_SUBDIR); $(IMAKE_CMD) -DTOPDIR=$(UPPREFIX)$(UPPREFIX)$(UPPREFIX)$(TOP) -DCURDIR=$(NEW_CURRENT_DIR); \
+       $(MAKE) $(MFLAGS) Makefiles
+
+subsubsubsubdirMakefiles:
+       $(RM) $(MAKEFILE_SUBDIR)/Makefile.bak
+       -@if [ -f $(MAKEFILE_SUBDIR)/Makefile ]; then set -x; \
+       $(MV) $(MAKEFILE_SUBDIR)/Makefile $(MAKEFILE_SUBDIR)/Makefile.bak; \
+       else exit 0; fi
+       cd $(MAKEFILE_SUBDIR); $(IMAKE_CMD) -DTOPDIR=$(UPPREFIX)$(UPPREFIX)$(UPPREFIX)$(UPPREFIX)$(TOP) -DCURDIR=$(NEW_CURRENT_DIR); \
+       $(MAKE) $(MFLAGS) Makefiles
+
+includes::
+       @case '${MFLAGS}' in *[ik]*) set +e;; esac; \
+       for i in $(SUBDIRS) ;\
+       do \
+       (cd $$i ; echo including "in $(CURRENT_DIR)/$$i..."; \
+       $(MAKE) $(MFLAGS)  includes); \
+       done
+
+# -------------------------------------------------------------------------
+# dependencies generated by makedepend
+
diff --git a/Ui/Imakefile b/Ui/Imakefile
new file mode 100644 (file)
index 0000000..257cb3f
--- /dev/null
@@ -0,0 +1,24 @@
+#
+#
+#
+
+          OBJS = UiInit.o UiSelectionBox.o UiPage.o UiMisc.o           \
+                 UiSearch.o UiPageSettings.o UiList.o UiInfo.o         \
+                 UiControlPanel.o UiDefaults.o UiUtil.o UiPrint.o      \
+                 UiConnections.o UiFileSelection.o UiRecall.o
+
+          SRCS = UiInit.c UiSelectionBox.c UiPage.c UiMisc.c           \
+                 UiSearch.c UiPageSettings.c UiList.c UiInfo.c         \
+                 UiControlPanel.c UiDefaults.c UiUtil.c UiPrint.c      \
+                 UiConnections.c UiFileSelection.c UiRecall.c
+
+         XLDIR = ../Xl
+         HTDIR = ../HText
+        WWWDIR = ../Cl/WWWLibrary
+     MOTIF_HDRS = -I/p/motif/include
+    ERWISE_HDRS = -I$(XLDIR) -I$(HTDIR) -I$(WWWDIR)
+       DEFINES = $(ERWISE_HDRS) $(MOTIF_HDRS)  -DERWISE_UI
+
+NormalLibraryTarget(Ui, $(OBJS))
+
+DependTarget()
diff --git a/Ui/Makefile b/Ui/Makefile
new file mode 100644 (file)
index 0000000..d696b5c
--- /dev/null
@@ -0,0 +1,346 @@
+# Makefile generated by imake - do not edit!
+# $XConsortium: imake.c,v 1.65 91/07/25 17:50:17 rws Exp $
+#
+# The cpp used on this machine replaces all newlines and multiple tabs and
+# spaces in a macro expansion with a single space.  Imake tries to compensate
+# for this, but is not always successful.
+#
+
+# -------------------------------------------------------------------------
+# Makefile generated from "Imake.tmpl" and </tmp/IIf.a10907>
+# $XConsortium: Imake.tmpl,v 1.139 91/09/16 08:52:48 rws Exp $
+#
+# Platform-specific parameters may be set in the appropriate <vendor>.cf
+# configuration files.  Site-specific parameters should be set in the file
+# site.def.  Full rebuilds are recommended if any parameters are changed.
+#
+# If your C preprocessor does not define any unique symbols, you will need
+# to set BOOTSTRAPCFLAGS when rebuilding imake (usually when doing
+# "make World" the first time).
+#
+
+# -------------------------------------------------------------------------
+# site-specific configuration parameters that need to come before
+# the platform-specific parameters - edit site.def to change
+
+# site:  $XConsortium: site.def,v 1.2 91/07/30 20:26:44 rws Exp $
+
+# -------------------------------------------------------------------------
+# platform-specific configuration parameters - edit sun.cf to change
+
+# platform:  $XConsortium: sun.cf,v 1.72.1.1 92/03/18 13:13:37 rws Exp $
+
+# operating system:  SunOS 4.1.2
+
+# $XConsortium: sunLib.rules,v 1.7 91/12/20 11:19:47 rws Exp $
+
+.c.o:
+       $(CC) -c $(CFLAGS) $*.c
+
+# -------------------------------------------------------------------------
+# site-specific configuration parameters that go after
+# the platform-specific parameters - edit site.def to change
+
+# site:  $XConsortium: site.def,v 1.2 91/07/30 20:26:44 rws Exp $
+
+            SHELL = /bin/sh
+
+              TOP = ../.
+      CURRENT_DIR = ./Ui
+
+               AR = ar clq
+  BOOTSTRAPCFLAGS =
+               CC = gcc2 -pipe -fstrength-reduce -fpcc-struct-return
+               AS = as
+
+         COMPRESS = compress
+              CPP = /lib/cpp $(STD_CPP_DEFINES)
+    PREPROCESSCMD = gcc2 -pipe -fstrength-reduce -fpcc-struct-return -E $(STD_CPP_DEFINES)
+          INSTALL = install
+               LD = ld
+             LINT = lint
+      LINTLIBFLAG = -C
+         LINTOPTS = -axz
+               LN = ln -s
+             MAKE = make
+               MV = mv
+               CP = cp
+
+           RANLIB = ranlib
+  RANLIBINSTFLAGS =
+
+               RM = rm -f
+            TROFF = psroff
+         MSMACROS = -ms
+              TBL = tbl
+              EQN = eqn
+     STD_INCLUDES =
+  STD_CPP_DEFINES =
+      STD_DEFINES =
+ EXTRA_LOAD_FLAGS = -B/usr/bin/
+  EXTRA_LIBRARIES =
+             TAGS = ctags
+
+    SHAREDCODEDEF = -DSHAREDCODE
+         SHLIBDEF = -DSUNSHLIB
+
+    PROTO_DEFINES =
+
+     INSTPGMFLAGS =
+
+     INSTBINFLAGS = -m 0755
+     INSTUIDFLAGS = -m 4755
+     INSTLIBFLAGS = -m 0644
+     INSTINCFLAGS = -m 0444
+     INSTMANFLAGS = -m 0444
+     INSTDATFLAGS = -m 0444
+    INSTKMEMFLAGS = -g kmem -m 2755
+
+      PROJECTROOT = /v/X11R5
+
+     TOP_INCLUDES = -I$(INCROOT)
+
+      CDEBUGFLAGS = -O
+        CCOPTIONS =
+
+      ALLINCLUDES = $(INCLUDES) $(EXTRA_INCLUDES) $(TOP_INCLUDES) $(STD_INCLUDES)
+       ALLDEFINES = $(ALLINCLUDES) $(STD_DEFINES) $(EXTRA_DEFINES) $(PROTO_DEFINES) $(DEFINES)
+           CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLDEFINES)
+        LINTFLAGS = $(LINTOPTS) -DLINT $(ALLDEFINES)
+
+           LDLIBS = $(SYS_LIBRARIES) $(EXTRA_LIBRARIES)
+
+        LDOPTIONS = $(CDEBUGFLAGS) $(CCOPTIONS) $(LOCAL_LDFLAGS) -L$(USRLIBDIR)
+
+   LDCOMBINEFLAGS = -X -r
+      DEPENDFLAGS =
+
+        MACROFILE = sun.cf
+           RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *~ *.a .emacs_* tags TAGS make.log MakeOut
+
+    IMAKE_DEFINES =
+
+         IRULESRC = $(CONFIGDIR)
+        IMAKE_CMD = $(IMAKE) -DUseInstalled -I$(IRULESRC) $(IMAKE_DEFINES)
+
+     ICONFIGFILES = $(IRULESRC)/Imake.tmpl $(IRULESRC)/Imake.rules \
+                       $(IRULESRC)/Project.tmpl $(IRULESRC)/site.def \
+                       $(IRULESRC)/$(MACROFILE) $(EXTRA_ICONFIGFILES)
+
+# -------------------------------------------------------------------------
+# X Window System Build Parameters
+# $XConsortium: Project.tmpl,v 1.138 91/09/10 09:02:12 rws Exp $
+
+# -------------------------------------------------------------------------
+# X Window System make variables; this need to be coordinated with rules
+
+          PATHSEP = /
+        USRLIBDIR = /v/X11R5/lib
+           BINDIR = /v/X11R5/bin
+          INCROOT = /v/X11R5/include
+     BUILDINCROOT = $(TOP)
+      BUILDINCDIR = $(BUILDINCROOT)/X11
+      BUILDINCTOP = ..
+           INCDIR = $(INCROOT)/X11
+           ADMDIR = /usr/adm
+           LIBDIR = $(USRLIBDIR)/X11
+        CONFIGDIR = $(LIBDIR)/config
+       LINTLIBDIR = $(USRLIBDIR)/lint
+
+          FONTDIR = $(LIBDIR)/fonts
+         XINITDIR = $(LIBDIR)/xinit
+           XDMDIR = $(LIBDIR)/xdm
+           TWMDIR = $(LIBDIR)/twm
+          MANPATH = /v/X11R5/man
+    MANSOURCEPATH = $(MANPATH)/man
+        MANSUFFIX = n
+     LIBMANSUFFIX = 3
+           MANDIR = $(MANSOURCEPATH)$(MANSUFFIX)
+        LIBMANDIR = $(MANSOURCEPATH)$(LIBMANSUFFIX)
+           NLSDIR = $(LIBDIR)/nls
+        PEXAPIDIR = $(LIBDIR)/PEX
+      XAPPLOADDIR = $(LIBDIR)/app-defaults
+       FONTCFLAGS = -t
+
+     INSTAPPFLAGS = $(INSTDATFLAGS)
+
+            IMAKE = imake
+           DEPEND = makedepend
+              RGB = rgb
+
+            FONTC = bdftopcf
+
+        MKFONTDIR = mkfontdir
+        MKDIRHIER = /bin/sh $(BINDIR)/mkdirhier
+
+        CONFIGSRC = $(TOP)/config
+       DOCUTILSRC = $(TOP)/doc/util
+        CLIENTSRC = $(TOP)/clients
+          DEMOSRC = $(TOP)/demos
+           LIBSRC = $(TOP)/lib
+          FONTSRC = $(TOP)/fonts
+       INCLUDESRC = $(TOP)/X11
+        SERVERSRC = $(TOP)/server
+          UTILSRC = $(TOP)/util
+        SCRIPTSRC = $(UTILSRC)/scripts
+       EXAMPLESRC = $(TOP)/examples
+       CONTRIBSRC = $(TOP)/../contrib
+           DOCSRC = $(TOP)/doc
+           RGBSRC = $(TOP)/rgb
+        DEPENDSRC = $(UTILSRC)/makedepend
+         IMAKESRC = $(CONFIGSRC)
+         XAUTHSRC = $(LIBSRC)/Xau
+          XLIBSRC = $(LIBSRC)/X
+           XMUSRC = $(LIBSRC)/Xmu
+       TOOLKITSRC = $(LIBSRC)/Xt
+       AWIDGETSRC = $(LIBSRC)/Xaw
+       OLDXLIBSRC = $(LIBSRC)/oldX
+      XDMCPLIBSRC = $(LIBSRC)/Xdmcp
+      BDFTOSNFSRC = $(FONTSRC)/bdftosnf
+      BDFTOSNFSRC = $(FONTSRC)/clients/bdftosnf
+      BDFTOPCFSRC = $(FONTSRC)/clients/bdftopcf
+     MKFONTDIRSRC = $(FONTSRC)/clients/mkfontdir
+         FSLIBSRC = $(FONTSRC)/lib/fs
+    FONTSERVERSRC = $(FONTSRC)/server
+     EXTENSIONSRC = $(TOP)/extensions
+         XILIBSRC = $(EXTENSIONSRC)/lib/xinput
+      PHIGSLIBSRC = $(EXTENSIONSRC)/lib/PEX
+
+# $XConsortium: sunLib.tmpl,v 1.14.1.1 92/03/17 14:58:46 rws Exp $
+
+SHLIBLDFLAGS = -assert pure-text
+PICFLAGS = -fPIC
+
+  DEPEXTENSIONLIB =
+     EXTENSIONLIB = -lXext
+
+          DEPXLIB = $(DEPEXTENSIONLIB)
+             XLIB = $(EXTENSIONLIB) -lX11
+
+        DEPXMULIB = $(USRLIBDIR)/libXmu.sa.$(SOXMUREV)
+       XMULIBONLY = -lXmu
+           XMULIB = -lXmu
+
+       DEPOLDXLIB =
+          OLDXLIB = -loldX
+
+      DEPXTOOLLIB = $(USRLIBDIR)/libXt.sa.$(SOXTREV)
+         XTOOLLIB = -lXt
+
+        DEPXAWLIB = $(USRLIBDIR)/libXaw.sa.$(SOXAWREV)
+           XAWLIB = -lXaw
+
+        DEPXILIB =
+           XILIB = -lXi
+
+        SOXLIBREV = 4.10
+          SOXTREV = 4.10
+         SOXAWREV = 5.0
+        SOOLDXREV = 4.10
+         SOXMUREV = 4.10
+        SOXEXTREV = 4.10
+      SOXINPUTREV = 4.10
+
+      DEPXAUTHLIB = $(USRLIBDIR)/libXau.a
+         XAUTHLIB =  -lXau
+      DEPXDMCPLIB = $(USRLIBDIR)/libXdmcp.a
+         XDMCPLIB =  -lXdmcp
+
+        DEPPHIGSLIB = $(USRLIBDIR)/libphigs.a
+           PHIGSLIB =  -lphigs
+
+       DEPXBSDLIB = $(USRLIBDIR)/libXbsd.a
+          XBSDLIB =  -lXbsd
+
+ LINTEXTENSIONLIB = $(LINTLIBDIR)/llib-lXext.ln
+         LINTXLIB = $(LINTLIBDIR)/llib-lX11.ln
+          LINTXMU = $(LINTLIBDIR)/llib-lXmu.ln
+        LINTXTOOL = $(LINTLIBDIR)/llib-lXt.ln
+          LINTXAW = $(LINTLIBDIR)/llib-lXaw.ln
+           LINTXI = $(LINTLIBDIR)/llib-lXi.ln
+        LINTPHIGS = $(LINTLIBDIR)/llib-lphigs.ln
+
+          DEPLIBS = $(DEPXAWLIB) $(DEPXMULIB) $(DEPXTOOLLIB) $(DEPXLIB)
+
+         DEPLIBS1 = $(DEPLIBS)
+         DEPLIBS2 = $(DEPLIBS)
+         DEPLIBS3 = $(DEPLIBS)
+
+# -------------------------------------------------------------------------
+# Imake rules for building libraries, programs, scripts, and data files
+# rules:  $XConsortium: Imake.rules,v 1.123 91/09/16 20:12:16 rws Exp $
+
+# -------------------------------------------------------------------------
+# start of Imakefile
+
+#
+#
+#
+
+          OBJS = UiInit.o UiSelectionBox.o UiPage.o UiMisc.o           \
+                 UiSearch.o UiPageSettings.o UiList.o UiInfo.o         \
+                 UiControlPanel.o UiDefaults.o UiUtil.o UiPrint.o      \
+                 UiConnections.o UiFileSelection.o UiRecall.o
+
+          SRCS = UiInit.c UiSelectionBox.c UiPage.c UiMisc.c           \
+                 UiSearch.c UiPageSettings.c UiList.c UiInfo.c         \
+                 UiControlPanel.c UiDefaults.c UiUtil.c UiPrint.c      \
+                 UiConnections.c UiFileSelection.c UiRecall.c
+
+         XLDIR = ../Xl
+         HTDIR = ../HText
+        WWWDIR = ../Cl/WWWLibrary
+     MOTIF_HDRS = -I/p/motif/include
+    ERWISE_HDRS = -I$(XLDIR) -I$(HTDIR) -I$(WWWDIR)
+       DEFINES = $(ERWISE_HDRS) $(MOTIF_HDRS)  -DERWISE_UI
+
+all:: libUi.a
+
+libUi.a:  $(OBJS)
+       $(RM) $@
+       $(AR) $@  $(OBJS)
+       $(RANLIB) $@
+
+depend::
+       $(DEPEND) $(DEPENDFLAGS) -s "# DO NOT DELETE" -- $(ALLDEFINES) -- $(SRCS)
+
+# -------------------------------------------------------------------------
+# common rules for all Makefiles - do not edit
+
+emptyrule::
+
+clean::
+       $(RM_CMD) "#"*
+
+Makefile::
+       -@if [ -f Makefile ]; then set -x; \
+       $(RM) Makefile.bak; $(MV) Makefile Makefile.bak; \
+       else exit 0; fi
+       $(IMAKE_CMD) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT_DIR)
+
+tags::
+       $(TAGS) -w *.[ch]
+       $(TAGS) -xw *.[ch] > TAGS
+
+saber:
+       # load $(ALLDEFINES) $(SRCS)
+
+osaber:
+       # load $(ALLDEFINES) $(OBJS)
+
+# -------------------------------------------------------------------------
+# empty rules for directories that do not have SUBDIRS - do not edit
+
+install::
+       @echo "install in $(CURRENT_DIR) done"
+
+install.man::
+       @echo "install.man in $(CURRENT_DIR) done"
+
+Makefiles::
+
+includes::
+
+# -------------------------------------------------------------------------
+# dependencies generated by makedepend
+
diff --git a/Ui/RCS/.uidemo.c,v b/Ui/RCS/.uidemo.c,v
new file mode 100644 (file)
index 0000000..4d2bd2a
--- /dev/null
@@ -0,0 +1,145 @@
+head   1.1;
+access
+       kny
+       kss
+       kts
+       tvr;
+symbols;
+locks; strict;
+comment        @ * @;
+
+
+1.1
+date   92.02.09.16.41.46;      author kny;     state Exp;
+branches;
+next   1.0;
+
+1.0
+date   92.01.22.13.51.39;      author kny;     state Exp;
+branches;
+next   ;
+
+
+desc
+@Demo-program for Ui-library.
+@
+
+
+1.1
+log
+@Added demogetpage-callback, cleaned up some things.
+@
+text
+@static char *rcsid = "$Id: uidemo.c,v 1.0 1992/01/22 13:51:39 kny Exp kny $";
+
+#include <stdio.h>
+#include "Ui.h"
+
+
+void demoquit(void);
+void demoinfo(void);
+void demoopen(void);
+void demohelp(void);
+void demogetpage(char *nodename);
+
+
+void main(argc, argv)
+int   argc;
+char *argv[];
+{
+    if (UiInitialize(argc, argv) != UI_OK)
+    {
+       fprintf(stderr, "Error initializing Ui-toolkit\n");
+       exit(-1);
+    }
+
+    UiAttachCallback("Quit", demoquit);
+    UiAttachCallback("Info", demoinfo);
+    UiAttachCallback("Open", demoopen);
+    UiAttachCallback("Help", demohelp);
+
+    UiMainLoop();
+}
+
+
+void demoquit()
+{
+    printf("Quit me harder\n");
+
+    exit(0);
+}
+
+
+void demoinfo()
+{
+    printf("WWW-X-Client-Demo V0.000001ALPHA  (C) Copyright OHT-Erwise\n");
+}
+
+
+void demoopen()
+{
+    UiDisplaySelectionBox(demogetpage);
+}
+
+
+void demohelp()
+{
+    printf("Help my ass\n");
+}
+
+
+void demogetpage(nodename)
+char *nodename;
+{
+    void *hypetext = (void *) NULL;
+
+    printf("Retrieving page %s\n", nodename);
+    UiDisplayPage(nodename, hypetext);
+}
+@
+
+
+1.0
+log
+@Initial revision
+@
+text
+@d1 1
+a1 1
+static char *rcsid = "$Id$";
+d7 5
+a11 4
+void demoquit(void *parameter);
+void demoinfo(void *parameter);
+void demoopen(void *parameter);
+void demohelp(void *parameter);
+d24 4
+a27 4
+    UiAttachCallback("Quit", demoquit, (void *) "harder");
+    UiAttachCallback("Info", demoinfo, (void *) NULL);
+    UiAttachCallback("Open", demoopen, (void *) NULL);
+    UiAttachCallback("Help", demohelp, (void *) NULL);
+d33 1
+a33 2
+void demoquit(parameter)
+void *parameter;
+d35 1
+a35 1
+    printf("Quit me %s\n", (char *) parameter);
+d41 1
+a41 2
+void demoinfo(parameter)
+void *parameter;
+d47 1
+a47 2
+void demoopen(parameter)
+void *parameter;
+d49 1
+a49 1
+    UiDisplaySelectionBox(NULL);
+d53 1
+a53 2
+void demohelp(parameter)
+void *parameter;
+d56 10
+@
diff --git a/Ui/Ui.h b/Ui/Ui.h
new file mode 100644 (file)
index 0000000..d1e73e8
--- /dev/null
+++ b/Ui/Ui.h
@@ -0,0 +1,106 @@
+/* $Id: Ui.h,v 1.3 1992/04/28 00:34:53 kny Exp kny $ */
+
+
+#define UI_OK       0
+#define UI_ERROR    1
+#define UI_NOTFOUND 2
+
+#define UI_NONE  0
+#define UI_SHIFT 1
+#define UI_CTRL  4
+
+
+/*
+ * Config defines
+ */
+#define C_GLOBALSETTINGS  "GlobalSettings"
+
+#define C_TOPMARGIN      "topmargin"
+#define C_BOTTOMMARGIN   "bottommargin"
+#define C_LEFTMARGIN     "leftmargin"
+#define C_RIGHTMARGIN    "rightmargin"
+#define C_WIDTH          "width"
+#define C_HEIGHT         "height"
+#define C_ONEPAGEMODE     "onepagemode"
+#define C_FIXEDWIDTHMODE  "fixedwidthmode"
+#define C_FIXEDWIDTH      "fixedwidth"
+#define C_DOUBLECLICKTIME "doubleclicktime"
+
+#define C_SEARCH          "search"
+#define C_CONTROLPANEL    "controlpanel"
+#define C_LIST            "list"
+#define C_RECALL          "recall"
+#define C_PAGESETTINGS    "pagesettings"
+
+#define C_DEFAULTS        "Defaults"
+#define C_DEFAULTSTABLE   "defaultstable"
+
+
+typedef enum {
+    uiVTint,
+    uiVTdouble,
+    uiVTstring
+} uiVarType_t;
+
+
+extern int UiInitialize(int argc, char *argv[],
+                        void *(*configpf) (void *table, char *item),
+                        void *(*configsetpf) (void *table, char *item,
+                                               void *value));
+extern void UiMainLoop(void);
+
+extern int UiDisplaySelectionBox(void (*callback) (char *filename));
+
+extern int UiDisplayPage(char *address, HText_t * prevhtext, HText_t * htext,
+                         HTextObject_t * htextobject, char *title);
+extern int UiDeletePage(char *address, HText_t * htext);
+extern int UiSetCursor(char *address, HText_t * htext,
+                       HTextObject_t * htextobject);
+
+extern int UiDisplaySearchDialog(int type);
+
+extern int UiDisplayPageSettingsDialog(int type);
+
+extern int UiDisplayListDialog(char **listitems, char **addresses, int nitems,
+                               void (*callback) (char *topaddress,
+                                                  char *address,
+                                                  char *parentaddress));
+
+extern int UiDisplayRecallDialog(char **listitems, int nitems,
+                                 void (*callback) (char *topaddress,
+                                                    char *address,
+                                                  char *parentaddress));
+
+extern int UiAttachCallback(char *actionname,
+                            void (*callback) (char *address,
+                                               HText_t * htext,
+                                            HTextObject_t * htextobject,
+                                               void *parameter),
+                            void *parameter);
+extern int UiBindKey(char *keyname, int modifier,
+                     void (*callback) (char *address,
+                                        HText_t * htext,
+                                        HTextObject_t * htextobject,
+                                        void *parameter),
+                     void *parameter);
+extern int UiBindVariable(char *varname, void *variable, uiVarType_t type);
+extern int UiUpdateVariable(char *varname);
+extern void UiGetNextAction(void (*helponactioncb) (char *actionstring));
+extern int UiAddTimeOut(int timeout, void (*callback) (void *data),
+                        void *data);
+extern void UiDeleteTimeOut(int timoutid);
+extern int UiAddInputFD(int fd, void (*callback) (void *data), void *data);
+extern void UiDeleteInputFD(int inputid);
+extern void UiAddStringToCutBuffer(char *data);
+void UiDisplayPopup(void (*callback) (char *address, char *topaddress,
+                                      char *parentaddress),
+                    char *topaddress, char **items, int nitems);
+
+extern void UiShowInfo(void);
+
+extern int UiDisplayControlPanel(void);
+
+extern int UiDisplayFileSelection(void (*callback) (char *topaddress,
+                                                    HText_t * htext,
+                                            HTextObject_t * htextobject,
+                                                    void *parameter));
diff --git a/Ui/UiConnections.c b/Ui/UiConnections.c
new file mode 100644 (file)
index 0000000..8c2863d
--- /dev/null
@@ -0,0 +1,309 @@
+static char *rcsid = "$Id$";
+
+#include "UiIncludes.h"
+
+static Widget uicreateconnectionsform();
+static Widget uicreateconnectionslabel(Widget formwdg);
+static Widget uicreateconnectionskill(Widget formwdg);
+static Widget uicreateconnectionsclose(Widget formwdg);
+static Widget uicreateconnectionsseparator(Widget formwdg, Widget bottomwdg);
+static Widget
+ uicreateconnectionslist(Widget formwdg, Widget topwdg,
+                         Widget bottomwdg);
+static void uiconnectionsfreeprevious(void);
+static void uiconnectionssetitems(char **listitems, void **connections,
+                                  int nitems);
+static void uiconnectionskillcb(Widget wdg, caddr_t ignored,
+                                XmListCallbackStruct * calldata);
+static void uiconnectionsclosecb(Widget wdg, caddr_t ignored,
+                                 XmListCallbackStruct * calldata);
+
+
+static int uiconnectionsdisplayed = FALSE;
+static char **uilistitems;
+static void **uiconnections;
+static int uinitems;
+static void (*uiconnectionscallback) (void *connection);
+
+
+int UiDisplayConnectionsDialog(listitems, connections, nitems, callback)
+char **listitems;
+void **connections;
+int nitems;
+void (*callback) (void *connection);
+{
+    uiConnectionsGfx_t *connectionsgfx = &uiTopLevel.ConnectionsGfx;
+
+    uiconnectionsfreeprevious();
+
+    uiconnectionsdisplayed = TRUE;
+    uilistitems = listitems;
+    uiconnections = connections;
+    uinitems = nitems;
+    uiconnectionscallback = callback;
+
+    if (connectionsgfx->FormWdg) {
+       XtMapWidget(XtParent(connectionsgfx->FormWdg));
+       uiconnectionssetitems(listitems, connections, nitems);
+
+       return UI_OK;
+    }
+    connectionsgfx->FormWdg = uicreateconnectionsform();
+    connectionsgfx->LabelWdg =
+       uicreateconnectionslabel(connectionsgfx->FormWdg);
+    connectionsgfx->KillWdg =
+       uicreateconnectionskill(connectionsgfx->FormWdg);
+    connectionsgfx->CloseWdg =
+       uicreateconnectionsclose(connectionsgfx->FormWdg);
+    connectionsgfx->SeparatorWdg =
+       uicreateconnectionsseparator(connectionsgfx->FormWdg,
+                                    connectionsgfx->KillWdg);
+    connectionsgfx->ListWdg =
+       uicreateconnectionslist(connectionsgfx->FormWdg,
+                               connectionsgfx->LabelWdg,
+                               connectionsgfx->SeparatorWdg);
+
+    uiconnectionssetitems(listitems, connections, nitems);
+
+    XtManageChild(connectionsgfx->FormWdg);
+    XtRealizeWidget(XtParent(connectionsgfx->FormWdg));
+
+    return UI_OK;
+}
+
+
+int UiConnectionsDialogDisplayed()
+{
+    return uiconnectionsdisplayed;
+}
+
+
+void uiConnectionsUpdateDialog()
+{
+    if (!uiPageInfo.CurrentPage && uiTopLevel.ConnectionsGfx.FormWdg) {
+       uiconnectionsfreeprevious();
+       uiconnectionssetitems((char **) NULL, (void **) NULL, 0);
+       XtUnmapWidget(XtParent(uiTopLevel.ConnectionsGfx.FormWdg));
+    }
+}
+
+
+static Widget
+ uicreateconnectionsform()
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget formwdg;
+    Widget topwdg;
+
+    topwdg = XtCreateApplicationShell("Connections",
+                                     topLevelShellWidgetClass,
+                                     NULL, 0);
+    XtVaSetValues(topwdg,
+                 XmNtitle, UI_CONNECTIONS_TITLE, NULL);
+
+    args = uiVaSetArgs(&nargs,
+                      XmNresizePolicy, XmRESIZE_NONE,
+                      XmNautoUnmanage, FALSE, NULL);
+    formwdg = XmCreateForm(topwdg, "ConnectionsDialog",
+                          args, nargs);
+
+    return formwdg;
+}
+
+
+static Widget
+ uicreateconnectionslabel(formwdg)
+Widget formwdg;
+{
+    ArgList args;
+    Cardinal nargs;
+    XmString labelstr;
+    Widget labelwdg;
+
+    labelstr = XmStringCreateSimple("Open connections");
+    args = uiVaSetArgs(&nargs,
+                      XmNlabelString, labelstr,
+                      XmNtopAttachment, XmATTACH_FORM,
+                      XmNtopOffset, UI_CONNECTIONS_WDG_OFFSET,
+                      XmNleftAttachment, XmATTACH_FORM,
+                      XmNrightAttachment, XmATTACH_FORM, NULL);
+    labelwdg = XmCreateLabelGadget(formwdg, "ConnectionsLabel", args, nargs);
+    XtManageChild(labelwdg);
+    XmStringFree(labelstr);
+
+    return labelwdg;
+}
+
+
+static Widget
+ uicreateconnectionskill(formwdg)
+Widget formwdg;
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget killwdg;
+
+    args = uiVaSetArgs(&nargs,
+                      XmNleftAttachment, XmATTACH_POSITION,
+                      XmNleftPosition, 5,
+                      XmNrightAttachment, XmATTACH_POSITION,
+                      XmNrightPosition, 40,
+                      XmNbottomAttachment, XmATTACH_FORM,
+                      XmNbottomOffset, UI_CONNECTIONS_WDG_OFFSET, NULL);
+    killwdg = XmCreatePushButtonGadget(formwdg, "Kill", args, nargs);
+    XtAddCallback(killwdg, XmNactivateCallback,
+                 (XtCallbackProc) uiconnectionskillcb, (caddr_t) NULL);
+    XtManageChild(killwdg);
+
+    return killwdg;
+}
+
+
+static Widget
+ uicreateconnectionsclose(formwdg)
+Widget formwdg;
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget closewdg;
+
+    args = uiVaSetArgs(&nargs,
+                      XmNleftAttachment, XmATTACH_POSITION,
+                      XmNleftPosition, 60,
+                      XmNrightAttachment, XmATTACH_POSITION,
+                      XmNrightPosition, 95,
+                      XmNbottomAttachment, XmATTACH_FORM,
+                      XmNbottomOffset, UI_CONNECTIONS_WDG_OFFSET, NULL);
+    closewdg = XmCreatePushButtonGadget(formwdg, "Close", args, nargs);
+    XtAddCallback(closewdg, XmNactivateCallback,
+                 (XtCallbackProc) uiconnectionsclosecb, (caddr_t) NULL);
+    XtManageChild(closewdg);
+
+    return closewdg;
+}
+
+
+static Widget
+ uicreateconnectionsseparator(formwdg, bottomwdg)
+Widget formwdg;
+Widget bottomwdg;
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget separatorwdg;
+
+    args = uiVaSetArgs(&nargs,
+                      XmNbottomAttachment, XmATTACH_WIDGET,
+                      XmNbottomWidget, bottomwdg,
+                      XmNbottomOffset, UI_CONNECTIONS_WDG_OFFSET,
+                      XmNleftAttachment, XmATTACH_FORM,
+                      XmNrightAttachment, XmATTACH_FORM, NULL);
+    separatorwdg = XmCreateSeparatorGadget(formwdg, "ConnectionsSeparator",
+                                          args, nargs);
+    XtManageChild(separatorwdg);
+
+    return separatorwdg;
+}
+
+
+static Widget
+ uicreateconnectionslist(formwdg, topwdg, bottomwdg)
+Widget formwdg;
+Widget topwdg;
+Widget bottomwdg;
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget listwdg;
+
+    args = uiVaSetArgs(&nargs,
+                      XmNvisibleItemCount, 15,
+                      XmNwidth, 300,
+                      XmNselectionPolicy, XmSINGLE_SELECT,
+                      XmNlistSizePolicy, XmCONSTANT,
+                      XmNscrollBarDisplayPolicy, XmSTATIC,
+                      XmNtopAttachment, XmATTACH_WIDGET,
+                      XmNtopWidget, topwdg,
+                      XmNtopOffset, UI_CONNECTIONS_WDG_OFFSET,
+                      XmNbottomAttachment, XmATTACH_WIDGET,
+                      XmNbottomWidget, bottomwdg,
+                      XmNbottomOffset, UI_CONNECTIONS_WDG_OFFSET,
+                      XmNrightAttachment, XmATTACH_FORM,
+                      XmNrightOffset, UI_CONNECTIONS_WDG_OFFSET,
+                      XmNleftAttachment, XmATTACH_FORM,
+                      XmNleftOffset, UI_CONNECTIONS_WDG_OFFSET, NULL);
+    listwdg = XmCreateScrolledList(formwdg, "ConnectionsList", args, nargs);
+    XtManageChild(listwdg);
+    XtAddCallback(listwdg, XmNdefaultActionCallback,
+                 (XtCallbackProc) uiconnectionskillcb, (caddr_t) NULL);
+
+    return listwdg;
+}
+
+
+void uiconnectionsfreeprevious()
+{
+    if (uinitems)
+       uiFree(uilistitems);
+}
+
+
+static void uiconnectionssetitems(listitems, connections, nitems)
+char **listitems;
+void **connections;
+int nitems;
+{
+    Widget listwdg = uiTopLevel.ConnectionsGfx.ListWdg;
+    int i;
+    XmString *tmpstr = uiMalloc(nitems * sizeof(XmString));
+
+    XmListDeleteAllItems(listwdg);
+    if (nitems) {
+       for (i = 0; i < nitems; i++)
+           tmpstr[i] = XmStringCreateSimple(listitems[i]);
+
+       XmListAddItems(listwdg, tmpstr, nitems, 0);
+       for (i = 0; i < nitems; i++)
+           XmStringFree(tmpstr[i]);
+       uiFree((void *) tmpstr);
+    }
+}
+
+
+
+
+static void uiconnectionskillcb(wdg, ignored, calldata)
+Widget wdg;
+caddr_t ignored;
+XmListCallbackStruct *calldata;
+{
+    Widget connectionswdg = uiTopLevel.ConnectionsGfx.ListWdg;
+    int *poslist;
+    int poscount;
+    char *parentaddress;
+
+    if (uinitems)
+       if (XmListGetSelectedPos(connectionswdg, &poslist, &poscount)) {
+           uiDefineCursor(uiBusyCursor);
+           if (uiHelpOnActionCB) {
+               (*uiHelpOnActionCB) ("Kill connection");
+               uiHelpOnActionCB = (void (*) (char *actionstring)) NULL;
+           } else
+               (*uiconnectionscallback) (uiconnections[poslist[0] - 1]);
+
+           uiUndefineCursor();
+
+           XtFree(poslist);
+       }
+}
+
+
+static void uiconnectionsclosecb(wdg, ignored, calldata)
+Widget wdg;
+caddr_t ignored;
+XmListCallbackStruct *calldata;
+{
+    XtUnmapWidget(XtParent(uiTopLevel.ConnectionsGfx.FormWdg));
+    uiconnectionsdisplayed = FALSE;
+}
diff --git a/Ui/UiControlPanel.c b/Ui/UiControlPanel.c
new file mode 100644 (file)
index 0000000..09053e1
--- /dev/null
@@ -0,0 +1,244 @@
+static char *rcsid = "$Id$";
+
+#include "UiIncludes.h"
+
+static Widget uicreatecpform();
+static Widget
+ uicreatecpbutton(Widget parentwdg, char *name, char *actionname,
+                  int leftpos, int rightpos);
+static Widget uicreatecpclosebutton(Widget parentwdg);
+static Widget uicreatecplabel(Widget parentwdg, Widget rightwdg);
+static Widget uicreatecplist(Widget parentwdg, Widget bottomwdg,
+                             Widget topwdg);
+static void uicpclosecb(char *address, HText_t * htext,
+                        HTextObject_t * htextobject, void *parameter);
+static void uicpclickcb(Widget wdg, caddr_t ignored,
+                        XmListCallbackStruct * calldata);
+
+
+uiTopLevel_t uiTopLevel;
+
+
+int UiDisplayControlPanel()
+{
+    ArgList args;
+    Cardinal nargs;
+    uiTopLevelGfx_t *topgfx = &uiTopLevel.TopGfx;
+    uiControlPanelGfx_t *controlpanelgfx = &uiTopLevel.ControlPanelGfx;
+
+    if (controlpanelgfx->FormWdg) {
+       XtMapWidget(XtParent(controlpanelgfx->FormWdg));
+
+       uiWidgetPlacement(XtParent(controlpanelgfx->FormWdg),
+                       uiTopLevel.GlobalSettings.ControlPanelPlacement);
+
+       return UI_OK;
+    }
+    args = uiVaSetArgs(&nargs,
+                      XmNwidth, 280,
+                      XmNheight, 180,
+                      XmNresizePolicy, XmRESIZE_NONE,
+                      XmNautoUnmanage, FALSE, NULL);
+    controlpanelgfx->FormWdg = uicreatecpform();
+    controlpanelgfx->SearchWdg = uicreatecpbutton(controlpanelgfx->FormWdg,
+                                             "Search", "Search", 0, 25);
+    controlpanelgfx->HomeWdg = uicreatecpbutton(controlpanelgfx->FormWdg,
+                                               "Home", "Home", 25, 50);
+    controlpanelgfx->RecallWdg = uicreatecpbutton(controlpanelgfx->FormWdg,
+                                            "Recall", "Recall", 50, 75);
+    controlpanelgfx->CloseWdg = uicreatecpbutton(controlpanelgfx->FormWdg,
+                                                "Close\nhierarchy",
+                                            "Close hierarchy", 75, 100);
+    controlpanelgfx->DialogCloseWdg =
+       uicreatecpclosebutton(controlpanelgfx->FormWdg);
+    controlpanelgfx->LabelWdg =
+       uicreatecplabel(controlpanelgfx->FormWdg,
+                       controlpanelgfx->DialogCloseWdg);
+    controlpanelgfx->ListWdg = uicreatecplist(controlpanelgfx->FormWdg,
+                                             controlpanelgfx->SearchWdg,
+                                       controlpanelgfx->DialogCloseWdg);
+    XtManageChild(controlpanelgfx->FormWdg);
+    XtRealizeWidget(XtParent(controlpanelgfx->FormWdg));
+
+    uiWidgetPlacement(XtParent(controlpanelgfx->FormWdg),
+                     uiTopLevel.GlobalSettings.ControlPanelPlacement);
+
+    return UI_OK;
+}
+
+
+void uiControlPanelUpdateDialog()
+{
+    if (uiTopLevel.ControlPanelGfx.FormWdg) {
+       if (uiPageInfo.CurrentPage) {
+       } else
+           XtUnmapWidget(XtParent(uiTopLevel.ControlPanelGfx.FormWdg));
+    }
+}
+
+
+static Widget
+ uicreatecpform()
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget formwdg;
+    Widget topwdg;
+
+    topwdg = XtCreateApplicationShell("ControlPanel",
+                                     topLevelShellWidgetClass,
+                                     NULL, 0);
+    XtVaSetValues(topwdg,
+                 XmNtitle, UI_CONTROL_TITLE, NULL);
+
+    args = uiVaSetArgs(&nargs,
+                      XmNresizePolicy, XmRESIZE_NONE,
+                      XmNautoUnmanage, FALSE, NULL);
+    formwdg = XmCreateForm(topwdg, "ControlPanel", args, nargs);
+
+    return formwdg;
+}
+
+
+static Widget
+ uicreatecpbutton(parentwdg, name, actionname, leftpos, rightpos)
+Widget parentwdg;
+char *name;
+char *actionname;
+int leftpos;
+int rightpos;
+{
+    Widget tmpwdg;
+    uiActionData_t *actiondata = uiMalloc(sizeof(*actiondata));
+
+    tmpwdg = XmCreatePushButtonGadget(parentwdg, name,
+                                     (ArgList) NULL, 0);
+    XtVaSetValues(tmpwdg,
+                 XmNheight, 65,
+                 XmNtopAttachment, XmATTACH_FORM,
+                 XmNleftAttachment, XmATTACH_POSITION,
+                 XmNleftPosition, leftpos,
+                 XmNrightAttachment, XmATTACH_POSITION,
+                 XmNrightPosition, rightpos, NULL);
+    actiondata->ActionName = actionname;
+    actiondata->Page = uiPageInfo.CurrentPage;
+    XtAddCallback(tmpwdg, XmNactivateCallback,
+             (XtCallbackProc) uiDialogActivateCB, (caddr_t) actiondata);
+    XtManageChild(tmpwdg);
+
+    return tmpwdg;
+}
+
+
+static Widget
+ uicreatecpclosebutton(parentwdg)
+Widget parentwdg;
+{
+    Widget tmpwdg;
+    static uiActionData_t actiondata;
+
+    tmpwdg = XmCreatePushButtonGadget(parentwdg, "Close", (ArgList) NULL, 0);
+    XtVaSetValues(tmpwdg,
+                 XmNwidth, 70,
+                 XmNbottomAttachment, XmATTACH_FORM,
+                 XmNbottomOffset, UI_CP_WDG_OFFSET,
+                 XmNrightAttachment, XmATTACH_FORM,
+                 XmNrightOffset, UI_CP_WDG_OFFSET, NULL);
+    actiondata.ActionName = "CpClose";
+    actiondata.Page = uiPageInfo.CurrentPage;
+    XtAddCallback(tmpwdg, XmNactivateCallback,
+           (XtCallbackProc) uiDialogActivateCB, (caddr_t) & actiondata);
+    UiAttachCallback("CpClose", uicpclosecb, "CpClose");
+
+    XtManageChild(tmpwdg);
+
+    return tmpwdg;
+}
+
+
+static Widget
+ uicreatecplabel(parentwdg, rightwdg)
+Widget parentwdg;
+Widget rightwdg;
+{
+    Widget tmpwdg;
+
+    tmpwdg = XmCreateLabelGadget(parentwdg, "ControlPanelLabel",
+                                (ArgList) NULL, 0);
+    XtVaSetValues(tmpwdg,
+                 XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
+                 XmNbottomWidget, rightwdg,
+                 XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
+                 XmNtopWidget, rightwdg,
+                 XmNrightAttachment, XmATTACH_WIDGET,
+                 XmNrightWidget, rightwdg,
+                 XmNrightOffset, UI_CP_WDG_OFFSET,
+                 XmNleftAttachment, XmATTACH_FORM,
+                 XmNleftOffset, UI_CP_WDG_OFFSET, NULL);
+
+    XtManageChild(tmpwdg);
+
+    return tmpwdg;
+}
+
+
+static Widget
+ uicreatecplist(formwdg, topwdg, bottomwdg)
+Widget formwdg;
+Widget topwdg;
+Widget bottomwdg;
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget listwdg;
+    uiHierarchy_t *hierarchy = uiTopLevel.Hierarchies;
+    XmString dummystr;
+
+    args = uiVaSetArgs(&nargs,
+                      XmNvisibleItemCount, 5,
+                      XmNselectionPolicy, XmSINGLE_SELECT,
+                      XmNlistSizePolicy, XmCONSTANT,
+                      XmNscrollBarDisplayPolicy, XmSTATIC,
+                      XmNtopAttachment, XmATTACH_WIDGET,
+                      XmNtopWidget, topwdg,
+                      XmNtopOffset, UI_CP_WDG_OFFSET,
+                      XmNbottomAttachment, XmATTACH_WIDGET,
+                      XmNbottomWidget, bottomwdg,
+                      XmNbottomOffset, UI_CP_WDG_OFFSET,
+                      XmNrightAttachment, XmATTACH_FORM,
+                      XmNrightOffset, UI_CP_WDG_OFFSET,
+                      XmNleftAttachment, XmATTACH_FORM,
+                      XmNleftOffset, UI_CP_WDG_OFFSET, NULL);
+    listwdg = XmCreateScrolledList(formwdg, "CpList", args, nargs);
+    XtManageChild(listwdg);
+
+    while (hierarchy) {
+       dummystr = XmStringCreateSimple(hierarchy->Address);
+       XmListAddItem(listwdg, dummystr, 0);
+       XmStringFree(dummystr);
+       hierarchy = hierarchy->Next;
+    }
+
+    return listwdg;
+}
+
+
+static void uicpclickcb(wdg, ignored, calldata)
+Widget wdg;
+caddr_t ignored;
+XmListCallbackStruct *calldata;
+{
+    char *selection;
+
+    XmStringGetLtoR(calldata->item, XmSTRING_DEFAULT_CHARSET, &selection);
+}
+
+
+static void uicpclosecb(address, htext, htextobject, parameter)
+char *address;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    XtUnmapWidget(XtParent(uiTopLevel.ControlPanelGfx.FormWdg));
+}
diff --git a/Ui/UiDefaults.c b/Ui/UiDefaults.c
new file mode 100644 (file)
index 0000000..a2c6892
--- /dev/null
@@ -0,0 +1,262 @@
+static char *rcsid = "$Id$";
+
+#include "UiIncludes.h"
+
+static void uibinddefaultsvariables(void);
+static void uiupdatedefaultsvariables(void);
+static Widget uicreatedefaultsformdialog();
+static Widget uicreatedefaultslabel(Widget parent, Widget bottomwdg);
+static Widget
+ uicreatedefaultsitem(char *name, Widget parent,
+                      Widget bottomwdg);
+static Widget uicreatedefaultsclose(Widget parent);
+static void uidefaultsclosecb(char *address, HText_t * htext,
+                          HTextObject_t * htextobject, void *parameter);
+
+
+int UiDisplayDefaultsDialog()
+{
+    uiDefaultsGfx_t *defaultsgfx = &uiTopLevel.DefaultsGfx;
+
+    uibinddefaultsvariables();
+
+    if (defaultsgfx->FormWdg) {
+       XtMapWidget(XtParent(defaultsgfx->FormWdg));
+
+       uiupdatedefaultsvariables();
+
+       return UI_OK;
+    }
+    defaultsgfx->FormWdg = uicreatedefaultsformdialog();
+    defaultsgfx->CloseWdg = uicreatedefaultsclose(defaultsgfx->FormWdg);
+    defaultsgfx->PageSettings = uicreatedefaultsitem("Page Settings window",
+                                                    defaultsgfx->FormWdg,
+                                                 defaultsgfx->CloseWdg);
+    defaultsgfx->RecallWindow =
+       uicreatedefaultsitem("Recall window",
+                            defaultsgfx->FormWdg,
+                            defaultsgfx->PageSettings);
+    defaultsgfx->ListWindow = uicreatedefaultsitem("List window",
+                                                  defaultsgfx->FormWdg,
+                                             defaultsgfx->RecallWindow);
+    defaultsgfx->ControlPanel = uicreatedefaultsitem("Control panel",
+                                                    defaultsgfx->FormWdg,
+                                               defaultsgfx->ListWindow);
+    defaultsgfx->SearchWindow =
+       uicreatedefaultsitem("Search window", defaultsgfx->FormWdg,
+                            defaultsgfx->ControlPanel);
+    defaultsgfx->LabelWdg = uicreatedefaultslabel(defaultsgfx->FormWdg,
+                                             defaultsgfx->SearchWindow);
+
+    XtManageChild(defaultsgfx->FormWdg);
+    XtRealizeWidget(XtParent(defaultsgfx->FormWdg));
+
+    uiupdatedefaultsvariables();
+
+    return UI_OK;
+}
+
+
+void uiDefaultsUpdateDialog()
+{
+    if (uiTopLevel.DefaultsGfx.FormWdg) {
+       if (uiPageInfo.CurrentPage) {
+           uibinddefaultsvariables();
+           uiupdatedefaultsvariables();
+       } else
+           XtUnmapWidget(XtParent(uiTopLevel.DefaultsGfx.FormWdg));
+    }
+}
+
+
+static void uibinddefaultsvariables()
+{
+    UiBindVariable("Page Settings window",
+              (void *) &uiTopLevel.GlobalSettings.PageSettingsPlacement,
+                  uiVTint);
+    UiBindVariable("Recall window",
+                  (void *) &uiTopLevel.GlobalSettings.RecallPlacement,
+                  uiVTint);
+    UiBindVariable("List window",
+                  (void *) &uiTopLevel.GlobalSettings.ListPlacement,
+                  uiVTint);
+    UiBindVariable("Control panel",
+              (void *) &uiTopLevel.GlobalSettings.ControlPanelPlacement,
+                  uiVTint);
+    UiBindVariable("Search window",
+                  (void *) &uiTopLevel.GlobalSettings.SearchPlacement,
+                  uiVTint);
+}
+
+
+static void uiupdatedefaultsvariables()
+{
+    UiUpdateVariable("Page Settings window");
+    UiUpdateVariable("Recall window");
+    UiUpdateVariable("List window");
+    UiUpdateVariable("Control panel");
+    UiUpdateVariable("Search window");
+}
+
+
+static Widget
+ uicreatedefaultsformdialog()
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget formwdg;
+    Widget topwdg;
+
+    topwdg = XtCreateApplicationShell("Defaults",
+                                     topLevelShellWidgetClass,
+                                     NULL, 0);
+    XtVaSetValues(topwdg,
+                 XmNtitle, UI_DEFAULTS_TITLE, NULL);
+
+    args = uiVaSetArgs(&nargs,
+                      XmNresizePolicy, XmRESIZE_NONE,
+                      XmNautoUnmanage, FALSE, NULL);
+    formwdg = XmCreateForm(topwdg, "Defaults", args, nargs);
+
+    return formwdg;
+}
+
+static Widget
+ uicreatedefaultslabel(parent, bottomwdg)
+Widget parent;
+Widget bottomwdg;
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget labelwdg;
+    XmString labelstr;
+
+    labelstr = XmStringCreateSimple("Follow pointer");
+
+    args = uiVaSetArgs(&nargs,
+                      XmNlabelString, labelstr,
+                      XmNtopAttachment, XmATTACH_FORM,
+                      XmNtopOffset, UI_DEFAULTS_WDG_OFFSET,
+                      XmNbottomAttachment, XmATTACH_WIDGET,
+                      XmNbottomWidget, bottomwdg,
+                      XmNbottomOffset, UI_DEFAULTS_WDG_OFFSET,
+                      XmNleftAttachment, XmATTACH_FORM,
+                      XmNrightAttachment, XmATTACH_FORM, NULL);
+    labelwdg = XmCreateLabelGadget(parent, "DEFAULTSLabel", args, nargs);
+    XtManageChild(labelwdg);
+
+    return labelwdg;
+}
+
+
+static Widget
+ uicreatedefaultsitem(name, parent, bottomwdg)
+char *name;
+Widget parent;
+Widget bottomwdg;
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget formwdg;
+    Widget togglewdg;
+    static uiActionData_t actiondata;
+
+    args = uiVaSetArgs(&nargs,
+                      XmNbottomAttachment, XmATTACH_WIDGET,
+                      XmNbottomWidget, bottomwdg,
+                      XmNbottomOffset, UI_DEFAULTS_WDG_OFFSET,
+                      XmNleftAttachment, XmATTACH_FORM,
+                      XmNrightAttachment, XmATTACH_FORM, NULL);
+    formwdg = XmCreateForm(parent, name, args, nargs);
+    XtManageChild(formwdg);
+
+    togglewdg = XmCreateToggleButtonGadget(formwdg, name,
+                                          (ArgList) NULL, 0);
+    XtVaSetValues(togglewdg,
+                 XmNbottomAttachment, XmATTACH_FORM,
+                 XmNtopAttachment, XmATTACH_FORM,
+                 XmNleftAttachment, XmATTACH_FORM,
+                 XmNleftOffset, UI_DEFAULTS_WDG_OFFSET,
+                 XmNrightAttachment, XmATTACH_FORM,
+                 XmNrightOffset, UI_DEFAULTS_WDG_OFFSET, NULL);
+    XtAddCallback(togglewdg, XmNvalueChangedCallback,
+                 (XtCallbackProc) uiDialogVariableCB, (caddr_t) name);
+    /* Ignore */
+    (void) uiAddWidgetInfo(name, togglewdg, uiWTcheckbutton);
+    XtManageChild(togglewdg);
+
+    return formwdg;
+}
+
+
+static Widget
+ uicreatedefaultsclose(parent)
+Widget parent;
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget separatorwdg;
+    Widget tmpwdg;
+    static uiActionData_t actiondata;
+
+    tmpwdg = XmCreatePushButtonGadget(parent, "Close", (ArgList) NULL, 0);
+    XtVaSetValues(tmpwdg,
+                 XmNwidth, 70,
+                 XmNbottomAttachment, XmATTACH_FORM,
+                 XmNbottomOffset, UI_DEFAULTS_WDG_OFFSET,
+                 XmNrightAttachment, XmATTACH_FORM,
+                 XmNrightOffset, UI_DEFAULTS_WDG_OFFSET, NULL);
+    actiondata.ActionName = "DefaultsClose";
+    actiondata.Page = uiPageInfo.CurrentPage;
+    XtAddCallback(tmpwdg, XmNactivateCallback,
+           (XtCallbackProc) uiDialogActivateCB, (caddr_t) & actiondata);
+    UiAttachCallback("DefaultsClose", uidefaultsclosecb,
+                    "DefaultsGfx.FormWdg");
+
+    XtManageChild(tmpwdg);
+
+    args = uiVaSetArgs(&nargs,
+                      XmNbottomAttachment, XmATTACH_WIDGET,
+                      XmNbottomWidget, tmpwdg,
+                      XmNbottomOffset, UI_DEFAULTS_WDG_OFFSET,
+                      XmNleftAttachment, XmATTACH_FORM,
+                      XmNrightAttachment, XmATTACH_FORM, NULL);
+    separatorwdg = XmCreateSeparatorGadget(parent, "DefaultsSeparator",
+                                          args, nargs);
+    XtManageChild(separatorwdg);
+
+    return separatorwdg;
+}
+
+
+static void setplacementvalue(uiconfigsetfp, table, item, placementvalue)
+void *(*uiconfigsetfp) (void *table, char *item, void *value);
+void *table;
+char *item;
+int placementvalue;
+{
+    if (placementvalue)
+       uiconfigsetfp(table, item, "Mouse");
+    else
+       uiconfigsetfp(table, item, "Fixed");
+}
+
+
+static void uidefaultsclosecb(address, htext, htextobject, parameter)
+char *address;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    uiGlobalSettings_t *gs = &uiTopLevel.GlobalSettings;
+    void *table;
+
+    table = uiConfigPF((void *) NULL, C_GLOBALSETTINGS);
+    setplacementvalue(uiConfigSetPF, table, C_SEARCH, gs->SearchPlacement);
+    setplacementvalue(uiConfigSetPF, table, C_CONTROLPANEL, gs->ControlPanelPlacement);
+    setplacementvalue(uiConfigSetPF, table, C_LIST, gs->ListPlacement);
+    setplacementvalue(uiConfigSetPF, table, C_RECALL, gs->RecallPlacement);
+    setplacementvalue(uiConfigSetPF, table, C_PAGESETTINGS, gs->PageSettingsPlacement);
+
+    XtUnmapWidget(XtParent(uiTopLevel.DefaultsGfx.FormWdg));
+}
diff --git a/Ui/UiDefs.h b/Ui/UiDefs.h
new file mode 100644 (file)
index 0000000..a0943f9
--- /dev/null
@@ -0,0 +1,37 @@
+/* $Id: UiDefs.h,v 1.2 1992/04/05 11:44:09 kss Exp kny $ */
+
+
+#define UI_INVALID (-1)
+
+#define UI_SEARCH_WDG_OFFSET       10
+#define UI_PAGESETTINGS_WDG_OFFSET 10
+#define UI_LIST_WDG_OFFSET         10
+#define UI_INFO_WDG_OFFSET         10
+#define UI_CP_WDG_OFFSET           10
+#define UI_DEFAULTS_WDG_OFFSET     10
+#define UI_PRINT_WDG_OFFSET        10
+#define UI_CONNECTIONS_WDG_OFFSET        10
+
+#define UI_LEFT  0
+#define UI_RIGHT 1
+#define UI_UP    2
+#define UI_DOWN  3
+
+#define UI_HSCROLLBAR "HScrollBar"
+#define UI_VSCROLLBAR "VScrollBar"
+
+#define UI_ERWISE_TITLE "Erwise"
+#define UI_SEARCH_TITLE "Text search"
+#define UI_LIST_TITLE "List of tags"
+#define UI_PRINT_TITLE "Print"
+#define UI_SETTINGS_TITLE "Page settings"
+#define UI_RECALL_TITLE "Browsed documents"
+#define UI_CONTROL_TITLE "Control panel"
+#define UI_CONNECTIONS_TITLE "Open connections"
+#define UI_DEFAULTS_TITLE "Defaults"
+
+#define ui_VALID(x) ((x) != (-1))
+#define ui_INVALID(x) ((x) == (-1))
+
+#define ui_HELPMENU(x) (!strcmp(x, "Help"))
+#define ui_TOGGLE(x) ((x)[-1] == '*')
diff --git a/Ui/UiFileSelection.c b/Ui/UiFileSelection.c
new file mode 100644 (file)
index 0000000..a880c2f
--- /dev/null
@@ -0,0 +1,150 @@
+static char *rcsid = "$Id$";
+
+#include "UiIncludes.h"
+
+
+static Widget uicreatefsformdialog();
+static Widget
+ uicreatefsfsbox(Widget formwdg,
+                 void (*callback) (char *topaddress,
+                                    HText_t * htext,
+                                    HTextObject_t * htextobject,
+                                    void *parameter));
+static void uifileselectionokcb(Widget wdg, caddr_t callback,
+                                XmPushButtonCallbackStruct * calldata);
+static void uifileselectioncancelcb(Widget wdg, caddr_t ignored,
+                                 XmPushButtonCallbackStruct * calldata);
+static void uifileselectionclickcb(Widget wdg, caddr_t ignored,
+                                   XmListCallbackStruct * calldata);
+
+
+uiTopLevel_t uiTopLevel;
+
+
+int UiDisplayFileSelection(callback)
+void (*callback) (char *topaddress, HText_t * htext, HTextObject_t * htextobject,
+                  void *parameter);
+{
+    uiFileSelectionGfx_t *fsgfx = &uiTopLevel.FSGfx;
+
+    if (fsgfx->FormWdg) {
+       XtMapWidget(XtParent(fsgfx->FormWdg));
+
+       return UI_OK;
+    }
+    fsgfx->FormWdg = uicreatefsformdialog();
+    fsgfx->FSBoxWdg = uicreatefsfsbox(fsgfx->FormWdg, callback);
+
+    XtManageChild(fsgfx->FormWdg);
+    XtRealizeWidget(XtParent(fsgfx->FormWdg));
+
+    return UI_OK;
+}
+
+
+static Widget
+ uicreatefsformdialog()
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget formwdg;
+    Widget topwdg;
+
+    topwdg = XtCreateApplicationShell("FileSelection",
+                                     topLevelShellWidgetClass,
+                                     NULL, 0);
+
+    args = uiVaSetArgs(&nargs,
+                      XmNresizePolicy, XmRESIZE_NONE,
+                      XmNautoUnmanage, FALSE, NULL);
+    formwdg = XmCreateForm(topwdg, "FileSelection",
+                          args, nargs);
+
+    return formwdg;
+}
+
+
+static Widget
+ uicreatefsfsbox(formwdg, callback)
+Widget formwdg;
+void (*callback) (char *topaddress, HText_t * htext,
+                  HTextObject_t * htextobject, void *parameter);
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget fsboxwdg, textwdg, okwdg, cancelwdg;
+
+    args = uiVaSetArgs(&nargs,
+                      XmNtopAttachment, XmATTACH_FORM,
+                      XmNtopOffset, 1,
+                      XmNleftAttachment, XmATTACH_FORM,
+                      XmNleftOffset, 1,
+                      XmNrightAttachment, XmATTACH_FORM,
+                      XmNrightOffset, 1,
+                      XmNbottomOffset, 1,
+                      XmNbottomAttachment, XmATTACH_FORM, NULL);
+    fsboxwdg = XmCreateFileSelectionBox(formwdg, "FSBox",
+                                       args, nargs);
+    XtUnmanageChild(XmFileSelectionBoxGetChild(fsboxwdg,
+                                              XmDIALOG_HELP_BUTTON));
+
+    textwdg = XmFileSelectionBoxGetChild(fsboxwdg, XmDIALOG_TEXT);
+    XmTextSetString(textwdg, "");
+
+    okwdg = XmFileSelectionBoxGetChild(fsboxwdg, XmDIALOG_OK_BUTTON);
+    XtAddCallback(okwdg, XmNactivateCallback, uifileselectionokcb,
+                 (caddr_t) callback);
+
+    cancelwdg = XmFileSelectionBoxGetChild(fsboxwdg, XmDIALOG_CANCEL_BUTTON);
+    XtAddCallback(cancelwdg, XmNactivateCallback, uifileselectioncancelcb,
+                 (caddr_t) NULL);
+    XtManageChild(fsboxwdg);
+
+    return fsboxwdg;
+}
+
+
+static void uifileselectionokcb(wdg, callback, calldata)
+Widget wdg;
+caddr_t callback;
+XmPushButtonCallbackStruct *calldata;
+{
+    Widget textwdg;
+    char *selection;
+
+    textwdg = XmFileSelectionBoxGetChild(uiTopLevel.FSGfx.FSBoxWdg,
+                                        XmDIALOG_TEXT);
+    selection = XmTextGetString(textwdg);
+    XtUnmapWidget(XtParent(uiTopLevel.FSGfx.FormWdg));
+    (*(void (*) (char *, HText_t *, HTextObject_t *, void *)) callback)
+       (uiPageInfo.CurrentPage->Hierarchy->Address,
+      uiPageInfo.CurrentPage->HText, uiPageInfo.CurrentPage->HTextObject,
+        (void *) selection);
+
+    XtFree(selection);
+}
+
+
+static void uifileselectioncancelcb(wdg, ignored, calldata)
+Widget wdg;
+caddr_t ignored;
+XmPushButtonCallbackStruct *calldata;
+{
+    XtUnmapWidget(XtParent(uiTopLevel.FSGfx.FormWdg));
+}
+
+
+static void uifileselectionclickcb(wdg, ignored, calldata)
+Widget wdg;
+caddr_t ignored;
+XmListCallbackStruct *calldata;
+{
+    Widget textwdg;
+    char *selection;
+
+    XmStringGetLtoR(calldata->item, XmSTRING_DEFAULT_CHARSET, &selection);
+    textwdg = XmFileSelectionBoxGetChild(uiTopLevel.FSGfx.FSBoxWdg,
+                                        XmDIALOG_TEXT);
+    XmTextSetString(textwdg, selection);
+    XtFree(selection);
+}
diff --git a/Ui/UiIncludes.h b/Ui/UiIncludes.h
new file mode 100644 (file)
index 0000000..a34d59c
--- /dev/null
@@ -0,0 +1,39 @@
+/* $Id: UiIncludes.h,v 1.3 1992/03/26 18:13:50 kny Exp kny $ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <varargs.h>
+
+#include <X11/Intrinsic.h>
+#include <X11/cursorfont.h>
+#include <X11/keysym.h>
+#include <Xm/Xm.h>
+#include <Xm/ArrowBG.h>
+#include <Xm/CascadeBG.h>
+#include <Xm/DrawingA.h>
+#include <Xm/FileSB.h>
+#include <Xm/Form.h>
+#include <Xm/Frame.h>
+#include <Xm/LabelG.h>
+#include <Xm/List.h>
+#include <Xm/MenuShell.h>
+#include <Xm/MessageB.h>
+#include <Xm/PushBG.h>
+#include <Xm/RowColumn.h>
+#include <Xm/ScrollBar.h>
+#include <Xm/ScrolledW.h>
+#include <Xm/SeparatoG.h>
+#include <Xm/Text.h>
+#include <Xm/ToggleBG.h>
+
+#include "HTAnchor.h"
+#include "HTStyle.h"
+#include "HText.h"
+
+#include "Xl.h"
+#include "Ui.h"
+#include "UiDefs.h"
+#include "UiTypes.h"
+#include "UiProtos.h"
diff --git a/Ui/UiInfo.c b/Ui/UiInfo.c
new file mode 100644 (file)
index 0000000..4c13503
--- /dev/null
@@ -0,0 +1,252 @@
+static char *rcsid = "$Id: UiInfo.c,v 1.1 1992/03/26 18:13:50 kny Exp kny $";
+
+
+#include "UiIncludes.h"
+
+#define logo_width 90
+#define logo_height 90
+static char logo_bits[] =
+{
+  0x00, 0x00, 0x00, 0x00, 0xd8, 0xcf, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xc0, 0xff, 0x01, 0xc0, 0x02, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xa0, 0x7f, 0x00, 0x2e, 0x0f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xd8, 0x4f, 0x01, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xe7, 0xa0, 0x80, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x31, 0x00, 0xc4, 0xef, 0xff, 0x07, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xe0, 0x00, 0x00, 0x84, 0xef, 0xff, 0x0f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x70, 0x00, 0x00, 0x0c, 0xce, 0xff, 0x3f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x7c, 0x00, 0x00, 0x9f, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x3e, 0x00, 0x00, 0xfd, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
+  0x00, 0x80, 0x1f, 0x00, 0x00, 0xf4, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00,
+  0x00, 0x80, 0x13, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00,
+  0x00, 0xe0, 0x09, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00,
+  0x00, 0xe0, 0x00, 0x00, 0x00, 0xfa, 0xed, 0xff, 0xff, 0x1f, 0x00, 0x00,
+  0x00, 0x38, 0x00, 0x00, 0x80, 0x3f, 0x9c, 0xff, 0xff, 0x3f, 0x00, 0x00,
+  0x00, 0x08, 0x00, 0x00, 0x80, 0x5f, 0x62, 0xff, 0xff, 0x7f, 0x00, 0x00,
+  0x00, 0x0c, 0x00, 0x00, 0x80, 0x1f, 0x40, 0xf6, 0xff, 0xff, 0x00, 0x00,
+  0x00, 0x02, 0x00, 0x00, 0x00, 0xaf, 0x36, 0xe8, 0xff, 0xff, 0x00, 0x00,
+  0x00, 0x03, 0x00, 0x00, 0x00, 0xfa, 0x0f, 0x14, 0xfd, 0xff, 0x01, 0x00,
+  0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0xfc, 0xff, 0x03, 0x00,
+  0x80, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x3f, 0x0c, 0xfc, 0xff, 0x07, 0x00,
+  0x40, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xfd, 0xff, 0xff, 0x07, 0x00,
+  0x40, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00,
+  0x20, 0x00, 0x00, 0x00, 0xf2, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x0f, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xf7, 0xef, 0x1f, 0x00,
+  0x30, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xef, 0x9f, 0x1f, 0x00,
+  0x18, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x38, 0x00,
+  0x18, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xbf, 0xff, 0x38, 0x00,
+  0x1c, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0x71, 0x00,
+  0x14, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x7f, 0xff, 0x61, 0x00,
+  0x5a, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x7f, 0xfe, 0x61, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xc0, 0x00,
+  0x41, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7d, 0xc0, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x80, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xfe, 0x07, 0xff, 0x81, 0x80, 0x08, 0x08, 0x02, 0xff, 0xc1, 0xff, 0x00,
+  0xff, 0x8f, 0xff, 0xc3, 0xc1, 0x1d, 0x1c, 0x87, 0xff, 0xe3, 0xff, 0x01,
+  0xff, 0x87, 0xff, 0xc7, 0xc1, 0x1d, 0x1c, 0xc7, 0xff, 0xe1, 0xff, 0x00,
+  0x07, 0x80, 0x03, 0x87, 0x83, 0x0f, 0x0e, 0xc7, 0x01, 0xe0, 0x00, 0x00,
+  0x07, 0x80, 0x03, 0x87, 0x83, 0x0f, 0x0e, 0xc7, 0x01, 0xe0, 0x00, 0x00,
+  0x07, 0x80, 0x03, 0x87, 0x83, 0x0f, 0x0e, 0xc7, 0x01, 0xe0, 0x00, 0x00,
+  0x07, 0x80, 0x03, 0x07, 0x07, 0x07, 0x07, 0xc7, 0x01, 0xe0, 0x00, 0x00,
+  0x7f, 0x80, 0xff, 0x07, 0x07, 0x07, 0x07, 0xc7, 0xff, 0xe0, 0x1f, 0x00,
+  0xff, 0x80, 0xff, 0x03, 0x07, 0x07, 0x07, 0x87, 0xff, 0xe1, 0x1f, 0x00,
+  0x7f, 0x80, 0xff, 0x01, 0x8e, 0x8f, 0x03, 0x07, 0xff, 0xe3, 0x1f, 0x00,
+  0x07, 0x80, 0xc3, 0x01, 0x8e, 0x8f, 0x03, 0x07, 0x80, 0xe3, 0x00, 0x00,
+  0x07, 0x80, 0xc3, 0x01, 0x8e, 0x8f, 0x03, 0x07, 0x80, 0xe3, 0x00, 0x00,
+  0x07, 0x80, 0x83, 0x03, 0xdc, 0xdd, 0x01, 0x07, 0x80, 0xe3, 0x00, 0x00,
+  0x07, 0x80, 0x83, 0x03, 0xdc, 0xdd, 0x01, 0x07, 0x80, 0xe3, 0x00, 0x00,
+  0xff, 0x87, 0x03, 0x07, 0xf8, 0xf8, 0x00, 0x87, 0xff, 0xe3, 0xff, 0x00,
+  0xff, 0x8f, 0x03, 0x07, 0xf8, 0xf8, 0x00, 0xc7, 0xff, 0xe1, 0xff, 0x01,
+  0xfe, 0x07, 0x01, 0x02, 0x70, 0x70, 0x00, 0x82, 0xff, 0xc0, 0xff, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xfd, 0xff, 0x07, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x03, 0x00, 0x01,
+  0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x41, 0x00, 0x01,
+  0xfa, 0xff, 0x01, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x23, 0x00, 0x01,
+  0xfe, 0xff, 0x03, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x31, 0x80, 0x00,
+  0xf2, 0xff, 0x03, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x39, 0x80, 0x00,
+  0xf4, 0xff, 0x03, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x7f, 0x3c, 0x80, 0x00,
+  0xe4, 0xff, 0x03, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x3f, 0x1c, 0x40, 0x00,
+  0xe4, 0xff, 0x01, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x1f, 0x0c, 0x40, 0x00,
+  0xe8, 0xff, 0x03, 0x00, 0x00, 0x00, 0x80, 0xff, 0x1f, 0x0e, 0x40, 0x00,
+  0xc8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x1f, 0x06, 0x20, 0x00,
+  0xc8, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x0f, 0x06, 0x20, 0x00,
+  0xd0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x07, 0x00, 0x10, 0x00,
+  0x90, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x07, 0x00, 0x10, 0x00,
+  0xa0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03, 0x00, 0x08, 0x00,
+  0x20, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x08, 0x00,
+  0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x04, 0x00,
+  0x80, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x04, 0x00,
+  0x80, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00,
+  0x00, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+  0x00, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+  0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+  0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
+  0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+  0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
+  0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+  0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
+  0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
+  0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x60, 0x20, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x80, 0x09, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x88, 0x03, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0xa0, 0x7f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xc0, 0x03, 0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xdc, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xa0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+
+Widget uicreateinfoform();
+Widget uicreateinfook(Widget parent);
+void uicreateinfolabels(Widget parent, Widget bottomwdg);
+static void uiinfookcb(char *address, HText_t * htext,
+                       HTextObject_t * htextobject, void *parameter);
+
+
+int UiDisplayInfo()
+{
+    uiInfoGfx_t *infogfx = &uiTopLevel.InfoGfx;
+
+    if (infogfx->FormWdg) {
+       XtMapWidget(XtParent(infogfx->FormWdg));
+
+       return UI_OK;
+    }
+    infogfx->FormWdg = uicreateinfoform();
+    infogfx->OkWdg = uicreateinfook(infogfx->FormWdg);
+    uicreateinfolabels(infogfx->FormWdg, infogfx->OkWdg);
+
+    XtManageChild(infogfx->FormWdg);
+    XtRealizeWidget(XtParent(infogfx->FormWdg));
+
+    return UI_OK;
+}
+
+
+static Widget
+ uicreateinfoform()
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget formwdg;
+    Widget topwdg;
+
+    topwdg = XtCreateApplicationShell("Info",
+                                     topLevelShellWidgetClass,
+                                     NULL, 0);
+
+    args = uiVaSetArgs(&nargs,
+                      XmNresizePolicy, XmRESIZE_NONE,
+                      XmNautoUnmanage, FALSE, NULL);
+    formwdg = XmCreateForm(topwdg, "InfoDialog",
+                          args, nargs);
+
+    return formwdg;
+}
+
+
+static Widget
+ uicreateinfook(formwdg)
+Widget formwdg;
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget okwdg;
+    static uiActionData_t actiondata;
+
+    args = uiVaSetArgs(&nargs,
+                      XmNrightAttachment, XmATTACH_FORM,
+                      XmNrightOffset, UI_INFO_WDG_OFFSET,
+                      XmNbottomAttachment, XmATTACH_FORM,
+                      XmNbottomOffset, UI_INFO_WDG_OFFSET, NULL);
+    okwdg = XmCreatePushButtonGadget(formwdg, "   Ok   ", args, nargs);
+    actiondata.ActionName = "InfoOk";
+    actiondata.Page = uiPageInfo.CurrentPage;
+    XtAddCallback(okwdg, XmNactivateCallback, uiinfookcb, (caddr_t) NULL);
+    XtManageChild(okwdg);
+
+    return okwdg;
+}
+
+
+void uicreateinfolabels(formwdg, bottomwdg)
+Widget formwdg;
+Widget bottomwdg;
+{
+    ArgList args;
+    Cardinal nargs;
+    XmString labelstr;
+    Pixmap logo_pixmap;
+    Widget wdg;
+    Display *dpy;
+    Widget label1wdg;
+    Widget label2wdg;
+    Widget label3wdg;
+
+    wdg = uiTopLevel.TopGfx.TopWdg;
+    dpy = XtDisplay(wdg);
+
+    logo_pixmap =
+       XCreatePixmapFromBitmapData(dpy, XtWindow(wdg), logo_bits,
+                                   logo_height, logo_width,
+                                   BlackPixel(dpy, DefaultScreen(dpy)),
+                                   uiGetArg(wdg, XmNbackground),
+                                 DefaultDepth(dpy, DefaultScreen(dpy)));
+
+    if (logo_pixmap == NULL) {
+       printf("Pixmap creation failed\n");
+       exit(1);
+    }
+    args = uiVaSetArgs(&nargs,
+                      XmNlabelType, XmPIXMAP,
+                      XmNlabelPixmap, logo_pixmap,
+                      XmNtopAttachment, XmATTACH_FORM,
+                      XmNtopOffset, UI_INFO_WDG_OFFSET,
+                      XmNleftAttachment, XmATTACH_FORM,
+                      XmNleftOffset, UI_INFO_WDG_OFFSET, NULL);
+    label1wdg = XmCreateLabelGadget(formwdg, "InfoLabel1", args, nargs);
+    XtManageChild(label1wdg);
+
+    labelstr = XmStringCreateLtoR("WorldWideWeb \n browser \n for the X Window System \n \n Version 1.0 Alpha", XmSTRING_DEFAULT_CHARSET);
+    args = uiVaSetArgs(&nargs,
+                      XmNlabelString, labelstr,
+                      XmNtopAttachment, XmATTACH_FORM,
+                      XmNtopOffset, UI_INFO_WDG_OFFSET,
+                      XmNrightAttachment, XmATTACH_FORM,
+                      XmNleftAttachment, XmATTACH_WIDGET,
+                      XmNleftWidget, label1wdg,
+                      XmNrightOffset, UI_INFO_WDG_OFFSET, NULL);
+    label2wdg = XmCreateLabelGadget(formwdg, "InfoLabel2", args, nargs);
+    XtManageChild(label2wdg);
+    XmStringFree(labelstr);
+
+    labelstr = XmStringCreateLtoR("Authors: \n Kim Nyberg, Teemu Rantanen, \n Kati Suominen, Kari Syd{nmaanlakka\n\nE-mail: erwise@cs.hut.fi", XmSTRING_DEFAULT_CHARSET);
+    args = uiVaSetArgs(&nargs,
+                      XmNlabelString, labelstr,
+                      XmNtopAttachment, XmATTACH_WIDGET,
+                      XmNtopWidget, label1wdg,
+                      XmNtopOffset, UI_INFO_WDG_OFFSET,
+                      XmNbottomAttachment, XmATTACH_WIDGET,
+                      XmNbottomWidget, bottomwdg,
+                      XmNbottomOffset, UI_INFO_WDG_OFFSET,
+                      XmNleftAttachment, XmATTACH_FORM,
+                      XmNleftOffset, UI_INFO_WDG_OFFSET,
+                      XmNrightAttachment, XmATTACH_FORM,
+                      XmNrightOffset, UI_INFO_WDG_OFFSET, NULL);
+    label3wdg = XmCreateLabelGadget(formwdg, "InfoLabel3", args, nargs);
+    XtManageChild(label3wdg);
+    XmStringFree(labelstr);
+}
+
+
+static void uiinfookcb(address, htext, htextobject, parameter)
+char *address;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    XtUnmapWidget(XtParent(uiTopLevel.InfoGfx.FormWdg));
+}
diff --git a/Ui/UiInit.c b/Ui/UiInit.c
new file mode 100644 (file)
index 0000000..330d1ad
--- /dev/null
@@ -0,0 +1,156 @@
+static char *rcsid = "$Id: UiInit.c,v 1.3 1992/03/26 18:13:50 kny Exp kny $";
+
+#include "UiIncludes.h"
+
+
+static void uisetupdefaults(int argc, char *argv[],
+                            void *(*configpf) (void *table, char *item));
+static Widget uicreatebutton(Widget parentwdg, char *name, int leftpos,
+                             int rightpos);
+
+static void uitopactivatecb(Widget wdg, caddr_t actionname,
+                            XmPushButtonCallbackStruct * calldata);
+
+
+uiTopLevel_t uiTopLevel;
+Cursor uiBusyCursor, uiArrowCursor;
+void *(*uiConfigPF) (void *table, char *item);
+void *(*uiConfigSetPF) (void *table, char *item, void *value);
+
+
+int UiInitialize(argc, argv, configpf, configsetpf)
+int argc;
+char *argv[];
+void *(*configpf) (void *table, char *item);
+void *(*configsetpf) (void *table, char *item, void *value);
+{
+    uiTopLevelGfx_t *topgfx = &uiTopLevel.TopGfx;
+
+    uiConfigPF = configpf;
+    uiConfigSetPF = configsetpf;
+
+    topgfx->TopWdg = XtInitialize(argv[0], "Erwise", NULL, 0, &argc, argv);
+    topgfx->FormWdg = XmCreateForm(topgfx->TopWdg, "Form",
+                                  (ArgList) NULL, 0);
+    XtVaSetValues(topgfx->FormWdg,
+                 XmNwidth, 280,
+                 XmNheight, 70, NULL);
+    topgfx->InfoWdg = uicreatebutton(topgfx->FormWdg, "Info", 0, 25);
+    topgfx->OpenWdg = uicreatebutton(topgfx->FormWdg, "Open", 25, 50);
+    topgfx->QuitWdg = uicreatebutton(topgfx->FormWdg, "Quit", 50, 75);
+    topgfx->HelpWdg = uicreatebutton(topgfx->FormWdg, "Help", 75, 100);
+
+    XtManageChild(topgfx->FormWdg);
+    XtRealizeWidget(topgfx->TopWdg);
+
+    XlSetupResources(configpf);
+
+    uisetupdefaults(argc, argv, configpf);
+
+    uiBusyCursor = XCreateFontCursor(XtDisplay(topgfx->TopWdg), XC_watch);
+    uiArrowCursor = XCreateFontCursor(XtDisplay(topgfx->TopWdg),
+                                     XC_right_ptr);
+
+    return UI_OK;
+}
+
+
+void UiMainLoop()
+{
+    XtMainLoop();
+}
+
+
+int PlaceValue(value)
+char *value;
+{
+    if (value && !strncasecmp(value, "mouse", strlen("mouse")))
+       return TRUE;
+    return FALSE;
+}
+
+
+static void uisetupdefaults(argc, argv, configpf)
+int argc;
+char *argv[];
+void *(*configpf) (void *table, char *item);
+{
+    uiGlobalSettings_t *gs = &uiTopLevel.GlobalSettings;
+    void *table;
+
+    if (table = configpf((void *) NULL, C_GLOBALSETTINGS)) {
+       gs->TopMargin = atoi((char *) configpf(table, C_TOPMARGIN));
+       gs->BottomMargin = atoi((char *) configpf(table, C_BOTTOMMARGIN));
+       gs->LeftMargin = atoi((char *) configpf(table, C_LEFTMARGIN));
+       gs->RightMargin = atoi((char *) configpf(table, C_RIGHTMARGIN));
+       gs->UseFixed = TruthValue((char *) configpf(table, C_FIXEDWIDTHMODE));
+       gs->FixedWidth = atoi((char *) configpf(table, C_FIXEDWIDTH));
+       gs->OnePageMode = TruthValue((char *) configpf(table, C_ONEPAGEMODE));
+       gs->Width = atoi((char *) configpf(table, C_WIDTH));
+       gs->Height = atoi((char *) configpf(table, C_HEIGHT));
+       gs->DoubleClickTime =
+           (Time) atoi((char *) configpf(table, C_DOUBLECLICKTIME));
+       gs->SearchPlacement = PlaceValue((char *) configpf(table, C_SEARCH));
+       gs->ControlPanelPlacement =
+           PlaceValue((char *) configpf(table, C_CONTROLPANEL));
+       gs->ListPlacement =
+           PlaceValue((char *) configpf(table, C_LIST));
+       gs->RecallPlacement =
+           PlaceValue((char *) configpf(table, C_RECALL));
+       gs->PageSettingsPlacement =
+           PlaceValue((char *) configpf(table, C_PAGESETTINGS));
+    } else
+       uiDisplayWarning("failed to get configurations for global settings");
+
+    if (table = configpf((void *) NULL, C_DEFAULTS))
+       uiSelectionArray = (char **) configpf(table, C_DEFAULTSTABLE);
+    else
+       uiDisplayWarning("failed to get configurations for selection");
+
+    uiPageAttachCallbacks();
+    uiPageDefineKeys();
+}
+
+
+static Widget
+ uicreatebutton(parentwdg, name, leftpos, rightpos)
+Widget parentwdg;
+char *name;
+int leftpos;
+int rightpos;
+{
+    Widget tmpwdg;
+
+    tmpwdg = XmCreatePushButtonGadget(parentwdg, name,
+                                     (ArgList) NULL, 0);
+    XtVaSetValues(tmpwdg,
+                 XmNtopAttachment, XmATTACH_FORM,
+                 XmNbottomAttachment, XmATTACH_FORM,
+                 XmNleftAttachment, XmATTACH_POSITION,
+                 XmNleftPosition, leftpos,
+                 XmNrightAttachment, XmATTACH_POSITION,
+                 XmNrightPosition, rightpos, NULL);
+    XtAddCallback(tmpwdg, XmNactivateCallback, uitopactivatecb,
+                 (caddr_t) name);
+    XtManageChild(tmpwdg);
+
+    return tmpwdg;
+}
+
+
+static void uitopactivatecb(wdg, actionname, calldata)
+Widget wdg;
+caddr_t actionname;
+XmPushButtonCallbackStruct *calldata;
+{
+    uiAction_t *tmpaction;
+
+    if (tmpaction = uiFindAction((char *) actionname))
+       if (uiHelpOnActionCB) {
+           (*uiHelpOnActionCB) (actionname);
+           uiHelpOnActionCB = (void (*) (char *actionstring)) NULL;
+       } else
+           (*tmpaction->Callback) ((char *) NULL, (HText_t *) NULL,
+                                   (HTextObject_t *) NULL,
+                                   tmpaction->Parameter);
+}
diff --git a/Ui/UiList.c b/Ui/UiList.c
new file mode 100644 (file)
index 0000000..bb332fd
--- /dev/null
@@ -0,0 +1,314 @@
+static char *rcsid = "$Id: UiList.c,v 1.1 1992/03/26 18:13:50 kny Exp kny $";
+
+
+#include "UiIncludes.h"
+
+
+static void uilistfreeprevious(void);
+static void uilistsetitems(char **listitems, int nitems);
+
+static Widget uicreatelistform(void);
+static Widget uicreatelistlabel(Widget parent);
+static Widget uicreatelistopen(Widget parent);
+static Widget uicreatelistclose(Widget parent);
+static Widget uicreatelistseparator(Widget parent, Widget bottomwdg);
+static Widget uicreatelistlist(Widget parent, Widget topwdg, Widget bottomwdg);
+static void uilistopencb(Widget wdg, caddr_t ignored,
+                         XmListCallbackStruct * calldata);
+static void uilistclosecb(Widget wdg, caddr_t ignored,
+                          XmListCallbackStruct * calldata);
+
+
+static uiPage_t *uilistpage = (uiPage_t *) NULL;
+static char **uilistitems;
+static char **uiaddresses;
+static int uinitems;
+static void (*uilistcallback) (char *topaddress, char *address,
+                               char *parentaddress);
+
+
+int UiDisplayListDialog(listitems, addresses, nitems, callback)
+char **listitems;
+char **addresses;
+int nitems;
+void (*callback) (char *topaddress, char *address, char *parentaddress);
+{
+    uiListGfx_t *listgfx = &uiTopLevel.ListGfx;
+
+    uilistfreeprevious();
+
+    uilistpage = uiPageInfo.CurrentPage;
+    uilistitems = listitems;
+    uiaddresses = addresses;
+    uinitems = nitems;
+    uilistcallback = callback;
+
+    if (listgfx->FormWdg) {
+       XtMapWidget(XtParent(listgfx->FormWdg));
+
+       uiWidgetPlacement(XtParent(listgfx->FormWdg),
+                         uiTopLevel.GlobalSettings.ListPlacement);
+
+       uilistsetitems(listitems, nitems);
+
+       return UI_OK;
+    }
+    listgfx->FormWdg = uicreatelistform();
+    listgfx->LabelWdg = uicreatelistlabel(listgfx->FormWdg);
+    listgfx->OpenWdg = uicreatelistopen(listgfx->FormWdg);
+    listgfx->CloseWdg = uicreatelistclose(listgfx->FormWdg);
+    listgfx->SeparatorWdg = uicreatelistseparator(listgfx->FormWdg,
+                                                 listgfx->OpenWdg);
+    listgfx->ListWdg = uicreatelistlist(listgfx->FormWdg, listgfx->LabelWdg,
+                                       listgfx->SeparatorWdg);
+
+    uilistsetitems(listitems, nitems);
+
+    XtManageChild(listgfx->FormWdg);
+    XtRealizeWidget(XtParent(listgfx->FormWdg));
+
+    uiWidgetPlacement(XtParent(listgfx->FormWdg),
+                     uiTopLevel.GlobalSettings.ListPlacement);
+
+    return UI_OK;
+}
+
+
+void uiListUpdateDialog(page)
+uiPage_t *page;
+{
+    if (uiTopLevel.ListGfx.FormWdg && (page == uilistpage)) {
+       uilistfreeprevious();
+       uilistsetitems((char **) NULL, 0);
+       uilistpage = (uiPage_t *) NULL;
+       XtUnmapWidget(XtParent(uiTopLevel.ListGfx.FormWdg));
+    }
+}
+
+
+static Widget
+ uicreatelistform()
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget formwdg;
+    Widget topwdg;
+
+    topwdg = XtCreateApplicationShell("List",
+                                     topLevelShellWidgetClass,
+                                     NULL, 0);
+    XtVaSetValues(topwdg,
+                 XmNtitle, UI_LIST_TITLE, NULL);
+
+    args = uiVaSetArgs(&nargs,
+                      XmNresizePolicy, XmRESIZE_NONE,
+                      XmNautoUnmanage, FALSE, NULL);
+    formwdg = XmCreateForm(topwdg, "ListDialog", args, nargs);
+
+    return formwdg;
+}
+
+
+static Widget
+ uicreatelistlabel(formwdg)
+Widget formwdg;
+{
+    ArgList args;
+    Cardinal nargs;
+    XmString labelstr;
+    Widget labelwdg;
+
+    labelstr = XmStringCreateSimple("List of references");
+    args = uiVaSetArgs(&nargs,
+                      XmNlabelString, labelstr,
+                      XmNtopAttachment, XmATTACH_FORM,
+                      XmNtopOffset, UI_LIST_WDG_OFFSET,
+                      XmNleftAttachment, XmATTACH_FORM,
+                      XmNrightAttachment, XmATTACH_FORM, NULL);
+    labelwdg = XmCreateLabelGadget(formwdg, "ListLabel", args, nargs);
+    XtManageChild(labelwdg);
+    XmStringFree(labelstr);
+
+    return labelwdg;
+}
+
+
+static Widget
+ uicreatelistopen(formwdg)
+Widget formwdg;
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget openwdg;
+
+    args = uiVaSetArgs(&nargs,
+                      XmNleftAttachment, XmATTACH_POSITION,
+                      XmNleftPosition, 5,
+                      XmNrightAttachment, XmATTACH_POSITION,
+                      XmNrightPosition, 40,
+                      XmNbottomAttachment, XmATTACH_FORM,
+                      XmNbottomOffset, UI_LIST_WDG_OFFSET, NULL);
+    openwdg = XmCreatePushButtonGadget(formwdg, "Open", args, nargs);
+    XtAddCallback(openwdg, XmNactivateCallback,
+                 (XtCallbackProc) uilistopencb, (caddr_t) NULL);
+    XtManageChild(openwdg);
+
+    return openwdg;
+}
+
+
+static Widget
+ uicreatelistclose(formwdg)
+Widget formwdg;
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget closewdg;
+
+    args = uiVaSetArgs(&nargs,
+                      XmNleftAttachment, XmATTACH_POSITION,
+                      XmNleftPosition, 60,
+                      XmNrightAttachment, XmATTACH_POSITION,
+                      XmNrightPosition, 95,
+                      XmNbottomAttachment, XmATTACH_FORM,
+                      XmNbottomOffset, UI_LIST_WDG_OFFSET, NULL);
+    closewdg = XmCreatePushButtonGadget(formwdg, "Close", args, nargs);
+    XtAddCallback(closewdg, XmNactivateCallback,
+                 (XtCallbackProc) uilistclosecb, (caddr_t) NULL);
+    XtManageChild(closewdg);
+
+    return closewdg;
+}
+
+
+static Widget
+ uicreatelistseparator(formwdg, bottomwdg)
+Widget formwdg;
+Widget bottomwdg;
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget separatorwdg;
+
+    args = uiVaSetArgs(&nargs,
+                      XmNbottomAttachment, XmATTACH_WIDGET,
+                      XmNbottomWidget, bottomwdg,
+                      XmNbottomOffset, UI_LIST_WDG_OFFSET,
+                      XmNleftAttachment, XmATTACH_FORM,
+                      XmNrightAttachment, XmATTACH_FORM, NULL);
+    separatorwdg = XmCreateSeparatorGadget(formwdg, "ListSeparator",
+                                          args, nargs);
+    XtManageChild(separatorwdg);
+
+    return separatorwdg;
+}
+
+
+static Widget
+ uicreatelistlist(formwdg, topwdg, bottomwdg)
+Widget formwdg;
+Widget topwdg;
+Widget bottomwdg;
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget listwdg;
+
+    args = uiVaSetArgs(&nargs,
+                      XmNvisibleItemCount, 15,
+                      XmNwidth, 300,
+                      XmNselectionPolicy, XmSINGLE_SELECT,
+                      XmNlistSizePolicy, XmCONSTANT,
+                      XmNscrollBarDisplayPolicy, XmSTATIC,
+                      XmNtopAttachment, XmATTACH_WIDGET,
+                      XmNtopWidget, topwdg,
+                      XmNtopOffset, UI_LIST_WDG_OFFSET,
+                      XmNbottomAttachment, XmATTACH_WIDGET,
+                      XmNbottomWidget, bottomwdg,
+                      XmNbottomOffset, UI_LIST_WDG_OFFSET,
+                      XmNrightAttachment, XmATTACH_FORM,
+                      XmNrightOffset, UI_LIST_WDG_OFFSET,
+                      XmNleftAttachment, XmATTACH_FORM,
+                      XmNleftOffset, UI_LIST_WDG_OFFSET, NULL);
+    listwdg = XmCreateScrolledList(formwdg, "ListList", args, nargs);
+    XtManageChild(listwdg);
+    XtAddCallback(listwdg, XmNdefaultActionCallback,
+                 (XtCallbackProc) uilistopencb, (caddr_t) NULL);
+
+    return listwdg;
+}
+
+
+void uilistfreeprevious()
+{
+    if (uilistpage && uinitems) {
+       uiFree((void *) uiaddresses);
+
+       while (uinitems--)
+           uiFree(uilistitems[uinitems]);
+
+       uiFree(uilistitems);
+    }
+}
+
+
+static void uilistsetitems(listitems, nitems)
+char **listitems;
+int nitems;
+{
+    Widget listwdg = uiTopLevel.ListGfx.ListWdg;
+    int i;
+    XmString *tmpstr = uiMalloc(nitems * sizeof(XmString));
+
+    XmListDeleteAllItems(listwdg);
+    if (nitems) {
+       for (i = 0; i < nitems; i++)
+           tmpstr[i] = XmStringCreateSimple(listitems[i]);
+
+       XmListAddItems(listwdg, tmpstr, nitems, 0);
+       for (i = 0; i < nitems; i++)
+           XmStringFree(tmpstr[i]);
+       uiFree((void *) tmpstr);
+    }
+}
+
+
+static void uilistopencb(wdg, ignored, calldata)
+Widget wdg;
+caddr_t ignored;
+XmListCallbackStruct *calldata;
+{
+    Widget listwdg = uiTopLevel.ListGfx.ListWdg;
+    int *poslist;
+    int poscount;
+    char *parentaddress;
+
+    if (uinitems)
+       if (XmListGetSelectedPos(listwdg, &poslist, &poscount)) {
+           uiDefineCursor(uiBusyCursor);
+           if (uiHelpOnActionCB) {
+               (*uiHelpOnActionCB) ("Get page");
+               uiHelpOnActionCB = (void (*) (char *actionstring)) NULL;
+           } else {
+               parentaddress =
+                   HTAnchor_address((HTAnchor *)
+                                    uilistpage->HText->node_anchor);
+               (*uilistcallback) (uiaddresses[poslist[0] - 1],
+                                  uilistpage->Hierarchy->Address,
+                                  parentaddress);
+           }
+
+           uiUndefineCursor();
+
+           XtFree(poslist);
+       }
+}
+
+
+static void uilistclosecb(wdg, ignored, calldata)
+Widget wdg;
+caddr_t ignored;
+XmListCallbackStruct *calldata;
+{
+    XtUnmapWidget(XtParent(uiTopLevel.ListGfx.FormWdg));
+}
diff --git a/Ui/UiMisc.c b/Ui/UiMisc.c
new file mode 100644 (file)
index 0000000..d1789a9
--- /dev/null
@@ -0,0 +1,619 @@
+static char *rcsid = "$Id: UiMisc.c,v 1.3 1992/03/26 18:13:50 kny Exp kny $";
+
+#include "UiIncludes.h"
+
+
+static void uitimeouthandler(XtPointer data, XtIntervalId * id);
+static void uifdinputhandler(XtPointer data, int *fd, XtInputId * id);
+static void uipopupcb(Widget wdg, char *address,
+                      XmAnyCallbackStruct * calldata);
+
+
+void (*uiHelpOnActionCB) (char *actionstring) =
+ (
+      void (*) (char *actionstring)) NULL;
+
+static void (*uitimeoutcallback) (void *data);
+static void (*uifdinputcallback) (void *data);
+
+static XtInputId uiinputid;
+static void (*uipopupcallback) (char *address, char *topaddress,
+                                char *parentaddress);
+static char *uipopuptopaddress;
+
+
+int UiAttachCallback(actionname, callback, parameter)
+char *actionname;
+void (*callback) (char *address, HText_t * htext,
+                  HTextObject_t * htextobject, void *parameter);
+void *parameter;
+{
+    uiAction_t *tmpaction;
+
+    if (!(tmpaction = uiFindAction(actionname))) {
+       tmpaction = uiTopLevel.Actions;
+       if (!tmpaction)
+           tmpaction =
+               uiTopLevel.Actions =
+               (uiAction_t *) uiMalloc(sizeof(*tmpaction));
+       else {
+           while (tmpaction->Next)
+               tmpaction = tmpaction->Next;
+           tmpaction =
+               tmpaction->Next = (uiAction_t *) uiMalloc(sizeof(*tmpaction));
+       }
+       tmpaction->Name = strdup(actionname);
+       tmpaction->Next = (uiAction_t *) NULL;
+    }
+    tmpaction->Callback = callback;
+    tmpaction->Parameter = parameter;
+
+    return UI_OK;
+}
+
+
+int UiBindKey(keyname, modifier, callback, parameter)
+char *keyname;
+int modifier;
+void (*callback) (char *address, HText_t * htext,
+                  HTextObject_t * htextobject, void *parameter);
+void *parameter;
+{
+    uiKey_t *tmpkey;
+
+    if (!(tmpkey = uiFindKey(keyname, modifier))) {
+       tmpkey = uiTopLevel.Keys;
+       if (!tmpkey)
+           tmpkey =
+               uiTopLevel.Keys =
+               (uiKey_t *) uiMalloc(sizeof(*tmpkey));
+       else {
+           while (tmpkey->Next)
+               tmpkey = tmpkey->Next;
+           tmpkey =
+               tmpkey->Next = (uiKey_t *) uiMalloc(sizeof(*tmpkey));
+       }
+       tmpkey->Name = strdup(keyname);
+       tmpkey->Next = (uiKey_t *) NULL;
+    }
+    tmpkey->Modifier = modifier;
+    tmpkey->Callback = callback;
+    tmpkey->Parameter = parameter;
+
+    return UI_OK;
+}
+
+
+int UiBindVariable(varname, variable, type)
+char *varname;
+void *variable;
+uiVarType_t type;
+{
+    uiVariable_t *tmpvar;
+
+    if (!(tmpvar = uiFindVariable(varname))) {
+       tmpvar = uiTopLevel.Variables;
+       if (!tmpvar)
+           tmpvar =
+               uiTopLevel.Variables =
+               (uiVariable_t *) uiMalloc(sizeof(*tmpvar));
+       else {
+           while (tmpvar->Next)
+               tmpvar = tmpvar->Next;
+           tmpvar =
+               tmpvar->Next = (uiVariable_t *) uiMalloc(sizeof(*tmpvar));
+       }
+       tmpvar->Name = strdup(varname);
+       tmpvar->Next = (uiVariable_t *) NULL;
+    }
+    tmpvar->Value = variable;
+    tmpvar->VarType = type;
+
+    return UI_OK;
+}
+
+
+int UiUpdateVariable(varname)
+char *varname;
+{
+    uiVariable_t *tmpvar;
+    char *tmpstr;
+    static char staticstr[100];        /* Is this overkill? */
+
+    tmpstr = staticstr;
+    if (tmpvar = uiFindVariable(varname)) {
+       switch (tmpvar->WdgType) {
+       case uiWTtext:
+           switch (tmpvar->VarType) {
+           case uiVTint:
+               sprintf(staticstr, "%d", *(int *) tmpvar->Value);
+               break;
+           case uiVTdouble:
+               sprintf(staticstr, "%d", *(int *) tmpvar->Value);
+               break;
+           case uiVTstring:
+               tmpstr = (char *) tmpvar->Value;
+           }
+           XmTextSetString(tmpvar->Wdg, tmpstr);
+           break;
+       case uiWToptionmenu:
+           /* Not implemented yet */
+           break;
+       case uiWTradiobox:
+           /* Not implemented yet */
+           break;
+       case uiWTcheckbutton:
+           XtVaSetValues(tmpvar->Wdg,
+                         XmNset, (*(int *) tmpvar->Value != 0), NULL);
+           break;
+       case uiWTscale:
+           /* Not implemented yet */
+           break;
+       }
+       return UI_OK;
+    }
+    return UI_NOTFOUND;
+}
+
+
+void UiGetNextAction(helponactioncb)
+void (*helponactioncb) (char *actionstring);
+{
+    uiHelpOnActionCB = helponactioncb;
+}
+
+
+int UiAddTimeOut(timeout, callback, data)
+int timeout;
+void (*callback) (void *data);
+void *data;
+{
+    uitimeoutcallback = callback;
+
+    return (int) XtAddTimeOut(timeout, uitimeouthandler, (caddr_t) data);
+}
+
+
+void UiDeleteTimeOut(timeoutid)
+int timeoutid;
+{
+    XtRemoveTimeOut((XtIntervalId) timeoutid);
+}
+
+
+int UiAddInputFD(fd, callback, data)
+int fd;
+void (*callback) (void *data);
+void *data;
+{
+    uifdinputcallback = callback;
+
+    return (int) XtAddInput(fd, XtInputReadMask | XtInputExceptMask,
+                           uifdinputhandler, (caddr_t) data);
+}
+
+
+void UiDeleteInputFD(inputid)
+int inputid;
+{
+    XtRemoveInput((XtInputId) inputid);
+}
+
+
+void UiAddStringToCutBuffer(data)
+char *data;
+{
+    static char *cutbuffer = (char *) NULL;
+    int oldlen;
+
+    if (data) {
+       oldlen = cutbuffer ? strlen(cutbuffer) : 0;
+
+       cutbuffer = (char *) uiReAlloc((void *) cutbuffer,
+                                      oldlen + strlen(data) + 1);
+       strcpy(&cutbuffer[oldlen], data);
+    } else if (cutbuffer) {
+       XStoreBytes(XtDisplay(uiTopLevel.TopGfx.TopWdg), cutbuffer,
+                   strlen(cutbuffer));
+       uiFree(cutbuffer);
+       cutbuffer = (char *) NULL;
+    } else
+       XStoreBytes(XtDisplay(uiTopLevel.TopGfx.TopWdg), "", 0);
+}
+
+
+void UiDisplayPopup(callback, topaddress, items, nitems)
+void (*callback) (char *address, char *topaddress, char *parentaddress);
+char *topaddress;
+char **items;
+int nitems;
+{
+    Widget topwdg = uiPageInfo.CurrentPage->Gfx.TopWdg;
+    ArgList args;
+    Cardinal nargs;
+    Widget pmwdg, rcwdg, buttonwdg;
+    Window root, child;
+    int root_x, root_y, win_x, win_y;
+    unsigned int mask;
+
+    uipopupcallback = callback;
+    uipopuptopaddress = topaddress;
+
+    if (XQueryPointer(XtDisplay(topwdg), XtWindow(topwdg), &root, &child,
+                     &root_x, &root_y, &win_x, &win_y, &mask)) {
+       args = uiVaSetArgs(&nargs,
+                          XmNborderWidth, 0,
+                          XmNwidth, 100,
+                          XmNheight, 100, NULL);
+       pmwdg = XmCreateMenuShell(topwdg, "popupmenu", args, nargs);
+
+       args = uiVaSetArgs(&nargs,
+                          XmNx, (Position) (root_x - 20),
+                          XmNy, (Position) (root_y - 5),
+                          XmNspacing, 0,
+                          XmNmarginWidth, 0,
+                          XmNmarginHeight, 0, NULL);
+       rcwdg = XmCreateRowColumn(pmwdg, "rowcol", args, nargs);
+       while (nitems--) {
+           args = uiVaSetArgs(&nargs,
+                              XmNhighlightThickness, 0, NULL);
+           buttonwdg = XmCreatePushButtonGadget(rcwdg, items[nitems],
+                                                args, nargs);
+           XtAddCallback(buttonwdg, XmNactivateCallback,
+                   (XtCallbackProc) uipopupcb, (caddr_t) items[nitems]);
+           XtManageChild(buttonwdg);
+       }
+
+       XtManageChild(rcwdg);
+       XtRealizeWidget(pmwdg);
+       XtMapWidget(pmwdg);
+
+       XGrabPointer(XtDisplay(pmwdg), XtWindow(pmwdg), TRUE, 0,
+                    GrabModeAsync, GrabModeAsync, XtWindow(pmwdg),
+                    uiArrowCursor, CurrentTime);
+
+       XFlush(XtDisplay(pmwdg));
+    }
+}
+
+
+uiAction_t *
+ uiFindAction(actionname)
+char *actionname;
+{
+    uiAction_t *tmpaction = uiTopLevel.Actions;
+
+    while (tmpaction) {
+       if (!strcmp(actionname, tmpaction->Name))
+           return tmpaction;
+
+       tmpaction = tmpaction->Next;
+    }
+
+    return (uiAction_t *) NULL;
+}
+
+
+uiKey_t *
+ uiFindKey(keyname, modifier)
+char *keyname;
+int modifier;
+{
+    uiKey_t *tmpkey = uiTopLevel.Keys;
+
+    while (tmpkey) {
+       if (!strcmp(keyname, tmpkey->Name) && modifier == tmpkey->Modifier)
+           return tmpkey;
+
+       tmpkey = tmpkey->Next;
+    }
+
+    return (uiKey_t *) NULL;
+}
+
+
+uiVariable_t *
+ uiFindVariable(varname)
+char *varname;
+{
+    uiVariable_t *tmpvar = uiTopLevel.Variables;
+
+    while (tmpvar) {
+       if (!strcmp(varname, tmpvar->Name))
+           return tmpvar;
+
+       tmpvar = tmpvar->Next;
+    }
+
+    return (uiVariable_t *) NULL;
+}
+
+
+int uiAddWidgetInfo(varname, wdg, wdgtype)
+char *varname;
+Widget wdg;
+uiWdgType_t wdgtype;
+{
+    uiVariable_t *tmpvar;
+
+    if (tmpvar = uiFindVariable(varname)) {
+       tmpvar->Wdg = wdg;
+       tmpvar->WdgType = wdgtype;
+
+       return UI_OK;
+    }
+    return UI_NOTFOUND;
+}
+
+
+void uiDialogActivateCB(wdg, actiondata, calldata)
+Widget wdg;
+uiActionData_t *actiondata;
+XmAnyCallbackStruct *calldata;
+{
+    uiAction_t *tmpaction;
+
+    actiondata->Page = uiPageInfo.CurrentPage;
+    uiPageInfo.Wdg = wdg;
+    uiPageInfo.CallData = (void *) calldata;
+
+    if (tmpaction = uiFindAction(actiondata->ActionName)) {
+       uiDefineCursor(uiBusyCursor);
+       if (uiHelpOnActionCB) {
+           (*uiHelpOnActionCB) (actiondata->ActionName);
+           uiHelpOnActionCB = (void (*) (char *actionstring)) NULL;
+       } else
+           (*tmpaction->Callback) (actiondata->Page->Hierarchy->Address,
+                                   actiondata->Page->HText,
+                                   actiondata->Page->HTextObject,
+                                   tmpaction->Parameter);
+       uiUndefineCursor();
+    }
+}
+
+
+void uiDialogVariableCB(wdg, varname, calldata)
+Widget wdg;
+caddr_t varname;
+XmAnyCallbackStruct *calldata;
+{
+    uiVariable_t *tmpvar;
+    char *tmpstr;
+
+    if (tmpvar = uiFindVariable((char *) varname)) {
+       switch (tmpvar->WdgType) {
+       case uiWTtext:
+           tmpstr = XmTextGetString(tmpvar->Wdg);
+           switch (tmpvar->VarType) {
+           case uiVTint:
+               *(int *) tmpvar->Value = atoi(tmpstr);
+               break;
+           case uiVTdouble:
+               *(double *) tmpvar->Value = atof(tmpstr);
+               break;
+           case uiVTstring:
+               strcpy((char *) tmpvar->Value, tmpstr);
+           }
+           XtFree(tmpstr);
+           break;
+       case uiWToptionmenu:
+           /* Not implemented yet */
+           break;
+       case uiWTradiobox:
+           /* Not implemented yet */
+           break;
+       case uiWTcheckbutton:
+           *(int *) tmpvar->Value = uiGetArg(tmpvar->Wdg, XmNset);
+           break;
+       case uiWTscale:
+           /* Not implemented yet */
+           break;
+       }
+    }
+}
+
+
+void uiDefineCursor(cursor)
+Cursor cursor;
+{
+    uiHierarchy_t *tmphierarchy = uiTopLevel.Hierarchies;
+    uiPage_t *tmppage;
+
+    while (tmphierarchy) {
+       tmppage = tmphierarchy->Pages;
+       while (tmppage) {
+           if (tmppage->Visible)
+               XDefineCursor(XtDisplay(uiTopLevel.TopGfx.TopWdg),
+                             XtWindow(tmppage->Gfx.TopWdg),
+                             cursor);
+           tmppage = tmppage->Next;
+       }
+       tmphierarchy = tmphierarchy->Next;
+    }
+
+    XDefineCursor(XtDisplay(uiTopLevel.TopGfx.TopWdg),
+                 XtWindow(uiTopLevel.TopGfx.TopWdg),
+                 cursor);
+    if (uiTopLevel.PageSettingsGfx.FormWdg)
+       XDefineCursor(XtDisplay(uiTopLevel.TopGfx.TopWdg),
+                     XtWindow(uiTopLevel.PageSettingsGfx.FormWdg),
+                     cursor);
+    if (uiTopLevel.SearchGfx.FormWdg)
+       XDefineCursor(XtDisplay(uiTopLevel.TopGfx.TopWdg),
+                     XtWindow(uiTopLevel.SearchGfx.FormWdg),
+                     cursor);
+    if (uiTopLevel.ListGfx.FormWdg)
+       XDefineCursor(XtDisplay(uiTopLevel.TopGfx.TopWdg),
+                     XtWindow(uiTopLevel.ListGfx.FormWdg),
+                     cursor);
+}
+
+
+void uiUndefineCursor()
+{
+    uiHierarchy_t *tmphierarchy = uiTopLevel.Hierarchies;
+    uiPage_t *tmppage;
+
+    while (tmphierarchy) {
+       tmppage = tmphierarchy->Pages;
+       while (tmppage) {
+           if (tmppage->Visible)
+               XUndefineCursor(XtDisplay(uiTopLevel.TopGfx.TopWdg),
+                               XtWindow(tmppage->Gfx.TopWdg));
+           tmppage = tmppage->Next;
+       }
+       tmphierarchy = tmphierarchy->Next;
+    }
+
+    XUndefineCursor(XtDisplay(uiTopLevel.TopGfx.TopWdg),
+                   XtWindow(uiTopLevel.TopGfx.TopWdg));
+    if (uiTopLevel.PageSettingsGfx.FormWdg)
+       XUndefineCursor(XtDisplay(uiTopLevel.TopGfx.TopWdg),
+                       XtWindow(uiTopLevel.PageSettingsGfx.FormWdg));
+    if (uiTopLevel.SearchGfx.FormWdg)
+       XUndefineCursor(XtDisplay(uiTopLevel.TopGfx.TopWdg),
+                       XtWindow(uiTopLevel.SearchGfx.FormWdg));
+    if (uiTopLevel.ListGfx.FormWdg)
+       XUndefineCursor(XtDisplay(uiTopLevel.TopGfx.TopWdg),
+                       XtWindow(uiTopLevel.ListGfx.FormWdg));
+}
+
+
+ArgList
+uiVaSetArgs(nargs, va_alist)
+int *nargs;
+va_dcl
+{
+    static Arg args[50];
+    String tmpstr;
+    va_list pvar;
+
+    *nargs = 0;
+
+    va_start(pvar);
+    tmpstr = va_arg(pvar, String);
+    while (tmpstr) {
+       XtSetArg(args[(int) *nargs], tmpstr, va_arg(pvar, XtArgVal));
+       *nargs += 1;
+       tmpstr = va_arg(pvar, String);
+    }
+    va_end(pvar);
+
+    return args;
+}
+
+
+XtArgVal
+uiGetArg(wdg, resource)
+Widget wdg;
+String resource;
+{
+    Arg args[1];
+
+    XtSetArg(args[0], resource, (XtArgVal) 0);
+    XtGetValues(wdg, args, 1);
+
+    return args[0].value;
+}
+
+
+void *
+ uiMalloc(size)
+int size;
+{
+    void *tmpptr;
+
+    if (!(tmpptr = (void *) malloc(size))) {
+       uiDisplayFatal("No swap, buy a computer");
+       exit(1);
+    }                          /* Not reached */
+    return tmpptr;
+}
+
+
+void *
+ uiReAlloc(ptr, size)
+void *ptr;
+int size;
+{
+    void *tmpptr;
+
+    if (!ptr)
+       return uiMalloc(size);
+    else if (!(tmpptr = (void *) realloc((char *) ptr, size))) {
+       uiDisplayFatal("No swap, buy a computer");
+       exit(1);
+    }                          /* Not reached */
+    return tmpptr;
+}
+
+
+void uiFree(ptr)
+void *ptr;
+{
+    if (ptr)
+       free(ptr);
+}
+
+
+void uiDisplayWarning(text)
+char *text;
+{
+    (void) fprintf(stderr, "Ui-warning: %s\n", text);
+}
+
+
+void uiDisplayFatal(text)
+char *text;
+{
+    (void) fprintf(stderr, "Ui-fatal: %s\n", text);
+
+    abort();
+}
+
+
+void uiWidgetPlacement(wdg, placement)
+Widget wdg;
+int placement;
+{
+    Window root, child;
+    int root_x, root_y, win_x, win_y;
+    unsigned int mask;
+
+    if (placement) {
+       if (XQueryPointer(XtDisplay(wdg),
+                         XtWindow(wdg), &root, &child,
+                         &root_x, &root_y, &win_x, &win_y, &mask))
+           XtMoveWidget(wdg, root_x - 50, root_y - 50);
+    }
+}
+
+
+static void uitimeouthandler(data, id)
+XtPointer data;
+XtIntervalId *id;
+{
+    (*uitimeoutcallback) (data);
+}
+
+
+static void uifdinputhandler(data, fd, id)
+XtPointer data;
+int *fd;
+XtInputId *id;
+{
+    uiinputid = *id;
+
+    (*uifdinputcallback) (data);
+}
+
+
+static void uipopupcb(wdg, address, calldata)
+Widget wdg;
+char *address;
+XmAnyCallbackStruct *calldata;
+{
+    XtDestroyWidget(XtParent(XtParent(wdg)));
+
+    uipopupcallback(address, uipopuptopaddress, address);
+}
diff --git a/Ui/UiPage.c b/Ui/UiPage.c
new file mode 100644 (file)
index 0000000..f869520
--- /dev/null
@@ -0,0 +1,1272 @@
+static char *rcsid = "$Id: UiPage.c,v 1.4 1992/03/26 18:13:50 kny Exp kny $";
+
+#include "UiIncludes.h"
+
+
+static uiHierarchy_t *uifindoraddhierarchy(char *topaddress);
+static uiHierarchy_t *uifindhierarchy(char *topaddress);
+static int uideletehierarchy(uiHierarchy_t * hierarchy);
+static uiPage_t *uifindpage(HText_t * htext, uiHierarchy_t * hierarchy);
+static uiPage_t *
+ uiaddpage(HText_t * htext, HTextObject_t * htextobject,
+           uiHierarchy_t * hierarchy, uiPage_t * prevpage);
+static int uideletepage(uiPage_t * page, uiHierarchy_t * hierarchy);
+static void uideletepagecallbacks(uiPage_t * page);
+static uiPage_t *uifindshadowpage(uiHierarchy_t * hierarchy, uiPage_t * page);
+static int uicreatepagewidgets(uiPage_t * page, uiPage_t * prevpage,
+                               char *title);
+static void uicreatepageform(uiPage_t * page, char *title, Widget topwdg);
+static Widget uicreatepagemenu(uiPage_t * page, Widget formwdg);
+static Widget uicreatepagemenuitem(uiPage_t * page, Widget menuwdg,
+                                   int itempos, int level);
+static int uifindnextitem(int itempos, int level);
+static Widget uicreatepagecontrol(uiPage_t * page, Widget formwdg, char *title);
+static void uicreatepagelabel(Widget parentwdg, char *label);
+static void uicreatepagebutton(uiPage_t * page, Widget parentwdg, char *name,
+                               int leftpos, int rightpos);
+static Widget uicreatepagefind(uiPage_t * page, Widget formwdg,
+                               Widget controlwdg);
+static Widget uicreatepagescroll(uiPage_t * page, Widget formwdg,
+                                 Widget menuwdg, Widget controlwdg);
+static void uiconnectpage(uiPage_t * page);
+static void uipageupdatescrollbars(uiPage_t * page);
+static uiActionData_t *uicreatepageactiondata(uiPage_t * page,
+                                              char *actionname);
+static void uisetcurrentpage(uiPage_t * page);
+static int uideletepageinternal(char *topaddress, HText_t * htext);
+
+static void uipageactivatecb(Widget wdg, uiActionData_t * actiondata,
+                             XmAnyCallbackStruct * calldata);
+static void uipagekludgecb(Widget wdg, uiActionData_t * actiondata,
+                           XEvent * event);
+static void uipageexposecb(Widget wdg, uiPage_t * page,
+                           XmDrawingAreaCallbackStruct * calldata);
+static void uipageresizecb(Widget wdg, uiPage_t * page,
+                           XmDrawingAreaCallbackStruct * calldata);
+static void uipageinputcb(char *topaddress, HText_t * htext,
+                          HTextObject_t * htextobject, void *parameter);
+static void uipagescrollbarcb(char *topaddress, HText_t * htext,
+                          HTextObject_t * htextobject, void *parameter);
+static void uipagedowncb(char *topaddress, HText_t * htext,
+                         HTextObject_t * htextobject, void *parameter);
+static void uipageupcb(char *topaddress, HText_t * htext,
+                       HTextObject_t * htextobject, void *parameter);
+static void uipagetopcb(char *topaddress, HText_t * htext,
+                        HTextObject_t * htextobject, void *parameter);
+static void uipagebottomcb(char *topaddress, HText_t * htext,
+                           HTextObject_t * htextobject, void *parameter);
+
+uiPageInfo_t uiPageInfo =
+{
+    (uiPage_t *) NULL,
+    (Widget) NULL,
+    (void *) NULL
+};
+
+
+int UiDisplayPage(topaddress, prevhtext, htext, htextobject, title)
+char *topaddress;
+HText_t *prevhtext;
+HText_t *htext;
+HTextObject_t *htextobject;
+char *title;
+{
+    uiHierarchy_t *hierarchy;
+    uiPage_t *prevpage, *page;
+
+    if (!(hierarchy = uifindoraddhierarchy(topaddress)))
+       return UI_ERROR;
+
+    if (!(page = uifindpage(htext, hierarchy)) || !page->Visible) {
+       prevpage = uifindpage(prevhtext, hierarchy);
+
+       if (!page)
+           if (!(page = uiaddpage(htext, htextobject, hierarchy, prevpage))) {
+               if (!hierarchy->Pages)
+                   (void) uideletehierarchy(hierarchy);        /* already an error */
+
+               return UI_ERROR;
+           }
+       if (uicreatepagewidgets(page, prevpage, title) == UI_OK) {
+           uisetcurrentpage(page);
+
+           return UI_OK;
+       } else
+           return UI_ERROR;
+    } else {
+       XRaiseWindow(XtDisplay(page->Gfx.TopWdg), XtWindow(page->Gfx.TopWdg));
+       uisetcurrentpage(page);
+    }
+
+    return UI_OK;
+}
+
+
+int UiDeletePage(topaddress, htext)
+char *topaddress;
+HText_t *htext;
+{
+    uiHierarchy_t *hierarchy;
+    uiPage_t *page, *shadowpage;
+    uiAction_t *tmpaction;
+
+    if (!(hierarchy = uifindhierarchy(topaddress)))
+       return UI_ERROR;
+
+    if (!(page = uifindpage(htext, hierarchy)))
+       return UI_ERROR;
+
+    XlDeleteText(htext);
+
+    shadowpage = uifindshadowpage(hierarchy, page);
+
+    if (page->Visible)
+       XtDestroyWidget(XtParent(page->Gfx.FormWdg));
+    uideletepage(page, hierarchy);
+
+    if (shadowpage) {          /* Recursive destroy, oh yeah */
+       tmpaction = uiFindAction("Close");
+       (tmpaction->Callback) (topaddress, shadowpage->HText,
+                         shadowpage->HTextObject, tmpaction->Parameter);
+    }
+    return UI_OK;
+}
+
+
+int UiSetCursor(topaddress, htext, htextobject)
+char *topaddress;
+HText_t *htext;
+HTextObject_t *htextobject;
+{
+    uiHierarchy_t *hierarchy;
+    uiPage_t *page;
+    int tmpx, tmpy;
+
+    if (!(hierarchy = uifindhierarchy(topaddress)))
+       return UI_ERROR;
+
+    if (!(page = uifindpage(htext, hierarchy)))
+       return UI_ERROR;
+
+    page->HTextObject = htextobject;
+
+    if (!page->Visible)
+       return UI_OK;
+
+    XlSetCursor(htext, htextobject);
+
+    XlGetCoordinates(&tmpx, &tmpy, htextobject);
+    if (tmpx < page->Layout.X || tmpx > page->Layout.X + page->Layout.Width)
+       page->Layout.X = tmpx - page->Layout.Width / 2;
+    if (tmpy < page->Layout.Y || tmpy > page->Layout.Y + page->Layout.Height)
+       page->Layout.Y = tmpy - page->Layout.Height / 2;
+
+    uipageupdatescrollbars(page);
+    XlMoveWindow(page->Layout.X, page->Layout.Y, page->HText);
+
+    return UI_OK;
+}
+
+
+void uiPageUpdateWindow(page)
+uiPage_t *page;
+{
+    HTextObject_t *htextobject;
+    int tmpwidth;
+
+    if (page->Settings.UseFixed)
+       tmpwidth = page->Settings.FixedWidth - page->Settings.LeftMargin -
+           page->Settings.RightMargin;
+    else
+       tmpwidth = page->Layout.Width - page->Settings.LeftMargin -
+           page->Settings.RightMargin;
+
+    htextobject = XlLocateHTextObject(0, 0, page->HText);
+    XlFormatText(page->Settings.LeftMargin, tmpwidth,
+                page->Settings.TopMargin, &page->Layout.VirtualWidth,
+                &page->Layout.VirtualHeight, page->HText);
+    XlGetCoordinates(&page->Layout.X, &page->Layout.Y, htextobject);
+
+    if (page->Layout.VirtualWidth > tmpwidth + page->Settings.LeftMargin)
+       page->Layout.VirtualWidth += page->Settings.RightMargin;
+    else
+       page->Layout.VirtualWidth = tmpwidth + page->Settings.LeftMargin +
+           page->Settings.RightMargin;
+    page->Layout.VirtualHeight += page->Settings.BottomMargin;
+
+    if (!page->Settings.UseFixed)
+       page->Layout.X = 0;
+    uipageupdatescrollbars(page);
+
+    XlSetPageCoordinates(page->Layout.X, page->Layout.Y, page->HText);
+}
+
+
+void uiPageAttachCallbacks()
+{
+    UiAttachCallback("Top", uipagetopcb, (void *) NULL);
+    UiAttachCallback("Bottom", uipagebottomcb, (void *) NULL);
+}
+
+
+void uiPageDefineKeys()
+{
+    UiBindKey("space", UI_NONE, uipagedowncb, (void *) NULL);
+    UiBindKey("Delete", UI_NONE, uipageupcb, (void *) NULL);
+
+    UiBindKey("less", UI_SHIFT, uipagetopcb, (void *) NULL);
+    UiBindKey("greater", UI_SHIFT, uipagebottomcb, (void *) NULL);
+}
+
+
+static uiHierarchy_t *
+ uifindoraddhierarchy(topaddress)
+char *topaddress;
+{
+    uiHierarchy_t *tmphierarchy;
+
+    if (!(tmphierarchy = uifindhierarchy(topaddress))) {
+       tmphierarchy = uiTopLevel.Hierarchies;
+       if (!tmphierarchy)
+           tmphierarchy = uiTopLevel.Hierarchies =
+               (uiHierarchy_t *) uiMalloc(sizeof(*tmphierarchy));
+       else {
+           while (tmphierarchy->Next)
+               tmphierarchy = tmphierarchy->Next;
+           tmphierarchy = tmphierarchy->Next =
+               (uiHierarchy_t *) uiMalloc(sizeof(*tmphierarchy));
+       }
+       tmphierarchy->Address = topaddress;
+       tmphierarchy->Pages = (uiPage_t *) NULL;
+       tmphierarchy->Next = (uiHierarchy_t *) NULL;
+    }
+    return tmphierarchy;
+}
+
+
+static uiHierarchy_t *
+ uifindhierarchy(topaddress)
+char *topaddress;
+{
+    uiHierarchy_t *tmphierarchy = uiTopLevel.Hierarchies;
+
+    while (tmphierarchy && strcmp(tmphierarchy->Address, topaddress))
+       tmphierarchy = tmphierarchy->Next;
+
+    return tmphierarchy;
+}
+
+
+static int uideletehierarchy(hierarchy)
+uiHierarchy_t *hierarchy;
+{
+    uiHierarchy_t *tmphierarchy = uiTopLevel.Hierarchies;
+
+    if (hierarchy == tmphierarchy)
+       if (tmphierarchy->Next) {
+           uiTopLevel.Hierarchies = hierarchy->Next;
+           uisetcurrentpage(hierarchy->Next->Pages);
+       } else {
+           uiTopLevel.Hierarchies = (uiHierarchy_t *) NULL;
+           uisetcurrentpage((uiPage_t *) NULL);
+       }
+    else {
+       while (tmphierarchy->Next && tmphierarchy->Next != hierarchy)
+           tmphierarchy = tmphierarchy->Next;
+       if (tmphierarchy->Next) {
+           tmphierarchy->Next = tmphierarchy->Next->Next;
+           uisetcurrentpage(tmphierarchy->Pages);
+       } else {
+           /* This shouldn't happen unless we have a stray pointer */
+           uiDisplayWarning("Messed up hierarchy-list");
+
+           return UI_ERROR;
+       }
+    }
+
+    uiFree(hierarchy);
+
+    return UI_OK;
+}
+
+
+static uiPage_t *
+ uifindpage(htext, hierarchy)
+HText_t *htext;
+uiHierarchy_t *hierarchy;
+{
+    uiPage_t *tmppage = hierarchy->Pages;
+
+    while (tmppage && tmppage->HText != htext)
+       tmppage = tmppage->Next;
+
+    return tmppage;
+}
+
+
+static uiPage_t *
+ uiaddpage(htext, htextobject, hierarchy, prevpage)
+HText_t *htext;
+HTextObject_t *htextobject;
+uiHierarchy_t *hierarchy;
+uiPage_t *prevpage;
+{
+    uiPage_t *tmppage = hierarchy->Pages;
+
+    if (!tmppage)
+       tmppage = hierarchy->Pages =
+           (uiPage_t *) uiMalloc(sizeof(*tmppage));
+    else {
+       while (tmppage->Next)
+           tmppage = tmppage->Next;
+       tmppage = tmppage->Next =
+           (uiPage_t *) uiMalloc(sizeof(*tmppage));
+    }
+    tmppage->HText = htext;
+    tmppage->HTextObject = htextobject;
+    tmppage->Hierarchy = hierarchy;
+
+    if (prevpage) {
+       tmppage->Settings.TopMargin = prevpage->Settings.TopMargin;
+       tmppage->Settings.BottomMargin = prevpage->Settings.BottomMargin;
+       tmppage->Settings.LeftMargin = prevpage->Settings.LeftMargin;
+       tmppage->Settings.RightMargin = prevpage->Settings.RightMargin;
+       tmppage->Settings.OnePageMode = prevpage->Settings.OnePageMode;
+       tmppage->Settings.UseFixed = prevpage->Settings.UseFixed;
+       tmppage->Settings.FixedWidth = prevpage->Settings.FixedWidth;
+       tmppage->Layout.Width = prevpage->Layout.Width;
+       tmppage->Layout.Height = prevpage->Layout.Height;
+    } else {
+       uiGlobalSettings_t *gs = &uiTopLevel.GlobalSettings;
+
+       tmppage->Settings.TopMargin = gs->TopMargin;
+       tmppage->Settings.BottomMargin = gs->BottomMargin;
+       tmppage->Settings.LeftMargin = gs->LeftMargin;
+       tmppage->Settings.RightMargin = gs->RightMargin;
+       tmppage->Settings.OnePageMode = gs->OnePageMode;
+       tmppage->Settings.UseFixed = gs->UseFixed;
+       tmppage->Settings.FixedWidth = gs->FixedWidth;
+       tmppage->Layout.Width = gs->Width;
+       tmppage->Layout.Height = gs->Height;
+    }
+
+    /* X and Y are href-dependent, Width and Height default, or previous */
+    tmppage->Layout.X = 0;
+    tmppage->Layout.Y = 0;
+
+    tmppage->Callbacks = (uiPageCBList_t *) NULL;
+    tmppage->Next = (uiPage_t *) NULL;
+
+    return tmppage;
+}
+
+
+static int uideletepage(page, hierarchy)
+uiPage_t *page;
+uiHierarchy_t *hierarchy;
+{
+    uiPage_t *tmppage = hierarchy->Pages;
+
+    if (tmppage == page)
+       if (tmppage->Next) {
+           hierarchy->Pages = tmppage->Next;
+           uisetcurrentpage(tmppage->Next);
+       } else
+           uideletehierarchy(hierarchy);
+    else {
+       while (tmppage->Next && tmppage->Next != page)
+           tmppage = tmppage->Next;
+       if (tmppage->Next) {
+           tmppage->Next = tmppage->Next->Next;
+           if (tmppage->Next)
+               uisetcurrentpage(tmppage->Next);
+           else
+               uisetcurrentpage(tmppage);
+       } else {
+           /* This shouldn't happen unless we have a stray pointer */
+           uiDisplayWarning("Messed up page-list");
+
+           return UI_ERROR;
+       }
+    }
+
+    uiListUpdateDialog(page);
+    uideletepagecallbacks(page);
+    uiFree(page);
+
+    return UI_OK;
+}
+
+
+static void uideletepagecallbacks(page)
+uiPage_t *page;
+{
+    uiPageCBList_t *tmpcb = page->Callbacks;
+
+    while (tmpcb) {
+       tmpcb = tmpcb->Next;
+       uiFree(page->Callbacks);
+       page->Callbacks = tmpcb;
+    }
+}
+
+
+static uiPage_t *
+ uifindshadowpage(hierarchy, page)
+uiHierarchy_t *hierarchy;
+uiPage_t *page;
+{
+    uiPage_t *tmppage = hierarchy->Pages;
+
+    while (tmppage)
+       if (tmppage != page && tmppage->Gfx.TopWdg == page->Gfx.TopWdg)
+           return tmppage;
+       else
+           tmppage = tmppage->Next;
+
+    return (uiPage_t *) NULL;
+}
+
+
+static int uicreatepagewidgets(page, prevpage, title)
+uiPage_t *page;
+uiPage_t *prevpage;
+char *title;
+{
+    uiTopLevelGfx_t *topgfx = &uiTopLevel.TopGfx;
+    uiPageGfx_t *pagegfx = &page->Gfx;
+    Widget topwdg, bottomwdg;
+
+    /* Ahemm, we could of course try to salvage as much as possible
+       of the widget tree, but why bother? No, just destroy everything
+       except for the toplevel shell, no need to remove callbacks and
+       event handlers
+    */
+    if (prevpage && prevpage->Settings.OnePageMode) {
+       topwdg = prevpage->Gfx.TopWdg;
+       uideletepageinternal(prevpage->Hierarchy->Address, prevpage->HText);
+       uicreatepageform(page, title, topwdg);
+    } else
+       uicreatepageform(page, title, (Widget) NULL);
+
+    page->Visible = TRUE;
+    pagegfx->MenuWdg = uicreatepagemenu(page, pagegfx->FormWdg);
+    XtManageChild(pagegfx->MenuWdg);
+    pagegfx->ControlWdg = uicreatepagecontrol(page, pagegfx->FormWdg, title);
+    XtManageChild(pagegfx->ControlWdg);
+    page->Gfx.FindTextWdg = (Widget) NULL;
+    if (HTAnchor_isIndex(page->HText->node_anchor)) {
+       pagegfx->FindWdg = uicreatepagefind(page, pagegfx->FormWdg,
+                                           pagegfx->ControlWdg);
+       XtManageChild(pagegfx->FindWdg);
+       bottomwdg = pagegfx->FindWdg;
+    } else
+       bottomwdg = pagegfx->ControlWdg;
+    pagegfx->DrawAreaWdg = uicreatepagescroll(page, pagegfx->FormWdg,
+                                           pagegfx->MenuWdg, bottomwdg);
+
+    XtManageChild(pagegfx->FormWdg);
+    XtRealizeWidget(pagegfx->TopWdg);
+
+    /* Do setup that cannot be done before managing the form */
+    XtVaSetValues(pagegfx->HScrollBarWdg,
+                 XmNrightAttachment, XmATTACH_FORM,
+                 XmNrightOffset, uiGetArg(pagegfx->FormWdg, XmNwidth) -
+                 uiGetArg(pagegfx->DrawAreaWdg, XmNwidth), NULL);
+    uiconnectpage(page);
+
+    /* Is this really necessary?
+    XmUpdateDisplay(XtParent(pagegfx->FormWdg));
+    Nope, don't think so */
+
+    return UI_OK;
+}
+
+
+static void uicreatepageform(page, title, topwdg)
+uiPage_t *page;
+char *title;
+Widget topwdg;
+{
+    ArgList args;
+    Cardinal nargs;
+    char *tmptitle;
+
+    if (topwdg)
+       page->Gfx.TopWdg = topwdg;
+    else
+       page->Gfx.TopWdg = XtCreateApplicationShell("Page",
+                                               topLevelShellWidgetClass,
+                                                   NULL, 0);
+    if (title) {
+       tmptitle = uiMalloc(strlen(UI_ERWISE_TITLE) + strlen(title) + 4);
+       sprintf(tmptitle, "%s - %s", UI_ERWISE_TITLE, title);
+       XtVaSetValues(page->Gfx.TopWdg,
+                     XmNtitle, tmptitle, NULL);
+       uiFree(tmptitle);
+    } else
+       XtVaSetValues(page->Gfx.TopWdg,
+                     XmNtitle, UI_ERWISE_TITLE, NULL);
+
+    args = uiVaSetArgs(&nargs,
+                      NULL);
+    page->Gfx.FormWdg = XmCreateForm(page->Gfx.TopWdg, "Form", args, nargs);
+}
+
+
+static char *uimenu[] =
+{
+    "Page", NULL,
+    " Search", "Search",
+    " Copy", "Copy",
+    " List", "List",
+    " Load to file", "Load to file",
+    " Print", "Print",
+    " Settings", "Settings",
+    " ", NULL,
+    " Close", "Close",
+    "Movement", "Movement",
+    " Top", "Top",
+    " Bottom", "Bottom",
+    " Prev tag", "Prev tag",
+    " Next tag", "Next tag",
+    "Hierarchy", NULL,
+    " Home", "Home",
+    " Recall", "Recall",
+    " Back", "Back",
+    " Prev page", "Prev page",
+    " Next page", "Next page",
+    " Close", NULL,
+    "  hierarchy", "Close hierarchy",
+    "Misc", NULL,
+    " Connections", "Connections",
+    " Controlpanel", "Controlpanel",
+    " Defaults", "Defaults",
+    "Help", NULL,
+    " On function", "On function",
+    " Manual", "Help",
+    NULL
+};
+
+static Widget
+ uicreatepagemenu(page, formwdg)
+uiPage_t *page;
+Widget formwdg;
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget menuwdg, tmpmenuwdg;
+    int itempos = 0;
+
+    args = uiVaSetArgs(&nargs,
+                      XmNleftAttachment, XmATTACH_FORM,
+                      XmNrightAttachment, XmATTACH_FORM,
+                      XmNtopAttachment, XmATTACH_FORM, NULL);
+    menuwdg = XmCreateMenuBar(formwdg, "menubar", args, nargs);
+
+    do {
+       tmpmenuwdg = uicreatepagemenuitem(page, menuwdg, itempos, 0);
+       if (ui_HELPMENU(uimenu[itempos]))
+           XtVaSetValues(menuwdg,
+                         XmNmenuHelpWidget, tmpmenuwdg, NULL);
+       itempos = uifindnextitem(itempos, 0);
+    }
+    while (ui_VALID(itempos));
+
+    return menuwdg;
+}
+
+
+static Widget
+ uicreatepagemenuitem(page, menuwdg, itempos, level)
+uiPage_t *page;
+Widget menuwdg;
+int itempos;
+int level;
+{
+    int childitempos = itempos;
+    int childlevel = level + 1;
+    char *label;
+    ArgList args;
+    Cardinal nargs;
+    Widget pulldownwdg;
+    Widget cascadewdg;
+    Widget tmpwdg;
+    uiActionData_t *actiondata;
+
+    label = &uimenu[itempos][level];
+    if (ui_VALID(uifindnextitem(itempos, childlevel))) {
+       pulldownwdg = XmCreatePulldownMenu(menuwdg, "Pulldown", NULL, 0);
+       args = uiVaSetArgs(&nargs, XmNsubMenuId, pulldownwdg, NULL);
+       cascadewdg = XmCreateCascadeButtonGadget(menuwdg, label, args, nargs);
+       XtManageChild(cascadewdg);
+
+       while (ui_VALID(childitempos =
+                       uifindnextitem(childitempos, childlevel)))
+           uicreatepagemenuitem(page, pulldownwdg, childitempos, childlevel);
+
+       tmpwdg = cascadewdg;
+    } else {
+       if (label[0]) {
+           if (ui_TOGGLE(label)) {
+               tmpwdg = XmCreateToggleButtonGadget(menuwdg, label, NULL, 0);
+           } else {
+               tmpwdg = XmCreatePushButtonGadget(menuwdg, label, NULL, 0);
+               actiondata = uicreatepageactiondata(page, uimenu[itempos + 1]);
+               XtAddCallback(tmpwdg, XmNactivateCallback,
+                             (XtCallbackProc) uipageactivatecb,
+                             (caddr_t) actiondata);
+           }
+       } else
+           tmpwdg = XmCreateSeparatorGadget(menuwdg, "Separator", NULL, 0);
+       XtManageChild(tmpwdg);
+    }
+
+    return tmpwdg;
+}
+
+
+static int uifindnextitem(itempos, level)
+int itempos;
+int level;
+{
+    int i = itempos + 2;
+
+    while (uimenu[i] &&
+          (uimenu[i][level] == ' ' || uimenu[i][level] == '*'))
+       i += 2;
+    if (!uimenu[i] ||
+    (level && uimenu[i][level - 1] != ' ' && uimenu[i][level - 1] != '*'))
+       return UI_INVALID;
+
+    return i;
+}
+
+
+static Widget
+ uicreatepagecontrol(page, formwdg, title)
+uiPage_t *page;
+Widget formwdg;
+char *title;
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget controlwdg;
+
+    args = uiVaSetArgs(&nargs,
+                      XmNheight, 70,
+                      XmNshadowThickness, 2,
+                      XmNleftAttachment, XmATTACH_FORM,
+                      XmNrightAttachment, XmATTACH_FORM,
+                      XmNbottomAttachment, XmATTACH_FORM, NULL);
+    controlwdg = XmCreateForm(formwdg, "Control", args, nargs);
+
+    uicreatepagelabel(controlwdg,
+               HTAnchor_address((HTAnchor *) page->HText->node_anchor));
+
+    uicreatepagebutton(page, controlwdg, "Prev tag", 1, 16);
+    uicreatepagebutton(page, controlwdg, "Next tag", 17, 32);
+    uicreatepagebutton(page, controlwdg, "Prev page", 35, 50);
+    uicreatepagebutton(page, controlwdg, "Back", 51, 66);
+    uicreatepagebutton(page, controlwdg, "Next page", 67, 82);
+    uicreatepagebutton(page, controlwdg, "Close", 85, 99);
+
+    return controlwdg;
+}
+
+
+static void uicreatepagelabel(parentwdg, label)
+Widget parentwdg;
+char *label;
+{
+    Widget labelwdg;
+    XmString labelstr;
+
+    labelstr = XmStringCreateSimple(label);
+    labelwdg = XmCreateLabelGadget(parentwdg, "Label", (ArgList) NULL, 0);
+    XtVaSetValues(labelwdg,
+                 XmNtopAttachment, XmATTACH_FORM,
+                 XmNtopOffset, 5,
+                 XmNleftAttachment, XmATTACH_FORM,
+                 XmNleftOffset, 5,
+                 XmNrightAttachment, XmATTACH_FORM,
+                 XmNrightOffset, 5,
+                 XmNlabelString, labelstr, NULL);
+
+    XtManageChild(labelwdg);
+}
+
+
+static void uicreatepagebutton(page, parentwdg, name, leftpos, rightpos)
+uiPage_t *page;
+Widget parentwdg;
+char *name;
+int leftpos;
+int rightpos;
+{
+    Widget tmpwdg;
+    uiActionData_t *actiondata;
+
+    tmpwdg = XmCreatePushButtonGadget(parentwdg, name, (ArgList) NULL, 0);
+    XtVaSetValues(tmpwdg,
+                 XmNbottomAttachment, XmATTACH_FORM,
+                 XmNbottomOffset, 5,
+                 XmNleftAttachment, XmATTACH_POSITION,
+                 XmNleftPosition, leftpos,
+                 XmNrightAttachment, XmATTACH_POSITION,
+                 XmNrightPosition, rightpos, NULL);
+    actiondata = uicreatepageactiondata(page, name);
+    XtAddCallback(tmpwdg, XmNactivateCallback, uipageactivatecb,
+                 (caddr_t) actiondata);
+
+    XtManageChild(tmpwdg);
+}
+
+
+static Widget
+ uicreatepagefind(page, formwdg, controlwdg)
+uiPage_t *page;
+Widget formwdg;
+Widget controlwdg;
+{
+    Widget framewdg, findformwdg, buttonwdg, textwdg;
+    uiActionData_t *actiondata;
+    XmString labelstr;
+
+    labelstr = XmStringCreateSimple("     Find:     ");
+
+    framewdg = XmCreateFrame(formwdg, "FindFrame", (ArgList) NULL, 0);
+    XtVaSetValues(framewdg,
+                 XmNshadowType, XmSHADOW_OUT,
+                 XmNmarginWidth, 2,
+                 XmNmarginHeight, 2,
+                 XmNleftAttachment, XmATTACH_FORM,
+                 XmNrightAttachment, XmATTACH_FORM,
+                 XmNbottomAttachment, XmATTACH_WIDGET,
+                 XmNbottomWidget, controlwdg,
+                 XmNbottomOffset, 1, NULL);
+
+    findformwdg = XmCreateForm(framewdg, "FindForm", (ArgList) NULL, 0);
+    XtManageChild(findformwdg);
+
+    buttonwdg = XmCreatePushButtonGadget(findformwdg, "FindButton",
+                                        (ArgList) NULL, 0);
+    XtVaSetValues(buttonwdg,
+                 XmNlabelString, labelstr,
+                 XmNtopAttachment, XmATTACH_FORM,
+                 XmNleftAttachment, XmATTACH_FORM,
+                 XmNbottomAttachment, XmATTACH_FORM, NULL);
+    actiondata = uicreatepageactiondata(page, "IndexFind");
+    XtAddCallback(buttonwdg, XmNactivateCallback, uipageactivatecb,
+                 (caddr_t) actiondata);
+    XmStringFree(labelstr);
+    XtManageChild(buttonwdg);
+
+    textwdg = XmCreateText(findformwdg, "FindText", (ArgList) NULL, 0);
+    XtVaSetValues(textwdg,
+                 XmNtopAttachment, XmATTACH_FORM,
+                 XmNleftAttachment, XmATTACH_WIDGET,
+                 XmNleftWidget, buttonwdg,
+                 XmNrightAttachment, XmATTACH_FORM,
+                 XmNbottomAttachment, XmATTACH_FORM, NULL);
+    XtAddCallback(textwdg, XmNactivateCallback, uipageactivatecb,
+                 (caddr_t) actiondata);
+    XtAddCallback(textwdg, XmNactivateCallback,
+             (XtCallbackProc) uiDialogVariableCB, (caddr_t) "FindText");
+    XtAddCallback(textwdg, XmNlosingFocusCallback,
+             (XtCallbackProc) uiDialogVariableCB, (caddr_t) "FindText");
+    XtAddCallback(textwdg, XmNvalueChangedCallback,
+             (XtCallbackProc) uiDialogVariableCB, (caddr_t) "FindText");
+    (void) uiAddWidgetInfo("FindText", textwdg, uiWTtext);     /* Ignore */
+    page->Gfx.FindTextWdg = textwdg;
+    XtManageChild(textwdg);
+
+    return framewdg;
+}
+
+
+static Widget
+ uicreatepagescroll(page, formwdg, menuwdg, bottomwdg)
+uiPage_t *page;
+Widget formwdg;
+Widget menuwdg;
+Widget bottomwdg;
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget drawwdg, hsbwdg, vsbwdg;
+    uiActionData_t *actiondata;
+
+    args = uiVaSetArgs(&nargs,
+                      XmNorientation, XmHORIZONTAL,
+                      XmNwidth, page->Layout.Width,
+                      XmNbottomAttachment, XmATTACH_WIDGET,
+                      XmNbottomWidget, bottomwdg,
+                      XmNbottomOffset, 2, NULL);
+    hsbwdg = XmCreateScrollBar(formwdg, "HScrollBar", args, nargs);
+    page->Gfx.HScrollBarWdg = hsbwdg;
+    actiondata = uicreatepageactiondata(page, "HScrollBar");
+    XtAddCallback(hsbwdg, XmNvalueChangedCallback,
+             (XtCallbackProc) uipageactivatecb, (caddr_t *) actiondata);
+    UiAttachCallback("HScrollBar", uipagescrollbarcb, (void *) "HScrollBar");
+
+    args = uiVaSetArgs(&nargs,
+                      XmNorientation, XmVERTICAL,
+                      XmNheight, page->Layout.Height,
+                      XmNtopAttachment, XmATTACH_WIDGET,
+                      XmNtopWidget, menuwdg,
+                      XmNrightAttachment, XmATTACH_FORM,
+                      XmNbottomAttachment, XmATTACH_WIDGET,
+                      XmNbottomWidget, hsbwdg, NULL);
+    vsbwdg = XmCreateScrollBar(formwdg, "VScrollBar", args, nargs);
+    page->Gfx.VScrollBarWdg = vsbwdg;
+    actiondata = uicreatepageactiondata(page, "VScrollBar");
+    XtAddCallback(vsbwdg, XmNvalueChangedCallback,
+             (XtCallbackProc) uipageactivatecb, (caddr_t *) actiondata);
+    UiAttachCallback("VScrollBar", uipagescrollbarcb, (void *) "VScrollBar");
+
+    args = uiVaSetArgs(&nargs,
+                      XmNwidth, page->Layout.Width,
+                      XmNheight, page->Layout.Height,
+                      XmNtopAttachment, XmATTACH_WIDGET,
+                      XmNtopWidget, menuwdg,
+                      XmNleftAttachment, XmATTACH_FORM,
+                      XmNrightAttachment, XmATTACH_WIDGET,
+                      XmNrightWidget, vsbwdg,
+                      XmNbottomAttachment, XmATTACH_WIDGET,
+                      XmNbottomWidget, hsbwdg, NULL);
+    drawwdg = XmCreateDrawingArea(formwdg, "Draw", args, nargs);
+    XtAddCallback(drawwdg, XmNexposeCallback, (XtCallbackProc) uipageexposecb,
+                 (caddr_t) page);
+    XtAddCallback(drawwdg, XmNresizeCallback, (XtCallbackProc) uipageresizecb,
+                 (caddr_t) page);
+    actiondata = uicreatepageactiondata(page, "PageInput");
+    XtAddCallback(drawwdg, XmNinputCallback, (XtCallbackProc) uipageactivatecb,
+                 (caddr_t) actiondata);
+    XtAddEventHandler(drawwdg, KeyPressMask, FALSE, uipagekludgecb,
+                     (caddr_t) actiondata);
+    UiAttachCallback("PageInput", uipageinputcb, (void *) NULL);
+
+    XtManageChild(drawwdg);
+    XtManageChild(hsbwdg);
+    XtManageChild(vsbwdg);
+
+    return drawwdg;
+}
+
+
+static void uiconnectpage(page)
+uiPage_t *page;
+{
+    Widget drawwdg = page->Gfx.DrawAreaWdg;
+    Widget hsbwdg = page->Gfx.HScrollBarWdg;
+    Widget vsbwdg = page->Gfx.VScrollBarWdg;
+    int tmpwidth;
+
+    XlSetupText(XtDisplay(drawwdg), XtWindow(drawwdg),
+               (Pixel) uiGetArg(drawwdg, XmNforeground),
+               (Pixel) uiGetArg(drawwdg, XmNbackground), page->HText);
+
+    if (page->Settings.UseFixed)
+       tmpwidth = page->Settings.FixedWidth - page->Settings.LeftMargin -
+           page->Settings.RightMargin;
+    else
+       tmpwidth = page->Layout.Width - page->Settings.LeftMargin -
+           page->Settings.RightMargin;
+
+    XlFormatText(page->Settings.LeftMargin, tmpwidth,
+                page->Settings.TopMargin, &page->Layout.VirtualWidth,
+                &page->Layout.VirtualHeight, page->HText);
+
+    if (page->Layout.VirtualWidth > tmpwidth + page->Settings.LeftMargin)
+       page->Layout.VirtualWidth += page->Settings.RightMargin;
+    else
+       page->Layout.VirtualWidth = tmpwidth + page->Settings.LeftMargin +
+           page->Settings.RightMargin;
+    page->Layout.VirtualHeight += page->Settings.BottomMargin;
+
+    if (page->HTextObject)
+       XlGetCoordinates(&page->Layout.X, &page->Layout.Y, page->HTextObject);
+    page->Layout.X = 0;
+    uipageupdatescrollbars(page);
+    if (page->HTextObject)
+       XlMoveWindow(page->Layout.X, page->Layout.Y, page->HText);
+
+    XlSetCursor(page->HText, page->HTextObject);
+}
+
+
+static void uipageupdatescrollbars(page)
+uiPage_t *page;
+{
+    Widget hsbwdg = page->Gfx.HScrollBarWdg;
+    Widget vsbwdg = page->Gfx.VScrollBarWdg;
+    int maxwidth, maxheight;
+    int hsbwidth, vsbheight;
+
+    maxwidth = page->Layout.VirtualWidth;
+    if (page->Layout.X + page->Layout.Width > maxwidth)
+       page->Layout.X -= ((page->Layout.X + page->Layout.Width) - maxwidth);
+    hsbwidth = (page->Layout.Width > maxwidth) ? maxwidth : page->Layout.Width;
+    if (page->Layout.X < 0)
+       page->Layout.X = 0;
+
+    maxheight = page->Layout.VirtualHeight;
+    if (page->Layout.Y + page->Layout.Height > maxheight)
+       page->Layout.Y -= ((page->Layout.Y + page->Layout.Height) - maxheight);
+    vsbheight =
+       (page->Layout.Height > maxheight) ? maxheight : page->Layout.Height;
+    if (page->Layout.Y < 0)
+       page->Layout.Y = 0;
+
+
+    XtVaSetValues(hsbwdg,
+                 XmNmaximum, maxwidth,
+                 XmNvalue, page->Layout.X,
+                 XmNsliderSize, hsbwidth,
+                 XmNincrement, hsbwidth / 10,
+                 XmNpageIncrement, hsbwidth, NULL);
+    XtVaSetValues(vsbwdg,
+                 XmNmaximum, maxheight,
+                 XmNvalue, page->Layout.Y,
+                 XmNsliderSize, vsbheight,
+                 XmNincrement, vsbheight / 10,
+                 XmNpageIncrement, vsbheight, NULL);
+}
+
+
+uiActionData_t *
+ uicreatepageactiondata(page, actionname)
+uiPage_t *page;
+char *actionname;
+{
+    uiPageCBList_t *tmppagecb = page->Callbacks;
+
+    if (!tmppagecb)
+       tmppagecb =
+           page->Callbacks = (uiPageCBList_t *) uiMalloc(sizeof(*tmppagecb));
+    else {
+       while (tmppagecb->Next)
+           tmppagecb = tmppagecb->Next;
+       tmppagecb = tmppagecb->Next =
+           (uiPageCBList_t *) uiMalloc(sizeof(*tmppagecb));
+    }
+    tmppagecb->ActionData.ActionName = actionname;
+    tmppagecb->ActionData.Page = page;
+    tmppagecb->Next = (uiPageCBList_t *) NULL;
+
+    return &tmppagecb->ActionData;
+}
+
+
+static void uisetcurrentpage(page)
+uiPage_t *page;
+{
+    uiPage_t *oldpage;
+
+    oldpage = uiPageInfo.CurrentPage;
+    uiPageInfo.CurrentPage = page;
+
+    if (oldpage != page) {
+       uiPageSettingsUpdateDialog();
+       uiSearchUpdateDialog();
+       uiControlPanelUpdateDialog();
+       uiPrintUpdateDialog();
+       uiRecallUpdateDialog();
+       uiConnectionsUpdateDialog();
+    }
+}
+
+
+static int uideletepageinternal(topaddress, htext)
+char *topaddress;
+HText_t *htext;
+{
+    uiHierarchy_t *hierarchy;
+    uiPage_t *page;
+    Widget topwdg;
+
+    if (!(hierarchy = uifindhierarchy(topaddress)))
+       return UI_ERROR;
+
+    if (!(page = uifindpage(htext, hierarchy)))
+       return UI_ERROR;
+
+/*    XlDeleteText(htext);*/
+
+    topwdg = page->Gfx.TopWdg;
+    page = hierarchy->Pages;
+    while (page) {
+       if (page->Gfx.TopWdg == topwdg) {
+           if (page->Visible)
+               XtDestroyWidget(page->Gfx.FormWdg);
+           page->Visible = FALSE;
+       }
+       page = page->Next;
+    }
+/*    uideletepage(page, hierarchy);*/
+
+    return UI_OK;
+}
+
+
+static void uipageactivatecb(wdg, actiondata, calldata)
+Widget wdg;
+uiActionData_t *actiondata;
+XmAnyCallbackStruct *calldata;
+{
+    uiAction_t *tmpaction;
+
+    uiPageInfo.Wdg = wdg;
+    uiPageInfo.CallData = (void *) calldata;
+    uisetcurrentpage(actiondata->Page);
+    if (actiondata->Page->Gfx.FindTextWdg) {
+       (void) uiAddWidgetInfo("FindText", actiondata->Page->Gfx.FindTextWdg,
+                              uiWTtext);       /* Ignore */
+       (void) uiDialogVariableCB((Widget) NULL, "FindText",
+                                 (XmAnyCallbackStruct *) NULL);        /* Hmm? */
+    }
+    if (tmpaction = uiFindAction(actiondata->ActionName)) {
+       uiDefineCursor(uiBusyCursor);
+       if (uiHelpOnActionCB) {
+           (*uiHelpOnActionCB) (actiondata->ActionName);
+           uiHelpOnActionCB = (void (*) (char *actionstring)) NULL;
+       } else
+           (*tmpaction->Callback) (actiondata->Page->Hierarchy->Address,
+                                   actiondata->Page->HText,
+                                   actiondata->Page->HTextObject,
+                                   tmpaction->Parameter);
+       uiUndefineCursor();
+    }
+}
+
+
+/*
+ *  Massive braindamage ahead ... default translation in
+ *  drawingarea-widget for return is activate, even if the widget
+ *  doesn't support activate. Gawd! Anyway, we have to resort to this:
+ */
+
+static void uipagekludgecb(wdg, actiondata, event)
+Widget wdg;
+uiActionData_t *actiondata;
+XEvent *event;
+{
+    XKeyEvent *kevent = (XKeyEvent *) event;
+    XmAnyCallbackStruct tmpstruct;
+
+    if (XLookupKeysym(kevent, kevent->state) == XK_Return) {
+       tmpstruct.event = event;
+       uipageactivatecb(wdg, actiondata, &tmpstruct);
+    }
+}
+
+
+static void uipageexposecb(wdg, page, calldata)
+Widget wdg;
+uiPage_t *page;
+XmDrawingAreaCallbackStruct *calldata;
+{
+    XExposeEvent *event = (XExposeEvent *) calldata->event;
+
+#ifdef DEBUG
+    printf("Explode: %d %d %d %d %x\n",
+          event->x, event->y, event->width, event->height, page->HText);
+#endif
+    XlRedraw(event->x, event->y, event->width, event->height, page->HText);
+}
+
+
+static void uipageresizecb(wdg, page, calldata)
+Widget wdg;
+uiPage_t *page;
+XmDrawingAreaCallbackStruct *calldata;
+{
+    Widget hsbwdg = page->Gfx.HScrollBarWdg;
+    Widget vsbwdg = page->Gfx.VScrollBarWdg;
+    HTextObject_t *htextobject;
+
+#ifdef DEBUG
+    printf("Resize: %d %d\n",
+          (int) ((Dimension) uiGetArg(wdg, XmNwidth)),
+          (int) ((Dimension) uiGetArg(wdg, XmNheight)));
+#endif
+
+    if (!XtIsRealized(page->Gfx.DrawAreaWdg))
+       return;
+
+    XlClearWindow(page->Layout.Width, page->Layout.Height, page->HText);
+
+    page->Layout.Width = (int) ((Dimension) uiGetArg(wdg, XmNwidth));
+    page->Layout.Height = (int) ((Dimension) uiGetArg(wdg, XmNheight));
+
+    uiPageUpdateWindow(page);
+}
+
+
+static void uipageinputcb(topaddress, htext, htextobject, parameter)
+char *topaddress;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    Widget wdg = uiPageInfo.Wdg;
+    uiPage_t *page = uiPageInfo.CurrentPage;
+    XmDrawingAreaCallbackStruct *calldata =
+    (XmDrawingAreaCallbackStruct *) uiPageInfo.CallData;
+    XButtonEvent *bevent = (XButtonEvent *) calldata->event;
+    XKeyEvent *kevent = (XKeyEvent *) calldata->event;
+    static int dragx, dragy;
+    static Time oldtime = (Time) 0;
+    uiAction_t *tmpaction;
+    uiKey_t *tmpkey;
+    KeySym keysym;
+    char *keysymstring;
+    switch (bevent->type) {
+    case ButtonPress:
+       switch (bevent->button) {
+       case 1:
+           page->HTextObject = XlLocateHTextObject(bevent->x, bevent->y,
+                                                   page->HText);
+           XlSetCursor(htext, page->HTextObject);
+           if (page->HTextObject) {
+               if (bevent->time - oldtime <
+                   uiTopLevel.GlobalSettings.DoubleClickTime)
+                   tmpaction = uiFindAction("Get page");
+               else
+                   tmpaction = uiFindAction("Click page");
+               if (tmpaction) {
+                   uiDefineCursor(uiBusyCursor);
+                   if (uiHelpOnActionCB) {
+                       (*uiHelpOnActionCB) ("Get page");
+                       uiHelpOnActionCB = (void (*) (char *actionstring)) NULL;
+                   } else
+                       (*tmpaction->Callback) (topaddress, htext,
+                                               page->HTextObject,
+                                               tmpaction->Parameter);
+                   uiUndefineCursor();
+               }
+               oldtime = (Time) 0;
+           }
+           oldtime = bevent->time;
+           break;
+       case 2:
+           dragx = bevent->x;
+           dragy = bevent->y;
+           break;
+       }
+       break;
+    case ButtonRelease:
+       switch (bevent->button) {
+       case 2:
+           page->Layout.X -= (bevent->x - dragx);
+           page->Layout.Y -= (bevent->y - dragy);
+           uipageupdatescrollbars(page);
+           XlMoveWindow(page->Layout.X, page->Layout.Y, page->HText);
+           break;
+       }
+       break;
+    case KeyPress:
+       keysym = XLookupKeysym(kevent, 0);
+       if (keysym != NoSymbol && (keysymstring = XKeysymToString(keysym))) {
+           if (tmpkey = uiFindKey(keysymstring, kevent->state)) {
+               uiDefineCursor(uiBusyCursor);
+               if (uiHelpOnActionCB) {
+                   (*uiHelpOnActionCB) (keysymstring);
+                   uiHelpOnActionCB = (void (*) (char *actionstring)) NULL;
+               } else
+                   (*tmpkey->Callback) (topaddress,
+                                        htext,
+                                        page->HTextObject,
+                                        tmpkey->Parameter);
+               uiUndefineCursor();
+           }
+       }
+       break;
+    }
+}
+
+
+static void uipagescrollbarcb(topaddress, htext, htextobject, parameter)
+char *topaddress;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    XmUpdateDisplay(uiPageInfo.CurrentPage->Gfx.DrawAreaWdg);
+
+    if (!strcmp("HScrollBar", (char *) parameter))
+       uiPageInfo.CurrentPage->Layout.X =
+           ((XmScrollBarCallbackStruct *) uiPageInfo.CallData)->value;
+    else
+       uiPageInfo.CurrentPage->Layout.Y =
+           ((XmScrollBarCallbackStruct *) uiPageInfo.CallData)->value;
+
+#ifdef DEBUG
+    printf("scrollbar: %d %d\n", uiPageInfo.CurrentPage->Layout.X,
+          uiPageInfo.CurrentPage->Layout.Y);
+#endif
+    XlMoveWindow(uiPageInfo.CurrentPage->Layout.X,
+                uiPageInfo.CurrentPage->Layout.Y,
+                uiPageInfo.CurrentPage->HText);
+}
+
+
+static void uipagedowncb(topaddress, htext, htextobject, parameter)
+char *topaddress;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    uiPage_t *page = uiPageInfo.CurrentPage;
+
+    page->Layout.Y = page->Layout.Y + page->Layout.Height;
+
+    uipageupdatescrollbars(page);
+    XlMoveWindow(page->Layout.X, page->Layout.Y, page->HText);
+}
+
+
+static void uipageupcb(topaddress, htext, htextobject, parameter)
+char *topaddress;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    uiPage_t *page = uiPageInfo.CurrentPage;
+
+    page->Layout.Y = page->Layout.Y - page->Layout.Height;
+
+    uipageupdatescrollbars(page);
+    XlMoveWindow(page->Layout.X, page->Layout.Y, page->HText);
+}
+
+
+static void uipagetopcb(topaddress, htext, htextobject, parameter)
+char *topaddress;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    uiPage_t *page = uiPageInfo.CurrentPage;
+
+    page->Layout.Y = 0;
+
+    uipageupdatescrollbars(page);
+    XlMoveWindow(page->Layout.X, page->Layout.Y, page->HText);
+}
+
+
+static void uipagebottomcb(topaddress, htext, htextobject, parameter)
+char *topaddress;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    uiPage_t *page = uiPageInfo.CurrentPage;
+
+    page->Layout.Y = page->Layout.VirtualHeight - page->Layout.Height;
+
+    uipageupdatescrollbars(page);
+    XlMoveWindow(page->Layout.X, page->Layout.Y, page->HText);
+}
diff --git a/Ui/UiPageSettings.c b/Ui/UiPageSettings.c
new file mode 100644 (file)
index 0000000..f572d7b
--- /dev/null
@@ -0,0 +1,617 @@
+static char *rcsid = "$Id: UiPageSettings.c,v 1.1 1992/03/26 18:13:50 kny Exp kny $";
+
+#include "UiIncludes.h"
+
+
+static void uibindpsvariables(void);
+static void uiupdatepsvariables(void);
+static Widget uicreatepsformdialog();
+static Widget uicreatepslabel(Widget parent);
+static Widget
+ uicreatepsmargin(Widget parent, Widget topwdg, char *name,
+                  int position);
+static Widget uicreatepsseparator(Widget formwdg, Widget topwdg);
+static Widget uicreatepsusefixed(Widget parent, Widget topwdg);
+static Widget uicreatepssinglepage(Widget parent, Widget topwdg);
+static void uicreatepsbuttons(Widget formwdg, Widget topwdg);
+
+static void uipagesettingsmargincb(char *address, HText_t * htext,
+                                   HTextObject_t * htextobject,
+                                   void *parameter);
+static void uipagesettingsusefixedcb(char *address, HText_t * htext,
+                                     HTextObject_t * htextobject,
+                                     void *parameter);
+static void uipagesettingsbuttoncb(char *address, HText_t * htext,
+                                   HTextObject_t * htextobject,
+                                   void *parameter);
+
+
+int UiDisplayPageSettingsDialog(type)
+int type;
+{
+    uiPageSettingsGfx_t *psgfx = &uiTopLevel.PageSettingsGfx;
+    Widget separatorwdg;
+
+    uibindpsvariables();
+
+    if (psgfx->FormWdg) {
+       XtMapWidget(XtParent(psgfx->FormWdg));
+
+       uiWidgetPlacement(XtParent(psgfx->FormWdg),
+                       uiTopLevel.GlobalSettings.PageSettingsPlacement);
+
+       uiupdatepsvariables();
+
+       return UI_OK;
+    }
+    psgfx->FormWdg = uicreatepsformdialog();
+    psgfx->LabelWdg = uicreatepslabel(psgfx->FormWdg);
+
+    psgfx->LeftMarginWdg = uicreatepsmargin(psgfx->FormWdg, psgfx->LabelWdg,
+                                           "Left", UI_LEFT);
+    psgfx->RightMarginWdg =
+       uicreatepsmargin(psgfx->FormWdg, psgfx->LeftMarginWdg,
+                        "Right", UI_LEFT);
+    psgfx->TopMarginWdg = uicreatepsmargin(psgfx->FormWdg, psgfx->LabelWdg,
+                                          "Top", UI_RIGHT);
+    psgfx->BottomMarginWdg =
+       uicreatepsmargin(psgfx->FormWdg, psgfx->TopMarginWdg,
+                        "Bottom", UI_RIGHT);
+
+    separatorwdg = uicreatepsseparator(psgfx->FormWdg, psgfx->RightMarginWdg);
+
+    psgfx->UseFixedWdg = uicreatepsusefixed(psgfx->FormWdg,
+                                           separatorwdg);
+    psgfx->SinglePageWdg = uicreatepssinglepage(psgfx->FormWdg,
+                                               psgfx->UseFixedWdg);
+
+    separatorwdg = uicreatepsseparator(psgfx->FormWdg, psgfx->SinglePageWdg);
+    uicreatepsbuttons(psgfx->FormWdg, separatorwdg);
+    XtManageChild(psgfx->FormWdg);
+    XtRealizeWidget(XtParent(psgfx->FormWdg));
+
+    uiWidgetPlacement(XtParent(psgfx->FormWdg),
+                     uiTopLevel.GlobalSettings.PageSettingsPlacement);
+
+    uiupdatepsvariables();
+
+    return UI_OK;
+}
+
+
+void uiPageSettingsUpdateDialog()
+{
+    if (uiTopLevel.PageSettingsGfx.FormWdg) {
+       if (uiPageInfo.CurrentPage) {
+           uibindpsvariables();
+           uiupdatepsvariables();
+       } else
+           XtUnmapWidget(XtParent(uiTopLevel.PageSettingsGfx.FormWdg));
+    }
+}
+
+
+static void uibindpsvariables()
+{
+    UiBindVariable("TopMargin",
+                  (void *) &uiPageInfo.CurrentPage->Settings.TopMargin,
+                  uiVTint);
+    UiBindVariable("BottomMargin",
+                (void *) &uiPageInfo.CurrentPage->Settings.BottomMargin,
+                  uiVTint);
+    UiBindVariable("LeftMargin",
+                  (void *) &uiPageInfo.CurrentPage->Settings.LeftMargin,
+                  uiVTint);
+    UiBindVariable("RightMargin",
+                  (void *) &uiPageInfo.CurrentPage->Settings.RightMargin,
+                  uiVTint);
+
+    UiBindVariable("UseFixed",
+                  (void *) &uiPageInfo.CurrentPage->Settings.UseFixed,
+                  uiVTint);
+    UiBindVariable("FixedWidth",
+                  (void *) &uiPageInfo.CurrentPage->Settings.FixedWidth,
+                  uiVTint);
+    UiBindVariable("OnePageMode",
+                  (void *) &uiPageInfo.CurrentPage->Settings.OnePageMode,
+                  uiVTint);
+}
+
+
+static void uiupdatepsvariables()
+{
+    UiUpdateVariable("TopMargin");
+    UiUpdateVariable("BottomMargin");
+    UiUpdateVariable("LeftMargin");
+    UiUpdateVariable("RightMargin");
+
+    UiUpdateVariable("UseFixed");
+    UiUpdateVariable("FixedWidth");
+    UiUpdateVariable("OnePageMode");
+}
+
+
+static Widget
+ uicreatepsformdialog()
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget formwdg;
+    Widget topwdg;
+
+    topwdg = XtCreateApplicationShell("PageSettings",
+                                     topLevelShellWidgetClass,
+                                     NULL, 0);
+    XtVaSetValues(topwdg,
+                 XmNtitle, UI_SETTINGS_TITLE, NULL);
+
+    args = uiVaSetArgs(&nargs,
+                      XmNresizePolicy, XmRESIZE_NONE,
+                      XmNautoUnmanage, FALSE, NULL);
+    formwdg = XmCreateForm(topwdg, "PageSettings", args, nargs);
+
+    return formwdg;
+}
+
+
+static Widget
+ uicreatepslabel(formwdg)
+Widget formwdg;
+{
+    ArgList args;
+    Cardinal nargs;
+    XmString labelstr;
+    Widget labelwdg;
+
+    labelstr = XmStringCreateSimple("Define Margins:");
+    args = uiVaSetArgs(&nargs,
+                      XmNlabelString, labelstr,
+                      XmNtopAttachment, XmATTACH_FORM,
+                      XmNtopOffset, UI_PAGESETTINGS_WDG_OFFSET,
+                      XmNleftAttachment, XmATTACH_FORM,
+                      XmNrightAttachment, XmATTACH_FORM, NULL);
+    labelwdg = XmCreateLabelGadget(formwdg, "TextLabel", args, nargs);
+    XtManageChild(labelwdg);
+    XmStringFree(labelstr);
+
+    return labelwdg;
+}
+
+
+static uiActionData_t uiactiondata[8] =
+{
+    {"LArrowDown", (uiPage_t *) NULL},
+    {"LArrowUp", (uiPage_t *) NULL},
+    {"RArrowDown", (uiPage_t *) NULL},
+    {"RArrowUp", (uiPage_t *) NULL},
+    {"TArrowDown", (uiPage_t *) NULL},
+    {"TArrowUp", (uiPage_t *) NULL},
+    {"BArrowDown", (uiPage_t *) NULL},
+    {"BArrowUp", (uiPage_t *) NULL}
+};
+
+static Widget uipstextwidget[] =
+{
+    (Widget) NULL,
+    (Widget) NULL,
+    (Widget) NULL,
+    (Widget) NULL
+};
+
+static Widget
+ uicreatepsmargin(formwdg, topwdg, name, pos)
+Widget formwdg;
+Widget topwdg;
+char *name;
+int pos;
+{
+    ArgList args;
+    Cardinal nargs;
+    XmString labelstr;
+    static int callnr = 0;
+    Widget marginformwdg, labelwdg;
+    Widget margindownwdg, marginupwdg, textwdg;
+    static char textvar[4][13];        /* strlen("BottomMargin") */
+    char *text;
+
+    args = uiVaSetArgs(&nargs,
+                      XmNtopAttachment, XmATTACH_WIDGET,
+                      XmNtopWidget, topwdg,
+                      XmNtopOffset, UI_PAGESETTINGS_WDG_OFFSET,
+                      XmNleftAttachment, XmATTACH_POSITION,
+                      XmNleftPosition, 5 + 50 * (pos == UI_RIGHT),
+                      XmNrightAttachment, XmATTACH_POSITION,
+                   XmNrightPosition, 45 + 50 * (pos == UI_RIGHT), NULL);
+    marginformwdg = XmCreateForm(formwdg, "MarginForm", args, nargs);
+    XtManageChild(marginformwdg);
+
+    labelstr = XmStringCreateSimple(name);
+    args = uiVaSetArgs(&nargs,
+                      XmNlabelString, labelstr,
+                      XmNalignment, XmALIGNMENT_BEGINNING,
+                      XmNtopAttachment, XmATTACH_FORM,
+                      XmNleftAttachment, XmATTACH_POSITION,
+                      XmNleftPosition, 5,
+                      XmNrightAttachment, XmATTACH_POSITION,
+                      XmNrightPosition, 40,
+                      XmNbottomAttachment, XmATTACH_FORM, NULL);
+    labelwdg = XmCreateLabelGadget(marginformwdg, "TextLabel", args, nargs);
+    XtManageChild(labelwdg);
+    XmStringFree(labelstr);
+
+    args = uiVaSetArgs(&nargs,
+                      XmNarrowDirection, XmARROW_DOWN,
+                      XmNwidth, 15,
+                      XmNheight, 5,
+                      XmNtopAttachment, XmATTACH_POSITION,
+                      XmNtopPosition, 50,
+                      XmNrightAttachment, XmATTACH_POSITION,
+                      XmNrightPosition, 95,
+                      XmNbottomAttachment, XmATTACH_FORM, NULL);
+    margindownwdg = XmCreateArrowButtonGadget(marginformwdg,
+                                        uiactiondata[callnr].ActionName,
+                                             args, nargs);
+    uiactiondata[callnr].Page = uiPageInfo.CurrentPage;
+    XtAddCallback(margindownwdg, XmNactivateCallback,
+                 (XtCallbackProc) uiDialogActivateCB,
+                 (caddr_t) & uiactiondata[callnr]);
+    UiAttachCallback(uiactiondata[callnr].ActionName, uipagesettingsmargincb,
+                    uiactiondata[callnr].ActionName);
+    callnr++;
+    XtManageChild(margindownwdg);
+
+    args = uiVaSetArgs(&nargs,
+                      XmNarrowDirection, XmARROW_UP,
+                      XmNwidth, 15,
+                      XmNheight, 5,
+                      XmNrightAttachment, XmATTACH_POSITION,
+                      XmNrightPosition, 95,
+                      XmNtopAttachment, XmATTACH_FORM,
+                      XmNbottomAttachment, XmATTACH_POSITION,
+                      XmNbottomPosition, 50, NULL);
+    marginupwdg = XmCreateArrowButtonGadget(marginformwdg, "ArrowDown",
+                                           args, nargs);
+    uiactiondata[callnr].Page = uiPageInfo.CurrentPage;
+    XtAddCallback(marginupwdg, XmNactivateCallback,
+                 (XtCallbackProc) uiDialogActivateCB,
+                 (caddr_t) & uiactiondata[callnr]);
+    UiAttachCallback(uiactiondata[callnr].ActionName, uipagesettingsmargincb,
+                    uiactiondata[callnr].ActionName);
+    callnr++;
+    XtManageChild(marginupwdg);
+
+    text = textvar[callnr / 2 - 1];
+    sprintf(text, "%sMargin", name);
+    args = uiVaSetArgs(&nargs,
+                      XmNcolumns, 4,
+                      XmNtopAttachment, XmATTACH_FORM,
+                      XmNrightAttachment, XmATTACH_WIDGET,
+                      XmNrightWidget, margindownwdg,
+                      XmNbottomAttachment, XmATTACH_FORM, NULL);
+    textwdg = XmCreateText(marginformwdg, text, args, nargs);
+    uipstextwidget[callnr / 2 - 1] = textwdg;
+    XtAddCallback(textwdg, XmNactivateCallback,
+                 (XtCallbackProc) uiDialogVariableCB, (caddr_t) text);
+    XtAddCallback(textwdg, XmNlosingFocusCallback,
+                 (XtCallbackProc) uiDialogVariableCB, (caddr_t) text);
+    XtAddCallback(textwdg, XmNvalueChangedCallback,
+                 (XtCallbackProc) uiDialogVariableCB, (caddr_t) text);
+    (void) uiAddWidgetInfo(text, textwdg, uiWTtext);   /* ignore */
+    XtManageChild(textwdg);
+
+    return marginformwdg;
+}
+
+
+static Widget
+ uicreatepsseparator(formwdg, topwdg)
+Widget formwdg;
+Widget topwdg;
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget separatorwdg;
+
+    args = uiVaSetArgs(&nargs,
+                      XmNtopAttachment, XmATTACH_WIDGET,
+                      XmNtopWidget, topwdg,
+                      XmNtopOffset, UI_PAGESETTINGS_WDG_OFFSET,
+                      XmNleftAttachment, XmATTACH_FORM,
+                      XmNrightAttachment, XmATTACH_FORM, NULL);
+    separatorwdg = XmCreateSeparatorGadget(formwdg, "PSSeparator",
+                                          args, nargs);
+    XtManageChild(separatorwdg);
+
+    return separatorwdg;
+}
+
+
+static Widget
+ uicreatepsusefixed(formwdg, topwdg)
+Widget formwdg;
+Widget topwdg;
+{
+    XmString labelstr;
+    ArgList args;
+    Cardinal nargs;
+    Widget tmpformwdg, usefixedwdg;
+    Widget textwdg, usefixeddownwdg, usefixedupwdg;
+    static uiActionData_t actiondata[2];
+
+    labelstr = XmStringCreateSimple("Use Fixed Width");
+    args = uiVaSetArgs(&nargs,
+                      XmNtopAttachment, XmATTACH_WIDGET,
+                      XmNtopWidget, topwdg,
+                      XmNtopOffset, UI_PAGESETTINGS_WDG_OFFSET,
+                      XmNleftAttachment, XmATTACH_POSITION,
+                      XmNleftPosition, 20, NULL);
+    tmpformwdg = XmCreateForm(formwdg, "UseFixedForm", args, nargs);
+    XtManageChild(tmpformwdg);
+
+    args = uiVaSetArgs(&nargs,
+                      XmNlabelString, labelstr,
+                      XmNtopAttachment, XmATTACH_FORM,
+                      XmNleftAttachment, XmATTACH_FORM,
+                      XmNbottomAttachment, XmATTACH_FORM, NULL);
+    usefixedwdg = XmCreateToggleButtonGadget(tmpformwdg, "UseFixed",
+                                            args, nargs);
+    XtAddCallback(usefixedwdg, XmNvalueChangedCallback,
+                 (XtCallbackProc) uiDialogVariableCB,
+                 (caddr_t) "UseFixed");
+    /* Ignore */
+    (void) uiAddWidgetInfo("UseFixed", usefixedwdg, uiWTcheckbutton);
+    XtManageChild(usefixedwdg);
+
+    args = uiVaSetArgs(&nargs,
+                      XmNcolumns, 4,
+                      XmNtopAttachment, XmATTACH_FORM,
+                      XmNbottomAttachment, XmATTACH_FORM,
+                      XmNleftAttachment, XmATTACH_WIDGET,
+                      XmNleftWidget, usefixedwdg,
+                      XmNleftOffset, UI_PAGESETTINGS_WDG_OFFSET, NULL);
+    textwdg = XmCreateText(tmpformwdg, "FixedWidth", args, nargs);
+    uiTopLevel.PageSettingsGfx.UseFixedTextWdg = textwdg;
+    XtAddCallback(textwdg, XmNactivateCallback,
+                 (XtCallbackProc) uiDialogVariableCB,
+                 (caddr_t) "FixedWidth");
+    XtAddCallback(textwdg, XmNlosingFocusCallback,
+                 (XtCallbackProc) uiDialogVariableCB,
+                 (caddr_t) "FixedWidth");
+    XtAddCallback(textwdg, XmNvalueChangedCallback,
+                 (XtCallbackProc) uiDialogVariableCB,
+                 (caddr_t) "FixedWidth");
+    /* Ignore */
+    (void) uiAddWidgetInfo("FixedWidth", textwdg, uiWTtext);
+    XtManageChild(textwdg);
+
+    args = uiVaSetArgs(&nargs,
+                      XmNarrowDirection, XmARROW_DOWN,
+                      XmNwidth, 15,
+                      XmNheight, 5,
+                      XmNbottomAttachment, XmATTACH_FORM,
+                      XmNrightAttachment, XmATTACH_FORM,
+                      XmNleftAttachment, XmATTACH_WIDGET,
+                      XmNleftWidget, textwdg,
+                      XmNtopAttachment, XmATTACH_POSITION,
+                      XmNtopPosition, 50, NULL);
+    usefixeddownwdg = XmCreateArrowButtonGadget(tmpformwdg, "UseFixedDown",
+                                               args, nargs);
+    actiondata[0].ActionName = "UseFixedDown";
+    actiondata[0].Page = uiPageInfo.CurrentPage;
+    XtAddCallback(usefixeddownwdg, XmNactivateCallback,
+                 (XtCallbackProc) uiDialogActivateCB,
+                 (caddr_t) & actiondata[0]);
+    UiAttachCallback("UseFixedDown", uipagesettingsusefixedcb, "UseFixedDown");
+    XtManageChild(usefixeddownwdg);
+
+    args = uiVaSetArgs(&nargs,
+                      XmNarrowDirection, XmARROW_UP,
+                      XmNwidth, 15,
+                      XmNheight, 5,
+                      XmNtopAttachment, XmATTACH_FORM,
+                      XmNrightAttachment, XmATTACH_FORM,
+                      XmNleftAttachment, XmATTACH_WIDGET,
+                      XmNleftWidget, textwdg,
+                      XmNbottomAttachment, XmATTACH_POSITION,
+                      XmNbottomPosition, 50, NULL);
+    usefixedupwdg = XmCreateArrowButtonGadget(tmpformwdg, "UseFixedUp",
+                                             args, nargs);
+    actiondata[1].ActionName = "UseFixedUp";
+    actiondata[1].Page = uiPageInfo.CurrentPage;
+    XtAddCallback(usefixedupwdg, XmNactivateCallback,
+                 (XtCallbackProc) uiDialogActivateCB,
+                 (caddr_t) & actiondata[1]);
+    UiAttachCallback("UseFixedUp", uipagesettingsusefixedcb, "UseFixedUp");
+    XtManageChild(usefixedupwdg);
+
+    return tmpformwdg;
+}
+
+
+static Widget
+ uicreatepssinglepage(formwdg, usefixedwdg)
+Widget formwdg;
+Widget usefixedwdg;
+{
+    XmString labelstr;
+    ArgList args;
+    Cardinal nargs;
+    Widget singlepagewdg;
+
+    labelstr = XmStringCreateSimple("Single Page Mode");
+    args = uiVaSetArgs(&nargs,
+                      XmNlabelString, labelstr,
+                      XmNtopAttachment, XmATTACH_WIDGET,
+                      XmNtopWidget, usefixedwdg,
+                      XmNtopOffset, UI_PAGESETTINGS_WDG_OFFSET,
+                      XmNleftAttachment, XmATTACH_POSITION,
+                      XmNleftPosition, 20, NULL);
+    singlepagewdg = XmCreateToggleButtonGadget(formwdg, "OnePageMode",
+                                              args, nargs);
+    XtAddCallback(singlepagewdg, XmNvalueChangedCallback,
+                 (XtCallbackProc) uiDialogVariableCB,
+                 (caddr_t) "OnePageMode");
+    /* Ignore */
+    (void) uiAddWidgetInfo("OnePageMode", singlepagewdg, uiWTcheckbutton);
+    XtManageChild(singlepagewdg);
+
+    return singlepagewdg;
+}
+
+
+static void uicreatepsbuttons(formwdg, topwdg)
+Widget formwdg;
+Widget topwdg;
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget okwdg, applywdg, closewdg;
+    static uiActionData_t actiondata[3];
+
+    args = uiVaSetArgs(&nargs,
+                      XmNtopAttachment, XmATTACH_WIDGET,
+                      XmNtopWidget, topwdg,
+                      XmNtopOffset, UI_PAGESETTINGS_WDG_OFFSET,
+                      XmNleftAttachment, XmATTACH_POSITION,
+                      XmNleftPosition, 5,
+                      XmNrightAttachment, XmATTACH_POSITION,
+                      XmNrightPosition, 25,
+                      XmNbottomAttachment, XmATTACH_FORM,
+                      XmNbottomOffset, 10, NULL);
+    okwdg = XmCreatePushButtonGadget(formwdg, "Ok", args, nargs);
+    actiondata[0].ActionName = "PSOk";
+    actiondata[0].Page = uiPageInfo.CurrentPage;
+    XtAddCallback(okwdg, XmNactivateCallback,
+                 (XtCallbackProc) uiDialogActivateCB,
+                 (caddr_t) & actiondata[0]);
+    UiAttachCallback("PSOk", uipagesettingsbuttoncb, "PSOk");
+    XtManageChild(okwdg);
+
+    args = uiVaSetArgs(&nargs,
+                      XmNtopAttachment, XmATTACH_WIDGET,
+                      XmNtopWidget, topwdg,
+                      XmNtopOffset, UI_PAGESETTINGS_WDG_OFFSET,
+                      XmNleftAttachment, XmATTACH_POSITION,
+                      XmNleftPosition, 40,
+                      XmNrightAttachment, XmATTACH_POSITION,
+                      XmNrightPosition, 60,
+                      XmNbottomAttachment, XmATTACH_FORM,
+                      XmNbottomOffset, 10, NULL);
+    applywdg = XmCreatePushButtonGadget(formwdg, "Apply", args, nargs);
+    actiondata[1].ActionName = "PSApply";
+    actiondata[1].Page = uiPageInfo.CurrentPage;
+    XtAddCallback(applywdg, XmNactivateCallback,
+                 (XtCallbackProc) uiDialogActivateCB,
+                 (caddr_t) & actiondata[1]);
+    UiAttachCallback("PSApply", uipagesettingsbuttoncb, "PSApply");
+    XtManageChild(applywdg);
+
+    args = uiVaSetArgs(&nargs,
+                      XmNtopAttachment, XmATTACH_WIDGET,
+                      XmNtopWidget, topwdg,
+                      XmNtopOffset, UI_PAGESETTINGS_WDG_OFFSET,
+                      XmNleftAttachment, XmATTACH_POSITION,
+                      XmNleftPosition, 75,
+                      XmNrightAttachment, XmATTACH_POSITION,
+                      XmNrightPosition, 95,
+                      XmNbottomAttachment, XmATTACH_FORM,
+                      XmNbottomOffset, 10, NULL);
+    closewdg = XmCreatePushButtonGadget(formwdg, "Close", args, nargs);
+    actiondata[2].ActionName = "PSClose";
+    actiondata[2].Page = uiPageInfo.CurrentPage;
+    XtAddCallback(closewdg, XmNactivateCallback,
+                 (XtCallbackProc) uiDialogActivateCB,
+                 (caddr_t) & actiondata[2]);
+    UiAttachCallback("PSClose", uipagesettingsbuttoncb, "PSClose");
+    XtManageChild(closewdg);
+}
+
+
+static void uipagesettingsmargincb(address, htext, htextobject, parameter)
+char *address;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    int i;
+    Widget textwdg;
+    char *text;
+    int margin;
+    char tmpbuffer[4];
+
+    for (i = 0; i < 8; i++)
+       if (!strcmp(uiactiondata[i].ActionName, (char *) parameter)) {
+           textwdg = uipstextwidget[i / 2];
+           text = XmTextGetString(textwdg);
+           margin = atoi(text);
+           if (i % 2) {
+               margin += 10;
+               if (margin > 9999)
+                   margin = 9999;
+               sprintf(tmpbuffer, "%d", margin);
+               XmTextSetString(textwdg, tmpbuffer);
+           } else {
+               margin = (margin - 10) * (margin > 9);
+               sprintf(tmpbuffer, "%d", margin);
+               XmTextSetString(textwdg, tmpbuffer);
+           }
+           XtFree(text);
+
+           return;
+       }
+}
+
+
+static void uipagesettingsusefixedcb(address, htext, htextobject, parameter)
+char *address;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    Widget textwdg = uiTopLevel.PageSettingsGfx.UseFixedTextWdg;
+    char *fixedtext;
+    int width;
+    char tmpbuffer[4];
+
+    fixedtext = XmTextGetString(textwdg);
+    width = atoi(fixedtext);
+
+    if (!strcmp("UseFixedDown", (char *) parameter)) {
+       if (width) {
+           width = (width - 10) * (width > 9);
+           sprintf(tmpbuffer, "%d", width);
+           XmTextSetString(textwdg, tmpbuffer);
+       }
+    } else {
+       width += 10;
+       if (width > 9999)
+           width = 9999;
+       sprintf(tmpbuffer, "%d", width);
+       XmTextSetString(textwdg, tmpbuffer);
+    }
+
+    XtFree(fixedtext);
+}
+
+
+static void uipagesettingsbuttoncb(address, htext, htextobject, parameter)
+char *address;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    uiPage_t *page = uiPageInfo.CurrentPage;
+
+    if (!strcmp("PSOk", (char *) parameter)) {
+       XlClearWindow(page->Layout.Width, page->Layout.Height, page->HText);
+       uiPageUpdateWindow(page);
+       XtUnmapWidget(XtParent(uiTopLevel.PageSettingsGfx.FormWdg));
+    } else if (!strcmp("PSApply", (char *) parameter)) {
+       XlClearWindow(page->Layout.Width, page->Layout.Height,
+                     page->HText);
+       uiPageUpdateWindow(page);
+    } else if (!strcmp("PSClose", (char *) parameter))
+       XtUnmapWidget(XtParent(uiTopLevel.PageSettingsGfx.FormWdg));
+    else                       /* Shouldn't reach this point */
+       uiDisplayWarning("psbuttoncb called with illegal parameter");
+}
diff --git a/Ui/UiPrint.c b/Ui/UiPrint.c
new file mode 100644 (file)
index 0000000..6d6f856
--- /dev/null
@@ -0,0 +1,608 @@
+static char *rcsid = "$Id$";
+
+#include "UiIncludes.h"
+
+
+static Widget uicreateprintformdialog();
+static Widget uicreateprintcmd(Widget formwdg);
+static Widget
+ uicreateprintmargin(Widget formwdg, Widget topwdg,
+                     char *name, char *labeltext, int pos);
+static Widget uicreateprintseparator(Widget formwdg, Widget topwdg);
+static Widget uicreateprintwidth(Widget formwdg, Widget topwdg);
+static Widget uicreateprintfile(Widget formwdg, Widget topwdg);
+static void uicreateprintbuttons(Widget formwdg, Widget topwdg);
+static void uiprintmargincb(char *address, HText_t * htext,
+                            HTextObject_t * htextobject,
+                            void *parameter);
+static void uiprintwidthcb(char *address, HText_t * htext,
+                           HTextObject_t * htextobject,
+                           void *parameter);
+static void uiprintbuttoncb(char *address, HText_t * htext,
+                            HTextObject_t * htextobject,
+                            void *parameter);
+
+
+static uiActionData_t uiactiondata[8] =
+{
+    {"LArrowDown", (uiPage_t *) NULL},
+    {"LArrowUp", (uiPage_t *) NULL},
+    {"RArrowDown", (uiPage_t *) NULL},
+    {"RArrowUp", (uiPage_t *) NULL},
+    {"TArrowDown", (uiPage_t *) NULL},
+    {"TArrowUp", (uiPage_t *) NULL},
+    {"BArrowDown", (uiPage_t *) NULL},
+    {"BArrowUp", (uiPage_t *) NULL}
+};
+
+
+static Widget uiprinttextwidget[] =
+{
+    (Widget) NULL,
+    (Widget) NULL,
+    (Widget) NULL,
+    (Widget) NULL
+};
+
+
+int UiDisplayPrintDialog(type)
+int type;
+{
+    uiPrintGfx_t *printgfx = &uiTopLevel.PrintGfx;
+    Widget separatorwdg, tmpwdg;
+
+
+    if (printgfx->FormWdg) {
+       XtMapWidget(XtParent(printgfx->FormWdg));
+
+       return UI_OK;
+    }
+    printgfx->FormWdg = uicreateprintformdialog();
+
+    printgfx->PrintCmdWdg = uicreateprintcmd(printgfx->FormWdg);
+    printgfx->PrintFileWdg = uicreateprintfile(printgfx->FormWdg,
+                                              printgfx->PrintCmdWdg);
+
+    printgfx->LeftMarginWdg = uicreateprintmargin(printgfx->FormWdg,
+                                                 printgfx->PrintFileWdg,
+                                                 "PrintLeft", "Left",
+                                                 UI_LEFT);
+    printgfx->RightMarginWdg =
+       uicreateprintmargin(printgfx->FormWdg, printgfx->LeftMarginWdg,
+                           "PrintRight", "Right", UI_LEFT);
+    printgfx->TopMarginWdg = uicreateprintmargin(printgfx->FormWdg,
+                                                printgfx->PrintFileWdg,
+                                           "PrintTop", "Top", UI_RIGHT);
+    printgfx->BottomMarginWdg =
+       uicreateprintmargin(printgfx->FormWdg, printgfx->TopMarginWdg,
+                           "PrintBottom", "Bottom", UI_RIGHT);
+
+    tmpwdg = uicreateprintwidth(printgfx->FormWdg, printgfx->BottomMarginWdg);
+
+    separatorwdg = uicreateprintseparator(printgfx->FormWdg, tmpwdg);
+    uicreateprintbuttons(printgfx->FormWdg, separatorwdg);
+    XtManageChild(printgfx->FormWdg);
+    XtRealizeWidget(XtParent(printgfx->FormWdg));
+
+    return UI_OK;
+}
+
+
+void uiPrintUpdateDialog()
+{
+    if (uiTopLevel.PrintGfx.FormWdg) {
+       if (uiPageInfo.CurrentPage) {
+       } else
+           XtUnmapWidget(XtParent(uiTopLevel.PrintGfx.FormWdg));
+    }
+}
+
+
+static Widget
+ uicreateprintformdialog()
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget formwdg;
+    Widget topwdg;
+
+    topwdg = XtCreateApplicationShell("Print",
+                                     topLevelShellWidgetClass,
+                                     NULL, 0);
+    XtVaSetValues(topwdg,
+                 XmNtitle, UI_PRINT_TITLE, NULL);
+
+    args = uiVaSetArgs(&nargs,
+                      XmNresizePolicy, XmRESIZE_NONE,
+                      XmNautoUnmanage, FALSE, NULL);
+    formwdg = XmCreateForm(topwdg, "Print", args, nargs);
+
+    return formwdg;
+}
+
+
+static Widget
+ uicreateprintmargin(formwdg, topwdg, name, labeltext, pos)
+Widget formwdg;
+Widget topwdg;
+char *name;
+char *labeltext;
+int pos;
+{
+    ArgList args;
+    Cardinal nargs;
+    XmString labelstr;
+    static int callnr = 0;
+    Widget marginformwdg, labelwdg;
+    Widget margindownwdg, marginupwdg, textwdg;
+    static char textvar[4][18];        /* strlen("PrintBottomMargin") */
+    char *text;
+
+    args = uiVaSetArgs(&nargs,
+                      XmNtopAttachment, XmATTACH_WIDGET,
+                      XmNtopWidget, topwdg,
+                      XmNtopOffset, UI_PRINT_WDG_OFFSET,
+                      XmNleftAttachment, XmATTACH_POSITION,
+                      XmNleftPosition, 5 + 50 * (pos == UI_RIGHT),
+                      XmNrightAttachment, XmATTACH_POSITION,
+                   XmNrightPosition, 45 + 50 * (pos == UI_RIGHT), NULL);
+    marginformwdg = XmCreateForm(formwdg, "MarginForm", args, nargs);
+    XtManageChild(marginformwdg);
+
+    labelstr = XmStringCreateSimple(labeltext);
+    args = uiVaSetArgs(&nargs,
+                      XmNlabelString, labelstr,
+                      XmNalignment, XmALIGNMENT_BEGINNING,
+                      XmNtopAttachment, XmATTACH_FORM,
+                      XmNleftAttachment, XmATTACH_POSITION,
+                      XmNleftPosition, 5,
+                      XmNrightAttachment, XmATTACH_POSITION,
+                      XmNrightPosition, 40,
+                      XmNbottomAttachment, XmATTACH_FORM, NULL);
+    labelwdg = XmCreateLabelGadget(marginformwdg, "TextLabel", args, nargs);
+    XtManageChild(labelwdg);
+    XmStringFree(labelstr);
+
+    args = uiVaSetArgs(&nargs,
+                      XmNarrowDirection, XmARROW_DOWN,
+                      XmNwidth, 15,
+                      XmNheight, 5,
+                      XmNtopAttachment, XmATTACH_POSITION,
+                      XmNtopPosition, 50,
+                      XmNrightAttachment, XmATTACH_POSITION,
+                      XmNrightPosition, 95,
+                      XmNbottomAttachment, XmATTACH_FORM, NULL);
+    margindownwdg = XmCreateArrowButtonGadget(marginformwdg,
+                                        uiactiondata[callnr].ActionName,
+                                             args, nargs);
+    uiactiondata[callnr].Page = uiPageInfo.CurrentPage;
+    XtAddCallback(margindownwdg, XmNactivateCallback,
+                 (XtCallbackProc) uiDialogActivateCB,
+                 (caddr_t) & uiactiondata[callnr]);
+    UiAttachCallback(uiactiondata[callnr].ActionName, uiprintmargincb,
+                    uiactiondata[callnr].ActionName);
+    callnr++;
+    XtManageChild(margindownwdg);
+
+    args = uiVaSetArgs(&nargs,
+                      XmNarrowDirection, XmARROW_UP,
+                      XmNwidth, 15,
+                      XmNheight, 5,
+                      XmNrightAttachment, XmATTACH_POSITION,
+                      XmNrightPosition, 95,
+                      XmNtopAttachment, XmATTACH_FORM,
+                      XmNbottomAttachment, XmATTACH_POSITION,
+                      XmNbottomPosition, 50, NULL);
+    marginupwdg = XmCreateArrowButtonGadget(marginformwdg, "ArrowDown",
+                                           args, nargs);
+    uiactiondata[callnr].Page = uiPageInfo.CurrentPage;
+    XtAddCallback(marginupwdg, XmNactivateCallback,
+                 (XtCallbackProc) uiDialogActivateCB,
+                 (caddr_t) & uiactiondata[callnr]);
+    UiAttachCallback(uiactiondata[callnr].ActionName, uiprintmargincb,
+                    uiactiondata[callnr].ActionName);
+    callnr++;
+    XtManageChild(marginupwdg);
+
+    text = textvar[callnr / 2 - 1];
+    sprintf(text, "%sMargin", name);
+    args = uiVaSetArgs(&nargs,
+                      XmNcolumns, 4,
+                      XmNtopAttachment, XmATTACH_FORM,
+                      XmNrightAttachment, XmATTACH_WIDGET,
+                      XmNrightWidget, margindownwdg,
+                      XmNbottomAttachment, XmATTACH_FORM,
+                      XmNvalue, "0", NULL);
+    textwdg = XmCreateText(marginformwdg, text, args, nargs);
+    uiprinttextwidget[callnr / 2 - 1] = textwdg;
+    XtAddCallback(textwdg, XmNactivateCallback,
+                 (XtCallbackProc) uiDialogVariableCB, (caddr_t) text);
+    XtAddCallback(textwdg, XmNlosingFocusCallback,
+                 (XtCallbackProc) uiDialogVariableCB, (caddr_t) text);
+    XtAddCallback(textwdg, XmNvalueChangedCallback,
+                 (XtCallbackProc) uiDialogVariableCB, (caddr_t) text);
+    (void) uiAddWidgetInfo(text, textwdg, uiWTtext);   /* ignore */
+    XtManageChild(textwdg);
+
+    return marginformwdg;
+}
+
+
+static Widget
+ uicreateprintseparator(formwdg, topwdg)
+Widget formwdg;
+Widget topwdg;
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget separatorwdg;
+
+    args = uiVaSetArgs(&nargs,
+                      XmNtopAttachment, XmATTACH_WIDGET,
+                      XmNtopWidget, topwdg,
+                      XmNtopOffset, UI_PRINT_WDG_OFFSET,
+                      XmNleftAttachment, XmATTACH_FORM,
+                      XmNrightAttachment, XmATTACH_FORM, NULL);
+    separatorwdg = XmCreateSeparatorGadget(formwdg, "PRINTSeparator",
+                                          args, nargs);
+    XtManageChild(separatorwdg);
+
+    return separatorwdg;
+}
+
+
+static Widget
+ uicreateprintcmd(formwdg)
+Widget formwdg;
+{
+    XmString labelstr;
+    ArgList args;
+    Cardinal nargs;
+    Widget tmpformwdg;
+    Widget labelwdg;
+    Widget textwdg;
+    static uiActionData_t actiondata[2];
+
+    labelstr = XmStringCreateSimple("Print command");
+    args = uiVaSetArgs(&nargs,
+                      XmNtopAttachment, XmATTACH_FORM,
+                      XmNtopOffset, UI_PRINT_WDG_OFFSET,
+                      XmNrightAttachment, XmATTACH_FORM,
+                      XmNrightOffset, UI_PRINT_WDG_OFFSET,
+                      XmNleftAttachment, XmATTACH_FORM,
+                      XmNleftOffset, UI_PRINT_WDG_OFFSET, NULL);
+    tmpformwdg = XmCreateForm(formwdg, "PrintcmdForm", args, nargs);
+    XtManageChild(tmpformwdg);
+
+    args = uiVaSetArgs(&nargs,
+                      XmNlabelString, labelstr,
+                      XmNtopAttachment, XmATTACH_FORM,
+                      XmNleftAttachment, XmATTACH_FORM,
+                      XmNbottomAttachment, XmATTACH_FORM, NULL);
+    labelwdg = XmCreateLabelGadget(tmpformwdg, "Label", args, nargs);
+    XtManageChild(labelwdg);
+
+    args = uiVaSetArgs(&nargs,
+                      XmNtopAttachment, XmATTACH_FORM,
+                      XmNbottomAttachment, XmATTACH_FORM,
+                      XmNrightAttachment, XmATTACH_WIDGET,
+                      XmNleftAttachment, XmATTACH_WIDGET,
+                      XmNleftWidget, labelwdg,
+                      XmNleftOffset, UI_PRINT_WDG_OFFSET,
+                      XmNvalue, "lpr", NULL);
+    textwdg = XmCreateText(tmpformwdg, "PrintCmd", args, nargs);
+    uiTopLevel.PrintGfx.WidthWdg = textwdg;
+    XtAddCallback(textwdg, XmNactivateCallback,
+                 (XtCallbackProc) uiDialogVariableCB,
+                 (caddr_t) "PrintCommand");
+    XtAddCallback(textwdg, XmNlosingFocusCallback,
+                 (XtCallbackProc) uiDialogVariableCB,
+                 (caddr_t) "PrintCommand");
+    XtAddCallback(textwdg, XmNvalueChangedCallback,
+                 (XtCallbackProc) uiDialogVariableCB,
+                 (caddr_t) "PrintCommand");
+    /* Ignore */
+    (void) uiAddWidgetInfo("PrintCommand", textwdg, uiWTtext);
+    XtManageChild(textwdg);
+
+    return tmpformwdg;
+}
+
+
+static Widget
+ uicreateprintfile(formwdg, topwdg)
+Widget formwdg;
+Widget topwdg;
+{
+    XmString labelstr;
+    ArgList args;
+    Cardinal nargs;
+    Widget tmpformwdg, widthwdg;
+    Widget textwdg;
+    static uiActionData_t actiondata[2];
+
+    labelstr = XmStringCreateSimple("Print to a file:");
+    args = uiVaSetArgs(&nargs,
+                      XmNtopAttachment, XmATTACH_WIDGET,
+                      XmNtopWidget, topwdg,
+                      XmNtopOffset, UI_PRINT_WDG_OFFSET,
+                      XmNrightAttachment, XmATTACH_FORM,
+                      XmNrightOffset, UI_PRINT_WDG_OFFSET,
+                      XmNleftAttachment, XmATTACH_FORM,
+                      XmNleftOffset, UI_PRINT_WDG_OFFSET, NULL);
+    tmpformwdg = XmCreateForm(formwdg, "FileForm", args, nargs);
+    XtManageChild(tmpformwdg);
+
+    args = uiVaSetArgs(&nargs,
+                      XmNlabelString, labelstr,
+                      XmNtopAttachment, XmATTACH_FORM,
+                      XmNleftAttachment, XmATTACH_FORM,
+                      XmNbottomAttachment, XmATTACH_FORM, NULL);
+    widthwdg = XmCreateToggleButtonGadget(tmpformwdg, "PrintToFile",
+                                         args, nargs);
+    XtAddCallback(widthwdg, XmNvalueChangedCallback,
+                 (XtCallbackProc) uiDialogVariableCB,
+                 (caddr_t) "PrintToFile");
+    /* Ignore */
+    (void) uiAddWidgetInfo("PrintToFile", widthwdg, uiWTcheckbutton);
+    XtManageChild(widthwdg);
+
+    args = uiVaSetArgs(&nargs,
+                      XmNtopAttachment, XmATTACH_FORM,
+                      XmNbottomAttachment, XmATTACH_FORM,
+                      XmNrightAttachment, XmATTACH_FORM,
+                      XmNleftAttachment, XmATTACH_WIDGET,
+                      XmNleftWidget, widthwdg,
+                      XmNvalue, "foobar.www", NULL);
+    textwdg = XmCreateText(tmpformwdg, "PrintFileName", args, nargs);
+    uiTopLevel.PrintGfx.WidthWdg = textwdg;
+    XtAddCallback(textwdg, XmNactivateCallback,
+                 (XtCallbackProc) uiDialogVariableCB,
+                 (caddr_t) "PrintFileName");
+    XtAddCallback(textwdg, XmNlosingFocusCallback,
+                 (XtCallbackProc) uiDialogVariableCB,
+                 (caddr_t) "PrintfileName");
+    XtAddCallback(textwdg, XmNvalueChangedCallback,
+                 (XtCallbackProc) uiDialogVariableCB,
+                 (caddr_t) "PrintFileName");
+    /* Ignore */
+    (void) uiAddWidgetInfo("PrintFileName", textwdg, uiWTtext);
+    XtManageChild(textwdg);
+
+    return tmpformwdg;
+}
+
+
+static Widget
+ uicreateprintwidth(formwdg, topwdg)
+Widget formwdg;
+Widget topwdg;
+{
+    XmString labelstr;
+    ArgList args;
+    Cardinal nargs;
+    Widget tmpformwdg, labelwdg;
+    Widget textwdg, widthdownwdg, widthupwdg;
+    static uiActionData_t actiondata[2];
+
+    labelstr = XmStringCreateSimple("Width");
+    args = uiVaSetArgs(&nargs,
+                      XmNtopAttachment, XmATTACH_WIDGET,
+                      XmNtopWidget, topwdg,
+                      XmNtopOffset, UI_PRINT_WDG_OFFSET,
+                      XmNleftAttachment, XmATTACH_POSITION,
+                      XmNleftPosition, 5,
+                      XmNrightAttachment, XmATTACH_POSITION,
+                      XmNrightPosition, 45, NULL);
+    tmpformwdg = XmCreateForm(formwdg, "WidthForm", args, nargs);
+    XtManageChild(tmpformwdg);
+
+    args = uiVaSetArgs(&nargs,
+                      XmNlabelString, labelstr,
+                      XmNalignment, XmALIGNMENT_BEGINNING,
+                      XmNtopAttachment, XmATTACH_FORM,
+                      XmNleftAttachment, XmATTACH_POSITION,
+                      XmNleftPosition, 5,
+                      XmNrightAttachment, XmATTACH_POSITION,
+                      XmNrightPosition, 40,
+                      XmNbottomAttachment, XmATTACH_FORM, NULL);
+    labelwdg = XmCreateLabelGadget(tmpformwdg, "Label", args, nargs);
+    XtManageChild(labelwdg);
+
+    args = uiVaSetArgs(&nargs,
+                      XmNarrowDirection, XmARROW_DOWN,
+                      XmNwidth, 15,
+                      XmNheight, 5,
+                      XmNtopAttachment, XmATTACH_POSITION,
+                      XmNtopPosition, 50,
+                      XmNrightAttachment, XmATTACH_POSITION,
+                      XmNrightPosition, 95,
+                      XmNbottomAttachment, XmATTACH_FORM, NULL);
+    widthdownwdg = XmCreateArrowButtonGadget(tmpformwdg, "WidthDown",
+                                            args, nargs);
+    actiondata[0].ActionName = "WidthDown";
+    actiondata[0].Page = uiPageInfo.CurrentPage;
+    XtAddCallback(widthdownwdg, XmNactivateCallback,
+                 (XtCallbackProc) uiDialogActivateCB,
+                 (caddr_t) & actiondata[0]);
+    UiAttachCallback("WidthDown", uiprintwidthcb, "WidthDown");
+    XtManageChild(widthdownwdg);
+
+    args = uiVaSetArgs(&nargs,
+                      XmNarrowDirection, XmARROW_UP,
+                      XmNwidth, 15,
+                      XmNheight, 5,
+                      XmNrightAttachment, XmATTACH_POSITION,
+                      XmNrightPosition, 95,
+                      XmNtopAttachment, XmATTACH_FORM,
+                      XmNbottomAttachment, XmATTACH_POSITION,
+                      XmNbottomPosition, 50, NULL);
+    widthupwdg = XmCreateArrowButtonGadget(tmpformwdg, "WidthUp",
+                                          args, nargs);
+    actiondata[1].ActionName = "WidthUp";
+    actiondata[1].Page = uiPageInfo.CurrentPage;
+    XtAddCallback(widthupwdg, XmNactivateCallback,
+                 (XtCallbackProc) uiDialogActivateCB,
+                 (caddr_t) & actiondata[1]);
+    UiAttachCallback("WidthUp", uiprintwidthcb, "WidthUp");
+    XtManageChild(widthupwdg);
+
+    args = uiVaSetArgs(&nargs,
+                      XmNcolumns, 4,
+                      XmNtopAttachment, XmATTACH_FORM,
+                      XmNrightAttachment, XmATTACH_WIDGET,
+                      XmNrightWidget, widthdownwdg,
+                      XmNbottomAttachment, XmATTACH_FORM,
+                      XmNvalue, "80", NULL);
+    textwdg = XmCreateText(tmpformwdg, "PrintWidth", args, nargs);
+    uiTopLevel.PrintGfx.WidthWdg = textwdg;
+    XtAddCallback(textwdg, XmNactivateCallback,
+                 (XtCallbackProc) uiDialogVariableCB,
+                 (caddr_t) "PrintWidth");
+    XtAddCallback(textwdg, XmNlosingFocusCallback,
+                 (XtCallbackProc) uiDialogVariableCB,
+                 (caddr_t) "PrintWidth");
+    XtAddCallback(textwdg, XmNvalueChangedCallback,
+                 (XtCallbackProc) uiDialogVariableCB,
+                 (caddr_t) "PrintWidth");
+    /* Ignore */
+    (void) uiAddWidgetInfo("PrintWidth", textwdg, uiWTtext);
+    XtManageChild(textwdg);
+
+    return tmpformwdg;
+}
+
+
+static void uicreateprintbuttons(formwdg, topwdg)
+Widget formwdg;
+Widget topwdg;
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget okwdg, closewdg;
+    static uiActionData_t actiondata[3];
+
+    args = uiVaSetArgs(&nargs,
+                      XmNtopAttachment, XmATTACH_WIDGET,
+                      XmNtopWidget, topwdg,
+                      XmNtopOffset, UI_PRINT_WDG_OFFSET,
+                      XmNleftAttachment, XmATTACH_POSITION,
+                      XmNleftPosition, 5,
+                      XmNrightAttachment, XmATTACH_POSITION,
+                      XmNrightPosition, 25,
+                      XmNbottomAttachment, XmATTACH_FORM,
+                      XmNbottomOffset, UI_PRINT_WDG_OFFSET, NULL);
+    okwdg = XmCreatePushButtonGadget(formwdg, "Print", args, nargs);
+    actiondata[0].ActionName = "PRINTOk";
+    actiondata[0].Page = uiPageInfo.CurrentPage;
+    XtAddCallback(okwdg, XmNactivateCallback,
+                 (XtCallbackProc) uiDialogActivateCB,
+                 (caddr_t) & actiondata[0]);
+    UiAttachCallback("PRINTOk", uiprintbuttoncb, "PRINTOk");
+    XtManageChild(okwdg);
+
+    args = uiVaSetArgs(&nargs,
+                      XmNtopAttachment, XmATTACH_WIDGET,
+                      XmNtopWidget, topwdg,
+                      XmNtopOffset, UI_PRINT_WDG_OFFSET,
+                      XmNleftAttachment, XmATTACH_POSITION,
+                      XmNleftPosition, 75,
+                      XmNrightAttachment, XmATTACH_POSITION,
+                      XmNrightPosition, 95,
+                      XmNbottomAttachment, XmATTACH_FORM,
+                      XmNbottomOffset, UI_PRINT_WDG_OFFSET, NULL);
+    closewdg = XmCreatePushButtonGadget(formwdg, "Close", args, nargs);
+    actiondata[2].ActionName = "PRINTClose";
+    actiondata[2].Page = uiPageInfo.CurrentPage;
+    XtAddCallback(closewdg, XmNactivateCallback,
+                 (XtCallbackProc) uiDialogActivateCB,
+                 (caddr_t) & actiondata[2]);
+    UiAttachCallback("PRINTClose", uiprintbuttoncb, "PRINTClose");
+    XtManageChild(closewdg);
+}
+
+
+
+static void uiprintmargincb(address, htext, htextobject, parameter)
+char *address;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    int i;
+    Widget textwdg;
+    char *text;
+    int margin;
+    char tmpbuffer[5];
+
+    for (i = 0; i < 8; i++)
+       if (!strcmp(uiactiondata[i].ActionName, (char *) parameter)) {
+           textwdg = uiprinttextwidget[i / 2];
+           text = XmTextGetString(textwdg);
+           margin = atoi(text);
+           if (i % 2) {
+               margin += 1;
+               if (margin > 9999)
+                   margin = 9999;
+               sprintf(tmpbuffer, "%d", margin);
+               XmTextSetString(textwdg, tmpbuffer);
+           } else {
+               margin = (margin - 1) * (margin > 0);
+               sprintf(tmpbuffer, "%d", margin);
+               XmTextSetString(textwdg, tmpbuffer);
+           }
+           XtFree(text);
+
+           return;
+       }
+}
+
+
+static void uiprintwidthcb(address, htext, htextobject, parameter)
+char *address;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    Widget textwdg = uiTopLevel.PrintGfx.WidthWdg;
+    char *fixedtext;
+    int width;
+    char tmpbuffer[5];
+
+    fixedtext = XmTextGetString(textwdg);
+    width = atoi(fixedtext);
+
+    if (!strcmp("WidthDown", (char *) parameter)) {
+       if (width) {
+           width = (width - 5) * (width > 4);
+           sprintf(tmpbuffer, "%d", width);
+           XmTextSetString(textwdg, tmpbuffer);
+       }
+    } else {
+       width += 5;
+       if (width > 9999)
+           width = 9999;
+       sprintf(tmpbuffer, "%d", width);
+       XmTextSetString(textwdg, tmpbuffer);
+    }
+
+    XtFree(fixedtext);
+}
+
+
+static void uiprintbuttoncb(address, htext, htextobject, parameter)
+char *address;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    uiPage_t *page = uiPageInfo.CurrentPage;
+
+    if (!strcmp("PRINTOk", (char *) parameter)) {
+       Print(htext);
+       XtUnmapWidget(XtParent(uiTopLevel.PrintGfx.FormWdg));
+    } else if (!strcmp("PRINTClose", (char *) parameter))
+       XtUnmapWidget(XtParent(uiTopLevel.PrintGfx.FormWdg));
+    else                       /* Shouldn't reach this point */
+       uiDisplayWarning("printbuttoncb called with illegal parameter");
+}
diff --git a/Ui/UiProtos.h b/Ui/UiProtos.h
new file mode 100644 (file)
index 0000000..cabd1bb
--- /dev/null
@@ -0,0 +1,94 @@
+/* $Id: UiProtos.h,v 1.4 1992/03/26 18:13:50 kny Exp kny $ */
+
+
+/*
+ *  Misc. prototypes (external to library)
+ */
+
+extern int fprintf(FILE * stream, char *format,...);
+
+
+/*
+ *  UiInit.c
+ */
+
+extern uiTopLevel_t uiTopLevel;
+extern char **uiSelectionArray;
+extern Cursor uiBusyCursor;
+extern Cursor uiArrowCursor;
+extern void *(*uiConfigPF) (void *table, char *item);
+extern void *(*uiConfigSetPF) (void *table, char *item, void *value);
+
+
+/*
+ *  UiControlPanel.c
+ */
+
+
+/*
+ *  UiSelectionBox.c
+ */
+
+
+/*
+ *  UiPage.c
+ */
+
+extern void uiPageUpdateWindow(uiPage_t * page);
+extern void uiPageAttachCallbacks(void);
+extern void uiPageDefineKeys(void);
+
+extern uiPageInfo_t uiPageInfo;
+
+
+/*
+ *  UiSearch.c
+ */
+
+extern void uiSearchUpdateDialog(void);
+
+
+/*
+ *  UiPageSettings.c
+ */
+
+extern void uiPageSettingsUpdateDialog(void);
+
+
+/*
+ *  UiList.c
+ */
+
+extern void uiListUpdateDialog(uiPage_t * page);
+
+
+/*
+ *  UiRecall.c
+ */
+
+extern void uiRecallUpdateDialog(void);
+
+
+/*
+ *  UiMisc.c
+ */
+
+extern uiAction_t *uiFindAction(char *actionname);
+extern uiKey_t *uiFindKey(char *keyname, int modifier);
+extern uiVariable_t *uiFindVariable(char *varname);
+extern int uiAddWidgetInfo(char *varname, Widget wdg, uiWdgType_t wdgtype);
+extern void uiDialogActivateCB(Widget wdg, uiActionData_t * actiondata,
+                               XmAnyCallbackStruct * calldata);
+extern void uiDialogVariableCB(Widget wdg, caddr_t variablename,
+                               XmAnyCallbackStruct * calldata);
+extern void uiDefineCursor(Cursor cursor);
+extern void uiUndefineCursor(void);
+extern ArgList uiVaSetArgs( /*int *nargs, va_alist*/ );
+extern XtArgVal uiGetArg(Widget wdg, String resource);
+extern void *uiMalloc(int size);
+extern void *uiReAlloc(void *, int size);
+extern void uiFree(void *ptr);
+extern void uiDisplayWarning(char *text);
+extern void uiDisplayFatal(char *text);
+extern void uiWidgetPlacement(Widget wdg, int placement);
+extern void (*uiHelpOnActionCB) (char *actionstring);
diff --git a/Ui/UiRecall.c b/Ui/UiRecall.c
new file mode 100644 (file)
index 0000000..978ff8a
--- /dev/null
@@ -0,0 +1,305 @@
+static char *rcsid = "$Id$";
+
+
+#include "UiIncludes.h"
+
+
+static void uirecallfreeprevious(void);
+static void uirecallsetitems(char **listitems, int nitems);
+
+static Widget uicreaterecallform(void);
+static Widget uicreaterecalllabel(Widget parent);
+static Widget uicreaterecallopen(Widget parent);
+static Widget uicreaterecallclose(Widget parent);
+static Widget uicreaterecallseparator(Widget parent, Widget bottomwdg);
+static Widget
+ uicreaterecalllist(Widget parent, Widget topwdg,
+                    Widget bottomwdg);
+static void uirecallopencb(Widget wdg, caddr_t ignored,
+                           XmListCallbackStruct * calldata);
+static void uirecallclosecb(Widget wdg, caddr_t ignored,
+                            XmListCallbackStruct * calldata);
+
+
+static char *uitopaddress = (char *) NULL;
+static char **uilistitems;
+static int uinitems;
+static void (*uirecallcallback) (char *topaddress, char *address,
+                                 char *parentaddress);
+
+
+int UiDisplayRecallDialog(listitems, nitems, callback)
+char **listitems;
+int nitems;
+void (*callback) (char *topaddress, char *address, char *parentaddress);
+{
+    uiRecallGfx_t *recallgfx = &uiTopLevel.RecallGfx;
+
+    uirecallfreeprevious();
+
+    uitopaddress = uiPageInfo.CurrentPage->Hierarchy->Address;
+    uilistitems = listitems;
+    uinitems = nitems;
+    uirecallcallback = callback;
+
+    if (recallgfx->FormWdg) {
+       XtMapWidget(XtParent(recallgfx->FormWdg));
+
+       uiWidgetPlacement(XtParent(recallgfx->FormWdg),
+                         uiTopLevel.GlobalSettings.RecallPlacement);
+
+       uirecallsetitems(listitems, nitems);
+
+       return UI_OK;
+    }
+    recallgfx->FormWdg = uicreaterecallform();
+    recallgfx->LabelWdg = uicreaterecalllabel(recallgfx->FormWdg);
+    recallgfx->OpenWdg = uicreaterecallopen(recallgfx->FormWdg);
+    recallgfx->CloseWdg = uicreaterecallclose(recallgfx->FormWdg);
+    recallgfx->SeparatorWdg = uicreaterecallseparator(recallgfx->FormWdg,
+                                                     recallgfx->OpenWdg);
+    recallgfx->ListWdg = uicreaterecalllist(recallgfx->FormWdg,
+                                           recallgfx->LabelWdg,
+                                           recallgfx->SeparatorWdg);
+
+    uirecallsetitems(listitems, nitems);
+
+    XtManageChild(recallgfx->FormWdg);
+    XtRealizeWidget(XtParent(recallgfx->FormWdg));
+
+    uiWidgetPlacement(XtParent(recallgfx->FormWdg),
+                     uiTopLevel.GlobalSettings.RecallPlacement);
+
+    return UI_OK;
+}
+
+
+void uiRecallUpdateDialog()
+{
+    if (!uiPageInfo.CurrentPage && uiTopLevel.RecallGfx.FormWdg) {
+       uirecallfreeprevious();
+       uirecallsetitems((char **) NULL, 0);
+       uitopaddress = (char *) NULL;
+       XtUnmapWidget(XtParent(uiTopLevel.RecallGfx.FormWdg));
+    }
+}
+
+
+static Widget
+ uicreaterecallform()
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget formwdg;
+    Widget topwdg;
+
+    topwdg = XtCreateApplicationShell("Recall",
+                                     topLevelShellWidgetClass,
+                                     NULL, 0);
+    XtVaSetValues(topwdg,
+                 XmNtitle, UI_RECALL_TITLE, NULL);
+
+    args = uiVaSetArgs(&nargs,
+                      XmNresizePolicy, XmRESIZE_NONE,
+                      XmNautoUnmanage, FALSE, NULL);
+    formwdg = XmCreateForm(topwdg, "RecallDialog", args, nargs);
+
+    return formwdg;
+}
+
+
+static Widget
+ uicreaterecalllabel(formwdg)
+Widget formwdg;
+{
+    ArgList args;
+    Cardinal nargs;
+    XmString labelstr;
+    Widget labelwdg;
+
+    labelstr = XmStringCreateSimple("List of documents");
+    args = uiVaSetArgs(&nargs,
+                      XmNlabelString, labelstr,
+                      XmNtopAttachment, XmATTACH_FORM,
+                      XmNtopOffset, UI_LIST_WDG_OFFSET,
+                      XmNleftAttachment, XmATTACH_FORM,
+                      XmNrightAttachment, XmATTACH_FORM, NULL);
+    labelwdg = XmCreateLabelGadget(formwdg, "ListLabel", args, nargs);
+    XtManageChild(labelwdg);
+    XmStringFree(labelstr);
+
+    return labelwdg;
+}
+
+
+static Widget
+ uicreaterecallopen(formwdg)
+Widget formwdg;
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget openwdg;
+
+    args = uiVaSetArgs(&nargs,
+                      XmNleftAttachment, XmATTACH_POSITION,
+                      XmNleftPosition, 5,
+                      XmNrightAttachment, XmATTACH_POSITION,
+                      XmNrightPosition, 40,
+                      XmNbottomAttachment, XmATTACH_FORM,
+                      XmNbottomOffset, UI_LIST_WDG_OFFSET, NULL);
+    openwdg = XmCreatePushButtonGadget(formwdg, "Open", args, nargs);
+    XtAddCallback(openwdg, XmNactivateCallback,
+                 (XtCallbackProc) uirecallopencb, (caddr_t) NULL);
+    XtManageChild(openwdg);
+
+    return openwdg;
+}
+
+
+static Widget
+ uicreaterecallclose(formwdg)
+Widget formwdg;
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget closewdg;
+
+    args = uiVaSetArgs(&nargs,
+                      XmNleftAttachment, XmATTACH_POSITION,
+                      XmNleftPosition, 60,
+                      XmNrightAttachment, XmATTACH_POSITION,
+                      XmNrightPosition, 95,
+                      XmNbottomAttachment, XmATTACH_FORM,
+                      XmNbottomOffset, UI_LIST_WDG_OFFSET, NULL);
+    closewdg = XmCreatePushButtonGadget(formwdg, "Close", args, nargs);
+    XtAddCallback(closewdg, XmNactivateCallback,
+                 (XtCallbackProc) uirecallclosecb, (caddr_t) NULL);
+    XtManageChild(closewdg);
+
+    return closewdg;
+}
+
+
+static Widget
+ uicreaterecallseparator(formwdg, bottomwdg)
+Widget formwdg;
+Widget bottomwdg;
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget separatorwdg;
+
+    args = uiVaSetArgs(&nargs,
+                      XmNbottomAttachment, XmATTACH_WIDGET,
+                      XmNbottomWidget, bottomwdg,
+                      XmNbottomOffset, UI_LIST_WDG_OFFSET,
+                      XmNleftAttachment, XmATTACH_FORM,
+                      XmNrightAttachment, XmATTACH_FORM, NULL);
+    separatorwdg = XmCreateSeparatorGadget(formwdg, "ListSeparator",
+                                          args, nargs);
+    XtManageChild(separatorwdg);
+
+    return separatorwdg;
+}
+
+
+static Widget
+ uicreaterecalllist(formwdg, topwdg, bottomwdg)
+Widget formwdg;
+Widget topwdg;
+Widget bottomwdg;
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget listwdg;
+
+    args = uiVaSetArgs(&nargs,
+                      XmNvisibleItemCount, 15,
+                      XmNwidth, 300,
+                      XmNselectionPolicy, XmSINGLE_SELECT,
+                      XmNlistSizePolicy, XmCONSTANT,
+                      XmNscrollBarDisplayPolicy, XmSTATIC,
+                      XmNtopAttachment, XmATTACH_WIDGET,
+                      XmNtopWidget, topwdg,
+                      XmNtopOffset, UI_LIST_WDG_OFFSET,
+                      XmNbottomAttachment, XmATTACH_WIDGET,
+                      XmNbottomWidget, bottomwdg,
+                      XmNbottomOffset, UI_LIST_WDG_OFFSET,
+                      XmNrightAttachment, XmATTACH_FORM,
+                      XmNrightOffset, UI_LIST_WDG_OFFSET,
+                      XmNleftAttachment, XmATTACH_FORM,
+                      XmNleftOffset, UI_LIST_WDG_OFFSET, NULL);
+    listwdg = XmCreateScrolledList(formwdg, "ListList", args, nargs);
+    XtManageChild(listwdg);
+    XtAddCallback(listwdg, XmNdefaultActionCallback,
+                 (XtCallbackProc) uirecallopencb, (caddr_t) NULL);
+
+    return listwdg;
+}
+
+
+void uirecallfreeprevious()
+{
+    if (uitopaddress && uinitems) {
+       while (uinitems--)
+           uiFree(uilistitems[uinitems]);
+
+       uiFree(uilistitems);
+    }
+}
+
+
+static void uirecallsetitems(listitems, nitems)
+char **listitems;
+int nitems;
+{
+    Widget listwdg = uiTopLevel.RecallGfx.ListWdg;
+    int i;
+    XmString *tmpstr = uiMalloc(nitems * sizeof(XmString));
+
+    XmListDeleteAllItems(listwdg);
+    if (nitems) {
+       for (i = 0; i < nitems; i++)
+           tmpstr[i] = XmStringCreateSimple(listitems[i]);
+
+       XmListAddItems(listwdg, tmpstr, nitems, 0);
+       for (i = 0; i < nitems; i++)
+           XmStringFree(tmpstr[i]);
+       uiFree((void *) tmpstr);
+    }
+}
+
+
+static void uirecallopencb(wdg, ignored, calldata)
+Widget wdg;
+caddr_t ignored;
+XmListCallbackStruct *calldata;
+{
+    Widget listwdg = uiTopLevel.RecallGfx.ListWdg;
+    int *poslist;
+    int poscount;
+
+    if (uinitems)
+       if (XmListGetSelectedPos(listwdg, &poslist, &poscount)) {
+           uiDefineCursor(uiBusyCursor);
+           if (uiHelpOnActionCB) {
+               (*uiHelpOnActionCB) ("Get page");
+               uiHelpOnActionCB = (void (*) (char *actionstring)) NULL;
+           } else
+               (*uirecallcallback) (uilistitems[poslist[0] - 1],
+                                    uitopaddress, (char *) NULL);
+
+           uiUndefineCursor();
+
+           XtFree(poslist);
+       }
+}
+
+
+static void uirecallclosecb(wdg, ignored, calldata)
+Widget wdg;
+caddr_t ignored;
+XmListCallbackStruct *calldata;
+{
+    XtUnmapWidget(XtParent(uiTopLevel.RecallGfx.FormWdg));
+}
diff --git a/Ui/UiSearch.c b/Ui/UiSearch.c
new file mode 100644 (file)
index 0000000..e3c8648
--- /dev/null
@@ -0,0 +1,488 @@
+static char *rcsid = "$Id: UiSearch.c,v 1.1 1992/03/26 18:13:50 kny Exp kss $";
+
+#include "UiIncludes.h"
+
+
+static Widget uicreatesearchformdialog();
+static Widget uicreatesearchtext(Widget formwdg);
+static Widget uicreatesearchlevel(Widget formwdg, Widget textwdg);
+static Widget uicreatesearchlevelform(Widget formwdg, Widget levelwdg);
+static Widget uicreatesearchleveldown(Widget formwdg);
+static Widget uicreatesearchlevelup(Widget formwdg);
+static Widget uicreatesearchcase(Widget formwdg, Widget levelwdg);
+static Widget uicreatesearchbackward(Widget formwdg, Widget levelwdg);
+static Widget uicreatesearchforward(Widget formwdg, Widget textwdg);
+static Widget uicreatesearchlabel(Widget formwdg, Widget closewdg);
+static Widget uicreatesearchclose(Widget formwdg, Widget forwardwdg);
+
+static void uisearchlevelcb(char *address, HText_t * htex,
+                          HTextObject_t * htextobject, void *parameter);
+static void uisearchclosecb(char *address, HText_t * htext,
+                          HTextObject_t * htextobject, void *parameter);
+
+
+int UiDisplaySearchDialog(type)
+int type;
+{
+    uiSearchGfx_t *searchgfx = &uiTopLevel.SearchGfx;
+
+    if (searchgfx->FormWdg) {
+       XtMapWidget(XtParent(searchgfx->FormWdg));
+       uiWidgetPlacement(XtParent(searchgfx->FormWdg),
+                         uiTopLevel.GlobalSettings.SearchPlacement);
+       uiSearchUpdateDialog();
+       return UI_OK;
+    }
+    searchgfx->FormWdg = uicreatesearchformdialog();
+    searchgfx->TextWdg = uicreatesearchtext(searchgfx->FormWdg);
+    searchgfx->LevelWdg = uicreatesearchlevel(searchgfx->FormWdg,
+                                             searchgfx->TextWdg);
+    searchgfx->LevelFormWdg = uicreatesearchlevelform(searchgfx->FormWdg,
+                                                   searchgfx->LevelWdg);
+    searchgfx->CaseWdg = uicreatesearchcase(searchgfx->FormWdg,
+                                           searchgfx->LevelWdg);
+    searchgfx->BackwardWdg = uicreatesearchbackward(searchgfx->FormWdg,
+                                                   searchgfx->TextWdg);
+    searchgfx->ForwardWdg = uicreatesearchforward(searchgfx->FormWdg,
+                                                 searchgfx->BackwardWdg);
+    searchgfx->CloseWdg = uicreatesearchclose(searchgfx->FormWdg,
+                                             searchgfx->ForwardWdg);
+    searchgfx->LabelWdg = uicreatesearchlabel(searchgfx->FormWdg,
+                                             searchgfx->CloseWdg);
+
+    XtManageChild(searchgfx->FormWdg);
+    XtRealizeWidget(XtParent(searchgfx->FormWdg));
+
+    uiWidgetPlacement(XtParent(searchgfx->FormWdg),
+                     uiTopLevel.GlobalSettings.SearchPlacement);
+
+    return UI_OK;
+}
+
+
+void uiSearchUpdateDialog()
+{
+    XmString labelstr;
+
+    if (uiTopLevel.SearchGfx.FormWdg) {
+       if (uiPageInfo.CurrentPage) {
+           labelstr =
+               XmStringCreateSimple(HTAnchor_address((HTAnchor *)
+                                                uiPageInfo.CurrentPage->
+                                                   HText->node_anchor));
+           XtVaSetValues(uiTopLevel.SearchGfx.LabelWdg,
+                         XmNlabelString, labelstr, NULL);
+           XmStringFree(labelstr);
+       } else
+           XtUnmapWidget(XtParent(uiTopLevel.SearchGfx.FormWdg));
+    }
+}
+
+
+static Widget
+ uicreatesearchformdialog()
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget formwdg;
+    Widget topwdg;
+
+    topwdg = XtCreateApplicationShell("Search",
+                                     topLevelShellWidgetClass,
+                                     NULL, 0);
+    XtVaSetValues(topwdg,
+                 XmNtitle, UI_SEARCH_TITLE, NULL);
+
+    args = uiVaSetArgs(&nargs,
+                      XmNresizePolicy, XmRESIZE_NONE,
+                      XmNautoUnmanage, FALSE, NULL);
+    formwdg = XmCreateForm(topwdg, "Search", args, nargs);
+
+    return formwdg;
+}
+
+
+static Widget
+ uicreatesearchtext(formwdg)
+Widget formwdg;
+{
+    ArgList args;
+    Cardinal nargs;
+    XmString labelstr;
+    Widget labelwdg, textwdg;
+
+    labelstr = XmStringCreateSimple("Search for:");
+    args = uiVaSetArgs(&nargs,
+                      XmNlabelString, labelstr,
+                      XmNtopAttachment, XmATTACH_FORM,
+                      XmNtopOffset, UI_SEARCH_WDG_OFFSET,
+                      XmNleftAttachment, XmATTACH_FORM,
+                      XmNleftOffset, UI_SEARCH_WDG_OFFSET, NULL);
+    labelwdg = XmCreateLabelGadget(formwdg, "TextLabel", args, nargs);
+    XtManageChild(labelwdg);
+    XmStringFree(labelstr);
+
+    args = uiVaSetArgs(&nargs,
+                      XmNcolumns, 40,
+                      XmNtopAttachment, XmATTACH_WIDGET,
+                      XmNtopWidget, labelwdg,
+                      XmNtopOffset, UI_SEARCH_WDG_OFFSET / 2,
+                      XmNleftAttachment, XmATTACH_FORM,
+                      XmNleftOffset, UI_SEARCH_WDG_OFFSET,
+                      XmNrightAttachment, XmATTACH_FORM,
+                      XmNrightOffset, UI_SEARCH_WDG_OFFSET, NULL);
+    textwdg = XmCreateText(formwdg, "Text", args, nargs);
+    XtAddCallback(textwdg, XmNactivateCallback,
+           (XtCallbackProc) uiDialogVariableCB, (caddr_t) "SearchText");
+    XtAddCallback(textwdg, XmNlosingFocusCallback,
+           (XtCallbackProc) uiDialogVariableCB, (caddr_t) "SearchText");
+    XtAddCallback(textwdg, XmNvalueChangedCallback,
+           (XtCallbackProc) uiDialogVariableCB, (caddr_t) "SearchText");
+    (void) uiAddWidgetInfo("SearchText", textwdg, uiWTtext);   /* Ignore */
+    XtManageChild(textwdg);
+
+    return textwdg;
+}
+
+
+static Widget
+ uicreatesearchlevel(formwdg, textwdg)
+Widget formwdg;
+Widget textwdg;
+{
+    ArgList args;
+    Cardinal nargs;
+    XmString labelstr;
+    Widget labelwdg, levelwdg;
+
+    labelstr = XmStringCreateSimple("Depth of search:");
+    args = uiVaSetArgs(&nargs,
+                      XmNlabelString, labelstr,
+                      XmNtopAttachment, XmATTACH_WIDGET,
+                      XmNtopWidget, textwdg,
+                      XmNtopOffset, UI_SEARCH_WDG_OFFSET,
+                      XmNleftAttachment, XmATTACH_FORM,
+                      XmNleftOffset, UI_SEARCH_WDG_OFFSET, NULL);
+    labelwdg = XmCreateLabelGadget(formwdg, "LevelLabel", args, nargs);
+    XtManageChild(labelwdg);
+    XmStringFree(labelstr);
+
+    args = uiVaSetArgs(&nargs,
+                      XmNtopAttachment, XmATTACH_WIDGET,
+                      XmNtopWidget, labelwdg,
+                      XmNtopOffset, UI_SEARCH_WDG_OFFSET / 2,
+                      XmNleftAttachment, XmATTACH_FORM,
+                      XmNleftOffset, UI_SEARCH_WDG_OFFSET,
+                      XmNcolumns, 3,
+                      XmNmaxLength, 3,
+                      XmNvalue, "1", NULL);
+    levelwdg = XmCreateText(formwdg, "Level", args, nargs);
+    XtAddCallback(levelwdg, XmNactivateCallback,
+                 (XtCallbackProc) uiDialogVariableCB,
+                 (caddr_t) "SearchLevel");
+    XtAddCallback(levelwdg, XmNlosingFocusCallback,
+                 (XtCallbackProc) uiDialogVariableCB,
+                 (caddr_t) "SearchLevel");
+    XtAddCallback(levelwdg, XmNvalueChangedCallback,
+                 (XtCallbackProc) uiDialogVariableCB,
+                 (caddr_t) "SearchLevel");
+    (void) uiAddWidgetInfo("SearchLevel", levelwdg, uiWTtext); /* Ignore */
+    XtManageChild(levelwdg);
+
+    return levelwdg;
+}
+
+
+static Widget
+ uicreatesearchlevelform(formwdg, levelwdg)
+Widget formwdg;
+Widget levelwdg;
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget levelformwdg;
+    uiSearchGfx_t *searchgfx = &uiTopLevel.SearchGfx;
+
+    args = uiVaSetArgs(&nargs,
+                      XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
+                      XmNtopWidget, levelwdg,
+                      XmNleftAttachment, XmATTACH_WIDGET,
+                      XmNleftWidget, levelwdg,
+                      XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
+                      XmNbottomWidget, levelwdg, NULL);
+    levelformwdg = XmCreateForm(formwdg, "LevelForm", args, nargs);
+    XtManageChild(levelformwdg);
+
+    searchgfx->LevelDownWdg = uicreatesearchleveldown(levelformwdg);
+    searchgfx->LevelUpWdg = uicreatesearchlevelup(levelformwdg);
+
+    return levelformwdg;
+}
+
+
+static Widget
+ uicreatesearchleveldown(formwdg)
+Widget formwdg;
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget leveldownwdg;
+    char *actionname = "LevelDown";
+    static uiActionData_t actiondata;
+
+    args = uiVaSetArgs(&nargs,
+                      XmNarrowDirection, XmARROW_DOWN,
+                      XmNwidth, 15,
+                      XmNtopAttachment, XmATTACH_POSITION,
+                      XmNtopPosition, 50,
+                      XmNleftAttachment, XmATTACH_FORM,
+                      XmNrightAttachment, XmATTACH_FORM,
+                      XmNbottomAttachment, XmATTACH_FORM, NULL);
+    leveldownwdg = XmCreateArrowButtonGadget(formwdg, actionname,
+                                            args, nargs);
+    actiondata.ActionName = actionname;
+    actiondata.Page = uiPageInfo.CurrentPage;
+    XtAddCallback(leveldownwdg, XmNactivateCallback,
+           (XtCallbackProc) uiDialogActivateCB, (caddr_t) & actiondata);
+    UiAttachCallback(actionname, uisearchlevelcb, (void *) actionname);
+    XtManageChild(leveldownwdg);
+
+    return leveldownwdg;
+}
+
+
+static Widget
+ uicreatesearchlevelup(formwdg)
+Widget formwdg;
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget levelupwdg;
+    char *actionname = "LevelUp";
+    static uiActionData_t actiondata;
+
+    args = uiVaSetArgs(&nargs,
+                      XmNarrowDirection, XmARROW_UP,
+                      XmNwidth, 15,
+                      XmNtopAttachment, XmATTACH_FORM,
+                      XmNleftAttachment, XmATTACH_FORM,
+                      XmNrightAttachment, XmATTACH_FORM,
+                      XmNbottomAttachment, XmATTACH_POSITION,
+                      XmNbottomPosition, 50, NULL);
+    levelupwdg = XmCreateArrowButtonGadget(formwdg, "LevelUp",
+                                          args, nargs);
+    actiondata.ActionName = actionname;
+    actiondata.Page = uiPageInfo.CurrentPage;
+    XtAddCallback(levelupwdg, XmNactivateCallback,
+           (XtCallbackProc) uiDialogActivateCB, (caddr_t) & actiondata);
+    UiAttachCallback(actionname, uisearchlevelcb, (void *) actionname);
+    XtManageChild(levelupwdg);
+
+    return levelupwdg;
+}
+
+
+static Widget
+ uicreatesearchcase(formwdg, levelwdg)
+Widget formwdg;
+Widget levelwdg;
+{
+    XmString labelstr;
+    ArgList args;
+    Cardinal nargs;
+    Widget casewdg;
+
+    labelstr = XmStringCreateSimple("Case sensitive");
+    args = uiVaSetArgs(&nargs,
+                      XmNlabelString, labelstr,
+                      XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
+                      XmNtopWidget, levelwdg,
+                      XmNleftAttachment, XmATTACH_POSITION,
+                      XmNleftPosition, 30,
+                      XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
+                      XmNbottomWidget, levelwdg, NULL);
+    casewdg = XmCreateToggleButtonGadget(formwdg, "Case", args, nargs);
+    XtAddCallback(casewdg, XmNvalueChangedCallback,
+           (XtCallbackProc) uiDialogVariableCB, (caddr_t) "SearchCase");
+    /* Ignore */
+    (void) uiAddWidgetInfo("SearchCase", casewdg, uiWTcheckbutton);
+    XtManageChild(casewdg);
+
+    return casewdg;
+}
+
+
+static Widget
+ uicreatesearchbackward(formwdg, textwdg)
+Widget formwdg;
+Widget textwdg;
+{
+    XmString labelstr;
+    ArgList args;
+    Cardinal nargs;
+    Widget backwardwdg;
+    char *actionname = "SearchBackward";
+    static uiActionData_t actiondata;
+
+    labelstr = XmStringCreateSimple("Search backward");
+    args = uiVaSetArgs(&nargs,
+                      XmNlabelString, labelstr,
+                      XmNtopAttachment, XmATTACH_WIDGET,
+                      XmNtopWidget, textwdg,
+                      XmNtopOffset, UI_SEARCH_WDG_OFFSET,
+                      XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET,
+                      XmNrightWidget, textwdg, NULL);
+    backwardwdg = XmCreatePushButtonGadget(formwdg, "SearchBackward",
+                                          args, nargs);
+    actiondata.ActionName = actionname;
+    actiondata.Page = uiPageInfo.CurrentPage;
+    XtAddCallback(backwardwdg, XmNactivateCallback,
+           (XtCallbackProc) uiDialogActivateCB, (caddr_t) & actiondata);
+    XtManageChild(backwardwdg);
+    XmStringFree(labelstr);
+
+    return backwardwdg;
+}
+
+
+static Widget
+ uicreatesearchforward(formwdg, backwardwdg)
+Widget formwdg;
+Widget backwardwdg;
+{
+    XmString labelstr;
+    ArgList args;
+    Cardinal nargs;
+    Widget forwardwdg;
+    char *actionname = "SearchForward";
+    static uiActionData_t actiondata;
+
+    labelstr = XmStringCreateSimple("Search forward");
+    args = uiVaSetArgs(&nargs,
+                      XmNlabelString, labelstr,
+                      XmNtopAttachment, XmATTACH_WIDGET,
+                      XmNtopWidget, backwardwdg,
+                      XmNtopOffset, UI_SEARCH_WDG_OFFSET / 2,
+                      XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET,
+                      XmNleftWidget, backwardwdg,
+                      XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET,
+                      XmNrightWidget, backwardwdg, NULL);
+    forwardwdg = XmCreatePushButtonGadget(formwdg, "SearchForward",
+                                         args, nargs);
+    actiondata.ActionName = actionname;
+    actiondata.Page = uiPageInfo.CurrentPage;
+    XtAddCallback(forwardwdg, XmNactivateCallback,
+           (XtCallbackProc) uiDialogActivateCB, (caddr_t) & actiondata);
+    XtManageChild(forwardwdg);
+    XmStringFree(labelstr);
+
+    return forwardwdg;
+}
+
+
+static Widget
+ uicreatesearchclose(parentwdg, topwdg)
+Widget parentwdg;
+Widget topwdg;
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget separatorwdg;
+    Widget tmpwdg;
+    static uiActionData_t actiondata;
+
+    args = uiVaSetArgs(&nargs,
+                      XmNtopAttachment, XmATTACH_WIDGET,
+                      XmNtopWidget, topwdg,
+                      XmNtopOffset, UI_SEARCH_WDG_OFFSET,
+                      XmNleftAttachment, XmATTACH_FORM,
+                      XmNrightAttachment, XmATTACH_FORM, NULL);
+    separatorwdg = XmCreateSeparatorGadget(parentwdg, "SearchSeparator",
+                                          args, nargs);
+    XtManageChild(separatorwdg);
+
+    tmpwdg = XmCreatePushButtonGadget(parentwdg, "Close", (ArgList) NULL, 0);
+    XtVaSetValues(tmpwdg,
+                 XmNwidth, 70,
+                 XmNbottomAttachment, XmATTACH_FORM,
+                 XmNbottomOffset, UI_SEARCH_WDG_OFFSET,
+                 XmNtopAttachment, XmATTACH_WIDGET,
+                 XmNtopWidget, separatorwdg,
+                 XmNtopOffset, UI_SEARCH_WDG_OFFSET,
+                 XmNrightAttachment, XmATTACH_FORM,
+                 XmNrightOffset, UI_SEARCH_WDG_OFFSET, NULL);
+    actiondata.ActionName = "SearchClose";
+    actiondata.Page = uiPageInfo.CurrentPage;
+    XtAddCallback(tmpwdg, XmNactivateCallback,
+           (XtCallbackProc) uiDialogActivateCB, (caddr_t) & actiondata);
+    UiAttachCallback("SearchClose", uisearchclosecb, "SearchClose");
+
+    XtManageChild(tmpwdg);
+
+    return tmpwdg;
+}
+
+
+static Widget
+ uicreatesearchlabel(formwdg, rightwdg)
+Widget formwdg;
+Widget rightwdg;
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget labelwdg;
+
+    args = uiVaSetArgs(&nargs,
+                      XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
+                      XmNtopWidget, rightwdg,
+                      XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
+                      XmNbottomWidget, rightwdg,
+                      XmNleftAttachment, XmATTACH_FORM,
+                      XmNleftOffset, UI_SEARCH_WDG_OFFSET,
+                      XmNrightAttachment, XmATTACH_WIDGET,
+                      XmNrightWidget, rightwdg,
+                      XmNrightOffset, UI_SEARCH_WDG_OFFSET, NULL);
+    labelwdg = XmCreateLabelGadget(formwdg, "Label", args, nargs);
+    XtManageChild(labelwdg);
+
+    return labelwdg;
+}
+
+
+static void uisearchlevelcb(address, htext, htextobject, parameter)
+char *address;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    Widget levelwdg = uiTopLevel.SearchGfx.LevelWdg;
+    char *leveltext;
+    int level;
+    char tmpbuffer[4];
+
+    leveltext = XmTextGetString(levelwdg);
+    level = atoi(leveltext);
+
+    if (!strcmp("LevelDown", (char *) parameter)) {
+       if (level > 1) {
+           level--;
+           sprintf(tmpbuffer, "%d", level);
+           XmTextSetString(levelwdg, tmpbuffer);
+       }
+    } else if (level < 1) {
+       level++;
+       sprintf(tmpbuffer, "%d", level);
+       XmTextSetString(levelwdg, tmpbuffer);
+    }
+    XtFree(leveltext);
+}
+
+
+static void uisearchclosecb(address, htext, htextobject, parameter)
+char *address;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    XtUnmapWidget(XtParent(uiTopLevel.SearchGfx.FormWdg));
+}
diff --git a/Ui/UiSelectionBox.c b/Ui/UiSelectionBox.c
new file mode 100644 (file)
index 0000000..52a644a
--- /dev/null
@@ -0,0 +1,403 @@
+static char *rcsid = "$Id: UiSelectionBox.c,v 1.3 1992/03/26 18:13:50 kny Exp $";
+
+#include "UiIncludes.h"
+
+
+static Widget uicreatesbformdialog();
+static Widget
+ uicreatesbfsbox(Widget formwdg,
+                 void (*callback) (char *nodename));
+static Widget uicreatesbseparator(Widget formwdg, Widget fsboxwdg);
+static Widget uicreatesbadd(Widget formwdg, Widget fsboxwdg,
+                            Widget separatorwdg);
+static Widget uicreatesbdelete(Widget formwdg, Widget fsboxwdg);
+static Widget uicreatesblist(Widget formwdg, Widget deletewdg,
+                             Widget separatorwdg);
+static char *uifixselection(char *selection);
+
+static void uiselectionboxokcb(Widget wdg, caddr_t callback,
+                               XmPushButtonCallbackStruct * calldata);
+static void uiselectionboxcancelcb(Widget wdg, caddr_t ignored,
+                                 XmPushButtonCallbackStruct * calldata);
+static void uiselectionboxaddcb(Widget wdg, caddr_t ignored,
+                                XmPushButtonCallbackStruct * calldata);
+static void uiselectionboxdeletecb(Widget wdg, caddr_t ignored,
+                                 XmPushButtonCallbackStruct * calldata);
+static void uiselectionboxclickcb(Widget wdg, caddr_t ignored,
+                                  XmListCallbackStruct * calldata);
+static void uiselectionboxupdateconfig(void);
+
+
+uiTopLevel_t uiTopLevel;
+char **uiSelectionArray;
+
+
+static int uidummy;
+
+
+int UiDisplaySelectionBox(callback)
+void (*callback) (char *nodename);
+{
+    uiSelectionBoxGfx_t *sbgfx = &uiTopLevel.SBGfx;
+    XmString dummystr;
+    int i = 0;
+
+    if (sbgfx->FormWdg) {
+       XtMapWidget(XtParent(sbgfx->FormWdg));
+
+       return UI_OK;
+    }
+    sbgfx->FormWdg = uicreatesbformdialog();
+    sbgfx->FSBoxWdg = uicreatesbfsbox(sbgfx->FormWdg, callback);
+    sbgfx->SeparatorWdg = uicreatesbseparator(sbgfx->FormWdg, sbgfx->FSBoxWdg);
+    sbgfx->AddWdg = uicreatesbadd(sbgfx->FormWdg, sbgfx->FSBoxWdg,
+                                 sbgfx->SeparatorWdg);
+    sbgfx->DeleteWdg = uicreatesbdelete(sbgfx->FormWdg, sbgfx->FSBoxWdg);
+    sbgfx->ListWdg = uicreatesblist(sbgfx->FormWdg, sbgfx->DeleteWdg,
+                                   sbgfx->SeparatorWdg);
+
+    XtManageChild(sbgfx->FormWdg);
+    XtRealizeWidget(XtParent(sbgfx->FormWdg));
+
+    if (!uiSelectionArray) {
+       dummystr = XmStringCreateSimple(" ");
+       XmListAddItem(uiTopLevel.SBGfx.ListWdg, dummystr, 0);
+       XtSetSensitive(uiTopLevel.SBGfx.ListWdg, FALSE);
+       XmStringFree(dummystr);
+       uidummy = TRUE;
+    } else {
+       while (uiSelectionArray[i]) {
+           dummystr = XmStringCreateSimple(uiSelectionArray[i++]);
+           XmListAddItem(uiTopLevel.SBGfx.ListWdg, dummystr, 0);
+           XmStringFree(dummystr);
+       }
+       uidummy = FALSE;
+    }
+
+    return UI_OK;
+}
+
+
+static Widget
+ uicreatesbformdialog()
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget formwdg;
+    Widget topwdg;
+
+    topwdg = XtCreateApplicationShell("SelectionBox",
+                                     topLevelShellWidgetClass,
+                                     NULL, 0);
+
+    args = uiVaSetArgs(&nargs,
+                      XmNresizePolicy, XmRESIZE_NONE,
+                      XmNautoUnmanage, FALSE, NULL);
+    formwdg = XmCreateForm(topwdg, "SelectionBox",
+                          args, nargs);
+
+    return formwdg;
+}
+
+
+static Widget
+ uicreatesbfsbox(formwdg, callback)
+Widget formwdg;
+void (*callback) (char *nodename);
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget fsboxwdg, textwdg, okwdg, cancelwdg;
+
+    args = uiVaSetArgs(&nargs,
+                      XmNtopAttachment, XmATTACH_FORM,
+                      XmNtopOffset, 1,
+                      XmNleftAttachment, XmATTACH_FORM,
+                      XmNleftOffset, 1,
+                      XmNbottomOffset, 1,
+                      XmNbottomAttachment, XmATTACH_FORM, NULL);
+    fsboxwdg = XmCreateFileSelectionBox(formwdg, "FSBox",
+                                       args, nargs);
+    XtUnmanageChild(XmFileSelectionBoxGetChild(fsboxwdg,
+                                              XmDIALOG_HELP_BUTTON));
+
+    textwdg = XmFileSelectionBoxGetChild(fsboxwdg, XmDIALOG_TEXT);
+    XmTextSetString(textwdg, "");
+
+    okwdg = XmFileSelectionBoxGetChild(fsboxwdg, XmDIALOG_OK_BUTTON);
+    XtAddCallback(okwdg, XmNactivateCallback, uiselectionboxokcb,
+                 (caddr_t) callback);
+
+    cancelwdg = XmFileSelectionBoxGetChild(fsboxwdg, XmDIALOG_CANCEL_BUTTON);
+    XtAddCallback(cancelwdg, XmNactivateCallback, uiselectionboxcancelcb,
+                 (caddr_t) NULL);
+    XtManageChild(fsboxwdg);
+
+    return fsboxwdg;
+}
+
+
+static Widget
+ uicreatesbseparator(formwdg, fsboxwdg)
+Widget formwdg;
+Widget fsboxwdg;
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget separatorwdg;
+
+    args = uiVaSetArgs(&nargs,
+                      XmNorientation, XmVERTICAL,
+                      XmNleftAttachment, XmATTACH_WIDGET,
+                      XmNleftWidget, fsboxwdg,
+                      XmNleftOffset, 10,
+                      XmNtopAttachment, XmATTACH_FORM,
+                      XmNbottomAttachment, XmATTACH_FORM, NULL);
+    separatorwdg = XmCreateSeparatorGadget(formwdg, "Separator",
+                                          args, nargs);
+    XtManageChild(separatorwdg);
+
+    return separatorwdg;
+}
+
+
+static Widget
+ uicreatesbadd(formwdg, fsboxwdg, separatorwdg)
+Widget formwdg;
+Widget fsboxwdg;
+Widget separatorwdg;
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget addwdg;
+
+    args = uiVaSetArgs(&nargs,
+                      XmNwidth, 70,
+                      XmNleftOffset, 20,
+                      XmNleftAttachment, XmATTACH_WIDGET,
+                      XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
+                      XmNbottomWidget, fsboxwdg,
+                      XmNbottomOffset, 20,
+                      XmNleftWidget, separatorwdg, NULL);
+    addwdg = XmCreatePushButtonGadget(formwdg, "Add",
+                                     args, nargs);
+    XtManageChild(addwdg);
+    XtAddCallback(addwdg, XmNactivateCallback, uiselectionboxaddcb,
+                 (caddr_t) NULL);
+
+    return addwdg;
+}
+
+
+static Widget
+ uicreatesbdelete(formwdg, fsboxwdg)
+Widget formwdg;
+Widget fsboxwdg;
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget deletewdg;
+
+    args = uiVaSetArgs(&nargs,
+                      XmNwidth, 70,
+                      XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
+                      XmNbottomWidget, fsboxwdg,
+                      XmNbottomOffset, 20,
+                      XmNrightOffset, 10,
+                      XmNrightAttachment, XmATTACH_FORM, NULL);
+    deletewdg = XmCreatePushButtonGadget(formwdg, "Delete",
+                                        args, nargs);
+    XtManageChild(deletewdg);
+    XtAddCallback(deletewdg, XmNactivateCallback, uiselectionboxdeletecb,
+                 (caddr_t) NULL);
+
+    return deletewdg;
+}
+
+
+static Widget
+ uicreatesblist(formwdg, deletewdg, separatorwdg)
+Widget formwdg;
+Widget deletewdg;
+Widget separatorwdg;
+{
+    ArgList args;
+    Cardinal nargs;
+    Widget listwdg;
+
+    args = uiVaSetArgs(&nargs,
+                      XmNvisibleItemCount, 15,
+                      XmNwidth, 200,
+                      XmNselectionPolicy, XmSINGLE_SELECT,
+                      XmNlistSizePolicy, XmCONSTANT,
+                      XmNscrollBarDisplayPolicy, XmSTATIC,
+                      XmNtopAttachment, XmATTACH_FORM,
+                      XmNtopOffset, 11,
+                      XmNbottomAttachment, XmATTACH_WIDGET,
+                      XmNbottomWidget, deletewdg,
+                      XmNbottomOffset, 20,
+                      XmNrightAttachment, XmATTACH_FORM,
+                      XmNrightOffset, 11,
+                      XmNleftOffset, 20,
+                      XmNleftAttachment, XmATTACH_WIDGET,
+                      XmNleftWidget, separatorwdg, NULL);
+    listwdg = XmCreateScrolledList(formwdg, "List",
+                                  args, nargs);
+    XtManageChild(listwdg);
+    XtAddCallback(listwdg, XmNdefaultActionCallback, uiselectionboxclickcb,
+                 (caddr_t) NULL);
+
+    return listwdg;
+}
+
+
+static char *
+ uifixselection(selection)
+char *selection;
+{
+    char *newselection;
+
+    if (!selection)
+       return selection;
+
+    if (index(selection, ':'))
+       return strdup(selection);
+
+    newselection = uiMalloc(strlen(selection) + strlen("file:") + 1);
+    strcpy(newselection, "file:");
+    strcat(newselection, selection);
+
+    return newselection;
+}
+
+
+static void uiselectionboxokcb(wdg, callback, calldata)
+Widget wdg;
+caddr_t callback;
+XmPushButtonCallbackStruct *calldata;
+{
+    Widget textwdg;
+    char *selection, *fixedselection;
+
+    textwdg = XmFileSelectionBoxGetChild(uiTopLevel.SBGfx.FSBoxWdg,
+                                        XmDIALOG_TEXT);
+    selection = XmTextGetString(textwdg);
+    fixedselection = uifixselection(selection);
+    XtUnmapWidget(XtParent(uiTopLevel.SBGfx.FormWdg));
+    (*(void (*) (char *nodename)) callback) (fixedselection);
+
+    XtFree(selection);
+    XtFree(fixedselection);
+}
+
+
+static void uiselectionboxcancelcb(wdg, ignored, calldata)
+Widget wdg;
+caddr_t ignored;
+XmPushButtonCallbackStruct *calldata;
+{
+    XtUnmapWidget(XtParent(uiTopLevel.SBGfx.FormWdg));
+}
+
+
+static void uiselectionboxaddcb(wdg, ignored, calldata)
+Widget wdg;
+caddr_t ignored;
+XmPushButtonCallbackStruct *calldata;
+{
+    Widget textwdg;
+    char *selection, *fixedselection;
+    XmString selectionstr;
+    int *poslist;
+    int poscount;
+
+    textwdg = XmFileSelectionBoxGetChild(uiTopLevel.SBGfx.FSBoxWdg,
+                                        XmDIALOG_TEXT);
+    selection = XmTextGetString(textwdg);
+    fixedselection = uifixselection(selection);
+
+    if (fixedselection && fixedselection[0]) {
+       selectionstr = XmStringCreateSimple(fixedselection);
+       if (uidummy) {
+           XmListDeletePos(uiTopLevel.SBGfx.ListWdg, 1);
+           XtSetSensitive(uiTopLevel.SBGfx.ListWdg, TRUE);
+           uidummy = FALSE;
+       }
+       if (XmListGetSelectedPos(uiTopLevel.SBGfx.ListWdg, &poslist,
+                                &poscount)) {
+           XmListDeselectPos(uiTopLevel.SBGfx.ListWdg, poslist[0]);
+           XmListAddItem(uiTopLevel.SBGfx.ListWdg, selectionstr, poslist[0]);
+           XmListSelectPos(uiTopLevel.SBGfx.ListWdg, poslist[0] + 1, FALSE);
+           XtFree(poslist);
+       } else
+           XmListAddItem(uiTopLevel.SBGfx.ListWdg, selectionstr, 0);
+       XmStringFree(selectionstr);
+    }
+    XtFree(selection);
+    XtFree(fixedselection);
+
+    uiselectionboxupdateconfig();
+}
+
+
+static void uiselectionboxdeletecb(wdg, ignored, calldata)
+Widget wdg;
+caddr_t ignored;
+XmPushButtonCallbackStruct *calldata;
+{
+    int *poslist;
+    int poscount;
+    XmString dummystr;
+
+    /* We should have only one selected item */
+    if (XmListGetSelectedPos(uiTopLevel.SBGfx.ListWdg, &poslist, &poscount)) {
+       XmListDeletePos(uiTopLevel.SBGfx.ListWdg, poslist[0]);
+       XmListSelectPos(uiTopLevel.SBGfx.ListWdg, poslist[0], FALSE);
+       XtFree(poslist);
+    }
+    if (!uiGetArg(uiTopLevel.SBGfx.ListWdg, XmNitemCount)) {
+       dummystr = XmStringCreateSimple(" ");
+       XmListAddItem(uiTopLevel.SBGfx.ListWdg, dummystr, 0);
+       XmStringFree(dummystr);
+       XtSetSensitive(uiTopLevel.SBGfx.ListWdg, FALSE);
+       uidummy = TRUE;
+    }
+    uiselectionboxupdateconfig();
+}
+
+
+static void uiselectionboxclickcb(wdg, ignored, calldata)
+Widget wdg;
+caddr_t ignored;
+XmListCallbackStruct *calldata;
+{
+    Widget textwdg;
+    char *selection;
+
+    XmStringGetLtoR(calldata->item, XmSTRING_DEFAULT_CHARSET, &selection);
+    textwdg = XmFileSelectionBoxGetChild(uiTopLevel.SBGfx.FSBoxWdg,
+                                        XmDIALOG_TEXT);
+    XmTextSetString(textwdg, selection);
+    XtFree(selection);
+}
+
+
+static void uiselectionboxupdateconfig()
+{
+    Widget listwdg = uiTopLevel.SBGfx.ListWdg;
+    int nitems, i;
+    char **items;
+    XmStringTable stringtable;
+    void *table;
+
+    nitems = uiGetArg(listwdg, XmNitemCount);
+    items = (char **) uiMalloc((nitems + 1) * sizeof(*items));
+
+    stringtable = (XmStringTable) uiGetArg(listwdg, XmNitems);
+    for (i = 0; i < nitems; i++)
+       XmStringGetLtoR(stringtable[i], XmSTRING_DEFAULT_CHARSET, &items[i]);
+    items[nitems] = (char *) NULL;
+
+    table = uiConfigPF((void *) NULL, C_DEFAULTS);
+    (void) uiConfigSetPF(table, C_DEFAULTSTABLE, (void *) items);
+}
diff --git a/Ui/UiTypes.h b/Ui/UiTypes.h
new file mode 100644 (file)
index 0000000..48939d8
--- /dev/null
@@ -0,0 +1,281 @@
+typedef struct {
+    int TopMargin, BottomMargin;
+    int LeftMargin, RightMargin;
+    int UseFixed;
+    int FixedWidth;
+    int OnePageMode;
+} uiPageSettings_t;
+
+
+typedef struct {
+    int X, Y;
+    int Width, Height;
+    int VirtualWidth, VirtualHeight;
+} uiPageLayout_t;
+
+
+typedef struct {
+    Widget TopWdg;
+    Widget FormWdg;
+    Widget MenuWdg;
+    Widget DrawAreaWdg;
+    Widget HScrollBarWdg;
+    Widget VScrollBarWdg;
+    Widget FindFrameWdg;
+    Widget FindWdg;
+    Widget FindTextWdg;
+    Widget ControlWdg;
+} uiPageGfx_t;
+
+
+struct _uipage;
+
+typedef struct {
+    char *ActionName;
+    struct _uipage *Page;
+} uiActionData_t;
+
+
+typedef struct _pagecblist {
+    uiActionData_t ActionData;
+    struct _pagecblist *Next;
+} uiPageCBList_t;
+
+
+struct _uihierarchy;
+
+typedef struct _uipage {
+    HText_t *HText;
+    HTextObject_t *HTextObject;
+    int Visible;
+    struct _uihierarchy *Hierarchy;
+    uiPageSettings_t Settings;
+    uiPageLayout_t Layout;
+    uiPageGfx_t Gfx;
+    uiPageCBList_t *Callbacks;
+    struct _uipage *Next;
+} uiPage_t;
+
+
+typedef struct _uihierarchy {
+    char *Address;
+    uiPage_t *Pages;
+    struct _uihierarchy *Next;
+} uiHierarchy_t;
+
+
+typedef struct _uiaction {
+    char *Name;
+    void (*Callback) (char *address, HText_t * htext,
+                      HTextObject_t * htextobject, void *parameter);
+    void *Parameter;
+    struct _uiaction *Next;
+} uiAction_t;
+
+
+typedef struct _uikey {
+    char *Name;
+    int Modifier;
+    void (*Callback) (char *address, HText_t * htext,
+                      HTextObject_t * htextobject, void *parameter);
+    void *Parameter;
+    struct _uikey *Next;
+} uiKey_t;
+
+
+typedef enum {
+    uiWTtext,
+    uiWToptionmenu,
+    uiWTradiobox,
+    uiWTcheckbutton,
+    uiWTscale
+} uiWdgType_t;
+
+
+typedef struct _uivariable {
+    char *Name;
+    void *Value;
+    uiVarType_t VarType;
+    Widget Wdg;
+    uiWdgType_t WdgType;
+    struct _uivariable *Next;
+} uiVariable_t;
+
+
+typedef struct {
+    int TopMargin, BottomMargin;
+    int LeftMargin, RightMargin;
+    int UseFixed;
+    int FixedWidth;
+    int OnePageMode;
+    int Width;
+    int Height;
+    int SearchPlacement;
+    int ControlPanelPlacement;
+    int ListPlacement;
+    int RecallPlacement;
+    int PageSettingsPlacement;
+    Time DoubleClickTime;
+} uiGlobalSettings_t;
+
+
+typedef struct {
+    Widget TopWdg;
+    Widget FormWdg;
+    Widget InfoWdg;
+    Widget OpenWdg;
+    Widget QuitWdg;
+    Widget HelpWdg;
+} uiTopLevelGfx_t;
+
+
+typedef struct {
+    Widget FormWdg;
+    Widget FSBoxWdg;
+    Widget SeparatorWdg;
+    Widget ListWdg;
+    Widget AddWdg;
+    Widget DeleteWdg;
+} uiSelectionBoxGfx_t;
+
+
+typedef struct {
+    Widget FormWdg;
+    Widget TextWdg;
+    Widget LevelWdg;
+    Widget LevelFormWdg;
+    Widget LevelDownWdg;
+    Widget LevelUpWdg;
+    Widget CaseWdg;
+    Widget BackwardWdg;
+    Widget ForwardWdg;
+    Widget LabelWdg;
+    Widget CloseWdg;
+} uiSearchGfx_t;
+
+
+typedef struct {
+    Widget FormWdg;
+    Widget LabelWdg;
+    Widget LeftMarginWdg;
+    Widget RightMarginWdg;
+    Widget TopMarginWdg;
+    Widget BottomMarginWdg;
+    Widget LeftMarginTextWdg;
+    Widget RightMarginTextWdg;
+    Widget TopMarginTextWdg;
+    Widget BottomMarginTextWdg;
+    Widget UseFixedWdg;
+    Widget UseFixedTextWdg;
+    Widget SinglePageWdg;
+} uiPageSettingsGfx_t;
+
+
+typedef struct {
+    Widget FormWdg;
+    Widget PrintCmdWdg;
+    Widget PrintFileWdg;
+    Widget LeftMarginWdg;
+    Widget RightMarginWdg;
+    Widget TopMarginWdg;
+    Widget BottomMarginWdg;
+    Widget LeftMarginTextWdg;
+    Widget RightMarginTextWdg;
+    Widget TopMarginTextWdg;
+    Widget BottomMarginTextWdg;
+    Widget WidthWdg;
+} uiPrintGfx_t;
+
+
+typedef struct {
+    Widget FormWdg;
+    Widget LabelWdg;
+    Widget ListWdg;
+    Widget SeparatorWdg;
+    Widget OpenWdg;
+    Widget CloseWdg;
+} uiListGfx_t;
+
+
+typedef struct {
+    Widget FormWdg;
+    Widget LabelWdg;
+    Widget ListWdg;
+    Widget SeparatorWdg;
+    Widget OpenWdg;
+    Widget CloseWdg;
+} uiRecallGfx_t;
+
+
+typedef struct {
+    Widget FormWdg;
+    Widget OkWdg;
+} uiInfoGfx_t;
+
+
+typedef struct {
+    Widget SearchWdg;
+    Widget FormWdg;
+    Widget HomeWdg;
+    Widget RecallWdg;
+    Widget CloseWdg;
+    Widget LabelWdg;
+    Widget DialogCloseWdg;
+    Widget ListWdg;
+} uiControlPanelGfx_t;
+
+
+typedef struct {
+    Widget FormWdg;
+    Widget LabelWdg;
+    Widget SearchWindow;
+    Widget ControlPanel;
+    Widget ListWindow;
+    Widget RecallWindow;
+    Widget PageSettings;
+    Widget CloseWdg;
+} uiDefaultsGfx_t;
+
+
+typedef struct {
+    Widget FormWdg;
+    Widget LabelWdg;
+    Widget KillWdg;
+    Widget CloseWdg;
+    Widget SeparatorWdg;
+    Widget ListWdg;
+} uiConnectionsGfx_t;
+
+
+typedef struct {
+    Widget FormWdg;
+    Widget FSBoxWdg;
+} uiFileSelectionGfx_t;
+
+
+typedef struct {
+    uiHierarchy_t *Hierarchies;
+    uiAction_t *Actions;
+    uiKey_t *Keys;
+    uiVariable_t *Variables;
+    uiGlobalSettings_t GlobalSettings;
+    uiTopLevelGfx_t TopGfx;
+    uiSelectionBoxGfx_t SBGfx;
+    uiSearchGfx_t SearchGfx;
+    uiPageSettingsGfx_t PageSettingsGfx;
+    uiListGfx_t ListGfx;
+    uiRecallGfx_t RecallGfx;
+    uiInfoGfx_t InfoGfx;
+    uiControlPanelGfx_t ControlPanelGfx;
+    uiDefaultsGfx_t DefaultsGfx;
+    uiPrintGfx_t PrintGfx;
+    uiConnectionsGfx_t ConnectionsGfx;
+    uiFileSelectionGfx_t FSGfx;
+} uiTopLevel_t;
+
+
+typedef struct {
+    uiPage_t *CurrentPage;
+    Widget Wdg;
+    void *CallData;
+} uiPageInfo_t;
diff --git a/Ui/UiUtil.c b/Ui/UiUtil.c
new file mode 100644 (file)
index 0000000..30e72cc
--- /dev/null
@@ -0,0 +1,127 @@
+static char *rcsid = "$Id$";
+
+#include "UiIncludes.h"
+
+
+static void uiwarningokcb(Widget wdg, caddr_t callback,
+                          XmListCallbackStruct * calldata);
+static void uiwarningcancelcb(Widget wdg, caddr_t callback,
+                              XmListCallbackStruct * calldata);
+
+int UiDisplayWarningDialog(warning, callback)
+char *warning;
+void (*callback) (int button);
+{
+    Widget labelwdg;
+    Widget separatorwdg;
+    Widget okwdg;
+    Widget cancelwdg;
+    XmString warningstr;
+    ArgList args;
+    Cardinal nargs;
+    Window root, child;
+    int root_x, root_y, win_x, win_y;
+    unsigned int mask;
+    Widget formwdg;
+    Widget topwdg;
+    char tmpstr[11];
+
+    if (XQueryPointer(XtDisplay(uiTopLevel.TopGfx.TopWdg),
+                     XtWindow(uiTopLevel.TopGfx.TopWdg), &root, &child,
+                     &root_x, &root_y, &win_x, &win_y, &mask)) {
+       sprintf(tmpstr, "+%d+%d", root_x - 50, root_y - 50);
+
+       topwdg = XtCreateApplicationShell("Warning",
+                                         topLevelShellWidgetClass,
+                                         NULL, 0);
+       XtVaSetValues(topwdg,
+                     XmNgeometry, tmpstr, NULL);
+
+       args = uiVaSetArgs(&nargs,
+                          XmNresizePolicy, XmRESIZE_NONE,
+                          XmNautoUnmanage, FALSE, NULL);
+       formwdg = XmCreateForm(topwdg, "WarningDialog", args, nargs);
+
+       warningstr = XmStringCreateSimple(warning);
+       args = uiVaSetArgs(&nargs,
+                          XmNlabelString, warningstr,
+                          XmNtopAttachment, XmATTACH_FORM,
+                          XmNtopOffset, UI_LIST_WDG_OFFSET,
+                          XmNleftAttachment, XmATTACH_FORM,
+                          XmNrightAttachment, XmATTACH_FORM, NULL);
+       labelwdg = XmCreateLabelGadget(formwdg, "WarningLabel",
+                                      args, nargs);
+       XtManageChild(labelwdg);
+
+       args = uiVaSetArgs(&nargs,
+                          XmNtopAttachment, XmATTACH_WIDGET,
+                          XmNtopWidget, labelwdg,
+                          XmNtopOffset, UI_LIST_WDG_OFFSET,
+                          XmNleftAttachment, XmATTACH_FORM,
+                          XmNrightAttachment, XmATTACH_FORM, NULL);
+       separatorwdg = XmCreateSeparatorGadget(formwdg, "WarningSeparator",
+                                              args, nargs);
+       XtManageChild(separatorwdg);
+
+       args = uiVaSetArgs(&nargs,
+                          XmNleftAttachment, XmATTACH_POSITION,
+                          XmNleftPosition, 5,
+                          XmNrightAttachment, XmATTACH_POSITION,
+                          XmNrightPosition, 40,
+                          XmNtopAttachment, XmATTACH_WIDGET,
+                          XmNtopWidget, separatorwdg,
+                          XmNtopOffset, UI_LIST_WDG_OFFSET,
+                          XmNbottomAttachment, XmATTACH_FORM,
+                          XmNbottomOffset, UI_LIST_WDG_OFFSET, NULL);
+       okwdg = XmCreatePushButtonGadget(formwdg, "Ok", args, nargs);
+       XtAddCallback(okwdg, XmNactivateCallback,
+                     (XtCallbackProc) uiwarningokcb, (caddr_t) callback);
+       XtManageChild(okwdg);
+
+       if (callback) {
+           args = uiVaSetArgs(&nargs,
+                              XmNleftAttachment, XmATTACH_POSITION,
+                              XmNleftPosition, 60,
+                              XmNrightAttachment, XmATTACH_POSITION,
+                              XmNrightPosition, 95,
+                              XmNtopAttachment, XmATTACH_WIDGET,
+                              XmNtopWidget, separatorwdg,
+                              XmNtopOffset, UI_LIST_WDG_OFFSET,
+                              XmNbottomAttachment, XmATTACH_FORM,
+                              XmNbottomOffset, UI_LIST_WDG_OFFSET, NULL);
+           cancelwdg = XmCreatePushButtonGadget(formwdg, "Cancel",
+                                                args, nargs);
+           XtAddCallback(cancelwdg, XmNactivateCallback,
+                         (XtCallbackProc) uiwarningcancelcb,
+                         (caddr_t) callback);
+           XtManageChild(cancelwdg);
+       }
+       XtManageChild(formwdg);
+       XtRealizeWidget(XtParent(formwdg));
+
+       return UI_OK;
+    }
+}
+
+
+static void uiwarningokcb(wdg, callback, calldata)
+Widget wdg;
+caddr_t callback;
+XmListCallbackStruct *calldata;
+{
+    int button = UI_OK;
+
+    if (callback)
+       (*(void (*) (int button)) callback) (UI_OK);
+
+    XtUnmapWidget(XtParent(XtParent(wdg)));
+}
+
+
+static void uiwarningcancelcb(wdg, ignored, calldata)
+Widget wdg;
+caddr_t ignored;
+XmListCallbackStruct *calldata;
+{
+    XtUnmapWidget(XtParent(XtParent(wdg)));
+}
diff --git a/Xl/Imakefile b/Xl/Imakefile
new file mode 100644 (file)
index 0000000..cd05a8e
--- /dev/null
@@ -0,0 +1,17 @@
+#
+#
+#
+
+          OBJS = XlFormatText.o XlSetup.o XlUtil.o XlWindow.o XlStyle.o
+          SRCS = XlFormatText.c XlSetup.c XlUtil.c XlWindow.c XlStyle.c
+
+         XLDIR = ../Xl
+         HTDIR = ../HText
+        WWWDIR = ../Cl/WWWLibrary
+     MOTIF_HDRS = -I/p/motif/include
+    ERWISE_HDRS = -I$(XLDIR) -I$(HTDIR) -I$(WWWDIR)
+       DEFINES = $(ERWISE_HDRS) $(MOTIF_HDRS)
+
+NormalLibraryTarget(Xl, $(OBJS))
+
+DependTarget()
diff --git a/Xl/Makefile b/Xl/Makefile
new file mode 100644 (file)
index 0000000..c4f0561
--- /dev/null
@@ -0,0 +1,339 @@
+# Makefile generated by imake - do not edit!
+# $XConsortium: imake.c,v 1.65 91/07/25 17:50:17 rws Exp $
+#
+# The cpp used on this machine replaces all newlines and multiple tabs and
+# spaces in a macro expansion with a single space.  Imake tries to compensate
+# for this, but is not always successful.
+#
+
+# -------------------------------------------------------------------------
+# Makefile generated from "Imake.tmpl" and </tmp/IIf.a10887>
+# $XConsortium: Imake.tmpl,v 1.139 91/09/16 08:52:48 rws Exp $
+#
+# Platform-specific parameters may be set in the appropriate <vendor>.cf
+# configuration files.  Site-specific parameters should be set in the file
+# site.def.  Full rebuilds are recommended if any parameters are changed.
+#
+# If your C preprocessor does not define any unique symbols, you will need
+# to set BOOTSTRAPCFLAGS when rebuilding imake (usually when doing
+# "make World" the first time).
+#
+
+# -------------------------------------------------------------------------
+# site-specific configuration parameters that need to come before
+# the platform-specific parameters - edit site.def to change
+
+# site:  $XConsortium: site.def,v 1.2 91/07/30 20:26:44 rws Exp $
+
+# -------------------------------------------------------------------------
+# platform-specific configuration parameters - edit sun.cf to change
+
+# platform:  $XConsortium: sun.cf,v 1.72.1.1 92/03/18 13:13:37 rws Exp $
+
+# operating system:  SunOS 4.1.2
+
+# $XConsortium: sunLib.rules,v 1.7 91/12/20 11:19:47 rws Exp $
+
+.c.o:
+       $(CC) -c $(CFLAGS) $*.c
+
+# -------------------------------------------------------------------------
+# site-specific configuration parameters that go after
+# the platform-specific parameters - edit site.def to change
+
+# site:  $XConsortium: site.def,v 1.2 91/07/30 20:26:44 rws Exp $
+
+            SHELL = /bin/sh
+
+              TOP = ../.
+      CURRENT_DIR = ./Xl
+
+               AR = ar clq
+  BOOTSTRAPCFLAGS =
+               CC = gcc2 -pipe -fstrength-reduce -fpcc-struct-return
+               AS = as
+
+         COMPRESS = compress
+              CPP = /lib/cpp $(STD_CPP_DEFINES)
+    PREPROCESSCMD = gcc2 -pipe -fstrength-reduce -fpcc-struct-return -E $(STD_CPP_DEFINES)
+          INSTALL = install
+               LD = ld
+             LINT = lint
+      LINTLIBFLAG = -C
+         LINTOPTS = -axz
+               LN = ln -s
+             MAKE = make
+               MV = mv
+               CP = cp
+
+           RANLIB = ranlib
+  RANLIBINSTFLAGS =
+
+               RM = rm -f
+            TROFF = psroff
+         MSMACROS = -ms
+              TBL = tbl
+              EQN = eqn
+     STD_INCLUDES =
+  STD_CPP_DEFINES =
+      STD_DEFINES =
+ EXTRA_LOAD_FLAGS = -B/usr/bin/
+  EXTRA_LIBRARIES =
+             TAGS = ctags
+
+    SHAREDCODEDEF = -DSHAREDCODE
+         SHLIBDEF = -DSUNSHLIB
+
+    PROTO_DEFINES =
+
+     INSTPGMFLAGS =
+
+     INSTBINFLAGS = -m 0755
+     INSTUIDFLAGS = -m 4755
+     INSTLIBFLAGS = -m 0644
+     INSTINCFLAGS = -m 0444
+     INSTMANFLAGS = -m 0444
+     INSTDATFLAGS = -m 0444
+    INSTKMEMFLAGS = -g kmem -m 2755
+
+      PROJECTROOT = /v/X11R5
+
+     TOP_INCLUDES = -I$(INCROOT)
+
+      CDEBUGFLAGS = -O
+        CCOPTIONS =
+
+      ALLINCLUDES = $(INCLUDES) $(EXTRA_INCLUDES) $(TOP_INCLUDES) $(STD_INCLUDES)
+       ALLDEFINES = $(ALLINCLUDES) $(STD_DEFINES) $(EXTRA_DEFINES) $(PROTO_DEFINES) $(DEFINES)
+           CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLDEFINES)
+        LINTFLAGS = $(LINTOPTS) -DLINT $(ALLDEFINES)
+
+           LDLIBS = $(SYS_LIBRARIES) $(EXTRA_LIBRARIES)
+
+        LDOPTIONS = $(CDEBUGFLAGS) $(CCOPTIONS) $(LOCAL_LDFLAGS) -L$(USRLIBDIR)
+
+   LDCOMBINEFLAGS = -X -r
+      DEPENDFLAGS =
+
+        MACROFILE = sun.cf
+           RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *~ *.a .emacs_* tags TAGS make.log MakeOut
+
+    IMAKE_DEFINES =
+
+         IRULESRC = $(CONFIGDIR)
+        IMAKE_CMD = $(IMAKE) -DUseInstalled -I$(IRULESRC) $(IMAKE_DEFINES)
+
+     ICONFIGFILES = $(IRULESRC)/Imake.tmpl $(IRULESRC)/Imake.rules \
+                       $(IRULESRC)/Project.tmpl $(IRULESRC)/site.def \
+                       $(IRULESRC)/$(MACROFILE) $(EXTRA_ICONFIGFILES)
+
+# -------------------------------------------------------------------------
+# X Window System Build Parameters
+# $XConsortium: Project.tmpl,v 1.138 91/09/10 09:02:12 rws Exp $
+
+# -------------------------------------------------------------------------
+# X Window System make variables; this need to be coordinated with rules
+
+          PATHSEP = /
+        USRLIBDIR = /v/X11R5/lib
+           BINDIR = /v/X11R5/bin
+          INCROOT = /v/X11R5/include
+     BUILDINCROOT = $(TOP)
+      BUILDINCDIR = $(BUILDINCROOT)/X11
+      BUILDINCTOP = ..
+           INCDIR = $(INCROOT)/X11
+           ADMDIR = /usr/adm
+           LIBDIR = $(USRLIBDIR)/X11
+        CONFIGDIR = $(LIBDIR)/config
+       LINTLIBDIR = $(USRLIBDIR)/lint
+
+          FONTDIR = $(LIBDIR)/fonts
+         XINITDIR = $(LIBDIR)/xinit
+           XDMDIR = $(LIBDIR)/xdm
+           TWMDIR = $(LIBDIR)/twm
+          MANPATH = /v/X11R5/man
+    MANSOURCEPATH = $(MANPATH)/man
+        MANSUFFIX = n
+     LIBMANSUFFIX = 3
+           MANDIR = $(MANSOURCEPATH)$(MANSUFFIX)
+        LIBMANDIR = $(MANSOURCEPATH)$(LIBMANSUFFIX)
+           NLSDIR = $(LIBDIR)/nls
+        PEXAPIDIR = $(LIBDIR)/PEX
+      XAPPLOADDIR = $(LIBDIR)/app-defaults
+       FONTCFLAGS = -t
+
+     INSTAPPFLAGS = $(INSTDATFLAGS)
+
+            IMAKE = imake
+           DEPEND = makedepend
+              RGB = rgb
+
+            FONTC = bdftopcf
+
+        MKFONTDIR = mkfontdir
+        MKDIRHIER = /bin/sh $(BINDIR)/mkdirhier
+
+        CONFIGSRC = $(TOP)/config
+       DOCUTILSRC = $(TOP)/doc/util
+        CLIENTSRC = $(TOP)/clients
+          DEMOSRC = $(TOP)/demos
+           LIBSRC = $(TOP)/lib
+          FONTSRC = $(TOP)/fonts
+       INCLUDESRC = $(TOP)/X11
+        SERVERSRC = $(TOP)/server
+          UTILSRC = $(TOP)/util
+        SCRIPTSRC = $(UTILSRC)/scripts
+       EXAMPLESRC = $(TOP)/examples
+       CONTRIBSRC = $(TOP)/../contrib
+           DOCSRC = $(TOP)/doc
+           RGBSRC = $(TOP)/rgb
+        DEPENDSRC = $(UTILSRC)/makedepend
+         IMAKESRC = $(CONFIGSRC)
+         XAUTHSRC = $(LIBSRC)/Xau
+          XLIBSRC = $(LIBSRC)/X
+           XMUSRC = $(LIBSRC)/Xmu
+       TOOLKITSRC = $(LIBSRC)/Xt
+       AWIDGETSRC = $(LIBSRC)/Xaw
+       OLDXLIBSRC = $(LIBSRC)/oldX
+      XDMCPLIBSRC = $(LIBSRC)/Xdmcp
+      BDFTOSNFSRC = $(FONTSRC)/bdftosnf
+      BDFTOSNFSRC = $(FONTSRC)/clients/bdftosnf
+      BDFTOPCFSRC = $(FONTSRC)/clients/bdftopcf
+     MKFONTDIRSRC = $(FONTSRC)/clients/mkfontdir
+         FSLIBSRC = $(FONTSRC)/lib/fs
+    FONTSERVERSRC = $(FONTSRC)/server
+     EXTENSIONSRC = $(TOP)/extensions
+         XILIBSRC = $(EXTENSIONSRC)/lib/xinput
+      PHIGSLIBSRC = $(EXTENSIONSRC)/lib/PEX
+
+# $XConsortium: sunLib.tmpl,v 1.14.1.1 92/03/17 14:58:46 rws Exp $
+
+SHLIBLDFLAGS = -assert pure-text
+PICFLAGS = -fPIC
+
+  DEPEXTENSIONLIB =
+     EXTENSIONLIB = -lXext
+
+          DEPXLIB = $(DEPEXTENSIONLIB)
+             XLIB = $(EXTENSIONLIB) -lX11
+
+        DEPXMULIB = $(USRLIBDIR)/libXmu.sa.$(SOXMUREV)
+       XMULIBONLY = -lXmu
+           XMULIB = -lXmu
+
+       DEPOLDXLIB =
+          OLDXLIB = -loldX
+
+      DEPXTOOLLIB = $(USRLIBDIR)/libXt.sa.$(SOXTREV)
+         XTOOLLIB = -lXt
+
+        DEPXAWLIB = $(USRLIBDIR)/libXaw.sa.$(SOXAWREV)
+           XAWLIB = -lXaw
+
+        DEPXILIB =
+           XILIB = -lXi
+
+        SOXLIBREV = 4.10
+          SOXTREV = 4.10
+         SOXAWREV = 5.0
+        SOOLDXREV = 4.10
+         SOXMUREV = 4.10
+        SOXEXTREV = 4.10
+      SOXINPUTREV = 4.10
+
+      DEPXAUTHLIB = $(USRLIBDIR)/libXau.a
+         XAUTHLIB =  -lXau
+      DEPXDMCPLIB = $(USRLIBDIR)/libXdmcp.a
+         XDMCPLIB =  -lXdmcp
+
+        DEPPHIGSLIB = $(USRLIBDIR)/libphigs.a
+           PHIGSLIB =  -lphigs
+
+       DEPXBSDLIB = $(USRLIBDIR)/libXbsd.a
+          XBSDLIB =  -lXbsd
+
+ LINTEXTENSIONLIB = $(LINTLIBDIR)/llib-lXext.ln
+         LINTXLIB = $(LINTLIBDIR)/llib-lX11.ln
+          LINTXMU = $(LINTLIBDIR)/llib-lXmu.ln
+        LINTXTOOL = $(LINTLIBDIR)/llib-lXt.ln
+          LINTXAW = $(LINTLIBDIR)/llib-lXaw.ln
+           LINTXI = $(LINTLIBDIR)/llib-lXi.ln
+        LINTPHIGS = $(LINTLIBDIR)/llib-lphigs.ln
+
+          DEPLIBS = $(DEPXAWLIB) $(DEPXMULIB) $(DEPXTOOLLIB) $(DEPXLIB)
+
+         DEPLIBS1 = $(DEPLIBS)
+         DEPLIBS2 = $(DEPLIBS)
+         DEPLIBS3 = $(DEPLIBS)
+
+# -------------------------------------------------------------------------
+# Imake rules for building libraries, programs, scripts, and data files
+# rules:  $XConsortium: Imake.rules,v 1.123 91/09/16 20:12:16 rws Exp $
+
+# -------------------------------------------------------------------------
+# start of Imakefile
+
+#
+#
+#
+
+          OBJS = XlFormatText.o XlSetup.o XlUtil.o XlWindow.o XlStyle.o
+          SRCS = XlFormatText.c XlSetup.c XlUtil.c XlWindow.c XlStyle.c
+
+         XLDIR = ../Xl
+         HTDIR = ../HText
+        WWWDIR = ../Cl/WWWLibrary
+     MOTIF_HDRS = -I/p/motif/include
+    ERWISE_HDRS = -I$(XLDIR) -I$(HTDIR) -I$(WWWDIR)
+       DEFINES = $(ERWISE_HDRS) $(MOTIF_HDRS)
+
+all:: libXl.a
+
+libXl.a:  $(OBJS)
+       $(RM) $@
+       $(AR) $@  $(OBJS)
+       $(RANLIB) $@
+
+depend::
+       $(DEPEND) $(DEPENDFLAGS) -s "# DO NOT DELETE" -- $(ALLDEFINES) -- $(SRCS)
+
+# -------------------------------------------------------------------------
+# common rules for all Makefiles - do not edit
+
+emptyrule::
+
+clean::
+       $(RM_CMD) "#"*
+
+Makefile::
+       -@if [ -f Makefile ]; then set -x; \
+       $(RM) Makefile.bak; $(MV) Makefile Makefile.bak; \
+       else exit 0; fi
+       $(IMAKE_CMD) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT_DIR)
+
+tags::
+       $(TAGS) -w *.[ch]
+       $(TAGS) -xw *.[ch] > TAGS
+
+saber:
+       # load $(ALLDEFINES) $(SRCS)
+
+osaber:
+       # load $(ALLDEFINES) $(OBJS)
+
+# -------------------------------------------------------------------------
+# empty rules for directories that do not have SUBDIRS - do not edit
+
+install::
+       @echo "install in $(CURRENT_DIR) done"
+
+install.man::
+       @echo "install.man in $(CURRENT_DIR) done"
+
+Makefiles::
+
+includes::
+
+# -------------------------------------------------------------------------
+# dependencies generated by makedepend
+
diff --git a/Xl/Xl.h b/Xl/Xl.h
new file mode 100644 (file)
index 0000000..e413943
--- /dev/null
+++ b/Xl/Xl.h
@@ -0,0 +1,44 @@
+/*
+ * Xl.h --
+ *
+ * Author: Teemu Rantanen <tvr@cs.hut.fi>
+ * Copyright (c) 1992 Teemu Rantanen
+ *                    All rights reserved
+ *
+ * Created: Tue Mar 10 20:43:22 1992 tvr
+ * Last modified: Wed May 13 06:21:11 1992 tvr
+ *
+ */
+
+
+/*
+ * Prototypes
+ */
+int XlFormatText(int leftmargin, int width, int topmargin,
+                 int *vwidth, int *vheight, HText_t * htext);
+
+int XlSetupResources(void *(*func) (void *, char *));
+
+int XlSetupText(Display * display, Window window,
+                unsigned long fg,
+                unsigned long bg,
+                HText_t * htext);
+
+void XlSetPageCoordinates(int virtualx, int virtualy, HText_t * htext);
+
+void XlGetCoordinates(int *virtualx, int *virtualy,
+                      HTextObject_t * htextobject);
+
+HTextObject_t *XlLocateHTextObject(int windowx, int windowy,
+                                   HText_t * htext);
+
+void XlDeleteText(HText_t * htext);
+
+void XlRedraw(int windowx, int windowy, int width, int height,
+              HText_t * htext);
+
+void XlMoveWindow(int newvx, int newvy, HText_t * htext);
+
+void XlClearWindow(int width, int height, HText_t * htext);
+
+void XlSetCursor(HText_t * htext, HTextObject_t * object);
diff --git a/Xl/XlConfig.h b/Xl/XlConfig.h
new file mode 100644 (file)
index 0000000..0d37f97
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * XlConfig.h --
+ *
+ * Author: Teemu Rantanen <tvr@cs.hut.fi>
+ * Copyright (c) 1992 Teemu Rantanen
+ *                    All rights reserved
+ *
+ * Created: Wed May 13 06:21:04 1992 tvr
+ * Last modified: Wed May 13 06:21:14 1992 tvr
+ *
+ */
+
+
+/*
+ * Fucking configurestuff here
+ */
+
+#define C_FONTS                "Fonts"
+
+#define C_FONT_NORMAL          "normal"
+#define C_FONT_LIST            "list"
+#define C_FONT_LISTCOMPACT     "listcompact"
+#define C_FONT_GLOSSARY        "glossary"
+#define C_FONT_GLOSSARYCOMPACT "glossarycompact"
+#define C_FONT_EXAMPLE         "example"
+#define C_FONT_LISTING         "listing"
+#define C_FONT_ADDRESS         "address"
+#define C_FONT_HEADER1         "header1"
+#define C_FONT_HEADER2         "header2"
+#define C_FONT_HEADER3         "header3"
+#define C_FONT_HEADER4         "header4"
+#define C_FONT_HEADER5         "header5"
+#define C_FONT_HEADER6         "header6"
+#define C_FONT_HEADER7         "header7"
diff --git a/Xl/XlDefaultFonts.h b/Xl/XlDefaultFonts.h
new file mode 100644 (file)
index 0000000..4961a5d
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * XlDefaultFonts.h --
+ *
+ * Author: Teemu Rantanen <tvr@cs.hut.fi>
+ * Copyright (c) 1992 Teemu Rantanen
+ *                    All rights reserved
+ *
+ * Created: Sat Mar  7 03:33:24 1992 tvr
+ * Last modified: Mon Mar  9 05:27:20 1992 tvr
+ *
+ */
+
+#define FONT_NORMAL            "-adobe-times-medium-r-normal--12-120-75-75-p-64-iso8859-1"
+
+#define FONT_LIST              "8x13"
+
+#define FONT_LISTCOMPACT       "6x13"
+
+#define FONT_GLOSSARY          "-adobe-times-medium-r-normal--12-120-75-75-p-64-iso8859-1"
+
+#define FONT_GLOSSARYCOMPACT   "-adobe-times-medium-r-normal--12-120-75-75-p-64-iso8859-1"
+
+/*
+ * Text on the LISTING tag is to be portrayed in a fixed width font, so that any formatting done by
+ * character spacing on successive lines will be maintained.
+ *
+ * At least 132 characters have to fit on a line.
+ */
+#define FONT_EXAMPLE           "7x13"
+
+#define FONT_LISTING           "7x13"
+
+#define FONT_ADDRESS           "8x13"
+
+#define FONT_HEADER1           "-adobe-times-medium-r-normal--20-140-100-100-p-96-iso8859-1"
+
+#define FONT_HEADER2           "-adobe-times-medium-r-normal--18-180-75-75-p-94-iso8859-1"
+
+#define FONT_HEADER3           "-adobe-times-medium-r-normal--17-120-100-100-p-84-iso8859-1"
+
+#define FONT_HEADER4           "-adobe-times-medium-r-normal--14-100-100-100-p-74-iso8859-1"
+
+#define FONT_HEADER5           "-adobe-times-medium-r-normal--14-100-100-100-p-74-iso8859-1"
+
+#define FONT_HEADER6           "-adobe-times-medium-r-normal--14-100-100-100-p-74-iso8859-1"
+
+#define FONT_HEADER7           "-adobe-times-medium-r-normal--14-100-100-100-p-74-iso8859-1"
diff --git a/Xl/XlFormatText.c b/Xl/XlFormatText.c
new file mode 100644 (file)
index 0000000..f97bdbf
--- /dev/null
@@ -0,0 +1,573 @@
+/*
+ * XlFormatText.c --
+ *
+ * Author: Teemu Rantanen <tvr@cs.hut.fi>
+ * Copyright (c) 1992 Teemu Rantanen
+ *                    All rights reserved
+ *
+ * Created: Tue Mar  3 02:54:45 1992 tvr
+ * Last modified: Tue May 12 04:26:29 1992 tvr
+ *
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <limits.h>
+
+#include "HTAnchor.h"
+#include "HTStyle.h"
+#include "../HText/HText.h"
+
+#include "XlFormatText.h"
+
+int xl_calc_position();
+int xl_character_width();
+
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+
+/*
+ * Set up how to format text (current left and right margins)
+ */
+void xl_set_margins(p, left, right, c_l, c_r, x, y, low_y, m)
+HTextObject_t *p;
+int left, right;
+int *c_l, *c_r;
+int *x, *y;
+int low_y;
+int m;
+{
+    int i;
+
+    switch (m) {
+    case MARGIN_START_STYLE:
+       i = xl_object_mode(p);
+
+       *c_l = xl_calc_position(p, I_LEFT, left, right);
+
+       *x = xl_calc_position(p, I_LEFT | I_FIRST, left, right);
+
+       if (i & STYLE_RAW) {
+           *c_r = INT_MAX;
+       } else {
+
+           if (i & STYLE_CHANGE_REGION_ON_TAB) {
+
+               *c_r = xl_calc_position(p, I_MIDDLE_L, left, right);
+
+           } else {
+
+               *c_r = xl_calc_position(p, I_RIGHT, left, right);
+
+           }
+       }
+       break;
+
+    case MARGIN_HANDLE_P_OBJECT:
+       if (xl_object_mode(p) & STYLE_CHANGE_REGION_ON_TAB) {
+
+           *c_l = xl_calc_position(p, I_MIDDLE_R, left, right);
+           *c_r = xl_calc_position(p, I_RIGHT, left, right);
+           *y = low_y;
+           *x = xl_calc_position(p, I_MIDDLE_R | I_FIRST, left, right);
+
+       } else {
+
+           *x += 60;           /* :-) */
+
+#ifdef XL_DEBUG
+           printf("xl_set_margins(): normal tab ... barf\n");
+#endif
+       }
+       break;
+
+#ifdef XL_DEBUG
+    default:
+       printf("xl_set_margins: illegal mode\n");
+#endif
+    }
+}
+
+
+/*
+ * Check how many objects belongs to this line.
+ */
+int xl_check_objects(pp, x_corner, y, right)
+HTextObject_t **pp;
+int *x_corner;
+int y;
+int right;
+{
+    HTextObject_t *p, *p_old;
+
+    int x;
+
+    int r = 0;
+
+    p = *pp;
+
+    p_old = NULL;
+
+    x = *x_corner;
+
+    while (!r) {
+       /*
+         * Region ends ?
+         */
+       if (!p || (p->paragraph)) {
+           r |= FORMAT_REGION_ENDS;
+       }
+       /*
+         * End of text
+         */
+       if (!p) {
+           break;
+       }
+       /*
+         * New style?
+         */
+       if (p_old && (p_old->style != p->style)) {
+           r |= FORMAT_NEW_STYLE;
+           r |= FORMAT_REGION_ENDS;
+       }
+       /*
+         * Text full ?
+         */
+       if ((x + p->width) >= right) {
+           r |= FORMAT_NEXT_OBJECT_TOO_LONG;
+       }
+       /*
+         * Setup object
+         */
+       p->x = x;
+       p->y = y;
+
+       x += p->width + xl_wordgap(p);
+
+
+       if (!r) {
+           p_old = p;
+
+           p = p->next;
+       }
+    }
+
+    /*
+     * Return pointer to where to go on.
+     */
+    if (p_old) {
+       *pp = p;
+    }
+    *x_corner = x;
+
+    return r;
+}
+
+/*
+ * Set new x-koordinate if line of objects is not 'leftified'
+ * Set new y coordinate above all objects.
+ */
+void xl_modify_objects(p_start, p_end, right, mode)
+HTextObject_t *p_start;
+HTextObject_t *p_end;
+int right;
+int mode;
+{
+    HTextObject_t *p = p_start;
+    HTextObject_t *p_last;
+
+    int offset;
+
+    /*
+     * Set last object
+     */
+
+    if (p_start == p_end) {
+
+#ifdef XL_DEBUG
+       if (!p_start->paragraph) {
+           printf("zero object ?\n");
+       }
+#endif
+       p_last = p_start;
+
+    } else if (p_end) {
+
+       p_last = p_end->prev;
+
+    } else {
+
+       for (p_last = p; p_last->next; p_last = p_last->next);
+
+    }
+
+    switch (xl_object_style(p_start)) {
+    case STYLE_LEFTIFY:
+       /*
+         * Do nothing.
+         */
+       break;
+
+    case STYLE_CENTER:
+
+       offset = (right - (p_last->x + p_last->width)) / 2;
+
+       for (p; p != p_end; p = p->next) {
+           p->x += offset;
+       }
+       break;
+
+#ifdef XL_DEBUG
+    default:
+       printf("Style not supported yet\n");
+#endif
+    }
+#if 0
+    *newy = p_start->y + xl_lineheightandgap(p_start, p_end);
+#endif
+}
+
+
+/*
+ *  width is a request which can be denied (in case of ftp-text for
+ *  example)
+ *  Maximum width used on the page is returned. Everything else on the screen
+ *  is formatted using given width.
+ */
+int XlFormatText(leftmargin, width, topmargin, vwidth, vheight, htext)
+int leftmargin, width;
+int topmargin;
+int *vwidth, *vheight;
+HText_t *htext;
+{
+    int stepped_y;
+
+    int max_right_position = leftmargin;
+
+    /*
+     * Current x,y coordinates.
+     */
+    int x, y;
+
+    /*
+     * When there are many regions next to other, store starting
+     * upper and lower levels
+     */
+    int low_y = 0;
+    int high_y = 0;
+
+    /*
+     * current format region
+     */
+    int current_left;
+    int current_right;
+
+    /*
+     * Point out line
+     */
+    HTextObject_t *p = htext->first;
+
+    HTextObject_t *p_start = 0;
+
+    /*
+     * Should check ascend (if there is any text)
+     */
+    if (p) {
+
+       low_y = high_y = y = topmargin;
+
+       xl_set_margins(p, leftmargin, leftmargin + width,
+                      &current_left, &current_right,
+                      &x, &y, low_y, MARGIN_START_STYLE);
+    }
+    /*
+     * Loop through text
+     */
+    while (p) {
+       int mode;
+
+       int high_y_old;
+
+       stepped_y = 0;
+
+       high_y_old = y;
+
+       /*
+         * What objects are on this line ?
+         */
+       p_start = p;
+
+       mode = xl_check_objects(&p, &x, y, current_right);
+
+       /*
+         * Check for zero objects. This prevents endless loop and makes
+         * sure this object will be modified
+         */
+       if ((p == p_start) && p && !p->paragraph &&
+           (mode & FORMAT_NEXT_OBJECT_TOO_LONG)) {
+           mode |= FORMAT_ONLY_OBJECT_TOO_LONG;
+           p = p->next;
+       }
+       /*
+         * Update object positions if needs justifying etc
+         */
+       xl_modify_objects(p_start, p, current_right, mode);
+
+       /*
+         * Check maximum object x position
+         */
+
+       if (p && p->prev &&
+           ((p->prev->x + p->prev->width) > max_right_position)) {
+           max_right_position = p->prev->x + p->prev->width;
+       }
+       if (xl_object_mode(p_start) & STYLE_RAW) {
+           /*
+             * Raw style HTextObject paragraphs
+             */
+
+           if (p && p_start->paragraph) {
+               p = p->next;
+
+           }
+           switch (p_start->paragraph) {
+           case HTEXT_NEWLINE:
+               /*
+                * New line
+                */
+               x = current_left;
+
+               y += xl_linespace(p_start, p);
+
+               low_y = high_y = MAX(y, high_y);
+               break;
+
+           case HTEXT_TAB:
+               /*
+                * Tabulator
+                */
+#if 0
+               {
+                   int i = 0;
+                   HTextObject_t *pp;
+
+                   for (pp = p_start; pp != p; pp = pp->next) {
+                       switch (pp->paragraph) {
+                       case 0:
+                           i += pp->length;
+                           break;
+
+                       case HTEXT_TAB:
+                           i = 0;
+                       }
+                   }
+
+                   i = 8 - (i % 8);
+
+                   x += xl_character_width(p_start) * i;
+               }
+#endif
+               {
+                   int i;
+                   int cl = xl_character_width(p_start);
+
+                   i = ((x - leftmargin) % (cl * 8));
+
+                   x += (cl * 8) - i;
+               }
+
+               break;
+           }
+       } else {
+           /*
+             * Hypertext style
+             */
+
+           /*
+             * Wrap
+             */
+           if (mode & FORMAT_NEXT_OBJECT_TOO_LONG) {
+               x = current_left;
+               y += xl_linespace(p_start, p);
+
+               high_y = MAX(y, high_y);
+
+               if (mode & FORMAT_ONLY_OBJECT_TOO_LONG) {
+                   low_y = high_y;
+               }
+               stepped_y++;
+           }
+           /*
+             * Check paragraph objects
+             */
+           if (p_start->paragraph) {
+               switch (p_start->paragraph) {
+               case HTEXT_NEWLINE:
+
+                   x = current_left;
+                   if (!stepped_y) {
+                       y += xl_linespace(p_start, p);
+
+                       stepped_y++;
+
+                       high_y = MAX(y, high_y);
+                   }
+                   high_y = y;
+
+#ifdef XL_DEBUG
+                   printf("XlFormatText(): there should not be newlines in htext\n");
+#endif
+                   break;
+
+               case HTEXT_PARAGRAPH:
+
+                   if (!stepped_y) {
+                       y += xl_linespace(p_start, p);
+                       y += xl_paragraphspace(p_start, p);
+
+                       stepped_y++;
+                   }
+                   low_y = high_y = y;
+
+                   xl_set_margins(p, leftmargin, leftmargin + width,
+                                  &current_left, &current_right,
+                                  &x, &y, low_y, MARGIN_START_STYLE);
+                   break;
+
+               case HTEXT_TAB:
+
+                   xl_set_margins(p, leftmargin, leftmargin + width,
+                                  &current_left, &current_right, &x, &y,
+                                  low_y, MARGIN_HANDLE_P_OBJECT);
+                   break;
+
+               case HTEXT_CONTINUE:
+                   printf("format: dont understand continued objects here\n");
+                   exit(1);
+                   break;
+
+               }
+
+               p = p->next;
+
+           }
+       }
+
+       /*
+         * Make sure paragraph endings happen
+         */
+       if (p && (p->style != p_start->style)) {
+           mode |= FORMAT_NEW_STYLE;
+       }
+       /*
+         * Check for new style
+         */
+       if (mode & FORMAT_NEW_STYLE) {
+           /*
+             * Make sure one and only line is advanced always
+             */
+           if (y < high_y) {
+               if (!stepped_y) {
+                   high_y += xl_linespace(p_start, p);
+               }
+               high_y += xl_stylespace(p_start, p);
+
+               y = low_y = high_y;
+
+               stepped_y++;
+           } else {
+               if (high_y_old == high_y) {
+                   high_y += xl_linespace(p_start, p);
+               }
+               if (p) {
+                   high_y += xl_stylespace_before(p, p);
+               }
+               high_y += xl_stylespace(p_start, p);
+
+               y = low_y = high_y;
+
+               stepped_y++;
+           }
+
+           xl_set_margins(p, leftmargin, leftmargin + width,
+                          &current_left, &current_right,
+                          &x, &y, low_y, MARGIN_START_STYLE);
+       }
+    }
+
+#if 0
+    /*
+     * Check region ending
+     */
+    /* tab sivulle tai tab sivulleyl|s depending on object and so on */
+    /* p = p->next */
+    /* set regions with margin_handle_p_object */
+    /* check where to start (y, x). x = regionstart or tab */
+
+    if ((mode & FORMAT_REGION_ENDS) && p) {
+       int i;
+
+       i = p->paragraph;
+
+       switch (i) {
+       case HTEXT_PARAGRAPH:
+           high_y += xl_lineheightandgap(p_start, p);
+
+           y = low_y = high_y;
+
+           xl_set_margins(p, leftmargin, leftmargin + width,
+                          &current_left, &current_right,
+                          &x, &y, low_y, MARGIN_START_STYLE);
+           break;
+
+       case HTEXT_NEWLINE:
+           /*high_y += xl_lineheightandgap(p_start, p);*/
+           y = low_y = high_y;
+           x = current_left;
+
+           break;
+
+       case HTEXT_TAB:
+           xl_set_margins(p, leftmargin, leftmargin + width,
+                          &current_left, &current_right, &x, &y, low_y,
+                          MARGIN_HANDLE_P_OBJECT);
+           break;
+
+       case HTEXT_CONTINUE:
+           printf("format: dont understand continued objects here\n");
+           exit(1);
+           break;
+
+       }
+
+       if (i) {
+           p = p->next;
+       }
+    }
+    /*
+     * Check New style
+     */
+    if (mode & FORMAT_NEW_STYLE) {
+       high_y = low_y = y;
+
+       xl_set_margins(p, leftmargin, leftmargin + width,
+                      &current_left, &current_right,
+                      &x, &y, low_y, MARGIN_START_STYLE);
+    }
+#endif
+
+    /*
+     * Give width and height to caller
+     */
+
+    if (!stepped_y) {
+       if (p_start)
+           y += xl_linespace(p_start, p);
+       else
+           y = 1;
+    }
+    *vwidth = MAX(max_right_position, width);
+
+    *vheight = y;
+
+    return 0;
+}
diff --git a/Xl/XlFormatText.h b/Xl/XlFormatText.h
new file mode 100644 (file)
index 0000000..e5391ad
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * XlFormatText.h --
+ *
+ * Author: Teemu Rantanen <tvr@cs.hut.fi>
+ * Copyright (c) 1992 Teemu Rantanen
+ *                    All rights reserved
+ *
+ * Created: Fri Mar  6 20:44:40 1992 tvr
+ * Last modified: Mon Mar  9 04:57:21 1992 tvr
+ *
+ */
+
+/*
+ * Returncode of line checking
+ */
+#define FORMAT_FULL_LINE               1
+#define FORMAT_NEXT_OBJECT_TOO_LONG    2
+#define FORMAT_REGION_ENDS             4
+#define FORMAT_NEW_STYLE               8
+#define FORMAT_ONLY_OBJECT_TOO_LONG    16
+
+/*
+ * Indent defines
+ */
+#define I_LEFT                         1
+#define I_FIRST                                2
+#define        I_MIDDLE_L                      4
+#define        I_MIDDLE_R                      8
+#define        I_RIGHT                         16
+
+/*
+ * Font style flags stored on XlStyle_t
+ */
+
+/*
+ * Line styles
+ */
+#define STYLE_LEFTIFY                          0
+#define STYLE_RIGHTIFY                         1
+#define STYLE_CENTER                           2
+#define STYLE_JUSTIFY                          3
+
+#define STYLE_MASK                             3
+
+/*
+ * Do not format text
+ */
+#define STYLE_RAW                              4
+
+/*
+ * Generate region change on tabulator
+ */
+#define STYLE_CHANGE_REGION_ON_TAB             8
+
+
+/*
+ * How to set current margins
+ */
+
+#define MARGIN_START_STYLE                     0
+#define MARGIN_HANDLE_P_OBJECT                 1
diff --git a/Xl/XlSetup.c b/Xl/XlSetup.c
new file mode 100644 (file)
index 0000000..6846aec
--- /dev/null
@@ -0,0 +1,372 @@
+/*
+ * XlSetup.c --
+ *
+ * Author: Teemu Rantanen <tvr@cs.hut.fi>
+ * Copyright (c) 1992 Teemu Rantanen
+ *                    All rights reserved
+ *
+ * Created: Mon Mar  2 22:06:56 1992 tvr
+ * Last modified: Wed May 13 06:44:12 1992 tvr
+ *
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+
+#include <X11/Xlib.h>
+
+#include "HTAnchor.h"
+#include "HTStyle.h"
+#include "../HText/HText.h"
+
+#include "Xl.h"
+#include "XlStyle.h"
+#include "XlTypes.h"
+#include "XlFormatText.h"
+
+#include "XlConfig.h"
+
+int xl_junk_object(HTextObject_t * p);
+
+/*
+ * Find a style
+ */
+XlStyle_t *
+ xl_get_style_and_gc(p, currentgc, t)
+HTextObject_t *p;
+GC *currentgc;
+HText_t *t;
+{
+    XlStyle_t *loop = t->xl_global->XlStyles;
+
+    if (!p->style) {
+       sleep(1);
+    }
+    while (loop->fontname && strcmp(loop->styletags, p->style->SGMLTag)) {
+       loop++;
+    }
+    if (loop->fontname) {
+       if (currentgc)
+           *currentgc = t->xl_global->gcs[loop - t->xl_global->XlStyles];
+
+       return loop;
+    }
+#ifdef XL_DEBUG
+    printf("holy mony, style not found\n");
+#endif
+    return NULL;
+}
+
+
+
+/*
+ *  Setup resources for Xl (this can be changed at runtime some day)
+ */
+int XlSetupResources(func)
+void *(*func) ();
+{
+    void *table;
+    char *item;
+    XlStyle_t *styles;
+
+    char *resource;
+
+    table = (void *) (*func) ((void *) NULL, C_FONTS);
+
+    styles = XlStyles;
+
+    for (styles = XlStyles; styles->fontname; styles++) {
+       resource = (char *) (*func) (table, styles->config_name);
+
+       if (resource) {
+
+           if (styles->must_free_fontname)
+               free(styles->fontname);
+
+           styles->must_free_fontname = 1;
+
+           styles->fontname = (char *) strdup(resource);
+#ifdef XL_DEBUG
+           printf("XlConfigure: %s -> %s\n", styles->config_name, resource);
+#endif
+       }
+    }
+
+    return 0;
+}
+
+
+
+
+/*
+ *  For every page, setup Xl-stuff (including dpy, for multiple screens)
+ *  - Setup GC's
+ *  - Calculate width and height for each object
+ *  - Set page display coordinates to (0, 0)
+ *  - Delete null space-objects (only spaces on nonraw-mode)
+ *  - Something else (uh?)
+ */
+int XlSetupText(display, window, fg, bg, htext)
+Display *display;
+Window window;
+unsigned long fg;
+unsigned long bg;
+HText_t *htext;
+{
+    HTextObject_t *p;
+
+    XlStyle_t *s, *s_alloc;
+
+    HTStyle *st = NULL;
+    XlStyle_t *current;
+
+    GC currentgc;
+
+    int i;
+
+    int struct_length;
+
+    /*
+     * safe
+     */
+    if (!htext)
+       return;
+
+
+    /*
+     * Duplicate Style-structure
+     */
+
+    s = XlStyles;
+
+    while (s->fontname)
+       s++;
+
+    /*
+     * NOTE!!! Add one element because of null element at the end !!!
+     */
+    struct_length = sizeof(XlStyle_t) * ((s - XlStyles) + 1);
+
+    s_alloc = s = (XlStyle_t *) malloc(struct_length);
+
+    if (!s) {
+       printf("cannot malloc on Xl\n");
+
+       exit(1);
+    }
+    memcpy(s, XlStyles, struct_length);
+
+    /*
+     * Load fonts. Note. Fonts should be cached for every display.
+     */
+    while (s->fontname) {
+       s->fontinfo =
+           (XFontStruct *) XLoadQueryFont(display, s->fontname);
+
+       if (!s->fontinfo) {
+           printf("XlSetup: Cannot load font %s\nXlSetup: trying 'fixed'.\n",
+                  s->fontname);
+
+           s->fontinfo =
+               (XFontStruct *) XLoadQueryFont(display, "fixed");
+
+           /*
+             * Set font up on XlStyles -table so that font wont be tried
+             * every time.
+             */
+           {
+               XlStyle_t *ss = XlStyles + (s - s_alloc);
+
+               if (ss->must_free_fontname)
+                   free(ss->fontname);
+
+               ss->fontname = (char *) strdup("fixed");
+           }
+
+
+           if (!s->fontinfo) {
+
+               printf("XlSetup: Cannot load 'fixed' ... sorry.\n");
+
+               exit(1);
+           }
+       }
+       /*
+         * Next font
+         */
+       s++;
+    }
+
+    /*
+     * Allocate space for page specific Xl data
+     */
+
+    if (!htext->xl_global) {
+
+       htext->xl_global = (XlGlobalData_t *) malloc(sizeof(XlGlobalData_t));
+
+       memset(htext->xl_global, 0, sizeof(XlGlobalData_t));
+
+    }
+    htext->xl_global->dpy = display;
+
+    htext->xl_global->window = window;
+
+    htext->xl_global->XlStyles = s_alloc;
+
+    /*
+     * Set up GC:s
+     */
+    htext->xl_global->xorgc = XCreateGC(htext->xl_global->dpy,
+                                       htext->xl_global->window,
+                                       0,
+                                       NULL);
+
+    XSetFunction(htext->xl_global->dpy, htext->xl_global->xorgc, GXxor);
+
+    XSetForeground(htext->xl_global->dpy, htext->xl_global->xorgc, fg ^ bg);
+
+
+    htext->xl_global->nr_gcs = s - s_alloc;
+
+    htext->xl_global->gcs = (GC *) malloc((s - s_alloc) * sizeof(GC));
+
+    for (s = s_alloc, i = 0; s->fontname; s++, i++) {
+
+       htext->xl_global->gcs[i] =
+           XCreateGC(htext->xl_global->dpy,
+                     htext->xl_global->window, 0, NULL);
+
+       XSetForeground(htext->xl_global->dpy,
+                      htext->xl_global->gcs[i],
+                      fg);
+
+       XSetFont(htext->xl_global->dpy,
+                htext->xl_global->gcs[i],
+                s->fontinfo->fid);
+
+       s->char_width = (int) XTextWidth(s->fontinfo, "i", 1);
+    }
+
+    /*
+     * Set up graphics exposures to XCopyArea GC
+     */
+    XSetGraphicsExposures(display, htext->xl_global->gcs[0], True);
+
+    /*
+     * Loop all objects
+     */
+    p = htext->first;
+
+    while (p) {
+
+       /*
+         * Allocate space for Xl specific object part
+         */
+
+       p->xl_data = (XlObjectData_t *) malloc(sizeof(XlObjectData_t));
+
+       if (!p->xl_data) {
+           printf("cannot malloc in XlSetupText\n");
+           exit(1);
+       }
+       memset(p->xl_data, 0, sizeof(XlObjectData_t));
+
+       /*
+         * Setup Xl styles. Check Xl style only on style changes
+         */
+       if (!st || (st != p->style)) {
+
+           current = xl_get_style_and_gc(p, &currentgc, htext);
+
+           st = p->style;
+       }
+       p->xl_data->style = current;
+
+       p->xl_data->gc = currentgc;
+
+       /*
+         * Set up text dimensions. Use 'XTextExtents()'.
+         */
+       p->width = (int) XTextWidth(current->fontinfo,
+                                   (const char *) p->data,
+                                   p->length);
+
+       p->height = current->fontinfo->ascent + current->fontinfo->descent;
+
+       /*
+         * Next
+         */
+
+       /*
+         * Check if this object is 'junk'-object and delete it if needed.
+         * Has to be here, because we need styles.
+         */
+       if (xl_junk_object(p)) {
+           HTextObject_t *prev = p->prev;
+
+           /*
+             * Set links
+             */
+           if (prev) {
+
+               prev->next = p->next;
+
+           } else {
+
+               htext->first = p->next;
+
+           }
+
+           if (p->next) {
+
+               p->next->prev = prev;
+
+           } else {
+
+               htext->last = prev;
+
+           }
+
+           /*
+             * Free everything allocated
+             */
+           if (p->data)
+               free(p->data);
+
+           free(p->xl_data);
+
+           free(p);
+       }
+       p = p->next;
+
+    }
+
+    /*
+     * Cannot fail ;)
+     */
+    return 0;
+}
+
+
+
+/*
+ * If this object is not needed, it is 'junk' -object
+ */
+int xl_junk_object(p)
+HTextObject_t *p;
+{
+    register int i;
+
+    if (p->paragraph)
+       return 0;
+
+    if (xl_object_mode(p) & STYLE_RAW)
+       return 0;
+
+    for (i = 0; i < p->length; i++)
+       if (p->data[i] != ' ')
+           return 0;
+
+    return 1;
+}
diff --git a/Xl/XlStyle.c b/Xl/XlStyle.c
new file mode 100644 (file)
index 0000000..24ff490
--- /dev/null
@@ -0,0 +1,286 @@
+/*
+ * XlStyle.c --
+ *
+ * Author: Teemu Rantanen <tvr@cs.hut.fi>
+ * Copyright (c) 1992 Teemu Rantanen
+ *                    All rights reserved
+ *
+ * Created: Thu Mar  5 00:56:46 1992 tvr
+ * Last modified: Wed May 13 06:21:48 1992 tvr
+ *
+ */
+
+#include <stdio.h>
+#include <X11/Xlib.h>
+
+#include "HTAnchor.h"
+#include "HTStyle.h"
+#include "../HText/HText.h"
+
+#include "Xl.h"
+#include "XlStyle.h"
+#include "XlTypes.h"
+#include "XlFormatText.h"
+
+#include "XlDefaultFonts.h"
+
+#include "XlConfig.h"
+
+int xl_object_mode();
+
+/*
+ * All hypertext styles. Also needed configure data (font configure-name)
+ */
+
+#define CREATE_STYLE(font, cname, tag, mode, first, left, right) \
+{NULL, font, 0, cname, tag, 0, mode, first, left, right, 140, 100, 100, 50}
+
+XlStyle_t XlStyles[] =
+{
+    CREATE_STYLE(FONT_NORMAL,
+                C_FONT_NORMAL,
+                "P",
+                STYLE_LEFTIFY,
+                0, 0, 100),
+
+    CREATE_STYLE(FONT_LIST,
+                C_FONT_LIST,
+                "UL",
+                STYLE_LEFTIFY,
+                0, 5, 95),
+
+    CREATE_STYLE(FONT_LISTCOMPACT,
+                C_FONT_LISTCOMPACT,
+                "ULC",
+                STYLE_LEFTIFY,
+                0, 5, 95),
+
+    CREATE_STYLE(FONT_GLOSSARY,
+                C_FONT_GLOSSARY,
+                "DL",
+                STYLE_LEFTIFY | STYLE_CHANGE_REGION_ON_TAB,
+                0, 0, 100),
+
+    CREATE_STYLE(FONT_GLOSSARYCOMPACT,
+                C_FONT_GLOSSARYCOMPACT,
+                "DLC",
+                STYLE_LEFTIFY | STYLE_CHANGE_REGION_ON_TAB,
+                0, 0, 100),
+
+    CREATE_STYLE(FONT_EXAMPLE,
+                C_FONT_EXAMPLE,
+                "XMP",
+                STYLE_LEFTIFY | STYLE_RAW,
+                0, 0, 100),
+
+    CREATE_STYLE(FONT_LISTING,
+                C_FONT_LISTING,
+                "LISTING",
+                STYLE_LEFTIFY | STYLE_RAW,
+                0, 0, 100),
+
+    CREATE_STYLE(FONT_ADDRESS,
+                C_FONT_ADDRESS,
+                "ADDRESS",
+                STYLE_LEFTIFY,
+                0, 0, 100),
+
+    CREATE_STYLE(FONT_HEADER1,
+                C_FONT_HEADER1,
+                "H1",
+                STYLE_CENTER,
+                0, 0, 100),
+
+    CREATE_STYLE(FONT_HEADER2,
+                C_FONT_HEADER2,
+                "H2",
+                STYLE_CENTER,
+                0, 0, 100),
+
+    CREATE_STYLE(FONT_HEADER3,
+                C_FONT_HEADER3,
+                "H3",
+                STYLE_CENTER,
+                0, 0, 100),
+
+    CREATE_STYLE(FONT_HEADER4,
+                C_FONT_HEADER4,
+                "H4",
+                STYLE_CENTER,
+                0, 0, 100),
+
+    CREATE_STYLE(FONT_HEADER5,
+                C_FONT_HEADER5,
+                "H5",
+                STYLE_CENTER,
+                0, 0, 100),
+
+    CREATE_STYLE(FONT_HEADER6,
+                C_FONT_HEADER6,
+                "H6",
+                STYLE_CENTER,
+                0, 0, 100),
+
+    CREATE_STYLE(FONT_HEADER7,
+                C_FONT_HEADER7,
+                "H7",
+                STYLE_CENTER,
+                0, 0, 100),
+
+    CREATE_STYLE(NULL,
+                NULL,
+                NULL,
+                0,
+                0, 0, 0),
+};
+
+
+/*
+ * How much to increase y coordinate after this line ?
+ */
+/* ARGS_IN_USE */
+
+int xl_linespace(p_start, p_end)
+HTextObject_t *p_start;
+HTextObject_t *p_end;
+{
+    if (p_start->xl_data->style->fontinfo) {
+
+       return ((p_start->xl_data->style->fontinfo->ascent +
+                p_start->xl_data->style->fontinfo->descent) *
+               p_start->xl_data->style->space_line) / 100;
+    } else {
+
+       return p_start->xl_data->style->space_line / 100;
+    }
+}
+
+
+int xl_paragraphspace(p_start, p_end)
+HTextObject_t *p_start;
+HTextObject_t *p_end;
+{
+    if (p_start->xl_data->style->fontinfo) {
+
+       return ((p_start->xl_data->style->fontinfo->ascent +
+                p_start->xl_data->style->fontinfo->descent) *
+               p_start->xl_data->style->space_paragraph) / 100;
+    } else {
+
+       return p_start->xl_data->style->space_paragraph / 100;
+    }
+}
+
+
+int xl_stylespace(p_start, p_end)
+HTextObject_t *p_start;
+HTextObject_t *p_end;
+{
+    if (p_start->xl_data->style->fontinfo) {
+
+       return ((p_start->xl_data->style->fontinfo->ascent +
+                p_start->xl_data->style->fontinfo->descent) *
+               p_start->xl_data->style->space_style) / 100;
+
+    } else {
+
+       return 1;
+    }
+}
+
+
+int xl_stylespace_before(p_start, p_end)
+HTextObject_t *p_start;
+HTextObject_t *p_end;
+{
+    if (p_start->xl_data->style->fontinfo) {
+
+       return ((p_start->xl_data->style->fontinfo->ascent +
+                p_start->xl_data->style->fontinfo->descent) *
+               p_start->xl_data->style->space_style_before) / 100;
+    } else {
+
+       return 1;
+    }
+}
+
+
+/*
+ * How much to increase x-coordinate after this object ?
+ */
+/* ARGS_IN_USE */
+int xl_wordgap(p)
+HTextObject_t *p;
+{
+    if (xl_object_mode(p) & STYLE_RAW)
+       return 0;
+    else
+       return p->xl_data->style->char_width;
+}
+
+
+/*
+ * Return width of a character 'a'. Used to mostly when calculating
+ * tabulator spaces.
+ */
+int xl_character_width(p)
+HTextObject_t *p;
+{
+    return p->xl_data->style->char_width;
+}
+
+
+/*
+ * Return style of this object
+ */
+int xl_object_style(p)
+HTextObject_t *p;
+{
+    return p->xl_data->style->mode & STYLE_MASK;
+}
+
+
+/*
+ * Return mode of this object
+ */
+int xl_object_mode(p)
+HTextObject_t *p;
+{
+    return p->xl_data->style->mode;
+}
+
+
+/*
+ * Calculate position of a coordinate according to left and right margins
+ */
+
+int xl_calc_position(p, which, left, right)
+HTextObject_t *p;
+int which;
+int left;
+int right;
+{
+    int r = 0;
+    int delta = right - left;
+
+    XlStyle_t *s = p->xl_data->style;
+
+    if (which & I_LEFT) {
+       r += (s->left * delta) / 100;
+    }
+    if (which & I_MIDDLE_L) {
+       r += (MIDDLE_L_HACK * delta) / 100;
+    }
+    if (which & I_MIDDLE_R) {
+       r += (MIDDLE_R_HACK * delta) / 100;
+    }
+    if (which & I_RIGHT) {
+       r += (s->right * delta) / 100;
+    }
+    if (which & I_FIRST) {
+       r += (s->indent1st * delta) / 100;
+    }
+    r += left;
+
+    return r;
+}
diff --git a/Xl/XlStyle.h b/Xl/XlStyle.h
new file mode 100644 (file)
index 0000000..1af12ed
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * XlStyle.h --
+ *
+ * Author: Teemu Rantanen <tvr@cs.hut.fi>
+ * Copyright (c) 1992 Teemu Rantanen
+ *                    All rights reserved
+ *
+ * Created: Thu Mar  5 00:32:52 1992 tvr
+ * Last modified: Tue May 12 21:49:52 1992 tvr
+ *
+ */
+
+/*
+ * Flags needed for text formatting are on XlFormatText.h
+ */
+
+/*
+ * This structure contains *all* information needed to format text
+ */
+
+typedef struct XlStyle {
+    /*
+     * Font structure
+     */
+    XFontStruct *fontinfo;
+
+    /*
+     * Name of the font used to display this style. When we setup resources,
+     * identify whether we should or should not free original string.
+     */
+    char *fontname;
+    int must_free_fontname;
+
+    /*
+     * Name of the font on configure -data
+     */
+
+    char *config_name;
+
+    /*
+     * Tags. This way no enumeration is needed
+     */
+    char *styletags;
+
+    /*
+     * Width of a character 'm'.
+     */
+    int char_width;
+
+    /*
+     * Stylespecific object positioning
+     */
+    int mode;
+
+    /*
+     * How much to indent first line of a paragraph
+     */
+    int indent1st;
+
+    /*
+     * left and righ limits
+     */
+    int left;
+    int right;
+
+    /*
+     * Spaces on linespaces, stylechanges and paragraphchanges
+     */
+    int space_line;
+    int space_paragraph;
+    int space_style_before;
+    int space_style;
+
+} XlStyle_t;
+
+
+
+extern XlStyle_t XlStyles[];
+extern int xl_lineheightandgap();
+extern int xl_wordgap();
+extern int xl_object_style();
+
+
+
+#define MIDDLE_L_HACK          25
+#define MIDDLE_R_HACK          30
diff --git a/Xl/XlTypes.h b/Xl/XlTypes.h
new file mode 100644 (file)
index 0000000..9a3e771
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * XlTypes.h --
+ *
+ * Author: Teemu Rantanen <tvr@cs.hut.fi>
+ * Copyright (c) 1992 Teemu Rantanen
+ *                    All rights reserved
+ *
+ * Created: Thu Feb 27 21:50:02 1992 tvr
+ * Last modified: Tue Apr 21 00:32:43 1992 tvr
+ *
+ */
+
+/*
+ * This structure consists of all Xl specific object data
+ */
+typedef struct XlObjectData {
+    /*
+     * X11 info. This graphical context has all information about
+     * the used font. Text sizes can be calculated when font is
+     * known.
+     */
+    GC gc;
+
+    /*
+     * Pointer to XlStyle table.
+     */
+    struct XlStyle *style;
+
+} XlObjectData_t;
+
+
+/*
+ * Global data stored for a hypertext page.
+ */
+typedef struct XlGlobalData {
+    /*
+     * X11 specific data for a page
+     */
+    Display *dpy;
+    Window window;
+
+    /*
+     * Coordinates of a view window left upper corner
+     */
+    long x;
+    long y;
+
+    /*
+     * store GC:s for all fonts here
+     */
+    GC *gcs;
+
+    GC xorgc;
+
+    int nr_gcs;
+
+    /*
+     * Save styledata here
+     */
+
+    XlStyle_t *XlStyles;
+
+} XlGlobalData_t;
+
+
+
+#if 0
+
+/*
+ * No paragraph ending
+ */
+#define PTYPE_NONE     0
+
+/*
+ * Normal paragraph ending.
+ */
+#define PTYPE_NORMAL   1
+
+/*
+ * On a paragraph ending reset y value to same level where we started.
+ * store maximum y.
+ */
+#define PTYPE_CONTINUE 2
+
+/*
+ * On a paragraph ending set y value to maximum y value of stored
+ * 'PTYPE_CONTINUE' -values.
+ */
+#define PTYPE_NEXT     3
+
+
+#endif
diff --git a/Xl/XlUtil.c b/Xl/XlUtil.c
new file mode 100644 (file)
index 0000000..f513d94
--- /dev/null
@@ -0,0 +1,289 @@
+/*
+ * XlUtil.c --
+ *
+ * Author: Teemu Rantanen <tvr@cs.hut.fi>
+ * Copyright (c) 1992 Teemu Rantanen
+ *                    All rights reserved
+ *
+ * Created: Tue Mar  3 02:55:55 1992 tvr
+ * Last modified: Mon May 11 00:16:48 1992 tvr
+ *
+ */
+
+
+#include <stdio.h>
+#include <sys/types.h>
+
+#include <X11/Xlib.h>
+
+#include "HTAnchor.h"
+#include "HTStyle.h"
+#include "../HText/HText.h"
+
+#include "XlStyle.h"
+#include "XlFormatText.h"
+#include "XlTypes.h"
+
+/*
+ *  Does nothing but updates htext-object positions. This has to be
+ *  used after text is reformatted (on window size change).
+ */
+void XlSetPageCoordinates(virtualx, virtualy, htext)
+int virtualx, virtualy;
+HText_t *htext;
+{
+    htext->xl_global->x = virtualx;
+    htext->xl_global->y = virtualy;
+}
+
+
+/*
+ *  Get HTextObject position (virtual position of screen area to display)
+ */
+void XlGetCoordinates(virtualx, virtualy, htextobject)
+int *virtualx, *virtualy;
+HTextObject_t *htextobject;
+{
+    if (!htextobject)
+       return;
+
+    *virtualx = htextobject->x;
+    *virtualy = htextobject->y;
+}
+
+
+/*
+ * Can this object be cursor?
+ */
+int xl_can_be_cursor(htextobject)
+HTextObject_t *htextobject;
+{
+    int i;
+
+    if (htextobject->paragraph)
+       return FALSE;
+
+    for (i = 0; i < htextobject->length; i++)
+       if (htextobject->data[i] != ' ')
+           return TRUE;
+
+    return FALSE;
+}
+
+
+/*
+ *  Get pointer to hypertextobject nearest to chosen coordinates
+ */
+HTextObject_t *
+ XlLocateHTextObject(windowx, windowy, htext)
+int windowx, windowy;
+HText_t *htext;
+{
+    HTextObject_t *p;
+    HTextObject_t *p_closest = NULL;
+
+    int virtualx;
+    int virtualy;
+    int distance;
+
+    virtualx = windowx + htext->xl_global->x;
+    virtualy = windowy + htext->xl_global->y;
+
+    for (p = htext->first; p; p = p->next) {
+       int i = xl_object_on_region(htext, p, windowx, windowy, 0, 0);
+
+       if (xl_can_be_cursor(p)) {
+           if (!i) {
+               /*
+                * Point inside object ?
+                */
+               p_closest = p;
+               p = htext->last;
+
+           } else {
+               /*
+                * Is this object closest ?
+                */
+               if (!p_closest) {
+                   p_closest = p;
+
+                   distance = i;
+               } else if (i < distance) {
+                   distance = i;
+
+                   p_closest = p;
+               }
+           }
+       }
+    }
+
+#ifdef XL_DEBUG
+    if (p_closest) {
+       printf("XlLocateHTextObject(%d, %d) -> (%d, %d) tag %s object '%s'\n",
+              windowx, windowy,
+              p_closest->x, p_closest->y,
+              p_closest->xl_data->style->styletags,
+              p_closest ? p_closest->data : "");
+    }
+#endif
+    return p_closest;
+}
+
+/*
+ * Delete all Xl data from a page. Free all data allocated on Xl-library.
+ */
+void XlDeleteText(htext)
+HText_t *htext;
+{
+    int i;
+
+    /*
+     * Free X11 resources
+     */
+    for (i = 0; i < htext->xl_global->nr_gcs; i++) {
+       XFreeGC(htext->xl_global->dpy, htext->xl_global->gcs[i]);
+       XFreeFont(htext->xl_global->dpy,
+                 htext->xl_global->XlStyles[i].fontinfo);
+    }
+
+    XFreeGC(htext->xl_global->dpy, htext->xl_global->xorgc);
+
+    /*
+     * Free data allocated here
+     */
+
+    {
+       HTextObject_t *p;
+
+       p = htext->first;
+
+       while (p) {
+           free(p->xl_data);
+
+           p = p->next;
+       }
+    }
+
+    free(htext->xl_global->XlStyles);
+
+    free(htext->xl_global->gcs);
+
+    free(htext->xl_global);
+}
+
+
+/*
+ * What is the length of this without spaces
+ */
+int xl_nospacelength(p, data, len)
+HTextObject_t *p;
+char *data;
+int len;
+{
+    if (xl_object_mode(p) & STYLE_RAW) {
+
+       return len;
+    } else {
+
+       int i;
+
+       for (i = 0; (i < len) && (*data++ != ' '); i++);
+
+       return i;
+    }
+}
+
+
+/*
+ * Set up stuff needed to format text intelligently
+ */
+void XlFormatTextForPrinting(htext, lmargin, rmargin)
+HText_t *htext;
+int lmargin;
+int rmargin;
+{
+    HTextObject_t *p;
+    int i, struct_len;
+    XlStyle_t *loop = XlStyles;
+    int junk1;
+    int junk2;
+
+    if (!htext)
+       return;
+
+    /*
+     * Set up format info
+     */
+
+    i = 1;
+
+    while (loop->fontname) {
+
+       loop++;
+
+       i++;
+    }
+
+    struct_len = sizeof(XlStyle_t) * i;
+
+    loop = (XlStyle_t *) malloc(struct_len);
+
+    htext->xl_global = (XlGlobalData_t *) malloc(sizeof(XlGlobalData_t));
+
+    htext->xl_global->XlStyles = loop;
+
+    memcpy(loop, XlStyles, struct_len);
+
+    while (--i) {
+
+       loop->char_width = 1;
+
+       loop++;
+    }
+
+    /*
+     * Set up length and width
+     */
+    p = htext->first;
+
+    while (p) {
+       HTStyle *st = NULL;
+
+       XlStyle_t *current;
+
+       p->height = 1;
+
+       if (!st || (st != p->style)) {
+
+           current = (XlStyle_t *) xl_get_style_and_gc(p, NULL, htext);
+
+           st = p->style;
+       }
+       p->xl_data = (XlObjectData_t *) malloc(sizeof(XlObjectData_t));
+
+       p->xl_data->style = current;
+
+       p->width = xl_nospacelength(p, p->data, p->length);
+
+       p = p->next;
+    }
+
+    XlFormatText(lmargin, rmargin - lmargin, 0, &junk1, &junk2, htext);
+
+    /*
+     * Free local stuff
+     */
+
+    p = htext->first;
+
+    while (p) {
+
+       free(p->xl_data);
+
+       p = p->next;
+    }
+
+    free(loop);
+
+    free(htext->xl_global);
+}
diff --git a/Xl/XlWindow.c b/Xl/XlWindow.c
new file mode 100644 (file)
index 0000000..d194dc0
--- /dev/null
@@ -0,0 +1,358 @@
+/*
+ * XlWindow.c --
+ *
+ * Author: Teemu Rantanen <tvr@cs.hut.fi>
+ * Copyright (c) 1992 Teemu Rantanen
+ *                    All rights reserved
+ *
+ * Created: Tue Mar  3 02:59:10 1992 tvr
+ * Last modified: Tue Apr 21 00:34:09 1992 tvr
+ *
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+
+#include <X11/Xlib.h>
+
+#include "HTAnchor.h"
+#include "HTStyle.h"
+#include "../HText/HText.h"
+
+#include "Xl.h"
+#include "XlStyle.h"
+#include "XlTypes.h"
+#include "XlFormatText.h"
+
+/*
+ * Make cursor positioning more intelligent
+ */
+#define Y_MULTIPLIER 50
+
+/*
+ * Is there spaces at the end of data ?
+ */
+int xl_space_index(data, length)
+char *data;
+int length;
+{
+    int i;
+
+    if (!data)
+       return -1;
+
+    for (i = 0; i < length; i++)
+       if (*data++ == ' ')
+           return i;
+
+    return length;
+}
+
+
+/*
+ * Draw one Xl object to screen
+ */
+void xl_draw_object(htext, object)
+HText_t *htext;
+HTextObject_t *object;
+{
+    /*
+     * If this object is cursor, clear area or else partial updating
+     * does not work correctly
+     */
+
+    if (object == htext->cursor) {
+       XClearArea(htext->xl_global->dpy,
+                  htext->xl_global->window,
+                  object->x - htext->xl_global->x,
+                  object->y - htext->xl_global->y,
+                  object->width,
+                  object->height,
+                  False);
+    }
+    XDrawString(htext->xl_global->dpy,
+               htext->xl_global->window,
+               object->xl_data->gc,
+               object->x - htext->xl_global->x,
+               object->y - htext->xl_global->y +
+               object->xl_data->style->fontinfo->ascent,
+               object->data,
+               object->length);
+
+    /*
+     * Draw underline for anchors
+     */
+    if (object->anchor) {
+       int y;
+       int x;
+       int width;
+
+       y = object->y + object->xl_data->style->fontinfo->ascent +
+           object->xl_data->style->fontinfo->descent -
+           htext->xl_global->y;
+
+       x = object->x - htext->xl_global->x;
+
+       width = object->width;
+
+       if (object->next && (object->anchor == object->next->anchor) &&
+           (object->y == object->next->y)) {
+           width += xl_wordgap(object);
+       }
+       XDrawLine(htext->xl_global->dpy,
+                 htext->xl_global->window,
+                 object->xl_data->gc,
+                 x, y,
+                 x + width, y);
+    }
+    /*
+     * Is this object cursor ?
+     */
+    if (object == htext->cursor) {
+       int cursorwidth;
+
+       /*
+         * If cursor is on raw mode, get rid of spaces at the end
+         */
+       if (xl_object_mode(object) & STYLE_RAW) {
+           int i = xl_space_index(object->data, object->length);
+
+           if (i >= 0) {
+               cursorwidth = (int) XTextWidth(object->xl_data->style->fontinfo,
+                                              object->data,
+                                              i);
+           } else {
+               cursorwidth = object->width;
+           }
+       } else {
+           cursorwidth = object->width;
+       }
+
+       XDrawRectangle(htext->xl_global->dpy,
+                      htext->xl_global->window,
+                      htext->xl_global->xorgc,
+                      object->x - htext->xl_global->x,
+                      object->y - htext->xl_global->y,
+                      cursorwidth - 1,
+                      object->height - 1);
+    }
+}
+
+
+/*
+ * Check is object is on wanted region. Return 0 if point is on region.
+ * Otherwise return distance. NOTE. y-distance is multiplied by a big
+ * number because this way cursor positioning works more intelligently than
+ * without it.
+ */
+int xl_object_on_region(htext, object, x, y, w, h)
+HText_t *htext;
+HTextObject_t *object;
+int x, y;
+int w, h;
+{
+    int r = 0;
+
+    /*
+     * Change real coordinates to virtual coordinates
+     */
+    x += htext->xl_global->x;
+    y += htext->xl_global->y;
+
+    if ((object->y + object->height) < y)
+       r += (y - (object->y + object->height)) * Y_MULTIPLIER;
+
+    if (object->y > (y + h))
+       r += (object->y - (y + h)) * Y_MULTIPLIER;
+
+    if ((object->x + object->width) < x)
+       r += x - (object->x + object->width);
+
+    if (object->x > (x + w))
+       r += object->x - (x + w);
+
+    return r;
+}
+
+
+
+/*
+ *  Redraw region of the window. Draw all objects (or parts of the objects)
+ *  on redraw region.
+ */
+void XlRedraw(windowx, windowy, width, height, htext)
+int windowx, windowy;
+int width, height;
+HText_t *htext;
+{
+    HTextObject_t *p;
+
+    /*
+     * This is stupid. This has to be written again
+     */
+
+    p = htext->first;
+
+    while (p) {
+       if (xl_object_on_region(htext, p, windowx, windowy, width, height) == 0) {
+           xl_draw_object(htext, p);
+       }
+       p = p->next;
+    }
+}
+
+
+/*
+ *  Move window to other coordinates. Xl can optimize window moving by using
+ *  regioncopy and updating only parts of display.
+ */
+void XlMoveWindow(newvx, newvy, htext)
+int newvx, newvy;
+HText_t *htext;
+{
+    XWindowAttributes a;
+
+    long deltax, deltay;
+
+    /*
+     * Need to know window dimensions
+     */
+    XGetWindowAttributes(htext->xl_global->dpy,
+                        htext->xl_global->window,
+                        &a);
+
+    /*
+     * How much to move
+     */
+    deltax = newvx - htext->xl_global->x;
+    deltay = newvy - htext->xl_global->y;
+
+    /*
+     * Can move be optimized ?
+     */
+    if ((abs(deltax) < a.width) && (abs(deltay) < a.height)) {
+       XCopyArea(htext->xl_global->dpy,
+                 htext->xl_global->window,
+                 htext->xl_global->window,
+                 htext->xl_global->gcs[0],     /* dummy GC */
+                 deltax < 0 ? 0 : deltax,
+                 deltay < 0 ? 0 : deltay,
+                 a.width - abs(deltax),
+                 a.height - abs(deltay),
+                 deltax < 0 ? -deltax : 0,
+                 deltay < 0 ? -deltay : 0);
+    }
+    /*
+     * Set new corner coordinates
+     */
+
+    XlSetPageCoordinates(newvx, newvy, htext);
+
+    /*
+     * Clear borders to be updated again
+     */
+    if (deltax != 0) {
+       XClearArea(htext->xl_global->dpy,
+                  htext->xl_global->window,
+                  deltax > 0 ? a.width - deltax : 0,
+                  0,
+                  abs(deltax),
+                  a.height,
+                  True);
+    }
+    if (deltay != 0) {
+       XClearArea(htext->xl_global->dpy,
+                  htext->xl_global->window,
+                  0,
+                  deltay > 0 ? a.height - deltay : 0,
+                  a.width,
+                  abs(deltay),
+                  True);
+    }
+}
+
+
+
+/*
+ * Clear window
+ */
+void XlClearWindow(width, height, htext)
+int width;
+int height;
+HText_t *htext;
+{
+    XClearArea(htext->xl_global->dpy,
+              htext->xl_global->window,
+              0, 0, width, height, True);
+}
+
+
+/*
+ * Setup cursorposition on a page
+ */
+void XlSetCursor(htext, object)
+HText_t *htext;
+HTextObject_t *object;
+{
+    XWindowAttributes a;
+    HTextObject_t *old_object;
+
+
+    if (!htext || !htext->xl_global ||
+       !htext->xl_global->dpy ||
+       !htext->xl_global->window)
+       return;
+
+    /*
+     * Need to know window dimensions
+     */
+    XGetWindowAttributes(htext->xl_global->dpy,
+                        htext->xl_global->window,
+                        &a);
+
+    /*
+     * Clear old cursor
+     */
+    if (htext->cursor) {
+       if (xl_object_on_region(htext, htext->cursor, 0, 0,
+                               a.width, a.height) == 0) {
+           XClearArea(htext->xl_global->dpy,
+                      htext->xl_global->window,
+                      htext->cursor->x - htext->xl_global->x,
+                      htext->cursor->y - htext->xl_global->y,
+                      htext->cursor->width,
+                      htext->cursor->height,
+                      False);
+
+           /*
+             * When drawing old area, must clear htext->cursor for a while
+             */
+           old_object = htext->cursor;
+
+           htext->cursor = 0;
+
+           xl_draw_object(htext, old_object);
+       }
+    }
+    old_object = object;
+    htext->cursor = object;
+
+    if (htext->cursor) {
+       if (xl_object_on_region(htext, object, 0, 0, a.width, a.height) == 0) {
+#if 0
+           /*
+             * This is moved to draw object. partial drawing updating of
+             * cursor causes otherwise problems
+             */
+           XClearArea(htext->xl_global->dpy,
+                      htext->xl_global->window,
+                      htext->cursor->x - htext->xl_global->x,
+                      htext->cursor->y - htext->xl_global->y,
+                      htext->cursor->width,
+                      htext->cursor->height,
+                      False);
+#endif
+           xl_draw_object(htext, htext->cursor);
+       }
+    }
+}
diff --git a/erwise/Config.c b/erwise/Config.c
new file mode 100644 (file)
index 0000000..5bd81a2
--- /dev/null
@@ -0,0 +1,591 @@
+#include "Includes.h"
+
+#define BUFFER_SIZE 79
+#ifndef TRUE
+#define TRUE  1
+#define FALSE 0
+#endif
+
+#define INDENT_STR  "    "
+
+static char *strdupmax(char *str, int length);
+static char *parseid(char *str);
+static char *parsevalue(char *str);
+static char *readline(FILE * fp);
+
+static int ConfigLines = 0;
+
+
+static Config_t Fonts[] =
+{
+    {RESOURCE, C_FONT_NORMAL, (void *) "-adobe-times-medium-r-normal--12-120-75-75-p-64-iso8859-1"},
+    {RESOURCE, C_FONT_LIST, (void *) "8x13"},
+    {RESOURCE, C_FONT_LISTCOMPACT, (void *) "6x13"},
+    {RESOURCE, C_FONT_GLOSSARY, (void *) "-adobe-times-medium-r-normal--12-120-75-75-p-64-iso8859-1"},
+    {RESOURCE, C_FONT_GLOSSARYCOMPACT, (void *) "-adobe-times-medium-r-normal--12-120-75-75-p-64-iso8859-1"},
+    {RESOURCE, C_FONT_EXAMPLE, (void *) "7x13"},
+    {RESOURCE, C_FONT_LISTING, (void *) "7x13"},
+    {RESOURCE, C_FONT_ADDRESS, (void *) "8x13"},
+    {RESOURCE, C_FONT_HEADER1, (void *) "-adobe-times-medium-r-normal--20-140-100-100-p-96-iso8859-1"},
+    {RESOURCE, C_FONT_HEADER2, (void *) "-adobe-times-medium-r-normal--18-180-75-75-p-94-iso8859-1"},
+    {RESOURCE, C_FONT_HEADER3, (void *) "-adobe-times-medium-r-normal--17-120-100-100-p-84-iso8859-1"},
+    {RESOURCE, C_FONT_HEADER4, (void *) "-adobe-times-medium-r-normal--14-100-100-100-p-74-iso8859-1"},
+    {RESOURCE, C_FONT_HEADER5, (void *) "-adobe-times-medium-r-normal--14-100-100-100-p-74-iso8859-1"},
+    {RESOURCE, C_FONT_HEADER6, (void *) "-adobe-times-medium-r-normal--14-100-100-100-p-74-iso8859-1"},
+    {RESOURCE, C_FONT_HEADER7, (void *) "-adobe-times-medium-r-normal--14-100-100-100-p-74-iso8859-1"},
+    {EOC, (char *) NULL, (void *) NULL}
+};
+
+
+static Config_t GlobalSettings[] =
+{
+    {RESOURCE, C_TOPMARGIN, (void *) "0"},
+    {RESOURCE, C_BOTTOMMARGIN, (void *) "0"},
+    {RESOURCE, C_LEFTMARGIN, (void *) "0"},
+    {RESOURCE, C_RIGHTMARGIN, (void *) "0"},
+    {RESOURCE, C_FIXEDWIDTHMODE, (void *) "Off"},
+    {RESOURCE, C_FIXEDWIDTH, (void *) "560"},
+    {RESOURCE, C_ONEPAGEMODE, (void *) "Off"},
+    {RESOURCE, C_WIDTH, (void *) "560"},
+    {RESOURCE, C_HEIGHT, (void *) "600"},
+    {RESOURCE, C_DOUBLECLICKTIME, (void *) "500"},
+    {RESOURCE, C_SEARCH, (void *) "Fixed"},
+    {RESOURCE, C_CONTROLPANEL, (void *) "Fixed"},
+    {RESOURCE, C_LIST, (void *) "Fixed"},
+    {RESOURCE, C_RECALL, (void *) "Fixed"},
+    {RESOURCE, C_PAGESETTINGS, (void *) "Fixed"},
+    {EOC, (char *) NULL, (void *) NULL}
+};
+
+
+static Config_t Print[] =
+{
+    {RESOURCE, C_COMMAND, (void *) "lpr"},
+    {RESOURCE, C_FILENAME, (void *) "print.out"},
+    {RESOURCE, C_PRINTTOFILE, (void *) "False"},
+    {RESOURCE, C_TOPMARGIN, (void *) "0"},
+    {RESOURCE, C_BOTTOMMARGIN, (void *) "0"},
+    {RESOURCE, C_LEFTMARGIN, (void *) "0"},
+    {RESOURCE, C_RIGHTMARGIN, (void *) "0"},
+    {RESOURCE, C_WIDTH, (void *) "80"},
+    {EOC, (char *) NULL, (void *) NULL}
+};
+
+
+static Config_t Defaults[] =
+{
+    {DYNAMIC_PTR, C_DEFAULTSTABLE, (void *) NULL},
+    {EOC, (char *) NULL, (void *) NULL}
+};
+
+
+static Config_t KeyBindings[] =
+{
+    {RESOURCE, C_GETPAGE, (void *) "Return"},
+    {RESOURCE, C_PREVWORD, (void *) "Left"},
+    {RESOURCE, C_NEXTWORD, (void *) "Right"},
+    {RESOURCE, C_PREVTAG, (void *) "Up"},
+    {RESOURCE, C_NEXTTAG, (void *) "Down"},
+    {RESOURCE, C_CLOSE, (void *) "^c"},
+    {RESOURCE, C_SEARCH, (void *) "^s"},
+    {RESOURCE, C_SETTINGS, (void *) "S"},
+    {RESOURCE, C_PRINTDOC, (void *) "p"},
+    {RESOURCE, C_LIST, (void *) "L"},
+    {EOC, (char *) NULL, (void *) NULL}
+};
+
+
+Config_t Config[] =
+{
+    {COMMENT, C_COMMENT, (void *) "Erwise configuration file"},
+    {BLOCK, C_FONTS, (void *) &Fonts},
+    {BLOCK, C_KEYBINDINGS, (void *) &KeyBindings},
+    {BLOCK, C_PRINT, (void *) &Print},
+    {BLOCK, C_GLOBALSETTINGS, (void *) &GlobalSettings},
+    {DYNAMIC, C_DEFAULTS, (void *) &Defaults},
+    {EOC, (char *) NULL, (void *) NULL}
+};
+
+
+/*
+ * misc routines
+ */
+static char *
+ strdupmax(str, length)
+char *str;
+int length;
+{
+    char *dup = (char *) NULL;
+
+    if (str) {
+       dup = (char *) malloc((length + 1) * sizeof(char));
+       strncpy(dup, str, length);
+       dup[length] = '\0';
+    }
+    return dup;
+}
+
+
+static char *
+ stripnewline(str)
+char *str;
+{
+    int length;
+
+    if (str) {
+       length = strlen(str);
+       if (length && (str[length - 1] == '\n'))
+           str[length - 1] = '\0';
+    }
+    return str;
+}
+
+
+/*
+ * config's code starts here
+ */
+static char *
+ readline(fp)
+FILE *fp;
+{
+    char buffer[BUFFER_SIZE + 1];
+    char *line = (char *) NULL;
+    char *data;
+    int length = 1;
+
+    line = (char *) malloc(sizeof(char));
+    line[0] = '\0';
+
+    while (!feof(fp) && !strrchr(line, '\n')) {
+       if (data = fgets(buffer, BUFFER_SIZE, fp)) {
+           line =
+               (char *) realloc(line, (strlen(data) + length) * sizeof(char));
+           strcat(line, data);
+           length = strlen(line) + 1;
+       }
+    }
+#ifdef DEBUG_CONFIG
+    printf("read line: '%s'\n", line);
+#endif
+    ConfigLines++;
+    return line;
+}
+
+
+/*
+ * returns a copy of id
+ */
+static char *
+ parseid(str)
+char *str;
+{
+    char *ptr, *id = (char *) NULL;
+    int length = 0;
+
+    while (str && *str && isspace(*str))
+       str++;
+    ptr = str;
+    while (str && *str && !isspace(str[length]))
+       length++;
+    id = strdupmax(ptr, length);
+#ifdef DEBUG_CONFIG
+    printf("id: '%s'\n", id);
+#endif
+    return id;
+}
+
+
+/*
+ * returns a copy of value
+ */
+static char *
+ parsevalue(str)
+char *str;
+{
+    char *ptr;
+    char *value = (char *) NULL;
+
+    if (ptr = strchr(str, '=')) {
+       ptr++;
+       while (ptr && *ptr && isspace(*ptr))
+           ptr++;
+       value = stripnewline(strdup(ptr));
+    }
+    return value;
+}
+
+
+static Config_t *
+ getitem(id, table)
+char *id;
+Config_t *table;
+{
+    Config_t *walker;
+
+    walker = table;
+    while (walker && (walker->type != EOC)) {
+       if (!strcmp(id, walker->id))
+           return (walker);
+       walker++;
+    }
+    return ((Config_t *) NULL);
+}
+
+
+ConfigType_t
+getidtype(id, table)
+char *id;
+Config_t *table;
+{
+    Config_t *walker;
+
+    if (!strncmp(id, "{", 1))
+       return (START_OF_BLOCK);
+    if (!strncmp(id, "}", 1))
+       return (END_OF_BLOCK);
+    if (!strncmp(id, "", 1))
+       return (EMPTY);
+    if (!strncmp(id, "#", 1))
+       return (COMMENT);
+
+    if (walker = getitem(id, table))
+       return (walker->type);
+    return (UNKNOWN);
+}
+
+
+static char *
+ parsedynamicobject(line)
+char *line;
+{
+    char *ptr;
+
+    ptr = line;
+    while (ptr && *ptr && isspace(*ptr))
+       ptr++;
+    return (stripnewline(strdup(ptr)));
+}
+
+
+static int restoredynamicblock(fp, table)
+FILE *fp;
+Config_t *table;
+{
+    char *line;
+    char *id;
+    int done = FALSE;
+    char **items = (char **) NULL;
+    int count = 0;
+
+    do {
+       line = readline(fp);
+       if (line[0] == '\0')
+           done = TRUE;
+       else {
+           id = parseid(line);
+           switch (getidtype(id, table)) {
+           case END_OF_BLOCK:
+               done = TRUE;
+           case START_OF_BLOCK:
+               break;
+           default:
+               if (!count) {
+                   count = 1;
+                   items = (char **) malloc(2 * sizeof(char *));
+               } else {
+                   count++;
+                   items =
+                       (char **) realloc(items, (count + 1) * sizeof(char *));
+               }
+               items[count - 1] = parsedynamicobject(line);
+               items[count] = (char *) NULL;
+#ifdef DEBUG_CONFIG
+               printf("added to count[%d] value '%s'\n",
+                      count - 1, items[count - 1]);
+#endif
+               break;
+           }
+           free(id);
+       }
+       free(line);
+    } while (!done);
+    table->value = (void *) items;
+    return 0;
+}
+
+
+static void *
+ setitemvalue(item, value)
+Config_t *item;
+void *value;
+{
+    void *oldvalue = (void *) NULL;
+
+    switch (item->type) {
+    case DYNAMIC_PTR:
+       oldvalue = item->value;
+       item->value = value;
+       break;
+    case RESOURCE:
+       if (item->value)
+           free(item->value);
+       item->value = value;
+       break;
+    default:
+       /* error recovery - not needed? */
+       fprintf(stderr, "unknown type for given item\n");
+    }
+    return oldvalue;
+}
+
+
+static int restoreblock(fp, table)
+FILE *fp;
+Config_t *table;
+{
+    char *id, *value;
+    char *line;
+    int done = FALSE;
+    int ret;
+    Config_t *item;
+    int blockcount = 0;
+    int unknown = FALSE;
+    char *syncline;
+    int syncdone;
+
+#ifdef DEBUG_CONFIG
+    printf("parsing block\n");
+#endif
+    while (!feof(fp) && !done) {
+       line = readline(fp);
+       if (line[0] == '\0') {
+           id = (char *) NULL;
+       } else {
+           id = parseid(line);
+           item = getitem(id, table);
+           switch (getidtype(id, table)) {
+           case RESOURCE:
+               value = parsevalue(line);
+               /* we don't care about this return value... */
+               value = setitemvalue(item, (void *) strdup(value));
+               unknown = FALSE;
+               break;
+           case BLOCK:
+#ifdef DEBUG_CONFIG
+               printf("block: '%s'\n", id);
+#endif
+               ret = restoreblock(fp, (Config_t *) item->value);
+               unknown = FALSE;
+               break;
+           case START_OF_BLOCK:
+               if (!unknown)
+                   blockcount++;
+               else {
+#ifdef DEBUG_CONFIG
+                   printf("syncing\n");
+#endif
+                   syncdone = FALSE;
+                   while (!syncdone && !feof(fp) && (syncline = readline(fp))) {
+                       if (strchr(syncline, '}'))
+                           syncdone = TRUE;
+                       free(syncline);
+                   }
+               }
+               unknown = FALSE;
+               break;
+           case END_OF_BLOCK:
+               blockcount--;
+               if (blockcount == 0)
+                   done = TRUE;
+               else
+                   fprintf(stderr, "parse error at line %d\n", ConfigLines);
+               unknown = FALSE;
+               break;
+           case DYNAMIC:
+#ifdef DEBUG_CONFIG
+               printf("dynamic: '%s'\n", id);
+#endif
+               ret = restoredynamicblock(fp, (Config_t *) item->value);
+               unknown = FALSE;
+               break;
+           case UNKNOWN:
+               fprintf(stderr, "Unknown tag type '%s'\n", id);
+               unknown = TRUE;
+               break;
+           case EMPTY:
+           case COMMENT:
+           default:
+               unknown = FALSE;
+               break;
+           }
+       }
+       free(line);
+    }
+    if (blockcount) {
+       if (blockcount < 0)
+           fprintf(stderr, "missing { at %d\n", ConfigLines);
+       if (blockcount > 0)
+           fprintf(stderr, "missing } at %d\n", ConfigLines);
+    }
+#ifdef DEBUG_CONFIG
+    printf("end of block\n");
+#endif
+}
+
+
+int ConfigRestore(fp)
+FILE *fp;
+{
+    ConfigLines = 0;
+    restoreblock(fp, Config);
+}
+
+
+static void indent(fp, depth)
+FILE *fp;
+int depth;
+{
+    while (depth-- > 0)
+       fprintf(fp, INDENT_STR);
+}
+
+
+int saveblock(fp, table, depth)
+FILE *fp;
+Config_t *table;
+int depth;
+{
+    Config_t *walker;
+    char **dynamic_object;
+    int ret;
+
+    walker = table;
+    while (walker && (walker->type != EOC)) {
+       switch (walker->type) {
+       case COMMENT:
+           fprintf(fp, "# %s\n", (char *) walker->value);
+           break;
+       case RESOURCE:
+           indent(fp, depth);
+           fprintf(fp, "%s = %s\n", walker->id, (char *) walker->value);
+           break;
+       case DYNAMIC_PTR:
+           if (dynamic_object = (char **) walker->value)
+               while (*dynamic_object) {
+                   indent(fp, depth);
+                   fprintf(fp, "%s\n", (char *) *dynamic_object);
+                   dynamic_object++;
+               }
+           break;
+       case BLOCK:
+       case DYNAMIC:
+           fprintf(fp, "\n");
+           indent(fp, depth);
+           fprintf(fp, "%s\n", walker->id);
+           indent(fp, depth);
+           fprintf(fp, "{\n");
+           if (walker->type == BLOCK)
+               ret = saveblock(fp, (Config_t *) walker->value, depth + 1);
+           else
+               ret = saveblock(fp, (Config_t *) walker->value, depth + 1);
+           indent(fp, depth);
+           fprintf(fp, "}\n");
+           break;
+           /*
+             * case DYNAMIC: indent(fp, depth - 1); fprintf(fp, "%s\n",
+             * walker->id); indent(fp, depth - 1); fprintf(fp, "{\n"); ret =
+             * saveblock(fp, (Config_t *)walker->value, depth + 1);
+             * indent(fp, depth - 1); fprintf(fp, "}\n"); break;
+             */
+       default:
+           fprintf(stderr, "unknown type for '%s'\n", walker->id);
+       }
+       walker++;
+    }
+}
+
+
+int ConfigSave(fp)
+FILE *fp;
+{
+    saveblock(fp, Config, 0);
+    fflush(fp);
+}
+
+
+static void configinitloop(table)
+Config_t *table;
+{
+    Config_t *walker;
+
+    walker = table;
+    while (walker && (walker->type != EOC)) {
+       switch (walker->type) {
+       case RESOURCE:
+           walker->value = (void *) strdup((char *) walker->value);
+#ifdef DEBUG_CONFIG
+           printf("init: '%s': '%s'\n", walker->id, (void *) walker->value);
+#endif
+           break;
+       case BLOCK:
+#ifdef DEBUG_CONFIG
+           printf("init: table = %s\n", walker->id);
+#endif
+           configinitloop((Config_t *) walker->value);
+           break;
+       }
+       walker++;
+    }
+}
+
+
+void ConfigInit(void)
+{
+    configinitloop(Config);
+}
+
+
+void *
+ ConfigGetValue(tableptr, id)
+void *tableptr;
+char *id;
+{
+    Config_t *table = (Config_t *) tableptr;
+    Config_t *item;
+
+    if (!table)
+       table = Config;
+    if (item = getitem(id, table))
+       return (item->value);
+    return ((void *) NULL);
+}
+
+
+void *
+ ConfigSetValue(tableptr, id, value)
+void *tableptr;
+char *id;
+void *value;
+{
+    Config_t *table = (Config_t *) tableptr;
+    void *ret = (void *) NULL;
+    Config_t *item;
+
+    if (!table)
+       table = Config;
+    if (item = getitem(id, table))
+       switch (item->type) {
+       case RESOURCE:
+           if (item->value)
+               free(item->value);
+           item->value = value;
+           break;
+       case DYNAMIC_PTR:
+           ret = item->value;
+           item->value = value;
+           break;
+       default:
+           ;
+       }
+    return ret;
+}
diff --git a/erwise/Defs.h b/erwise/Defs.h
new file mode 100644 (file)
index 0000000..6f34278
--- /dev/null
@@ -0,0 +1,76 @@
+/* $Id: Defs.h,v 1.1 1992/05/18 21:43:03 tvr Exp tvr $ */
+
+
+#define ERWISERC ".erwiserc"
+
+#define HELP_DIR "file:/p/lib/erwise/help/"
+#define HELP_TOPLEVEL "file:/p/lib/erwise/help/help1.html"
+
+#define AUTOGET    0
+#define NO_AUTOGET 1
+
+#define POLLING   1
+#define SELECTING 2
+
+/*
+ * #define C_FONT_NORMAL          "normal" #define C_FONT_LIST "list" #define
+ * C_FONT_LISTCOMPACT     "listcompact" #define C_FONT_GLOSSARY
+ * "glossary" #define C_FONT_GLOSSARYCOMPACT "glossarycompact" #define
+ * C_FONT_EXAMPLE         "example" #define C_FONT_LISTING         "listing"
+ * #define C_FONT_ADDRESS         "address" #define C_FONT_HEADER1
+ * "header1" #define C_FONT_HEADER2 "header2" #define C_FONT_HEADER3
+ * "header3" #define C_FONT_HEADER4 "header4" #define C_FONT_HEADER5
+ * "header5" #define C_FONT_HEADER6 "header6" #define C_FONT_HEADER7
+ * "header7"
+ */
+
+#define C_COMMAND        "command"
+#define C_FILENAME       "filename"
+#define C_PRINTTOFILE    "printtofile"
+
+/*
+ * #define C_TOPMARGIN      "topmargin" #define C_BOTTOMMARGIN "bottommargin"
+ * #define C_LEFTMARGIN     "leftmargin" #define C_RIGHTMARGIN "rightmargin"
+ * #define C_WIDTH          "width" #define C_HEIGHT "height" #define
+ * C_ONEPAGEMODE     "onepagemode" #define C_FIXEDWIDTHMODE "fixedwidthmode"
+ * #define C_FIXEDWIDTH      "fixedwidth" #define C_DOUBLECLICKTIME
+ * "doubleclicktime"
+ */
+
+/*
+ * #define C_SEARCH          "search" #define C_CONTROLPANEL "controlpanel"
+ * #define C_LIST            "list" #define C_RECALL "recall" #define
+ * C_PAGESETTINGS    "pagesettings"
+ */
+
+
+/* #define C_DEFAULTSTABLE   "defaultstable" */
+#define C_COMMENT         "comment"
+
+/* #define C_FONTS           "Fonts" */
+#define C_PRINT           "Print"
+#define C_WINDOWPLACEMENT "WindowPlacement"
+#define C_KEYBINDINGS     "KeyBindings"
+#define C_PRINT           "Print"
+/* #define C_GLOBALSETTINGS  "GlobalSettings" */
+#define C_PAGE            "Page"
+/* #define C_DEFAULTS        "Defaults" */
+
+#define C_GETPAGE   "getpage"
+#define C_PREVWORD  "prevword"
+#define C_NEXTWORD  "nextword"
+#define C_PREVTAG   "prevtag"
+#define C_NEXTTAG   "nexttag"
+#define C_CLOSE     "close"
+#define C_SEARCH    "search"
+#define C_SETTINGS  "settings"
+#define C_PRINTDOC  "printdoc"
+#define C_LIST      "list"
+
+
+#define STR_FALSE "false"
+#define STR_TRUE  "true"
+#define STR_OFF   "off"
+#define STR_ON    "on"
+#define STR_YES   "yes"
+#define STR_NO    "no"
diff --git a/erwise/Help.c b/erwise/Help.c
new file mode 100644 (file)
index 0000000..105fee3
--- /dev/null
@@ -0,0 +1,85 @@
+static char *rcsid = "$Id: Help.c,v 1.1 1992/05/18 21:43:03 tvr Exp tvr $";
+
+#include "Includes.h"
+
+static struct anchorstr_st {
+    char *action, *address;
+} anchortable[] =
+
+{
+    "PageInput", "browserwin.html#browserwindow",
+    "Search", "browserwin.html#search",
+    "Copy", "browserwin.html#copy",
+    "List", "browserwin.html#list",
+    "Print", "browserwin.html#print",
+    "Settings", "browserwin.html#settings",
+    "Close", "browserwin.html#close",
+    "Top", "browserwin.html#top",
+    "Bottom", "browserwin.html#bottom",
+    "Prev tag", "browserwin.html#prevtag",
+    "Next tag", "browserwin.html#nexttag",
+    "Home", "browserwin.html#home",
+    "Recall", "browserwin.html#recall",
+    "Back", "browserwin.html#back",
+    "Prev page", "browserwin.html#prevpage",
+    "Next page", "browserwin.html#nextpage",
+    "Close hierarchy", "browserwin.html#close_hierarchy",
+    "Controlpanel", "browserwin.html#controlpanel",
+    "Defaults", "browserwin.html#defaults",
+    "On action", "browserwin.html#on_action",
+    "Help", "browserwin.html#manual",
+    NULL, NULL
+};
+
+static void helponactioncb(char *actionstring);
+
+
+void HelpOnFunctionCB(topaddress, htext, htextobject, parameter)
+char *topaddress;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    UiGetNextAction(helponactioncb);
+}
+
+
+void HelpManualCB(topaddress, htext, htextobject, parameter)
+char *topaddress;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    if (!FindPage(Pages, HELP_TOPLEVEL))
+       AddPage(&Pages, HELP_TOPLEVEL, (HText_t *) NULL, (Page_t *) NULL);
+
+    StartLoading(HELP_TOPLEVEL, HELP_TOPLEVEL, HELP_TOPLEVEL);
+}
+
+
+static void helponactioncb(actionstring)
+char *actionstring;
+{
+    int i;
+    char *addressstring;
+    Page_t *toppage;
+
+    if (!FindPage(Pages, HELP_TOPLEVEL)) {
+       toppage = AddPage(&Pages, HELP_TOPLEVEL, (HText_t *) NULL,
+                         (Page_t *) NULL);
+       AddPage(&toppage->Children, HELP_TOPLEVEL, (HText_t *) NULL,
+               toppage);
+    }
+    for (i = 0; anchortable[i].action; i++) {
+       if (!strcmp(anchortable[i].action, actionstring)) {
+           addressstring = (char *) malloc(strlen(HELP_DIR) +
+                                        strlen(anchortable[i].address) +
+                                           1);
+           sprintf(addressstring, "%s%s",
+                   HELP_DIR, anchortable[i].address);
+           StartLoading(addressstring, HELP_TOPLEVEL, HELP_TOPLEVEL);
+
+           return;
+       }
+    }
+}
diff --git a/erwise/Imakefile b/erwise/Imakefile
new file mode 100644 (file)
index 0000000..e2a5dd0
--- /dev/null
@@ -0,0 +1,28 @@
+#
+#
+#
+
+          OBJS = main.o Setup.o TopLevel.o Page.o Misc.o Help.o        \
+                 Print.o Config.o
+          SRCS = main.c Setup.c TopLevel.c Page.c Misc.c Help.c        \
+                 Print.c Config.c
+
+         XLDIR = ../Xl
+         HTDIR = ../HText
+         CLDIR = ../Cl
+        WWWDIR = $(CLDIR)/WWWLibrary
+         UIDIR = ../Ui
+
+     MOTIF_HDRS = -I/p/motif/include
+    ERWISE_HDRS = -I$(XLDIR) -I$(HTDIR) -I$(CLDIR) -I$(WWWDIR) -I$(UIDIR)
+       DEFINES = $(ERWISE_HDRS) $(MOTIF_HDRS)
+
+LOCAL_LIBRARIES = -L$(WWWDIR) -lWWW    \
+                 -L$(UIDIR) -lUi       \
+                 -L$(CLDIR) -lCl       \
+                 -L$(XLDIR) -lXl       \
+                 -L$(HTDIR) -lHt
+
+         LDLIBS = -L/p/motif/lib -lXm -lXt -lX11
+
+ComplexProgramTarget(erwise)
diff --git a/erwise/Includes.h b/erwise/Includes.h
new file mode 100644 (file)
index 0000000..72ecbe7
--- /dev/null
@@ -0,0 +1,15 @@
+/* $Id: Includes.h,v 1.1 1992/05/18 21:43:03 tvr Exp tvr $ */
+
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "Cl.h"
+#include "HTParse.h"
+#include "Ui.h"
+#include "XlConfig.h"
+
+#include "Defs.h"
+#include "Types.h"
+#include "Protos.h"
diff --git a/erwise/Makefile b/erwise/Makefile
new file mode 100644 (file)
index 0000000..8c7702a
--- /dev/null
@@ -0,0 +1,377 @@
+# Makefile generated by imake - do not edit!
+# $XConsortium: imake.c,v 1.65 91/07/25 17:50:17 rws Exp $
+#
+# The cpp used on this machine replaces all newlines and multiple tabs and
+# spaces in a macro expansion with a single space.  Imake tries to compensate
+# for this, but is not always successful.
+#
+
+# -------------------------------------------------------------------------
+# Makefile generated from "Imake.tmpl" and </tmp/IIf.a10927>
+# $XConsortium: Imake.tmpl,v 1.139 91/09/16 08:52:48 rws Exp $
+#
+# Platform-specific parameters may be set in the appropriate <vendor>.cf
+# configuration files.  Site-specific parameters should be set in the file
+# site.def.  Full rebuilds are recommended if any parameters are changed.
+#
+# If your C preprocessor does not define any unique symbols, you will need
+# to set BOOTSTRAPCFLAGS when rebuilding imake (usually when doing
+# "make World" the first time).
+#
+
+# -------------------------------------------------------------------------
+# site-specific configuration parameters that need to come before
+# the platform-specific parameters - edit site.def to change
+
+# site:  $XConsortium: site.def,v 1.2 91/07/30 20:26:44 rws Exp $
+
+# -------------------------------------------------------------------------
+# platform-specific configuration parameters - edit sun.cf to change
+
+# platform:  $XConsortium: sun.cf,v 1.72.1.1 92/03/18 13:13:37 rws Exp $
+
+# operating system:  SunOS 4.1.2
+
+# $XConsortium: sunLib.rules,v 1.7 91/12/20 11:19:47 rws Exp $
+
+.c.o:
+       $(CC) -c $(CFLAGS) $*.c
+
+# -------------------------------------------------------------------------
+# site-specific configuration parameters that go after
+# the platform-specific parameters - edit site.def to change
+
+# site:  $XConsortium: site.def,v 1.2 91/07/30 20:26:44 rws Exp $
+
+            SHELL = /bin/sh
+
+              TOP = ../.
+      CURRENT_DIR = ./erwise
+
+               AR = ar clq
+  BOOTSTRAPCFLAGS =
+               CC = gcc2 -pipe -fstrength-reduce -fpcc-struct-return
+               AS = as
+
+         COMPRESS = compress
+              CPP = /lib/cpp $(STD_CPP_DEFINES)
+    PREPROCESSCMD = gcc2 -pipe -fstrength-reduce -fpcc-struct-return -E $(STD_CPP_DEFINES)
+          INSTALL = install
+               LD = ld
+             LINT = lint
+      LINTLIBFLAG = -C
+         LINTOPTS = -axz
+               LN = ln -s
+             MAKE = make
+               MV = mv
+               CP = cp
+
+           RANLIB = ranlib
+  RANLIBINSTFLAGS =
+
+               RM = rm -f
+            TROFF = psroff
+         MSMACROS = -ms
+              TBL = tbl
+              EQN = eqn
+     STD_INCLUDES =
+  STD_CPP_DEFINES =
+      STD_DEFINES =
+ EXTRA_LOAD_FLAGS = -B/usr/bin/
+  EXTRA_LIBRARIES =
+             TAGS = ctags
+
+    SHAREDCODEDEF = -DSHAREDCODE
+         SHLIBDEF = -DSUNSHLIB
+
+    PROTO_DEFINES =
+
+     INSTPGMFLAGS =
+
+     INSTBINFLAGS = -m 0755
+     INSTUIDFLAGS = -m 4755
+     INSTLIBFLAGS = -m 0644
+     INSTINCFLAGS = -m 0444
+     INSTMANFLAGS = -m 0444
+     INSTDATFLAGS = -m 0444
+    INSTKMEMFLAGS = -g kmem -m 2755
+
+      PROJECTROOT = /v/X11R5
+
+     TOP_INCLUDES = -I$(INCROOT)
+
+      CDEBUGFLAGS = -O
+        CCOPTIONS =
+
+      ALLINCLUDES = $(INCLUDES) $(EXTRA_INCLUDES) $(TOP_INCLUDES) $(STD_INCLUDES)
+       ALLDEFINES = $(ALLINCLUDES) $(STD_DEFINES) $(EXTRA_DEFINES) $(PROTO_DEFINES) $(DEFINES)
+           CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLDEFINES)
+        LINTFLAGS = $(LINTOPTS) -DLINT $(ALLDEFINES)
+
+           LDLIBS = $(SYS_LIBRARIES) $(EXTRA_LIBRARIES)
+
+        LDOPTIONS = $(CDEBUGFLAGS) $(CCOPTIONS) $(LOCAL_LDFLAGS) -L$(USRLIBDIR)
+
+   LDCOMBINEFLAGS = -X -r
+      DEPENDFLAGS =
+
+        MACROFILE = sun.cf
+           RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *~ *.a .emacs_* tags TAGS make.log MakeOut
+
+    IMAKE_DEFINES =
+
+         IRULESRC = $(CONFIGDIR)
+        IMAKE_CMD = $(IMAKE) -DUseInstalled -I$(IRULESRC) $(IMAKE_DEFINES)
+
+     ICONFIGFILES = $(IRULESRC)/Imake.tmpl $(IRULESRC)/Imake.rules \
+                       $(IRULESRC)/Project.tmpl $(IRULESRC)/site.def \
+                       $(IRULESRC)/$(MACROFILE) $(EXTRA_ICONFIGFILES)
+
+# -------------------------------------------------------------------------
+# X Window System Build Parameters
+# $XConsortium: Project.tmpl,v 1.138 91/09/10 09:02:12 rws Exp $
+
+# -------------------------------------------------------------------------
+# X Window System make variables; this need to be coordinated with rules
+
+          PATHSEP = /
+        USRLIBDIR = /v/X11R5/lib
+           BINDIR = /v/X11R5/bin
+          INCROOT = /v/X11R5/include
+     BUILDINCROOT = $(TOP)
+      BUILDINCDIR = $(BUILDINCROOT)/X11
+      BUILDINCTOP = ..
+           INCDIR = $(INCROOT)/X11
+           ADMDIR = /usr/adm
+           LIBDIR = $(USRLIBDIR)/X11
+        CONFIGDIR = $(LIBDIR)/config
+       LINTLIBDIR = $(USRLIBDIR)/lint
+
+          FONTDIR = $(LIBDIR)/fonts
+         XINITDIR = $(LIBDIR)/xinit
+           XDMDIR = $(LIBDIR)/xdm
+           TWMDIR = $(LIBDIR)/twm
+          MANPATH = /v/X11R5/man
+    MANSOURCEPATH = $(MANPATH)/man
+        MANSUFFIX = n
+     LIBMANSUFFIX = 3
+           MANDIR = $(MANSOURCEPATH)$(MANSUFFIX)
+        LIBMANDIR = $(MANSOURCEPATH)$(LIBMANSUFFIX)
+           NLSDIR = $(LIBDIR)/nls
+        PEXAPIDIR = $(LIBDIR)/PEX
+      XAPPLOADDIR = $(LIBDIR)/app-defaults
+       FONTCFLAGS = -t
+
+     INSTAPPFLAGS = $(INSTDATFLAGS)
+
+            IMAKE = imake
+           DEPEND = makedepend
+              RGB = rgb
+
+            FONTC = bdftopcf
+
+        MKFONTDIR = mkfontdir
+        MKDIRHIER = /bin/sh $(BINDIR)/mkdirhier
+
+        CONFIGSRC = $(TOP)/config
+       DOCUTILSRC = $(TOP)/doc/util
+        CLIENTSRC = $(TOP)/clients
+          DEMOSRC = $(TOP)/demos
+           LIBSRC = $(TOP)/lib
+          FONTSRC = $(TOP)/fonts
+       INCLUDESRC = $(TOP)/X11
+        SERVERSRC = $(TOP)/server
+          UTILSRC = $(TOP)/util
+        SCRIPTSRC = $(UTILSRC)/scripts
+       EXAMPLESRC = $(TOP)/examples
+       CONTRIBSRC = $(TOP)/../contrib
+           DOCSRC = $(TOP)/doc
+           RGBSRC = $(TOP)/rgb
+        DEPENDSRC = $(UTILSRC)/makedepend
+         IMAKESRC = $(CONFIGSRC)
+         XAUTHSRC = $(LIBSRC)/Xau
+          XLIBSRC = $(LIBSRC)/X
+           XMUSRC = $(LIBSRC)/Xmu
+       TOOLKITSRC = $(LIBSRC)/Xt
+       AWIDGETSRC = $(LIBSRC)/Xaw
+       OLDXLIBSRC = $(LIBSRC)/oldX
+      XDMCPLIBSRC = $(LIBSRC)/Xdmcp
+      BDFTOSNFSRC = $(FONTSRC)/bdftosnf
+      BDFTOSNFSRC = $(FONTSRC)/clients/bdftosnf
+      BDFTOPCFSRC = $(FONTSRC)/clients/bdftopcf
+     MKFONTDIRSRC = $(FONTSRC)/clients/mkfontdir
+         FSLIBSRC = $(FONTSRC)/lib/fs
+    FONTSERVERSRC = $(FONTSRC)/server
+     EXTENSIONSRC = $(TOP)/extensions
+         XILIBSRC = $(EXTENSIONSRC)/lib/xinput
+      PHIGSLIBSRC = $(EXTENSIONSRC)/lib/PEX
+
+# $XConsortium: sunLib.tmpl,v 1.14.1.1 92/03/17 14:58:46 rws Exp $
+
+SHLIBLDFLAGS = -assert pure-text
+PICFLAGS = -fPIC
+
+  DEPEXTENSIONLIB =
+     EXTENSIONLIB = -lXext
+
+          DEPXLIB = $(DEPEXTENSIONLIB)
+             XLIB = $(EXTENSIONLIB) -lX11
+
+        DEPXMULIB = $(USRLIBDIR)/libXmu.sa.$(SOXMUREV)
+       XMULIBONLY = -lXmu
+           XMULIB = -lXmu
+
+       DEPOLDXLIB =
+          OLDXLIB = -loldX
+
+      DEPXTOOLLIB = $(USRLIBDIR)/libXt.sa.$(SOXTREV)
+         XTOOLLIB = -lXt
+
+        DEPXAWLIB = $(USRLIBDIR)/libXaw.sa.$(SOXAWREV)
+           XAWLIB = -lXaw
+
+        DEPXILIB =
+           XILIB = -lXi
+
+        SOXLIBREV = 4.10
+          SOXTREV = 4.10
+         SOXAWREV = 5.0
+        SOOLDXREV = 4.10
+         SOXMUREV = 4.10
+        SOXEXTREV = 4.10
+      SOXINPUTREV = 4.10
+
+      DEPXAUTHLIB = $(USRLIBDIR)/libXau.a
+         XAUTHLIB =  -lXau
+      DEPXDMCPLIB = $(USRLIBDIR)/libXdmcp.a
+         XDMCPLIB =  -lXdmcp
+
+        DEPPHIGSLIB = $(USRLIBDIR)/libphigs.a
+           PHIGSLIB =  -lphigs
+
+       DEPXBSDLIB = $(USRLIBDIR)/libXbsd.a
+          XBSDLIB =  -lXbsd
+
+ LINTEXTENSIONLIB = $(LINTLIBDIR)/llib-lXext.ln
+         LINTXLIB = $(LINTLIBDIR)/llib-lX11.ln
+          LINTXMU = $(LINTLIBDIR)/llib-lXmu.ln
+        LINTXTOOL = $(LINTLIBDIR)/llib-lXt.ln
+          LINTXAW = $(LINTLIBDIR)/llib-lXaw.ln
+           LINTXI = $(LINTLIBDIR)/llib-lXi.ln
+        LINTPHIGS = $(LINTLIBDIR)/llib-lphigs.ln
+
+          DEPLIBS = $(DEPXAWLIB) $(DEPXMULIB) $(DEPXTOOLLIB) $(DEPXLIB)
+
+         DEPLIBS1 = $(DEPLIBS)
+         DEPLIBS2 = $(DEPLIBS)
+         DEPLIBS3 = $(DEPLIBS)
+
+# -------------------------------------------------------------------------
+# Imake rules for building libraries, programs, scripts, and data files
+# rules:  $XConsortium: Imake.rules,v 1.123 91/09/16 20:12:16 rws Exp $
+
+# -------------------------------------------------------------------------
+# start of Imakefile
+
+#
+#
+#
+
+          OBJS = main.o Setup.o TopLevel.o Page.o Misc.o Help.o        \
+                 Print.o Config.o
+          SRCS = main.c Setup.c TopLevel.c Page.c Misc.c Help.c        \
+                 Print.c Config.c
+
+         XLDIR = ../Xl
+         HTDIR = ../HText
+         CLDIR = ../Cl
+        WWWDIR = $(CLDIR)/WWWLibrary
+         UIDIR = ../Ui
+
+     MOTIF_HDRS = -I/p/motif/include
+    ERWISE_HDRS = -I$(XLDIR) -I$(HTDIR) -I$(CLDIR) -I$(WWWDIR) -I$(UIDIR)
+       DEFINES = $(ERWISE_HDRS) $(MOTIF_HDRS)
+
+LOCAL_LIBRARIES = -L$(WWWDIR) -lWWW    \
+                 -L$(UIDIR) -lUi       \
+                 -L$(CLDIR) -lCl       \
+                 -L$(XLDIR) -lXl       \
+                 -L$(HTDIR) -lHt
+
+         LDLIBS = -L/p/motif/lib -lXm -lXt -lX11
+
+ PROGRAM = erwise
+
+all:: erwise
+
+erwise: $(OBJS) $(DEPLIBS)
+       $(RM) $@
+       $(CC) -o $@ $(OBJS) $(LDOPTIONS) $(LOCAL_LIBRARIES) $(LDLIBS) $(EXTRA_LOAD_FLAGS)
+
+saber_erwise:: $(SRCS)
+       # load $(ALLDEFINES) $(SRCS) $(LOCAL_LIBRARIES) $(SYS_LIBRARIES) $(EXTRA_LIBRARIES)
+
+osaber_erwise:: $(OBJS)
+       # load $(ALLDEFINES) $(OBJS) $(LOCAL_LIBRARIES) $(SYS_LIBRARIES) $(EXTRA_LIBRARIES)
+
+install:: erwise
+       @if [ -d $(DESTDIR)$(BINDIR) ]; then set +x; \
+       else (set -x; $(MKDIRHIER) $(DESTDIR)$(BINDIR)); fi
+       $(INSTALL) -c $(INSTPGMFLAGS)  erwise $(DESTDIR)$(BINDIR)
+
+install.man:: erwise.man
+       @if [ -d $(DESTDIR)$(MANDIR) ]; then set +x; \
+       else (set -x; $(MKDIRHIER) $(DESTDIR)$(MANDIR)); fi
+       $(INSTALL) -c $(INSTMANFLAGS) erwise.man $(DESTDIR)$(MANDIR)/erwise.$(MANSUFFIX)
+
+depend::
+       $(DEPEND) $(DEPENDFLAGS) -s "# DO NOT DELETE" -- $(ALLDEFINES) -- $(SRCS)
+
+lint:
+       $(LINT) $(LINTFLAGS) $(SRCS) $(LINTLIBS)
+lint1:
+       $(LINT) $(LINTFLAGS) $(FILE) $(LINTLIBS)
+
+clean::
+       $(RM) $(PROGRAM)
+
+# -------------------------------------------------------------------------
+# common rules for all Makefiles - do not edit
+
+emptyrule::
+
+clean::
+       $(RM_CMD) "#"*
+
+Makefile::
+       -@if [ -f Makefile ]; then set -x; \
+       $(RM) Makefile.bak; $(MV) Makefile Makefile.bak; \
+       else exit 0; fi
+       $(IMAKE_CMD) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT_DIR)
+
+tags::
+       $(TAGS) -w *.[ch]
+       $(TAGS) -xw *.[ch] > TAGS
+
+saber:
+       # load $(ALLDEFINES) $(SRCS)
+
+osaber:
+       # load $(ALLDEFINES) $(OBJS)
+
+# -------------------------------------------------------------------------
+# empty rules for directories that do not have SUBDIRS - do not edit
+
+install::
+       @echo "install in $(CURRENT_DIR) done"
+
+install.man::
+       @echo "install.man in $(CURRENT_DIR) done"
+
+Makefiles::
+
+includes::
+
+# -------------------------------------------------------------------------
+# dependencies generated by makedepend
+
diff --git a/erwise/Misc.c b/erwise/Misc.c
new file mode 100644 (file)
index 0000000..82c9f73
--- /dev/null
@@ -0,0 +1,426 @@
+static char *rcsid = "$Id: Misc.c,v 1.1 1992/05/18 21:43:03 tvr Exp $";
+
+#include "Includes.h"
+
+
+void displaypage(char *topaddress, HText_t * parenthtext, HText_t * htext,
+                 char *address);
+int addresscmp(char *addr1, char *addr2);
+
+
+Connection_t *Connections = (Connection_t *) NULL;
+Page_t *Pages = (Page_t *) NULL;
+
+
+Page_t *FindPage(hierarchy, address)
+Page_t *hierarchy;
+char *address;
+{
+    while (address && hierarchy)
+       if (!addresscmp(hierarchy->Address, address))
+           return hierarchy;
+       else
+           hierarchy = hierarchy->Next;
+
+    return (Page_t *) NULL;
+}
+
+
+Page_t *
+ GlobalFindPage(address)
+char *address;
+{
+    Page_t *hierarchy = Pages, *tmppage;
+
+    while (address && hierarchy)
+       if (tmppage = FindPage(hierarchy->Children, address))
+           return tmppage;
+       else
+           hierarchy = hierarchy->Next;
+
+    return (Page_t *) NULL;
+}
+
+
+Page_t *
+ AddPage(page, address, htext, toppage)
+Page_t **page;
+char *address;
+HText_t *htext;
+Page_t *toppage;
+{
+    if (*page) {
+       while ((*page)->Next)
+           page = &(*page)->Next;
+       (*page)->Next = (Page_t *) Malloc(sizeof(**page));
+       page = &(*page)->Next;
+    } else
+       *page = (Page_t *) Malloc(sizeof(**page));
+
+    (*page)->Address = strdup(address);
+    (*page)->HText = htext;
+    (*page)->ParentPage = toppage;
+    (*page)->Parents = (Page_t *) NULL;
+    (*page)->Children = (Page_t *) NULL;
+    (*page)->Next = (Page_t *) NULL;
+
+    return *page;
+}
+
+
+void DeletePage(page, address)
+Page_t **page;
+char *address;
+{
+    Page_t *oldpage = *page;
+
+    if (!strcmp((*page)->Address, address)) {
+       *page = (*page)->Next;
+       Free(oldpage);
+    } else
+       while (*page)
+           if (!strcmp((*page)->Address, address)) {
+               *page = (*page)->Next;
+               Free(oldpage);
+           } else {
+               page = &(*page)->Next;
+               oldpage = *page;
+           }
+}
+
+
+void DisplayWarning(text)
+char *text;
+{
+    fprintf(stderr, "Warning: %s\n", text);
+}
+
+
+void DisplayFatal(text)
+char *text;
+{
+    fprintf(stderr, "Fatal: %s\n", text);
+
+    abort();
+}
+
+
+int CanBeCursor(htextobject)
+HTextObject_t *htextobject;
+{
+    int i;
+
+    if (htextobject->paragraph)
+       return FALSE;
+
+    for (i = 0; i < htextobject->length; i++)
+       if (htextobject->data[i] != ' ')
+           return TRUE;
+
+    return FALSE;
+}
+
+
+void *
+ Malloc(size)
+int size;
+{
+    void *tmpptr;
+
+    if (!(tmpptr = (void *) malloc(size))) {
+       DisplayFatal("No swap, buy a computer");
+       exit(1);
+    }                          /* Not reached */
+    return tmpptr;
+}
+
+
+void *
+ ReAlloc(ptr, size)
+void *ptr;
+int size;
+{
+    void *tmpptr;
+
+    if (!ptr)
+       return Malloc(size);
+    else if (!(tmpptr = (void *) realloc((char *) ptr, size))) {
+       DisplayFatal("No swap, buy a computer");
+       exit(1);
+    }                          /* Not reached */
+    return tmpptr;
+}
+
+
+void Free(ptr)
+void *ptr;
+{
+    if (ptr)
+       free(ptr);
+}
+
+
+void StartLoading(address, topaddress, parentaddress)
+char *address;
+char *topaddress;
+char *parentaddress;
+{
+    Page_t *oldpage, *tmppage, *toppage, *parentpage;
+    HText_t *newhtext;
+    ClConnection_t *clconnection;
+    Connection_t *connection;
+
+    toppage = FindPage(Pages, topaddress);
+    parentpage = (toppage && parentaddress) ?
+       FindPage(toppage->Children, parentaddress) : (Page_t *) NULL;
+
+    if (toppage && (oldpage = GlobalFindPage(address))) {
+       if (tmppage = FindPage(toppage->Children, address)) {
+           if (tmppage->HText) {
+               /* add the parent */
+               if (parentaddress && strcmp(parentaddress, address) &&
+                   !FindPage(tmppage->Parents, parentaddress))
+                   AddPage(&tmppage->Parents, parentaddress, tmppage->HText,
+                           parentpage);
+               /* display the page */
+               displaypage(toppage ? toppage->Address : (char *) NULL,
+                      parentpage ? parentpage->HText : (HText_t *) NULL,
+                           tmppage->HText, address);
+
+               return;
+           }
+       } else {
+           if (oldpage->HText) {
+#if 0
+               /* copy the htext */
+               newhtext = HtDuplicate(oldpage->HText);
+               /* add the page */
+               tmppage = AddPage(&toppage->Children, address, newhtext,
+                                 toppage);
+               /* add the parent */
+               if (parentaddress && strcmp(parentaddress, address) &&
+                   !FindPage(tmppage->Parents, parentaddress))
+                   AddPage(&tmppage->Parents, parentaddress, tmppage->HText,
+                           parentpage);
+               /* display the page */
+               displaypage(toppage ? toppage->Address : (char *) NULL,
+                      parentpage ? parentpage->HText : (HText_t *) NULL,
+                           newhtext, address);
+
+               return;
+#endif
+               HTAnchor_setDocument((void *) oldpage->HText->node_anchor,
+                                    (void *) NULL);
+
+           }
+       }
+    }
+    if (FindConnection(address))
+       return;
+
+    if (!(clconnection = ClOpenConnection(address))) {
+       DisplayWarning("Error in ClOpenConnection");
+       return;
+    }
+    connection = AddConnection(address, toppage, parentpage, clconnection);
+
+    PollConnection(connection);
+}
+
+
+void PollConnection(connection)
+Connection_t *connection;
+{
+    HText_t *htext;
+    int status;
+    int oldfd = connection->FD;
+    char *topaddress, *parentaddress;
+    Page_t *tmppage, *toppage, *parentpage;
+
+    htext = ClReadData(connection->ClConnection, &status, &connection->FD);
+
+    switch (status) {
+    case CL_CONTINUES:
+       if (connection->FD && connection->Status == POLLING) {
+           connection->InputId =
+               UiAddInputFD(connection->FD,
+                            (void (*) (void *)) &PollConnection,
+                            (void *) connection);
+           connection->Status = SELECTING;
+       } else if (!connection->FD) {
+           if (oldfd)
+               UiDeleteInputFD(connection->InputId);
+           connection->TimeOutId =
+               UiAddTimeOut(200, (void (*) (void *)) &PollConnection,
+                            (void *) connection);
+           connection->Status = POLLING;
+       }
+       break;
+    case CL_COMPLETED:
+       if (connection->Status == SELECTING)
+           UiDeleteInputFD(connection->InputId);
+       if (htext && !connection->TopPage->HText)
+           connection->TopPage->HText = htext;
+
+       if (htext) {
+           parentaddress = connection->ParentPage ?
+               connection->ParentPage->Address : (char *) NULL;
+           toppage = connection->TopPage;
+
+           parentpage = connection->ParentPage;
+           if (!(tmppage = FindPage(toppage->Children, connection->Address))) {
+               tmppage = AddPage(&toppage->Children, connection->Address,
+                                 htext, toppage);
+               /* add the parent (what the fuck have I been thinkin' here?) */
+               if (connection->ParentPage && parentaddress &&
+                   !FindPage(tmppage->Parents, parentaddress))
+                   AddPage(&tmppage->Parents, parentaddress,
+                           tmppage->HText, parentpage);
+           } else
+               tmppage->HText = htext;
+
+           displaypage(connection->TopPage ?
+                       connection->TopPage->Address : (char *) NULL,
+                       connection->ParentPage ?
+                       connection->ParentPage->HText : (HText_t *) NULL,
+                       htext, connection->Address);
+       }
+       DeleteConnection(connection->Address);
+       break;
+    case CL_FAILED:
+       if (connection->Status == SELECTING)
+           UiDeleteInputFD(connection->InputId);
+       DeleteConnection(connection->Address);
+       break;
+    default:
+       DisplayWarning("Uh? :O");
+    }
+}
+
+
+void displaypage(topaddress, parenthtext, htext, address)
+char *topaddress;
+HText_t *parenthtext;
+HText_t *htext;
+char *address;
+{
+    HTextAnchor_t *htanchor = (HTextAnchor_t *) NULL;
+    HTextObject_t *htextobject;
+    char *tag = HTParse(address, "", PARSE_ANCHOR);
+
+    if (tag && tag[0]) {
+       htanchor = htext->anchorlist;
+       while (htanchor)
+           if (htanchor->anchor && htanchor->anchor->tag &&
+               !strcmp(htanchor->anchor->tag, tag))
+               break;
+           else
+               htanchor = htanchor->next;
+       Free(tag);
+    }
+    htextobject = htanchor ? htanchor->object : htext->first;
+
+    while (htextobject && !CanBeCursor(htextobject))
+       htextobject = htextobject->next;
+
+    UiDisplayPage(topaddress, parenthtext, htext, htextobject,
+                 (char *) HTAnchor_title(htext->node_anchor));
+}
+
+
+Connection_t *
+ AddConnection(address, toppage, parentpage, clconnection)
+char *address;
+Page_t *toppage;
+Page_t *parentpage;
+ClConnection_t *clconnection;
+{
+    Connection_t *tmpconnection = Connections;
+
+    if (tmpconnection) {
+       while (tmpconnection->Next)
+           tmpconnection = tmpconnection->Next;
+       tmpconnection = tmpconnection->Next = Malloc(sizeof(*tmpconnection));
+    } else
+       tmpconnection = Connections = Malloc(sizeof(*tmpconnection));
+
+    tmpconnection->Address = strdup(address);
+    tmpconnection->TopPage = toppage;
+    tmpconnection->ParentPage = parentpage;
+    tmpconnection->ClConnection = clconnection;
+    tmpconnection->FD = 0;
+    tmpconnection->Status = POLLING;
+    tmpconnection->Next = (Connection_t *) NULL;
+
+    if (UiConnectionsDialogDisplayed())
+       ConnectionsCB((char *) NULL, (HText_t *) NULL,
+                     (HTextObject_t *) NULL, (void *) NULL);
+
+    return tmpconnection;
+}
+
+
+Connection_t *
+ FindConnection(address)
+char *address;
+{
+    Connection_t *tmpconnection = Connections;
+
+    while (tmpconnection)
+       if (!addresscmp(tmpconnection->Address, address))
+           return tmpconnection;
+       else
+           tmpconnection = tmpconnection->Next;
+
+    return (Connection_t *) NULL;
+}
+
+
+void DeleteConnection(address)
+char *address;
+{
+    Connection_t *tmpconnection = Connections;
+
+    if (tmpconnection)
+       if (!strcmp(tmpconnection->Address, address))
+           Connections = Connections->Next;
+       else {
+           while (tmpconnection->Next &&
+                  strcmp(tmpconnection->Next->Address, address))
+               tmpconnection = tmpconnection->Next;
+           if (tmpconnection->Next) {
+               Connection_t *tmptmpconnection;
+
+               tmptmpconnection = tmpconnection->Next;
+               tmpconnection->Next = tmpconnection->Next->Next;
+               tmpconnection = tmptmpconnection;
+           } else
+               tmpconnection = (Connection_t *) NULL;
+       }
+    if (tmpconnection) {
+       if (UiConnectionsDialogDisplayed())
+           ConnectionsCB((char *) NULL, (HText_t *) NULL,
+                         (HTextObject_t *) NULL, (void *) NULL);
+       Free(tmpconnection->Address);
+       Free(tmpconnection);
+    } else
+       DisplayWarning("DeleteConnection failed");
+}
+
+
+int addresscmp(addr1, addr2)
+char *addr1, *addr2;
+{
+    int i = 0;
+
+    while (addr1[i] && addr2[i] && addr1[i] != '#' && addr2[i] != '#')
+       if (addr1[i] != addr2[i])
+           return 1;
+       else
+           i++;
+
+    if ((addr1[i] && addr1[i] != '#') || (addr2[i] && addr2[i] != '#'))
+       return 1;
+
+    return 0;
+}
diff --git a/erwise/Page.c b/erwise/Page.c
new file mode 100644 (file)
index 0000000..7b97a21
--- /dev/null
@@ -0,0 +1,739 @@
+static char *rcsid = "$Id: Page.c,v 1.1 1992/05/18 21:43:03 tvr Exp $";
+
+#include "Includes.h"
+
+
+void getanddisplaypage(char *topaddress, HText_t * htext,
+                       HTextObject_t * htextobject);
+int matchingstring(char *word);
+
+
+char FindText[256] = "\0";
+char SearchText[256] = "\0";
+int SearchDepth = 1;
+int SearchCase = FALSE;
+
+
+static int SearchDialogType;
+static int PageSettingsDialogType;
+
+static char *CopyTopAddress;
+static HText_t *CopyHText;
+static HTextObject_t *CopyHTextObject;
+
+
+void PageSearchCB(topaddress, htext, htextobject, parameter)
+char *topaddress;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    UiDisplaySearchDialog(SearchDialogType);
+}
+
+
+void PageCopyCB(topaddress, htext, htextobject, parameter)
+char *topaddress;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    CopyHTextObject = htextobject;
+    CopyTopAddress = strdup(topaddress);
+    CopyHText = htext;
+}
+
+
+void PageListCB(topaddress, htext, htextobject, parameter)
+char *topaddress;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    int i = 0, j, stringlength;
+    char **items = (char **) NULL;
+    char **addresses = (char **) NULL;
+    HTextObject_t *tmphtextobject = htext->first;
+    HTAnchor *tmpanchor, *destanchor;
+
+    while (tmphtextobject)
+       if (tmpanchor = (HTAnchor *) tmphtextobject->anchor) {
+           addresses = (char **) ReAlloc((void *) addresses,
+                                         ++i * sizeof(char *));
+           destanchor =
+               HTAnchor_followMainLink((HTAnchor *) tmphtextobject->anchor);
+           addresses[i - 1] = HTAnchor_address(destanchor);
+           items = (char **) ReAlloc((void *) items, i * sizeof(char *));
+           j = 1;
+           items[i - 1] = (char *) NULL;
+           while (tmphtextobject &&
+                  (HTAnchor *) tmphtextobject->anchor == tmpanchor) {
+               stringlength = strlen(tmphtextobject->data);
+               j += stringlength;
+               items[i - 1] = (char *) ReAlloc((void *) items[i - 1],
+                                               j * sizeof(char));
+               strcpy(&items[i - 1][j - stringlength - 1],
+                      tmphtextobject->data);
+               items[i - 1][j - 1] = '\0';
+               tmphtextobject = tmphtextobject->next;
+           }
+       } else
+           tmphtextobject = tmphtextobject->next;
+
+    UiDisplayListDialog(items, addresses, i, StartLoading);
+}
+
+
+void PageLoadToFileCB(topaddress, htext, htextobject, parameter)
+char *topaddress;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    HTAnchor *destanchor;
+
+    if (!htextobject || !htextobject->anchor) {
+       UiDisplayWarningDialog("No active tag", (void (*) (int)) NULL);
+       return;
+    }
+    destanchor = HTAnchor_followMainLink((HTAnchor *) htextobject->anchor);
+    if (ClCanLoadToFile(HTAnchor_address(destanchor)))
+       UiDisplayFileSelection(PageGetPageCB);
+    else
+       UiDisplayWarningDialog("Load to file not supported for this tag",
+                              (void (*) (int)) NULL);
+}
+
+
+int TruthValue(value)
+char *value;
+{
+    if (value && (!strncasecmp(value, STR_TRUE, strlen(STR_TRUE)) ||
+                 !strncasecmp(value, STR_ON, strlen(STR_ON)) ||
+                 !strncasecmp(value, STR_YES, strlen(STR_YES))))
+       return TRUE;
+    return FALSE;
+}
+
+
+void PagePrintCB(topaddress, htext, htextobject, parameter)
+char *topaddress;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    static void *table = (void *) NULL;
+    int update = FALSE;
+    char *configstr;
+
+    if (!table) {
+       update = TRUE;
+       table = ConfigGetValue((void *) NULL, C_PRINT);
+       PrintTopMargin = atoi((char *) ConfigGetValue(table, C_TOPMARGIN));
+       PrintBottomMargin =
+           atoi((char *) ConfigGetValue(table, C_BOTTOMMARGIN));
+       PrintLeftMargin = atoi((char *) ConfigGetValue(table, C_LEFTMARGIN));
+       PrintWidth = atoi((char *) ConfigGetValue(table, C_WIDTH));
+       if (configstr = (char *) ConfigGetValue(table, C_COMMAND))
+           strcpy(PrintCommand, configstr);
+       else
+           strcpy(PrintCommand, "");
+       PrintToFile = TruthValue((char *) ConfigGetValue(table, C_PRINTTOFILE));
+       if (configstr = (char *) ConfigGetValue(table, C_FILENAME))
+           strcpy(PrintFileName, configstr);
+       else
+           strcpy(PrintFileName, "");
+    }
+    UiDisplayPrintDialog(htext);
+
+    if (update) {
+       UiUpdateVariable("PrintTopMargin");
+       UiUpdateVariable("PrintBottomMargin");
+       UiUpdateVariable("PrintLeftMargin");
+       UiUpdateVariable("PrintWidth");
+       UiUpdateVariable("PrintCommand");
+       UiUpdateVariable("PrintToFile");
+       UiUpdateVariable("PrintFileName");
+    }
+}
+
+
+void PageSettingsCB(topaddress, htext, htextobject, parameter)
+char *topaddress;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    UiDisplayPageSettingsDialog(PageSettingsDialogType);
+}
+
+
+void PageCloseCB(topaddress, htext, htextobject, parameter)
+char *topaddress;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    char *address = HTAnchor_address((HTAnchor *) htext->node_anchor);
+    Page_t *toppage, *page;
+
+    toppage = FindPage(Pages, topaddress);
+    page = FindPage(toppage->Children, address);
+
+    UiDeletePage(toppage->Address, htext);
+    page->HText = (HText_t *) NULL;
+    HText_free(htext);
+
+    page = toppage->Children;
+    while (page)
+       if (page->HText)
+           return;
+       else
+           page = page->Next;
+
+    HierarchyClose(topaddress, htext, htextobject, parameter);
+}
+
+
+void PagePrevWordCB(topaddress, htext, htextobject, parameter)
+char *topaddress;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    HTextObject_t *tmphtextobject;
+
+    if (!htextobject)
+       return;
+
+    tmphtextobject = htextobject->prev;
+
+    while (tmphtextobject && !CanBeCursor(tmphtextobject))
+       tmphtextobject = tmphtextobject->prev;
+
+    if (tmphtextobject)
+       UiSetCursor(topaddress, htext, tmphtextobject);
+}
+
+
+void PageNextWordCB(topaddress, htext, htextobject, parameter)
+char *topaddress;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    HTextObject_t *tmphtextobject;
+
+    if (!htextobject)
+       return;
+
+    tmphtextobject = htextobject->next;
+
+    while (tmphtextobject && !CanBeCursor(tmphtextobject))
+       tmphtextobject = tmphtextobject->next;
+
+    if (tmphtextobject)
+       UiSetCursor(topaddress, htext, tmphtextobject);
+}
+
+
+void PagePrevTagCB(topaddress, htext, htextobject, parameter)
+char *topaddress;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    HTextAnchor_t *tmphtanchor;
+    HTAnchor *tmpanchor, *destanchor;
+    HText_t *newhtext;
+    HTextObject_t *newhtextobject;
+
+    if (!htextobject)
+       return;
+
+    tmpanchor = (HTAnchor *) htextobject->anchor;
+
+    /* Ignore htextobject with same anchor */
+    while (tmpanchor && htextobject &&
+          ((HTAnchor *) htextobject->anchor == tmpanchor))
+       htextobject = htextobject->prev;
+
+    /* Search for previous anchor */
+    while (htextobject && !htextobject->anchor)
+       htextobject = htextobject->prev;
+
+    /* No anchor found */
+    if (!htextobject)
+       return;
+
+    /* We want the first word in the tag to be highlighted */
+    while (htextobject->prev &&
+          (htextobject->anchor == htextobject->prev->anchor))
+       htextobject = htextobject->prev;
+
+    UiSetCursor(topaddress, htext, htextobject);
+
+    if ((int) parameter == NO_AUTOGET)
+       return;
+
+    getanddisplaypage(topaddress, htext, htextobject);
+}
+
+
+void PageNextTagCB(topaddress, htext, htextobject, parameter)
+char *topaddress;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    HTAnchor *tmpanchor;
+    HTextObject_t *newhtextobject;
+
+    if (!htextobject)
+       return;
+
+    tmpanchor = (HTAnchor *) htextobject->anchor;
+
+    /* Ignore htextobject with same anchor */
+    while (tmpanchor && htextobject &&
+          ((HTAnchor *) htextobject->anchor == tmpanchor))
+       htextobject = htextobject->next;
+
+    /* Search for previous anchor */
+    while (htextobject && !htextobject->anchor)
+       htextobject = htextobject->next;
+
+    /* No anchor found */
+    if (!htextobject)
+       return;
+
+    UiSetCursor(topaddress, htext, htextobject);
+
+    if ((int) parameter == NO_AUTOGET)
+       return;
+
+    getanddisplaypage(topaddress, htext, htextobject);
+}
+
+
+void PageHomeCB(topaddress, htext, htextobject, parameter)
+char *topaddress;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    StartLoading(topaddress, topaddress, (char *) NULL);
+}
+
+
+void PageRecallCB(topaddress, htext, htextobject, parameter)
+char *topaddress;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    Page_t *toppage, *page;
+    int i = 0;
+    char **items = (char **) NULL;
+
+    toppage = FindPage(Pages, topaddress);
+    page = toppage->Children;
+
+    while (page) {
+       items = (char **) ReAlloc((void *) items, ++i * sizeof(char *));
+       items[i - 1] = strdup(page->Address);
+       page = page->Next;
+    }
+
+    UiDisplayRecallDialog(items, i, StartLoading);
+}
+
+
+void PageBackCB(topaddress, htext, htextobject, parameter)
+char *topaddress;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    char *address = HTAnchor_address((HTAnchor *) htext->node_anchor);
+    Page_t *toppage, *parentpage, *page;
+
+    toppage = FindPage(Pages, topaddress);
+    page = FindPage(toppage->Children, address);
+
+    if (parentpage = page->Parents) {
+       if (parentpage->Next)
+           PageGeneratePopup(parentpage, topaddress);
+       else {
+           while (parentpage->Next)
+               parentpage = parentpage->Next;
+           StartLoading(parentpage->Address, topaddress, parentpage->Address);
+       }
+    }
+}
+
+
+PageGeneratePopup(parentpage, topaddress)
+Page_t *parentpage;
+char *topaddress;
+{
+    char **items = (char **) NULL;
+    int nitems = 0;
+
+    while (parentpage) {
+       items = (char **) ReAlloc((void *) items, ++nitems * sizeof(char *));
+       items[nitems - 1] = parentpage->Address;
+       parentpage = parentpage->Next;
+    }
+
+    UiDisplayPopup(StartLoading, topaddress, items, nitems);
+}
+
+
+HTextObject_t *
+ FindHTextObject(htext, address)
+HText_t *htext;
+char *address;
+{
+    HTextObject_t *newhtextobject;
+    HTAnchor *destanchor;
+
+    newhtextobject = htext->first;
+    while (newhtextobject) {
+       if (newhtextobject->anchor) {
+           destanchor =
+               HTAnchor_followMainLink((HTAnchor *) newhtextobject->anchor);
+           if (destanchor && !strcmp(HTAnchor_address(destanchor), address))
+               return newhtextobject;
+       }
+       newhtextobject = newhtextobject->next;
+    }
+
+    return (HTextObject_t *) NULL;
+}
+
+
+void PagePrevPageCB(topaddress, htext, htextobject, parameter)
+char *topaddress;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    char *address = HTAnchor_address((HTAnchor *) htext->node_anchor);
+    Page_t *toppage, *parentpage, *page;
+    HTextObject_t *newhtextobject;
+
+    toppage = FindPage(Pages, topaddress);
+    page = FindPage(toppage->Children, address);
+
+    if (parentpage = page->Parents) {
+       if (parentpage->Next)
+           PageGeneratePopup(parentpage, topaddress);
+       while (parentpage->Next)
+           parentpage = parentpage->Next;
+       parentpage = parentpage->ParentPage;
+       if (parentpage->HText) {
+           newhtextobject = FindHTextObject(parentpage->HText, page->Address);
+           if (newhtextobject)
+               PagePrevTagCB(topaddress, parentpage->HText,
+                             newhtextobject, (void *) AUTOGET);
+       } else
+           StartLoading(parentpage->Address, topaddress, (char *) NULL);
+    }
+}
+
+
+void PageNextPageCB(topaddress, htext, htextobject, parameter)
+char *topaddress;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    char *address = HTAnchor_address((HTAnchor *) htext->node_anchor);
+    Page_t *toppage, *parentpage, *page;
+    HTextObject_t *newhtextobject;
+
+    toppage = FindPage(Pages, topaddress);
+    page = FindPage(toppage->Children, address);
+
+    if (parentpage = page->Parents) {
+       if (parentpage->Next)
+           PageGeneratePopup(parentpage, topaddress);
+       while (parentpage->Next)
+           parentpage = parentpage->Next;
+       parentpage = parentpage->ParentPage;
+       if (parentpage->HText) {
+           newhtextobject = FindHTextObject(parentpage->HText, page->Address);
+           if (newhtextobject)
+               PageNextTagCB(topaddress, parentpage->HText,
+                             newhtextobject, (void *) AUTOGET);
+       } else
+           StartLoading(parentpage->Address, topaddress, (char *) NULL);
+    }
+}
+
+
+void PageGetPageCB(topaddress, htext, htextobject, parameter)
+char *topaddress;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    if (!htextobject || !htextobject->anchor)
+       return;
+
+    if (parameter)
+       ClSetFileNameForLoadingToFile((char *) parameter);
+
+    getanddisplaypage(topaddress, htext, htextobject);
+}
+
+
+void PageClickCB(topaddress, htext, htextobject, parameter)
+char *topaddress;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    HTextObject_t *tmphtextobject = htext->first;
+    int state = 0;
+
+    if (CopyHTextObject && !strcmp(topaddress, CopyTopAddress)
+       && htext == CopyHText)
+       while (tmphtextobject) {
+           if (tmphtextobject == CopyHTextObject ||
+               tmphtextobject == htextobject)
+               state += 1 + (CopyHTextObject == htextobject);
+           switch (state) {
+           case 2:
+               if (tmphtextobject->data)
+                   UiAddStringToCutBuffer(tmphtextobject->data);
+               else
+                   UiAddStringToCutBuffer("\n");
+               UiAddStringToCutBuffer((char *) NULL);
+               tmphtextobject = (HTextObject_t *) NULL;
+               Free(CopyTopAddress);
+               break;
+           case 1:
+               if (tmphtextobject->data)
+                   UiAddStringToCutBuffer(tmphtextobject->data);
+               else
+                   UiAddStringToCutBuffer("\n");
+               /* Fall through */
+           default:
+               tmphtextobject = tmphtextobject->next;
+           }
+       }
+
+    CopyHTextObject = (HTextObject_t *) NULL;
+}
+
+
+void IndexFindCB(topaddress, htext, htextobject, parameter)
+char *topaddress;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    char *newaddress;
+
+    if (!FindText[0])
+       return;
+
+    HTMainAnchor = htext->node_anchor; /* Kludguality */
+    newaddress = (char *) HTSearchAddress(FindText);   /* missa proto, meeTu? */
+
+    StartLoading(newaddress, topaddress,
+                HTAnchor_address((HTAnchor *) htext->node_anchor));
+    Free(newaddress);
+}
+
+
+static char *hiertopaddress;
+static HText_t *hierhtext;
+static HTextObject_t *hierhtextobject;
+static void *hierparameter;
+
+void HierarchyCloseCB(topaddress, htext, htextobject, parameter)
+char *topaddress;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    hiertopaddress = topaddress;
+    hierhtext = htext;
+    hierhtextobject = htextobject;
+    hierparameter = parameter;
+
+    UiDisplayWarningDialog("Close hierarchy?", HierarchyNukeCB);
+}
+
+
+void HierarchyNukeCB(button)
+int button;
+{
+    HierarchyClose(hiertopaddress, hierhtext, hierhtextobject, hierparameter);
+}
+
+
+void HierarchyClose(topaddress, htext, htextobject, parameter)
+char *topaddress;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    Page_t *toppage;
+
+    toppage = FindPage(Pages, topaddress);
+
+    while (toppage->Children) {
+       if (toppage->Children->HText) {
+           HText_free(toppage->Children->HText);
+           UiDeletePage(toppage->Address, toppage->Children->HText);
+       }
+       while (toppage->Children->Parents)
+           DeletePage(&toppage->Children->Parents,
+                      toppage->Children->Parents->Address);
+       DeletePage(&toppage->Children, toppage->Children->Address);
+    }
+
+    DeletePage(&Pages, toppage->Address);
+}
+
+
+void SearchBackwardCB(topaddress, htext, htextobject, parameter)
+char *topaddress;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    HTextObject_t *newhtextobject;
+
+    if (!htextobject)
+       return;
+
+    newhtextobject = htextobject->prev;
+    while (newhtextobject && !matchingstring(newhtextobject->data))
+       newhtextobject = newhtextobject->prev;
+
+    if (newhtextobject)
+       UiSetCursor(topaddress, htext, newhtextobject);
+}
+
+
+void SearchForwardCB(topaddress, htext, htextobject, parameter)
+char *topaddress;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    HTextObject_t *newhtextobject;
+
+    if (!htextobject)
+       return;
+
+    newhtextobject = htextobject->next;
+    while (newhtextobject && !matchingstring(newhtextobject->data))
+       newhtextobject = newhtextobject->next;
+
+    if (newhtextobject)
+       UiSetCursor(topaddress, htext, newhtextobject);
+}
+
+
+void ConnectionsCB(topaddress, htext, htextobject, parameter)
+char *topaddress;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    Connection_t *tmpconnection = Connections;
+    char **listitems = (char **) NULL;
+    void **connections = (void **) NULL;
+    int nitems = 0;
+
+    while (tmpconnection) {
+       listitems = (char **) ReAlloc((void *) listitems,
+                                     ++nitems * sizeof(char *));
+       listitems[nitems - 1] = tmpconnection->Address;
+       connections = (void **) ReAlloc((void *) connections,
+                                       nitems * sizeof(void *));
+       connections[nitems - 1] = tmpconnection;
+       tmpconnection = tmpconnection->Next;
+    }
+
+    UiDisplayConnectionsDialog(listitems, connections, nitems, KillCB);
+}
+
+
+void KillCB(connection)
+void *connection;
+{
+    Connection_t *tmpconnection = (Connection_t *) connection;
+
+    switch (tmpconnection->Status) {
+    case SELECTING:
+       UiDeleteInputFD(tmpconnection->InputId);
+       break;
+    case POLLING:
+       UiDeleteTimeOut(tmpconnection->TimeOutId);
+    }
+
+    ClCloseConnection(tmpconnection->ClConnection);
+    DeleteConnection(tmpconnection->Address);
+}
+
+
+void ControlPanelCB(topaddress, htext, htextobject, parameter)
+char *topaddress;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    UiDisplayControlPanel();
+}
+
+
+void DefaultsCB(topaddress, htext, htextobject, parameter)
+char *topaddress;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    UiDisplayDefaultsDialog();
+}
+
+
+void getanddisplaypage(topaddress, htext, htextobject)
+char *topaddress;
+HText_t *htext;
+HTextObject_t *htextobject;
+{
+    HTAnchor *destanchor;
+
+    destanchor = HTAnchor_followMainLink((HTAnchor *) htextobject->anchor);
+    HTMainAnchor = (HTParentAnchor *) NULL;
+
+    StartLoading(HTAnchor_address(destanchor),
+                topaddress,
+                HTAnchor_address((HTAnchor *) htext->node_anchor));
+}
+
+
+int matchingstring(word)
+char *word;
+{
+    char *tmpptr = word;
+    int searchlength = strlen(SearchText);
+
+    while (tmpptr && strlen(tmpptr) >= searchlength) {
+       if (SearchCase) {
+           if (!strncmp(tmpptr, SearchText, searchlength))
+               return TRUE;
+       } else if (!strncasecmp(tmpptr, SearchText, searchlength))
+           return TRUE;
+       tmpptr++;
+    }
+
+    return FALSE;
+}
diff --git a/erwise/Print.c b/erwise/Print.c
new file mode 100644 (file)
index 0000000..362995d
--- /dev/null
@@ -0,0 +1,526 @@
+/*
+ * Print.c --
+ *
+ * Author: Teemu Rantanen <tvr@cs.hut.fi> Copyright (c) 1992 Teemu Rantanen All
+ * rights reserved
+ *
+ * Created: Sun Apr 26 21:30:47 1992 tvr Last modified: Mon May 11 22:56:41 1992
+ * tvr
+ *
+ */
+
+#include "Includes.h"
+
+#include <fcntl.h>
+
+int PrintTopMargin = 0;
+int PrintBottomMargin = 0;
+int PrintLeftMargin = 0;
+int PrintWidth = 80;
+int PrintToFile = 0;
+
+char PrintCommand[1024] = "lpr";
+char PrintFileName[1024] = "foobar.www";
+
+
+/*
+ * One object on a line
+ */
+typedef struct PrintObject_s {
+
+    HTextObject_t *HtObject;
+
+    struct PrintObject_s *Next;
+} PrintObject_t;
+
+
+/*
+ * All line objects and info on line
+ */
+typedef struct PrintLine_s {
+
+    int LineY;
+
+    PrintObject_t *Objects;
+
+    struct PrintLine_s *Next;
+
+} PrintLine_t;
+
+
+
+/*
+ * Allocate new PrintObject.
+ */
+PrintObject_t *
+ new_print_object()
+{
+    PrintObject_t *p;
+
+    p = (PrintObject_t *) malloc(sizeof(*p));
+
+    if (!p)
+       return p;
+
+    memset(p, 0, sizeof(*p));
+
+    return p;
+}
+
+
+/*
+ * Allocate new PrintLine.
+ */
+PrintLine_t *
+ new_print_line()
+{
+    PrintLine_t *p;
+
+    p = (PrintLine_t *) malloc(sizeof(*p));
+
+    if (!p)
+       return p;
+
+    memset(p, 0, sizeof(*p));
+
+    return p;
+}
+
+
+/*
+ * Append object to a line. Sort objects according to x position
+ */
+int printobject_append(line, htobject)
+PrintLine_t *line;
+HTextObject_t *htobject;
+{
+    PrintObject_t *object = line->Objects;
+    PrintObject_t *prev = 0;
+
+    /*
+     * First object on a line
+     */
+    if (!object) {
+       if (!(line->Objects = new_print_object()))
+           return 0;
+
+       line->Objects->HtObject = htobject;
+
+       return 1;
+    }
+    /*
+     * Check on which place do we put this ?
+     */
+    while (object && (htobject->x > object->HtObject->x)) {
+
+       prev = object;
+
+       object = object->Next;
+    }
+
+    /*
+     * Set object to line-list
+     */
+
+    {
+       PrintObject_t *new_object = new_print_object();
+
+       if (!new_object)
+           return 0;
+
+       new_object->Next = object;
+
+       new_object->HtObject = htobject;
+
+       if (prev) {
+
+           prev->Next = new_object;
+
+       } else {
+
+           line->Objects = new_object;
+
+       }
+    }
+}
+
+
+/*
+ * Check on which line object should be appended
+ */
+PrintLine_t *
+ print_check_line_append(first, object)
+PrintLine_t *first;
+HTextObject_t *object;
+{
+    PrintLine_t *p;
+    PrintLine_t *new_line;
+    PrintLine_t *prev;
+
+    /*
+     * If this is first line, no problemo ...
+     */
+    if (!first) {
+
+       p = new_print_line();
+
+       if (!p)
+           return 0;
+
+       p->LineY = object->y;
+
+       if (!printobject_append(p, object))
+           return 0;
+
+       return p;
+    }
+    /*
+     * Find a line
+     */
+    p = first;
+    prev = 0;
+
+    while (p && (p->LineY < object->y)) {
+
+       prev = p;
+
+       p = p->Next;
+    }
+
+    /*
+     * Line already exists ?
+     */
+    if (p && (p->LineY == object->y)) {
+
+       if (!printobject_append(p, object))
+           return 0;
+
+       return first;
+    }
+    /*
+     * Line does not exist ... make one
+     */
+
+    new_line = new_print_line();
+
+    if (!new_line)
+       return 0;
+
+    new_line->LineY = object->y;
+
+    if (prev) {
+       /*
+         * Append to middle of the list
+         */
+       prev->Next = new_line;
+
+       new_line->Next = p;
+
+       if (!printobject_append(new_line, object))
+           return 0;
+
+       return first;
+    } else {
+       /*
+         * Append to first
+         */
+       new_line->Next = p;
+
+       if (!printobject_append(new_line, object))
+           return 0;
+
+       return new_line;
+    }
+
+    /*
+     * Should not get here
+     */
+    return 0;
+}
+
+
+/*
+ * Print using this command
+ */
+int erwise_popen(command)
+char *command;
+{
+    int fd[2];
+
+    int ppid;
+
+    if (pipe(fd)) {
+
+       printf("erwise_popen: cannot make pipe\n");
+
+       return -1;
+    }
+    switch (ppid = fork()) {
+    case 0:
+
+       dup2(fd[0], 0);
+
+       close(fd[1]);
+       close(fd[0]);
+
+       system(command);
+
+       close(0);
+
+       exit(0);
+
+       break;
+
+    case -1:
+
+       printf("cannot fork\n");
+
+       return -1;
+
+       break;
+
+    default:
+
+       close(fd[0]);
+
+       return (fd[1]);
+    }
+
+    /*
+     * should not get here ...
+     */
+    return -1;
+}
+
+
+
+/*
+ * Open files, handle commands, call DoPrint
+ */
+int Print(htext)
+HText_t *htext;
+{
+    int fd;
+
+    if ((PrintWidth <= 0) || (PrintTopMargin < 0) || (PrintBottomMargin < 0) ||
+       (PrintLeftMargin < 0)) {
+
+       printf("Print: parameters insane\n");
+
+       return 1;
+    }
+    if (PrintToFile) {
+
+       fd = open(PrintFileName, O_WRONLY | O_CREAT, 0666);
+
+       if (fd < 0) {
+
+           printf("Print: cannot create file %s\n", PrintFileName);
+
+           return 1;
+       }
+       DoPrint(htext, fd, PrintWidth, PrintLeftMargin, PrintTopMargin,
+               PrintBottomMargin);
+
+       close(fd);
+
+    } else {
+
+       fd = erwise_popen(PrintCommand);
+
+       if (fd < 0) {
+
+           printf("Print: failed printing to command %s\n", PrintCommand);
+
+           return 1;
+       }
+       DoPrint(htext, fd, PrintWidth, PrintLeftMargin, PrintTopMargin,
+               PrintBottomMargin);
+
+       close(fd);
+    }
+
+    return 0;
+}
+
+
+/*
+ * Handle printing. Format text (ascii) and put it to wanted fd
+ */
+int DoPrint(old_htext, fd, width, lmargin, top, bottom)
+HText_t *old_htext;
+int fd;
+int width;
+int lmargin;
+int top;
+int bottom;
+{
+    PrintLine_t *first_line = 0;
+
+    HText_t *htext = 0;
+
+    htext = (HText_t *) HtDuplicate(old_htext);
+
+    if (!htext)
+       return 0;
+
+    /*
+     * Format text using fixed width. After this call every object is
+     * positioned correctly.
+     */
+    XlFormatTextForPrinting(htext, lmargin, lmargin + width);
+
+    /*
+     * Because some objects may not be in x,y order, contruct list of lines
+     * so that lines are in order 0->j and for every line objects are in
+     * order 0->i.
+     *
+     * Because of allmost all objects are in order by default, contruct lists
+     * from last to first. Now most objects can be inserted as the first
+     * object of the first line.
+     */
+    {
+       HTextObject_t *p;
+
+       p = htext->last;
+
+       while (p) {
+
+           /*
+             * XXXXX free allocated on error
+             */
+           first_line = print_check_line_append(first_line, p);
+
+           p = p->prev;
+       }
+    }
+
+    /*
+     * Now, print line by line
+     */
+
+    {
+       PrintLine_t *line = first_line;
+
+       char newline[1];
+
+       int y = 0;
+       int max_x;
+
+       *newline = 10;
+
+       /*
+         * Write top margin
+         */
+       for (; top > 0; top--)
+           write(fd, newline, 1);
+
+       while (line) {
+           /*
+             * Print empty lines
+             */
+
+           while (y < line->LineY) {
+               y++;
+
+               write(fd, newline, 1);
+           }
+
+           /*
+             * Get maximum x on a line
+             */
+           {
+               PrintObject_t *p;
+
+               p = line->Objects;
+
+               max_x = 0;
+
+               while (p) {
+
+                   if (max_x < (p->HtObject->x + p->HtObject->width))
+                       max_x = p->HtObject->x + p->HtObject->width;
+
+                   p = p->Next;
+               }
+           }
+
+           /*
+             * Collect data on a line and print it
+             */
+           {
+               PrintObject_t *p;
+
+               char *d = malloc(max_x + 1);
+
+               p = line->Objects;
+
+               /*
+                * XXXXXX free
+                */
+               if (!d)
+                   return;
+
+               memset(d, ' ', max_x + 1);
+
+               while (p) {
+                   if (p->HtObject->data) {
+
+                       memcpy(d + p->HtObject->x, p->HtObject->data,
+                              p->HtObject->length);
+                   }
+                   p = p->Next;
+               }
+
+               write(fd, d, max_x + 1);
+
+               free(d);
+           }
+
+           line = line->Next;
+
+       }
+
+       write(fd, newline, 1);
+
+       /*
+         * Write bottom margin
+         */
+       for (; bottom > 0; bottom--)
+           write(fd, newline, 1);
+
+    }
+
+    /*
+     * Free objects allocated here
+     */
+
+    {
+       PrintLine_t *l;
+       PrintObject_t *p;
+
+       l = first_line;
+
+       while (l) {
+
+           p = l->Objects;
+
+           while (p) {
+
+               free(p);
+
+               p = p->Next;
+           }
+
+           free(l);
+
+           l = l->Next;
+       }
+    }
+
+    /*
+     * Delete extra page
+     */
+
+    HText_free(htext);
+}
diff --git a/erwise/Protos.h b/erwise/Protos.h
new file mode 100644 (file)
index 0000000..6e843bb
--- /dev/null
@@ -0,0 +1,166 @@
+/* $Id: Protos.h,v 1.1 1992/05/18 21:43:03 tvr Exp $ */
+
+
+/*
+ * From other objects/libraries
+ */
+
+extern HTParentAnchor *HTMainAnchor;   /* Can you spell kludge? */
+extern struct HText *HtLocalText;
+
+
+/*
+ * Main.c
+ */
+
+extern FILE *OpenErwiserc(char *type);
+
+
+/*
+ * Setup.c
+ */
+
+extern void AttachCallbacks(void);
+extern void BindKeys(void);
+extern void BindVariables(void);
+
+
+/*
+ * TopLevel.c
+ */
+
+extern void TopQuitCB(char *topaddress, HText_t * htext,
+                      HTextObject_t * htextobject, void *parameter);
+extern void NukeErwiseCB(int button);
+extern void TopInfoCB(char *topaddress, HText_t * htext,
+                      HTextObject_t * htextobject, void *parameter);
+extern void TopOpenCB(char *topaddress, HText_t * htext,
+                      HTextObject_t * htextobject, void *parameter);
+extern void TopHelpCB(char *topaddress, HText_t * htext,
+                      HTextObject_t * htextobject, void *parameter);
+extern void GetPageCB(char *nodename);
+
+extern char FindText[256];
+extern char SearchText[256];
+int SearchDepth;
+int SearchCase;
+
+
+/*
+ * Page.c
+ */
+
+extern void PageSearchCB(char *topaddress, HText_t * htext,
+                         HTextObject_t * htextobject, void *parameter);
+extern void PageCopyCB(char *topaddress, HText_t * htext,
+                       HTextObject_t * htextobject, void *parameter);
+extern void PageListCB(char *topaddress, HText_t * htext,
+                       HTextObject_t * htextobject, void *parameter);
+extern void PageLoadToFileCB(char *topaddress, HText_t * htext,
+                          HTextObject_t * htextobject, void *parameter);
+extern void PagePrintCB(char *topaddress, HText_t * htext,
+                        HTextObject_t * htextobject, void *parameter);
+extern void PageSettingsCB(char *topaddress, HText_t * htext,
+                           HTextObject_t * htextobject, void *parameter);
+extern void PageCloseCB(char *topaddress, HText_t * htext,
+                        HTextObject_t * htextobject, void *parameter);
+extern void PagePrevWordCB(char *topaddress, HText_t * htext,
+                           HTextObject_t * htextobject, void *parameter);
+extern void PageNextWordCB(char *topaddress, HText_t * htext,
+                           HTextObject_t * htextobject, void *parameter);
+extern void PagePrevTagCB(char *topaddress, HText_t * htext,
+                          HTextObject_t * htextobject, void *parameter);
+extern void PageNextTagCB(char *topaddress, HText_t * htext,
+                          HTextObject_t * htextobject, void *parameter);
+extern void PageHomeCB(char *topaddress, HText_t * htext,
+                       HTextObject_t * htextobject, void *parameter);
+extern void PageRecallCB(char *topaddress, HText_t * htext,
+                         HTextObject_t * htextobject, void *parameter);
+extern void PageBackCB(char *topaddress, HText_t * htext,
+                       HTextObject_t * htextobject, void *parameter);
+extern void PagePrevPageCB(char *topaddress, HText_t * htext,
+                           HTextObject_t * htextobject, void *parameter);
+extern void PageNextPageCB(char *topaddress, HText_t * htext,
+                           HTextObject_t * htextobject, void *parameter);
+extern void PageGetPageCB(char *topaddress, HText_t * htext,
+                          HTextObject_t * htextobject, void *parameter);
+extern void PageClickCB(char *topaddress, HText_t * htext,
+                        HTextObject_t * htextobject, void *parameter);
+extern void IndexFindCB(char *topaddress, HText_t * htext,
+                        HTextObject_t * htextobject, void *parameter);
+extern void HierarchyCloseCB(char *topaddress, HText_t * htext,
+                          HTextObject_t * htextobject, void *parameter);
+extern void HierarchyNukeCB(int button);
+extern void HierarchyClose(char *topaddress, HText_t * htext,
+                           HTextObject_t * htextobject, void *parameter);
+extern void SearchBackwardCB(char *topaddress, HText_t * htext,
+                          HTextObject_t * htextobject, void *parameter);
+extern void SearchForwardCB(char *topaddress, HText_t * htext,
+                          HTextObject_t * htextobject, void *parameter);
+extern void ConnectionsCB(char *topaddress, HText_t * htext,
+                          HTextObject_t * htextobject, void *parameter);
+extern void KillCB(void *connection);
+extern void ControlPanelCB(char *topaddress, HText_t * htext,
+                           HTextObject_t * htextobject, void *parameter);
+extern void DefaultsCB(char *topaddress, HText_t * htext,
+                       HTextObject_t * htextobject, void *parameter);
+
+
+/*
+ * Help.c
+ */
+
+extern void HelpOnFunctionCB(char *topaddress, HText_t * htext,
+                          HTextObject_t * htextobject, void *parameter);
+extern void HelpManualCB(char *topaddress, HText_t * htext,
+                         HTextObject_t * htextobject, void *parameter);
+
+
+/*
+ * Print.c
+ */
+
+extern int PrintTopMargin;
+extern int PrintBottomMargin;
+extern int PrintLeftMargin;
+extern int PrintWidth;
+extern char PrintCommand[1024];
+extern int PrintToFile;
+extern char PrintFileName[1024];
+
+
+/*
+ * Misc.c
+ */
+
+extern Page_t *FindPage(Page_t * hierarchy, char *address);
+extern Page_t *GlobalFindPage(char *address);
+extern Page_t *AddPage(Page_t ** page, char *address, HText_t * htext,
+                       Page_t * toppage);
+extern void DeletePage(Page_t ** page, char *address);
+extern void DisplayWarning(char *text);
+extern void DisplayFatal(char *text);
+extern int CanBeCursor(HTextObject_t * htextobject);
+extern void *Malloc(int size);
+extern void *ReAlloc(void *ptr, int size);
+extern void Free(void *ptr);
+extern void StartLoading(char *address, char *topaddress, char *parentaddress);
+void PollConnection(Connection_t * connection);
+Connection_t *AddConnection(char *address, Page_t * toppage, Page_t * parentpage,
+                            ClConnection_t * clconnection);
+Connection_t *FindConnection(char *address);
+void DeleteConnection(char *address);
+
+extern Page_t *Pages;
+extern Connection_t *Connections;
+
+
+/*
+ * Config.c
+ */
+
+extern void ConfigInit(void);
+extern int ConfigRestore(FILE * fp);
+extern int ConfigSave(FILE * fp);
+extern void *ConfigGetValue(void *table, char *id);
+extern void *ConfigSetValue(void *table, char *id, void *value);
diff --git a/erwise/Setup.c b/erwise/Setup.c
new file mode 100644 (file)
index 0000000..0e995ec
--- /dev/null
@@ -0,0 +1,198 @@
+static char *rcsid = "$Id: Setup.c,v 1.1 1992/05/18 21:43:03 tvr Exp $";
+
+#include "Includes.h"
+
+
+void attachtoplevelcallbacks(void);
+void attachpagecallbacks(void);
+void attachhierarchycallbacks(void);
+void attachsearchcallbacks(void);
+void bindpagevariables(void);
+void bindsearchvariables(void);
+void bindprintvariables(void);
+
+
+void AttachCallbacks()
+{
+    attachtoplevelcallbacks();
+    attachpagecallbacks();
+    attachhierarchycallbacks();
+    attachsearchcallbacks();
+}
+
+
+
+char *
+ parse_key(type, item)
+int *type;
+char *item;
+{
+    char *p;
+
+    if (!item)
+       return item;
+
+    if (*item == '^') {
+       *type = UI_CTRL;
+
+       p = strdup(item + 1);
+
+       if (strlen(p) == 1)
+           *p = tolower(*p);
+
+       return p;
+    }
+    if (strlen(item) == 1) {
+       if (isupper(*item)) {
+           *type = UI_SHIFT;
+       } else {
+           *type = UI_NONE;
+       }
+       p = (char *) strdup(item);
+
+       *p = tolower(*p);
+
+       return p;
+    }
+    *type = UI_NONE;
+
+    return (char *) strdup(item);
+}
+
+
+/*
+ * Keyboard bindings
+ */
+
+typedef struct erwise_key_bindings_s {
+    char *itemname;
+    void (*callback) ();
+    void *data;
+} erwise_key_bindings_t;
+
+erwise_key_bindings_t erwise_keys[] =
+{
+    {C_GETPAGE, PageGetPageCB, NULL},
+    {C_PREVWORD, PagePrevWordCB, NULL},
+    {C_NEXTWORD, PageNextWordCB, NULL},
+    {C_PREVTAG, PagePrevTagCB, (void *) NO_AUTOGET},
+    {C_NEXTTAG, PageNextTagCB, (void *) NO_AUTOGET},
+    {C_CLOSE, PageCloseCB, NULL},
+    {C_SEARCH, PageSearchCB, NULL},
+    {C_SETTINGS, PageSettingsCB, NULL},
+    {C_LIST, PageListCB, NULL},
+    {C_PRINTDOC, PagePrintCB, NULL},
+    {NULL, NULL, NULL},
+};
+
+
+void BindKeys()
+{
+    void *table;
+    char *item;
+    char *key;
+    int keytype;
+
+    erwise_key_bindings_t *k;
+
+    table = (void *) ConfigGetValue((void *) NULL, C_KEYBINDINGS);
+
+    for (k = erwise_keys; k->itemname; k++) {
+       item = (char *) ConfigGetValue(table, k->itemname);
+
+       if (item) {
+           key = parse_key(&keytype, item);
+
+           if (key) {
+               UiBindKey(key, keytype, k->callback, k->data);
+               free(key);
+           }
+       }
+    }
+}
+
+
+void BindVariables()
+{
+    bindpagevariables();
+    bindsearchvariables();
+    bindprintvariables();
+}
+
+
+void attachtoplevelcallbacks()
+{
+    UiAttachCallback("Quit", TopQuitCB, (void *) NULL);
+    UiAttachCallback("Info", TopInfoCB, (void *) NULL);
+    UiAttachCallback("Open", TopOpenCB, (void *) NULL);
+    UiAttachCallback("Help", HelpManualCB, (void *) NULL);
+}
+
+
+void attachpagecallbacks()
+{
+    UiAttachCallback("Search", PageSearchCB, (void *) NULL);
+    UiAttachCallback("Copy", PageCopyCB, (void *) NULL);
+    UiAttachCallback("List", PageListCB, (void *) NULL);
+    UiAttachCallback("Load to file", PageLoadToFileCB, (void *) NULL);
+    UiAttachCallback("Print", PagePrintCB, (void *) NULL);
+    UiAttachCallback("Settings", PageSettingsCB, (void *) NULL);
+    UiAttachCallback("Close", PageCloseCB, (void *) NULL);
+
+    UiAttachCallback("Prev tag", PagePrevTagCB, (void *) AUTOGET);
+    UiAttachCallback("Next tag", PageNextTagCB, (void *) AUTOGET);
+
+    UiAttachCallback("Home", PageHomeCB, (void *) NULL);
+    UiAttachCallback("Recall", PageRecallCB, (void *) NULL);
+    UiAttachCallback("Back", PageBackCB, (void *) NULL);
+    UiAttachCallback("Prev page", PagePrevPageCB, (void *) NULL);
+    UiAttachCallback("Next page", PageNextPageCB, (void *) NULL);
+
+    UiAttachCallback("On function", HelpOnFunctionCB, (void *) NULL);
+
+    UiAttachCallback("Get page", PageGetPageCB, (void *) NULL);
+    UiAttachCallback("Click page", PageClickCB, (void *) NULL);
+    UiAttachCallback("IndexFind", IndexFindCB, (void *) NULL);
+}
+
+
+void attachhierarchycallbacks()
+{
+    UiAttachCallback("Connections", ConnectionsCB, (void *) NULL);
+    UiAttachCallback("Controlpanel", ControlPanelCB, (void *) NULL);
+    UiAttachCallback("Defaults", DefaultsCB, (void *) NULL);
+    UiAttachCallback("Close hierarchy", HierarchyCloseCB, (void *) NULL);
+}
+
+
+void attachsearchcallbacks()
+{
+    UiAttachCallback("SearchBackward", SearchBackwardCB, (void *) NULL);
+    UiAttachCallback("SearchForward", SearchForwardCB, (void *) NULL);
+}
+
+
+void bindpagevariables()
+{
+    UiBindVariable("FindText", (void *) FindText, uiVTstring);
+}
+
+
+void bindsearchvariables()
+{
+    UiBindVariable("SearchText", (void *) SearchText, uiVTstring);
+    UiBindVariable("SearchDepth", (void *) &SearchDepth, uiVTint);
+    UiBindVariable("SearchCase", (void *) &SearchCase, uiVTint);
+}
+
+
+void bindprintvariables()
+{
+    UiBindVariable("PrintTopMargin", (void *) &PrintTopMargin, uiVTint);
+    UiBindVariable("PrintBottomMargin", (void *) &PrintBottomMargin, uiVTint);
+    UiBindVariable("PrintLeftMargin", (void *) &PrintLeftMargin, uiVTint);
+    UiBindVariable("PrintWidth", (void *) &PrintWidth, uiVTint);
+    UiBindVariable("PrintCommand", (void *) &PrintCommand, uiVTstring);
+    UiBindVariable("PrintToFile", (void *) &PrintToFile, uiVTint);
+    UiBindVariable("PrintFileName", (void *) &PrintFileName, uiVTstring);
+}
diff --git a/erwise/TopLevel.c b/erwise/TopLevel.c
new file mode 100644 (file)
index 0000000..a9d13d9
--- /dev/null
@@ -0,0 +1,61 @@
+static char *rcsid = "$Id: TopLevel.c,v 1.1 1992/05/18 21:43:03 tvr Exp $";
+
+#include "Includes.h"
+
+
+void TopQuitCB(topaddress, htext, htextobject, parameter)
+char *topaddress;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    UiDisplayWarningDialog("Quit Erwise?", NukeErwiseCB);
+}
+
+
+void NukeErwiseCB(button)
+int button;
+{
+    FILE *fp;
+
+    if (fp = OpenErwiserc("w")) {
+       ConfigSave(fp);
+       fclose(fp);
+    } else
+       fprintf(stderr, "Warning: could not save settings to .erwiserc\n");
+
+    exit(0);
+}
+
+
+void TopInfoCB(topaddress, htext, htextobject, parameter)
+char *topaddress;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    UiDisplayInfo();
+}
+
+
+void TopOpenCB(topaddress, htext, htextobject, parameter)
+char *topaddress;
+HText_t *htext;
+HTextObject_t *htextobject;
+void *parameter;
+{
+    UiDisplaySelectionBox(GetPageCB);
+}
+
+
+void GetPageCB(address)
+char *address;
+{
+    if (FindPage(Pages, address)) {
+       DisplayWarning("Already loaded");
+       return;
+    }
+    AddPage(&Pages, address, (HText_t *) NULL, (Page_t *) NULL);
+
+    StartLoading(address, address, (char *) NULL);
+}
diff --git a/erwise/Types.h b/erwise/Types.h
new file mode 100644 (file)
index 0000000..992810b
--- /dev/null
@@ -0,0 +1,45 @@
+/* $Id: Types.h,v 1.1 1992/05/18 21:43:03 tvr Exp $ */
+
+
+typedef struct _page {
+    char *Address;
+    HText_t *HText;
+    struct _page *ParentPage;
+    struct _page *Parents;
+    struct _page *Children;    /* only two levels */
+    struct _page *Next;
+} Page_t;
+
+
+typedef struct _connection {
+    char *Address;
+    int Status;
+    int FD;
+    int InputId;
+    int TimeOutId;
+    ClConnection_t *ClConnection;
+    Page_t *TopPage;
+    Page_t *ParentPage;
+    struct _connection *Next;
+} Connection_t;
+
+
+typedef enum {
+    EOC,                       /* eof */
+    EMPTY,                     /* "" */
+    UNKNOWN,
+    RESOURCE,                  /* resource definition, id = value */
+    BLOCK,                     /* a block containing resources */
+    DYNAMIC,                   /* dynamic BLOCK */
+    DYNAMIC_PTR,               /* ptr to dynamic data (void *ptr[]) */
+    COMMENT,                   /* "# ..." */
+    START_OF_BLOCK,            /* '{' */
+    END_OF_BLOCK               /* '}' */
+} ConfigType_t;
+
+
+typedef struct _config {
+    ConfigType_t type;
+    char *id;
+    void *value;
+} Config_t;
diff --git a/erwise/main.c b/erwise/main.c
new file mode 100644 (file)
index 0000000..788ba62
--- /dev/null
@@ -0,0 +1,74 @@
+static char *rcsid = "$Id: main.c,v 1.1 1992/05/18 21:43:03 tvr Exp $";
+
+#include "Includes.h"
+
+
+
+void main(argc, argv)
+int argc;
+char *argv[];
+{
+    FILE *fp;
+
+    ConfigInit();
+
+    if (fp = OpenErwiserc("r")) {
+       ConfigRestore(fp);
+       fclose(fp);
+    }
+    if (UiInitialize(argc, argv, ConfigGetValue, ConfigSetValue) != UI_OK)
+       DisplayFatal("Error initializing Ui-toolkit");
+
+    AttachCallbacks();
+    BindKeys();
+    BindVariables();
+
+    UiMainLoop();
+}
+
+#define RCPOSTFIX ".old"
+FILE *
+ OpenErwiserc(type)
+char *type;
+{
+    char *tmpstr;
+    char *bustr;
+    FILE *fp;
+
+    if (!getenv("HOME"))
+       return (FILE *) NULL;
+
+    tmpstr = strdup(getenv("HOME"));
+
+    tmpstr = (char *) ReAlloc((void *) tmpstr, strlen(tmpstr) +
+                             strlen(ERWISERC) + 2);
+    strcat(tmpstr, "/");
+    strcat(tmpstr, ERWISERC);
+    if (!strcmp(type, "w")) {
+       bustr = (char *) Malloc((strlen(tmpstr) + strlen(RCPOSTFIX) + 1) *
+                               sizeof(char));
+       strcpy(bustr, tmpstr);
+       strcat(bustr, RCPOSTFIX);
+       rename(tmpstr, bustr);
+       free(bustr);
+    }
+    fp = fopen(tmpstr, type);
+    Free(tmpstr);
+
+    return fp;
+}
+
+
+#ifdef mips
+char *
+ strdup(s)
+char *s;
+{
+    char *p = (char *) malloc(strlen(s) + 1);
+
+    strcpy(p, s);
+
+    return p;
+}
+
+#endif